#cloud-config mounts: - [ /dev/disk/by-label/config-2, /mnt/config ] packages: - python - python-requests write_files: - path: /root/setup-ssh.py permissions: '0700' owner: root:root content: | #!/usr/bin/env python print 'Importing packages' import json import requests import os import uuid def getVendordataFromConfigDrive(): path = '/mnt/config/openstack/latest/vendor_data2.json' with open(path, 'r') as f: json_string = f.read() return json.loads(json_string) def getInstanceAndProjectIdFromConfigDrive(): path = '/mnt/config/openstack/latest/meta_data.json' with open(path, 'r') as f: json_string = f.read() metadata = json.loads(json_string) assert 'uuid' in metadata assert 'project_id' in metadata return str(uuid.UUID(metadata['uuid'], version=4)), str(uuid.UUID(metadata['project_id'], version=4)) print 'Getting vendordata from ConfigDrive' vendordata = getVendordataFromConfigDrive() print 'Getting instance and project IDs' instance_id, project_id = getInstanceAndProjectIdFromConfigDrive() assert 'tatu' in vendordata tatu = vendordata['tatu'] assert 'token' in tatu assert 'auth_pub_key_user' in tatu assert 'principals' in tatu principals = tatu['principals'].split(',') with open('/etc/ssh/ssh_host_rsa_key.pub', 'r') as f: host_key_pub = f.read() server = 'http://172.24.4.1:18322' hostcert_request = { 'token_id': tatu['token'], 'host_id': instance_id, 'pub_key': host_key_pub } print 'Request the host certificate.' response = requests.post( # Hard-coded SSHaaS API address will only work for devstack and requires # routing and SNAT or DNAT. # This eventually needs to be either: # 1) 169.254.169.254 if there's a SSHaaS-proxy; OR # 2) the real address of the API, possibly supplied in the vendordata and # still requiring routing and SNAT or DNAT. server + '/noauth/hostcerts', data=json.dumps(hostcert_request) ) print 'Got the host certificate: {}'.format(response.content) assert response.status_code == 201 assert 'location' in response.headers location = response.headers['location'] # No need to GET the host cert - it's returned in the POST #response = requests.get(server + location) hostcert = json.loads(response.content) assert 'host_id' in hostcert assert hostcert['host_id'] == instance_id assert 'fingerprint' in hostcert assert 'auth_id' in hostcert auth_id = str(uuid.UUID(hostcert['auth_id'], version=4)) assert auth_id == project_id assert 'cert' in hostcert print 'Begin writing files.' # Write the host's certificate with open('/etc/ssh/ssh_host_rsa_key-cert.pub', 'w') as f: f.write(hostcert['cert']) # Write the authorized principals file os.mkdir('/etc/ssh/auth_principals') with open('/etc/ssh/auth_principals/root', 'w') as f: for p in principals: f.write(p + os.linesep) # Write the User CA public key file with open('/etc/ssh/ca_user.pub', 'w') as f: f.write(tatu['auth_pub_key_user']) print 'All tasks completed.' - path: /root/manage-revoked_keys.py permissions: '0700' owner: root:root content: | #!/usr/bin/env python import base64 import json import requests import uuid path = '/mnt/config/openstack/latest/meta_data.json' with open(path, 'r') as f: json_string = f.read() metadata = json.loads(json_string) auth_id = str(uuid.UUID(metadata['project_id'], version=4)) server = 'http://172.24.4.1:18322' response = requests.get(server + '/noauth/revokeduserkeys/' + auth_id) assert response.status_code == 200 body = json.loads(response.content) assert 'revoked_keys_data' in body with open('/etc/ssh/revoked-keys', 'w') as f: f.write(base64.b64decode(body['revoked_keys_data'])) runcmd: - dnf install -y python python-requests - python /root/setup-ssh.py > /var/log/setup-ssh.log 2>&1 - sed -i -e '$aTrustedUserCAKeys /etc/ssh/ca_user.pub' /etc/ssh/sshd_config - sed -i -e '$aAuthorizedPrincipalsFile /etc/ssh/auth_principals/%u' /etc/ssh/sshd_config - sed -i -e '$aHostCertificate /etc/ssh/ssh_host_rsa_key-cert.pub' /etc/ssh/sshd_config - python /root/manage-revoked-keys.py >> /var/log/setup-ssh.log 2>&1 - sed -i -e '$aRevokedKeys /etc/ssh/revoked-keys' /etc/ssh/sshd_config - systemctl restart sshd