summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--MANIFEST.in1
-rw-r--r--certmaster.spec9
-rwxr-xr-xcertmaster/certmaster.py34
-rwxr-xr-xcertmaster/utils.py33
-rw-r--r--setup.py9
5 files changed, 78 insertions, 8 deletions
diff --git a/MANIFEST.in b/MANIFEST.in
index bc0e08b..782337c 100644
--- a/MANIFEST.in
+++ b/MANIFEST.in
@@ -4,6 +4,7 @@ recursive-include docs *
recursive-include init-scripts *
recursive-include po *.po
recursive-include po *.pot
+recursice-include triggers *
include AUTHORS
include LICENSE
include README
diff --git a/certmaster.spec b/certmaster.spec
index bb252cc..e6868aa 100644
--- a/certmaster.spec
+++ b/certmaster.spec
@@ -63,6 +63,12 @@ rm -fr $RPM_BUILD_ROOT
%{python_sitelib}/certmaster/*.py*
%dir /var/log/certmaster
%dir /var/lib/certmaster
+%dir /var/lib/certmaster/triggers/sign/pre
+%dir /var/lib/certmaster/triggers/sign/post
+%dir /var/lib/certmaster/triggers/request/pre
+%dir /var/lib/certmaster/triggers/request/post
+%dir /var/lib/certmaster/triggers/remove/pre
+%dir /var/lib/certmaster/triggers/remove/post
%doc AUTHORS README LICENSE
%{_mandir}/man1/*.1.gz
@@ -99,6 +105,9 @@ fi
%changelog
+* Tue Apr 15 2008 Steve Salevan <ssalevan@redhat.com> - 0.1-3
+- added in trigger directories
+
* Mon Mar 17 2008 Adrian Likins <alikins@redhat.com> - 0.1-2
- removed unused minion/ and overlord/ dirs
diff --git a/certmaster/certmaster.py b/certmaster/certmaster.py
index 1bf3a2d..970ff59 100755
--- a/certmaster/certmaster.py
+++ b/certmaster/certmaster.py
@@ -90,7 +90,7 @@ class CertMaster(object):
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
@@ -104,7 +104,9 @@ class CertMaster(object):
return False, '', ''
requesting_host = self._sanitize_cn(csrreq.get_subject().CN)
-
+
+ if with_triggers:
+ self._run_triggers(None, '/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
@@ -137,6 +139,8 @@ class CertMaster(object):
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(None,'/var/lib/certmaster/triggers/request/post/*')
return True, cert_buf, cacert_buf
# if we don't have a cert then:
@@ -149,6 +153,8 @@ class CertMaster(object):
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:
@@ -158,6 +164,8 @@ class CertMaster(object):
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, '', ''
@@ -172,7 +180,7 @@ class CertMaster(object):
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)
@@ -183,12 +191,16 @@ class CertMaster(object):
# FIXME: should be an exception?
print 'No match for %s to clean up' % hn
return
+ if with_triggers:
+ self._run_triggers(None,'/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(None,'/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
@@ -216,6 +228,9 @@ class CertMaster(object):
else: # assume we got a bare csr req
csrreq = csr
+ if with_triggers:
+ self._run_triggers(None,'/var/lib/certmaster/triggers/sign/pre/*')
+
requesting_host = self._sanitize_cn(csrreq.get_subject().CN)
certfile = '%s/%s.cert' % (self.cfg.certroot, requesting_host)
@@ -228,13 +243,18 @@ class CertMaster(object):
del destfo
- self.logger.info("csr %s signed" % (certfile))
+ self.logger.info("csr %s signed" % (certfile))
+ if with_triggers:
+ self._run_triggers(None,'/var/lib/certmaster/triggers/sign/post/*')
+
+
if csr_unlink_file and os.path.exists(csr_unlink_file):
os.unlink(csr_unlink_file)
return certfile
-
+ def _run_triggers(self, ref, globber):
+ return utils.run_triggers(ref, globber)
class CertmasterXMLRPCServer(SimpleXMLRPCServer.SimpleXMLRPCServer):
diff --git a/certmaster/utils.py b/certmaster/utils.py
index eec3d2b..209e758 100755
--- a/certmaster/utils.py
+++ b/certmaster/utils.py
@@ -24,6 +24,7 @@ import certs
from config import read_config
from commonconfig import MinionConfig
import logger
+import sub_process
# FIXME: module needs better pydoc
@@ -108,6 +109,7 @@ def get_hostname(talk_to_certmaster=True):
try:
s = socket.socket()
s.settimeout(5)
+ print "server, port", server, port
s.connect((server, port))
(intf, port) = s.getsockname()
remote_hostname = socket.gethostbyaddr(intf)[0]
@@ -191,6 +193,37 @@ def create_minion_keys():
os.write(ca_cert_fd, ca_cert_string)
os.close(ca_cert_fd)
+def run_triggers(ref, globber):
+ """
+ Runs all the trigger scripts in a given directory.
+ ref can be a certmaster object, if not None, the name will be passed
+ to the script. If ref is None, the script will be called with
+ no argumenets. Globber is a wildcard expression indicating which
+ triggers to run. Example: "/var/lib/certmaster/triggers/blah/*"
+ """
+
+ log = logger.Logger().logger
+ triggers = glob.glob(globber)
+ triggers.sort()
+ for file in triggers:
+ log.debug("Executing trigger: %s" % file)
+ try:
+ if file.find(".rpm") != -1:
+ # skip .rpmnew files that may have been installed
+ # in the triggers directory
+ continue
+ if ref:
+ rc = sub_process.call([file, ref.name], shell=False)
+ else:
+ rc = sub_process.call([file], shell=False)
+ except:
+ log.warning("Warning: failed to execute trigger: %s" % file)
+ continue
+
+ if rc != 0:
+ raise codes.CMException, "certmaster trigger failed: %(file)s returns %(code)d" % { "file" : file, "code" : rc }
+
+
def submit_csr_to_master(csr_file, master_uri):
""""
gets us our cert back from the certmaster.wait_for_cert() method
diff --git a/setup.py b/setup.py
index bd1cf53..e47e1b0 100644
--- a/setup.py
+++ b/setup.py
@@ -18,6 +18,7 @@ if __name__ == "__main__":
initpath = "/etc/init.d/"
logpath = "/var/log/%s/" % NAME
certdir = "/var/lib/%s/" % NAME
+ trigpath = "/var/lib/%s/triggers/"% NAME
pkipath = "/etc/pki/%s" % NAME
rotpath = "/etc/logrotate.d"
aclpath = "%s/minion-acl.d" % etcpath
@@ -48,7 +49,13 @@ if __name__ == "__main__":
(certdir, []),
(etcpath, []),
(pkipath, []),
- (aclpath, [])
+ (aclpath, []),
+ ("%s/sign/pre/" % trigpath, []),
+ ("%s/sign/post/" % trigpath, []),
+ ("%s/remove/pre/" % trigpath, []),
+ ("%s/remove/post/" % trigpath, []),
+ ("%s/request/pre/" % trigpath, []),
+ ("%s/request/post/" % trigpath, []),
],
description = SHORT_DESC,
long_description = LONG_DESC