Chapter 2. Identity Management Integration This chapter describes how to integrate Identity Service (keystone) with Red Hat Identity Management. In this use case, Identity Service authenticates certain Red Hat Identity Management (IdM) users, while retaining authorization settings and critical service accounts in the Identity Service database. As a result, Identity Service has read-only access to IdM for user account authentication, while retaining management over the privileges assigned to authenticated accounts. Note If you are using director, see Chapter 4, Using domain-specific LDAP backends with director . This is because the configuration files referenced below are managed by Puppet. Consequently, any custom configuration you add might be overwritten whenever you run the openstack overcloud deploy process. Note For additional integration options using novajoin , see Chapter 3, Integrate with IdM using novajoin . 2.1. Key terms Authentication - The process of using a password to verify that the user is who they claim to be. Authorization - Validating that authenticated users have proper permissions to the systems they're attempting to access. Domain - Refers to the additional back ends configured in Identity Service. For example, Identity Service can be configured to authenticate users from external IdM environments. The resulting collection of users can be thought of as a domain . 2.2. Assumptions This example deployment makes the following assumptions: Red Hat Identity Management is configured and operational. Red Hat OpenStack Platform is configured and operational. DNS name resolution is fully functional and all hosts are registered appropriately. 2.3. Impact Statement These steps allow IdM users to authenticate to OpenStack and access resources. OpenStack service accounts (such as keystone and glance), and authorization management (permissions and roles) will remain in the Identity Service database. Permissions and roles are assigned to the IdM accounts using Identity Service management tools. 2.3.1. High Availability options This configuration creates a dependency on the availability of a single IdM server: Project users will be affected if Identity Service is unable to authenticate to the IdM Server. There are a number of options available to manage this risk, for example: you might configure keystone to query a DNS alias or a load balancing appliance, rather than an individual IdM server. You can also configure keystone to query a different IdM server, should one become unavailable. See Section 2.11, "Configure for high availability" for more information. 2.4. Outage requirements The Identity Service will need to be restarted in order to add the IdM back end. The Compute services on all nodes will need to be restarted in order to switch over to keystone v3 . Users will be unable to access the dashboard until their accounts have been created in IdM. To reduce downtime, consider pre-staging the IdM accounts well in advance of this change. 2.5. Firewall configuration If firewalls are filtering traffic between IdM and OpenStack, you will need to allow access through the following port: Source Destination Type Port OpenStack Controller Node Red Hat Identity Management LDAPS TCP 636 2.6. Configure the IdM server Run these commands on the IdM server: Create the LDAP lookup account. This account is used by Identity Service to query the IdM LDAP service: Note Review the password expiration settings of this account, once created. Create a group for OpenStack users, called grp-openstack . Only members of this group can have permissions assigned in OpenStack Identity. Set the svc-ldap account password, and add it to the grp-openstack group: Login as svc-ldap user and perform the password change when prompted: 2.7. Configure the LDAPS certificate Note When using multiple domains for LDAP authentication, you might receive various errors, such as Unable to retrieve authorized projects , or Peer's Certificate issuer is not recognized . This can arise if keystone uses the incorrect certificate for a certain domain. As a workaround, merge all of the LDAPS public keys into a single .crt bundle, and configure all of your keystone domains to use this file. In your IdM environment, locate the LDAPS certificate. This file can be located using /etc/openldap/ldap.conf : Copy the file to the OpenStack node that runs the keystone service. For example, this command uses scp to copy ca.crt to the node named node.lab.local : On the OpenStack node, convert the .crt to .pem: Copy the .crt to the certificate directory. This is the location that the keystone service will use to access the certificate: Note Optionally, if you need to run diagnostic commands, such as ldapsearch , you will also need to add the certificate to the RHEL certificate store. For example: 2.8. Configure Identity Service These steps prepare Identity Service for integration with IdM. Note If you are using director, note that the configuration files referenced below are managed by Puppet. Consequently, any custom configuration you add might be overwritten whenever you run the openstack overcloud deploy process. To apply these settings to director-based deployments, see Chapter 4, Using domain-specific LDAP backends with director . 2.8.1. Configure the controller Note If you intend to update any configuration files, you need to be aware that certain OpenStack services now run within containers; this applies to keystone, nova, and cinder, among others. As a result, there are certain administration practices to consider: Do not update any configuration file you might find on the physical node's host operating system, for example, /etc/cinder/cinder.conf . This is because the containerized service does not reference this file. Do not update the configuration file running within the container. This is because any changes are lost once you restart the container. Instead, if you need to add any changes to containerized services, you will need to update the configuration file that is used to generate the container. These are stored within /var/lib/config-data/puppet-generated/ For example: keystone: /var/lib/config-data/puppet-generated/keystone/etc/keystone/keystone.conf cinder: /var/lib/config-data/puppet-generated/cinder/etc/cinder/cinder.conf nova: /var/lib/config-data/puppet-generated/nova/etc/nova/nova.conf Any changes will then be applied once you restart the container. For example: sudo systemctl restart tripleo_keystone Perform this procedure on the controller running the keystone service: Configure SELinux: The output might include messages similar to this. They can be ignored: Create the domains directory: Configure Identity Service to use multiple back ends: Note You might need to install crudini using dnf install crudini . Note If you are using director, note that /var/lib/config-data/puppet-generated/keystone/etc/keystone/keystone.conf is managed by Puppet. Consequently, any custom configuration you add might be overwritten whenever you run the openstack overcloud deploy process. As a result, you might need to re-add this configuration manually each time. For director-based deployments, see Chapter 4, Using domain-specific LDAP backends with director . Enable multiple domains in dashboard. Add these lines to /var/lib/config-data/puppet-generated/horizon/etc/openstack-dashboard/local_settings : Note If you are using director, note that /var/lib/config-data/puppet-generated/horizon/etc/openstack-dashboard/local_settings is managed by Puppet. Consequently, any custom configuration you add might be overwritten whenever you run the openstack overcloud deploy process. As a result, you might need to re-add this configuration manually each time. Restart the horizon container to apply the settings: Configure an additional back end: Create the keystone domain for IdM integration. You will need to decide on a name to use for your new keystone domain, and then create the domain. For example, this command creates a keystone domain named LAB : Note If this command is not available, check that you have enabled keystone v3 for your command line session. Create the configuration file: To add the IdM back end, enter the LDAP settings in a new file called /var/lib/config-data/puppet-generated/keystone/etc/keystone/domains/keystone.LAB.conf (where LAB is the domain name created previously). You will need to edit the sample settings below to suit your IdM deployment: Explanation of each setting: Setting Description url The IdM server to use for authentication. Uses LDAPS port 636 . user The account in IdM to use for LDAP queries. password The plaintext password of the IdM account used above. user_filter Filters the users presented to Identity Service. As a result, only members of the grp-openstack group can have permissions defined in Identity Service. user_tree_dn The path to the OpenStack accounts in IdM. user_objectclass Defines the type of LDAP user. For IdM, use the inetUser type. user_id_attribute Maps the IdM value to use for user IDs. user_name_attribute Maps the IdM value to use for names . user_mail_attribute Maps the IdM value to use for user email addresses. user_pass_attribute Leave this value blank. Note Integration with an IdM group will only return direct members, and not nested groups. As a result, queries that rely on LDAP_MATCHING_RULE_IN_CHAIN or memberof:1.2.840.113556.1.4.1941: will not currently work with IdM. Change ownership of the config file to the keystone user: Grant the admin user access to the domain: Note This does not grant the OpenStack admin account any permissions in IdM. In this case, the term domain refers to OpenStack's usage of the keystone domain. Get the ID of the LAB domain: Get the ID value of the admin user: Get the ID value of the admin role: Use the returned domain and admin IDs to construct the command that adds the admin user to the admin role of the keystone LAB domain: Restart the keystone service to apply the changes: View the list of users in the IdM domain by adding the keystone domain name to the command: View the service accounts in the local keystone database: 2.8.2. Allow IdM group members to access Projects To allow authenticated users access to OpenStack resources, the recommended method is to authorize certain IdM groups to grant access to Projects. This saves the OpenStack administrators from having to allocate each user to a role in a Project. Instead, the IdM groups are granted roles in Projects. As a result, IdM users that are members of these IdM groups will be able to access pre-determined Projects. Note If you would prefer to manually manage the authorization of individual IdM users, see the Section 2.8.3, "Allow IdM users to access Projects" . This section presumes that the IdM administrator has already completed these steps: Create a group named grp-openstack-admin in IdM. Create a group named grp-openstack-demo in IdM. Add your IdM users to one of the above groups, as needed. Add your IdM users to the grp-openstack group. Have a designated project in mind. This example uses a project called demo , created using openstack project create --domain default --description "Demo Project" demo . These steps assign a role to an IdM group. Group members will then have permission to access OpenStack resources. Retrieve a list of IdM groups: Retrieve a list of roles: Grant the IdM groups access to Projects by adding them to one or more of these roles. For example, if you want users in the grp-openstack-demo group to be general users of the demo project, you must add the group to the _member_ role: As a result, members of grp-openstack-demo are able to log in to the dashboard by entering their IdM username and password, when also entering LAB in the Domain field: Note If users receive the error Error: Unable to retrieve container list. , and expect to be able to manage containers, then they must be added to the SwiftOperator role. 2.8.3. Allow IdM users to access Projects IdM users that are members of the grp-openstack IdM group can be granted permission to log in to a Project in the dashboard: Retrieve a list of IdM users: Retrieve a list of roles: Grant users access to Projects by adding them to one or more of these roles. For example, if you want user1 to be a general user of the demo project, you add them to the member role: Or, if you want user1 to be an administrative user of the demo project, you add them to the admin role: As a result, user1 is able to log in to the dashboard by entering their IdM username and password, when also entering LAB in the Domain field: Note If users receive the error Error: Unable to retrieve container list. , and expect to be able to manage containers, then they must be added to the SwiftOperator role. 2.9. Grant access to the Domain tab To allow the admin user to see the Domain tab, you will need to assign it the admin role in the default domain: Find the admin user's UUID: Add the admin role in the default domain to the admin user: As a result, the admin user can now see the Domain tab. 2.10. Creating a new project After you have completed these integration steps, when you create a new project you will need to decide whether to create it in the Default domain, or in the keystone domain you've just created. This decision can be reached by considering your workflow, and how you administer user accounts. The Default domain can be be thought of as an internal domain, used for service accounts and the admin project, so it might make sense for your AD-backed users to be placed within a different keystone domain; this does not strictly need to be the same keystone domain as the IdM users are in, and for separation purposes, there might be multiple keystone domains. 2.10.1. Changes to the dashboard log in process Configuring multiple domains in Identity Service enables a new Domain field in the dashboard login page. Users are expected to enter the domain that matches their login credentials. This field must be manually filled with one of the domains present in keystone. Use the openstack command to list the available entries. In this example, IdM accounts will need to specify the LAB domain. The built-in keystone accounts, such as admin , must specify Default as their domain: 2.10.2. Changes to the command line For certain commands, you might need to specify the applicable domain. For example, appending --domain LAB in this command returns users in the LAB domain (that are members of the grp-openstack group): Appending --domain Default returns the built-in keystone accounts: 2.10.3. Test IdM integration This procedure validates IdM integration by testing user access to dashboard features: Create a test user in IdM, and add the user to the grp-openstack IdM group. Add the user to the _member_ role of the demo project. Log in to the dashboard using the credentials of the IdM test user. Click on each of the tabs to confirm that they are presented successfully without error messages. Use the dashboard to build a test instance. Note If you experience issues with these steps, perform steps 3-5 with the built-in admin account. If successful, this demonstrates that OpenStack is still working as expected, and that an issue exists somewhere within the IdM <--> Identity integration settings. See Section 2.13, "Troubleshooting" . 2.11. Configure for high availability With keystone v3 enabled, you can make this configuration highly available by listing multiple IdM servers in the configuration file for that domain. Add a second server to the url entry. For example, updating the url setting in the keystone.LAB.conf file will have Identity Service send all query traffic to the first IdM server in the list, idm.lab.local : If a query to idm.lab.local fails due to it being unavailable, Identity Service will attempt to query the server in the list: idm2.lab.local . Note that this configuration does not perform queries in a round-robin fashion, so cannot be considered a load-balancing solution. Set the network timeout in /etc/openldap/ldap.conf : In addition, if you have firewalls configured between the controller and the IdM servers, then you should not configure the IdM servers to silently drop packets from the controller. This will allow python-keystoneclient to properly detect outages and redirect the request to the IdM server in the list. Note There might be connection delays while queries are being redirected to the second IdM server in the list. This is because the connection to the first server must first time out before the second is attempted. 2.12. Create a RC file for a non-admin user You might need to create a RC file for a non-admin user. For example: 2.13. Troubleshooting 2.13.1. Test LDAP connections Use ldapsearch to remotely perform test queries against the IdM server. A successful result here indicates that network connectivity is working, and the IdM services are up. In this example, a test query is performed against the server idm.lab.local on port 636: Note ldapsearch is a part of the openldap-clients package. You can install this using # dnf install openldap-clients . 2.13.2. Test port access Use nc to check that the LDAPS port (636) is remotely accessible. In this example, a probe is performed against the server idm.lab.local . Press ctrl-c to exit the prompt. Failure to establish a connection could indicate a firewall configuration issue.

Commands:
kinit admin ipa user-add First name: OpenStack Last name: LDAP User [radministrator]: svc-ldap
ipa group-add --desc="OpenStack Users" grp-openstack
ipa passwd svc-ldap ipa group-add-member --users=svc-ldap grp-openstack
kinit svc-ldap
TLS_CACERT /etc/ipa/ca.crt
scp /etc/ipa/ca.crt root@node.lab.local:/root/
openssl x509 -in ca.crt -out ca.pem -outform PEM
cp ca.crt/etc/pki/ca-trust/source/anchors
cp ca.pem /etc/pki/ca-trust/source/anchors/ update-ca-trust
setsebool -P authlogin_nsswitch_use_ldap=on
Full path required for exclude: net:[4026532245].
mkdir /var/lib/config-data/puppet-generated/keystone/etc/keystone/domains/ chown 42425:42425 /var/lib/config-data/puppet-generated/keystone/etc/keystone/domains/
crudini --set /var/lib/config-data/puppet-generated/keystone/etc/keystone/keystone.conf identity domain_specific_drivers_enabled true crudini --set /var/lib/config-data/puppet-generated/keystone/etc/keystone/keystone.conf identity domain_config_dir /etc/keystone/domains crudini --set /var/lib/config-data/puppet-generated/keystone/etc/keystone/keystone.conf assignment driver sql
OPENSTACK_API_VERSIONS = { "identity": 3 } OPENSTACK_KEYSTONE_MULTIDOMAIN_SUPPORT = True OPENSTACK_KEYSTONE_DEFAULT_DOMAIN = 'Default'
sudo systemctl restart tripleo_horizon
openstack domain create LAB
[ldap] url = ldaps://idm.lab.local user = uid=svc-ldap,cn=users,cn=accounts,dc=lab,dc=local user_filter = (memberOf=cn=grp-openstack,cn=groups,cn=accounts,dc=lab,dc=local) password = RedactedComplexPassword user_tree_dn = cn=users,cn=accounts,dc=lab,dc=local user_objectclass = inetUser user_id_attribute = uid user_name_attribute = uid user_mail_attribute = mail user_pass_attribute = group_tree_dn = cn=groups,cn=accounts,dc=lab,dc=local group_objectclass = groupOfNames group_id_attribute = cn group_name_attribute = cn group_member_attribute = member group_desc_attribute = description use_tls = False query_scope = sub chase_referrals = false tls_cacertfile =/etc/pki/ca-trust/source/anchors/anchorsca.crt [identity] driver = ldap
chown 42425:42425 /var/lib/config-data/puppet-generated/keystone/etc/keystone/domains/keystone.LAB.conf
openstack domain show LAB +---------+----------------------------------+ | Field | Value | +---------+----------------------------------+ | enabled | True | | id | 6800b0496429431ab1c4efbb3fe810d4 | | name | LAB | +---------+----------------------------------+
openstack user list --domain default | grep admin | 3d75388d351846c6a880e53b2508172a | admin |
openstack role list +----------------------------------+---------------+ | ID | Name | +----------------------------------+---------------+ | 544d48aaffde48f1b3c31a52c35f01f9 | SwiftOperator | | 6d005d783bf0436e882c55c62457d33d | ResellerAdmin | | 785c70b150ee4c778fe4de088070b4cf | admin | | 9fe2ff9ee4384b1894a90878d3e92bab | _member_ | +----------------------------------+---------------+
openstack role add --domain 6800b0496429431ab1c4efbb3fe810d4 --user 3d75388d351846c6a880e53b2508172a 785c70b150ee4c778fe4de088070b4cf
sudo podman restart keystone
openstack user list --domain LAB
openstack user list --domain default
openstack group list --domain LAB +------------------------------------------------------------------+---------------------+ | ID | Name | +------------------------------------------------------------------+---------------------+ | 185277be62ae17e498a69f98a59b66934fb1d6b7f745f14f5f68953a665b8851 | grp-openstack | | a8d17f19f464c4548c18b97e4aa331820f9d3be52654aa8094e698a9182cbb88 | grp-openstack-admin | | d971bb3bd5e64a454cbd0cc7af4c0773e78d61b5f81321809f8323216938cae8 | grp-openstack-demo | +------------------------------------------------------------------+---------------------+
openstack role list +----------------------------------+---------------+ | ID | Name | +----------------------------------+---------------+ | 0969957bce5e4f678ca6cef00e1abf8a | ResellerAdmin | | 1fcb3c9b50aa46ee8196aaaecc2b76b7 | admin | | 9fe2ff9ee4384b1894a90878d3e92bab | _member_ | | d3570730eb4b4780a7fed97eba197e1b | SwiftOperator | +----------------------------------+---------------+
openstack role add --project demo --group d971bb3bd5e64a454cbd0cc7af4c0773e78d61b5f81321809f8323216938cae8 _member_
openstack user list --domain LAB +------------------------------------------------------------------+----------------+ | ID | Name | +------------------------------------------------------------------+----------------+ | 1f24ec1f11aeb90520079c29f70afa060d22e2ce92b2eba7784c841ac418091e | user1 | | 12c062faddc5f8b065434d9ff6fce03eb9259537c93b411224588686e9a38bf1 | user2 | | afaf48031eb54c3e44e4cb0353f5b612084033ff70f63c22873d181fdae2e73c | user3 | | e47fc21dcf0d9716d2663766023e2d8dc15a6d9b01453854a898cabb2396826e | user4 | +------------------------------------------------------------------+----------------+
openstack role list +----------------------------------+---------------+ | ID | Name | +----------------------------------+---------------+ | 544d48aaffde48f1b3c31a52c35f01f9 | SwiftOperator | | 6d005d783bf0436e882c55c62457d33d | ResellerAdmin | | 785c70b150ee4c778fe4de088070b4cf | admin | | 9fe2ff9ee4384b1894a90878d3e92bab | _member_ | +----------------------------------+---------------+
openstack role add --project demo --user 1f24ec1f11aeb90520079c29f70afa060d22e2ce92b2eba7784c841ac418091e _member_
openstack role add --project demo --user 1f24ec1f11aeb90520079c29f70afa060d22e2ce92b2eba7784c841ac418091e admin
openstack user list | grep admin | a6a8adb6356f4a879f079485dad1321b | admin |
openstack role add --domain default --user a6a8adb6356f4a879f079485dad1321b admin
openstack domain list +----------------------------------+---------+---------+----------------------------------------------------------------------+ | ID | Name | Enabled | Description | +----------------------------------+---------+---------+----------------------------------------------------------------------+ | 6800b0496429431ab1c4efbb3fe810d4 | LAB | True | | | default | Default | True | Owns users and projects available on Identity API v2. | +----------------------------------+---------+---------+----------------------------------------------------------------------+
openstack user list --domain LAB
openstack user list --domain Default
url = ldaps://idm.lab.local,ldaps://idm2.lab.local
NETWORK_TIMEOUT 2
cat overcloudrc-v3-user1 Clear any old environment that may conflict. for key in USD( set | awk '{FS="="} /^OS_/ {print USD1}' ); do unset USDkey ; done export OS_USERNAME=user1 export NOVA_VERSION=1.1 export OS_PROJECT_NAME=demo export OS_PASSWORD=RedactedComplexPassword export OS_NO_CACHE=True export COMPUTE_API_VERSION=1.1 export no_proxy=,10.0.0.5,192.168.2.11 export OS_CLOUDNAME=overcloud export OS_AUTH_URL=https://10.0.0.5:5000/v3 export OS_AUTH_TYPE=password export PYTHONWARNINGS="ignore:Certificate has no, ignore:A true SSLContext object is not available" export OS_IDENTITY_API_VERSION=3 export OS_PROJECT_DOMAIN_NAME=Default export OS_USER_DOMAIN_NAME=LAB
ldapsearch -D "cn=directory manager" -H ldaps://idm.lab.local:636 -b "dc=lab,dc=local" -s sub "(objectclass=*)" -w RedactedComplexPassword
nc -v idm.lab.local 636 Ncat: Version 6.40 ( http://nmap.org/ncat ) Ncat: Connected to 192.168.200.10:636. ^C