#!/usr/bin/env python # # 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 os import sys import keystoneclient.exceptions as kc_exception from keystoneclient.v3 import client from oslo_config import cfg from oslo_log import log as logging from heat.common.i18n import _ from heat import version logger = logging.getLogger(__name__) DEBUG = False USERNAME = os.environ.get('OS_USERNAME') PASSWORD = os.environ.get('OS_PASSWORD') AUTH_URL = os.environ.get('OS_AUTH_URL', '').replace('v2.0', 'v3') PROJECT_NAME = os.environ.get('OS_PROJECT_NAME') USER_DOMAIN_NAME = os.environ.get('OS_USER_DOMAIN_NAME') PROJECT_DOMAIN_NAME = os.environ.get('OS_PROJECT_DOMAIN_NAME') opts = [ cfg.StrOpt('stack-user-domain-name', default="heat", help=_("Name of domain to create for stack users.")), cfg.StrOpt('stack-domain-admin', default="heat_stack_admin", help=_("Keystone username with roles sufficient to manage users" " and projects in the stack-user-domain")), cfg.StrOpt('stack-domain-admin-password', secret=True, help=_("Password to set for stack-domain-admin")), cfg.BoolOpt('insecure', default=False, help=_("If set, then the server's certificate will not " "be verified.")), cfg.StrOpt('os-cacert', help=_('Optional CA cert file to use in SSL connections.')), cfg.StrOpt('os-cert', help=_('Optional PEM-formatted certificate chain file.')), cfg.StrOpt('os-key', help=_('Optional PEM-formatted file that contains the ' 'private key.')), ] # Setup logging before registering additional options logging.register_options(cfg.CONF) extra_log_level_defaults = ['urllib3.connectionpool=WARNING'] logging.set_defaults( logging_context_format_string="%(levelname)s (%(module)s:" "%(lineno)d) %(message)s", default_log_levels=(logging.get_default_log_levels() + extra_log_level_defaults)) logging.setup(cfg.CONF, 'heat-keystone-setup-domain', version.version_info.version_string()) # Register additional options cfg.CONF.register_cli_opts(opts) cfg.CONF(sys.argv[1:], project='heat', prog='heat-keystone-setup-domain', version=version.version_info.version_string()) HEAT_DOMAIN_NAME = os.environ.get( 'HEAT_DOMAIN', cfg.CONF.stack_user_domain_name) HEAT_DOMAIN_ADMIN = os.environ.get('HEAT_DOMAIN_ADMIN', cfg.CONF.stack_domain_admin) HEAT_DOMAIN_PASSWORD = os.environ.get('HEAT_DOMAIN_PASSWORD', cfg.CONF.stack_domain_admin_password) HEAT_DOMAIN_DESCRIPTION = 'Contains users and projects created by heat' CACERT = os.environ.get('OS_CACERT', cfg.CONF.os_cacert) CERT = os.environ.get('OS_CERT', cfg.CONF.os_cert) KEY = os.environ.get('OS_KEY', cfg.CONF.os_key) insecure = cfg.CONF.insecure def main(): client_kwargs = { 'debug': DEBUG, 'username': USERNAME, 'password': PASSWORD, 'auth_url': AUTH_URL, 'endpoint': AUTH_URL, 'project_name': PROJECT_NAME, 'user_domain_name': USER_DOMAIN_NAME, 'project_domain_name': PROJECT_DOMAIN_NAME } if insecure: client_kwargs['verify'] = False else: client_kwargs.update({ 'cacert': CACERT, 'cert': CERT, 'key': KEY }) c = client.Client(**client_kwargs) c.authenticate() # Create the heat domain logger.info("Creating domain %s" % HEAT_DOMAIN_NAME) try: heat_domain = c.domains.create(name=HEAT_DOMAIN_NAME, description=HEAT_DOMAIN_DESCRIPTION) except kc_exception.Conflict: logger.warning("Domain %s already exists" % HEAT_DOMAIN_NAME) heat_domain = c.domains.list(name=HEAT_DOMAIN_NAME)[0] if heat_domain.name != HEAT_DOMAIN_NAME: logger.error("Unexpected filtered list response, please upgrade " "keystoneclient to >= 0.5") sys.exit(1) except kc_exception.Forbidden: logger.error("User '%s' is not authorized to perform this " "operation, please try with other OS_USERNAME setting." % USERNAME) sys.exit(1) # Create heat domain admin user if not HEAT_DOMAIN_PASSWORD: logger.error("Must export HEAT_DOMAIN_PASSWORD or use" " --stack-domain-admin-password") sys.exit(1) try: domain_admin = c.users.create(name=HEAT_DOMAIN_ADMIN, password=HEAT_DOMAIN_PASSWORD, domain=heat_domain, description="Heat domain admin") except kc_exception.Conflict: logger.warning("User %s already exists" % HEAT_DOMAIN_ADMIN) domain_admin = c.users.list(name=HEAT_DOMAIN_ADMIN, domain=heat_domain)[0] # Make the user a domain admin roles_list = c.roles.list() # FIXME(shardy): seems filtering roles by name currently doesn't work admin_role = [r for r in roles_list if r.name == 'admin'][0] c.roles.grant(role=admin_role, user=domain_admin, domain=heat_domain) print("\nPlease update your heat.conf with the following in [DEFAULT]\n") print("stack_user_domain_id=%s" % heat_domain.id) print("stack_domain_admin=%s" % HEAT_DOMAIN_ADMIN) print("stack_domain_admin_password=%s" % HEAT_DOMAIN_PASSWORD) if __name__ == "__main__": main()