summaryrefslogtreecommitdiffstats
path: root/ipaserver/install/cainstance.py
diff options
context:
space:
mode:
authorRob Crittenden <rcritten@redhat.com>2014-12-02 13:18:36 -0500
committerRob Crittenden <rcritten@redhat.com>2013-01-29 11:16:38 -0500
commit045b6e6ed995b4c1e5dab8dbcdf1af4896b52d19 (patch)
treeba63a832f67c4c9a8ceee62669b52dd37a853680 /ipaserver/install/cainstance.py
parentb382a77fc393a078ebbba8000284dd9abe75a3d5 (diff)
downloadfreeipa.git-045b6e6ed995b4c1e5dab8dbcdf1af4896b52d19.tar.gz
freeipa.git-045b6e6ed995b4c1e5dab8dbcdf1af4896b52d19.tar.xz
freeipa.git-045b6e6ed995b4c1e5dab8dbcdf1af4896b52d19.zip
Use new certmonger locking to prevent NSS database corruption.
dogtag opens its NSS database in read/write mode so we need to be very careful during renewal that we don't also open it up read/write. We basically need to serialize access to the database. certmonger does the majority of this work via internal locking from the point where it generates a new key/submits a rewewal through the pre_save and releases the lock after the post_save command. This lock is held per NSS database so we're save from certmonger. dogtag needs to be shutdown in the pre_save state so certmonger can safely add the certificate and we can manipulate trust in the post_save command. Fix a number of bugs in renewal. The CA wasn't actually being restarted at all due to a naming change upstream. In python we need to reference services using python-ish names but the service is pki-cad. We need a translation for non-Fedora systems as well. Update the CA ou=People entry when he CA subsystem certificate is renewed. This certificate is used as an identity certificate to bind to the DS instance. https://fedorahosted.org/freeipa/ticket/3292 https://fedorahosted.org/freeipa/ticket/3322
Diffstat (limited to 'ipaserver/install/cainstance.py')
-rw-r--r--ipaserver/install/cainstance.py113
1 files changed, 100 insertions, 13 deletions
diff --git a/ipaserver/install/cainstance.py b/ipaserver/install/cainstance.py
index 3d028a6a..a5cfc6fb 100644
--- a/ipaserver/install/cainstance.py
+++ b/ipaserver/install/cainstance.py
@@ -35,11 +35,13 @@ import urllib
import xml.dom.minidom
import stat
import socket
+import syslog
import ConfigParser
from ipapython import dogtag
from ipapython.certdb import get_ca_nickname
from ipapython import certmonger
from ipalib import pkcs10, x509
+from ipalib import errors
from ipapython.dn import DN
import subprocess
import traceback
@@ -1048,7 +1050,11 @@ class CAInstance(service.Service):
On upgrades this needs to be called from ipa-upgradeconfig.
"""
- certmonger.dogtag_start_tracking('dogtag-ipa-retrieve-agent-submit', 'ipaCert', None, '/etc/httpd/alias/pwdfile.txt', '/etc/httpd/alias', 'restart_httpd')
+ try:
+ certmonger.dogtag_start_tracking('dogtag-ipa-retrieve-agent-submit', 'ipaCert', None, '/etc/httpd/alias/pwdfile.txt', '/etc/httpd/alias', None, 'restart_httpd')
+ except (ipautil.CalledProcessError, RuntimeError), e:
+ root_logger.error(
+ "certmonger failed to start tracking certificate: %s" % str(e))
def __configure_ra(self):
# Create an RA user in the CA LDAP server and add that user to
@@ -1534,11 +1540,19 @@ class CAInstance(service.Service):
'Unable to determine PIN for CA instance: %s' % str(e))
def track_servercert(self):
+ """
+ Specifically do not tell certmonger to restart the CA. This will be
+ done by the renewal script, renew_ca_cert once all the subsystem
+ certificates are renewed.
+ """
pin = self.__get_ca_pin()
- certmonger.dogtag_start_tracking(
- 'dogtag-ipa-renew-agent', 'Server-Cert cert-pki-ca', pin, None,
- self.dogtag_constants.ALIAS_DIR,
- 'restart_pkicad "Server-Cert cert-pki-ca"')
+ try:
+ certmonger.dogtag_start_tracking(
+ 'dogtag-ipa-renew-agent', 'Server-Cert cert-pki-ca', pin, None,
+ self.dogtag_constants.ALIAS_DIR, None, None)
+ except (ipautil.CalledProcessError, RuntimeError), e:
+ root_logger.error(
+ "certmonger failed to start tracking certificate: %s" % str(e))
def configure_renewal(self):
cmonger = ipaservices.knownservices.certmonger
@@ -1552,12 +1566,20 @@ class CAInstance(service.Service):
for nickname in ['auditSigningCert cert-pki-ca',
'ocspSigningCert cert-pki-ca',
'subsystemCert cert-pki-ca']:
- certmonger.dogtag_start_tracking(
- 'dogtag-ipa-renew-agent', nickname, pin, None,
- self.dogtag_constants.ALIAS_DIR, 'renew_ca_cert "%s"' % nickname)
+ try:
+ certmonger.dogtag_start_tracking(
+ 'dogtag-ipa-renew-agent', nickname, pin, None,
+ self.dogtag_constants.ALIAS_DIR, 'stop_pkicad', 'renew_ca_cert "%s"' % nickname)
+ except (ipautil.CalledProcessError, RuntimeError), e:
+ root_logger.error(
+ "certmonger failed to start tracking certificate: %s" % str(e))
# Set up the agent cert for renewal
- certmonger.dogtag_start_tracking('dogtag-ipa-renew-agent', 'ipaCert', None, '/etc/httpd/alias/pwdfile.txt', '/etc/httpd/alias', 'renew_ra_cert')
+ try:
+ certmonger.dogtag_start_tracking('dogtag-ipa-renew-agent', 'ipaCert', None, '/etc/httpd/alias/pwdfile.txt', '/etc/httpd/alias', None, 'renew_ra_cert')
+ except (ipautil.CalledProcessError, RuntimeError), e:
+ root_logger.error(
+ "certmonger failed to start tracking certificate: %s" % str(e))
def configure_certmonger_renewal(self):
"""
@@ -1595,10 +1617,14 @@ class CAInstance(service.Service):
for nickname in ['auditSigningCert cert-pki-ca',
'ocspSigningCert cert-pki-ca',
'subsystemCert cert-pki-ca']:
- certmonger.dogtag_start_tracking(
- 'dogtag-ipa-retrieve-agent-submit', nickname, pin, None,
- self.dogtag_constants.ALIAS_DIR,
- 'restart_pkicad "%s"' % nickname)
+ try:
+ certmonger.dogtag_start_tracking(
+ 'dogtag-ipa-retrieve-agent-submit', nickname, pin, None,
+ self.dogtag_constants.ALIAS_DIR, 'stop_pkicad',
+ 'restart_pkicad "%s"' % nickname)
+ except (ipautil.CalledProcessError, RuntimeError), e:
+ root_logger.error(
+ "certmonger failed to start tracking certificate: %s" % str(e))
# The agent renewal is configured in import_ra_cert which is called
# after the HTTP instance is created.
@@ -1861,6 +1887,67 @@ def update_cert_config(nickname, cert):
base64.b64encode(cert),
quotes=False, separator='=')
+def update_people_entry(uid, dercert):
+ """
+ Update the userCerticate for an entry in the dogtag ou=People. This
+ is needed when a certificate is renewed.
+
+ uid: uid of user to update
+ dercert: An X509.3 certificate in DER format
+
+ Logging is done via syslog
+
+ Returns True or False
+ """
+ dn = DN(('uid',uid),('ou','People'),('o','ipaca'))
+ serial_number = x509.get_serial_number(dercert, datatype=x509.DER)
+ subject = x509.get_subject(dercert, datatype=x509.DER)
+ issuer = x509.get_issuer(dercert, datatype=x509.DER)
+
+ attempts = 0
+ dogtag_uri='ldap://localhost:%d' % DEFAULT_DSPORT
+ updated = False
+
+ try:
+ dm_password = certmonger.get_pin('internaldb')
+ except IOError, e:
+ syslog.syslog(syslog.LOG_ERR, 'Unable to determine PIN for CA instance: %s' % e)
+ return False
+
+ while attempts < 10:
+ conn = None
+ try:
+ conn = ldap2.ldap2(shared_instance=False, ldap_uri=dogtag_uri)
+ conn.connect(bind_dn=DN(('cn', 'directory manager')),
+ bind_pw=dm_password)
+ (entry_dn, entry_attrs) = conn.get_entry(dn, ['usercertificate'],
+ normalize=False)
+ entry_attrs['usercertificate'].append(dercert)
+ entry_attrs['description'] = '2;%d;%s;%s' % (serial_number, issuer,
+ subject)
+ conn.update_entry(dn, entry_attrs, normalize=False)
+ updated = True
+ break
+ except errors.NetworkError:
+ syslog.syslog(syslog.LOG_ERR, 'Connection to %s failed, sleeping 30s' % dogtag_uri)
+ time.sleep(30)
+ attempts += 1
+ except errors.EmptyModlist:
+ updated = True
+ break
+ except Exception, e:
+ syslog.syslog(syslog.LOG_ERR, 'Updating %s entry failed: %s' % (str(dn), e))
+ break
+ finally:
+ if conn.isconnected():
+ conn.disconnect()
+
+ if not updated:
+ syslog.syslog(syslog.LOG_ERR, 'Update failed.')
+ return False
+
+ return True
+
if __name__ == "__main__":
standard_logging_setup("install.log")
if not dogtag.install_constants.SHARED_DB: