renew agent: get rid of virtual profiles

Replace all uses of virtual profiles with `dogtag-ipa-ca-renew-agent-reuse`
and remove profile from the IPA CA certificate tracking request.

This prevents virtual profiles from making their way into CSRs and in turn
being rejected by certain CAs. This affected the IPA CA CSR with Microsoft
CS in particular.

https://pagure.io/freeipa/issue/5799

Reviewed-By: David Kupka <dkupka@redhat.com>
Reviewed-By: Stanislav Laznicka <slaznick@redhat.com>
This commit is contained in:
Jan Cholasta 2017-04-24 06:40:11 +00:00 committed by David Kupka
parent 0bf41e804e
commit 21f4cbf8da
8 changed files with 46 additions and 67 deletions

View File

@ -297,7 +297,7 @@ def store_cert(**kwargs):
syslog.syslog( syslog.syslog(
syslog.LOG_ERR, syslog.LOG_ERR,
"Giving up. To retry storing the certificate, resubmit the " "Giving up. To retry storing the certificate, resubmit the "
"request with profile \"ipaStorage\"") "request with CA \"dogtag-ipa-ca-renew-agent-reuse\"")
return (ISSUED, cert) return (ISSUED, cert)
@ -420,33 +420,6 @@ def retrieve_cert(**kwargs):
return result return result
def export_csr(**kwargs):
"""
This does not actually renew the cert, it just writes the CSR provided
by certmonger to /var/lib/ipa/ca.csr and returns the existing cert.
"""
operation = os.environ.get('CERTMONGER_OPERATION')
if operation != 'SUBMIT':
return (OPERATION_NOT_SUPPORTED_BY_HELPER,)
csr = os.environ.get('CERTMONGER_CSR')
if not csr:
return (UNCONFIGURED, "Certificate request not provided")
cert = os.environ.get('CERTMONGER_CERTIFICATE')
if not cert:
return (REJECTED, "New certificate requests not supported")
csr_file = paths.IPA_CA_CSR
try:
with open(csr_file, 'wb') as f:
f.write(csr)
except Exception as e:
return (UNREACHABLE, "Failed to write %s: %s" % (csr_file, e))
return (ISSUED, cert)
def renew_ca_cert(reuse_existing, **kwargs): def renew_ca_cert(reuse_existing, **kwargs):
""" """
This is used for automatic CA certificate renewal. This is used for automatic CA certificate renewal.
@ -497,12 +470,15 @@ def renew_ca_cert(reuse_existing, **kwargs):
"use ipa-cacert-manage to renew it" "use ipa-cacert-manage to renew it"
% (os.environ.get("CERTMONGER_REQ_SUBJECT"),)) % (os.environ.get("CERTMONGER_REQ_SUBJECT"),))
elif state == 'request': elif state == 'request':
profile = os.environ['CERTMONGER_CA_PROFILE'] profile = os.environ.get('CERTMONGER_CA_PROFILE')
os.environ['CERTMONGER_CA_PROFILE'] = 'caCACert' os.environ['CERTMONGER_CA_PROFILE'] = 'caCACert'
result = call_handler(request_and_store_cert, result = call_handler(request_and_store_cert,
reuse_existing=reuse_existing, reuse_existing=reuse_existing,
**kwargs) **kwargs)
os.environ['CERTMONGER_CA_PROFILE'] = profile if profile is not None:
os.environ['CERTMONGER_CA_PROFILE'] = profile
else:
del os.environ['CERTMONGER_CA_PROFILE']
if result[0] == WAIT: if result[0] == WAIT:
return (result[0], '%s:%s' % (state, result[1])) return (result[0], '%s:%s' % (state, result[1]))
@ -522,14 +498,6 @@ def main():
else: else:
kwargs['reuse_existing'] = True kwargs['reuse_existing'] = True
handlers = {
'ipaStorage': store_cert,
'ipaRetrievalOrReuse': retrieve_or_reuse_cert,
'ipaRetrieval': retrieve_cert,
'ipaCSRExport': export_csr,
'ipaCACertRenewal': renew_ca_cert,
}
api.bootstrap(in_server=True, context='renew', confdir=paths.ETC_IPA) api.bootstrap(in_server=True, context='renew', confdir=paths.ETC_IPA)
api.finalize() api.finalize()
@ -547,15 +515,15 @@ def main():
api.Backend.ldap2.connect() api.Backend.ldap2.connect()
profile = os.environ.get('CERTMONGER_CA_PROFILE') if get_nickname() == IPA_CA_NICKNAME:
if is_replicated(): handler = renew_ca_cert
elif is_replicated():
if is_renewal_master(): if is_renewal_master():
handler = request_and_store_cert handler = request_and_store_cert
else: else:
handler = retrieve_cert_continuous handler = retrieve_cert_continuous
else: else:
handler = request_cert handler = request_cert
handler = handlers.get(profile, handler)
res = call_handler(handler, **kwargs) res = call_handler(handler, **kwargs)
for item in res[1:]: for item in res[1:]:

View File

@ -153,7 +153,7 @@ class CertUpdate(admintool.AdminTool):
self.log.debug("resubmitting certmonger request '%s'", request_id) self.log.debug("resubmitting certmonger request '%s'", request_id)
certmonger.resubmit_request( certmonger.resubmit_request(
request_id, profile='ipaRetrievalOrReuse') request_id, ca='dogtag-ipa-ca-renew-agent-reuse', profile='')
try: try:
state = certmonger.wait_for_request(request_id, timeout) state = certmonger.wait_for_request(request_id, timeout)
except RuntimeError: except RuntimeError:
@ -167,7 +167,7 @@ class CertUpdate(admintool.AdminTool):
"please check the request manually" % request_id) "please check the request manually" % request_id)
self.log.debug("modifying certmonger request '%s'", request_id) self.log.debug("modifying certmonger request '%s'", request_id)
certmonger.modify(request_id, profile='ipaCACertRenewal') certmonger.modify(request_id, ca='dogtag-ipa-ca-renew-agent')
self.update_file(paths.CA_CRT, certs) self.update_file(paths.CA_CRT, certs)

View File

@ -501,18 +501,29 @@ def stop_tracking(secdir=None, request_id=None, nickname=None, certfile=None):
request.parent.obj_if.remove_request(request.path) request.parent.obj_if.remove_request(request.path)
def modify(request_id, profile=None): def modify(request_id, ca=None, profile=None):
if profile: if ca or profile:
request = _get_request({'nickname': request_id}) request = _get_request({'nickname': request_id})
if request: update = {}
request.obj_if.modify({'template-profile': profile}) if ca is not None:
cm = _certmonger()
update['CA'] = cm.obj_if.find_ca_by_nickname(ca)
if profile is not None:
update['template-profile'] = profile
request.obj_if.modify(update)
def resubmit_request(request_id, profile=None): def resubmit_request(request_id, ca=None, profile=None):
request = _get_request({'nickname': request_id}) request = _get_request({'nickname': request_id})
if request: if request:
if profile: if ca or profile:
request.obj_if.modify({'template-profile': profile}) update = {}
if ca is not None:
cm = _certmonger()
update['CA'] = cm.obj_if.find_ca_by_nickname(ca)
if profile is not None:
update['template-profile'] = profile
request.obj_if.modify(update)
request.obj_if.resubmit() request.obj_if.resubmit()

View File

@ -279,10 +279,10 @@ class CAInstance(DogtagInstance):
2 = have signed cert, continue installation 2 = have signed cert, continue installation
""" """
tracking_reqs = (('auditSigningCert cert-pki-ca', None), tracking_reqs = ('auditSigningCert cert-pki-ca',
('ocspSigningCert cert-pki-ca', None), 'ocspSigningCert cert-pki-ca',
('subsystemCert cert-pki-ca', None), 'subsystemCert cert-pki-ca',
('caSigningCert cert-pki-ca', 'ipaCACertRenewal')) 'caSigningCert cert-pki-ca')
server_cert_name = 'Server-Cert cert-pki-ca' server_cert_name = 'Server-Cert cert-pki-ca'
def __init__(self, realm=None, host_name=None): def __init__(self, realm=None, host_name=None):

View File

@ -275,7 +275,7 @@ class DogtagInstance(service.Service):
""" Configure certmonger to renew system certs """ """ Configure certmonger to renew system certs """
pin = self.__get_pin() pin = self.__get_pin()
for nickname, profile in self.tracking_reqs: for nickname in self.tracking_reqs:
try: try:
certmonger.start_tracking( certmonger.start_tracking(
certpath=self.nss_db, certpath=self.nss_db,
@ -284,7 +284,7 @@ class DogtagInstance(service.Service):
pin=pin, pin=pin,
pre_command='stop_pkicad', pre_command='stop_pkicad',
post_command='renew_ca_cert "%s"' % nickname, post_command='renew_ca_cert "%s"' % nickname,
profile=profile) )
except RuntimeError as e: except RuntimeError as e:
self.log.error( self.log.error(
"certmonger failed to start tracking certificate: %s", e) "certmonger failed to start tracking certificate: %s", e)
@ -319,7 +319,7 @@ class DogtagInstance(service.Service):
services.knownservices.messagebus.start() services.knownservices.messagebus.start()
cmonger.start() cmonger.start()
nicknames = [nickname for nickname, _profile in self.tracking_reqs] nicknames = self.tracking_reqs
if self.server_cert_name is not None: if self.server_cert_name is not None:
nicknames.append(self.server_cert_name) nicknames.append(self.server_cert_name)

View File

@ -172,14 +172,14 @@ class CACertManage(admintool.AdminTool):
except errors.NotFound: except errors.NotFound:
raise admintool.ScriptError("CA renewal master not found") raise admintool.ScriptError("CA renewal master not found")
self.resubmit_request(ca, 'caCACert') self.resubmit_request()
print("CA certificate successfully renewed") print("CA certificate successfully renewed")
def renew_external_step_1(self, ca): def renew_external_step_1(self, ca):
print("Exporting CA certificate signing request, please wait") print("Exporting CA certificate signing request, please wait")
self.resubmit_request(ca, 'ipaCSRExport') self.resubmit_request('dogtag-ipa-ca-renew-agent-reuse')
print(("The next step is to get %s signed by your CA and re-run " print(("The next step is to get %s signed by your CA and re-run "
"ipa-cacert-manage as:" % paths.IPA_CA_CSR)) "ipa-cacert-manage as:" % paths.IPA_CA_CSR))
@ -282,15 +282,15 @@ class CACertManage(admintool.AdminTool):
except errors.NotFound: except errors.NotFound:
raise admintool.ScriptError("CA renewal master not found") raise admintool.ScriptError("CA renewal master not found")
self.resubmit_request(ca, 'ipaRetrieval') self.resubmit_request('dogtag-ipa-ca-renew-agent-reuse')
print("CA certificate successfully renewed") print("CA certificate successfully renewed")
def resubmit_request(self, ca, profile): def resubmit_request(self, ca='dogtag-ipa-ca-renew-agent'):
timeout = api.env.startup_timeout + 60 timeout = api.env.startup_timeout + 60
self.log.debug("resubmitting certmonger request '%s'", self.request_id) self.log.debug("resubmitting certmonger request '%s'", self.request_id)
certmonger.resubmit_request(self.request_id, profile=profile) certmonger.resubmit_request(self.request_id, ca=ca, profile='')
try: try:
state = certmonger.wait_for_request(self.request_id, timeout) state = certmonger.wait_for_request(self.request_id, timeout)
except RuntimeError: except RuntimeError:
@ -304,7 +304,7 @@ class CACertManage(admintool.AdminTool):
"please check the request manually" % self.request_id) "please check the request manually" % self.request_id)
self.log.debug("modifying certmonger request '%s'", self.request_id) self.log.debug("modifying certmonger request '%s'", self.request_id)
certmonger.modify(self.request_id, profile='ipaCACertRenewal') certmonger.modify(self.request_id, ca='dogtag-ipa-ca-renew-agent')
def install(self): def install(self):
print("Installing CA certificate, please wait") print("Installing CA certificate, please wait")

View File

@ -60,9 +60,9 @@ class KRAInstance(DogtagInstance):
be the same for both the CA and KRA. be the same for both the CA and KRA.
""" """
tracking_reqs = (('auditSigningCert cert-pki-kra', None), tracking_reqs = ('auditSigningCert cert-pki-kra',
('transportCert cert-pki-kra', None), 'transportCert cert-pki-kra',
('storageCert cert-pki-kra', None)) 'storageCert cert-pki-kra')
def __init__(self, realm): def __init__(self, realm):
super(KRAInstance, self).__init__( super(KRAInstance, self).__init__(

View File

@ -937,7 +937,7 @@ def certificate_renewal_update(ca, ds, http):
'cert-presave-command': template % 'stop_pkicad', 'cert-presave-command': template % 'stop_pkicad',
'cert-postsave-command': 'cert-postsave-command':
(template % 'renew_ca_cert "caSigningCert cert-pki-ca"'), (template % 'renew_ca_cert "caSigningCert cert-pki-ca"'),
'template-profile': 'ipaCACertRenewal', 'template-profile': '',
}, },
{ {
'cert-database': paths.PKI_TOMCAT_ALIAS_DIR, 'cert-database': paths.PKI_TOMCAT_ALIAS_DIR,