# Copyright 2016 Red Hat, Inc. # All Rights Reserved. # # 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 base64 import hashlib import hmac import logging import os import paramiko import struct import time import uuid import passlib.pwd import six from tripleo_common import constants _MIN_PASSWORD_SIZE = 25 KEYSTONE_FERNET_REPO = '/etc/keystone/fernet-keys/' LOG = logging.getLogger(__name__) def generate_passwords(mistralclient=None, stack_env=None, rotate_passwords=False): """Create the passwords needed for deploying OpenStack via t-h-t. This will create the set of passwords required by the undercloud and overcloud installers that use tripleo-heat-templates and return them as a dict. The mistralclient is optional and only used to obtain the previously stored SnmpdReadonlyUserPassword supplied by the undercloud to the overcloud deployment. """ passwords = {} for name in constants.PASSWORD_PARAMETER_NAMES: # Support users upgrading from Mitaka or otherwise creating a plan for # a Heat stack that already exists. if (stack_env and name in stack_env.get('parameter_defaults', {}) and not rotate_passwords): passwords[name] = stack_env['parameter_defaults'][name] elif name.startswith("Ceph"): if name == "CephClusterFSID": # The FSID must be a UUID passwords[name] = six.text_type(uuid.uuid1()) else: # CephX keys aren't random strings passwords[name] = create_cephx_key() # Since by default passlib.pwd.genword uses all digits and ascii upper # & lowercase letters, it provides ~5.95 entropy per character. # Make the length of the default authkey 4096 bytes, which should give # us ~24000 bits of randomness elif name.startswith("PacemakerRemoteAuthkey"): passwords[name] = passlib.pwd.genword( length=4096) # The underclouds SnmpdReadonlyUserPassword is stored in a mistral env # for the overcloud. elif mistralclient and name == 'SnmpdReadonlyUserPassword': passwords[name] = get_snmpd_readonly_user_password(mistralclient) elif name in ('KeystoneCredential0', 'KeystoneCredential1', 'KeystoneFernetKey0', 'KeystoneFernetKey1'): passwords[name] = create_keystone_credential() elif name == 'KeystoneFernetKeys': passwords[name] = create_fernet_keys_repo_structure_and_keys() elif name == 'MigrationSshKey': passwords[name] = create_ssh_keypair() elif name == 'BarbicanSimpleCryptoKek': passwords[name] = create_keystone_credential() elif name.startswith("MysqlRootPassword"): passwords[name] = passlib.pwd.genword(length=10) elif name.startswith("RabbitCookie"): passwords[name] = passlib.pwd.genword(length=20) elif name.startswith("PcsdPassword"): passwords[name] = passlib.pwd.genword(length=16) elif name.startswith("HorizonSecret"): passwords[name] = passlib.pwd.genword(length=10) elif name.startswith("HeatAuthEncryptionKey"): passwords[name] = passlib.pwd.genword(length=32) elif name.startswith("OctaviaServerCertsKeyPassphrase"): passwords[name] = passlib.pwd.genword(length=32) elif name.startswith("DesignateRndcKey"): passwords[name] = create_rndc_key_secret() else: passwords[name] = passlib.pwd.genword(length=_MIN_PASSWORD_SIZE) return passwords def create_fernet_keys_repo_structure_and_keys(): return { KEYSTONE_FERNET_REPO + '0': { 'content': create_keystone_credential()}, KEYSTONE_FERNET_REPO + '1': { 'content': create_keystone_credential()} } def create_cephx_key(): # NOTE(gfidente): Taken from # https://github.com/ceph/ceph-deploy/blob/master/ceph_deploy/new.py#L21 key = os.urandom(16) header = struct.pack("