one
one copied to clipboard
Add option for group based authorization with AD schema
Description
In AD schema all groups are listed as memberOf attribute under the user record. In this case there is no need for ldap search to check group membership since it's already available.
Branches to which this PR applies
- [x] master
- [ ] Check this if this PR should not be squashed
I don't think this is correct, user_group_name
does not contain user groups but rather this is a field in which (in non-AD LDAP) the user is referenced from a group entry. So, usually dn
. Thus, this line
if !user_group_name.member?(server_conf[:group])
seems wrong to me.
I agree that in AD setup where groups are listed directly in the user entry we don't need 2 queries to check user presence in group, however we would need to address that first in find_user
method etc.
Is LDAP auth plugin performance the primary issue you are facing? We could alternatively improve this by either adding a cache or maintaining a connection pool.
Note: AD could be detected from configuration also by :rfc2307bis == true
This wasn't performance issue, but the fact we were unable to configure login based on group membership, with the patch we've set something like:
:ldap_schema: AD
:group: 'CN=...,OU=...,OU=....,DC=...,DC=com'
:user_group_field: 'memberOf'
You may be right that it's better to make that happen in find_user method, before the call. If you have any hints I can try to work on that (I'm not a rubby developer, but I'd like to have something running and stable in the mean of upgrade in our setup).
For AD I think following should be sufficient
:rfc2307bis: true
:user_field: 'sAMAccountName'
but we want to limit access to nebula to only certain group, do you mean that :group:
should work with just :rfc2307bis: true
?
Yes, rest of the options like :group
and others should work the same, the 2 I mentioned are specific for AD.
So from the tests we did it doesn't work. Looking at the code handling it:
[...]
user_dn, user_uid, user_group_name = ldap.find_user(user)
[...]
if server_conf[:group]
if !ldap.is_in_group?(user_group_name, server_conf[:group])
STDERR.puts "User #{user} is not in group #{server_conf[:group]}"
break
end
end
The functions used are defined as:
def find_user(name)
filter = Net::LDAP::Filter.equals(@options[:user_field], name)
result = @ldap.search(
:base => @options[:base],
:attributes => @options[:attributes],
:filter => filter
)
if result && result.first
@user = result.first
[@user.dn,
@user[@options[:user_field]].first,
@user[@options[:user_group_field]]]
[...]
def is_in_group?(user, group)
username = Net::LDAP::Filter.escape(
user.first.force_encoding(Encoding::UTF_8))
[email protected](
:base => group,
:attributes => [@options[:group_field]],
:filter => "(#{@options[:group_field]}:=#{username})")
if result && result.first
true
else
false
end
end
We call ldap.is_in_group
with values from find_user, which are: first memberOf ffield from user and :group:
configured in ldap_auth.conf
. And finally what happens is that is_in_group
executes a query for a field from a group entry where member field (in unix schema memberUid) matches the user uid. In AD case under a group (the one configured in auth_ldap.conf ) subtree there is no information about users in the group and one needs to rely on the info that was already available in the user entry (as memberOf).
This is indeed a bug, I have overlooked it, sorry. We will fix it in next release.
I opened an issue https://github.com/OpenNebula/one/issues/6528
Could you verify that https://github.com/OpenNebula/one/commit/bcb3e7df0ed05612946c68d448cfc7e9dd50bc9e fixes the issue please?
it works fine
Thanks, I will close the PR then.