#! /usr/bin/env python import sys import os import stat import argparse import yaml import subprocess import shutil def run_openssl(args): p = subprocess.Popen(['openssl'] + args, stderr=subprocess.PIPE) (_, out_stderr) = p.communicate() if p.returncode == 0: return True print >>sys.stderr, "openssl %s failure: %d: %s" % \ (args, p.returncode, out_stderr) return False def make_eckey(name): privkey = '%s-private.pem' % name pubkey = '%s.pem' % name if os.access(privkey, os.R_OK) and os.access(pubkey, os.R_OK): return True print "creating EC key \"%s\"" % name ecparam_args = ['ecparam', '-name', 'prime256v1', '-genkey', '-noout', '-out', privkey] if not run_openssl(ecparam_args): return False os.chmod(privkey, stat.S_IRUSR | stat.S_IWUSR) ec_args = ['ec', '-in', privkey, '-pubout', '-out', pubkey] if not run_openssl(ec_args): return False return True def make_ca(logname, cakey, cacert): os.makedirs('./demoCA/newcerts', 0700) f = open('./demoCA/index.txt', 'w') f.close() f = open('./demoCA/serial', 'w') f.write('00\n') f.close() f = open('caconfig.txt', 'w') f.write('[ req ]\n') f.write('distinguished_name = req_distinguished_name\n') f.write('x509_extensions = v3_ca\n') f.write('string_mask = utf8only\n') f.write('[ req_distinguished_name ]\n') f.write('[ v3_ca ]\n') f.write('basicConstraints=CA:true\n') f.close() subject = '/countryName=II/stateOrProvinceName=internets/organizationName=%s/commonName=ca' % logname req_args = ['req', '-newkey', 'rsa:2048', '-keyout', cakey, '-out', 'req.csr', '-nodes', '-subj', subject, '-config', 'caconfig.txt'] if not run_openssl(req_args): return False os.chmod(cakey, stat.S_IRUSR) ca_args = ['ca', '-in', 'req.csr', '-selfsign', '-keyfile', cakey, '-out', cacert, '-batch'] if not run_openssl(ca_args): return False return True def make_certs(logname, nodenames): wdir = './httpscerts' if not os.access(wdir, os.F_OK): os.mkdir(wdir) os.chdir(wdir) ca_key = './cakey.pem' ca_cert = './demoCA/cacert.pem' if not os.access(ca_key, os.R_OK) or not os.access(ca_cert, os.R_OK): if not make_ca(logname, ca_key, ca_cert): return False for nodename in nodenames: key = './%s-key.pem' % nodename csr = './%s.csr' % nodename cert = './%s.pem' % nodename subject = '/countryName=II/stateOrProvinceName=internets/organizationName=%s/CN=%s' % (logname, nodename) if os.access(key, os.R_OK) and os.access(cert, os.R_OK): continue print "creating cert for node %s" % nodename req_args = ['req', '-new', '-newkey', 'rsa:2048', '-keyout', key, '-out', csr, '-nodes', '-subj', subject] if not run_openssl(req_args): return False ca_args = ['ca', '-in', csr, '-keyfile', ca_key, '-out', cert, '-batch'] if not run_openssl(ca_args): return False shutil.copy(ca_cert, '../nodes/%s/cacert.pem' % nodename) shutil.copy(cert, '../nodes/%s/webcert-%s.pem' % (nodename, nodename)) shutil.copy(key, '../nodes/%s/webkey-%s.pem' % (nodename, nodename)) os.chmod('../nodes/%s/webkey-%s.pem' % (nodename, nodename), stat.S_IRUSR | stat.S_IWUSR) os.chdir('..') return True def make_authkeys(nodenames): wdir = './publickeys' if not os.access(wdir, os.F_OK): os.mkdir(wdir) os.chdir(wdir) for nodename in nodenames: priv_dst = '../nodes/%s/%s-private.pem' % (nodename, nodename) if os.access(priv_dst, os.R_OK): continue if not make_eckey(nodename): return False if os.access(priv_dst, os.F_OK) and not os.access(priv_dst, os.W_OK): os.chmod(priv_dst, stat.S_IWUSR) shutil.move('%s-private.pem' % nodename, priv_dst) for nodename in nodenames: pub_dst = '../nodes/%s/publickeys' % nodename shutil.rmtree(pub_dst, ignore_errors=True) shutil.copytree('.', pub_dst) os.chdir('..') return True def copy_logkey(logname, nodenames): for nodename in nodenames: shutil.copy('%s.pem' % logname, 'nodes/%s/' % nodename) def create_destdirs(logname, nodenames): for nodename in nodenames: d = 'nodes/%s' % nodename if not os.access(d, os.F_OK): os.makedirs(d) def copy_cacert(nodenames): ca_cert = './httpscerts/demoCA/cacert.pem' for nodename in nodenames: shutil.copy(ca_cert, './nodes/%s/cacert.pem' % nodename) def main(): parser = argparse.ArgumentParser(description="") parser.add_argument('config', help="System configuration") parser.add_argument('--logname', help="Log name", default="mylog") args = parser.parse_args() logname = args.logname config = yaml.load(open(args.config)) nodenames = [node["name"] for node in config["frontendnodes"] + config["storagenodes"] + config["signingnodes"]] mergenodenames = [node["name"] for node in config["mergenodes"]] create_destdirs(logname, nodenames + mergenodenames) make_eckey(logname) copy_logkey(logname, nodenames + mergenodenames) make_certs(logname, nodenames) make_authkeys(nodenames + mergenodenames) copy_cacert(mergenodenames) main()