# 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
self.logger = logger.Logger().logger
self.audit_logger = logger.AuditLogger()
+ # if ca_key_file exists and ca_cert_file is missing == minion only setup
+ if os.path.exists(self.ca_key_file) and not os.path.exists(self.ca_cert_file):
+ return
+
try:
if not os.path.exists(self.cfg.cadir):
os.makedirs(self.cfg.cadir)
commonname = commonname.replace('\\', '')
return commonname
- def wait_for_cert(self, csrbuf):
+ def wait_for_cert(self, csrbuf, with_triggers=True):
"""
takes csr as a string
returns True, caller_cert, ca_cert
return False, '', ''
requesting_host = self._sanitize_cn(csrreq.get_subject().CN)
-
+
+ if with_triggers:
+ 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
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:
slavecert = 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)
+ if with_triggers:
+ 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:
cert_buf = crypto.dump_certificate(crypto.FILETYPE_PEM, cert)
cacert_buf = crypto.dump_certificate(crypto.FILETYPE_PEM, self.cacert)
self.logger.info("cert for %s was autosigned" % (requesting_host))
+ if with_triggers:
+ self._run_triggers(None,'/var/lib/certmaster/triggers/request/post/*')
return True, cert_buf, cacert_buf
else:
destfo.close()
del destfo
self.logger.info("cert for %s created and ready to be signed" % (requesting_host))
+ if with_triggers:
+ self._run_triggers(None,'/var/lib/certmaster/triggers/request/post/*')
return False, '', ''
return False, '', ''
hosts.append(hn)
return hosts
- def remove_this_cert(self, hn):
+ def remove_this_cert(self, hn, with_triggers=True):
""" removes cert for hostname using unlink """
cm = self
csrglob = '%s/%s.csr' % (cm.cfg.csrroot, hn)
# FIXME: should be an exception?
print 'No match for %s to clean up' % hn
return
+ if with_triggers:
+ 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)
+ os.unlink(fn)
+ if with_triggers:
+ self._run_triggers(hn,'/var/lib/certmaster/triggers/remove/post/*')
- def sign_this_csr(self, csr):
+ def sign_this_csr(self, csr, with_triggers=True):
"""returns the path to the signed cert file"""
csr_unlink_file = None
csrreq = csr
- requesting_host = self._sanitize_cn(csrreq.get_subject().CN)
+ requesting_host = self._sanitize_cn(csrreq.get_subject().CN)
+ if with_triggers:
+ self._run_triggers(requesting_host,'/var/lib/certmaster/triggers/sign/pre/*')
+
+
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)
del destfo
- self.logger.info("csr %s signed" % (certfile))
+ self.logger.info("csr %s signed" % (certfile))
+ if with_triggers:
+ 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)
class CertmasterXMLRPCServer(SimpleXMLRPCServer.SimpleXMLRPCServer):
"""
- 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)