[Freeipa-devel] [PATCH] 0072..0075 Lightweight CA renewal
Fraser Tweedale
ftweedal at redhat.com
Fri Jun 24 06:49:43 UTC 2016
On Thu, Jun 23, 2016 at 09:51:02AM +0200, Jan Cholasta wrote:
> Hi,
>
> On 21.6.2016 08:24, Fraser Tweedale wrote:
> > The attached patches add lightweight CA renewal. There are two
> > substantive aspects:
> >
> > 1. The renew_ca_cert updates the serial number in the lightweight
> > CA's entry in the Dogtag database. This causes CA clones to observe
> > the renewal and update the certs in their own NSSDBs.
> >
> > 2. The ipa-certupdate command adds Certmonger tracking requests for
> > lightweight CAs (on the renewal master only).
> >
> > Correct behaviour also depends on my patch 0069 (in-server API for
> > renew_ca_cert script).
>
> Patch 0072-0074: LGTM
>
> Patch 0075:
>
> 1) Lightweight CA certs should be tracked by certmonger on all CA servers,
> not just on the renewal master. The behavior should be the same as for the
> main CA cert, i.e. the actual renewal is done only on the renewal master,
> other CA servers only update their NSS DBs (this is handled in
> dogtag-ipa-ca-renew-agent-submit).
>
> This is important because CA renewal master can change at any time, and
> without all CA certs being tracked on all CA servers, there is no guarantee
> the renewal would happen.
>
> 2) Since CA clones update their NSS DBs on their own,
> dogtag-ipa-ca-renew-agent should be updated not to put them in
> cn=ca_renewal,cn=ipa,cn=etc.
>
Thanks for the review, Honza. Updated patch 0075-2 attached.
-------------- next part --------------
From 9256f36d8df206642a51964ae2f40f4905e0c0bc Mon Sep 17 00:00:00 2001
From: Fraser Tweedale <ftweedal at redhat.com>
Date: Tue, 21 Jun 2016 15:01:41 +1000
Subject: [PATCH] ipa-certupdate: track lightweight CA certificates
Enhance the ipa-certupdate program to add Certmonger tracking
requests for lightweight CA certificates.
Also update the dogtag-ipa-ca-renew-agent-submit to not store or
retrieve lightweight CA certificates, becaues Dogtag clones observe
renewals and update their NSSDBs on their own, and allow the helper
to request non-self-signed certificates.
Part of: https://fedorahosted.org/freeipa/ticket/4559
---
.../certmonger/dogtag-ipa-ca-renew-agent-submit | 39 +++++++++++++---
ipaclient/ipa_certupdate.py | 52 ++++++++++++++++++++--
2 files changed, 82 insertions(+), 9 deletions(-)
diff --git a/install/certmonger/dogtag-ipa-ca-renew-agent-submit b/install/certmonger/dogtag-ipa-ca-renew-agent-submit
index 3f7333c0e0bb6059e8b3791ef5230c7e5663d2eb..7ab3ec15db37894ed443aa16b7edcf85d69c8192 100755
--- a/install/certmonger/dogtag-ipa-ca-renew-agent-submit
+++ b/install/certmonger/dogtag-ipa-ca-renew-agent-submit
@@ -62,6 +62,24 @@ if six.PY3:
unicode = str
+IPA_CA_NICKNAME = 'caSigningCert cert-pki-ca'
+
+def get_nickname():
+ csr = os.environ.get('CERTMONGER_CSR')
+ return pkcs10.get_friendlyname(csr) if csr else None
+
+def is_lightweight_ca():
+ nickname = get_nickname() or ''
+ return nickname != IPA_CA_NICKNAME and nickname.startswith(IPA_CA_NICKNAME)
+
+def is_renewable():
+ cert = os.environ.get('CERTMONGER_CERTIFICATE')
+ if not cert:
+ return False
+ else:
+ return x509.is_self_signed(cert) or is_lightweight_ca()
+
+
@contextlib.contextmanager
def ldap_connect():
conn = None
@@ -210,6 +228,11 @@ def store_cert():
if not cert:
return (REJECTED, "New certificate requests not supported")
+ if is_lightweight_ca():
+ # Lightweight CAs are updated in Dogtag's NSSDB
+ # by Dogtag itself, so do not store it
+ return (ISSUED, cert)
+
dercert = x509.normalize_certificate(cert)
dn = DN(('cn', nickname), ('cn', 'ca_renewal'),
@@ -338,6 +361,12 @@ def retrieve_cert_continuous():
if old_cert:
old_cert = x509.normalize_certificate(old_cert)
+ if is_lightweight_ca():
+ # Lightweight CAs are updated in Dogtag's NSSDB
+ # by Dogtag itself, so do not try to retrieve it.
+ # Everything is fine as is.
+ return (ISSUED, os.environ.get('CERTMONGER_CERTIFICATE'))
+
result = call_handler(retrieve_or_reuse_cert)
if result[0] != ISSUED:
return result
@@ -393,13 +422,12 @@ def renew_ca_cert():
cert = os.environ.get('CERTMONGER_CERTIFICATE')
if not cert:
return (REJECTED, "New certificate requests not supported")
- is_self_signed = x509.is_self_signed(cert)
operation = os.environ.get('CERTMONGER_OPERATION')
if operation == 'SUBMIT':
state = 'retrieve'
- if is_self_signed:
+ if is_renewable():
ca = cainstance.CAInstance(host_name=api.env.host, ldapi=False)
if ca.is_renewal_master():
state = 'request'
@@ -419,10 +447,11 @@ def renew_ca_cert():
if state == 'retrieve':
result = call_handler(retrieve_cert)
- if result[0] == REJECTED and not is_self_signed:
+ if result[0] == REJECTED and not is_renewable():
syslog.syslog(syslog.LOG_ALERT,
- "IPA CA certificate is about to expire, "
- "use ipa-cacert-manage to renew it")
+ "Certificate with subject '%s' is about to expire, "
+ "use ipa-cacert-manage to renew it"
+ % (os.environ.get("CERTMONGER_REQ_SUBJECT"),))
elif state == 'request':
profile = os.environ['CERTMONGER_CA_PROFILE']
os.environ['CERTMONGER_CA_PROFILE'] = 'caCACert'
diff --git a/ipaclient/ipa_certupdate.py b/ipaclient/ipa_certupdate.py
index b9572196c0eab3b35aa62790eed4ce8a21e3c130..e59047a2705eb8ccb98b5213c4c8771f55a29bc5 100644
--- a/ipaclient/ipa_certupdate.py
+++ b/ipaclient/ipa_certupdate.py
@@ -29,7 +29,10 @@ from ipaplatform import services
from ipaplatform.paths import paths
from ipaplatform.tasks import tasks
from ipalib import api, errors, x509, certstore
+from ipalib.constants import IPA_CA_CN
+IPA_CA_NICKNAME = 'caSigningCert cert-pki-ca'
+RENEWAL_CA_NAME = 'dogtag-ipa-ca-renew-agent'
class CertUpdate(admintool.AdminTool):
command_name = 'ipa-certupdate'
@@ -76,18 +79,27 @@ class CertUpdate(admintool.AdminTool):
version=u'2.0',
)
ca_enabled = result['result']['enable_ra']
- api.Backend.rpcclient.disconnect()
ldap.do_sasl_gssapi_bind()
certs = certstore.get_ca_certs(ldap, api.env.basedn,
api.env.realm, ca_enabled)
+
+ # find lightweight CAs (on renewal master only)
+ lwcas = []
+ for ca_obj in api.Command.ca_find()['result']:
+ if IPA_CA_CN not in ca_obj['cn']:
+ lwcas.append(ca_obj)
+
+ api.Backend.rpcclient.disconnect()
finally:
shutil.rmtree(tmpdir)
server_fstore = sysrestore.FileStore(paths.SYSRESTORE)
if server_fstore.has_files():
self.update_server(certs)
+ for entry in lwcas:
+ self.server_track_lightweight_ca(entry)
self.update_client(certs)
@@ -122,11 +134,10 @@ class CertUpdate(admintool.AdminTool):
if services.knownservices.httpd.is_running():
services.knownservices.httpd.restart()
- nickname = 'caSigningCert cert-pki-ca'
criteria = {
'cert-database': paths.PKI_TOMCAT_ALIAS_DIR,
- 'cert-nickname': nickname,
- 'ca-name': 'dogtag-ipa-ca-renew-agent',
+ 'cert-nickname': IPA_CA_NICKNAME,
+ 'ca-name': RENEWAL_CA_NAME
}
request_id = certmonger.get_request_id(criteria)
if request_id is not None:
@@ -152,6 +163,39 @@ class CertUpdate(admintool.AdminTool):
self.update_file(paths.CA_CRT, certs)
+ def server_track_lightweight_ca(self, entry):
+ nickname = "{} {}".format(IPA_CA_NICKNAME, entry['ipacaid'][0])
+ criteria = {
+ 'cert-database': paths.PKI_TOMCAT_ALIAS_DIR,
+ 'cert-nickname': nickname,
+ 'ca-name': RENEWAL_CA_NAME,
+ }
+ request_id = certmonger.get_request_id(criteria)
+ if request_id is None:
+ try:
+ certmonger.dogtag_start_tracking(
+ secdir=paths.PKI_TOMCAT_ALIAS_DIR,
+ pin=certmonger.get_pin('internal'),
+ pinfile=None,
+ nickname=nickname,
+ ca=RENEWAL_CA_NAME,
+ pre_command='stop_pkicad',
+ post_command='renew_ca_cert "%s"' % nickname,
+ )
+ request_id = certmonger.get_request_id(criteria)
+ certmonger.modify(request_id, profile='ipaCACertRenewal')
+ self.log.debug(
+ 'Lightweight CA renewal: '
+ 'added tracking request for "%s"', nickname)
+ except RuntimeError as e:
+ self.log.error(
+ 'Lightweight CA renewal: Certmonger failed to '
+ 'start tracking certificate: %s', e)
+ else:
+ self.log.debug(
+ 'Lightweight CA renewal: '
+ 'already tracking certificate "%s"', nickname)
+
def update_file(self, filename, certs, mode=0o444):
certs = (c[0] for c in certs if c[2] is not False)
try:
--
2.5.5
More information about the Freeipa-devel
mailing list