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: .. code-block:: yaml 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): .. code-block:: - 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: .. code-block:: json { "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: .. code-block:: console $ 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: .. code-block:: console $ 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: .. code-block:: console $ 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 .. code-block:: console $ 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: * `SCS—0302: Domain Manager configuration for Keystone `_ for general information about the Domain Manager role. * `SCS-0302 implementation notes `_ for the backported policy. 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.