Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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();

Expand Down Expand Up @@ -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++) {
Expand Down Expand Up @@ -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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
12 changes: 12 additions & 0 deletions ugsync/src/test/resources/ranger-ugsync-site.xml
Original file line number Diff line number Diff line change
Expand Up @@ -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>