kolla-ansible/kolla/cmd/genpwd.py
Shaun Smekel 1c68ae389b Add full support for fernet
This addresses the ansible aspects of fernet key bootstrapping as
well as distributed key rotation.

- Bootstrapping is handled in the same way as keystone bootstrap.
- A new keystone-fernet and keystone-ssh container is created to allow
  the nodes to communicate with each other (taken from nova-ssh).
- The keystone-fernet is a keystone container with crontab installed.
  This will handle key rotations through keystone-manage and trigger
  an rsync to push new tokens to other nodes.
- Key rotation is setup to be balanced across the keystone nodes using
  a round-robbin style. This ensures that any node failures will not
  stop the keys from rotating. This is configured by a desired token
  expiration time which then determines the cron scheduling for each
  node as well as the number of fernet tokens in rotation.
- Ability for recovered node to resync with the cluster. When a node
  starts it will run sanity checks to ensure that its fernet tokens
  are not stale. If they are it will rsync with other nodes to ensure
  its tokens are up to date.

The Docker component is implemented in:
  https://review.openstack.org/#/c/349366

Change-Id: I15052c25a1d1149d364236f10ced2e2346119738
Implements: blueprint keystone-fernet-token
2016-08-25 20:08:22 +10:00

85 lines
2.5 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 argparse
import os
import random
import string
import uuid
import yaml
from Crypto.PublicKey import RSA
def generate_RSA(bits=2048):
new_key = RSA.generate(bits, os.urandom)
private_key = new_key.exportKey("PEM")
public_key = new_key.publickey().exportKey("OpenSSH")
return private_key, public_key
def main():
parser = argparse.ArgumentParser()
parser.add_argument(
'-p', '--passwords', type=str,
default=os.path.abspath('/etc/kolla/passwords.yml'),
help=('Path to the passwords yml file'))
args = parser.parse_args()
passwords_file = os.path.expanduser(args.passwords)
# These keys should be random uuids
uuid_keys = ['ceph_cluster_fsid', 'rbd_secret_uuid']
# SSH key pair
ssh_keys = ['kolla_ssh_key', 'nova_ssh_key', 'keystone_ssh_key']
# If these keys are None, leave them as None
blank_keys = ['docker_registry_password']
# length of password
length = 40
with open(passwords_file, 'r') as f:
passwords = yaml.load(f.read())
for k, v in passwords.items():
if (k in ssh_keys and
(v is None
or v.get('public_key') is None
and v.get('private_key') is None)):
private_key, public_key = generate_RSA()
passwords[k] = {
'private_key': private_key,
'public_key': public_key
}
continue
if v is None:
if k in blank_keys and v is None:
continue
if k in uuid_keys:
passwords[k] = str(uuid.uuid4())
else:
passwords[k] = ''.join([
random.SystemRandom().choice(
string.ascii_letters + string.digits)
for n in range(length)
])
with open(passwords_file, 'w') as f:
f.write(yaml.dump(passwords, default_flow_style=False))
if __name__ == '__main__':
main()