X-Git-Url: https://pwan.org/git/?a=blobdiff_plain;ds=sidebyside;f=certmaster%2Fcertmaster.py;h=b0a216bbe52f961e1b394281b24b0fdf8aa178de;hb=5bdd42c1534a196d6be9104543e4a9a9b0442324;hp=970ff5970bbdc790903c4ed654a1975c126271d4;hpb=ece4c159e4fd726a70b1da25821493fb8a90c8b3;p=certmaster.git diff --git a/certmaster/certmaster.py b/certmaster/certmaster.py old mode 100755 new mode 100644 index 970ff59..b0a216b --- a/certmaster/certmaster.py +++ b/certmaster/certmaster.py @@ -16,11 +16,25 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. # standard modules import SimpleXMLRPCServer +import string import sys +import traceback import os import os.path from OpenSSL import crypto -import sha + +try: + import hashlib +except ImportError: + # Python-2.4.z ... gah! (or even 2.3!) + import sha + class hashlib: + @staticmethod + def new(algo): + if algo == 'sha1': + return sha.new() + raise ValueError, "Bad checksum type" + import glob import socket import exceptions @@ -106,7 +120,7 @@ class CertMaster(object): requesting_host = self._sanitize_cn(csrreq.get_subject().CN) if with_triggers: - self._run_triggers(None, '/var/lib/certmaster/triggers/request/pre/*') + self._run_triggers(requesting_host, '/var/lib/certmaster/triggers/request/pre/*') self.logger.info("%s requested signing of cert %s" % (requesting_host,csrreq.get_subject().CN)) # get rid of dodgy characters in the filename we're about to make @@ -121,10 +135,10 @@ class CertMaster(object): if os.path.exists(csrfile): oldfo = open(csrfile) oldcsrbuf = oldfo.read() - oldsha = sha.new() + oldsha = hashlib.new('sha1') oldsha.update(oldcsrbuf) olddig = oldsha.hexdigest() - newsha = sha.new() + newsha = hashlib.new('sha1') newsha.update(csrbuf) newdig = newsha.hexdigest() if not newdig == olddig: @@ -140,7 +154,7 @@ class CertMaster(object): cert_buf = crypto.dump_certificate(crypto.FILETYPE_PEM, slavecert) cacert_buf = crypto.dump_certificate(crypto.FILETYPE_PEM, self.cacert) if with_triggers: - self._run_triggers(None,'/var/lib/certmaster/triggers/request/post/*') + self._run_triggers(requesting_host,'/var/lib/certmaster/triggers/request/post/*') return True, cert_buf, cacert_buf # if we don't have a cert then: @@ -192,13 +206,13 @@ class CertMaster(object): print 'No match for %s to clean up' % hn return if with_triggers: - self._run_triggers(None,'/var/lib/certmaster/triggers/remove/pre/*') + self._run_triggers(hn,'/var/lib/certmaster/triggers/remove/pre/*') for fn in csrs + certs: print 'Cleaning out %s for host matching %s' % (fn, hn) self.logger.info('Cleaning out %s for host matching %s' % (fn, hn)) os.unlink(fn) if with_triggers: - self._run_triggers(None,'/var/lib/certmaster/triggers/remove/post/*') + self._run_triggers(hn,'/var/lib/certmaster/triggers/remove/post/*') def sign_this_csr(self, csr, with_triggers=True): """returns the path to the signed cert file""" @@ -228,11 +242,12 @@ class CertMaster(object): else: # assume we got a bare csr req csrreq = csr + + requesting_host = self._sanitize_cn(csrreq.get_subject().CN) if with_triggers: - self._run_triggers(None,'/var/lib/certmaster/triggers/sign/pre/*') + self._run_triggers(requesting_host,'/var/lib/certmaster/triggers/sign/pre/*') - requesting_host = self._sanitize_cn(csrreq.get_subject().CN) certfile = '%s/%s.cert' % (self.cfg.certroot, requesting_host) self.logger.info("Signing for csr %s requested" % certfile) thiscert = certs.create_slave_certificate(csrreq, self.cakey, self.cacert, self.cfg.cadir) @@ -245,14 +260,61 @@ class CertMaster(object): self.logger.info("csr %s signed" % (certfile)) if with_triggers: - self._run_triggers(None,'/var/lib/certmaster/triggers/sign/post/*') + self._run_triggers(requesting_host,'/var/lib/certmaster/triggers/sign/post/*') if csr_unlink_file and os.path.exists(csr_unlink_file): os.unlink(csr_unlink_file) return certfile + + # return a list of already signed certs + def get_signed_certs(self, hostglobs=None): + certglob = "%s/*.cert" % (self.cfg.certroot) + + certs = [] + globs = "*" + if hostglobs: + globs = hostglobs + + for hostglob in globs: + certglob = "%s/%s.cert" % (self.cfg.certroot, hostglob) + certs = certs + glob.glob(certglob) + + signed_certs = [] + for cert in certs: + # just want the hostname, so strip off path and ext + signed_certs.append(os.path.basename(cert).split(".cert", 1)[0]) + + return signed_certs + + def get_peer_certs(self): + """ + Returns a list of all certs under peerroot + """ + myglob = os.path.join(self.cfg.peerroot, '*.%s' % self.cfg.cert_extension) + return glob.glob(myglob) + + # return a list of the cert hash string we use to identify systems + def get_cert_hashes(self, hostglobs=None): + certglob = "%s/*.cert" % (self.cfg.certroot) + + certfiles = [] + globs = "*" + if hostglobs: + globs = hostglobs + + for hostglob in globs: + certglob = "%s/%s.cert" % (self.cfg.certroot, hostglob) + certfiles = certfiles + glob.glob(certglob) + cert_hashes = [] + for certfile in certfiles: + cert = certs.retrieve_cert_from_file(certfile) + cert_hashes.append("%s-%s" % (cert.get_subject().CN, cert.subject_name_hash())) + + return cert_hashes + def _run_triggers(self, ref, globber): return utils.run_triggers(ref, globber) @@ -270,24 +332,47 @@ def serve(xmlrpcinstance): """ - server = CertmasterXMLRPCServer((xmlrpcinstance.cfg.listen_addr, CERTMASTER_LISTEN_PORT)) + config = read_config(CERTMASTER_CONFIG, CMConfig) + listen_addr = config.listen_addr + listen_port = config.listen_port + if listen_port == '': + listen_port = CERTMASTER_LISTEN_PORT + server = CertmasterXMLRPCServer((listen_addr,listen_port)) server.logRequests = 0 # don't print stuff to console server.register_instance(xmlrpcinstance) xmlrpcinstance.logger.info("certmaster started") xmlrpcinstance.audit_logger.logger.info("certmaster started") server.serve_forever() +def excepthook(exctype, value, tracebackobj): + exctype_blurb = "Exception occured: %s" % exctype + excvalue_blurb = "Exception value: %s" % value + exctb_blurb = "Exception Info:\n%s" % string.join(traceback.format_list(traceback.extract_tb(tracebackobj))) + + print exctype_blurb + print excvalue_blurb + print exctb_blurb + + log = logger.Logger().logger + log.info(exctype_blurb) + log.info(excvalue_blurb) + log.info(exctb_blurb) + def main(argv): - + + sys.excepthook = excepthook cm = CertMaster('/etc/certmaster/certmaster.conf') + if "--version" in sys.argv or "-v" in sys.argv: + print >> sys.stderr, file("/etc/certmaster/version").read().strip() + sys.exit(0) + if "daemon" in argv or "--daemon" in argv: utils.daemonize("/var/run/certmaster.pid") else: print "serving...\n" - # just let exceptions bubble up for now serve(cm)