-
Notifications
You must be signed in to change notification settings - Fork 35
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
Fixes #36306 - Fixing the UserGroup issue when working with RHDS/POSIX #72
base: master
Are you sure you want to change the base?
Conversation
:base => @group_base, :attributes => ["cn"] | ||
).each do |entry| | ||
groups << entry[:cn][0] | ||
entry[:memberof].each do |grp| | ||
groups << grp.sub(/.*?cn=(.*?),.*/, '\1') |
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 don't have a RHDS at hand so I can't really test this and I'm not sure how exactly those strings look so maybe the things I'm about to describe cannot happen at all, but still.
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 regexp you used here assumes there is more than one key=value
element and I'm not sure if that's always there. Using something like /.*cn=([^,]+).*/
feels like a safer bet.
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.
#sed
returns the string as-is if it does not match. I'm not sure if it can happen, but again, something like this would probably be safer
groups << grp.sub(/.*?cn=(.*?),.*/, '\1') | |
group = grp.match(/cn=([^,]+)/)&.captures&.first | |
groups << group if group |
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.
Isn't something like https://stackoverflow.com/questions/50285542/parse-ldap-dn-string-into-key-value-pairs-in-ruby/57413350#57413350 better?
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.
That would indeed be better
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.
So add require 'net/ldap/dn'
(after net/ldap
, before it somehow fails for me) and then
groups << grp.sub(/.*?cn=(.*?),.*/, '\1') | |
dn = Net::LDAP::DN.new(grp) | |
groups << dn.enum_for(:each_pair).find { |key, _value| key == 'cn' }[1] |
Now I do wonder if this works though. In the filter you say you only want the cn
attribute, not memberof
so I think it won't retrieve the property and entry[:memberof]
will be nil
. And even if you retrieve it, it may be nil
as well for users without memberof
set.
So you do need to make it a safe navigator iteration: entry[:memberof]&.each
Hello @adamruzicka and @ekohl Please, let me know what you think. |
I don't think this refactor is really correct because you will break other use cases. AFAIK (and it's been a long time since I was an admin for an LDAP server) there are 2 ways to manage groups:
The current method implements the posixGroup approach, which is (as the name implies) similar to POSIX groups: they're a list of usernames stored in the Then there is the OpenLDAP needs an extension (https://linux.die.net/man/5/slapo-memberof) to support this. Now looking in the codebase, we already have an implementation for FreeIPA (https://github.com/theforeman/ldap_fluff/blob/master/lib/ldap_fluff/freeipa_member_service.rb) which is really unchanged since 2017. RHDS is the branded version of FreeIPA so I'm guessing it may be something of detecting the flavor. Edit: Of course I now read through the BZ where you say you selected the POSIX type, but I think you should select the FreeIPA type. |
Hello @ekohl Indeed, I agree. After installing a fresh RHDS, I saw this behavior and didn't see the Please, allow me some time to review and work with the group information that we have already by default.
I'll do some additional tests creating I'll keep you posted. |
Hello @adamruzicka and @ekohl Please, let me share the whole def here, once I'm testing it on Satellite and I did a complete change to filter passing by all the groups, I'll not change it yet on the upstream code.
and below, you can see how the group information is on a fresh vanilla RHDS
Above, the first group it's a I did all the tests locally and with or without group, the user is able to login and the I also would like to ask you both to suggest the best code implementation, once I'm improving my knowledge of ruby, I can feel that this code it's more like python than anything else ... I'm trying! :-) Ps.: I'm using all the split parse because the customer can create the user object using
Thank you again! |
Hello all, The code was updated. Please, let me know what you think. Thank you! |
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 still think this breaks plain RFC2307 support. The current LdapFluff::Posix::MemberService
class does exactly what it needs to. Technically speaking it should filter on objectClass
equals posixGroup
AND memberuid
equals $uid
, but that's redundant.
Reading https://access.redhat.com/documentation/en-us/red_hat_directory_server/11/html/administration_guide/advanced_entry_management they use the objectClass groupOfNames
which is completely different. We don't have such support today, so it deserves its own flavor. RHDS is the downstream of 389-ds though purely numeric class names probably don't work in Ruby. Not sure what the best name would be then.
@adamruzicka do you agree it should be its own flavor?
Hello @ekohl and @adamruzicka Just some news here, when doing the rhds implementation, we can see that the standard objectclass used when creating a group is
And I can see the complete description on rfc4519. That said, for the customer, looking for
and here we can see one example from the cu env (names removed)
I'll wait for your point of view. I believe covering both, we will catch 2 birds with a single stone. If you all agree with that, I'll work on the code to reach this goal. Thank you! |
Hello, Just FYI, the code that worked
|
@ekohl and @adamruzicka any thoughts on the proposal? |
I still think it should be its own flavor and not modify the existing flavors. As for the specific implementation I think it's inefficient because it does client side filtering. For large LDAP instances it will retrieve all groups every single time and then iterate over it which can consume a lot of memory on both the LDAP server and client side. I'd suggest is to offload it to the server, which usually has indexes allowing it to quickly find what you're looking for. This is untested, but it composes a more complex query that should achieve it. def find_user_groups(uid)
group_unique_filter = Net::LDAP::Filter.eq('objectClass', 'groupOfUniqueNames') & Net::LDAP::Filter.eq('uniqueMember', uid)
group_filter = Net::LDAP::Filter.eq('objectClass', 'groupOfNames') & Net::LDAP::Filter.eq('member', uid)
filter = group_unique_filter | group_filter
groups = ldap.search(filter: filter, attributes: ['cn']).map { |group| group[:cn] }
groups.flatten!
groups
end I'm not 100% sure on the flatten bit. Perhaps def find_user_groups(uid)
group_unique_filter = Net::LDAP::Filter.eq('objectClass', 'groupOfUniqueNames') & Net::LDAP::Filter.eq('uniqueMember', uid)
group_filter = Net::LDAP::Filter.eq('objectClass', 'groupOfNames') & Net::LDAP::Filter.eq('member', uid)
filter = group_unique_filter | group_filter
ldap.search(filter: filter, attributes: ['cn']).map { |group| group[:cn][0] }
end |
Hello @adamruzicka good morning This whole environment was implemented long ago, I'm pretty sure that the implemented code worked, but I'm not sure about the suggested one. I would recommend setting up an environment if possible and proceeding with the tests. At this moment, I can't do it. Maybe in the future, but if someone else has already the env and/or the ability to try it out quickly, I believe this would be the must. Thank you! |
When working with RHDS (RH Directory Server), the UserGroup feature it's not working properly, the
group_list
method doesn't return the correct group information, even when the pluginmemberof
it's already available.With this change, it will check the also the
@attr_login
attribute and will use it, once there is no value, then we will assumememberuid
. Before it was hardcoded tomemberuid
.Thank you!
Waldirio