Debugged cloud-init script; added script to get user cert.
This commit is contained in:
parent
6075058e1d
commit
d6f4f557ac
@ -1,11 +1,87 @@
|
||||
#cloud-config
|
||||
mounts:
|
||||
- [ /dev/disk/by-label/config-2, /mnt/config ]
|
||||
packages:
|
||||
- python
|
||||
- python-requests
|
||||
write_files:
|
||||
- path: /etc/ssh/auth_principals/ubuntu
|
||||
content: webRoot
|
||||
- path: /etc/ssh/ca_users.pub
|
||||
content: ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDM+YVCEZ4xCqBIGOQOEsGzBzOFS3JNDtPxLAviBMtS4zCwuGmOMvAvatKtPY5E9JMnkhI72faJnwYc4w/pnXf4Sh6AnLfwcOoQ6U16iucfY8tPOeFQhKJokSRdwnfm08QMOHN0xzCA/tL6HHZgPXGHUgTL18kkjv5Zk5Nv1H/ciuOSz24edo94Fu9eIQkK1pUhdejC6hDKdbki/c/3coZU4ZNDdtIpRlGnrUNTaAIq+E0TYEZkgClglTlBQOTvUoRkxEng/U23dfBCCz5DfewfA+6higUil5lIvidbaFjUiTMox38w9fM0wzUUs3o5pC9X/H3BE4mBrfpS9VmYHgll root@Bamboo
|
||||
- path: /root/setup-ssh.py
|
||||
permissions: '0700'
|
||||
owner: root:root
|
||||
content: |
|
||||
import json
|
||||
import requests
|
||||
import os
|
||||
import subprocess
|
||||
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))
|
||||
vendordata = getVendordataFromConfigDrive()
|
||||
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:18321'
|
||||
hostcert_request = {
|
||||
'token_id': tatu['token'],
|
||||
'host_id': instance_id,
|
||||
'key.pub': 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 + '/hostcerts',
|
||||
data=json.dumps(hostcert_request)
|
||||
)
|
||||
assert response.status_code == 201
|
||||
assert 'location' in response.headers
|
||||
location = response.headers['location']
|
||||
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 'key-cert.pub' 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['key-cert.pub'])
|
||||
# Write the authorized principals file
|
||||
os.mkdir('/etc/ssh/auth_principals')
|
||||
with open('/etc/ssh/auth_principals/ubuntu', '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.'
|
||||
runcmd:
|
||||
- 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
|
||||
- systemctl restart ssh
|
||||
|
@ -2,20 +2,15 @@ import json
|
||||
import requests
|
||||
import os
|
||||
import subprocess
|
||||
import uuid
|
||||
|
||||
def getVendordataFromMetadataAPI():
|
||||
response = requests.get(
|
||||
'http://169.254.169.254/openstack/2016-10-06/vendor_data2.json',
|
||||
'http://169.254.169.254/openstack/latest/vendor_data2.json',
|
||||
)
|
||||
assert response.status_code == 200
|
||||
return json.loads(response.content)
|
||||
|
||||
def getVendordataFromConfigDrive():
|
||||
path = '/mnt/openstack/2016-10-06/vendor_data2.json'
|
||||
with open(path, 'r') as f:
|
||||
json_string = f.read()
|
||||
return json.loads(json_string)
|
||||
|
||||
def getInstanceAndProjectIdFromMetadataAPI():
|
||||
response = requests.get(
|
||||
'http://169.254.169.254/openstack/latest/meta_data.json',
|
||||
@ -26,35 +21,44 @@ def getInstanceAndProjectIdFromMetadataAPI():
|
||||
assert 'project_id' in metadata
|
||||
return metadata['uuid'], metadata['project_id']
|
||||
|
||||
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/openstack/latest/meta_data.json'
|
||||
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 metadata['uuid'], metadata['project_id']
|
||||
return str(uuid.UUID(metadata['uuid'], version=4)), str(uuid.UUID(metadata['project_id'], version=4))
|
||||
|
||||
#vendordata = getVendordataFromConfigDrive()
|
||||
vendordata = getVendordataFromMetadataAPI()
|
||||
#instance_id = getInstanceIdFromConfigDrive()
|
||||
instance_id, project_id = getInstanceIdFromMetadataAPI()
|
||||
vendordata = getVendordataFromConfigDrive()
|
||||
#vendordata = getVendordataFromMetadataAPI()
|
||||
instance_id, project_id = getInstanceAndProjectIdFromConfigDrive()
|
||||
#instance_id, project_id = getInstanceIdFromMetadataAPI()
|
||||
|
||||
assert 'sshaas' in vendordata
|
||||
sshaas = vendordata['sshaas']
|
||||
assert 'token' in sshaas
|
||||
assert 'auth_pub_key_user' in sshaas
|
||||
assert 'principals' in sshaas
|
||||
principals = sshaas['principals'].split(',')
|
||||
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('~/.ssh/id_rsa.pub', 'r') as f:
|
||||
with open('/etc/ssh/ssh_host_rsa_key.pub', 'r') as f:
|
||||
host_key_pub = f.read()
|
||||
|
||||
server = 'http://172.24.4.1:18321'
|
||||
|
||||
hostcert_request = {
|
||||
'token_id': sshaas['token'],
|
||||
'token_id': tatu['token'],
|
||||
'host_id': instance_id,
|
||||
'key.pub': host_key_pub
|
||||
}
|
||||
|
||||
response = requests.post(
|
||||
# Hard-coded SSHaaS API address will only work for devstack and requires
|
||||
# routing and SNAT or DNAT.
|
||||
@ -62,27 +66,27 @@ response = requests.post(
|
||||
# 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.
|
||||
'http://localhost:8000/hostcerts',
|
||||
server + '/hostcerts',
|
||||
data=json.dumps(hostcert_request)
|
||||
)
|
||||
assert response.status_code == 201
|
||||
assert 'location' in response.headers
|
||||
location = response.headers['location']
|
||||
print location
|
||||
|
||||
response = requests.get(
|
||||
'http://169.254.169.254' + location
|
||||
)
|
||||
response = requests.get(server + location)
|
||||
hostcert = json.loads(response.content)
|
||||
assert 'host_id' in metadata
|
||||
assert metadata['host_id'] == instance_id
|
||||
assert 'fingerprint' in metadata
|
||||
assert 'auth_id' in metadata
|
||||
assert metadata['auth_id'] == project_id
|
||||
assert 'key-cert.pub' in metadata
|
||||
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 'key-cert.pub' in hostcert
|
||||
|
||||
# Write the host's certificate
|
||||
with open('/etc/ssh/ssh_host_rsa_key-cert.pub', 'w') as f:
|
||||
f.write(metadata['key-cert.pub'])
|
||||
f.write(hostcert['key-cert.pub'])
|
||||
|
||||
# Write the authorized principals file
|
||||
os.mkdir('/etc/ssh/auth_principals')
|
||||
@ -90,11 +94,11 @@ with open('/etc/ssh/auth_principals/ubuntu', 'w') as f:
|
||||
for p in principals:
|
||||
f.write(p + os.linesep)
|
||||
|
||||
# Write the UserCA public key file
|
||||
with open('/etc/ssh/user_ca.pub', 'w') as f:
|
||||
f.write(sshaas['auth_pub_key_user'])
|
||||
# Write the User CA public key file
|
||||
with open('/etc/ssh/ca_user.pub', 'w') as f:
|
||||
f.write(tatu['auth_pub_key_user'])
|
||||
|
||||
subprocess.check_output("sed -i -e '$aTrustedUserCAKeys /etc/ssh/user_ca.pub' /etc/ssh/sshd_config")
|
||||
subprocess.check_output("sed -i -e '$aTrustedUserCAKeys /etc/ssh/ca_user.pub' /etc/ssh/sshd_config")
|
||||
subprocess.check_output("sed -i -e '$aAuthorizedPrincipalsFile /etc/ssh/auth_principals/%u' /etc/ssh/sshd_config")
|
||||
subprocess.check_output("set -i -e '$aHostCertificate /etc/ssh/ssh_host_rsa_key-cert.pub' /etc/ssh/sshd_config")
|
||||
subprocess.check_output("systemctl restart ssh")
|
||||
subprocess.check_output("sed -i -e '$aHostCertificate /etc/ssh/ssh_host_rsa_key-cert.pub' /etc/ssh/sshd_config")
|
||||
subprocess.check_output("systemctl restart ssh")
|
59
scripts/get_user_cert.py
Normal file
59
scripts/get_user_cert.py
Normal file
@ -0,0 +1,59 @@
|
||||
import json
|
||||
import requests
|
||||
import os
|
||||
import subprocess
|
||||
import uuid
|
||||
from Crypto.PublicKey import RSA
|
||||
|
||||
keyfile = '/opt/stack/.ssh/mykey'
|
||||
user_id = str(uuid.uuid4())
|
||||
auth_id = str(uuid.UUID('0852c6cd6209425c88de582acbcd1170', version=4))
|
||||
key = RSA.generate(2048)
|
||||
keytxt = key.exportKey('PEM')
|
||||
pubkeytxt = key.publickey().exportKey('OpenSSH')
|
||||
server = 'http://127.0.0.1:18321'
|
||||
|
||||
with open('/etc/ssh/ssh_host_rsa_key.pub', 'r') as f:
|
||||
host_key_pub = f.read()
|
||||
|
||||
|
||||
user = {
|
||||
'user_id': user_id,
|
||||
'auth_id': auth_id,
|
||||
'key.pub': pubkeytxt
|
||||
}
|
||||
|
||||
response = requests.post(
|
||||
server + '/usercerts',
|
||||
data=json.dumps(user)
|
||||
)
|
||||
assert response.status_code == 201
|
||||
assert 'location' in response.headers
|
||||
location = response.headers['location']
|
||||
print location
|
||||
|
||||
response = requests.get(server + location)
|
||||
usercert = json.loads(response.content)
|
||||
assert 'user_id' in usercert
|
||||
assert usercert['user_id'] == user_id
|
||||
assert 'fingerprint' in usercert
|
||||
assert 'auth_id' in usercert
|
||||
au = str(uuid.UUID(usercert['auth_id'], version=4))
|
||||
assert au == auth_id
|
||||
assert 'key-cert.pub' in usercert
|
||||
|
||||
# Write the user's ID
|
||||
with open(keyfile + '_user_id', 'w') as f:
|
||||
f.write(user_id)
|
||||
|
||||
# Write the user private key
|
||||
with open(keyfile, 'w') as f:
|
||||
f.write(keytxt)
|
||||
|
||||
# Write the user public key
|
||||
with open(keyfile + '.pub', 'w') as f:
|
||||
f.write(pubkeytxt)
|
||||
|
||||
# Write the user certificate
|
||||
with open(keyfile + '-cert.pub', 'w') as f:
|
||||
f.write(usercert['key-cert.pub'])
|
@ -6,14 +6,11 @@ import falcon
|
||||
import sshpubkeys
|
||||
import uuid
|
||||
import os
|
||||
from tatu.utils import generateCert
|
||||
from tatu.utils import generateCert,random_uuid
|
||||
from Crypto.PublicKey import RSA
|
||||
|
||||
Base = declarative_base()
|
||||
|
||||
def generate_uuid():
|
||||
return str(uuid.uuid4())
|
||||
|
||||
class Authority(Base):
|
||||
__tablename__ = 'authorities'
|
||||
|
||||
@ -55,7 +52,7 @@ def createUserCert(session, user_id, auth_id, pub):
|
||||
certRecord = session.query(UserCert).get([user_id, fingerprint])
|
||||
if certRecord is not None:
|
||||
raise falcon.HTTPConflict('This public key is already signed.')
|
||||
cert = generateCert(auth.user_key, pub)
|
||||
cert = generateCert(auth.user_key, pub, principals='admin,root')
|
||||
if cert is None:
|
||||
raise falcon.HTTPInternalServerError("Failed to generate the certificate")
|
||||
user = UserCert(
|
||||
@ -72,7 +69,7 @@ class Token(Base):
|
||||
__tablename__ = 'tokens'
|
||||
|
||||
token_id = sa.Column(sa.String(36), primary_key=True,
|
||||
default=generate_uuid)
|
||||
default=random_uuid)
|
||||
auth_id = sa.Column(sa.String(36), sa.ForeignKey('authorities.auth_id'))
|
||||
host_id = sa.Column(sa.String(36), index=True, unique=True)
|
||||
hostname = sa.Column(sa.String(36))
|
||||
@ -140,7 +137,7 @@ def createHostCert(session, token_id, host_id, pub):
|
||||
certRecord = session.query(HostCert).get([host_id, fingerprint])
|
||||
if certRecord is not None:
|
||||
raise falcon.HTTPConflict('This public key is already signed.')
|
||||
cert = generateCert(auth.host_key, pub, token.hostname)
|
||||
cert = generateCert(auth.host_key, pub, hostname=token.hostname)
|
||||
if cert == '':
|
||||
raise falcon.HTTPInternalServerError("Failed to generate the certificate")
|
||||
host = HostCert(host_id=host_id,
|
||||
|
@ -7,6 +7,7 @@ import uuid
|
||||
from tatu.api.app import create_app
|
||||
from tatu.db.persistence import SQLAlchemySessionManager
|
||||
from tatu.db.models import Authority
|
||||
from tatu.utils import random_uuid
|
||||
from Crypto.PublicKey import RSA
|
||||
import sshpubkeys
|
||||
|
||||
@ -19,9 +20,6 @@ def client(db):
|
||||
api = create_app(db)
|
||||
return testing.TestClient(api)
|
||||
|
||||
def random_uuid():
|
||||
return str(uuid.uuid4())
|
||||
|
||||
token_id = ''
|
||||
|
||||
host_id = random_uuid()
|
||||
|
@ -2,7 +2,10 @@ import os
|
||||
import subprocess
|
||||
import uuid
|
||||
|
||||
def generateCert(auth_key, entity_key, hostname=None):
|
||||
def random_uuid():
|
||||
return str(uuid.uuid4())
|
||||
|
||||
def generateCert(auth_key, entity_key, hostname=None, principals='root'):
|
||||
# Temporarily write the authority private key and entity public key to files
|
||||
prefix = uuid.uuid4().hex
|
||||
# Todo: make the temporary directory configurable or secure it.
|
||||
@ -20,7 +23,7 @@ def generateCert(auth_key, entity_key, hostname=None):
|
||||
args = ['ssh-keygen', '-P "pinot"', '-s', ca_file, '-I testID', '-V',
|
||||
'-1d:+365d', '-n']
|
||||
if hostname is None:
|
||||
args.extend(['"myRoot,yourRoot"', pub_file])
|
||||
args.extend(['"' + principals + '"', pub_file])
|
||||
else:
|
||||
args.extend([hostname, '-h', pub_file])
|
||||
print subprocess.check_output(args, stderr=subprocess.STDOUT)
|
||||
|
Loading…
Reference in New Issue
Block a user