483b06
From 6a30753c5a437240e4678ef4acae3255ad6d15ee Mon Sep 17 00:00:00 2001
483b06
From: Jan Cholasta <jcholast@redhat.com>
483b06
Date: Mon, 24 Apr 2017 06:40:11 +0000
483b06
Subject: [PATCH] renew agent: get rid of virtual profiles
483b06
483b06
Replace all uses of virtual profiles with `dogtag-ipa-ca-renew-agent-reuse`
483b06
and remove profile from the IPA CA certificate tracking request.
483b06
483b06
This prevents virtual profiles from making their way into CSRs and in turn
483b06
being rejected by certain CAs. This affected the IPA CA CSR with Microsoft
483b06
CS in particular.
483b06
483b06
https://pagure.io/freeipa/issue/5799
483b06
483b06
Reviewed-By: David Kupka <dkupka@redhat.com>
483b06
Reviewed-By: Stanislav Laznicka <slaznick@redhat.com>
483b06
---
483b06
 .../certmonger/dogtag-ipa-ca-renew-agent-submit    | 50 ++++------------------
483b06
 ipaclient/install/ipa_certupdate.py                |  4 +-
483b06
 ipalib/install/certmonger.py                       | 25 ++++++++---
483b06
 ipaserver/install/cainstance.py                    |  8 ++--
483b06
 ipaserver/install/dogtaginstance.py                |  6 +--
483b06
 ipaserver/install/ipa_cacert_manage.py             | 12 +++---
483b06
 ipaserver/install/krainstance.py                   |  6 +--
483b06
 ipaserver/install/server/upgrade.py                |  2 +-
483b06
 8 files changed, 46 insertions(+), 67 deletions(-)
483b06
483b06
diff --git a/install/certmonger/dogtag-ipa-ca-renew-agent-submit b/install/certmonger/dogtag-ipa-ca-renew-agent-submit
483b06
index 657a1bc638e1da680522c638e92914098fc6ab4b..3d3e791449014082060ecdc50118a28a9ef315b8 100755
483b06
--- a/install/certmonger/dogtag-ipa-ca-renew-agent-submit
483b06
+++ b/install/certmonger/dogtag-ipa-ca-renew-agent-submit
483b06
@@ -297,7 +297,7 @@ def store_cert(**kwargs):
483b06
             syslog.syslog(
483b06
                 syslog.LOG_ERR,
483b06
                 "Giving up. To retry storing the certificate, resubmit the "
483b06
-                "request with profile \"ipaStorage\"")
483b06
+                "request with CA \"dogtag-ipa-ca-renew-agent-reuse\"")
483b06
 
483b06
     return (ISSUED, cert)
483b06
 
483b06
@@ -420,33 +420,6 @@ def retrieve_cert(**kwargs):
483b06
     return result
483b06
 
483b06
 
483b06
-def export_csr(**kwargs):
483b06
-    """
483b06
-    This does not actually renew the cert, it just writes the CSR provided
483b06
-    by certmonger to /var/lib/ipa/ca.csr and returns the existing cert.
483b06
-    """
483b06
-    operation = os.environ.get('CERTMONGER_OPERATION')
483b06
-    if operation != 'SUBMIT':
483b06
-        return (OPERATION_NOT_SUPPORTED_BY_HELPER,)
483b06
-
483b06
-    csr = os.environ.get('CERTMONGER_CSR')
483b06
-    if not csr:
483b06
-        return (UNCONFIGURED, "Certificate request not provided")
483b06
-
483b06
-    cert = os.environ.get('CERTMONGER_CERTIFICATE')
483b06
-    if not cert:
483b06
-        return (REJECTED, "New certificate requests not supported")
483b06
-
483b06
-    csr_file = paths.IPA_CA_CSR
483b06
-    try:
483b06
-        with open(csr_file, 'wb') as f:
483b06
-            f.write(csr)
483b06
-    except Exception as e:
483b06
-        return (UNREACHABLE, "Failed to write %s: %s" % (csr_file, e))
483b06
-
483b06
-    return (ISSUED, cert)
483b06
-
483b06
-
483b06
 def renew_ca_cert(reuse_existing, **kwargs):
483b06
     """
483b06
     This is used for automatic CA certificate renewal.
483b06
@@ -497,12 +470,15 @@ def renew_ca_cert(reuse_existing, **kwargs):
483b06
                           "use ipa-cacert-manage to renew it"
483b06
                           % (os.environ.get("CERTMONGER_REQ_SUBJECT"),))
483b06
     elif state == 'request':
483b06
-        profile = os.environ['CERTMONGER_CA_PROFILE']
483b06
+        profile = os.environ.get('CERTMONGER_CA_PROFILE')
483b06
         os.environ['CERTMONGER_CA_PROFILE'] = 'caCACert'
483b06
         result = call_handler(request_and_store_cert,
483b06
                               reuse_existing=reuse_existing,
483b06
                               **kwargs)
483b06
-        os.environ['CERTMONGER_CA_PROFILE'] = profile
483b06
+        if profile is not None:
483b06
+            os.environ['CERTMONGER_CA_PROFILE'] = profile
483b06
+        else:
483b06
+            del os.environ['CERTMONGER_CA_PROFILE']
483b06
 
483b06
     if result[0] == WAIT:
483b06
         return (result[0], '%s:%s' % (state, result[1]))
483b06
@@ -522,14 +498,6 @@ def main():
483b06
     else:
483b06
         kwargs['reuse_existing'] = True
483b06
 
483b06
-    handlers = {
483b06
-        'ipaStorage':           store_cert,
483b06
-        'ipaRetrievalOrReuse':  retrieve_or_reuse_cert,
483b06
-        'ipaRetrieval':         retrieve_cert,
483b06
-        'ipaCSRExport':         export_csr,
483b06
-        'ipaCACertRenewal':     renew_ca_cert,
483b06
-    }
483b06
-
483b06
     api.bootstrap(in_server=True, context='renew', confdir=paths.ETC_IPA)
483b06
     api.finalize()
483b06
 
483b06
@@ -547,15 +515,15 @@ def main():
483b06
 
483b06
         api.Backend.ldap2.connect()
483b06
 
483b06
-        profile = os.environ.get('CERTMONGER_CA_PROFILE')
483b06
-        if is_replicated():
483b06
+        if get_nickname() == IPA_CA_NICKNAME:
483b06
+            handler = renew_ca_cert
483b06
+        elif is_replicated():
483b06
             if is_renewal_master():
483b06
                 handler = request_and_store_cert
483b06
             else:
483b06
                 handler = retrieve_cert_continuous
483b06
         else:
483b06
             handler = request_cert
483b06
-        handler = handlers.get(profile, handler)
483b06
 
483b06
         res = call_handler(handler, **kwargs)
483b06
         for item in res[1:]:
483b06
diff --git a/ipaclient/install/ipa_certupdate.py b/ipaclient/install/ipa_certupdate.py
483b06
index d6ffbde1900280b548877752726e4f066632877a..7dc88f07ae14e5416f6fe3dc8400b7d4bcabef72 100644
483b06
--- a/ipaclient/install/ipa_certupdate.py
483b06
+++ b/ipaclient/install/ipa_certupdate.py
483b06
@@ -153,7 +153,7 @@ class CertUpdate(admintool.AdminTool):
483b06
 
483b06
             self.log.debug("resubmitting certmonger request '%s'", request_id)
483b06
             certmonger.resubmit_request(
483b06
-                request_id, profile='ipaRetrievalOrReuse')
483b06
+                request_id, ca='dogtag-ipa-ca-renew-agent-reuse', profile='')
483b06
             try:
483b06
                 state = certmonger.wait_for_request(request_id, timeout)
483b06
             except RuntimeError:
483b06
@@ -167,7 +167,7 @@ class CertUpdate(admintool.AdminTool):
483b06
                     "please check the request manually" % request_id)
483b06
 
483b06
             self.log.debug("modifying certmonger request '%s'", request_id)
483b06
-            certmonger.modify(request_id, profile='ipaCACertRenewal')
483b06
+            certmonger.modify(request_id, ca='dogtag-ipa-ca-renew-agent')
483b06
 
483b06
         self.update_file(paths.CA_CRT, certs)
483b06
 
483b06
diff --git a/ipalib/install/certmonger.py b/ipalib/install/certmonger.py
483b06
index 2a7876ea9ba986f57c00fc7ad61d10fe91894f55..5709853ffebdbf58929b9a935e906ae67341bea8 100644
483b06
--- a/ipalib/install/certmonger.py
483b06
+++ b/ipalib/install/certmonger.py
483b06
@@ -501,18 +501,29 @@ def stop_tracking(secdir=None, request_id=None, nickname=None, certfile=None):
483b06
         request.parent.obj_if.remove_request(request.path)
483b06
 
483b06
 
483b06
-def modify(request_id, profile=None):
483b06
-    if profile:
483b06
+def modify(request_id, ca=None, profile=None):
483b06
+    if ca or profile:
483b06
         request = _get_request({'nickname': request_id})
483b06
-        if request:
483b06
-            request.obj_if.modify({'template-profile': profile})
483b06
+        update = {}
483b06
+        if ca is not None:
483b06
+            cm = _certmonger()
483b06
+            update['CA'] = cm.obj_if.find_ca_by_nickname(ca)
483b06
+        if profile is not None:
483b06
+            update['template-profile'] = profile
483b06
+        request.obj_if.modify(update)
483b06
 
483b06
 
483b06
-def resubmit_request(request_id, profile=None):
483b06
+def resubmit_request(request_id, ca=None, profile=None):
483b06
     request = _get_request({'nickname': request_id})
483b06
     if request:
483b06
-        if profile:
483b06
-            request.obj_if.modify({'template-profile': profile})
483b06
+        if ca or profile:
483b06
+            update = {}
483b06
+            if ca is not None:
483b06
+                cm = _certmonger()
483b06
+                update['CA'] = cm.obj_if.find_ca_by_nickname(ca)
483b06
+            if profile is not None:
483b06
+                update['template-profile'] = profile
483b06
+            request.obj_if.modify(update)
483b06
         request.obj_if.resubmit()
483b06
 
483b06
 
483b06
diff --git a/ipaserver/install/cainstance.py b/ipaserver/install/cainstance.py
483b06
index ff5432d1a7460f1b853c7cf7490b3604c82cd1f7..a4aa4f2069277181501ebd92f3795c452b10acd0 100644
483b06
--- a/ipaserver/install/cainstance.py
483b06
+++ b/ipaserver/install/cainstance.py
483b06
@@ -279,10 +279,10 @@ class CAInstance(DogtagInstance):
483b06
        2 = have signed cert, continue installation
483b06
     """
483b06
 
483b06
-    tracking_reqs = (('auditSigningCert cert-pki-ca', None),
483b06
-                     ('ocspSigningCert cert-pki-ca', None),
483b06
-                     ('subsystemCert cert-pki-ca', None),
483b06
-                     ('caSigningCert cert-pki-ca', 'ipaCACertRenewal'))
483b06
+    tracking_reqs = ('auditSigningCert cert-pki-ca',
483b06
+                     'ocspSigningCert cert-pki-ca',
483b06
+                     'subsystemCert cert-pki-ca',
483b06
+                     'caSigningCert cert-pki-ca')
483b06
     server_cert_name = 'Server-Cert cert-pki-ca'
483b06
 
483b06
     def __init__(self, realm=None, host_name=None):
483b06
diff --git a/ipaserver/install/dogtaginstance.py b/ipaserver/install/dogtaginstance.py
483b06
index e0515973f7a598b30c6f12675b9ebdbfd0cf3423..3ba13815055612c5fff44831c8f874e6175d94cd 100644
483b06
--- a/ipaserver/install/dogtaginstance.py
483b06
+++ b/ipaserver/install/dogtaginstance.py
483b06
@@ -287,7 +287,7 @@ class DogtagInstance(service.Service):
483b06
         """ Configure certmonger to renew system certs """
483b06
         pin = self.__get_pin()
483b06
 
483b06
-        for nickname, profile in self.tracking_reqs:
483b06
+        for nickname in self.tracking_reqs:
483b06
             try:
483b06
                 certmonger.start_tracking(
483b06
                     certpath=self.nss_db,
483b06
@@ -296,7 +296,7 @@ class DogtagInstance(service.Service):
483b06
                     pin=pin,
483b06
                     pre_command='stop_pkicad',
483b06
                     post_command='renew_ca_cert "%s"' % nickname,
483b06
-                    profile=profile)
483b06
+                )
483b06
             except RuntimeError as e:
483b06
                 self.log.error(
483b06
                     "certmonger failed to start tracking certificate: %s", e)
483b06
@@ -331,7 +331,7 @@ class DogtagInstance(service.Service):
483b06
         services.knownservices.messagebus.start()
483b06
         cmonger.start()
483b06
 
483b06
-        nicknames = [nickname for nickname, _profile in self.tracking_reqs]
483b06
+        nicknames = self.tracking_reqs
483b06
         if self.server_cert_name is not None:
483b06
             nicknames.append(self.server_cert_name)
483b06
 
483b06
diff --git a/ipaserver/install/ipa_cacert_manage.py b/ipaserver/install/ipa_cacert_manage.py
483b06
index 363ba378ab206fae5c220b754f212666f20384af..6d28c62b36b3909c9a3d95a5c6c84d1779fe4c33 100644
483b06
--- a/ipaserver/install/ipa_cacert_manage.py
483b06
+++ b/ipaserver/install/ipa_cacert_manage.py
483b06
@@ -172,14 +172,14 @@ class CACertManage(admintool.AdminTool):
483b06
         except errors.NotFound:
483b06
             raise admintool.ScriptError("CA renewal master not found")
483b06
 
483b06
-        self.resubmit_request(ca, 'caCACert')
483b06
+        self.resubmit_request()
483b06
 
483b06
         print("CA certificate successfully renewed")
483b06
 
483b06
     def renew_external_step_1(self, ca):
483b06
         print("Exporting CA certificate signing request, please wait")
483b06
 
483b06
-        self.resubmit_request(ca, 'ipaCSRExport')
483b06
+        self.resubmit_request('dogtag-ipa-ca-renew-agent-reuse')
483b06
 
483b06
         print(("The next step is to get %s signed by your CA and re-run "
483b06
               "ipa-cacert-manage as:" % paths.IPA_CA_CSR))
483b06
@@ -282,15 +282,15 @@ class CACertManage(admintool.AdminTool):
483b06
         except errors.NotFound:
483b06
             raise admintool.ScriptError("CA renewal master not found")
483b06
 
483b06
-        self.resubmit_request(ca, 'ipaRetrieval')
483b06
+        self.resubmit_request('dogtag-ipa-ca-renew-agent-reuse')
483b06
 
483b06
         print("CA certificate successfully renewed")
483b06
 
483b06
-    def resubmit_request(self, ca, profile):
483b06
+    def resubmit_request(self, ca='dogtag-ipa-ca-renew-agent'):
483b06
         timeout = api.env.startup_timeout + 60
483b06
 
483b06
         self.log.debug("resubmitting certmonger request '%s'", self.request_id)
483b06
-        certmonger.resubmit_request(self.request_id, profile=profile)
483b06
+        certmonger.resubmit_request(self.request_id, ca=ca, profile='')
483b06
         try:
483b06
             state = certmonger.wait_for_request(self.request_id, timeout)
483b06
         except RuntimeError:
483b06
@@ -304,7 +304,7 @@ class CACertManage(admintool.AdminTool):
483b06
                 "please check the request manually" % self.request_id)
483b06
 
483b06
         self.log.debug("modifying certmonger request '%s'", self.request_id)
483b06
-        certmonger.modify(self.request_id, profile='ipaCACertRenewal')
483b06
+        certmonger.modify(self.request_id, ca='dogtag-ipa-ca-renew-agent')
483b06
 
483b06
     def install(self):
483b06
         print("Installing CA certificate, please wait")
483b06
diff --git a/ipaserver/install/krainstance.py b/ipaserver/install/krainstance.py
483b06
index c39d6874a9d685f91b5d30ea1954320b8ee0c1ed..abb81897a404613e20be10d348096402ef08624b 100644
483b06
--- a/ipaserver/install/krainstance.py
483b06
+++ b/ipaserver/install/krainstance.py
483b06
@@ -60,9 +60,9 @@ class KRAInstance(DogtagInstance):
483b06
     be the same for both the CA and KRA.
483b06
     """
483b06
 
483b06
-    tracking_reqs = (('auditSigningCert cert-pki-kra', None),
483b06
-                     ('transportCert cert-pki-kra', None),
483b06
-                     ('storageCert cert-pki-kra', None))
483b06
+    tracking_reqs = ('auditSigningCert cert-pki-kra',
483b06
+                     'transportCert cert-pki-kra',
483b06
+                     'storageCert cert-pki-kra')
483b06
 
483b06
     def __init__(self, realm):
483b06
         super(KRAInstance, self).__init__(
483b06
diff --git a/ipaserver/install/server/upgrade.py b/ipaserver/install/server/upgrade.py
483b06
index 96fdadf751ef619e198a861d9f62440c98f3abae..5e5c83731d3d3415deb61271baa7865c62f60336 100644
483b06
--- a/ipaserver/install/server/upgrade.py
483b06
+++ b/ipaserver/install/server/upgrade.py
483b06
@@ -937,7 +937,7 @@ def certificate_renewal_update(ca, ds, http):
483b06
             'cert-presave-command': template % 'stop_pkicad',
483b06
             'cert-postsave-command':
483b06
                 (template % 'renew_ca_cert "caSigningCert cert-pki-ca"'),
483b06
-            'template-profile': 'ipaCACertRenewal',
483b06
+            'template-profile': '',
483b06
         },
483b06
         {
483b06
             'cert-database': paths.PKI_TOMCAT_ALIAS_DIR,
483b06
-- 
483b06
2.9.3
483b06