mirror of
https://salsa.debian.org/freeipa-team/freeipa.git
synced 2025-02-25 18:55:28 -06:00
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>
This commit is contained in:
parent
b720aa94e9
commit
0078e7a919
@ -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'
|
||||
|
@ -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:
|
||||
|
Loading…
Reference in New Issue
Block a user