This is an automated email from the ASF dual-hosted git repository.

pradeepagrawal8184 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ranger.git


The following commit(s) were added to refs/heads/master by this push:
     new d0f9fe978 RANGER-5696: Added deltaSyncServerType config to optimize 
delta sync … (#1218)
d0f9fe978 is described below

commit d0f9fe978b929d71f953682b5d7792aa258cf7b4
Author: KRISHNA CHAITANYA MUTTEVI 
<[email protected]>
AuthorDate: Tue Sep 29 11:05:25 2026 +0530

    RANGER-5696: Added deltaSyncServerType config to optimize delta sync … 
(#1218)
    
    * RANGER-5696: Added deltaSyncServerType config to optimize delta sync 
filters for AD/LDAP
    
    * RANGER-5696: Added the getDeltaSyncFilter function
---
 .../ldapusersync/process/LdapUserGroupBuilder.java | 22 +++++-
 .../process/TestLdapUserGroupBuilder.java          | 91 ++++++++++++++++++++++
 ugsync/src/test/resources/ranger-ugsync-site.xml   | 12 +++
 3 files changed, 123 insertions(+), 2 deletions(-)

diff --git 
a/ugsync/src/main/java/org/apache/ranger/ldapusersync/process/LdapUserGroupBuilder.java
 
b/ugsync/src/main/java/org/apache/ranger/ldapusersync/process/LdapUserGroupBuilder.java
index ae860f275..e8379b211 100644
--- 
a/ugsync/src/main/java/org/apache/ranger/ldapusersync/process/LdapUserGroupBuilder.java
+++ 
b/ugsync/src/main/java/org/apache/ranger/ldapusersync/process/LdapUserGroupBuilder.java
@@ -513,11 +513,13 @@ private long getUsers(boolean computeDeletes) throws 
Throwable {
             }
 
             if (config.isDeltaSyncEnabled()) {
-                extendedUserSearchFilter = "(objectclass=" + userObjectClass + 
")(|(uSNChanged>=" + deltaSyncUserTime + ")(modifyTimestamp>=" + 
deltaSyncUserTimeStamp + "Z))";
+                extendedUserSearchFilter = "(objectclass=" + userObjectClass + 
")" + getDeltaSyncFilter(deltaSyncUserTime, deltaSyncUserTimeStamp);
             } else {
                 extendedUserSearchFilter = "(objectclass=" + userObjectClass + 
")";
             }
 
+            LOG.debug("custom userSearchFilter = {}, extendedUserSearchFilter 
= {}", userSearchFilter, extendedUserSearchFilter);
+            LOG.info("extendedUserSearchFilter = {}", 
extendedUserSearchFilter);
             if (userSearchFilter != null && 
!userSearchFilter.trim().isEmpty()) {
                 String customFilter = userSearchFilter.trim();
 
@@ -758,11 +760,12 @@ private long getGroups(boolean computeDeletes) throws 
Throwable {
             }
 
             if (config.isDeltaSyncEnabled()) {
-                extendedAllGroupsSearchFilter = "(&"  + 
extendedGroupSearchFilter + "(|(uSNChanged>=" + deltaSyncGroupTime + 
")(modifyTimestamp>=" + deltaSyncGroupTimeStamp + "Z)))";
+                extendedAllGroupsSearchFilter = "(&" + 
extendedGroupSearchFilter + getDeltaSyncFilter(deltaSyncGroupTime, 
deltaSyncGroupTimeStamp) + ")";
             } else {
                 extendedAllGroupsSearchFilter = "(&"  + 
extendedGroupSearchFilter + ")";
             }
 
+            LOG.debug("custom groupSearchFilter = {}, 
extendedGroupSearchFilter = {}", groupSearchFilter, extendedGroupSearchFilter);
             LOG.info("extendedAllGroupsSearchFilter = {}", 
extendedAllGroupsSearchFilter);
 
             for (int ou = 0; ou < groupSearchBase.length; ou++) {
@@ -909,6 +912,21 @@ private long getGroups(boolean computeDeletes) throws 
Throwable {
         return highestdeltaSyncGroupTime;
     }
 
+    private String getDeltaSyncFilter(long usnChangedTime, String 
modifyTimestamp) {
+        String result     = "";
+        String serverType = 
config.getProperty("ranger.usersync.ldap.deltasync.server.type", "").trim();
+
+        if (serverType.equalsIgnoreCase("ad")) {
+            result = "(uSNChanged>=" + usnChangedTime + ")";
+        } else if (serverType.equalsIgnoreCase("ldap")) {
+            result = "(modifyTimestamp>=" + modifyTimestamp + "Z)";
+        } else {
+            result = "(|(uSNChanged>=" + usnChangedTime + 
")(modifyTimestamp>=" + modifyTimestamp + "Z))";
+        }
+
+        return result;
+    }
+
     private void goUpGroupHierarchy(Set<String> groups, int 
groupHierarchyLevels, String groupSName) {
         if (groupHierarchyLevels <= 0 || groups.isEmpty()) {
             return;
diff --git 
a/ugsync/src/test/java/org/apache/ranger/ldapusersync/process/TestLdapUserGroupBuilder.java
 
b/ugsync/src/test/java/org/apache/ranger/ldapusersync/process/TestLdapUserGroupBuilder.java
index 0d677c384..0fae39013 100644
--- 
a/ugsync/src/test/java/org/apache/ranger/ldapusersync/process/TestLdapUserGroupBuilder.java
+++ 
b/ugsync/src/test/java/org/apache/ranger/ldapusersync/process/TestLdapUserGroupBuilder.java
@@ -420,6 +420,97 @@ public void 
testU_user_config_fields_reflect_properties_and_timestamps_initializ
         assertEquals(STR_EPOCH, ts.get(b));
     }
 
+    @Test
+    void testUG_getUsers_ad_filter_uses_uSNChanged_only() throws Throwable {
+        resetConfig();
+        configureMinimalLdapConfig();
+        UserGroupSyncConfig cfg = UserGroupSyncConfig.getInstance();
+        cfg.setProperty("ranger.usersync.ldap.deltasync", "true");
+        cfg.setProperty("ranger.usersync.ldap.deltasync.server.type", "ad");
+
+        LdapUserGroupBuilder b = new LdapUserGroupBuilder();
+        b.init();
+
+        Field fGroupEnabled = 
LdapUserGroupBuilder.class.getDeclaredField("groupSearchEnabled");
+        fGroupEnabled.setAccessible(true);
+        fGroupEnabled.setBoolean(b, false);
+
+        Field gutF      = 
LdapUserGroupBuilder.class.getDeclaredField("groupUserTable");
+        Field srcUsersF = 
LdapUserGroupBuilder.class.getDeclaredField("sourceUsers");
+        Field srcGroupsF = 
LdapUserGroupBuilder.class.getDeclaredField("sourceGroups");
+        gutF.setAccessible(true);
+        srcUsersF.setAccessible(true);
+        srcGroupsF.setAccessible(true);
+        gutF.set(b, HashBasedTable.create());
+        srcUsersF.set(b, new HashMap<>());
+        srcGroupsF.set(b, new HashMap<>());
+
+        final String userDn = "cn=User1000,ou=people,dc=example,dc=com";
+        Attributes attrs = new BasicAttributes(true);
+        attrs.put(new BasicAttribute("cn", "User1000"));
+        attrs.put(new BasicAttribute("uSNChanged", "2001"));
+
+        class TestSearchResult extends SearchResult {
+            private final String nameInNs;
+
+            TestSearchResult(String name, Attributes a, String nameInNs) {
+                super(name, null, a);
+                this.nameInNs = nameInNs;
+            }
+
+            @Override
+            public String getNameInNamespace() {
+                return nameInNs;
+            }
+        }
+
+        final SearchResult sr = new TestSearchResult(userDn, attrs, userDn);
+
+        class SingleEnum implements NamingEnumeration<SearchResult> {
+            private boolean consumed;
+
+            @Override
+            public SearchResult next() {
+                consumed = true;
+                return sr;
+            }
+
+            @Override
+            public boolean hasMore() {
+                return !consumed;
+            }
+
+            @Override
+            public void close() {}
+
+            @Override
+            public boolean hasMoreElements() {
+                return hasMore();
+            }
+
+            @Override
+            public SearchResult nextElement() {
+                return next();
+            }
+        }
+
+        try (MockedConstruction<InitialLdapContext> mocked = 
Mockito.mockConstruction(InitialLdapContext.class, (mock, ctx) -> {
+            Mockito.when(mock.search(Mockito.anyString(), Mockito.anyString(), 
Mockito.any(SearchControls.class)))
+                    .thenReturn(new SingleEnum());
+            Mockito.when(mock.getResponseControls()).thenReturn(null);
+        })) {
+            Method getUsers = 
LdapUserGroupBuilder.class.getDeclaredMethod("getUsers", boolean.class);
+            getUsers.setAccessible(true);
+            getUsers.invoke(b, false);
+
+            Field extFilF = 
LdapUserGroupBuilder.class.getDeclaredField("extendedUserSearchFilter");
+            extFilF.setAccessible(true);
+            String ext = (String) extFilF.get(b);
+            assertTrue(ext.contains("uSNChanged>="), ext);
+            assertFalse(ext.contains("modifyTimestamp>="), ext);
+        }
+    }
+
     @Test
     public void testV_getUsers_processes_user_and_group_memberships() throws 
Throwable {
         resetConfig();
diff --git a/ugsync/src/test/resources/ranger-ugsync-site.xml 
b/ugsync/src/test/resources/ranger-ugsync-site.xml
index 5ed504b86..98a80ecf6 100644
--- a/ugsync/src/test/resources/ranger-ugsync-site.xml
+++ b/ugsync/src/test/resources/ranger-ugsync-site.xml
@@ -177,4 +177,16 @@
       <name>ranger.usersync.group.hierarchylevels</name>
       <value>2</value>
     </property>
+
+    <property>
+        <name>ranger.usersync.ldap.deltasync.server.type</name>
+        <value></value>
+        <description>Specifies the LDAP server type for delta sync attribute 
selection.
+            Accepted values:
+            - "AD"   : Uses only 'uSNChanged' attribute for delta sync (Active 
Directory).
+            - "LDAP" : Uses only 'modifyTimestamp' attribute for delta sync 
(OpenLDAP).
+            - ""     : Uses both 'uSNChanged' and 'modifyTimestamp' attributes 
(default behavior).
+        </description>
+    </property>
+
   </configuration>

Reply via email to