diff options
author | Michael DeHaan <mdehaan@mdehaan.rdu.redhat.com> | 2007-09-26 16:35:41 -0400 |
---|---|---|
committer | Michael DeHaan <mdehaan@mdehaan.rdu.redhat.com> | 2007-09-26 16:35:41 -0400 |
commit | 484c9dba767b8a9b1e907d5e4179951ca3f1f2f7 (patch) | |
tree | ab8f91bcda34e11d6cba9840ee5326118aa6839e | |
parent | 62b705f2ef608e212229a234b9e53cf60f9dd83f (diff) | |
parent | 05034f278190ecaccdf61655d9b7c9bc97d52e79 (diff) | |
download | func-484c9dba767b8a9b1e907d5e4179951ca3f1f2f7.tar.gz func-484c9dba767b8a9b1e907d5e4179951ca3f1f2f7.tar.xz func-484c9dba767b8a9b1e907d5e4179951ca3f1f2f7.zip |
Merge branch 'master' of ssh://git.fedoraproject.org/git/hosted/func
-rw-r--r-- | func.spec | 1 | ||||
-rwxr-xr-x | func/certmaster.py | 74 | ||||
-rwxr-xr-x | minion/server.py | 1 | ||||
-rwxr-xr-x | scripts/certmaster-ca | 70 | ||||
-rw-r--r-- | setup.py | 2 | ||||
-rw-r--r-- | version | 2 |
6 files changed, 135 insertions, 15 deletions
@@ -38,6 +38,7 @@ rm -fr $RPM_BUILD_ROOT %{_bindir}/funcd %{_bindir}/func %{_bindir}/certmaster +%{_bindir}/certmaster-ca /etc/init.d/funcd /etc/init.d/certmaster %config(noreplace) /etc/func/minion.conf diff --git a/func/certmaster.py b/func/certmaster.py index 89b68a0..58840bb 100755 --- a/func/certmaster.py +++ b/func/certmaster.py @@ -1,5 +1,9 @@ #!/usr/bin/python +# FIXME: Perms checked and okayed on all csr, certs and keys, everywhere +# FIXME: picky about bogus CN names ../ ../ ./ etc, etc to avoid stupid attacks +# FIXME: more intelligent fault raises + """ cert master listener @@ -24,6 +28,7 @@ import os.path import traceback from OpenSSL import crypto import sha +import glob #from func.server import codes import func @@ -95,8 +100,7 @@ class CertMaster(object): if method in self.handlers.keys(): return self.handlers[method](*params) else: - pass - #raise codes.InvalidMethodException + raise func.codes.InvalidMethodException def wait_for_cert(self, csrbuf): @@ -113,7 +117,7 @@ class CertMaster(object): return False, '', '' requesting_host = csrreq.get_subject().CN - certfile = '%s/%s.pem' % (self.cfg.certroot, requesting_host) + certfile = '%s/%s.cert' % (self.cfg.certroot, requesting_host) csrfile = '%s/%s.csr' % (self.cfg.csrroot, requesting_host) # check for old csr on disk @@ -134,8 +138,7 @@ class CertMaster(object): # look for a cert: # if we have it, then return True, etc, etc if os.path.exists(certfile): - slavecert = crypto.load_certificate(crypto.FILETYPE_PEM, certfile) - + slavecert = func.certs.retrieve_cert_from_file(certfile) cert_buf = crypto.dump_certificate(crypto.FILETYPE_PEM, slavecert) cacert_buf = crypto.dump_certificate(crypto.FILETYPE_PEM, self.cacert) return True, cert_buf, cacert_buf @@ -145,14 +148,9 @@ class CertMaster(object): # else write out the csr if self.cfg.autosign: - slavecert = func.certs.create_slave_certificate(csrreq, - self.cakey, self.cacert, self.cfg.cadir) - - destfo = open(certfile, 'w') - destfo.write(crypto.dump_certificate(crypto.FILETYPE_PEM, slavecert)) - destfo.close() - del destfo - cert_buf = crypto.dump_certificate(crypto.FILETYPE_PEM, slavecert) + cert_fn = self.sign_this_csr(csrreq) + cert = func.certs.retrieve_cert_from_file(cert_fn) + cert_buf = crypto.dump_certificate(crypto.FILETYPE_PEM, cert) cacert_buf = crypto.dump_certificate(crypto.FILETYPE_PEM, self.cacert) return True, cert_buf, cacert_buf @@ -166,6 +164,56 @@ class CertMaster(object): return False, '', '' + def get_csrs_waiting(self): + hosts = [] + csrglob = '%s/*.csr' % self.cfg.csrroot + csr_list = glob.glob(csrglob) + for f in csr_list: + hn = os.path.basename(f) + hn = hn[:-4] + hosts.append(hn) + return hosts + + + def sign_this_csr(self, csr): + """returns the path to the signed cert file""" + csr_unlink_file = None + + if type(csr) is type(''): + if csr.startswith('/') and os.path.exists(csr): # we have a full path to the file + csrfo = open(csr) + csr_buf = csrfo.read() + csr_unlink_file = csr + + elif os.path.exists('%s/%s' % (self.cfg.csrroot, csr)): # we have a partial path? + csrfo = open('%s/%s' % (self.cfg.csrroot, csr)) + csr_buf = csrfo.read() + csr_unlink_file = '%s/%s' % (self.cfg.csrroot, csr) + + # we have a string of some kind + else: + csr_buf = csr + + try: + csrreq = crypto.load_certificate_request(crypto.FILETYPE_PEM, csr_buf) + except crypto.Error, e: + print 'Bad CSR: %s' % csr + + else: # assume we got a bare csr req + csrreq = csr + requesting_host = csrreq.get_subject().CN + certfile = '%s/%s.cert' % (self.cfg.certroot, requesting_host) + thiscert = func.certs.create_slave_certificate(csrreq, self.cakey, self.cacert, self.cfg.cadir) + destfo = open(certfile, 'w') + destfo.write(crypto.dump_certificate(crypto.FILETYPE_PEM, thiscert)) + destfo.close() + del destfo + if csr_unlink_file and os.path.exists(csr_unlink_file): + os.unlink(csr_unlink_file) + + return certfile + + class CertmasterXMLRPCServer(SimpleXMLRPCServer.SimpleXMLRPCServer): def __init__(self, args): self.allow_reuse_address = True diff --git a/minion/server.py b/minion/server.py index a047c53..0208f46 100755 --- a/minion/server.py +++ b/minion/server.py @@ -29,6 +29,7 @@ import codes import config_data import logger import module_loader +import utils class XmlRpcInterface(object): diff --git a/scripts/certmaster-ca b/scripts/certmaster-ca new file mode 100755 index 0000000..14f7c2f --- /dev/null +++ b/scripts/certmaster-ca @@ -0,0 +1,70 @@ +#!/usr/bin/python -tt +# sign/list keys +# --sign hostname hostname hostname +# --list # lists all csrs needing to be signed +# --list-all ? +# --clean? not sure what it will do + +import sys + +import func +import func.certs +import func.certmaster + + + +from optparse import OptionParser +defaults = { 'listen_addr': 'localhost', + 'listen_port': '51235', + 'cadir': '/etc/pki/func/ca', + 'certroot': '/var/lib/func/certmaster/certs', + 'csrroot': '/var/lib/func/certmaster/csrs', + 'autosign': 'false' + } + +def errorprint(stuff): + print >> sys.stderr, stuff + + +def parseargs(args): + usage = 'certmaster-ca [options]' + parser = OptionParser(usage=usage) + + parser.add_option('-l', '--list', default=False, action="store_true", + help='list signing requests remaining') + parser.add_option('-s', '--sign', default=False, action="store_true", + help='sign requests of hosts specified') + + (opts, args) = parser.parse_args() + # XXX FIXME check for obviously impossible things and exit, etc + + return (opts, args) + +def main(args): + cm = func.certmaster.CertMaster('/etc/func/certmaster.conf', defaults) + + (opts, args) = parseargs(args) + if opts.list: + hns = cm.get_csrs_waiting() + if hns: + for hn in cm.get_csrs_waiting(): + print hn + else: + print 'No certificates to sign' + + return 0 + + if opts.sign: + if not args: + errorprint('Need hostnames to sign') + return 1 + + for hn in args: + csrfile = '%s/%s.csr' % (cm.cfg.csrroot, hn) + certfile = cm.sign_this_csr(csrfile) + print '%s signed - cert located at %s' % (hn, certfile) + return 0 + + +if __name__ == "__main__": + sys.exit(main(sys.argv[1:])) @@ -27,7 +27,7 @@ if __name__ == "__main__": author_email = "func-list@redhat.com", url = "https://hosted.fedoraproject.org/projects/func/", license = "GPL", - scripts = ["scripts/funcd", "scripts/func", "scripts/certmaster"], + scripts = ["scripts/funcd", "scripts/func", "scripts/certmaster", "scripts/certmaster-ca"], # package_data = { '' : ['*.*'] }, package_dir = {"%s" % NAME: "%s" % NAME, "%s/minion" % NAME: "minion/", @@ -1 +1 @@ -0.11 5 +0.11 6 |