Description of problem: Our base issue is an inability to log in with LDAP users, provided by a Microsoft AD. When they attempt to log in, they are greeted with "Invalid username/password", however the logs show we hit this condition with an empty matching_groups set: module Authenticator class Base - - - - - 8< - - - - - def authorize(taskid, username, *args) audit = {:event => "authorize", :userid => username} decrypt_ldap_password(config) if MiqLdap.using_ldap? run_task(taskid, "Authorizing") do |task| begin identity = find_external_identity(username, *args) unless identity msg = "Authentication failed for userid #{username}, unable to find user object in #{self.class.proper_name}" _log.warn(msg) AuditEvent.failure(audit.merge(:message => msg)) task.error(msg) task.state_finished return nil end matching_groups = match_groups(groups_for(identity)) userid, user = find_or_initialize_user(identity, username) update_user_attributes(user, userid, identity) user.miq_groups = matching_groups if matching_groups.empty? msg = "Authentication failed for userid #{user.userid}, unable to match user's group membership to an EVM role" - - - - - 8< - - - - - Reviewing the logs and the appliance, and adding our own debugging, we found that our matching_groups set from match_groups() was due to an empty set being returned by groups_for for the identity provided. In match_groups, since we are supplied an empty set, we bail early in the method: def match_groups(external_group_names) return [] if external_group_names.empty? - - - - - 8< - - - - - However, in the groups_for method, we return an empty set every time, which causes us to fall through to matching_groups.empty? in the base authorize method, causing the error/exception. module Authenticator class Ldap < Base - - - - - 8< - - - - - def groups_for(obj) authentication = config.dup authentication[:group_memberships_max_depth] ||= DEFAULT_GROUP_MEMBERSHIPS_MAX_DEPTH if authentication.key?(:user_proxies) && !authentication[:user_proxies].blank? && authentication.key?(:get_direct_groups) && authentication[:get_direct_groups] == false _log.info("Skipping getting group memberships directly assigned to user bacause it has been disabled in the configuration") groups = [] else groups = ldap.get_memberships(obj, authentication[:group_memberships_max_depth]) end if authentication.key?(:user_proxies) if (sid = MiqLdap.get_attr(obj, :objectsid)) authentication[:user_proxies].each do |auth| begin groups += user_proxy_membership(auth, MiqLdap.sid_to_s(sid)) rescue Exception => err _log.warn("#{err.message} (from Authenticator#user_proxy_membership)") end end else _log.warn("User Object has no objectSID") end end groups.uniq end In the above, we have no user_proxies and by default get_direct_groups is false, so we start by assigning groups as an empty set. Since we have no user_proxies, we skip user_proxy_membership and the group set remains blank. Unless we set get_direct_groups to true under the authentication section of the advanced settings, which causes get_memberships on the ldap object to run, we will always return an empty set unless user_proxies are also in place. With the end goal of having as fast and efficient, as well as working, LDAP logins being possible, a few questions: - What is the purpose of get_direct_groups in this context? - In order for authorization to function when doing group lookups, when get_direct_groups is set to false, do we always expect there to be a user_proxies setting? - Is the solution to this to ensure get_direct_groups is set to true so appropriate LDAP lookups can be performed for each login? - Is there some other thing I am missing concerning how we validate groups so that we do not get an empty set when validating a user's authorization? Version-Release number of selected component (if applicable): 5.9.2.4 How reproducible: Every time, while get_direct_groups is false. Works when get_direct_groups is true. Steps to Reproduce: 1. In their environment, connect AD to CFME environment. 2. Accept defaults and map groups to EVM roles appropriately 3. Be unable to log in Actual results: Users are unable to log in unless get_direct_groups is set. Expected results: Logins should match users to groups as expected under the correct default conditions, if what we are utilizing is correct and nothing special. Additional info: We have validated the groups returned by the AD by basic tests such as ldapsearch from the appliance.
So, it appears I was very wrong, the default for get_direct_groups is true: config/settings.yml: :get_direct_groups: true An explanation of this setting would be helpful, although we can see what it does here; it appears maybe this is a check box when setting up LDAPS and this is possibly just misconfiguration.
This bug can probably be closed; it turns out we have unchecked "Get Roles from Home Forest" from the UI, defined here: = hidden_div_if(!@edit[:new][:authentication][:ldap_role], :id => "ldap_role_details_div") do .form-horizontal .form-group#get_roles_now{:style => @edit[:new][:authentication][:user_proxies].blank? ? "display: none" : ""} %label.col-md-2.control-label = _("Get Roles from Home Forest") .col-md-8 = check_box_tag("get_direct_groups", "1", @edit[:new][:authentication][:get_direct_groups], "data-miq_observe_checkbox" => {:url => url}.to_json) The confusion was concerning the wording of the button, as they (and I) thought it had more to do with roles than groups. We'd still like a definition as to what the usage of get_direct_groups is intended to be and an explanation of how it matches the description of the button, since that was the point of confusion, but all seems well now. Thanks!
Closing based on phone discussion with Robb. Thanks for the great analysis Robb! Bottom line is if "Get User Groups from LDAP" is checked then "Get Roles from Home Forest" needs to be checked.
Regarding comment #6, I'm changing this to a doc bug. Looking at the current documentation in https://access.redhat.com/documentation/en-us/red_hat_cloudforms/4.6/html/managing_authentication_for_cloudforms/ldap_settings#ldap_config section 2.1.7 talks about "roles" when it should be "groups" because group assignment is the important thing here. I think that is partly responsible for the confusion causing this BZ to be opened. The words role and group are being conflated and causing the misunderstanding.
This should no longer be a blocker. The customer is up and running and is willing to close this BZ. Before we resolved the customer issue this was correctly marked a blocker. Then we closed this bug as not a bug. GreggT decided to reopen as a documentation issue so we can get the documentation clearer to help avoid the same confusion in the future. Unfortunately the blocker flag was still set when the bug was reopened. I discussed with GreggT and we both feel this should not be a blocker. I will meet with Dayle to resolve her questions. JoeV
Updates for this BZ are now in the CloudForms 4.6 Managing Authentication guide published on the Customer Portal (in chapters 2 and 4): https://access.redhat.com/documentation/en-us/red_hat_cloudforms/4.6/html-single/managing_authentication_for_cloudforms/