heat/bin/heat-keystone-setup-domain
Sharmin Choksey 1745a9b950 Fixes heat-keystone-setup-domain authentication failures with v3
With keystone v3 configured, attempting to create a heat domain
and heat user fails with authentication errors

Change-Id: Ieb1cb7a62b32e842d80020b4ab2870ef1394ba86
Closes-Bug: #1667795
2017-03-14 07:00:33 -07:00

167 lines
6.1 KiB
Python
Executable File

#!/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()