Skip to content

Commit 1d2ea8b

Browse files
committed
Allow users to configure group search filter and attributes
1 parent 2151b13 commit 1d2ea8b

File tree

4 files changed

+71
-10
lines changed

4 files changed

+71
-10
lines changed

README.md

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,35 @@ c.LDAPAuthenticator.allowed_groups = [
127127
]
128128
```
129129

130+
#### `LDAPAuthenticator.group_search_filter`
131+
132+
The LDAP group search filter.
133+
134+
The default value is an LDAP OR search that looks like the following:
135+
136+
```
137+
(|(member={userdn})(uniqueMember={userdn})(memberUid={uid}))
138+
```
139+
140+
So it basically compares the `userdn` attribute against the `member` attribute,
141+
then against the `uniqueMember`, and finally checks the `memberUid` against
142+
the `uid`.
143+
144+
If you modify this value, you probably want to change `group_attributes` too.
145+
Here is an example that should work with OpenLDAP servers.
146+
147+
```
148+
(member={userdn})
149+
```
150+
151+
#### `LDAPAuthenticator.group_attributes`
152+
153+
A list of attributes used when searching for LDAP groups.
154+
155+
By default, it uses `member`, `uniqueMember`, and `memberUid`. Certain
156+
servers may reject invalid values causing exceptions during
157+
authentication.
158+
130159
#### `LDAPAuthenticator.valid_username_regex`
131160

132161
All usernames will be checked against this before being sent

ldapauthenticator/ldapauthenticator.py

Lines changed: 26 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,23 @@ def _validate_bind_dn_template(self, proposal):
9494
""",
9595
)
9696

97+
group_search_filter = Unicode(
98+
config=True,
99+
default_value="(|(member={userdn})(uniqueMember={userdn})(memberUid={uid}))",
100+
help="""
101+
The search filter used to locate groups.
102+
103+
Certain server types may use different values, and may also
104+
reject invalid values by raising exceptions.
105+
""",
106+
)
107+
108+
group_attributes = List(
109+
config=True,
110+
default_value=["member", "uniqueMember", "memberUid"],
111+
help="List of attributes to be searched",
112+
)
113+
97114
# FIXME: Use something other than this? THIS IS LAME, akin to websites restricting things you
98115
# can use in usernames / passwords to protect from SQL injection!
99116
valid_username_regex = Unicode(
@@ -412,25 +429,24 @@ async def authenticate(self, handler, data):
412429
return None
413430

414431
if self.allowed_groups:
432+
if not self.group_search_filter or not self.group_attributes:
433+
self.log.warning(
434+
"Missing group_search_filter or group_attributes. Both are required."
435+
)
436+
return None
415437
self.log.debug("username:%s Using dn %s", username, userdn)
416438
found = False
417439
for group in self.allowed_groups:
418-
group_filter = (
419-
"(|"
420-
"(member={userdn})"
421-
"(uniqueMember={userdn})"
422-
"(memberUid={uid})"
423-
")"
424-
)
425-
group_filter = group_filter.format(
440+
group_search_filter = self.group_search_filter
441+
group_filter = group_search_filter.format(
426442
userdn=escape_filter_chars(userdn),
427443
uid=escape_filter_chars(username),
428444
)
429-
group_attributes = ["member", "uniqueMember", "memberUid"]
445+
group_attributes = self.group_attributes
430446
found = conn.search(
431447
group,
432448
search_scope=ldap3.BASE,
433-
search_filter=group_filter,
449+
search_filter=group_search_filter,
434450
attributes=group_attributes,
435451
)
436452
if found:

ldapauthenticator/tests/conftest.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,10 @@ def authenticator():
1717
authenticator.escape_userdn = True
1818
authenticator.attributes = ["uid", "cn", "mail", "ou"]
1919
authenticator.use_lookup_dn_username = False
20+
authenticator.group_filter = (
21+
"(|(member={userdn})(uniqueMember={userdn})(memberUid={uid}))"
22+
)
23+
authenticator.group_attributes = ["member", "uniqueMember", "memberUid"]
2024

2125
authenticator.allowed_groups = [
2226
"cn=admin_staff,ou=people,dc=planetexpress,dc=com",

ldapauthenticator/tests/test_ldapauthenticator.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,3 +104,15 @@ async def test_ldap_auth_state_attributes(authenticator):
104104
)
105105
assert authorized["name"] == "fry"
106106
assert authorized["auth_state"] == {"employeeType": ["Delivery boy"]}
107+
108+
109+
async def test_ldap_auth_state_attributes2(authenticator):
110+
authenticator.group_search_filter = "(cn=ship_crew)"
111+
authenticator.group_attributes = ["cn"]
112+
authenticator.auth_state_attributes = ["description"]
113+
# proper username and password in allowed group
114+
authorized = await authenticator.get_authenticated_user(
115+
None, {"username": "leela", "password": "leela"}
116+
)
117+
assert authorized["name"] == "leela"
118+
assert authorized["auth_state"] == {"description": ["Mutant"]}

0 commit comments

Comments
 (0)