apiVersion: v1
data:
  bootstrap.sh: |
    #!/bin/bash



    set -ex

    # admin needs the admin role for the default domain
    openstack role add \
          --user="${OS_USERNAME}" \
          --domain="${OS_DEFAULT_DOMAIN}" \
          "admin"
  cred-clean.py: |2


    #!/usr/bin/python

    # Drops db and user for an OpenStack Service:
    # Set ROOT_DB_CONNECTION and DB_CONNECTION environment variables to contain
    # SQLAlchemy strings for the root connection to the database and the one you
    # wish the service to use. Alternatively, you can use an ini formatted config
    # at the location specified by OPENSTACK_CONFIG_FILE, and extract the string
    # from the key OPENSTACK_CONFIG_DB_KEY, in the section specified by
    # OPENSTACK_CONFIG_DB_SECTION.

    import os
    import sys
    try:
        import ConfigParser
        PARSER_OPTS = {}
    except ImportError:
        import configparser as ConfigParser
        PARSER_OPTS = {"strict": False}
    import logging
    from sqlalchemy import create_engine
    from sqlalchemy import text

    # Create logger, console handler and formatter
    logger = logging.getLogger('OpenStack-Helm DB Drop')
    logger.setLevel(logging.DEBUG)
    ch = logging.StreamHandler()
    ch.setLevel(logging.DEBUG)
    formatter = logging.Formatter(
        '%(asctime)s - %(name)s - %(levelname)s - %(message)s')

    # Set the formatter and add the handler
    ch.setFormatter(formatter)
    logger.addHandler(ch)


    # Get the connection string for the service db root user
    if "ROOT_DB_CONNECTION" in os.environ:
        db_connection = os.environ['ROOT_DB_CONNECTION']
        logger.info('Got DB root connection')
    else:
        logger.critical('environment variable ROOT_DB_CONNECTION not set')
        sys.exit(1)

    mysql_x509 = os.getenv('MARIADB_X509', "")
    ssl_args = {}
    if mysql_x509:
        ssl_args = {'ssl': {'ca': '/etc/mysql/certs/ca.crt',
                            'key': '/etc/mysql/certs/tls.key',
                            'cert': '/etc/mysql/certs/tls.crt'}}

    # Get the connection string for the service db
    if "OPENSTACK_CONFIG_FILE" in os.environ:
        os_conf = os.environ['OPENSTACK_CONFIG_FILE']
        if "OPENSTACK_CONFIG_DB_SECTION" in os.environ:
            os_conf_section = os.environ['OPENSTACK_CONFIG_DB_SECTION']
        else:
            logger.critical(
                'environment variable OPENSTACK_CONFIG_DB_SECTION not set')
            sys.exit(1)
        if "OPENSTACK_CONFIG_DB_KEY" in os.environ:
            os_conf_key = os.environ['OPENSTACK_CONFIG_DB_KEY']
        else:
            logger.critical('environment variable OPENSTACK_CONFIG_DB_KEY not set')
            sys.exit(1)
        try:
            config = ConfigParser.RawConfigParser(**PARSER_OPTS)
            logger.info("Using {0} as db config source".format(os_conf))
            config.read(os_conf)
            logger.info("Trying to load db config from {0}:{1}".format(
                os_conf_section, os_conf_key))
            user_db_conn = config.get(os_conf_section, os_conf_key)
            logger.info("Got config from {0}".format(os_conf))
        except:
            logger.critical(
                "Tried to load config from {0} but failed.".format(os_conf))
            raise
    elif "DB_CONNECTION" in os.environ:
        user_db_conn = os.environ['DB_CONNECTION']
        logger.info('Got config from DB_CONNECTION env var')
    else:
        logger.critical(
            'Could not get db config, either from config file or env var')
        sys.exit(1)

    # Root DB engine
    try:
        root_engine_full = create_engine(db_connection)
        root_user = root_engine_full.url.username
        root_password = root_engine_full.url.password
        drivername = root_engine_full.url.drivername
        host = root_engine_full.url.host
        port = root_engine_full.url.port
        root_engine_url = ''.join([drivername, '://', root_user, ':',
                                   root_password, '@', host, ':', str(port)])
        root_engine = create_engine(root_engine_url, connect_args=ssl_args)
        connection = root_engine.connect()
        connection.close()
        logger.info("Tested connection to DB @ {0}:{1} as {2}".format(
            host, port, root_user))
    except:
        logger.critical('Could not connect to database as root user')
        raise

    # User DB engine
    try:
        user_engine = create_engine(user_db_conn, connect_args=ssl_args)
        # Get our user data out of the user_engine
        database = user_engine.url.database
        user = user_engine.url.username
        password = user_engine.url.password
        logger.info('Got user db config')
    except:
        logger.critical('Could not get user database config')
        raise

    # Delete all entries from credential table

    try:
        cmd = text("DELETE FROM credential")
        with user_engine.connect() as connection:
            connection.execute(cmd)
            try:
                connection.commit()
            except AttributeError:
                pass
        logger.info('Deleted all entries in credential table')
    except:
        logger.critical('Failed to clean up credential table in keystone db')
        raise

    logger.info('Finished DB Management')
  db-drop.py: |
    #!/usr/bin/env python

    # Drops db and user for an OpenStack Service:
    # Set ROOT_DB_CONNECTION and DB_CONNECTION environment variables to contain
    # SQLAlchemy strings for the root connection to the database and the one you
    # wish the service to use. Alternatively, you can use an ini formatted config
    # at the location specified by OPENSTACK_CONFIG_FILE, and extract the string
    # from the key OPENSTACK_CONFIG_DB_KEY, in the section specified by
    # OPENSTACK_CONFIG_DB_SECTION.

    import os
    import sys
    try:
        import ConfigParser
        PARSER_OPTS = {}
    except ImportError:
        import configparser as ConfigParser
        PARSER_OPTS = {"strict": False}
    import logging
    from sqlalchemy import create_engine
    from sqlalchemy import text

    # Create logger, console handler and formatter
    logger = logging.getLogger('OpenStack-Helm DB Drop')
    logger.setLevel(logging.DEBUG)
    ch = logging.StreamHandler()
    ch.setLevel(logging.DEBUG)
    formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')

    # Set the formatter and add the handler
    ch.setFormatter(formatter)
    logger.addHandler(ch)


    # Get the connection string for the service db root user
    if "ROOT_DB_CONNECTION" in os.environ:
        db_connection = os.environ['ROOT_DB_CONNECTION']
        logger.info('Got DB root connection')
    else:
        logger.critical('environment variable ROOT_DB_CONNECTION not set')
        sys.exit(1)

    mysql_x509 = os.getenv('MARIADB_X509', "")
    ssl_args = {}
    if mysql_x509:
        ssl_args = {'ssl': {'ca': '/etc/mysql/certs/ca.crt',
                            'key': '/etc/mysql/certs/tls.key',
                            'cert': '/etc/mysql/certs/tls.crt'}}

    # Get the connection string for the service db
    if "OPENSTACK_CONFIG_FILE" in os.environ:
        os_conf = os.environ['OPENSTACK_CONFIG_FILE']
        if "OPENSTACK_CONFIG_DB_SECTION" in os.environ:
            os_conf_section = os.environ['OPENSTACK_CONFIG_DB_SECTION']
        else:
            logger.critical('environment variable OPENSTACK_CONFIG_DB_SECTION not set')
            sys.exit(1)
        if "OPENSTACK_CONFIG_DB_KEY" in os.environ:
            os_conf_key = os.environ['OPENSTACK_CONFIG_DB_KEY']
        else:
            logger.critical('environment variable OPENSTACK_CONFIG_DB_KEY not set')
            sys.exit(1)
        try:
            config = ConfigParser.RawConfigParser(**PARSER_OPTS)
            logger.info("Using {0} as db config source".format(os_conf))
            config.read(os_conf)
            logger.info("Trying to load db config from {0}:{1}".format(
                os_conf_section, os_conf_key))
            user_db_conn = config.get(os_conf_section, os_conf_key)
            logger.info("Got config from {0}".format(os_conf))
        except:
            logger.critical("Tried to load config from {0} but failed.".format(os_conf))
            raise
    elif "DB_CONNECTION" in os.environ:
        user_db_conn = os.environ['DB_CONNECTION']
        logger.info('Got config from DB_CONNECTION env var')
    else:
        logger.critical('Could not get db config, either from config file or env var')
        sys.exit(1)

    # Root DB engine
    try:
        root_engine_full = create_engine(db_connection)
        root_user = root_engine_full.url.username
        root_password = root_engine_full.url.password
        drivername = root_engine_full.url.drivername
        host = root_engine_full.url.host
        port = root_engine_full.url.port
        root_engine_url = ''.join([drivername, '://', root_user, ':', root_password, '@', host, ':', str (port)])
        root_engine = create_engine(root_engine_url, connect_args=ssl_args)
        connection = root_engine.connect()
        connection.close()
        logger.info("Tested connection to DB @ {0}:{1} as {2}".format(
            host, port, root_user))
    except:
        logger.critical('Could not connect to database as root user')
        raise

    # User DB engine
    try:
        user_engine = create_engine(user_db_conn, connect_args=ssl_args)
        # Get our user data out of the user_engine
        database = user_engine.url.database
        user = user_engine.url.username
        password = user_engine.url.password
        logger.info('Got user db config')
    except:
        logger.critical('Could not get user database config')
        raise

    # Delete DB
    try:
        with root_engine.connect() as connection:
            connection.execute(text("DROP DATABASE IF EXISTS {0}".format(database)))
            try:
                connection.commit()
            except AttributeError:
                pass
        logger.info("Deleted database {0}".format(database))
    except:
        logger.critical("Could not drop database {0}".format(database))
        raise

    # Delete DB User
    try:
        with root_engine.connect() as connection:
            connection.execute(text("DROP USER IF EXISTS {0}".format(user)))
            try:
                connection.commit()
            except AttributeError:
                pass
        logger.info("Deleted user {0}".format(user))
    except:
        logger.critical("Could not delete user {0}".format(user))
        raise

    logger.info('Finished DB Management')
  db-init.py: |
    #!/usr/bin/env python

    # Creates db and user for an OpenStack Service:
    # Set ROOT_DB_CONNECTION and DB_CONNECTION environment variables to contain
    # SQLAlchemy strings for the root connection to the database and the one you
    # wish the service to use. Alternatively, you can use an ini formatted config
    # at the location specified by OPENSTACK_CONFIG_FILE, and extract the string
    # from the key OPENSTACK_CONFIG_DB_KEY, in the section specified by
    # OPENSTACK_CONFIG_DB_SECTION.

    import os
    import sys
    try:
        import ConfigParser
        PARSER_OPTS = {}
    except ImportError:
        import configparser as ConfigParser
        PARSER_OPTS = {"strict": False}
    import logging
    from sqlalchemy import create_engine
    from sqlalchemy import text

    # Create logger, console handler and formatter
    logger = logging.getLogger('OpenStack-Helm DB Init')
    logger.setLevel(logging.DEBUG)
    ch = logging.StreamHandler()
    ch.setLevel(logging.DEBUG)
    formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')

    # Set the formatter and add the handler
    ch.setFormatter(formatter)
    logger.addHandler(ch)


    # Get the connection string for the service db root user
    if "ROOT_DB_CONNECTION" in os.environ:
        db_connection = os.environ['ROOT_DB_CONNECTION']
        logger.info('Got DB root connection')
    else:
        logger.critical('environment variable ROOT_DB_CONNECTION not set')
        sys.exit(1)

    mysql_x509 = os.getenv('MARIADB_X509', "")
    ssl_args = {}
    if mysql_x509:
        ssl_args = {'ssl': {'ca': '/etc/mysql/certs/ca.crt',
                    'key': '/etc/mysql/certs/tls.key',
                    'cert': '/etc/mysql/certs/tls.crt'}}

    # Get the connection string for the service db
    if "OPENSTACK_CONFIG_FILE" in os.environ:
        os_conf = os.environ['OPENSTACK_CONFIG_FILE']
        if "OPENSTACK_CONFIG_DB_SECTION" in os.environ:
            os_conf_section = os.environ['OPENSTACK_CONFIG_DB_SECTION']
        else:
            logger.critical('environment variable OPENSTACK_CONFIG_DB_SECTION not set')
            sys.exit(1)
        if "OPENSTACK_CONFIG_DB_KEY" in os.environ:
            os_conf_key = os.environ['OPENSTACK_CONFIG_DB_KEY']
        else:
            logger.critical('environment variable OPENSTACK_CONFIG_DB_KEY not set')
            sys.exit(1)
        try:
            config = ConfigParser.RawConfigParser(**PARSER_OPTS)
            logger.info("Using {0} as db config source".format(os_conf))
            config.read(os_conf)
            logger.info("Trying to load db config from {0}:{1}".format(
                os_conf_section, os_conf_key))
            user_db_conn = config.get(os_conf_section, os_conf_key)
            logger.info("Got config from {0}".format(os_conf))
        except:
            logger.critical("Tried to load config from {0} but failed.".format(os_conf))
            raise
    elif "DB_CONNECTION" in os.environ:
        user_db_conn = os.environ['DB_CONNECTION']
        logger.info('Got config from DB_CONNECTION env var')
    else:
        logger.critical('Could not get db config, either from config file or env var')
        sys.exit(1)

    # Root DB engine
    try:
        root_engine_full = create_engine(db_connection)
        root_user = root_engine_full.url.username
        root_password = root_engine_full.url.password
        drivername = root_engine_full.url.drivername
        host = root_engine_full.url.host
        port = root_engine_full.url.port
        root_engine_url = ''.join([drivername, '://', root_user, ':', root_password, '@', host, ':', str (port)])
        root_engine = create_engine(root_engine_url, connect_args=ssl_args)
        connection = root_engine.connect()
        connection.close()
        logger.info("Tested connection to DB @ {0}:{1} as {2}".format(
            host, port, root_user))
    except:
        logger.critical('Could not connect to database as root user')
        raise

    # User DB engine
    try:
        user_engine = create_engine(user_db_conn, connect_args=ssl_args)
        # Get our user data out of the user_engine
        database = user_engine.url.database
        user = user_engine.url.username
        password = user_engine.url.password
        logger.info('Got user db config')
    except:
        logger.critical('Could not get user database config')
        raise

    # Create DB
    try:
        with root_engine.connect() as connection:
            connection.execute(text("CREATE DATABASE IF NOT EXISTS {0}".format(database)))
            try:
                connection.commit()
            except AttributeError:
                pass
        logger.info("Created database {0}".format(database))
    except:
        logger.critical("Could not create database {0}".format(database))
        raise

    # Create DB User
    try:
        with root_engine.connect() as connection:
            connection.execute(
                text("CREATE USER IF NOT EXISTS \'{0}\'@\'%\' IDENTIFIED BY \'{1}\' {2}".format(
                    user, password, mysql_x509)))
            connection.execute(
                text("GRANT ALL ON `{0}`.* TO \'{1}\'@\'%\'".format(database, user)))
            try:
                connection.commit()
            except AttributeError:
                pass
        logger.info("Created user {0} for {1}".format(user, database))
    except:
        logger.critical("Could not create user {0} for {1}".format(user, database))
        raise

    # Test connection
    try:
        connection = user_engine.connect()
        connection.close()
        logger.info("Tested connection to DB @ {0}:{1}/{2} as {3}".format(
            host, port, database, user))
    except:
        logger.critical('Could not connect to database as user')
        raise

    logger.info('Finished DB Management')
  db-sync.sh: |
    #!/bin/bash



    set -ex

    keystone-manage --config-file=/etc/keystone/keystone.conf db_sync
    keystone-manage --config-file=/etc/keystone/keystone.conf bootstrap \
        --bootstrap-username ${OS_USERNAME} \
        --bootstrap-password ${OS_PASSWORD} \
        --bootstrap-project-name ${OS_PROJECT_NAME} \
        --bootstrap-admin-url ${OS_BOOTSTRAP_ADMIN_URL} \
        --bootstrap-public-url ${OS_BOOTSTRAP_PUBLIC_URL} \
        --bootstrap-internal-url ${OS_BOOTSTRAP_INTERNAL_URL} \
        --bootstrap-region-id ${OS_REGION_NAME}

    exec python /tmp/endpoint-update.py
  domain-manage.sh: |
    #!/bin/bash



    set -e
    openstack domain create --or-show atmosphere
  endpoint-update.py: |
    #!/usr/bin/env python
    import os
    import logging
    import sys

    from sqlalchemy import create_engine
    from sqlalchemy import text

    try:
        import ConfigParser
        PARSER_OPTS = {}
    except ImportError:
        import configparser as ConfigParser
        PARSER_OPTS = {"strict": False}

    # Create logger, console handler and formatter
    logger = logging.getLogger('OpenStack-Helm Keystone Endpoint management')
    logger.setLevel(logging.DEBUG)
    ch = logging.StreamHandler()
    ch.setLevel(logging.DEBUG)
    formatter = logging.Formatter(
        '%(asctime)s - %(name)s - %(levelname)s - %(message)s')

    # Set the formatter and add the handler
    ch.setFormatter(formatter)
    logger.addHandler(ch)

    # Get the connection string for the service db
    if "OPENSTACK_CONFIG_FILE" in os.environ:
        os_conf = os.environ['OPENSTACK_CONFIG_FILE']
        if "OPENSTACK_CONFIG_DB_SECTION" in os.environ:
            os_conf_section = os.environ['OPENSTACK_CONFIG_DB_SECTION']
        else:
            logger.critical(
                'environment variable OPENSTACK_CONFIG_DB_SECTION not set')
            sys.exit(1)
        if "OPENSTACK_CONFIG_DB_KEY" in os.environ:
            os_conf_key = os.environ['OPENSTACK_CONFIG_DB_KEY']
        else:
            logger.critical('environment variable OPENSTACK_CONFIG_DB_KEY not set')
            sys.exit(1)
        try:
            config = ConfigParser.RawConfigParser(**PARSER_OPTS)
            logger.info("Using {0} as db config source".format(os_conf))
            config.read(os_conf)
            logger.info("Trying to load db config from {0}:{1}".format(
                os_conf_section, os_conf_key))
            user_db_conn = config.get(os_conf_section, os_conf_key)
            logger.info("Got config from {0}".format(os_conf))
        except:
            logger.critical(
                "Tried to load config from {0} but failed.".format(os_conf))
            raise
    elif "DB_CONNECTION" in os.environ:
        user_db_conn = os.environ['DB_CONNECTION']
        logger.info('Got config from DB_CONNECTION env var')
    else:
        logger.critical(
            'Could not get db config, either from config file or env var')
        sys.exit(1)

    # User DB engine
    try:
        user_engine = create_engine(user_db_conn)
    except:
        logger.critical('Could not get user database config')
        raise

    # Set Internal Endpoint
    try:
        endpoint_url = os.environ['OS_BOOTSTRAP_INTERNAL_URL']
        region_id = os.environ['OS_REGION_NAME']
        cmd = text("update endpoint set url = :endpoint_url where interface ='internal' and "
                   "service_id = (select id from service where "
                   "service.type = 'identity') and "
                   "region_id = :region_id")
        with user_engine.connect() as connection:
            connection.execute(cmd, {"endpoint_url": endpoint_url, "region_id": region_id})
            try:
                connection.commit()
            except AttributeError:
                pass
    except:
        logger.critical("Could not update internal endpoint")
        raise

    # Set Admin Endpoint
    try:
        endpoint_url = os.environ['OS_BOOTSTRAP_ADMIN_URL']
        region_id = os.environ['OS_REGION_NAME']
        cmd = text("update endpoint set url = :endpoint_url where interface ='admin' "
                   "and service_id = (select id from service where "
                   "service.type = 'identity') "
                   "and region_id = :region_id")
        with user_engine.connect() as connection:
            connection.execute(cmd, {"endpoint_url": endpoint_url, "region_id": region_id})
            try:
                connection.commit()
            except AttributeError:
                pass
    except:
        logger.critical("Could not update admin endpoint")
        raise

    # Set Public Endpoint
    try:
        endpoint_url = os.environ['OS_BOOTSTRAP_PUBLIC_URL']
        region_id = os.environ['OS_REGION_NAME']
        cmd = text("update endpoint set url = :endpoint_url where interface ='public' "
                   "and service_id = (select id from service where "
                   "service.type = 'identity') "
                   "and region_id = :region_id")
        with user_engine.connect() as connection:
            connection.execute(cmd, {"endpoint_url": endpoint_url, "region_id": region_id})
            try:
                connection.commit()
            except AttributeError:
                pass
    except:
        logger.critical("Could not update public endpoint")
        raise

    # Print endpoints
    try:
        with user_engine.connect() as connection:
            endpoints = connection.execute(
                text("select interface, url from endpoint where service_id = "
                     "(select id from service where service.type = 'identity')")
            ).fetchall()
        for row in endpoints:
            logger.info("endpoint ({0}): {1}".format(row[0], row[1]))
    except:
        logger.critical("Could not update endpoint")
        raise

    logger.info('Finished Endpoint Management')
  fernet-manage.py: |
    #!/usr/bin/env python



    import argparse
    import base64
    import errno
    import grp
    import logging
    import os
    import pwd
    import re
    import subprocess  #nosec
    import sys
    import time

    import requests

    FERNET_DIR = os.environ['KEYSTONE_KEYS_REPOSITORY']
    KEYSTONE_USER = os.environ['KEYSTONE_USER']
    KEYSTONE_GROUP = os.environ['KEYSTONE_GROUP']
    NAMESPACE = os.environ['KUBERNETES_NAMESPACE']

    # k8s connection data
    KUBE_HOST = None
    KUBE_CERT = '/var/run/secrets/kubernetes.io/serviceaccount/ca.crt'
    KUBE_TOKEN = None

    LOG_DATEFMT = "%Y-%m-%d %H:%M:%S"
    LOG_FORMAT = "%(asctime)s.%(msecs)03d - %(levelname)s - %(message)s"
    logging.basicConfig(format=LOG_FORMAT, datefmt=LOG_DATEFMT)
    LOG = logging.getLogger(__name__)
    LOG.setLevel(logging.INFO)


    def read_kube_config():
        global KUBE_HOST, KUBE_TOKEN
        KUBE_HOST = "https://%s:%s" % ('kubernetes.default',
                                       os.environ['KUBERNETES_SERVICE_PORT'])
        with open('/var/run/secrets/kubernetes.io/serviceaccount/token', 'r') as f:
            KUBE_TOKEN = f.read()


    def get_secret_definition(name):
        url = '%s/api/v1/namespaces/%s/secrets/%s' % (KUBE_HOST, NAMESPACE, name)
        resp = requests.get(url,
                            headers={'Authorization': 'Bearer %s' % KUBE_TOKEN},
                            verify=KUBE_CERT)
        if resp.status_code != 200:
            LOG.error('Cannot get secret %s.', name)
            LOG.error(resp.text)
            return None
        return resp.json()


    def update_secret(name, secret):
        url = '%s/api/v1/namespaces/%s/secrets/%s' % (KUBE_HOST, NAMESPACE, name)
        resp = requests.put(url,
                            json=secret,
                            headers={'Authorization': 'Bearer %s' % KUBE_TOKEN},
                            verify=KUBE_CERT)
        if resp.status_code != 200:
            LOG.error('Cannot update secret %s.', name)
            LOG.error(resp.text)
            return False
        return True


    def read_from_files():
        keys = [name for name in os.listdir(FERNET_DIR) if os.path.isfile(FERNET_DIR + name)
                and re.match("^\d+$", name)]
        data = {}
        for key in keys:
            with open(FERNET_DIR + key, 'r') as f:
                data[key] = f.read()
        if len(list(keys)):
            LOG.debug("Keys read from files: %s", keys)
        else:
            LOG.warning("No keys were read from files.")
        return data


    def get_keys_data():
        keys = read_from_files()
        return dict([(key, base64.b64encode(value.encode()).decode())
                    for (key, value) in keys.items()])


    def write_to_files(data):
        if not os.path.exists(os.path.dirname(FERNET_DIR)):
            try:
                os.makedirs(os.path.dirname(FERNET_DIR))
            except OSError as exc: # Guard against race condition
                if exc.errno != errno.EEXIST:
                    raise
            uid = pwd.getpwnam(KEYSTONE_USER).pw_uid
            gid = grp.getgrnam(KEYSTONE_GROUP).gr_gid
            os.chown(FERNET_DIR, uid, gid)

        for (key, value) in data.items():
            with open(FERNET_DIR + key, 'w') as f:
                decoded_value = base64.b64decode(value).decode()
                f.write(decoded_value)
                LOG.debug("Key %s: %s", key, decoded_value)
        LOG.info("%s keys were written", len(data))


    def execute_command(cmd):
        LOG.info("Executing 'keystone-manage %s --keystone-user=%s "
                 "--keystone-group=%s' command.",
                 cmd, KEYSTONE_USER, KEYSTONE_GROUP)
        subprocess.call(['keystone-manage', cmd,  #nosec
                         '--keystone-user=%s' % KEYSTONE_USER,
                         '--keystone-group=%s' % KEYSTONE_GROUP])

    def main():
        parser = argparse.ArgumentParser()
        parser.add_argument('command', choices=['fernet_setup', 'fernet_rotate',
                                                'credential_setup',
                                                'credential_rotate'])
        args = parser.parse_args()

        is_credential = args.command.startswith('credential')

        SECRET_NAME = ('keystone-credential-keys' if is_credential else
                       'keystone-fernet-keys')

        read_kube_config()
        secret = get_secret_definition(SECRET_NAME)
        if not secret:
            LOG.error("Secret '%s' does not exist.", SECRET_NAME)
            sys.exit(1)

        if args.command in ('fernet_rotate', 'credential_rotate'):
            LOG.info("Copying existing %s keys from secret '%s' to %s.",
                     'credential' if is_credential else 'fernet', SECRET_NAME,
                     FERNET_DIR)
            write_to_files(secret['data'])

        if args.command in ('credential_setup', 'fernet_setup'):
            if secret.get('data', False):
                LOG.info('Keys already exist, skipping setup...')
                sys.exit(0)

        execute_command(args.command)

        LOG.info("Updating data for '%s' secret.", SECRET_NAME)
        updated_keys = get_keys_data()
        secret['data'] = updated_keys
        if not update_secret(SECRET_NAME, secret):
            sys.exit(1)
        LOG.info("%s fernet keys have been placed to secret '%s'",
                 len(updated_keys), SECRET_NAME)
        LOG.debug("Placed keys: %s", updated_keys)
        LOG.info("%s keys %s has been completed",
                 "Credential" if is_credential else 'Fernet',
                 "rotation" if args.command.endswith('_rotate') else "generation")

        if args.command == 'credential_rotate':
            # `credential_rotate` needs doing `credential_migrate` as well once all
            # of the nodes have the new keys. So we'll sleep configurable amount of
            # time to make sure k8s reloads the secrets in all pods and then
            # execute `credential_migrate`.

            migrate_wait = int(os.getenv('KEYSTONE_CREDENTIAL_MIGRATE_WAIT', "60"))
            LOG.info("Waiting %d seconds to execute `credential_migrate`.",
                     migrate_wait)
            time.sleep(migrate_wait)

            execute_command('credential_migrate')

    if __name__ == "__main__":
        main()
  keystone-api.sh: |
    #!/bin/bash



    set -ex

    COMMAND="${@:-start}"

    function start () {

      for KEYSTONE_WSGI_SCRIPT in keystone-wsgi-public; do
        cp -a $(type -p ${KEYSTONE_WSGI_SCRIPT}) /var/www/cgi-bin/keystone/
      done

      if [ -f /etc/apache2/envvars ]; then
         # Loading Apache2 ENV variables
         source /etc/apache2/envvars
      fi

      if [ -f /var/run/apache2/apache2.pid ]; then
         # Remove the stale pid for debian/ubuntu images
         rm -f /var/run/apache2/apache2.pid
      fi

      # Start Apache2
      exec apache2 -DFOREGROUND
    }

    function stop () {
      if [ -f /etc/apache2/envvars ]; then
         # Loading Apache2 ENV variables
         source /etc/apache2/envvars
      fi
      apache2 -k graceful-stop
    }

    $COMMAND
  ks-user.sh: |
    #!/bin/bash

    # Copyright 2017 Pete Birley
    #
    # 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.

    set -ex

    shopt -s nocasematch

    if [[ "${SERVICE_OS_PROJECT_DOMAIN_NAME}" == "Default" ]]
    then
      PROJECT_DOMAIN_ID="default"
    else
      # Manage project domain
      PROJECT_DOMAIN_ID=$(openstack domain create --or-show --enable -f value -c id \
        --description="Domain for ${SERVICE_OS_REGION_NAME}/${SERVICE_OS_PROJECT_DOMAIN_NAME}" \
        "${SERVICE_OS_PROJECT_DOMAIN_NAME}")
    fi

    if [[ "${SERVICE_OS_USER_DOMAIN_NAME}" == "Default" ]]
    then
      USER_DOMAIN_ID="default"
    else
      # Manage user domain
      USER_DOMAIN_ID=$(openstack domain create --or-show --enable -f value -c id \
        --description="Domain for ${SERVICE_OS_REGION_NAME}/${SERVICE_OS_USER_DOMAIN_NAME}" \
        "${SERVICE_OS_USER_DOMAIN_NAME}")
    fi

    shopt -u nocasematch

    # Manage user project
    USER_PROJECT_DESC="Service Project for ${SERVICE_OS_REGION_NAME}/${SERVICE_OS_PROJECT_DOMAIN_NAME}"
    USER_PROJECT_ID=$(openstack project create --or-show --enable -f value -c id \
        --domain="${PROJECT_DOMAIN_ID}" \
        --description="${USER_PROJECT_DESC}" \
        "${SERVICE_OS_PROJECT_NAME}");

    # Manage user
    USER_DESC="Service User for ${SERVICE_OS_REGION_NAME}/${SERVICE_OS_USER_DOMAIN_NAME}/${SERVICE_OS_SERVICE_NAME}"
    USER_ID=$(openstack user create --or-show --enable -f value -c id \
        --domain="${USER_DOMAIN_ID}" \
        --project-domain="${PROJECT_DOMAIN_ID}" \
        --project="${USER_PROJECT_ID}" \
        --description="${USER_DESC}" \
        "${SERVICE_OS_USERNAME}");

    # Manage user password (we do this in a seperate step to ensure the password is updated if required)
    set +x
    echo "Setting user password via: openstack user set --password=xxxxxxx ${USER_ID}"
    openstack user set --password="${SERVICE_OS_PASSWORD}" "${USER_ID}"
    set -x

    function ks_assign_user_role () {
      if [[ "$SERVICE_OS_ROLE" == "admin" ]]
      then
        USER_ROLE_ID="$SERVICE_OS_ROLE"
      else
        USER_ROLE_ID=$(openstack role create --or-show -f value -c id "${SERVICE_OS_ROLE}");
      fi

      # Manage user role assignment
      openstack role add \
          --user="${USER_ID}" \
          --user-domain="${USER_DOMAIN_ID}" \
          --project-domain="${PROJECT_DOMAIN_ID}" \
          --project="${USER_PROJECT_ID}" \
          "${USER_ROLE_ID}"
    }

    # Manage user service role
    IFS=','
    for SERVICE_OS_ROLE in ${SERVICE_OS_ROLES}; do
      ks_assign_user_role
    done

    # Manage user member role
    : ${MEMBER_OS_ROLE:="member"}
    export USER_ROLE_ID=$(openstack role create --or-show -f value -c id \
        "${MEMBER_OS_ROLE}");
    ks_assign_user_role
  rabbit-init.sh: |
    #!/bin/bash
    set -e
    # Extract connection details
    RABBIT_HOSTNAME=$(echo "${RABBITMQ_ADMIN_CONNECTION}" | \
      awk -F'[@]' '{print $2}' | \
      awk -F'[:/]' '{print $1}')
    RABBIT_PORT=$(echo "${RABBITMQ_ADMIN_CONNECTION}" | \
      awk -F'[@]' '{print $2}' | \
      awk -F'[:/]' '{print $2}')

    # Extract Admin User creadential
    RABBITMQ_ADMIN_USERNAME=$(echo "${RABBITMQ_ADMIN_CONNECTION}" | \
      awk -F'[@]' '{print $1}' | \
      awk -F'[//:]' '{print $4}')
    RABBITMQ_ADMIN_PASSWORD=$(echo "${RABBITMQ_ADMIN_CONNECTION}" | \
      awk -F'[@]' '{print $1}' | \
      awk -F'[//:]' '{print $5}' | \
      sed 's/%/\\x/g' | \
      xargs -0 printf "%b")

    # Extract User creadential
    RABBITMQ_USERNAME=$(echo "${RABBITMQ_USER_CONNECTION}" | \
      awk -F'[@]' '{print $1}' | \
      awk -F'[//:]' '{print $4}')
    RABBITMQ_PASSWORD=$(echo "${RABBITMQ_USER_CONNECTION}" | \
      awk -F'[@]' '{print $1}' | \
      awk -F'[//:]' '{print $5}' | \
      sed 's/%/\\x/g' | \
      xargs -0 printf "%b")

    # Extract User vHost
    RABBITMQ_VHOST=$(echo "${RABBITMQ_USER_CONNECTION}" | \
      awk -F'[@]' '{print $2}' | \
      awk -F'[:/]' '{print $3}')
    # Resolve vHost to / if no value is set
    RABBITMQ_VHOST="${RABBITMQ_VHOST:-/}"

    function rabbitmqadmin_cli () {
      if [ -n "$RABBITMQ_X509" ]
      then
        rabbitmqadmin \
          --ssl \
          --ssl-disable-hostname-verification \
          --ssl-ca-cert-file="${USER_CERT_PATH}/ca.crt" \
          --ssl-cert-file="${USER_CERT_PATH}/tls.crt" \
          --ssl-key-file="${USER_CERT_PATH}/tls.key" \
          --host="${RABBIT_HOSTNAME}" \
          --port="${RABBIT_PORT}" \
          --username="${RABBITMQ_ADMIN_USERNAME}" \
          --password="${RABBITMQ_ADMIN_PASSWORD}" \
          ${@}
      else
        rabbitmqadmin \
          --host="${RABBIT_HOSTNAME}" \
          --port="${RABBIT_PORT}" \
          --username="${RABBITMQ_ADMIN_USERNAME}" \
          --password="${RABBITMQ_ADMIN_PASSWORD}" \
          ${@}
      fi
    }

    echo "Managing: User: ${RABBITMQ_USERNAME}"
    rabbitmqadmin_cli \
      declare user \
      name="${RABBITMQ_USERNAME}" \
      password="${RABBITMQ_PASSWORD}" \
      tags="user"

    echo "Deleting Guest User"
    rabbitmqadmin_cli \
      delete user \
      name="guest" || true

    if [ "${RABBITMQ_VHOST}" != "/" ]
    then
      echo "Managing: vHost: ${RABBITMQ_VHOST}"
      rabbitmqadmin_cli \
        declare vhost \
        name="${RABBITMQ_VHOST}"
    else
      echo "Skipping root vHost declaration: vHost: ${RABBITMQ_VHOST}"
    fi

    echo "Managing: Permissions: ${RABBITMQ_USERNAME} on ${RABBITMQ_VHOST}"
    rabbitmqadmin_cli \
      declare permission \
      vhost="${RABBITMQ_VHOST}" \
      user="${RABBITMQ_USERNAME}" \
      configure=".*" \
      write=".*" \
      read=".*"

    if [ ! -z "$RABBITMQ_AUXILIARY_CONFIGURATION" ]
    then
      echo "Applying additional configuration"
      echo "${RABBITMQ_AUXILIARY_CONFIGURATION}" > /tmp/rmq_definitions.json
      rabbitmqadmin_cli import /tmp/rmq_definitions.json
    fi
  rally-test.sh: "#!/bin/bash\nset -ex\n\n: \"${RALLY_ENV_NAME:=\"openstack-helm\"}\"\n:
    \"${OS_INTERFACE:=\"public\"}\"\n: \"${RALLY_CLEANUP:=\"true\"}\"\n\nif [ \"x$RALLY_CLEANUP\"
    == \"xtrue\" ]; then\n  function rally_cleanup {\n    openstack user delete \\\n
    \       --domain=\"${SERVICE_OS_USER_DOMAIN_NAME}\" \\\n        \"${SERVICE_OS_USERNAME}\"\n
    \   \n  }\n  trap rally_cleanup EXIT\nfi\n\nfunction create_or_update_db () {\n
    \ revisionResults=$(rally db revision)\n  if [ $revisionResults = \"None\"  ]\n
    \ then\n    rally db create\n  else\n    rally db upgrade\n  fi\n}\n\ncreate_or_update_db\n\ncat
    > /tmp/rally-config.json << EOF\n{\n    \"openstack\": {\n        \"auth_url\":
    \"${OS_AUTH_URL}\",\n        \"region_name\": \"${OS_REGION_NAME}\",\n        \"endpoint_type\":
    \"${OS_INTERFACE}\",\n        \"admin\": {\n            \"username\": \"${OS_USERNAME}\",\n
    \           \"password\": \"${OS_PASSWORD}\",\n            \"user_domain_name\":
    \"${OS_USER_DOMAIN_NAME}\",\n            \"project_name\": \"${OS_PROJECT_NAME}\",\n
    \           \"project_domain_name\": \"${OS_PROJECT_DOMAIN_NAME}\"\n        },\n
    \       \"users\": [\n            {\n                \"username\": \"${SERVICE_OS_USERNAME}\",\n
    \               \"password\": \"${SERVICE_OS_PASSWORD}\",\n                \"project_name\":
    \"${SERVICE_OS_PROJECT_NAME}\",\n                \"user_domain_name\": \"${SERVICE_OS_USER_DOMAIN_NAME}\",\n
    \               \"project_domain_name\": \"${SERVICE_OS_PROJECT_DOMAIN_NAME}\"\n
    \           }\n        ],\n        \"https_insecure\": false,\n        \"https_cacert\":
    \"${OS_CACERT}\"\n    }\n}\nEOF\nrally deployment create --file /tmp/rally-config.json
    --name \"${RALLY_ENV_NAME}\"\nrm -f /tmp/rally-config.json\nrally deployment use
    \"${RALLY_ENV_NAME}\"\nrally deployment check\nrally task validate /etc/rally/rally_tests.yaml\nrally
    task start /etc/rally/rally_tests.yaml\nrally task sla-check\nrally env cleanup\nrally
    deployment destroy --deployment \"${RALLY_ENV_NAME}\"\n"
kind: ConfigMap
metadata:
  annotations:
    meta.helm.sh/release-name: keystone
    meta.helm.sh/release-namespace: openstack
  creationTimestamp: "2026-04-20T12:03:37Z"
  labels:
    app.kubernetes.io/managed-by: Helm
  name: keystone-bin
  namespace: openstack
  resourceVersion: "5453"
  uid: 309de8c6-0402-4595-91ea-ed942ba0e52d
