From 24cc8d4f334c8b61bac09371b5f9f8919395d172 Mon Sep 17 00:00:00 2001 From: Rob Crittenden Date: Tue, 10 Apr 2012 21:21:08 +0200 Subject: Configure certmonger to execute restart scripts on renewal. certmonger now has the ability to execute a script when it renews a certificate. This can be used to automatically restart servers so the certificate doesn't expire in the running server. https://fedorahosted.org/freeipa/ticket/2050 --- freeipa.spec.in | 11 +++++++++-- install/Makefile.am | 1 + install/configure.ac | 1 + install/restart_scripts/Makefile.am | 15 +++++++++++++++ install/restart_scripts/README | 2 ++ install/restart_scripts/restart_dirsrv | 13 +++++++++++++ install/restart_scripts/restart_httpd | 7 +++++++ ipapython/certmonger.py | 9 ++++++++- ipaserver/install/certs.py | 14 ++++++++++++-- ipaserver/install/dsinstance.py | 6 +++--- ipaserver/install/httpinstance.py | 4 ++-- 11 files changed, 73 insertions(+), 10 deletions(-) create mode 100644 install/restart_scripts/Makefile.am create mode 100644 install/restart_scripts/README create mode 100644 install/restart_scripts/restart_dirsrv create mode 100644 install/restart_scripts/restart_httpd diff --git a/freeipa.spec.in b/freeipa.spec.in index dc06d410..f3168830 100644 --- a/freeipa.spec.in +++ b/freeipa.spec.in @@ -117,7 +117,7 @@ Requires(pre): systemd-units Requires(post): systemd-units %endif %if 0%{?fedora} >= 17 -Requires: selinux-policy >= 3.10.0-82 +Requires: selinux-policy >= 3.10.0-110 %else %if 0%{?fedora} == 16 Requires: selinux-policy >= 3.10.0-78 @@ -214,7 +214,7 @@ Requires: xmlrpc-c %endif %endif Requires: sssd >= 1.8.0 -Requires: certmonger >= 0.26 +Requires: certmonger >= 0.53 Requires: nss-tools Requires: bind-utils Requires: oddjob-mkhomedir @@ -538,6 +538,8 @@ fi %endif %dir %{python_sitelib}/ipaserver %{python_sitelib}/ipaserver/* +%dir %{_libdir}/ipa/certmonger +%attr(755,root,root) %{_libdir}/ipa/certmonger/* %dir %{_usr}/share/ipa %{_usr}/share/ipa/wsgi.py* %{_usr}/share/ipa/*.ldif @@ -674,6 +676,11 @@ fi %ghost %attr(0644,root,apache) %config(noreplace) %{_sysconfdir}/ipa/ca.crt %changelog +* Tue Apr 10 2012 Rob Crittenden - 2.2.0-21 +- Set min for selinux-policy to 3.10.0-110 on F-17 to pick up certmonger + policy for restarting services. +- Set min for certmonger to 0.53 so we have the -C option to set restart + commands. * Thu Apr 5 2012 Rob Crittenden - 2.2.0-20 - Bump minimum version of slapi-nis to 0.40 diff --git a/install/Makefile.am b/install/Makefile.am index 1b0cda90..4d24d072 100644 --- a/install/Makefile.am +++ b/install/Makefile.am @@ -13,6 +13,7 @@ SUBDIRS = \ tools \ updates \ po \ + restart_scripts \ $(NULL) install-exec-local: diff --git a/install/configure.ac b/install/configure.ac index bb1ec502..827ddbab 100644 --- a/install/configure.ac +++ b/install/configure.ac @@ -81,6 +81,7 @@ AC_CONFIG_FILES([ tools/man/Makefile updates/Makefile po/Makefile + restart_scripts/Makefile ]) AC_OUTPUT diff --git a/install/restart_scripts/Makefile.am b/install/restart_scripts/Makefile.am new file mode 100644 index 00000000..abc066b3 --- /dev/null +++ b/install/restart_scripts/Makefile.am @@ -0,0 +1,15 @@ +NULL = + +appdir = $(libdir)/ipa/certmonger +app_DATA = \ + restart_dirsrv \ + restart_httpd \ + $(NULL) + +EXTRA_DIST = \ + $(app_DATA) \ + $(NULL) + +MAINTAINERCLEANFILES = \ + *~ \ + Makefile.in diff --git a/install/restart_scripts/README b/install/restart_scripts/README new file mode 100644 index 00000000..64ad8b43 --- /dev/null +++ b/install/restart_scripts/README @@ -0,0 +1,2 @@ +This directory contains scripts to be used by the command (-C) option +of certmonger to restart services when the certificates are renewed. diff --git a/install/restart_scripts/restart_dirsrv b/install/restart_scripts/restart_dirsrv new file mode 100644 index 00000000..e243583f --- /dev/null +++ b/install/restart_scripts/restart_dirsrv @@ -0,0 +1,13 @@ +#!/usr/bin/python -E +import sys +from ipapython import services as ipaservices + +try: + instance = sys.argv[1] +except IndexError: + instance = "" + +try: + ipaservices.knownservices.dirsrv.restart(instance) +except Exception, e: + print "Cannot restart dirsrv (instance: '%s'): %s" % (instance, str(e)) diff --git a/install/restart_scripts/restart_httpd b/install/restart_scripts/restart_httpd new file mode 100644 index 00000000..a53ab6e6 --- /dev/null +++ b/install/restart_scripts/restart_httpd @@ -0,0 +1,7 @@ +#!/usr/bin/python -E +from ipapython import services as ipaservices + +try: + ipaservices.knownservices.httpd.restart() +except Exception, e: + print "Cannot restart httpd: %s" % str(e) diff --git a/ipapython/certmonger.py b/ipapython/certmonger.py index fda539b3..22a599ae 100644 --- a/ipapython/certmonger.py +++ b/ipapython/certmonger.py @@ -189,11 +189,15 @@ def cert_exists(nickname, secdir): else: return False -def start_tracking(nickname, secdir, password_file=None): +def start_tracking(nickname, secdir, password_file=None, command=None): """ Tell certmonger to track the given certificate nickname in NSS database in secdir protected by optional password file password_file. + command is an optional parameter which specifies a command for + certmonger to run when it renews a certificate. This command must + reside in /usr/lib/ipa/certmonger to work with SELinux. + Returns the stdout, stderr and returncode from running ipa-getcert This assumes that certmonger is already running. @@ -206,6 +210,9 @@ def start_tracking(nickname, secdir, password_file=None): if password_file: args.append("-p") args.append(os.path.abspath(password_file)) + if command: + args.append("-C") + args.append(command) (stdout, stderr, returncode) = ipautil.run(args) diff --git a/ipaserver/install/certs.py b/ipaserver/install/certs.py index 13770811..d25a471e 100644 --- a/ipaserver/install/certs.py +++ b/ipaserver/install/certs.py @@ -18,6 +18,7 @@ # import os, stat, subprocess, re +import sys import errno import tempfile import shutil @@ -492,16 +493,25 @@ class CertDB(object): raise RuntimeError("Unable to find serial number") - def track_server_cert(self, nickname, principal, password_file=None): + def track_server_cert(self, nickname, principal, password_file=None, command=None): """ Tell certmonger to track the given certificate nickname. + + If command is not a full path then it is prefixed with + /usr/lib[64]/ipa/certmonger. """ + if command is not None and not os.path.isabs(command): + if sys.maxsize > 2**32: + libpath = 'lib64' + else: + libpath = 'lib' + command = '/usr/%s/ipa/certmonger/%s' % (libpath, command) cmonger = ipaservices.knownservices.certmonger cmonger.enable() ipaservices.knownservices.messagebus.start() cmonger.start() try: - (stdout, stderr, rc) = certmonger.start_tracking(nickname, self.secdir, password_file) + (stdout, stderr, rc) = certmonger.start_tracking(nickname, self.secdir, password_file, command) except (ipautil.CalledProcessError, RuntimeError), e: root_logger.error("certmonger failed starting to track certificate: %s" % str(e)) return diff --git a/ipaserver/install/dsinstance.py b/ipaserver/install/dsinstance.py index 0dc3d256..5a92bf97 100644 --- a/ipaserver/install/dsinstance.py +++ b/ipaserver/install/dsinstance.py @@ -513,21 +513,21 @@ class DsInstance(service.Service): # We only handle one server cert nickname = server_certs[0][0] self.dercert = dsdb.get_cert_from_db(nickname, pem=False) - dsdb.track_server_cert(nickname, self.principal, dsdb.passwd_fname) + dsdb.track_server_cert(nickname, self.principal, dsdb.passwd_fname, 'restart_dirsrv %s' % self.serverid ) else: nickname = "Server-Cert" cadb = certs.CertDB(self.realm_name, host_name=self.fqdn, subject_base=self.subject_base) if self.self_signed_ca: dsdb.create_from_cacert(cadb.cacert_fname, passwd=None) self.dercert = dsdb.create_server_cert("Server-Cert", self.fqdn, cadb) - dsdb.track_server_cert("Server-Cert", self.principal, dsdb.passwd_fname) + dsdb.track_server_cert("Server-Cert", self.principal, dsdb.passwd_fname, 'restart_dirsrv %s' % self.serverid) dsdb.create_pin_file() else: # FIXME, need to set this nickname in the RA plugin cadb.export_ca_cert('ipaCert', False) dsdb.create_from_cacert(cadb.cacert_fname, passwd=None) self.dercert = dsdb.create_server_cert("Server-Cert", self.fqdn, cadb) - dsdb.track_server_cert("Server-Cert", self.principal, dsdb.passwd_fname) + dsdb.track_server_cert("Server-Cert", self.principal, dsdb.passwd_fname, 'restart_dirsrv %s' % self.serverid) dsdb.create_pin_file() conn = ipaldap.IPAdmin("127.0.0.1") diff --git a/ipaserver/install/httpinstance.py b/ipaserver/install/httpinstance.py index 0a09c26f..e1bbc30a 100644 --- a/ipaserver/install/httpinstance.py +++ b/ipaserver/install/httpinstance.py @@ -210,7 +210,7 @@ class HTTPInstance(service.Service): # We only handle one server cert nickname = server_certs[0][0] self.dercert = db.get_cert_from_db(nickname, pem=False) - db.track_server_cert(nickname, self.principal, db.passwd_fname) + db.track_server_cert(nickname, self.principal, db.passwd_fname, 'restart_httpd') self.__set_mod_nss_nickname(nickname) else: @@ -219,7 +219,7 @@ class HTTPInstance(service.Service): db.create_password_conf() self.dercert = db.create_server_cert("Server-Cert", self.fqdn, ca_db) - db.track_server_cert("Server-Cert", self.principal, db.passwd_fname) + db.track_server_cert("Server-Cert", self.principal, db.passwd_fname, 'restart_httpd') db.create_signing_cert("Signing-Cert", "Object Signing Cert", ca_db) # Fix the database permissions -- cgit