Add support for user/group search rules & baseDNs
This is for feature request b/8757112.
diff --git a/src/com/google/enterprise/adaptor/ad/AdAdaptor.java b/src/com/google/enterprise/adaptor/ad/AdAdaptor.java
index 3590e91..234bbd4 100644
--- a/src/com/google/enterprise/adaptor/ad/AdAdaptor.java
+++ b/src/com/google/enterprise/adaptor/ad/AdAdaptor.java
@@ -69,6 +69,10 @@
private boolean feedBuiltinGroups;
private GroupCatalog lastCompleteGroupCatalog = null;
private String ldapTimeoutInMillis;
+ private String userSearchBaseDN;
+ private String groupSearchBaseDN;
+ private String userSearchFilter;
+ private String groupSearchFilter;
@Override
public void initConfig(Config config) {
@@ -83,6 +87,10 @@
config.addKey("ad.localized.Builtin", "BUILTIN");
config.addKey("ad.feedBuiltinGroups", "false");
config.addKey("ad.ldapReadTimeoutSecs", "90");
+ config.addKey("ad.userSearchBaseDN", "");
+ config.addKey("ad.groupSearchBaseDN", "");
+ config.addKey("ad.userSearchFilter", "");
+ config.addKey("ad.groupSearchFilter", "");
}
@Override
@@ -97,6 +105,12 @@
config.getValue("ad.feedBuiltinGroups"));
ldapTimeoutInMillis = parseLdapTimeoutInMillis(
config.getValue("ad.ldapReadTimeoutSecs"));
+ // TBD(myk): Determine if any of the following need any sort of validation
+ // beyond the single warning logged if any are provided.
+ userSearchBaseDN = config.getValue("ad.userSearchBaseDN");
+ groupSearchBaseDN = config.getValue("ad.groupSearchBaseDN");
+ userSearchFilter = config.getValue("ad.userSearchFilter");
+ groupSearchFilter = config.getValue("ad.groupSearchFilter");
// register for incremental pushes
context.setPollingIncrementalLister(this);
List<Map<String, String>> serverConfigs
@@ -213,12 +227,14 @@
@VisibleForTesting
GroupCatalog makeFullCatalog() throws InterruptedException, IOException {
GroupCatalog cumulativeCatalog = new GroupCatalog(localizedStrings,
- namespace, feedBuiltinGroups);
+ namespace, feedBuiltinGroups, userSearchBaseDN, groupSearchBaseDN,
+ userSearchFilter, groupSearchFilter);
for (AdServer server : servers) {
try {
server.ensureConnectionIsCurrent();
GroupCatalog catalog = new GroupCatalog(localizedStrings, namespace,
- feedBuiltinGroups);
+ feedBuiltinGroups, userSearchBaseDN, groupSearchBaseDN,
+ userSearchFilter, groupSearchFilter);
catalog.readEverythingFrom(server, /*includeMembers=*/ true);
cumulativeCatalog.add(catalog);
} catch (NamingException ne) {
@@ -240,8 +256,8 @@
public void getModifiedDocIds(DocIdPusher pusher) throws InterruptedException,
IOException {
if (!mutex.tryLock()) {
- log.log(Level.FINE, "getModifiedDocIds could not acquire lock; " +
- "will retry later.");
+ log.log(Level.FINE, "getModifiedDocIds could not acquire lock; "
+ + "will retry later.");
return;
}
try {
@@ -314,12 +330,22 @@
final AdEntity interactive;
final AdEntity authenticatedUsers;
final Map<AdEntity, Set<String>> wellKnownMembership;
+ final String userSearchBaseDN;
+ final String groupSearchBaseDN;
+ final String userSearchFilter;
+ final String groupSearchFilter;
public GroupCatalog(Map<String, String> localizedStrings, String namespace,
- boolean feedBuiltinGroups) {
+ boolean feedBuiltinGroups, String userSearchBaseDN,
+ String groupSearchBaseDN, String userSearchFilter,
+ String groupSearchFilter) {
this.localizedStrings = localizedStrings;
this.namespace = namespace;
this.feedBuiltinGroups = feedBuiltinGroups;
+ this.userSearchBaseDN = userSearchBaseDN;
+ this.groupSearchBaseDN = groupSearchBaseDN;
+ this.userSearchFilter = userSearchFilter;
+ this.groupSearchFilter = groupSearchFilter;
everyone = new AdEntity("S-1-1-0",
MessageFormat.format("CN={0}",
localizedStrings.get("Everyone")));
@@ -366,8 +392,15 @@
Map<AdEntity, Set<String>> members,
Map<String, AdEntity> bySid,
Map<String, AdEntity> byDn,
- Map<AdEntity, String> domain) {
- this(localizedStrings, namespace, feedBuiltinGroups);
+ Map<AdEntity, String> domain,
+ String userSearchBaseDN,
+ String groupSearchBaseDN,
+ String userSearchFilter,
+ String groupSearchFilter) {
+ this(localizedStrings, namespace, feedBuiltinGroups, userSearchBaseDN,
+ groupSearchBaseDN, userSearchFilter, groupSearchFilter);
+ this.localizedStrings = localizedStrings;
+ this.namespace = namespace;
this.entities.clear();
this.entities.addAll(entities);
this.members.putAll(members);
@@ -386,19 +419,80 @@
nonMemberAttributes.length + 1);
allAttributes[nonMemberAttributes.length] = "member";
log.log(Level.FINE, "Starting full crawl.");
- // LDAP_MATCHING_RULE_BIT_AND = 1.2.840.113556.1.4.803
- // and ADS_GROUP_TYPE_SECURITY_ENABLED = 2147483648.
- entities = server.search("(|(&(objectClass=group)"
- + "(groupType:1.2.840.113556.1.4.803:=2147483648))"
- + "(&(objectClass=user)(objectCategory=person)))",
- /*deleted=*/ false,
- includeMembers ? allAttributes : nonMemberAttributes);
+ if (groupSearchBaseDN.equals(userSearchBaseDN)) {
+ entities = server.search(userSearchBaseDN, generateLdapQuery(),
+ /*deleted=*/ false,
+ includeMembers ? allAttributes : nonMemberAttributes);
+ } else {
+ entities = server.search(groupSearchBaseDN, generateGroupLdapQuery(),
+ /*deleted=*/ false,
+ includeMembers ? allAttributes : nonMemberAttributes);
+ entities.addAll(server.search(userSearchBaseDN, generateUserLdapQuery(),
+ /*deleted=*/ false, nonMemberAttributes));
+ }
// disabled groups handled later, in makeDefs()
log.log(Level.FINE, "Ending full crawl - now starting processing.");
processEntities(entities, server.getnETBIOSName());
}
/**
+ * Generates a query to return groups (optionally with a group filter).
+ * This is useful when either a user BaseDN or a group BaseDN has been
+ * specified (or if they are different).
+ */
+ @VisibleForTesting
+ String generateGroupLdapQuery() {
+ String groupQuery;
+ if ("".equals(groupSearchFilter)) {
+ groupQuery = "(&(objectClass=group)"
+ + "(groupType:1.2.840.113556.1.4.803:=2147483648))";
+ // LDAP_MATCHING_RULE_BIT_AND = 1.2.840.113556.1.4.803
+ // and ADS_GROUP_TYPE_SECURITY_ENABLED = 2147483648.
+ } else {
+ groupQuery = "(&(&(objectClass=group)"
+ + "(groupType:1.2.840.113556.1.4.803:=2147483648))"
+ + "(" + groupSearchFilter + "))";
+ }
+ return groupQuery;
+ }
+
+ /**
+ * Generates a query to return users (optionally with a user filter).
+ * This is useful when either a user BaseDN or a group BaseDN has been
+ * specified (or if they are different).
+ */
+ @VisibleForTesting
+ String generateUserLdapQuery() {
+ String userQuery;
+ if ("".equals(userSearchFilter)) {
+ userQuery = "(&(objectClass=user)(objectCategory=person))";
+ } else {
+ userQuery = "(&(&(objectClass=user)(objectCategory=person))"
+ + "(" + userSearchFilter + "))";
+ }
+ return userQuery;
+ }
+
+ /**
+ * Generates a query to return users (optionally with a user filter) and
+ * groups (optionally with a group filter) -- this is only useful when
+ * neither a user BaseDN or a group BaseDN has been specified (or if they
+ * are both equal).
+ */
+ @VisibleForTesting
+ String generateLdapQuery() {
+ String groupQuery = generateGroupLdapQuery();
+ String userQuery = generateUserLdapQuery();
+ // error if BaseDNs are not equal
+ if (groupSearchBaseDN != userSearchBaseDN) {
+ throw new IllegalArgumentException("not handling differing "
+ + "BaseDNs properly!");
+ }
+ String query = "(|" + groupQuery + userQuery + ")";
+ return query;
+ }
+
+ /**
* Do an AD search for only groups/users that have been updated since the
* previous full or incremental search.
* <p>If either <code>getDsServiceName()</code> or
@@ -459,6 +553,13 @@
}
private void processEntities(Set<AdEntity> entities, String nETBIOSName) {
+ if (!(("".equals(userSearchBaseDN)) && ("".equals(groupSearchBaseDN))
+ && ("".equals(userSearchFilter)) && ("".equals(groupSearchFilter)))) {
+ log.log(Level.CONFIG, "CAUTION: Customized LDAP search base(s) and/or "
+ + "filter(s) have been configured! If users are experiencing issues"
+ + " with finding content, investigate if relevant users/groups are "
+ + "being excluded from indexing.");
+ }
log.log(Level.FINE, "received {0} entities from server", entities.size());
for (AdEntity e : entities) {
bySid.put(e.getSid(), e);
@@ -476,16 +577,25 @@
Set<AdEntity> incrementalCrawl(AdServer server, long previousHighestUSN,
long currentHighestUSN) throws InterruptedNamingException {
log.log(Level.FINE, "Starting incremental crawl.");
- // LDAP_MATCHING_RULE_BIT_AND = 1.2.840.113556.1.4.803
- // and ADS_GROUP_TYPE_SECURITY_ENABLED = 2147483648.
- Set<AdEntity> newOrModifiedEntities = server.search("(&(uSNChanged>="
- + (previousHighestUSN + 1) + ")(|(&(objectClass=group)"
- + "(groupType:1.2.840.113556.1.4.803:=2147483648))"
- + "(&(objectClass=user)(objectCategory=person))))",
- /*deleted=*/ false,
- new String[] { "uSNChanged", "sAMAccountName", "objectGUID;binary",
- "objectSid;binary", "userPrincipalName", "primaryGroupId",
- "member", "userAccountControl" });
+ final String[] attributes = new String[] { "uSNChanged", "member",
+ "sAMAccountName", "objectGUID;binary", "objectSid;binary",
+ "userPrincipalName", "primaryGroupId", "userAccountControl" };
+ Set<AdEntity> newOrModifiedEntities;
+
+ String newEntryQuery = "(uSNChanged>=" + (previousHighestUSN + 1) + ")";
+ if (groupSearchBaseDN.equals(userSearchBaseDN)) {
+ newOrModifiedEntities = server.search(userSearchBaseDN,
+ "(&" + newEntryQuery + generateLdapQuery() + ")",
+ /*deleted=*/ false, attributes);
+ } else {
+ newOrModifiedEntities = server.search(groupSearchBaseDN,
+ "(&" + newEntryQuery + generateGroupLdapQuery() + ")",
+ /*deleted=*/ false, attributes);
+ newOrModifiedEntities.addAll(server.search(userSearchBaseDN,
+ "(&" + newEntryQuery + generateUserLdapQuery() + ")",
+ /*deleted=*/ false, attributes));
+ }
+
// disabled groups handled later, in makeDefs()
log.log(Level.FINE, "Ending incremental crawl - now starting "
+ "processing.");
diff --git a/src/com/google/enterprise/adaptor/ad/AdServer.java b/src/com/google/enterprise/adaptor/ad/AdServer.java
index de93e5b..a0e7342 100644
--- a/src/com/google/enterprise/adaptor/ad/AdServer.java
+++ b/src/com/google/enterprise/adaptor/ad/AdServer.java
@@ -306,21 +306,25 @@
/**
* Searches Active Directory and creates AdEntity on each result found
+ * @param baseDN baseDN for the search (use "dn" when empty/null)
* @param filter LDAP filter to search in the AD for
* @param attributes list of attributes to retrieve
* @return list of entities found
*/
- public Set<AdEntity> search(String filter, boolean deleted,
+ public Set<AdEntity> search(String baseDN, String filter, boolean deleted,
String[] attributes) throws InterruptedNamingException {
Set<AdEntity> results = new HashSet<AdEntity>();
searchCtls.setReturningAttributes(attributes);
setControls(deleted);
+ if (null == baseDN || "".equals(baseDN)) {
+ baseDN = dn;
+ }
try {
ensureConnectionIsCurrent();
byte[] cookie = null;
do {
NamingEnumeration<SearchResult> ldapResults =
- ldapContext.search(dn, filter, searchCtls);
+ ldapContext.search(baseDN, filter, searchCtls);
while (ldapResults.hasMoreElements()) {
SearchResult sr = ldapResults.next();
try {
@@ -365,7 +369,8 @@
"Retrieving additional groups for [" + g + "] " + memberRange);
searchCtls.setReturningAttributes(new String[] {memberRange});
NamingEnumeration<SearchResult> ldapResults = ldapContext.search(
- dn, "(sAMAccountName=" + g.getSAMAccountName() + ")", searchCtls);
+ baseDN, "(sAMAccountName=" + g.getSAMAccountName() + ")",
+ searchCtls);
SearchResult sr = ldapResults.next();
int found = g.appendGroups(sr);
start += found;
diff --git a/test/com/google/enterprise/adaptor/ad/AdAdaptorTest.java b/test/com/google/enterprise/adaptor/ad/AdAdaptorTest.java
index a00b22b..dbaa7d0 100644
--- a/test/com/google/enterprise/adaptor/ad/AdAdaptorTest.java
+++ b/test/com/google/enterprise/adaptor/ad/AdAdaptorTest.java
@@ -66,27 +66,21 @@
@Test
public void testGroupCatalogConstructor() {
- Map<String, String> strings = defaultLocalizedStringMap();
-
- AdAdaptor.GroupCatalog groupCatalog = new AdAdaptor.GroupCatalog(
- strings, "example.com", /*feedBuiltinGroups=*/ false);
- final AdAdaptor.GroupCatalog golden = new AdAdaptor.GroupCatalog(
- strings, "example.com", /*feedBuiltinGroups=*/ true);
+ AdAdaptor.GroupCatalog groupCatalog = new GroupCatalogBuilder().build();
+ AdAdaptor.GroupCatalog golden = new GroupCatalogBuilder()
+ .setFeedBuiltinGroups(true).build();
assertTrue(golden.equals(groupCatalog));
}
@Test
public void testGroupCatalogEquals() {
- Map<String, String> strings = defaultLocalizedStringMap();
- final AdAdaptor.GroupCatalog golden = new AdAdaptor.GroupCatalog(
- strings, "example.com", /*feedBuiltinGroups=*/ true);
+ AdAdaptor.GroupCatalog golden = new GroupCatalogBuilder().build();
golden.members.put(new AdEntity("Test", "dn=Test"),
Sets.newHashSet("Test"));
final Map<AdEntity, Set<String>> goldenWellKnownMembership =
golden.wellKnownMembership;
- AdAdaptor.GroupCatalog groupCatalog = new AdAdaptor.GroupCatalog(
- strings, "example.com", /*feedBuiltinGroups=*/ false);
+ AdAdaptor.GroupCatalog groupCatalog = new GroupCatalogBuilder().build();
groupCatalog.members.put(new AdEntity("Test", "dn=Test"),
Sets.newHashSet("Test"));
@@ -133,10 +127,7 @@
@Test
public void testGroupCatalogReadFrom() throws Exception {
- Map<String, String> strings = defaultLocalizedStringMap();
-
- AdAdaptor.GroupCatalog groupCatalog = new AdAdaptor.GroupCatalog(
- strings, "example.com", /*feedBuiltinGroups=*/ false);
+ AdAdaptor.GroupCatalog groupCatalog = new GroupCatalogBuilder().build();
MockLdapContext ldapContext = defaultMockLdapContext();
// add a group
String filter = "(|(&(objectClass=group)"
@@ -173,23 +164,20 @@
final Map<AdEntity, String> goldenDomain = new HashMap<AdEntity, String>();
goldenDomain.put(goldenEntity, "GSA-CONNECTORS");
- final AdAdaptor.GroupCatalog golden = new AdAdaptor.GroupCatalog(
- strings, "example.com", /*feedBuiltinGroups=*/ true,
- /*entities*/ Sets.newHashSet(goldenEntity),
- /*members*/ goldenMembers,
- /*bySid*/ goldenSid,
- /*byDn*/ goldenDn,
- /*domain*/ goldenDomain);
+ AdAdaptor.GroupCatalog golden = new GroupCatalogBuilder()
+ .setFeedBuiltinGroups(true)
+ .setEntities(Sets.newHashSet(goldenEntity))
+ .setMembers(goldenMembers)
+ .setBySid(goldenSid)
+ .setByDn(goldenDn)
+ .setDomain(goldenDomain).build();
assertTrue(golden.equals(groupCatalog));
}
@Test
public void testGroupCatalogReadFromReturnsDisabledGroup() throws Exception {
- Map<String, String> strings = defaultLocalizedStringMap();
-
- AdAdaptor.GroupCatalog groupCatalog = new AdAdaptor.GroupCatalog(
- strings, "example.com", /*feedBuiltinGroups=*/ false);
+ AdAdaptor.GroupCatalog groupCatalog = new GroupCatalogBuilder().build();
MockLdapContext ldapContext = defaultMockLdapContext();
// add a disabled group
String filter = "(|(&(objectClass=group)"
@@ -237,21 +225,20 @@
goldenDomain.put(interactive, "NT Authority");
goldenDomain.put(authUsers, "NT Authority");
- final AdAdaptor.GroupCatalog golden = new AdAdaptor.GroupCatalog(
- strings, "example.com", /*feedBuiltinGroups=*/ true,
- /*entities*/ Sets.newHashSet(goldenEntity),
- /*members*/ goldenMembers,
- /*bySid*/ goldenSid,
- /*byDn*/ goldenDn,
- /*domain*/ goldenDomain);
+ AdAdaptor.GroupCatalog golden = new GroupCatalogBuilder()
+ .setFeedBuiltinGroups(true)
+ .setEntities(Sets.newHashSet(goldenEntity))
+ .setMembers(goldenMembers)
+ .setBySid(goldenSid)
+ .setByDn(goldenDn)
+ .setDomain(goldenDomain).build();
assertTrue(golden.equals(groupCatalog));
}
@Test
public void testGroupCatalogReadFromReturnsUser() throws Exception {
- AdAdaptor.GroupCatalog groupCatalog = new AdAdaptor.GroupCatalog(
- defaultLocalizedStringMap(), "example", /*feedBuiltinGroups=*/ false);
+ AdAdaptor.GroupCatalog groupCatalog = new GroupCatalogBuilder().build();
MockLdapContext ldapContext = defaultMockLdapContext();
// add a user
String filter = "(|(&(objectClass=group)"
@@ -288,13 +275,13 @@
final Map<AdEntity, String> goldenDomain = new HashMap<AdEntity, String>();
goldenDomain.put(goldenEntity, "BUILTIN");
- final AdAdaptor.GroupCatalog golden = new AdAdaptor.GroupCatalog(
- defaultLocalizedStringMap(), "example.com", /*feedBuiltinGroups=*/ true,
- /*entities*/ Sets.newHashSet(goldenEntity, userGroup, everyone),
- /*members*/ goldenMembers,
- /*bySid*/ goldenSid,
- /*byDn*/ goldenDn,
- /*domain*/ goldenDomain);
+ AdAdaptor.GroupCatalog golden = new GroupCatalogBuilder()
+ .setFeedBuiltinGroups(true)
+ .setEntities(Sets.newHashSet(goldenEntity, userGroup, everyone))
+ .setMembers(goldenMembers)
+ .setBySid(goldenSid)
+ .setByDn(goldenDn)
+ .setDomain(goldenDomain).build();
golden.wellKnownMembership.get(golden.everyone).add(goldenEntity.getDn());
assertTrue(golden.equals(groupCatalog));
@@ -306,8 +293,7 @@
@Test
public void testGroupCatalogReadFromReturnsUserMissingPrimaryGroup()
throws Exception {
- AdAdaptor.GroupCatalog groupCatalog = new AdAdaptor.GroupCatalog(
- defaultLocalizedStringMap(), "example", /*feedBuiltinGroups=*/ false);
+ AdAdaptor.GroupCatalog groupCatalog = new GroupCatalogBuilder().build();
MockLdapContext ldapContext = defaultMockLdapContext();
// add a user
String filter = "(|(&(objectClass=group)"
@@ -339,14 +325,13 @@
final Map<AdEntity, String> goldenDomain = new HashMap<AdEntity, String>();
goldenDomain.put(goldenEntity, "BUILTIN");
- final AdAdaptor.GroupCatalog golden = new AdAdaptor.GroupCatalog(
- defaultLocalizedStringMap(), "example.com", /*feedBuiltinGroups=*/ true,
- /*entities*/ Sets.newHashSet(goldenEntity),
- /*members*/ goldenMembers,
- /*bySid*/ goldenSid,
- /*byDn*/ goldenDn,
- /*domain*/ goldenDomain);
-
+ final AdAdaptor.GroupCatalog golden = new GroupCatalogBuilder()
+ .setFeedBuiltinGroups(true)
+ .setEntities(Sets.newHashSet(goldenEntity))
+ .setMembers(goldenMembers)
+ .setBySid(goldenSid)
+ .setByDn(goldenDn)
+ .setDomain(goldenDomain).build();
assertTrue(golden.equals(groupCatalog));
// make sure readEverythingFrom call is idempotent
@@ -355,10 +340,147 @@
}
@Test
+ public void testLdapQueriesWithNoFiltersOrBaseDns() throws Exception {
+ final FakeAdaptor adAdaptor = new FakeAdaptor();
+ final FakeCatalog groupCatalog = new FakeCatalog(
+ defaultLocalizedStringMap(), "example.com", false, "", "", "", "");
+ MockLdapContext ldapContext = defaultMockLdapContext();
+ final AdServer adServer = new AdServer("localhost", ldapContext);
+ adServer.initialize();
+ final String expectedGroupQuery = "(&(objectClass=group)"
+ + "(groupType:1.2.840.113556.1.4.803:=2147483648))";
+ assertEquals(expectedGroupQuery, groupCatalog.generateGroupLdapQuery());
+ final String expectedUserQuery = "(&(objectClass=user)"
+ + "(objectCategory=person))";
+ assertEquals(expectedUserQuery, groupCatalog.generateUserLdapQuery());
+ final String expectedQuery = "(|" + expectedGroupQuery + expectedUserQuery
+ + ")";
+ assertEquals(expectedQuery, groupCatalog.generateLdapQuery());
+
+ groupCatalog.resetCrawlFlags();
+ assertFalse(groupCatalog.ranFullCrawl());
+ assertFalse(groupCatalog.ranIncrementalCrawl());
+
+ groupCatalog.readEverythingFrom(adServer, /*includeMembers=*/ true);
+ assertTrue(groupCatalog.ranFullCrawl());
+ assertFalse(groupCatalog.ranIncrementalCrawl());
+
+ groupCatalog.resetCrawlFlags();
+ groupCatalog.readUpdatesFrom(adServer, "ds_service_name", "0x0123456789abc",
+ 12345677L); // earlier USN than previous run: does an incremental run
+ assertFalse(groupCatalog.ranFullCrawl());
+ assertTrue(groupCatalog.ranIncrementalCrawl());
+ }
+
+ @Test
+ public void testLdapQueriesWithFilters() throws Exception {
+ final FakeAdaptor adAdaptor = new FakeAdaptor();
+ final FakeCatalog groupCatalog = new FakeCatalog(
+ defaultLocalizedStringMap(), "example.com", false, "", "",
+ "ou=UserFilter", "ou=GroupFilter");
+ MockLdapContext ldapContext = defaultMockLdapContext();
+ final AdServer adServer = new AdServer("localhost", ldapContext);
+ adServer.initialize();
+ final String expectedGroupQuery = "(&(&(objectClass=group)"
+ + "(groupType:1.2.840.113556.1.4.803:=2147483648))(ou=GroupFilter))";
+ assertEquals(expectedGroupQuery, groupCatalog.generateGroupLdapQuery());
+ final String expectedUserQuery = "(&(&(objectClass=user)"
+ + "(objectCategory=person))(ou=UserFilter))";
+ assertEquals(expectedUserQuery, groupCatalog.generateUserLdapQuery());
+ final String expectedQuery = "(|" + expectedGroupQuery + expectedUserQuery
+ + ")";
+ assertEquals(expectedQuery, groupCatalog.generateLdapQuery());
+
+ groupCatalog.resetCrawlFlags();
+ assertFalse(groupCatalog.ranFullCrawl());
+ assertFalse(groupCatalog.ranIncrementalCrawl());
+
+ groupCatalog.readEverythingFrom(adServer, /*includeMembers=*/ true);
+ assertTrue(groupCatalog.ranFullCrawl());
+ assertFalse(groupCatalog.ranIncrementalCrawl());
+
+ groupCatalog.resetCrawlFlags();
+ groupCatalog.readUpdatesFrom(adServer, "ds_service_name", "0x0123456789abc",
+ 12345677L); // earlier USN than previous run: does an incremental run
+ assertFalse(groupCatalog.ranFullCrawl());
+ assertTrue(groupCatalog.ranIncrementalCrawl());
+ }
+
+ @Test
+ public void testLdapQueriesWithBaseDNsButNoFilters() throws Exception {
+ final FakeAdaptor adAdaptor = new FakeAdaptor();
+ final FakeCatalog groupCatalog = new FakeCatalog(
+ defaultLocalizedStringMap(), "example.com", false, "ou=UserBaseDn",
+ "ou=GroupBaseDn", "", "");
+ MockLdapContext ldapContext = defaultMockLdapContext();
+ final AdServer adServer = new AdServer("localhost", ldapContext);
+ adServer.initialize();
+ final String expectedGroupQuery = "(&(objectClass=group)"
+ + "(groupType:1.2.840.113556.1.4.803:=2147483648))";
+ assertEquals(expectedGroupQuery, groupCatalog.generateGroupLdapQuery());
+ final String expectedUserQuery = "(&(objectClass=user)"
+ + "(objectCategory=person))";
+ assertEquals(expectedUserQuery, groupCatalog.generateUserLdapQuery());
+ final String expectedQuery = "(|" + expectedGroupQuery + expectedUserQuery
+ + ")";
+ try {
+ String query = groupCatalog.generateLdapQuery();
+ fail("Did not catch expected exception!");
+ } catch (IllegalArgumentException iae) {
+ assertTrue(iae.toString().contains("not handling differing BaseDNs"));
+ }
+
+ groupCatalog.resetCrawlFlags();
+ assertFalse(groupCatalog.ranFullCrawl());
+ assertFalse(groupCatalog.ranIncrementalCrawl());
+
+ groupCatalog.readEverythingFrom(adServer, /*includeMembers=*/ true);
+ assertTrue(groupCatalog.ranFullCrawl());
+ assertFalse(groupCatalog.ranIncrementalCrawl());
+
+ groupCatalog.resetCrawlFlags();
+ groupCatalog.readUpdatesFrom(adServer, "ds_service_name", "0x0123456789abc",
+ 12345677L); // earlier USN than previous run: does an incremental run
+ assertFalse(groupCatalog.ranFullCrawl());
+ assertTrue(groupCatalog.ranIncrementalCrawl());
+ }
+
+ @Test
+ public void testLdapQueriesWithBaseDNsAndFilters() throws Exception {
+ final FakeAdaptor adAdaptor = new FakeAdaptor();
+ AdAdaptor.GroupCatalog groupCatalog = new GroupCatalogBuilder()
+ .setUserSearchBaseDN("ou=UserBaseDn")
+ .setGroupSearchBaseDN("ou=GroupBaseDn")
+ .setUserSearchFilter("ou=UserFilter")
+ .setGroupSearchFilter("ou=GroupFilter").build();
+ MockLdapContext ldapContext = defaultMockLdapContext();
+ final AdServer adServer = new AdServer("localhost", ldapContext);
+ adServer.initialize();
+ final String expectedGroupQuery = "(&(&(objectClass=group)"
+ + "(groupType:1.2.840.113556.1.4.803:=2147483648))(ou=GroupFilter))";
+ assertEquals(expectedGroupQuery, groupCatalog.generateGroupLdapQuery());
+ final String expectedUserQuery = "(&(&(objectClass=user)"
+ + "(objectCategory=person))(ou=UserFilter))";
+ assertEquals(expectedUserQuery, groupCatalog.generateUserLdapQuery());
+ final String expectedQuery = "(|" + expectedGroupQuery + expectedUserQuery
+ + ")";
+ try {
+ String query = groupCatalog.generateLdapQuery();
+ fail("Did not catch expected exception!");
+ } catch (IllegalArgumentException iae) {
+ assertTrue(iae.toString().contains("not handling differing BaseDNs"));
+ }
+
+ groupCatalog.readEverythingFrom(adServer, /*includeMembers=*/ false);
+ groupCatalog.readUpdatesFrom(adServer, "ds_service_name", "0x0123456789abc",
+ 12345677L); // earlier USN than previous run: does an incremental run
+ }
+
+ @Test
public void testFullCrawlVersusIncrementalCrawlFlow() throws Exception {
final FakeAdaptor adAdaptor = new FakeAdaptor();
final FakeCatalog groupCatalog = new FakeCatalog(
- defaultLocalizedStringMap(), "example.com", false);
+ defaultLocalizedStringMap(), "example.com", false, "", "", "", "");
MockLdapContext ldapContext = defaultMockLdapContext();
final AdServer adServer = new AdServer("localhost", ldapContext);
adServer.initialize();
@@ -431,10 +553,7 @@
@Test
public void testGroupCatalogReadFromIncrementalCrawl() throws Exception {
- Map<String, String> strings = defaultLocalizedStringMap();
-
- AdAdaptor.GroupCatalog groupCatalog = new AdAdaptor.GroupCatalog(
- strings, "example.com", /*feedBuiltinGroups=*/ false);
+ AdAdaptor.GroupCatalog groupCatalog = new GroupCatalogBuilder().build();
MockLdapContext ldapContext = defaultMockLdapContext();
// add a group
String filter = "(|(&(objectClass=group)"
@@ -485,8 +604,8 @@
"0x0123456789abc", 12345677L);
// extract incrementally-added user as one golden entity
- Set<AdEntity> incrementalUserSet = adServer.search(incrementalFilter, false,
- new String[] { "member", "objectSid;binary", "objectGUID;binary",
+ Set<AdEntity> incrementalUserSet = adServer.search("", incrementalFilter,
+ false, new String[] { "member", "objectSid;binary", "objectGUID;binary",
"primaryGroupId", "sAMAccountName" });
goldenResults = incrementalUserSet;
assertEquals(goldenResults, updateResults);
@@ -499,7 +618,7 @@
final AdEntity goldenUserEntity = searchedEntity[0];
// extract group from full crawl as the other golden entity
- Set<AdEntity> fullyCrawledGroupSet = adServer.search(filter, false,
+ Set<AdEntity> fullyCrawledGroupSet = adServer.search("", filter, false,
new String[] { "member", "objectSid;binary", "objectGUID;binary",
"primaryGroupId", "sAMAccountName" });
assertEquals(1, fullyCrawledGroupSet.size());
@@ -524,13 +643,13 @@
goldenDomain.put(goldenUserEntity, "BUILTIN");
goldenDomain.put(goldenGroupEntity, "GSA-CONNECTORS");
- final AdAdaptor.GroupCatalog golden = new AdAdaptor.GroupCatalog(
- strings, "example.com", /*feedBuiltinGroups=*/ true,
- /*entities*/ Sets.newHashSet(goldenUserEntity, goldenGroupEntity),
- /*members*/ goldenMembers,
- /*bySid*/ goldenSid,
- /*byDn*/ goldenDn,
- /*domain*/ goldenDomain);
+ final AdAdaptor.GroupCatalog golden = new GroupCatalogBuilder()
+ .setFeedBuiltinGroups(true)
+ .setEntities(Sets.newHashSet(goldenUserEntity, goldenGroupEntity))
+ .setMembers(goldenMembers)
+ .setBySid(goldenSid)
+ .setByDn(goldenDn)
+ .setDomain(goldenDomain).build();
assertEquals(golden, groupCatalog);
// do another incremental crawl with same results
@@ -542,10 +661,7 @@
@Test
public void testGroupCatalogResolveForeignSecurityPrincipals()
throws Exception {
- Map<String, String> strings = defaultLocalizedStringMap();
-
- AdAdaptor.GroupCatalog groupCatalog = new AdAdaptor.GroupCatalog(
- strings, "example.com", /*feedBuiltinGroups=*/ false);
+ AdAdaptor.GroupCatalog groupCatalog = new GroupCatalogBuilder().build();
MockLdapContext ldapContext = defaultMockLdapContext();
// add a group
String filter = "(|(&(objectClass=group)"
@@ -580,7 +696,7 @@
// add two additional entities to test all branches of our method.
// first -- a user
- Set<AdEntity> userEntitySet = adServer.search(filter2, false,
+ Set<AdEntity> userEntitySet = adServer.search("", filter2, false,
new String[] { "cn", "objectSid;binary", "objectGUID;binary",
"primaryGroupId", "sAMAccountName" });
assertEquals(1, userEntitySet.size());
@@ -598,7 +714,7 @@
groupCatalog.resolveForeignSecurityPrincipals(groupCatalog.entities);
// extract original group entity
- Set<AdEntity> groupEntitySet = adServer.search(filter, false,
+ Set<AdEntity> groupEntitySet = adServer.search("", filter, false,
new String[] { "member", "objectSid;binary", "objectGUID;binary",
"sAMAccountName" });
assertEquals(1, groupEntitySet.size());
@@ -631,15 +747,14 @@
goldenDn.put(goldenEntity.getDn(), goldenEntity);
final Map<AdEntity, String> goldenDomain = new HashMap<AdEntity, String>();
goldenDomain.put(goldenEntity, "GSA-CONNECTORS");
- final AdAdaptor.GroupCatalog golden = new AdAdaptor.GroupCatalog(
- defaultLocalizedStringMap(), "example.com", /*feedBuiltinGroups=*/ true,
- /*entities*/ goldenEntities,
- /*members*/ goldenMembers,
- /*bySid*/ goldenSid,
- /*byDn*/ goldenDn,
- /*domain*/ goldenDomain);
-
- assertTrue(golden.equals(groupCatalog));
+ final AdAdaptor.GroupCatalog golden = new GroupCatalogBuilder()
+ .setFeedBuiltinGroups(true)
+ .setEntities(goldenEntities)
+ .setMembers(goldenMembers)
+ .setBySid(goldenSid)
+ .setByDn(goldenDn)
+ .setDomain(goldenDomain).build();
+ assertEquals(golden, groupCatalog);
// make sure resolveForeignSecurityPrincipals call is idempotent
groupCatalog.resolveForeignSecurityPrincipals(groupCatalog.entities);
@@ -648,10 +763,7 @@
@Test
public void testGroupCatalogMakeDefs() throws Exception {
- Map<String, String> strings = defaultLocalizedStringMap();
-
- AdAdaptor.GroupCatalog groupCatalog = new AdAdaptor.GroupCatalog(
- strings, "example.com", /*feedBuiltinGroups=*/ false);
+ AdAdaptor.GroupCatalog groupCatalog = new GroupCatalogBuilder().build();
MockLdapContext ldapContext = mockLdapContextForMakeDefs(false);
@@ -677,10 +789,7 @@
@Test
public void testGroupCatalogMakeDefsWithDisabledGroup() throws Exception {
- Map<String, String> strings = defaultLocalizedStringMap();
-
- AdAdaptor.GroupCatalog groupCatalog = new AdAdaptor.GroupCatalog(
- strings, "example.com", /*feedBuiltinGroups=*/ false);
+ AdAdaptor.GroupCatalog groupCatalog = new GroupCatalogBuilder().build();
MockLdapContext ldapContext = mockLdapContextForMakeDefs(true);
@@ -704,10 +813,8 @@
@Test
public void testGroupCatalogMakeDefsWellKnownParent() throws Exception {
- Map<String, String> strings = defaultLocalizedStringMap();
-
- AdAdaptor.GroupCatalog groupCatalog = new AdAdaptor.GroupCatalog(
- strings, "example.com", /*feedBuiltinGroups=*/ true);
+ AdAdaptor.GroupCatalog groupCatalog = new GroupCatalogBuilder()
+ .setFeedBuiltinGroups(true).build();
Logger log = Logger.getLogger(AdAdaptor.class.getName());
Level oldLevel = log.getLevel();
log.setLevel(Level.FINER);
@@ -746,7 +853,7 @@
replacementGroup.getMembers().add("dn=");
groupCatalog.members.put(groupWithNoName, new TreeSet<String>());
- Set<AdEntity> emptyUser = adServer.search(filter, false,
+ Set<AdEntity> emptyUser = adServer.search("", filter, false,
new String[] { "objectSid;binary", "objectGUID;binary",
"primaryGroupId", "sAMAccountName" });
assertEquals(1, emptyUser.size());
@@ -807,6 +914,7 @@
configEntries.put("ad.defaultUser", "defaultUser");
configEntries.put("ad.defaultPassword", "password");
configEntries.put("ad.ldapReadTimeoutSecs", "");
+ configEntries.put("ad.userSearchFilter", "cn=UserNotFound");
configEntries.put("server.port", "5680");
configEntries.put("server.dashboardPort", "5681");
pushGroupDefinitions(adAdaptor, configEntries, pusher, /*fullPush=*/ true,
@@ -833,6 +941,50 @@
configEntries.put("ad.defaultUser", "defaultUser");
configEntries.put("ad.defaultPassword", "password");
configEntries.put("ad.ldapReadTimeoutSecs", "0");
+ configEntries.put("ad.groupSearchFilter", "cn=GroupNotFound");
+ configEntries.put("server.port", "5680");
+ configEntries.put("server.dashboardPort", "5681");
+ pushGroupDefinitions(adAdaptor, configEntries, pusher, /*fullPush=*/ true,
+ /*init=*/ true);
+ Map<GroupPrincipal, Collection<Principal>> results = pusher.getGroups();
+ // the above (eventually) calls AdAdaptor.init() with the specified config.
+ }
+
+ @Test
+ public void testFakeAdaptorUserAndPasswordSpecified() throws Exception {
+ AdAdaptor adAdaptor = new FakeAdaptor();
+ AccumulatingDocIdPusher pusher = new AccumulatingDocIdPusher();
+ Map<String, String> configEntries = new HashMap<String, String>();
+ configEntries.put("gsa.hostname", "localhost");
+ configEntries.put("ad.servers", "server1");
+ configEntries.put("ad.servers.server1.host", "localhost");
+ configEntries.put("ad.servers.server1.port", "1234");
+ configEntries.put("ad.servers.server1.user", "username");
+ configEntries.put("ad.servers.server1.password", "password");
+ configEntries.put("ad.servers.server1.method", "ssl");
+ configEntries.put("ad.userSearchBaseDN", "ou=DoesNotMatter");
+ configEntries.put("server.port", "5680");
+ configEntries.put("server.dashboardPort", "5681");
+ pushGroupDefinitions(adAdaptor, configEntries, pusher, /*fullPush=*/ true,
+ /*init=*/ true);
+ Map<GroupPrincipal, Collection<Principal>> results = pusher.getGroups();
+ // the above (eventually) calls AdAdaptor.init() with the specified config.
+ }
+
+ @Test
+ public void testFakeAdaptorDefaultUserAndPasswordSpecified()
+ throws Exception {
+ AdAdaptor adAdaptor = new FakeAdaptor();
+ AccumulatingDocIdPusher pusher = new AccumulatingDocIdPusher();
+ Map<String, String> configEntries = new HashMap<String, String>();
+ configEntries.put("gsa.hostname", "localhost");
+ configEntries.put("ad.servers", "server1");
+ configEntries.put("ad.servers.server1.host", "localhost");
+ configEntries.put("ad.servers.server1.port", "1234");
+ configEntries.put("ad.servers.server1.method", "ssl");
+ configEntries.put("ad.defaultUser", "defaultUser");
+ configEntries.put("ad.defaultPassword", "defaultPassword");
+ configEntries.put("ad.groupSearchBaseDN", "ou=DoesNotMatter");
configEntries.put("server.port", "5680");
configEntries.put("server.dashboardPort", "5681");
pushGroupDefinitions(adAdaptor, configEntries, pusher, /*fullPush=*/ true,
@@ -978,12 +1130,13 @@
int timesSearchCalled = 0;
int timesEnsureConnectionCalled = 0;
@Override
- public Set<AdEntity> search(String filter, boolean deleted,
- String[] attributes) throws InterruptedNamingException {
+ public Set<AdEntity> search(String baseDn, String filter,
+ boolean deleted, String[] attributes)
+ throws InterruptedNamingException {
if (errorFilter.equals(filter) && timesSearchCalled++ == 0) {
throw new InterruptedNamingException("First exception");
} else {
- return super.search(filter, deleted, attributes);
+ return super.search(baseDn, filter, deleted, attributes);
}
}
@Override
@@ -1039,7 +1192,7 @@
return AdServerTest.hexStringToByteArray(s);
}
- private Map<String, String> defaultLocalizedStringMap() {
+ private static Map<String, String> defaultLocalizedStringMap() {
Map<String, String> strings = new HashMap<String, String>();
strings.put("Everyone", "everyone");
strings.put("NTAuthority", "NT Authority");
@@ -1126,7 +1279,7 @@
// add two additional entities to test all branches of our method.
assertEquals(1, groupCatalog.entities.size());
// first -- a user
- Set<AdEntity> userEntity = adServer.search(
+ Set<AdEntity> userEntity = adServer.search("",
"(&(objectClass=user)(objectCategory=person))", false,
new String[] { "cn", "objectSid;binary", "objectGUID;binary",
"primaryGroupId", "sAMAccountName" });
@@ -1320,8 +1473,11 @@
private boolean ranIncrementalCrawl;
public FakeCatalog(Map<String, String> localizedStrings, String namespace,
- boolean feedBuiltinGroups) {
- super(localizedStrings, namespace, feedBuiltinGroups);
+ boolean feedBuiltinGroups, String userSearchBaseDn,
+ String groupSearchBaseDn, String userSearchFilter,
+ String groupSearchFilter) {
+ super(localizedStrings, namespace, feedBuiltinGroups, userSearchBaseDn,
+ groupSearchBaseDn, userSearchFilter, groupSearchFilter);
}
@Override
@@ -1395,7 +1551,7 @@
}
ranFullCrawl = true;
return new AdAdaptor.GroupCatalog(defaultLocalizedStringMap(),
- "example.com", /*feedBuiltinGroups=*/ true);
+ "example.com", /*feedBuiltinGroups=*/ true, "", "", "", "");
}
};
@@ -1432,4 +1588,105 @@
}));
}
}
+
+ private static class GroupCatalogBuilder {
+ private Map<String, String> localizedStrings = defaultLocalizedStringMap();
+ private String namespace = "example.com";
+ private boolean feedBuiltinGroups = false;
+ private String userSearchBaseDN = "";
+ private String groupSearchBaseDN = "";
+ private String userSearchFilter = "";
+ private String groupSearchFilter = "";
+ private Set<AdEntity> entities;
+ private Map<AdEntity, Set<String>> members;
+ private Map<String, AdEntity> bySid;
+ private Map<String, AdEntity> byDn;
+ private Map<AdEntity, String> domain;
+ /**
+ * The following field is only used by this Builder class, to determine if
+ * the build() method should call the standard constructor or the extended
+ * constructor.
+ */
+ private boolean useExtendedConstructor = false;
+
+ public GroupCatalogBuilder setLocalizedStrings(Map<String, String> locals) {
+ this.localizedStrings = locals;
+ return this;
+ }
+
+ public GroupCatalogBuilder setNamespace(String namespace) {
+ this.namespace = namespace;
+ return this;
+ }
+
+ public GroupCatalogBuilder setFeedBuiltinGroups(boolean feedBuiltinGroups) {
+ this.feedBuiltinGroups = feedBuiltinGroups;
+ return this;
+ }
+
+ public GroupCatalogBuilder setUserSearchBaseDN(String userSearchBaseDN) {
+ this.userSearchBaseDN = userSearchBaseDN;
+ return this;
+ }
+
+ public GroupCatalogBuilder setGroupSearchBaseDN(String groupSearchBaseDN) {
+ this.groupSearchBaseDN = groupSearchBaseDN;
+ return this;
+ }
+
+ public GroupCatalogBuilder setUserSearchFilter(String userSearchFilter) {
+ this.userSearchFilter = userSearchFilter;
+ return this;
+ }
+
+ public GroupCatalogBuilder setGroupSearchFilter(String groupSearchFilter) {
+ this.groupSearchFilter = groupSearchFilter;
+ return this;
+ }
+
+ // The remaining fields are the "extended" fields -- their setters set the
+ // variable as well as the flag to use the extended constructor.
+
+ public GroupCatalogBuilder setEntities(Set<AdEntity> entities) {
+ this.entities = entities;
+ this.useExtendedConstructor = true;
+ return this;
+ }
+
+ public GroupCatalogBuilder setMembers(Map<AdEntity, Set<String>> members) {
+ this.members = members;
+ this.useExtendedConstructor = true;
+ return this;
+ }
+
+ public GroupCatalogBuilder setBySid(Map<String, AdEntity> bySid) {
+ this.bySid = bySid;
+ this.useExtendedConstructor = true;
+ return this;
+ }
+
+ public GroupCatalogBuilder setByDn(Map<String, AdEntity> byDn) {
+ this.byDn = byDn;
+ this.useExtendedConstructor = true;
+ return this;
+ }
+
+ public GroupCatalogBuilder setDomain(Map<AdEntity, String> domain) {
+ this.domain = domain;
+ this.useExtendedConstructor = true;
+ return this;
+ }
+
+ public AdAdaptor.GroupCatalog build() {
+ if (useExtendedConstructor) {
+ return new AdAdaptor.GroupCatalog(localizedStrings, namespace,
+ feedBuiltinGroups, entities, members, bySid, byDn, domain,
+ userSearchBaseDN, groupSearchBaseDN, userSearchFilter,
+ groupSearchFilter);
+ }
+ return new AdAdaptor.GroupCatalog(localizedStrings, namespace,
+ feedBuiltinGroups, userSearchBaseDN, groupSearchBaseDN,
+ userSearchFilter, groupSearchFilter);
+ }
+ }
}
diff --git a/test/com/google/enterprise/adaptor/ad/AdServerTest.java b/test/com/google/enterprise/adaptor/ad/AdServerTest.java
index 66973d1..2a66305 100644
--- a/test/com/google/enterprise/adaptor/ad/AdServerTest.java
+++ b/test/com/google/enterprise/adaptor/ad/AdServerTest.java
@@ -16,19 +16,18 @@
import static org.junit.Assert.*;
+import com.google.enterprise.adaptor.InvalidConfigurationException;
+
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
-import com.google.enterprise.adaptor.InvalidConfigurationException;
-import com.google.enterprise.adaptor.StartupException;
+import java.util.*;
import javax.naming.*;
import javax.naming.directory.*;
import javax.naming.ldap.*;
-import java.util.*;
-
/** Test cases for {@link AdServer}. */
public class AdServerTest {
@Rule
@@ -307,7 +306,49 @@
hexStringToByteArray("000102030405060708090a0b0c"));
AdServer adServer = new AdServer("localhost", ldapContext);
adServer.initialize();
- Set<AdEntity> resultSet = adServer.search(filter, false,
+ Set<AdEntity> resultSet = adServer.search("", filter, false,
+ new String[] { "cn", "primaryGroupId", "objectGUID;binary" });
+ assertEquals(1, resultSet.size());
+ for (AdEntity ae : resultSet) {
+ assertEquals("name under", ae.getCommonName());
+ }
+ }
+
+ @Test
+ public void testSearchWithNullBaseDnReturnsOneUser() throws Exception {
+ MockLdapContext ldapContext = new MockLdapContext();
+ addStandardKeysAndResults(ldapContext);
+ // populate additional attributes with values we can test
+ final String filter = "ou=Users";
+ final String userDn = "DN_for_default_naming_context";
+ ldapContext.addSearchResult(filter, "cn", userDn, "user1")
+ .addSearchResult(filter, "primaryGroupId", userDn, "users")
+ .addSearchResult(filter, "objectGUID;binary", userDn,
+ hexStringToByteArray("000102030405060708090a0b0c"));
+ AdServer adServer = new AdServer("localhost", ldapContext);
+ adServer.initialize();
+ Set<AdEntity> resultSet = adServer.search(null, filter, false,
+ new String[] { "cn", "primaryGroupId", "objectGUID;binary" });
+ assertEquals(1, resultSet.size());
+ for (AdEntity ae : resultSet) {
+ assertEquals("name under", ae.getCommonName());
+ }
+ }
+
+ @Test
+ public void testSearchUnderDifferentBaseDnReturnsOneUser() throws Exception {
+ MockLdapContext ldapContext = new MockLdapContext();
+ addStandardKeysAndResults(ldapContext);
+ // populate additional attributes with values we can test
+ final String filter = "ou=Users";
+ final String userDn = "DN_for_default_naming_context";
+ ldapContext.addSearchResult(filter, "cn", userDn, "user1")
+ .addSearchResult(filter, "primaryGroupId", userDn, "users")
+ .addSearchResult(filter, "objectGUID;binary", userDn,
+ hexStringToByteArray("000102030405060708090a0b0c"));
+ AdServer adServer = new AdServer("localhost", ldapContext);
+ adServer.initialize();
+ Set<AdEntity> resultSet = adServer.search(userDn, filter, false,
new String[] { "cn", "primaryGroupId", "objectGUID;binary" });
assertEquals(1, resultSet.size());
for (AdEntity ae : resultSet) {
@@ -326,7 +367,7 @@
.addSearchResult(filter, "primaryGroupId", userDn, "users");
AdServer adServer = new AdServer("localhost", ldapContext);
adServer.initialize();
- Set<AdEntity> resultSet = adServer.search(filter, false,
+ Set<AdEntity> resultSet = adServer.search("", filter, false,
new String[] { "cn", "primaryGroupId", "objectGUID;binary" });
assertEquals(0, resultSet.size());
}
@@ -349,7 +390,7 @@
.addSearchResult(filter, "primaryGroupId", userDn, "users");
AdServer adServer = new AdServer("localhost", ldapContext);
adServer.initialize();
- Set<AdEntity> resultSet = adServer.search(filter, false,
+ Set<AdEntity> resultSet = adServer.search("", filter, false,
new String[] { "cn", "primaryGroupId", "objectGUID;binary" });
assertEquals(0, resultSet.size());
}
@@ -367,7 +408,7 @@
hexStringToByteArray("000102030405060708090a0b0c"));
AdServer adServer = new AdServer("localhost", ldapContext);
adServer.initialize();
- Set<AdEntity> resultSet = adServer.search(filter, true,
+ Set<AdEntity> resultSet = adServer.search("", filter, true,
new String[] { "cn", "primaryGroupId", "objectGUID;binary" });
assertEquals(1, resultSet.size());
for (AdEntity ae : resultSet) {
@@ -393,7 +434,7 @@
hexStringToByteArray("000102030405060708090a0b0c"));
AdServer adServer = new AdServer("localhost", ldapContext);
adServer.initialize();
- Set<AdEntity> resultSet = adServer.search(filter, true,
+ Set<AdEntity> resultSet = adServer.search("", filter, true,
new String[] { "cn", "members", "objectGUID;binary" });
assertEquals(1, resultSet.size());
for (AdEntity ae : resultSet) {
@@ -408,14 +449,25 @@
// populate additional attributes with values we can test
final String filter = "ou=Users";
final String userDn = "DN_for_default_naming_context";
+ final String group2Dn = "cn=Cn_for_another_group";
List<String> members = Arrays.asList("dn_for_user_1", "dn_for_user_2");
ldapContext.addSearchResult(filter, "cn", userDn, "users")
.addSearchResult(filter, "objectGUID;binary", userDn,
hexStringToByteArray("000102030405060708090a0b0c"))
- .addSearchResult(filter, "member", userDn, members);
+ .addSearchResult(filter, "member", userDn, members)
+ .addSearchResult(filter, "objectGUID;binary", group2Dn,
+ hexStringToByteArray("000102030405060708090a0b0d"))
+ .addSearchResult(filter, "member", group2Dn, members);
AdServer adServer = new AdServer("localhost", ldapContext);
adServer.initialize();
- Set<AdEntity> resultSet = adServer.search(filter, false,
+ Set<AdEntity> resultSet = adServer.search("", filter, false,
+ new String[] { "cn", "member", "objectGUID;binary" });
+ assertEquals(1, resultSet.size());
+ for (AdEntity ae : resultSet) {
+ assertEquals(new HashSet<String>(members), ae.getMembers());
+ }
+ // read second group under its baseDn
+ resultSet = adServer.search(group2Dn, filter, false,
new String[] { "cn", "member", "objectGUID;binary" });
assertEquals(1, resultSet.size());
for (AdEntity ae : resultSet) {
@@ -446,7 +498,7 @@
moreMembers);
AdServer adServer = new AdServer("localhost", ldapContext);
adServer.initialize();
- Set<AdEntity> resultSet = adServer.search(filter, false,
+ Set<AdEntity> resultSet = adServer.search("", filter, false,
// need the ranged members for MockLdapContext, not for "real" AD.
new String[] { "cn", "member", "member;Range=0-1", "member;Range=2-3",
"objectGUID;binary", "sAMAccountName" });
@@ -484,7 +536,7 @@
evenMore);
AdServer adServer = new AdServer("localhost", ldapContext);
adServer.initialize();
- Set<AdEntity> resultSet = adServer.search(filter, false,
+ Set<AdEntity> resultSet = adServer.search("", filter, false,
// need the ranged members for MockLdapContext, not for "real" AD.
new String[] { "cn", "member", "member;Range=0-1", "member;Range=2-3",
"member;Range=4-5*", "objectGUID;binary",