#!/usr/bin/python

import confluent.collective.manager as collective
import eventlet.green.subprocess as subprocess
import glob
import os
import shutil
import tempfile

def normalize_uid():
    curruid = os.getuid()
    neededuid = os.stat('/etc/confluent').st_uid
    if curruid != neededuid:
        os.setuid(neededuid)
    if os.getuid() != neededuid:
        raise Exception('Need to run as root or owner of /etc/confluent')

def initialize_ca():
    normalize_uid()
    try:
        os.makedirs('/etc/confluent/ssh', mode=0o700)
    except OSError as e:
        if e.errno != 17:
            raise
    caname = '{0} SSH CA'.format(collective.get_myname())
    subprocess.check_call(['ssh-keygen', '-C', caname, '-t', 'ed25519', '-f', '/etc/confluent/ssh/ca', '-N', ''])
    try:
        os.makedirs('/var/lib/confluent/ssh', mode=0o755)
    except OSError as e:
        if e.errno != 17:
            raise
    currknownhosts = []
    try:
        with open('/var/lib/confluent/ssh/ssh_known_hosts', 'r') as skh:
            for ent in skh:
                descr = ent.split(' ', 4)[-1].strip()
                if descr != caname:
                    currknownhosts.append(ent)
    except OSError as e:
        if e.errno != 2:
            raise
    with open('/etc/confluent/ssh/ca.pub', 'r') as capub:
        newent = '@cert-authority * ' + capub.read()
        currknownhosts.append(newent)
    with open('/var/lib/confluent/ssh/ssh_known_hosts', 'w') as skh:
        for ckh in currknownhosts:
            skh.write(ckh)

def sign_host_key(pubkey, nodename):
    tmpdir = tempfile.mkdtemp()
    try:
        pkeyname = os.path.join(tmpdir, 'hostkey.pub')
        with open(pkeyname, 'w') as pubfile:
            pubfile.write(pubkey)
        subprocess.check_call(
            ['ssh-keygen', '-s', '/etc/confluent/ssh/ca', '-I', nodename,
             '-n', nodename, '-h', pkeyname])
        certname = pkeyname.replace('.pub', '-cert.pub')
        with open(certname) as cert:
            return cert.read()
    finally:
        shutil.rmtree(tmpdir)

def initialize_root_key():
    authorized = []
    for currkey in glob.glob('/root/.ssh/*.pub'):
        authorized.append(open(currkey).read())
    if not authorized:
        subprocess.check_call(['ssh-keygen', '-t', 'ed25519', '-f', '/root/.ssh/id_ed25519', '-N', ''])
        for currkey in glob.glob('/root/.ssh/*.pub'):
            authorized.append(open(currkey).read())
    try:
        os.makedirs('/var/lib/confluent/ssh', mode=0o755)
        neededuid = os.stat('/etc/confluent').st_uid
        os.chown('/var/lib/confluent/ssh', neededuid, -1)
    except OSError as e:
        if e.errno != 17:
            raise
    for auth in authorized:
        if 'PRIVATE' in auth:
            continue
        currcomment = auth.split(' ', 2)[-1].strip()
        curralgo = auth.split(' ', 1)[0]
        authed = []
        try:
            with open('/var/lib/confluent/ssh/authorized_keys', 'r') as ak:
                for keyline in ak:
                    comment = keyline.split(' ', 2)[-1].strip()
                    algo = keyline.split(' ', 1)[0]
                    if currcomment != comment or algo != curralgo:
                        authed.append(keyline)
        except OSError as e:
            if e.errno != 2:
                raise
        authed.append(auth)
        with open('/var/lib/confluent/ssh/authorized_keys', 'w') as ak:
            for auth in authed:
                ak.write(auth)


def ca_exists():
    return os.path.exists('/etc/confluent/ssh/ca')


if __name__ == '__main__':
    initialize_root_key()
    if not ca_exists():
        initialize_ca()
    print(repr(sign_host_key(open('/etc/ssh/ssh_host_ed25519_key.pub').read(), collective.get_myname())))
@@ -424,16 +424,17 @@
 uent')%0A%0A
+%0A
 def init
@@ -594,24 +594,61 @@
       raise%0A
+    myname = collective.get_myname()%0A
     caname =
@@ -668,39 +668,22 @@
 .format(
-collective.get_
 myname
-()
 )%0A    su
@@ -831,35 +831,48 @@
 r/lib/confluent/
+public/site/
 ssh
+/
 ', mode=0o755)%0A 
@@ -948,355 +948,94 @@
    c
-urrknownhosts = %5B%5D%0A    try:%0A        with open('/var/lib/confluent/ssh/ssh_known_hosts', 'r') as skh:%0A            for ent in skh:%0A                descr = ent.split(' ', 4)%5B-1%5D.strip()%0A                if descr != caname:%0A                    currknownhosts.append(ent)%0A    except OSError as e:%0A        if e.errno != 2:%0A            raise%0A    with open
+afilename = '/var/lib/confluent/public/site/ssh/%7B0%7D.ca'.format(myname)%0A    shutil.copy
 ('/e
@@ -1064,27 +1064,25 @@
 b', 
-'r') as capub:
+cafilename)
 %0A    
+#
     
@@ -1130,176 +1130,8 @@
 d()%0A
-        currknownhosts.append(newent)%0A    with open('/var/lib/confluent/ssh/ssh_known_hosts', 'w') as skh:%0A        for ckh in currknownhosts:%0A            skh.write(ckh)
 %0A%0Ade

Rework CA layout to file-per-CA