Merge pull request #147 from clems4ever/userdn-ldap-filter
Add {dn} as an available matcher in LDAP groups filterpull/149/head
commit
4b51ae30cc
|
@ -33,8 +33,9 @@ ldap:
|
|||
|
||||
# The groups filter used for retrieving groups of a given user.
|
||||
# {0} is a matcher replaced by username.
|
||||
# 'member=cn={0},<additional_users_dn>,<base_dn>' by default.
|
||||
groups_filter: (&(member=cn={0},ou=users,dc=example,dc=com)(objectclass=groupOfNames))
|
||||
# {dn} is a matcher replaced by user DN.
|
||||
# 'member={dn}' by default.
|
||||
groups_filter: (&(member={dn})(objectclass=groupOfNames))
|
||||
|
||||
# The attribute holding the name of the group
|
||||
group_name_attribute: cn
|
||||
|
|
|
@ -33,8 +33,9 @@ ldap:
|
|||
|
||||
# The groups filter used for retrieving groups of a given user.
|
||||
# {0} is a matcher replaced by username.
|
||||
# 'member=cn={0},<additional_users_dn>,<base_dn>' by default.
|
||||
groups_filter: (&(member=cn={0},ou=users,dc=example,dc=com)(objectclass=groupOfNames))
|
||||
# {dn} is a matcher replaced by user DN.
|
||||
# 'member={dn}' by default.
|
||||
groups_filter: (&(member={dn})(objectclass=groupOfNames))
|
||||
|
||||
# The attribute holding the name of the group
|
||||
group_name_attribute: cn
|
||||
|
|
|
@ -29,10 +29,7 @@ function ensure_key_existence(config: object, path: string): void {
|
|||
|
||||
function adaptLdapConfiguration(userConfig: UserLdapConfiguration): LdapConfiguration {
|
||||
const DEFAULT_USERS_FILTER = "cn={0}";
|
||||
const DEFAULT_GROUPS_FILTER =
|
||||
userConfig.additional_users_dn
|
||||
? Util.format("member=cn={0},%s,%s", userConfig.additional_groups_dn, userConfig.base_dn)
|
||||
: Util.format("member=cn={0},%s", userConfig.base_dn);
|
||||
const DEFAULT_GROUPS_FILTER = "member={dn}";
|
||||
const DEFAULT_GROUP_NAME_ATTRIBUTE = "cn";
|
||||
const DEFAULT_MAIL_ATTRIBUTE = "mail";
|
||||
|
||||
|
|
|
@ -47,18 +47,34 @@ export class Client implements IClient {
|
|||
});
|
||||
}
|
||||
|
||||
private createGroupsFilter(userGroupsFilter: string, username: string): BluebirdPromise<string> {
|
||||
if (userGroupsFilter.indexOf("{0}") > 0) {
|
||||
return BluebirdPromise.resolve(userGroupsFilter.replace("{0}", username));
|
||||
}
|
||||
else if (userGroupsFilter.indexOf("{dn}") > 0) {
|
||||
return this.searchUserDn(username)
|
||||
.then(function (userDN: string) {
|
||||
return BluebirdPromise.resolve(userGroupsFilter.replace("{dn}", userDN));
|
||||
});
|
||||
}
|
||||
return BluebirdPromise.resolve(userGroupsFilter);
|
||||
}
|
||||
|
||||
searchGroups(username: string): BluebirdPromise<string[]> {
|
||||
const that = this;
|
||||
const filter = that.options.groups_filter.replace("{0}", username);
|
||||
const query = {
|
||||
scope: "sub",
|
||||
attributes: [that.options.group_name_attribute],
|
||||
filter: filter
|
||||
};
|
||||
return this.ldapClient.searchAsync(that.options.groups_dn, query)
|
||||
return this.createGroupsFilter(this.options.groups_filter, username)
|
||||
.then(function (groupsFilter: string) {
|
||||
that.logger.debug("Computed groups filter is %s", groupsFilter);
|
||||
const query = {
|
||||
scope: "sub",
|
||||
attributes: [that.options.group_name_attribute],
|
||||
filter: groupsFilter
|
||||
};
|
||||
return that.ldapClient.searchAsync(that.options.groups_dn, query);
|
||||
})
|
||||
.then(function (docs: { cn: string }[]) {
|
||||
const groups = docs.map((doc: any) => { return doc.cn; });
|
||||
that.logger.debug("LDAP: groups of user %s are %s", username, groups);
|
||||
that.logger.debug("LDAP: groups of user %s are [%s]", username, groups.join(","));
|
||||
return BluebirdPromise.resolve(groups);
|
||||
});
|
||||
}
|
||||
|
@ -66,6 +82,7 @@ export class Client implements IClient {
|
|||
searchUserDn(username: string): BluebirdPromise<string> {
|
||||
const that = this;
|
||||
const filter = this.options.users_filter.replace("{0}", username);
|
||||
this.logger.debug("Computed users filter is %s", filter);
|
||||
const query = {
|
||||
scope: "sub",
|
||||
sizeLimit: 1,
|
||||
|
|
|
@ -45,7 +45,7 @@ function verify_filter(req: express.Request, res: express.Response): BluebirdPro
|
|||
|
||||
const isAllowed = accessController.isAccessAllowed(domain, path, username, groups);
|
||||
if (!isAllowed) return BluebirdPromise.reject(
|
||||
new exceptions.DomainAccessDenied(Util.format("User '%s' does not have access to '%'",
|
||||
new exceptions.DomainAccessDenied(Util.format("User '%s' does not have access to '%s'",
|
||||
username, domain)));
|
||||
|
||||
if (authenticationMethod == "two_factor" && !authSession.second_factor)
|
||||
|
|
|
@ -56,7 +56,7 @@ describe("test ldap configuration adaptation", function () {
|
|||
users_dn: "dc=example,dc=com",
|
||||
users_filter: "cn={0}",
|
||||
groups_dn: "dc=example,dc=com",
|
||||
groups_filter: "member=cn={0},dc=example,dc=com",
|
||||
groups_filter: "member={dn}",
|
||||
group_name_attribute: "cn",
|
||||
mail_attribute: "mail",
|
||||
user: "admin",
|
||||
|
|
|
@ -31,9 +31,9 @@ describe("test authelia ldap client", function () {
|
|||
const ldapClient = new LdapClientStub();
|
||||
|
||||
factory.createStub.returns(ldapClient);
|
||||
ldapClient.searchAsyncStub.returns(BluebirdPromise.resolve([
|
||||
"group1"
|
||||
]));
|
||||
ldapClient.searchAsyncStub.returns(BluebirdPromise.resolve([{
|
||||
cn: "group1"
|
||||
}]));
|
||||
const client = new Client(ADMIN_USER_DN, ADMIN_PASSWORD, options, factory, Dovehash, Winston);
|
||||
|
||||
return client.searchGroups("user1")
|
||||
|
@ -42,4 +42,49 @@ describe("test authelia ldap client", function () {
|
|||
"member=cn=user1,ou=users,dc=example,dc=com");
|
||||
});
|
||||
});
|
||||
|
||||
it("should replace {dn} by user DN when searching for groups in LDAP", function () {
|
||||
const USER_DN = "cn=user1,ou=users,dc=example,dc=com";
|
||||
const options: LdapConfiguration = {
|
||||
url: "ldap://ldap",
|
||||
users_dn: "ou=users,dc=example,dc=com",
|
||||
users_filter: "cn={0}",
|
||||
groups_dn: "ou=groups,dc=example,dc=com",
|
||||
groups_filter: "member={dn}",
|
||||
group_name_attribute: "cn",
|
||||
mail_attribute: "mail",
|
||||
user: "cn=admin,dc=example,dc=com",
|
||||
password: "password"
|
||||
};
|
||||
const factory = new LdapClientFactoryStub();
|
||||
const ldapClient = new LdapClientStub();
|
||||
|
||||
factory.createStub.returns(ldapClient);
|
||||
|
||||
// Retrieve user DN
|
||||
ldapClient.searchAsyncStub.withArgs("ou=users,dc=example,dc=com", {
|
||||
scope: "sub",
|
||||
sizeLimit: 1,
|
||||
attributes: ["dn"],
|
||||
filter: "cn=user1"
|
||||
}).returns(BluebirdPromise.resolve([{
|
||||
dn: USER_DN
|
||||
}]));
|
||||
|
||||
// Retrieve groups
|
||||
ldapClient.searchAsyncStub.withArgs("ou=groups,dc=example,dc=com", {
|
||||
scope: "sub",
|
||||
attributes: ["cn"],
|
||||
filter: "member=" + USER_DN
|
||||
}).returns(BluebirdPromise.resolve([{
|
||||
cn: "group1"
|
||||
}]));
|
||||
|
||||
const client = new Client(ADMIN_USER_DN, ADMIN_PASSWORD, options, factory, Dovehash, Winston);
|
||||
|
||||
return client.searchGroups("user1")
|
||||
.then(function (groups: string[]) {
|
||||
Assert.deepEqual(groups, ["group1"]);
|
||||
});
|
||||
});
|
||||
});
|
Loading…
Reference in New Issue