Support recursive queries against LDAP directories
The top domain of a company might be DC=example,DC=com, while a sub-domain may be DC=asia,DC=example,DC=com. Assuming all users in the company will use Gerrit, but their accounts are in different sub-domains, recursive search under DC=example,DC=com is required. So ldap.accountScope can be set to subtree for this case. Change-Id: I9c6f98148b00e7c3f1e197054efcb2899f370d74 Signed-off-by: Shawn O. Pearce <sop@google.com>
This commit is contained in:
@@ -514,6 +514,17 @@ server is attempted.
|
||||
Root of the tree containing all user accounts. This is typically
|
||||
of the form `ou=people,dc=example,dc=com`.
|
||||
|
||||
[[ldap.accountScope]]ldap.accountScope::
|
||||
+
|
||||
Scope of the search performed for accounts. Must be one of:
|
||||
+
|
||||
* `one`: Search only one level below accountBase, but not recursive
|
||||
* `sub` or `subtree`: Search recursively below accountBase
|
||||
* `base` or `object`: Search exactly accountBase; probably not desired
|
||||
|
||||
+
|
||||
Default is `subtree` as many directories have several levels.
|
||||
|
||||
[[ldap.accountPattern]]ldap.accountPattern::
|
||||
+
|
||||
Query pattern to use when searching for a user account. This may be
|
||||
@@ -572,6 +583,17 @@ Default is `uid`, a common value for most servers.
|
||||
Root of the tree containing all group objects. This is typically
|
||||
of the form `ou=groups,dc=example,dc=com`.
|
||||
|
||||
[[ldap.groupScope]]ldap.groupScope::
|
||||
+
|
||||
Scope of the search performed for group objects. Must be one of:
|
||||
+
|
||||
* `one`: Search only one level below groupBase, but not recursive
|
||||
* `sub` or `subtree`: Search recursively below groupBase
|
||||
* `base` or `object`: Search exactly groupBase; probably not desired
|
||||
|
||||
+
|
||||
Default is `subtree` as many directories have several levels.
|
||||
|
||||
[[ldap.groupName]]ldap.groupName::
|
||||
+
|
||||
Name of an attribute on the group object which matches to the name
|
||||
|
||||
@@ -29,14 +29,45 @@ import javax.naming.directory.SearchResult;
|
||||
|
||||
/** Supports issuing parameterized queries against an LDAP data source. */
|
||||
class LdapQuery {
|
||||
static enum SearchScope {
|
||||
// Search only the base DN
|
||||
//
|
||||
OBJECT(SearchControls.OBJECT_SCOPE), //
|
||||
BASE(SearchControls.OBJECT_SCOPE),
|
||||
|
||||
// Search all entries one level under the base DN
|
||||
//
|
||||
// Does not include the base DN, and does not include items below items
|
||||
// under the base DN.
|
||||
//
|
||||
ONE(SearchControls.ONELEVEL_SCOPE),
|
||||
|
||||
// Search all entries under the base DN, including the base DN.
|
||||
//
|
||||
SUBTREE(SearchControls.SUBTREE_SCOPE), //
|
||||
SUB(SearchControls.SUBTREE_SCOPE);
|
||||
|
||||
private final int scope;
|
||||
|
||||
SearchScope(final int scope) {
|
||||
this.scope = scope;
|
||||
}
|
||||
|
||||
int scope() {
|
||||
return scope;
|
||||
}
|
||||
}
|
||||
|
||||
private final String base;
|
||||
private final SearchScope searchScope;
|
||||
private final String pattern;
|
||||
private final String[] patternArgs;
|
||||
private final String[] returnAttributes;
|
||||
|
||||
LdapQuery(final String base, final String pattern,
|
||||
final Set<String> returnAttributes) {
|
||||
LdapQuery(final String base, final SearchScope searchScope,
|
||||
final String pattern, final Set<String> returnAttributes) {
|
||||
this.base = base;
|
||||
this.searchScope = searchScope;
|
||||
|
||||
final StringBuilder p = new StringBuilder();
|
||||
final List<String> a = new ArrayList<String>(4);
|
||||
@@ -76,7 +107,7 @@ class LdapQuery {
|
||||
final SearchControls sc = new SearchControls();
|
||||
final NamingEnumeration<SearchResult> res;
|
||||
|
||||
sc.setSearchScope(SearchControls.ONELEVEL_SCOPE);
|
||||
sc.setSearchScope(searchScope.scope());
|
||||
sc.setReturningAttributes(returnAttributes);
|
||||
res = ctx.search(base, pattern, bind(params), sc);
|
||||
try {
|
||||
|
||||
@@ -26,7 +26,9 @@ import com.google.gerrit.server.account.GroupCache;
|
||||
import com.google.gerrit.server.account.Realm;
|
||||
import com.google.gerrit.server.cache.Cache;
|
||||
import com.google.gerrit.server.cache.SelfPopulatingCache;
|
||||
import com.google.gerrit.server.config.ConfigUtil;
|
||||
import com.google.gerrit.server.config.GerritServerConfig;
|
||||
import com.google.gerrit.server.ldap.LdapQuery.SearchScope;
|
||||
import com.google.gwtorm.client.OrmException;
|
||||
import com.google.gwtorm.client.SchemaFactory;
|
||||
import com.google.inject.Inject;
|
||||
@@ -96,9 +98,11 @@ class LdapRealm implements Realm {
|
||||
groupName = reqdef(config, "groupName", "cn");
|
||||
groupAtts.add(groupName);
|
||||
final String groupBase = required(config, "groupBase");
|
||||
final SearchScope groupScope = scope(config, "groupScope");
|
||||
final String groupMemberPattern =
|
||||
reqdef(config, "groupMemberPattern", "(memberUid=${username})");
|
||||
groupMemberQuery = new LdapQuery(groupBase, groupMemberPattern, groupAtts);
|
||||
groupMemberQuery =
|
||||
new LdapQuery(groupBase, groupScope, groupMemberPattern, groupAtts);
|
||||
if (groupMemberQuery.getParameters().length == 0) {
|
||||
throw new IllegalArgumentException(
|
||||
"No variables in ldap.groupMemberPattern");
|
||||
@@ -140,9 +144,11 @@ class LdapRealm implements Realm {
|
||||
}
|
||||
}
|
||||
final String accountBase = required(config, "accountBase");
|
||||
final SearchScope accountScope = scope(config, "accountScope");
|
||||
final String accountPattern =
|
||||
reqdef(config, "accountPattern", "(uid=${username})");
|
||||
accountQuery = new LdapQuery(accountBase, accountPattern, accountAtts);
|
||||
accountQuery =
|
||||
new LdapQuery(accountBase, accountScope, accountPattern, accountAtts);
|
||||
if (accountQuery.getParameters().length == 0) {
|
||||
throw new IllegalArgumentException("No variables in ldap.accountPattern");
|
||||
}
|
||||
@@ -155,6 +161,10 @@ class LdapRealm implements Realm {
|
||||
};
|
||||
}
|
||||
|
||||
private static SearchScope scope(final Config c, final String setting) {
|
||||
return ConfigUtil.getEnum(c, "ldap", null, setting, SearchScope.SUBTREE);
|
||||
}
|
||||
|
||||
private static String optional(final Config config, final String name) {
|
||||
return config.getString("ldap", null, name);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user