-
Notifications
You must be signed in to change notification settings - Fork 178
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add slightly better Active Directory support #94
Conversation
bump Is this something you're interested in (in which case I'll work on rebasing against master) or is there a better way to handle binding to AD? |
Unfortunately I've got zero bandwidth to look at this just at the moment. As I'm using Active Directory I do plan on looking at this when time allows but for me at least that's measured in weeks rather than days... |
@@ -62,6 +63,9 @@ def _server_port_default(self): | |||
uid={username},ou=people,dc=wikimedia,dc=org, | |||
uid={username},ou=Developers,dc=wikimedia,dc=org | |||
] | |||
|
|||
Active Directory Example: | |||
DOMAIN\{login} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm curious why this is needed? I'm on AD and I login with my samid (DOMAIN\samid
) which is used to look up my CN which is then substituted into my DN template.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For people with weird and wonderful OU configurations setting templates in bind_dn
is either very complex or potentially impossible (especially if you don't directly control Active Directory and the admin team keep making changes!). Being able to use standard AD syntax of DOMAIN\username
to bind with makes life much easier and means the JH admin doesn't have to care about the backend AD structure.
""" | ||
) | ||
|
||
activedirectory = Bool( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems a bit of a code-smell to have both get_groups_from_user
and activedirectory
. I have a niggling feeling that there must be a better way to do this... but I'm not an expert so, maybe there isn't?
Having more configuration knobs to turn adds complexity and this is especially true if they're only valid in some situations and not others. Given that I'd want to make sure they were really necessary and the benefit outweighed the added complexity (and hence maintenance burden)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The reason for the different configuration setting is to ensure we can use the AD specific search functionality to look up users in nested groups. AD user objects only have groups the user is a direct member of as a memberOf
attribute on their object.
For example, if we have group 'JH Users' which contains 'Lab APAC' and 'Lab EMEA' groups, a user in 'Lab EMEA' won't also show up as being in 'JH Users' when you query the memberOf
attribute on the user object, so you need to use the AD specific search syntax.
There is not, as far as I know, an easy way to tell if you're talking to 'Active Directory' LDAP or another implementation hence the configuration option. An alternative might be to test the AD specific search and if it fails, fall back to the "standard" behaviour but to me this seems to smell even more than the 'duplicate' code.
You know you can authenicate against groups with memberOf by just adding it to the
and also using |
we really need this. Group membership would be much better |
Seems like there's at least one other person who would find this useful so I'll have a go at rebasing the changes to master. |
Does the |
I don't see how that actually fixes the underlying issue - it would only work for a single group, and still relies on the |
f17c03e
to
dfe1788
Compare
I've reworked the logic here a bit, and twiddled some config options which hopefully make it a bit less finicky to configure, and simplify both AD and non-AD configurations and make it clear which is which. |
I'm pretty swamped (and don't really consider myself a proper maintainer) but I'll try to set aside some time to take a look... |
Just a gentle reminder here - it would be nice to get this merged (or rejected so I can work on an alternative if this PR isn't suitable). Active Directory (for better or worse...) is very popular in enterprise environments and this PR provides better integration with the Microsoft-way of managing LDAP. If you don't want the code-smell of |
ef6c7e0
to
b90fab3
Compare
Also add Microsoft Active directory specific lookup logic to resolve nested groups.
See jupyterhub#171 for further information
The port was changed at rroemhild/docker-test-openldap@adb4650
Co-authored-by: Simon Li <[email protected]>
if self.activedirectory: | ||
self.log.debug('Active Directory enabled') | ||
user_dn = self.resolve_username(username) | ||
search_filter='(member:1.2.840.113556.1.4.1941:={dn})'.format(dn=escape_filter_chars(user_dn)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
1.2.840.113556.1.4.1941
feels like a magic string, would extracting it as a well known constant be acceptable to you? https://ldapwiki.com/wiki/1.2.840.113556.1.4.1941
Despite "slightly better" in the title, this looks like a lot of great work! Thank you @jfautley for the effort into this and everyone involved in review efforts! I've recently onboarded myself as a maintainer to this project, and I think the right call for this PR is to close it at this point. I note that:
|
This change does the following:
memberOf
attribute attached to the user's LDAP objectallowed_groups
#177)bind_dn_template
to be provided with the user's provided login name rather than just the resolved version (EDIT: Relates to Active Directory requires "optional" bind_dn_template #146 perhaps?)It is anticipated this makes using JupyterHub when authenticating against Microsoft AD somewhat easier.