Connecting Keystone to multiple LDAP Domains

Keystone supports using different identity backends for different domains. This can either be done via domain-specific configuration files or using the API.

YAOOK does not support adding domain-specific configuration files, but instead only supports the way using the API. This is supported by the following quote from the above-linked Keystone documentation:

Keystone has deprecated the keystone-manage domain_config_upload option. The keystone team recommends setting domain config options via the API instead.

Hence, we can assume the API way to be future-proof.

Unfortunately, the API-based way is not supported with the openstack(1) command-line tool. We have to resort to readign the API reference for domain configuration and using curl directly.

Configure the KeystoneDeployment for LDAP

It is only necessary to configure the KeystoneDeployment specifically if using TLS. Further, it should only be necessary if the CA used to sign the LDAP server’s certificate is not trusted by default.

If not using TLS or if using a trusted CA, you may skip this entire section.

  1. Create a Kubernetes ConfigMap with the PEM-encoded CA certificate, looking similar to this:

    apiVersion: v1
    kind: ConfigMap
    metadata:
      namespace: yaook
      name: ldap-ca-customer-example
    data:
      ca.crt: |
        -----BEGIN CERTIFICATE-----
        ...
        -----END CERTIFICATE-----
    
  2. Configure the KeystoneDeployment to include the following spec.extraProjected.sources[] entry (create the section if it does not exist):

    - configMap:
      name: ldap-ca-customer-example  # adapt to the name of the ConfigMap
      items:
      - key: ca.crt  # adapt if the key in the ConfigMap differs
        path: ldap-ca-customer.example.crt
    

    This mounts the CA certificate at /mnt/projected/ldap-ca-customer.example.crt, which we can later reference in the domain configuration.

Configure the LDAP domain in Keystone via the API

This section must be executed in a yaookctl shell openstack or equivalent environment (that is, with admin credentials for OpenStack).

  1. Create a JSON file with the LDAP configuration. The format must be like this:

    {
      "config": {
         "ldap": {
            "url": "ldap://...",
            "user": "...",
            "password": "..."
         }
      }
    }
    

    The config.ldap part of the JSON object needs to be filled with the options documented in the the Keystone LDAP configuration reference. Options which are not needed or should stay at the defaults can be omitted.

    If using TLS with a custom CA as described above, make sure to set "tls_cacertfile": "/mnt/projected/ldap-ca-customer.example.crt" (or whichever filename you picked in the previous step; the directory /mnt/projected is hardcoded in YAOOK).

    Let’s call the resulting JSON file customer.example.json.

  2. If using TLS, ensure that the KeystoneDeployment has finished applying the changes from the previous section at this point.

  3. Create the domain:

    $ openstack domain create customer.example
    +-------------+----------------------------------+
    | Field       | Value                            |
    +-------------+----------------------------------+
    | id          | 95e1299481c146909e72120f8b1eef6a |
    | name        | customer.example                 |
    | enabled     | True                             |
    | description | None                             |
    | options     | {}                               |
    +-------------+----------------------------------+
    
  4. Obtain a token: export TOKEN=$(openstack token issue -f value -c id)

  5. Enable the LDAP backend for the domain:

    $ curl --capath /etc/pki/tls/certs/ -H "X-Auth-Token: $TOKEN" -H "Content-Type: application/json" -X PUT --data '{"config": {"identity": {"driver": "ldap"}}}' https://keystone.yaook.svc:5000/v3/domains/95e1299481c146909e72120f8b1eef6a/config
    

    Make sure to replace the domain ID in the URL according to the output of domain create!

  6. Configure the LDAP backend:

    $ curl --capath /etc/pki/tls/certs/ -H "X-Auth-Token: $TOKEN" -H "Content-Type: application/json" -X PATCH --data-binary @customer.example.json https://keystone.yaook.svc:5000/v3/domains/95e1299481c146909e72120f8b1eef6a/config
    

    Make sure that the configuration JSON from earlier is available at customer.example.json or adapt the path.

  7. Test the connection by running

    $ openstack user list --domain customer.example
    

    This should list the users from the LDAP directory, or die (with an “internal server error”) trying.

Further Hints

When using multiple domains, the use of the Domain Manager role is advisable. More information about the Domain Manager role, including a recommendation on policies to use in YAOOK (OpenStack 2024.1 and earlier, as well as OpenStack without enforce_new_defaults, which is the case in YAOOK as of writing) can be found in the Sovereign Cloud Stack documentation:

Troubleshooting

If you get 500 Internal Server Error errors from Keystone, make sure to get the Keystone logs (yaookctl logs keystone api) during the attempt.

If the domain connectivity is misconfigured, the keystone-bootstrap Job may get stuck. Its logs will also have useful information on what went wrong.

If you get the domain configuration curl call wrong and accidentally configure another domain, the domain you think should be using LDAP will use defaults. That will make the connection fail in non-obvious ways. You can retrieve the current configuration with a GET call. See the API docs linked in the introduction for details.