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
This commit is contained in:
Rob Crittenden
2012-04-10 21:21:08 +02:00
parent e9b79cc1e1
commit 717bbcd2bf
11 changed files with 73 additions and 10 deletions

View File

@@ -118,7 +118,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
@@ -215,7 +215,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
@@ -542,6 +542,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
@@ -681,6 +683,11 @@ fi
%ghost %attr(0644,root,apache) %config(noreplace) %{_sysconfdir}/ipa/ca.crt
%changelog
* Tue Apr 10 2012 Rob Crittenden <rcritten@redhat.com> - 2.99.0-28
- 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 <rcritten@redhat.com> - 2.99.0-27
- Bump minimum version of slapi-nis to 0.40

View File

@@ -13,6 +13,7 @@ SUBDIRS = \
tools \
updates \
po \
restart_scripts \
$(NULL)
install-exec-local:

View File

@@ -81,6 +81,7 @@ AC_CONFIG_FILES([
tools/man/Makefile
updates/Makefile
po/Makefile
restart_scripts/Makefile
])
AC_OUTPUT

View File

@@ -0,0 +1,15 @@
NULL =
appdir = $(libdir)/ipa/certmonger
app_DATA = \
restart_dirsrv \
restart_httpd \
$(NULL)
EXTRA_DIST = \
$(app_DATA) \
$(NULL)
MAINTAINERCLEANFILES = \
*~ \
Makefile.in

View File

@@ -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.

View File

@@ -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))

View File

@@ -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)

View File

@@ -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)

View File

@@ -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

View File

@@ -516,21 +516,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")

View File

@@ -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