summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFraser Tweedale <ftweedal@redhat.com>2016-06-21 15:01:41 +1000
committerJan Cholasta <jcholast@redhat.com>2016-06-29 08:52:29 +0200
commit0078e7a9192a940104d8f6621b33d24d814c109b (patch)
tree378d84d9d1e72c0ffa51dbe3a40f62d4f4f91ad5
parentb720aa94e9317b857734c08a69fe2dcc0d95bf68 (diff)
downloadfreeipa-0078e7a9192a940104d8f6621b33d24d814c109b.tar.gz
freeipa-0078e7a9192a940104d8f6621b33d24d814c109b.tar.xz
freeipa-0078e7a9192a940104d8f6621b33d24d814c109b.zip
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 Reviewed-By: Jan Cholasta <jcholast@redhat.com>
-rwxr-xr-xinstall/certmonger/dogtag-ipa-ca-renew-agent-submit39
-rw-r--r--ipaclient/ipa_certupdate.py52
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 3f7333c0e..7ab3ec15d 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 b9572196c..e59047a27 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: