Skip to content
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

support active directory #18

Open
wants to merge 7 commits into
base: master
Choose a base branch
from

Conversation

chrisbitmead
Copy link

This is the simplest thing that could work for supporting active directory. Seemingly, the typical ldap setup looks for roles by starting with the group, and then looking up the users via uniqueMember or some such. Typically in Active Directory you start from the member, and use the memberof attribute to find groups they belong to. (This is the approach of ActiveDirectoryRealm for example). Going the other way is problematic because seemingly the 'member' attribute of group gives the user display name, not the username. Because ldap searches are quite flexible we can support this rather different approach with a small upgrade to the code. When we retrieve the groups from memberof, they will typically be in a ldap hierarchy... e.g. test vs prod and so forth. We only want to extract the ones from the place in the hierarchy we are interested in. We can do that by using the groupPattern with a capture group to only grab the groups that we care about.

This code has been tested in its native environment to work with both regular ldap and active directory.

There's probably some more sophisticated way to support the whole ldap / active directory thing, but this is the simplest thing that could work. In particular, the shiro ActiveDirectoryRealm... and the shiro DefaultLdapRealm, and using those rather than this class. But I haven't gone all the way down the rabbit hole of looking into that.

@pmcneil
Copy link
Member

pmcneil commented Jun 15, 2022

Cool, thanks Chris! I hope to get time to review this over the week.

@chrisbitmead
Copy link
Author

Hi, I've updated it again with another commit. We had a requirement to search ldap from multiple parts in the ldap tree. e.g. we have users under /Users but also under /nsl/Users so we want to search from / and not /Users. So I found to do that, I needed two things: Firstly I had to put
env[Context.REFERRAL] = 'follow'
in the getLDAPContext, because if I didn't I would get javax.naming.PartialResultException: Unprocessed Continuation Reference(s)... which apparently is something to do with following referrals in ldap (whatever that is).

The other thing I needed to do is pass
searchCtls.setSearchScope(SearchControls.SUBTREE_SCOPE)
to the context.search() commands for the user. This is the equivilent of passing "-s sub" to the ldapsearch command (which
is actually the default for ldapsearch)
Rather than hard code that in LdapServer, I put a variable searchCtls in the class so that externally you can set parameters onto it.

I also made getLDAPContext a protected method rather than static so that users can potentially override it if they want to inherit it and override it with other parameters.

Now for whatever obscure reason, if you pass a SearchControls class to the search() method, it doesn't support the BasicAttributes or Attributes parameters. So instead you have to construct a filter string of the kind "variableName=value", so that's a slight difference there in the search setup.

@chrisbitmead
Copy link
Author

Made another change to make env a member of the class and make getBaseLDAPEnvironment protected instead of private to give maximum flexibility for users of the class to set parameters and override if necessary.

@chrisbitmead
Copy link
Author

I forgot that I did this pull request before, looks like you never got around to it. Because I've worked off the same repository, looks like my new work is added to the same pull request.... Anyway, if you ever get around to looking at it, these are my comments on the changes as of now:

  • Upgraded grails version to 5
    • Upgraded apache shiro from 1.7.1 to 2.0.1
    • commented out jfrog stuff, I don't know if that has value anymore or not
    • upgraded version of grails-shiro to 4.4
    • Added build rule to install locally if you want to using publishToMavenLocal
    • updated gradle wrapper version
    • LdapServer.groovy: made various things protected instead of private, in case someone needs to override behavior (private things are an abomination). I had to do this inheritance prior to some of the changes below, and not being able to override things made it a mess.
    • doCredentialsMatch ... the new code I put in looks like seemingly it does the same as the old code, however the old code doesn't work, at least not for us.
    • Same thing with roles, new search code doesn't look like it would work differently, but the old code doesn't work for us.
    • The pattern matching in roles is because shiro returns something like CN=treebuilder,OU=apni,OU=test,OU=nsl,DC=cloud,DC=biodiversity,DC=org,DC=au - treebuilder - CN=([^,]*),OU=apni,OU=test,OU=nsl
    and we need to extract "treebuilder" from the string. I don't know how this worked before if different LDAPs return different things or what. I don't know what that code was written to assume, but since LdapRealm.hasRole seems to assume that ldapServer.roles returns a plain set of string role names, it seems the code is going to have to extract it from the above. Not sure how to test the code with whatever you originally wrote it for.
    • getBaseLDAPEnvironment adds the 'follow' tag, because, depending on how your ldap is setup you could be redirected to the final location.

@pmcneil
Copy link
Member

pmcneil commented Nov 11, 2024

Thanks @chrisbitmead we'll have to look at the versioning. should be 5.x for Grails 5 support. I'll look through this now, sorry for letting the last one drop, I got stuck waiting on maven repo stuff IIRC.

@pmcneil
Copy link
Member

pmcneil commented Nov 11, 2024

Looks like I need to do a bit of testing on this Chris and we need to update the Doco too. The major version number should match the Grails version supported. I've cloned your repo to have a good look and make some changes. It'd be good to do these as branches as opposed to main... we have a grails 3 branch , should have a grails 4 branch and then pull in the grails 5 branch... give me a call if you can, cheers, and thanks for your work!

@pmcneil
Copy link
Member

pmcneil commented Nov 12, 2024

OK, because the grails commands and templates have gone, the tests that create test projects don't work, which is a bummer.

@chrisbitmead
Copy link
Author

OK, I'm not that familiar with how people normally do git versions and stuff with grails plugins, it seems like a bit of a can of worms. I'm sure you can import the code into a branch if that works for you. And yeah, sorry I didn't know what the version convention was. It's possible I've broken something in whatever LDAP version you originally used by way of supporting the Active Directory version of LDAP. I used pattern matching to extract the right details, on the theory that the global pattern could probably be changed one way or the other for different LDAPs, but then again I may be missing the real issues. And I don't know, you may have issues getting Active Directory to test with, I don't know. Not to mention time to look into it. What LDAP did you use originally, I don't know if I have time either to set that up. Not sure what you mean by grails commands and templates have gone, what that's about. I did notice there were some templates, but wasn't sure what the overall design was trying to achieve with those.

@pmcneil
Copy link
Member

pmcneil commented Nov 12, 2024

@chrisbitmead it's all good. Some of the underlying changes in Grails mean that some stuff is out of date.

I've fixed a few things and committed fixes up to Shiro 1.13.0 with Grails 4. Shiro 2.01 will require us to move to Grails 5 for the Java 11 requirements.

I'm currently merging in your changes, first to get us up to Shiro 2.0.1 and Grails 5, then I'll merge in changes for Active Directory support (which i may need some more advice on from you). I'll do them as separate things, making sure that we have all the tests working. We'll need to add tests for the AD stuff.

Currently the tests run up apacheds for testing with LDAP.

@pmcneil
Copy link
Member

pmcneil commented Nov 13, 2024

OK upgraded to Grails 5 and Shiro 2.0.1 and tests now working. Updated some doco. Breaking change is that you need to include Shiro in your dependencies now (see doco).

Next I'll apply the AD changes to the LDAP Realm.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants