216 lines
7.3 KiB
Python
Raw Normal View History

2014-08-26 18:08:15 -05:00
#!/usr/bin/env python
# Copyright 2014, Rackspace US, Inc.
#
# 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.
#
# (c) 2014, Kevin Carter <kevin.carter@rackspace.com>
import argparse
import datetime
import hashlib
import os
import random
import tarfile
Add Ceph/RBD support to playbooks Currently the playbooks do not allow Ceph to be configured as a backend for Cinder, Glance or Nova. This commit adds a new role called ceph_client to do the required configuration of the hosts and updates the service roles to include the required configuration file changes. This commit requires that a Ceph cluster already exists and does not make any changes to that cluster. ceph_client role, run on the OpenStack service hosts - configures the Ceph apt repo - installs any required Ceph dependencies - copies the ceph.conf file and appropriate keyring file to /etc/ceph - creates the necessary libvirt secrets os_glance role glance-api.conf will set the following variables for Ceph: - [DEFAULT]/show_image_direct_url - [glance_store]/stores - [glance_store]/rbd_store_pool - [glance_store]/rbd_store_user - [glance_store]/rbd_store_ceph_conf - [glance_store]/rbd_store_chunk_size os_nova role nova.conf will set the following variables for Ceph: - [libvirt]/rbd_user - [libvirt]/rbd_secret_uuid - [libvirt]/images_type - [libvirt]/images_rbd_pool - [libvirt]/images_rbd_ceph_conf - [libvirt]/inject_password - [libvirt]/inject_key - [libvirt]/inject_partition - [libvirt]/live_migration_flag os_cinder is not updated because ceph is defined as a backend and that is generated from a dictionary of the config, for an example backend config, see etc/openstack_deploy/openstack_user_config.yml.example pw-token-gen.py is updated so that variables ending in uuid are assigned a UUID. DocImpact Implements: blueprint ceph-block-devices Closes-Bug: #1455238 Change-Id: Ie484ce0bbb93adc53c30be32f291aa5058b20028
2015-05-07 16:41:18 +02:00
import uuid
2014-08-26 18:08:15 -05:00
from Crypto import Random
try:
import yaml
except ImportError:
raise SystemExit('Missing Dependency, "PyYAML"')
class CredentialGenerator(object):
"""Credential generator class.
This class is simply a method to generate random secrets. This class will
NOT encrypt values rather it creates the values which will be used as
secrets within an application. The credential generator will return
strings in various sizes based on the requested secret type.
There are four secret types that can be used within the class; `password`,
`token`, 'secret', and `key`. These types return variable lengths of data.
password: 16 - 64 character string
secret: 16 - 64 character string
token: 64 - 72 character string
key: 24, or 32 character string (Needs to be AES compatible)
Usage:
>>> generator = CredentialGenerator()
>>> token = generator.generator('token')
"""
def generator(self, pw_type):
"""Generate new secret string.
The generator method will check for a known method type and if found
generates a hashed string which is then routed to the appropriate
method.
:param pw_type: ``str`` Type of secret to generate.
:returns: ``str``
"""
if hasattr(self, '_%s_gen' % pw_type):
encoded_bytes = self._encode_bytes()
func = getattr(self, '_%s_gen' % pw_type)
return func(encoded_bytes=encoded_bytes)
else:
Add Ceph/RBD support to playbooks Currently the playbooks do not allow Ceph to be configured as a backend for Cinder, Glance or Nova. This commit adds a new role called ceph_client to do the required configuration of the hosts and updates the service roles to include the required configuration file changes. This commit requires that a Ceph cluster already exists and does not make any changes to that cluster. ceph_client role, run on the OpenStack service hosts - configures the Ceph apt repo - installs any required Ceph dependencies - copies the ceph.conf file and appropriate keyring file to /etc/ceph - creates the necessary libvirt secrets os_glance role glance-api.conf will set the following variables for Ceph: - [DEFAULT]/show_image_direct_url - [glance_store]/stores - [glance_store]/rbd_store_pool - [glance_store]/rbd_store_user - [glance_store]/rbd_store_ceph_conf - [glance_store]/rbd_store_chunk_size os_nova role nova.conf will set the following variables for Ceph: - [libvirt]/rbd_user - [libvirt]/rbd_secret_uuid - [libvirt]/images_type - [libvirt]/images_rbd_pool - [libvirt]/images_rbd_ceph_conf - [libvirt]/inject_password - [libvirt]/inject_key - [libvirt]/inject_partition - [libvirt]/live_migration_flag os_cinder is not updated because ceph is defined as a backend and that is generated from a dictionary of the config, for an example backend config, see etc/openstack_deploy/openstack_user_config.yml.example pw-token-gen.py is updated so that variables ending in uuid are assigned a UUID. DocImpact Implements: blueprint ceph-block-devices Closes-Bug: #1455238 Change-Id: Ie484ce0bbb93adc53c30be32f291aa5058b20028
2015-05-07 16:41:18 +02:00
raise SystemExit('Unknown secret type passed. [ %s ]' % pw_type)
2014-08-26 18:08:15 -05:00
@staticmethod
def _random_bytes():
"""Returns 1024 random bytes of data."""
return Random.get_random_bytes(1024)
def _encode_bytes(self):
"""Builds random strings based on random data.
`_encode_bytes` will ensure that there's never an opportunity for
duplicate data. Once the bytes are generated, they are hashed using
SHA512 and the returned as a **hex** digest.
"""
random_bytes = self._random_bytes()
hash_obj = hashlib.sha512(random_bytes)
return hash_obj.hexdigest()
def _password_gen(self, encoded_bytes):
"""Returns ``str`` with a length between 16 and 64.
:param encoded_bytes: ``str`` must be at least 64 charters long
"""
return encoded_bytes[:random.randrange(16, 64)]
def _token_gen(self, encoded_bytes):
"""Returns ``str`` with a length between 48 and 64.
:param encoded_bytes: ``str`` must be at least 72 charters long
"""
return encoded_bytes[:random.randrange(64, 72)]
def _key_gen(self, encoded_bytes):
"""Returns ``str`` with a length of 24 or 32.
Length restriction are required for key type secrets because of
requirements in AES.
:param encoded_bytes: ``str`` must be at least 32 charters long
"""
return encoded_bytes[:random.choice([24, 32])]
def args():
"""Setup argument Parsing."""
parser = argparse.ArgumentParser(
usage='%(prog)s',
Remove and/or rename Rackspace related bits This patch removes and/or renames anything that is Rackspace specific from the playbooks, roles and variables. It also removes items which appear to be orphaned/unused and flattens the playbooks into a single directory in order to better match ansible best practise (and remove some horrible fiddles we were doing). The following have been removed due to RAX/RPC naming or RAX/RPC specific usage: - playbooks/monitoring - playbooks/rax* - playbooks/rpc* - roles/maas* - roles/rax* - roles/rpc* - scripts/f5-* - scripts/maas* - scripts/rpc* - scripts/*lab* - vars/repo_packages/rackspace* - vars/repo_packages/rax* - vars/repo_packages/rpc* - vars/repo_packages/holland.yml The following have been removed as they are unused: - playbooks/setup/host-network-setup.yml - roles/openssl_pem_request - roles/host_interfaces - scripts/elsa* - ssh/ - vars/repo_packages/turbolift.yml The following directories have been renamed: - etc/rpc_deploy > etc/openstack_deploy - rpc_deployment > playbooks The playbooks have all been moved into a single directory: - rpc_deployment/playbooks/infrastructure/* > playbooks/ - rpc_deployment/playbooks/openstack/* > playbooks/ - rpc_deployment/playbooks/setup/* > playbooks/ The following files have been renamed: - lxc-rpc > lxc-openstack - lxc-rpc.conf > lxc-openstack.conf - rpc_environment > openstack_environment - rpc_release > openstack_release (etc and pip) - rpc_tempest_gate.sh > openstack_tempest_gate.sh - rpc_user_config > openstack_user_config The following variables have been renamed: - rpc_release > openstack_release - rpc_repo_url > openstack_repo_url The following variables have been introduced: - openstack_code_name: The code name of the upstream OpenStack release (eg: Juno) Notable variable/template value changes: - rabbit_cluster_name: rpc > openstack - wsrep_cluster_name: rpc_galera_cluster > openstack_galera_cluster DocImpact Closes-Bug: #1403676 Implements: blueprint rackspace-namesake Change-Id: Ib480fdad500b03c7cb90684aa444da9946ba8032
2015-02-11 16:26:22 +00:00
description='OpenStack Token Password and Key Generator',
2014-08-26 18:08:15 -05:00
epilog='Inventory Generator Licensed "Apache 2.0"'
)
parser.add_argument(
'--file',
help='User defined configuration file',
required=True,
default=None
)
parser.add_argument(
'--regen',
help='Regenerate all passwords',
action='store_true',
default=False
)
return vars(parser.parse_args())
def main():
"""Run the main Application.
This will open a file that was specified on the command line. The file
specified is assumed to be in valid YAML format, which is used in ansible.
When the YAML file will be processed and any key with a null value that
Add Ceph/RBD support to playbooks Currently the playbooks do not allow Ceph to be configured as a backend for Cinder, Glance or Nova. This commit adds a new role called ceph_client to do the required configuration of the hosts and updates the service roles to include the required configuration file changes. This commit requires that a Ceph cluster already exists and does not make any changes to that cluster. ceph_client role, run on the OpenStack service hosts - configures the Ceph apt repo - installs any required Ceph dependencies - copies the ceph.conf file and appropriate keyring file to /etc/ceph - creates the necessary libvirt secrets os_glance role glance-api.conf will set the following variables for Ceph: - [DEFAULT]/show_image_direct_url - [glance_store]/stores - [glance_store]/rbd_store_pool - [glance_store]/rbd_store_user - [glance_store]/rbd_store_ceph_conf - [glance_store]/rbd_store_chunk_size os_nova role nova.conf will set the following variables for Ceph: - [libvirt]/rbd_user - [libvirt]/rbd_secret_uuid - [libvirt]/images_type - [libvirt]/images_rbd_pool - [libvirt]/images_rbd_ceph_conf - [libvirt]/inject_password - [libvirt]/inject_key - [libvirt]/inject_partition - [libvirt]/live_migration_flag os_cinder is not updated because ceph is defined as a backend and that is generated from a dictionary of the config, for an example backend config, see etc/openstack_deploy/openstack_user_config.yml.example pw-token-gen.py is updated so that variables ending in uuid are assigned a UUID. DocImpact Implements: blueprint ceph-block-devices Closes-Bug: #1455238 Change-Id: Ie484ce0bbb93adc53c30be32f291aa5058b20028
2015-05-07 16:41:18 +02:00
ends with 'password', 'token', 'key' or 'uuid' will have a generated
password set as the value.
2014-08-26 18:08:15 -05:00
The main function will create a backup of all changes in the file as a
tarball in the same directory as the file specified.
Command line usage has one required argument and one optional. The
argument ``--file`` is used to specify the file which passwords will be
generated within. The argument ``--regen`` is used to regenerate all
secrets within a file even if they were already set.
"""
all_args = args()
user_vars_file = all_args['file']
user_vars_file = os.path.abspath(
os.path.expanduser(
user_vars_file
)
)
with open(user_vars_file, 'rb') as f:
user_vars = yaml.safe_load(f.read())
if not user_vars:
raise SystemExit(
'FAIL: The variable file provided [ %s ] is empty.'
% user_vars_file
)
2014-08-26 18:08:15 -05:00
changed = False
generator = CredentialGenerator()
for entry, value in user_vars.iteritems():
if value is None or all_args['regen'] is True:
if entry.endswith('password') or entry.endswith('secret'):
changed = True
user_vars[entry] = generator.generator(pw_type='password')
elif entry.endswith('token'):
changed = True
user_vars[entry] = generator.generator(pw_type='token')
elif entry.endswith('key'):
changed = True
user_vars[entry] = generator.generator(pw_type='key')
Add Ceph/RBD support to playbooks Currently the playbooks do not allow Ceph to be configured as a backend for Cinder, Glance or Nova. This commit adds a new role called ceph_client to do the required configuration of the hosts and updates the service roles to include the required configuration file changes. This commit requires that a Ceph cluster already exists and does not make any changes to that cluster. ceph_client role, run on the OpenStack service hosts - configures the Ceph apt repo - installs any required Ceph dependencies - copies the ceph.conf file and appropriate keyring file to /etc/ceph - creates the necessary libvirt secrets os_glance role glance-api.conf will set the following variables for Ceph: - [DEFAULT]/show_image_direct_url - [glance_store]/stores - [glance_store]/rbd_store_pool - [glance_store]/rbd_store_user - [glance_store]/rbd_store_ceph_conf - [glance_store]/rbd_store_chunk_size os_nova role nova.conf will set the following variables for Ceph: - [libvirt]/rbd_user - [libvirt]/rbd_secret_uuid - [libvirt]/images_type - [libvirt]/images_rbd_pool - [libvirt]/images_rbd_ceph_conf - [libvirt]/inject_password - [libvirt]/inject_key - [libvirt]/inject_partition - [libvirt]/live_migration_flag os_cinder is not updated because ceph is defined as a backend and that is generated from a dictionary of the config, for an example backend config, see etc/openstack_deploy/openstack_user_config.yml.example pw-token-gen.py is updated so that variables ending in uuid are assigned a UUID. DocImpact Implements: blueprint ceph-block-devices Closes-Bug: #1455238 Change-Id: Ie484ce0bbb93adc53c30be32f291aa5058b20028
2015-05-07 16:41:18 +02:00
elif entry.endswith('uuid'):
changed = True
user_vars[entry] = str(uuid.uuid4())
elif entry.startswith('swift_hash_path'):
changed = True
2014-08-26 18:08:15 -05:00
user_vars[entry] = generator.generator(pw_type='key')
# If changed is set to True, this will archive the old passwords
if changed is True:
user_vars_tar_file = '%s.tar' % user_vars_file
print('Creating backup file [ %s ]' % user_vars_tar_file)
# Create a tarball if needed
with tarfile.open(user_vars_tar_file, 'a') as tar:
os.chmod(user_vars_tar_file, 0o600)
2014-08-26 18:08:15 -05:00
basename = os.path.basename(user_vars_file)
# Time stamp the password file in UTC
utctime = datetime.datetime.utcnow()
utctime = utctime.strftime('%Y%m%d_%H%M%S')
backup_name = '%s-%s' % (basename, utctime)
tar.add(user_vars_file, arcname=backup_name)
with open(user_vars_file, 'wb') as f:
os.chmod(user_vars_file, 0o600)
2014-08-26 18:08:15 -05:00
f.write(
yaml.safe_dump(
user_vars,
default_flow_style=False,
width=1000
)
)
print('Operation Complete, [ %s ] is ready' % user_vars_file)
if __name__ == '__main__':
main()