diff --git a/tatu/api/models.py b/tatu/api/models.py index bc724e8..09971d6 100644 --- a/tatu/api/models.py +++ b/tatu/api/models.py @@ -19,8 +19,8 @@ from oslo_log import log as logging from tatu.config import CONF from tatu.db import models as db -from tatu.dns import add_srv_records -from tatu.pat import create_pat_entries +from tatu.dns import add_srv_records, get_srv_url +from tatu.pat import create_pat_entries, get_port_ip_tuples LOG = logging.getLogger(__name__) @@ -98,9 +98,9 @@ class Authorities(object): items.append({ 'auth_id': auth.auth_id, 'user_key.pub': user_pub_key, - 'host_key.pub': host_pub_key + 'host_key.pub': host_pub_key, }) - body = {'items': items} + body = {'CAs': items} resp.body = json.dumps(body) resp.status = falcon.HTTP_OK @@ -141,6 +141,21 @@ class UserCerts(object): resp.status = falcon.HTTP_201 resp.location = '/usercerts/' + user.user_id + '/' + user.fingerprint + @falcon.before(validate) + def on_get(self, req, resp): + users = db.getUserCerts(self.session) + items = [] + for user in users: + items.append({ + 'user_id': user.user_id, + 'fingerprint': user.fingerprint, + 'auth_id': user.auth_id, + 'key-cert.pub': user.cert, + }) + body = {'users': items} + resp.body = json.dumps(body) + resp.status = falcon.HTTP_OK + class UserCert(object): @falcon.before(validate) @@ -153,7 +168,7 @@ class UserCert(object): 'user_id': user.user_id, 'fingerprint': user.fingerprint, 'auth_id': user.auth_id, - 'key-cert.pub': user.cert + 'key-cert.pub': user.cert, } resp.body = json.dumps(body) resp.status = falcon.HTTP_OK @@ -186,6 +201,29 @@ class HostCerts(object): resp.status = falcon.HTTP_201 resp.location = '/hostcerts/' + host.host_id + '/' + host.fingerprint + @falcon.before(validate) + def on_get(self, req, resp): + hosts = db.getHostCerts(self.session) + items = [] + for host in hosts: + item = { + 'host_id': host.host_id, + 'fingerprint': host.fingerprint, + 'auth_id': host.auth_id, + 'key-cert.pub': host.cert, + 'hostname': host.hostname, + } + if CONF.tatu.use_pat_bastion: + item['pat_bastions'] = ','.join( + '{}:{}'.format(t[1], t[0]) for t in + get_port_ip_tuples(host.host_id, 22)) + item['srv_url'] = get_srv_url(host.hostname, host.auth_id) + items.append(item) + + body = {'hosts': items} + resp.body = json.dumps(body) + resp.status = falcon.HTTP_OK + class HostCert(object): @falcon.before(validate) @@ -254,6 +292,6 @@ class NovaVendorData(object): # TODO(pino): make this configurable per project or subnet if CONF.tatu.use_pat_bastion: port_ip_tuples = create_pat_entries(self.session, - req.body['instance-id'], 22) + req.body['instance-id'], 22) add_srv_records(req.body['hostname'], req.body['project-id'], port_ip_tuples) diff --git a/tatu/db/models.py b/tatu/db/models.py index 1e637ae..9a2c109 100644 --- a/tatu/db/models.py +++ b/tatu/db/models.py @@ -77,6 +77,10 @@ def getUserCert(session, user_id, fingerprint): return session.query(UserCert).get([user_id, fingerprint]) +def getUserCerts(session): + return session.query(UserCert) + + def createUserCert(session, user_id, auth_id, pub): # Retrieve the authority's private key and generate the certificate auth = getAuthority(session, auth_id) @@ -154,6 +158,10 @@ def getHostCert(session, host_id, fingerprint): return session.query(HostCert).get([host_id, fingerprint]) +def getHostCerts(session): + return session.query(HostCert) + + def createHostCert(session, token_id, host_id, pub): token = session.query(Token).get(token_id) if token is None: diff --git a/tatu/dns.py b/tatu/dns.py index be94fd4..8e4ad6c 100644 --- a/tatu/dns.py +++ b/tatu/dns.py @@ -48,6 +48,10 @@ def sync_bastions(ip_addresses): register_bastion(ip) +def get_srv_url(hostname, project_id): + return '_ssh._tcp.{}.{}.{}'.format(hostname, project_id[:8], ZONE['name']) + + def add_srv_records(hostname, project_id, port_ip_tuples): records = [] for port, ip in port_ip_tuples: @@ -56,9 +60,7 @@ def add_srv_records(hostname, project_id, port_ip_tuples): records.add( '10 50 {} {}'.format(port, bastion)) - DESIGNATE.recordsets.create(ZONE['id'], - '_ssh._tcp.{}.{}'.format(hostname, - project_id[:8]), + DESIGNATE.recordsets.create(ZONE['id'], get_srv_url(hostname, project_id), 'SRV', records) diff --git a/tatu/pat.py b/tatu/pat.py index a90d425..62f3890 100644 --- a/tatu/pat.py +++ b/tatu/pat.py @@ -83,6 +83,22 @@ def _df_find_lrouter_by_lport(lport): return lr return None + +def get_port_ip_tuples(instance_id, fixed_lport): + port_ip_tuples = [] + server = NOVA.servers.get(instance_id) + ifaces = server.interface_list() + for iface in ifaces: + lport = DRAGONFLOW.get(LogicalPort(id=iface['port_id'])) + lrouter = _df_find_lrouter_by_lport(lport) + if lrouter is None: continue + pat_entries = DRAGONFLOW.get(PATEntry(lport=lport)) + for entry in pat_entries: + if entry.fixed_l4_port == fixed_lport: + port_ip_tuples.append((entry.pat_l4_port, str(entry.pat.ip))) + return port_ip_tuples + + def create_pat_entries(sql_session, instance_id, fixed_l4_port, num=CONF.tatu.num_pat_bastions_per_server): port_ip_tuples = []