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>