Configure OpenStack Keystone support for domain-specific corporate directories

Get multiple domain support for LDAP and Active Directory with OpenStack Keystone


The open source OpenStack project provides an Infrastructure as a Service (IaaS) layer for building public and private clouds. OpenStack is currently seeing a huge growth in adoption by corporations, service providers, value-added resellers, small and mid-sized businesses, researchers, and global data centers for deploying large-scale private or public clouds. (See Related topics to learn more about OpenStack.)

As more and more enterprise customers begin to deploy OpenStack, it is becoming critical for these customers to seamlessly integrate OpenStack into their existing corporate directory infrastructure. While in some cases this might be handled through Keystone's federation support, for many enterprises the key is integration with their existing LDAP or Active Directory. Support for a single corporate directory has been part of Keystone for a number of releases, however more complex installations (such as enterprises that have a different directory or directory mount point for each division, or for service providers who would like to offer customers their own directory) were not well supported. An experimental version of domain-specific corporate directory support was first introduced in the Grizzly release. With the OpenStack Juno release, this is now fully supported. This article covers the following:

  • An overview of OpenStack Keystone's classic support for corporate directories
  • The enhancements that have been added to Keystone to enable it to support domain-specific directories
  • The basic steps on how to configure Keystone to use this new support
  • An overview of OpenStack Keystone future directions for improving domain-specific directories

Keystone's classic authorization model

Before examining Keystone's new domain-specific directory support, it is helpful to provide an overview of Keystone's classic mono-domain directory support. The core of Keystone is really split into two components: identity and assignment. Identity (i.e. who can authenticate) allows users and groups to be stored in a local SQL database, or to be backed by a remote LDAP or Active Directory service. Assignment (i.e. what a user can do once they have authenticated) stores the projects, domains, roles, and the assignments of those roles. Again, these can be stored in a local SQL database or, more rarely, in a remote LDAP/AD service as long as you have read-write access to it. Due to the challenges of mapping Keystone's domain structure to LDAP (from an identity point of view), up until now as soon as you enabled LDAP for identity, you were restricted to a single, default domain. This limited the use of LDAP/AD in more sophisticated environments.

Requirements for multi-domain corporate directory support

Given that you cannot change the fact that an LDAP/AD schema does not map that well onto the typical model required by an IaaS layer that wants, for efficiency reasons, to be shared-use, you need to change how the Keystone model interacts with the directory. In essence, you need to handle the "domain-ness" aspects within Keystone, and talk to the appropriate corporate directory as if it was the only one you are using. This includes defining all the typical LDAP/AD parameters (such as URL, directory attribute mapping, etc.) on a per-domain basis and ensuring that whenever you, say, read a user record for a given domain, route the call to the correct corporate directory. This level of support was introduced in Grizzly, but suffered from a number of problems. The most serious of these was a clash between a core concept in the Keystone API and such multi-domain support -- namely that you can hand the API a user or group ID and Keystone can use that to find the user/group entity in question. With multiple directory servers, which one would you look in? For performance reasons, searching them all is not a viable option. Hence the original implementation tried to deduce the domain in question -- for example, since you typically have to use a domain-scoped token to retrieve a user entity given its ID, you could use the scope of the token to determine the appropriate corporate directory for the domain in question. However, that method clearly has limitations; for example, you need to be able authenticate by just giving the user ID and password. And even if you could get around these limitations, should you trust any given corporate directory to create an entity ID that is unique across all other corporate directories?

Supporting multi-domain corporate directories

The Juno release of OpenStack solves the above problems by Keystone providing a directory-mapping layer that generates unique user and group IDs to its clients, and stores the underlying details of which identity backend driver holds the entity (and the local ID within that backend). This directory-mapping layer is essentially invisible to callers of the Keystone API, and the mapping is built on the fly as Keystone encounters entities in its identity drivers. The only thing a caller might notice is that the IDs for users and groups have gotten bigger. (They are, by default, 64-byte sha256 hashes as opposed to the classic 32-byte UUIDs.) It should be noted that this directory-mapping is not related to the Keystone federation mapping that is used to handle the mapping of IDP assertion attributes into Keystone role assignments.

So let's take a look at an example of using domain-specific directories in practice. In a service provider that offered cloud services to its customers, it would be common to represent a customer as a domain in Keystone. This allows customers to have their own users, groups, and projects. What the provider would like to do is to be able to offer customers the ability to use their existing corporate directory for authentication to their domain -- enabling each customer domain to point to the customer's own LDAP/AD service. The first thing to do is to enable domain-specific configuration support in Keystone (it is disabled by default) by setting the following two options in the main Keystone configuration file:


When domain-specific drivers are enabled, each time Keystone is started it will scan the contents of domain_config_dir for any domain-specific configuration files. For each domain that requires its unique corporate directory, the service provider creates a domain-specific configuration file that contains the specific details of the corporate directory for that domain. For example, if the service provider creates a domain called "customerA" to represent that customer, then they create a domain-specific configuration file called keystone.customerA.conf. (The name is important, and is always of the form: keystone.{domain-name}.conf -- the domain name must match the name of the domain created in keystone.) The contents of this configuration file might look something like this:

    url = ldap://
    user = cn=Manager,dc=openstack,dc=org
    password = mysecret
    suffix = dc=openstack,dc=org
    group_tree_dn = ou=UserGroups,dc=openstack,dc=org
    ;user_tree_dn = ou=Users,dc=openstack,dc=org
    user_mail_attribute = mail

    driver = keystone.identity.backends.ldap.Identity

As you can see, these are exactly the same types of configuration options that are normally set in the main Keystone configuration file -- except in this case they are specified in the specific configuration file for this domain. Each domain that needs its own configuration needs to have its own configuration file. Note that only the options that are specific to the domain need to be specified here; common options can stay in the main Keystone configuration file.

Once a domain has its own configuration file, Keystone will build a mapping for the user and group entities in that backend as it encounters them, and routes any requests issued for those entities to the appropriate corporate directory.

While it is primarily designed to support different corporate directories, you can also specify a configuration file for a domain to use an SQL backend. This is particularly useful if you want to have some local users (such as service users or local admin users) that you don't want to place in a corporate directory. This is done in exactly the same way as in the LDAP/AD case: Create a domain-specific configuration file for a domain using the same naming convention, but in this case it will probably just contain the name of the driver. For example, if you want domain CloudAdmin to be backed by SQL while all your other domains perhaps use LDAP, then create a domain-specific configuration file called keystone.CloudAdmin.conf that contains:

    driver = keystone.identity.backends.sql.Identity

The big restriction, however, is that Keystone currently allows only one SQL driver to be loaded at a time -- so either this can be the catch-all driver (by specifying identity as SQL in the main Keystone configuration file) or it can be assigned to a specific domain (using a domain-specific configuration file). If you try specifying more than one domain with its own SQL configuration, Keystone will raise an exception when starting up. Future versions of Keystone may lift this limitation.

Tips and tricks for practical use

There are a number of techniques that you can deploy to use the described capabilities to ease production configurations.

Do things in the right order

If you are starting with the classic configuration when you only have the default domain that points at a single LDAP/AD corporate directory, then the order of steps should be:

  1. Set domain_specific_drivers_enabled to "true" in the main keystone configuration file and restart Keystone.
  2. Create the domain for which you want to have specific configurations.
  3. Create the domain-specific configuration files for each of these domains.
  4. Restart Keystone again.

With LDAP as the default driver, if you don't first set domain_specific_drivers_enabled to "true," Keystone will prevent you from creating new domains (since it knows that the default LDAP driver can only handle the default domain).

Check the Keystone log file if the domain configuration is not working

If you have set up your domain and the configuration file but you still can't access the data in the corporate directory, then it might be worth checking the Keystone log file. At startup, as Keystone is scanning the domain_config_dir, it will examine each file. If it doesn't match the form of keystone.{domain-name}.conf, then it will be ignored. If Keystone can't find the domain of the name specified in the file name, then it will also ignore it. In both of these situations, Keystone will load a warning with the name of the problematic file. For example:

    Invalid domain name (CustomerB) found in config file name

Occasional maintenance on the directory-mapping table

As I mentioned earlier, Keystone dynamically builds the directory mapping from external published user and group IDs to the underlying local entities in the appropriate corporate directory service. Since these corporate directories are usually read-only from a Keystone perspective, any user management will happen out-of-band via the tooling used to maintain the corporate directory in question. In practice, this means that over time as user and group entities are deleted out of the corporate directory, old mapping entries will remain in Keystone's directory-mapping table. While this is benign, over time it could bloat the Keystone table. To manage this, the keystone-manage tool has been enhanced to support several options for purging entries out of the keystone directory-mapping table. The most specific option is to purge the mapping for a given local identifier in a given domain. For example:

    keystone-manage mapping_purge --domain-name CustomerA --local-id

If this is a relatively frequent occurrence, then you might want to automate such individual purging. An alternative, however, is to simply purge all the mappings periodically for a given domain. A more immediate concern might be whether this will cause you to lose the externally published ID for local entities. In fact, that's not an issue, since the algorithm for the mapping is designed such that Keystone can regenerate the mapping and guarantee to re-assign the same externally published user/group ID as before. Note that this assumes that a user has not moved between corporate directories; if they have, then they are considered a different user. To purge all the mappings for a given domain:

    keystone-manage mapping_purge --domain-name CustomerA


This article provided an overview of Keystone's new domain-specific configuration support and illustrated how this new capability enables Keystone to support more extensive enterprise configurations. It also demonstrated how to set up configuration files as well as some useful tips for managing this in production.

Downloadable resources

Related topics

  • OpenStack: Visit the OpenStack website to learn more about OpenStack software.
  • Keystone User Management: Find out more about Keystone's classic user authorization model.
  • Configuring Keystone: Learn how to configure Keystone in general, including domain-specific drivers.
  • Keystone: Learn more about OpenStack's Identity Service project.


Sign in or register to add and subscribe to comments.

Zone=Cloud computing, Open source
ArticleTitle=Configure OpenStack Keystone support for domain-specific corporate directories