Chapter 24. LDAP authentication Administrators use the Lightweight Directory Access Protocol (LDAP) as a source for account authentication information for automation controller users. User authentication is provided, but not the synchronization of user permissions and credentials. Organization membership and team membership can be synchronized by the organization administrator. 24.1. Setting up LDAP authentication When configured, a user who logs in with an LDAP username and password automatically has an automation controller account created for them. They can be automatically placed into organizations as either regular users or organization administrators. Users created in the user interface (Local) take precedence over those logging into automation controller for their first time with an alternative authentication solution. You must delete the local user if you want to re-use with another authentication method, such as LDAP. Users created through an LDAP login cannot change their username, given name, surname, or set a local password for themselves. You can also configure this to restrict editing of other field names. Note If the LDAP server you want to connect to has a certificate that is self-signed or signed by a corporate internal certificate authority (CA), you must add the CA certificate to the system's trusted CAs. Otherwise, connection to the LDAP server results in an error that the certificate issuer is not recognized. For more information, see Importing a certificate authority in automation controller for LDAPS integration . If prompted, use your Red Hat customer credentials to login. Procedure Create a user in LDAP that has access to read the entire LDAP structure. Use the ldapsearch command to test if you can make successful queries to the LDAP server. You can install this tool from automation controller's system command line, and by using other Linux and OSX systems. Example In this example, CN=josie,CN=users,DC=website,DC=com is the distinguished name of the connecting user. Note The ldapsearch utility is not automatically pre-installed with automation controller. However, you can install it from the openldap-clients package. From the navigation panel, select Settings in the automation controller UI. Select LDAP settings in the list of Authentication options. You do not need multiple LDAP configurations per LDAP server, but you can configure many LDAP servers from this page, otherwise, leave the server at Default . The equivalent API endpoints show AUTH_LDAP_* repeated: AUTH_LDAP_1_* , AUTH_LDAP_2_* , AUTH_LDAP_5_* to denote server designations. To enter or change the LDAP server address, click Edit and enter in the LDAP Server URI field by using the same format as the one pre-populated in the text field. Note You can specify multiple LDAP servers by separating each with spaces or commas. Click the icon to comply with the correct syntax and rules. Enter the password to use for the binding user in the LDAP Bind Password text field. For more information about LDAP variables, see Ansible automation hub variables . Click to select a group type from the LDAP Group Type list. The LDAP group types that are supported by automation controller use the underlying django-auth-ldap library . To specify the parameters for the selected group type, see Step 15. The LDAP Start TLS is disabled by default. To enable TLS when the LDAP connection is not using SSL/TLS, set the toggle to On . Enter the distinguished name in the LDAP Bind DN text field to specify the user that automation controller uses to connect (Bind) to the LDAP server. If that name is stored in key sAMAccountName , the LDAP User DN Template is populated from (sAMAccountName=%(user)s) . Active Directory stores the username to sAMAccountName . For OpenLDAP, the key is uid and the line becomes (uid=%(user)s) . Enter the distinguished group name to enable users within that group to access automation controller in the LDAP Require Group field, using the same format as the one shown in the text field, CN=controller Users,OU=Users,DC=website,DC=com . Enter the distinguished group name to prevent users within that group from accessing automation controller in the LDAP Deny Group field, using the same format as the one shown in the text field. Enter where to search for users while authenticating in the LDAP User Search field by using the same format as the one shown in the text field. In this example, use: [ "OU=Users,DC=website,DC=com", "SCOPE_SUBTREE", "(cn=%(user)s)" ] The first line specifies where to search for users in the LDAP tree. In the earlier example, the users are searched recursively starting from DC=website,DC=com . The second line specifies the scope where the users should be searched: SCOPE_BASE : Use this value to indicate searching only the entry at the base DN, resulting in only that entry being returned. SCOPE_ONELEVEL : Use this value to indicate searching all entries one level under the base DN, but not including the base DN and not including any entries under that one level under the base DN. SCOPE_SUBTREE : Use this value to indicate searching of all entries at all levels under and including the specified base DN. The third line specifies the key name where the user name is stored. For many search queries, use the following correct syntax: [ [ "OU=Users,DC=northamerica,DC=acme,DC=com", "SCOPE_SUBTREE", "(sAMAccountName=%(user)s)" ], [ "OU=Users,DC=apac,DC=corp,DC=com", "SCOPE_SUBTREE", "(sAMAccountName=%(user)s)" ], [ "OU=Users,DC=emea,DC=corp,DC=com", "SCOPE_SUBTREE", "(sAMAccountName=%(user)s)" ] ] In the LDAP Group Search text field, specify which groups to search and how to search them. In this example, use: [ "dc=example,dc=com", "SCOPE_SUBTREE", "(objectClass=group)" ] The first line specifies the BASE DN where the groups should be searched. The second line specifies the scope and is the same as that for the user directive. The third line specifies what the objectClass of a group object is in the LDAP that you are using. Enter the user attributes in the LDAP User Attribute Map the text field. In this example, use: { "first_name": "givenName", "last_name": "sn", "email": "mail" } The earlier example retrieves users by surname from the key sn . You can use the same LDAP query for the user to decide what keys they are stored under. Depending on the selected LDAP Group Type , different parameters are available in the LDAP Group Type Parameters field to account for this. LDAP_GROUP_TYPE_PARAMS is a dictionary that is converted by automation controller to kwargs and passed to the LDAP Group Type class selected. There are two common parameters used by any of the LDAP Group Type ; name_attr and member_attr . Where name_attr defaults to cn and member_attr defaults to member: {"name_attr": "cn", "member_attr": "member"} To find what parameters a specific LDAP Group Type expects, see the django_auth_ldap documentation around the classes init parameters. Enter the user profile flags in the LDAP User Flags by Group text field. The following example uses the syntax to set LDAP users as "Superusers" and "Auditors": { "is_superuser": "cn=superusers,ou=groups,dc=website,dc=com", "is_system_auditor": "cn=auditors,ou=groups,dc=website,dc=com" } For more information about completing the mapping fields, LDAP Organization Map and LDAP Team Map , see the LDAP Organization and team mapping section. Click Save . Note Automation controller does not actively synchronize users, but they are created during their initial login. To improve performance associated with LDAP authentication, see Preventing LDAP attributes from updating on each login . 24.1.1. LDAP organization and team mapping You can control which users are placed into which automation controller organizations based on LDAP attributes (mapping out between your organization administrators, users and LDAP groups). Keys are organization names. Organizations are created if not present. Values are dictionaries defining the options for each organization's membership. For each organization, you can specify what groups are automatically users of the organization and also what groups can administer the organization. admins : none , true , false , string or list/tuple of strings: If none , organization administrators are not updated based on LDAP values. If true , all users in LDAP are automatically added as administrators of the organization. If false , no LDAP users are automatically added as administrators of the organization. If a string or list of strings specifies the group DNs that are added to the organization if they match any of the specified groups. remove_admins: True/False. Defaults to False : When true , a user who is not a member of the given group is removed from the organization's administrative list. users : none , true , false , string or list/tuple of strings. The same rules apply as for administrators. remove_users : true or false . Defaults to false . The same rules apply as for administrators. Example When mapping between users and LDAP groups, keys are team names and are created if not present. Values are dictionaries of options for each team's membership, where each can contain the following parameters: organization : string . The name of the organization to which the team belongs. The team is created if the combination of organization and team name does not exist. The organization is first created if it does not exist. users : none , true , false , string , or list/tuple of strings: If none , team members are not updated. If true or false , all LDAP users are added or removed as team members. If a string or list of strings specifies the group DNs, the user is added as a team member if the user is a member of any of these groups. remove : true or false . Defaults to false . When true , a user who is not a member of the given group is removed from the team. Example 24.1.2. Enabling logging for LDAP To enable logging for LDAP, you must set the level to DEBUG in the Settings configuration window: Procedure From the navigation panel, select Settings . Select Logging settings from the list of System options. Click Edit . Set the Logging Aggregator Level Threshold field to DEBUG . Click Save . 24.1.3. Preventing LDAP attributes from updating on each login By default, when an LDAP user authenticates, all user-related attributes are updated in the database on each login. In some environments, you can skip this operation due to performance issues. To avoid it, you can disable the option AUTH_LDAP_ALWAYS_UPDATE_USER . Warning Set this option to false to not update the LDAP user's attributes. Attributes are only updated the first time the user is created. Procedure Create a custom file under /etc/tower/conf.d/custom-ldap.py with the following contents. If you have multiple nodes, execute it on all nodes: AUTH_LDAP_ALWAYS_UPDATE_USER = False Restart automation controller on all nodes: automation-controller-service restart With this option set to False , no changes to LDAP user's attributes are pushed to automation controller. Note that new users are created and their attributes are pushed to the database on their first login. By default, an LDAP user gets their attributes updated in the database upon each login. For a playbook that runs multiple times with an LDAP credential, those queries can be avoided. Verification Check the PostgreSQL for slow queries related to the LDAP authentication. Additional resources For more information, see AUTH_LDAP_ALWAYS_UPDATE_USER of the Django documentation. 24.1.4. Importing a certificate authority in automation controller for LDAPS integration You can authenticate to the automation controller server by using LDAP, but if you change to using LDAPS (LDAP over SSL/TLS) to authenticate, it fails with one of the following errors: 2020-04-28 17:25:36,184 WARNING django_auth_ldap Caught LDAPError while authenticating e079127: SERVER_DOWN({'info': 'error:14090086:SSL routines:ssl3_get_server_certificate:certificate verify failed (unable to get issuer certificate)', 'desc': "Can't contact LDAP server"},) 2020-06-02 11:48:24,840 WARNING django_auth_ldap Caught LDAPError while authenticating reinernippes: SERVER_DOWN({'desc': "Can't contact LDAP server", 'info': 'error:14090086:SSL routines:ssl3_get_server_certificate:certificate verify failed (certificate has expired)'},) Note By default, django_auth_ldap verifies SSL connections before starting an LDAPS transaction. When you receive a certificate verify failed error, this means that the django_auth_ldap could not verify the certificate. When the SSL/TLS connection cannot be verified, the connection attempt is halted. Procedure To import an LDAP CA, run the following commands: cp ldap_server-CA.crt /etc/pki/ca-trust/source/anchors/ update-ca-trust Note Run these two commands on all automation controller nodes in a clustered setup. 24.1.5. Referrals Active Directory uses "referrals" in case the queried object is not available in its database. This does not work correctly with the django LDAP client and it helps to disable referrals. Disable LDAP referrals by adding the following lines to your /etc/tower/conf.d/custom.py file: AUTH_LDAP_GLOBAL_OPTIONS = { ldap.OPT_REFERRALS: False, } 24.1.6. Changing the default timeout for authentication You can change the default length of time, in seconds, that your supplied token is valid in the Settings screen of the automation controller UI. Procedure From the navigation panel, select Settings . Select Miscellaneous Authentication settings from the list of System options. Click Edit . Enter the timeout period in seconds in the Idle Time Force Log Out text field. Click Save . Note If you access automation controller and have trouble logging in, clear your web browser's cache. In situations such as this, it is common for the authentication token to be cached during the browser session. You must clear it to continue.

Commands:
ldapsearch -x -H ldap://win -D "CN=josie,CN=Users,DC=website,DC=com" -b "dc=website,dc=com" -w Josie4Cloud
OU=Users,DC=website,DC=com
SCOPE_SUBTREE
(cn=%(user)s)
[ [ "OU=Users,DC=northamerica,DC=acme,DC=com", "SCOPE_SUBTREE", "(sAMAccountName=%(user)s)" ], [ "OU=Users,DC=apac,DC=corp,DC=com", "SCOPE_SUBTREE", "(sAMAccountName=%(user)s)" ], [ "OU=Users,DC=emea,DC=corp,DC=com", "SCOPE_SUBTREE", "(sAMAccountName=%(user)s)" ] ]
dc=example,dc=com
SCOPE_SUBTREE
(objectClass=group)
first_name: givenName
last_name: sn
email: mail
name_attr: cn
member_attr: member
is_superuser: cn=superusers,ou=groups,dc=website,dc=com
is_system_auditor: cn=auditors,ou=groups,dc=website,dc=com
{ "LDAP Organization": { "admins": "cn=engineering_admins,ou=groups,dc=example,dc=com", "remove_admins": false, "users": [ "cn=engineering,ou=groups,dc=example,dc=com", "cn=sales,ou=groups,dc=example,dc=com", "cn=it,ou=groups,dc=example,dc=com" ], "remove_users": false }, "LDAP Organization 2": { "admins": [ "cn=Administrators,cn=Builtin,dc=example,dc=com" ], "remove_admins": false, "users": true, "remove_users": false } }
{ "LDAP Engineering": { "organization": "LDAP Organization", "users": "cn=engineering,ou=groups,dc=example,dc=com", "remove": true }, "LDAP IT": { "organization": "LDAP Organization", "users": "cn=it,ou=groups,dc=example,dc=com", "remove": true }, "LDAP Sales": { "organization": "LDAP Organization", "users": "cn=sales,ou=groups,dc=example,dc=com", "remove": true } }
AUTH_LDAP_ALWAYS_UPDATE_USER = False
automation-controller-service restart
2020-04-28 17:25:36,184 WARNING django_auth_ldap Caught LDAPError while authenticating e079127: SERVER_DOWN({'info': 'error:14090086:SSL routines:ssl3_get_server_certificate:certificate verify failed (unable to get issuer certificate)', 'desc': "Can't contact LDAP server"},)
2020-06-02 11:48:24,840 WARNING django_auth_ldap Caught LDAPError while authenticating reinernippes: SERVER_DOWN({'desc': "Can't contact LDAP server", 'info': 'error:14090086:SSL routines:ssl3_get_server_certificate:certificate verify failed (certificate has expired)'},)
cp ldap_server-CA.crt /etc/pki/ca-trust/source/anchors/
update-ca-trust
AUTH_LDAP_GLOBAL_OPTIONS = { ldap.OPT_REFERRALS: False, }