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