# keystone.cmd.doctor.ldap

# Source code for keystone.cmd.doctor.ldap

    # Licensed under the Apache License, Version 2.0 (the "License"); you may
    # not use this file except in compliance with the License. You may obtain
    # a copy of the License at
    #
    #      http://www.apache.org/licenses/LICENSE-2.0
    #
    # Unless required by applicable law or agreed to in writing, software
    # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
    # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
    # License for the specific language governing permissions and limitations
    # under the License.

    import configparser
    import os
    import re

    import keystone.conf

    CONF = keystone.conf.CONF
    CONFIG_REGEX = r'^keystone\..*?\.conf$'

    def symptom_LDAP_user_enabled_emulation_dn_ignored():
        """`[ldap] user_enabled_emulation_dn` is being ignored.

        There is no reason to set this value unless `keystone.conf [ldap]
        user_enabled_emulation` is also enabled.
        """
        return (
            not CONF.ldap.user_enabled_emulation
            and CONF.ldap.user_enabled_emulation_dn is not None
        )

    def symptom_LDAP_user_enabled_emulation_use_group_config_ignored():
        """`[ldap] user_enabled_emulation_use_group_config` is being ignored.

        There is no reason to set this value unless `keystone.conf [ldap]
        user_enabled_emulation` is also enabled.
        """
        return (
            not CONF.ldap.user_enabled_emulation
            and CONF.ldap.user_enabled_emulation_use_group_config
        )

    def symptom_LDAP_group_members_are_ids_disabled():
        """`[ldap] group_members_are_ids` is not enabled.

        Because you've set `keystone.conf [ldap] group_objectclass = posixGroup`,
        we would have also expected you to enable set `keystone.conf [ldap]
        group_members_are_ids` because we suspect you're using Open Directory,
        which would contain user ID's in a `posixGroup` rather than LDAP DNs, as
        other object classes typically would.
        """
        return (
            CONF.ldap.group_objectclass == 'posixGroup'
            and not CONF.ldap.group_members_are_ids
        )

    def symptom_LDAP_file_based_domain_specific_configs():
        """Domain specific driver directory is invalid or contains invalid files.

        If `keystone.conf [identity] domain_specific_drivers_enabled` is set
        to `true`, then support is enabled for individual domains to have their
        own identity drivers. The configurations for these can either be stored
        in a config file or in the database. The case we handle in this symptom
        is when they are stored in config files, which is indicated by
        `keystone.conf [identity] domain_configurations_from_database`
        being set to `false`.
        """
        if (
            not CONF.identity.domain_specific_drivers_enabled
            or CONF.identity.domain_configurations_from_database
        ):
            return False

        invalid_files = []
        filedir = CONF.identity.domain_config_dir
        if os.path.isdir(filedir):
            for filename in os.listdir(filedir):
                if not re.match(CONFIG_REGEX, filename):
                    invalid_files.append(filename)
            if invalid_files:
                invalid_str = ', '.join(invalid_files)
                print(
                    f'Warning: The following non-config files were found: {invalid_str}\n'
                    'If they are intended to be config files then rename them '
                    'to the form of `keystone.<domain_name>.conf`. '
                    'Otherwise, ignore this warning'
                )
                return True
        else:
            print('Could not find directory ', filedir)
            return True

        return False

    def symptom_LDAP_file_based_domain_specific_configs_formatted_correctly():
        """LDAP domain specific configuration files are not formatted correctly.

        If `keystone.conf [identity] domain_specific_drivers_enabled` is set
        to `true`, then support is enabled for individual domains to have their
        own identity drivers. The configurations for these can either be stored
        in a config file or in the database. The case we handle in this symptom
        is when they are stored in config files, which is indicated by
        `keystone.conf [identity] domain_configurations_from_database`
        being set to false. The config files located in the directory specified
        by `keystone.conf [identity] domain_config_dir` should be in the
        form of `keystone.<domain_name>.conf` and their contents should look
        something like this:

        [ldap]
        url = ldap://ldapservice.thecustomer.com
        query_scope = sub

        user_tree_dn = ou=Users,dc=openstack,dc=org
        user_objectclass = MyOrgPerson
        user_id_attribute = uid
        ...
        """
        filedir = CONF.identity.domain_config_dir
        # NOTE(gagehugo): If domain_specific_drivers_enabled = false or
        # the value set in domain_config_dir is nonexistent/invalid, then
        # there is no point in continuing with this check.
        # symptom_LDAP_file_based_domain_specific_config will catch and
        # report this issue.
        if (
            not CONF.identity.domain_specific_drivers_enabled
            or CONF.identity.domain_configurations_from_database
            or not os.path.isdir(filedir)
        ):
            return False

        invalid_files = []
        for filename in os.listdir(filedir):
            if re.match(CONFIG_REGEX, filename):
                try:
                    parser = configparser.ConfigParser()
                    parser.read(os.path.join(filedir, filename))
                except configparser.Error:
                    invalid_files.append(filename)

        if invalid_files:
            invalid_str = ', '.join(invalid_files)
            print(
                'Error: The following config files are formatted incorrectly: ',
                invalid_str,
            )
            return True

        return False

this page last updated: 2026-08-17 12:45:24

Except where otherwise noted, this document is licensed under Creative Commons Attribution 3.0 License. See all OpenStack Legal Documents.

found an error? report a bug