URL: https://github.com/freeipa/freeipa/pull/4148
Author: frasertweedale
 Title: #4148: Do not renew externally-signed CA as self-signed
Action: opened

PR body:
"""
Commit 49cf5ec64b1b7a7437ca285430353473c215540e fixed a bug that
prevented migration from externally-signed to self-signed IPA CA.
But it introduced a subtle new issue: certmonger-initiated renewal
renews an externally-signed IPA CA as a self-signed CA.

To resolve this issue, introduce the `--force-self-signed' flag for
the dogtag-ipa-ca-renew-agent script.  Add another certmonger CA
definition that calls this script with the `--force-self-signed'
flag.  Update dogtag-ipa-ca-renew-agent to only issue a self-signed
CA certificate if the existing certificate is self-signed or if
`--force-self-signed' was given.  Update `ipa-cacert-manage renew'
to supply `--force-self-signed' when appropriate.

As a result of these changes, certmonger-initiated renewal of an
externally-signed IPA CA certificate will not issue a self-signed
certificate.

Fixes: https://pagure.io/freeipa/issue/8176
"""

To pull the PR as Git branch:
git remote add ghfreeipa https://github.com/freeipa/freeipa
git fetch ghfreeipa pull/4148/head:pr4148
git checkout pr4148
From 9b51470a3d391693c3bad4b835a6880a3f33e88a Mon Sep 17 00:00:00 2001
From: Fraser Tweedale <ftwee...@redhat.com>
Date: Wed, 22 Jan 2020 15:38:25 +1100
Subject: [PATCH] Do not renew externally-signed CA as self-signed

Commit 49cf5ec64b1b7a7437ca285430353473c215540e fixed a bug that
prevented migration from externally-signed to self-signed IPA CA.
But it introduced a subtle new issue: certmonger-initiated renewal
renews an externally-signed IPA CA as a self-signed CA.

To resolve this issue, introduce the `--force-self-signed' flag for
the dogtag-ipa-ca-renew-agent script.  Add another certmonger CA
definition that calls this script with the `--force-self-signed'
flag.  Update dogtag-ipa-ca-renew-agent to only issue a self-signed
CA certificate if the existing certificate is self-signed or if
`--force-self-signed' was given.  Update `ipa-cacert-manage renew'
to supply `--force-self-signed' when appropriate.

As a result of these changes, certmonger-initiated renewal of an
externally-signed IPA CA certificate will not issue a self-signed
certificate.

Fixes: https://pagure.io/freeipa/issue/8176
---
 .../certmonger/dogtag-ipa-ca-renew-agent-submit.in | 14 ++++++++++++--
 ipalib/constants.py                                |  1 +
 ipaserver/install/cainstance.py                    |  4 ++--
 ipaserver/install/dogtaginstance.py                |  8 ++++++--
 ipaserver/install/ipa_cacert_manage.py             |  6 ++++--
 ipaserver/install/krainstance.py                   |  2 +-
 ipaserver/install/server/upgrade.py                |  4 +++-
 7 files changed, 29 insertions(+), 10 deletions(-)

diff --git a/install/certmonger/dogtag-ipa-ca-renew-agent-submit.in b/install/certmonger/dogtag-ipa-ca-renew-agent-submit.in
index 95ad080578..95886e5a30 100644
--- a/install/certmonger/dogtag-ipa-ca-renew-agent-submit.in
+++ b/install/certmonger/dogtag-ipa-ca-renew-agent-submit.in
@@ -402,7 +402,7 @@ def retrieve_cert(**kwargs):
     return result
 
 
-def renew_ca_cert(reuse_existing, **kwargs):
+def renew_ca_cert(reuse_existing, force_self_signed, **kwargs):
     """
     This is used for automatic CA certificate renewal.
     """
@@ -420,7 +420,8 @@ def renew_ca_cert(reuse_existing, **kwargs):
     if operation == 'SUBMIT':
         state = 'retrieve'
 
-        if not reuse_existing and is_renewal_master():
+        if (is_self_signed or force_self_signed) \
+                and not reuse_existing and is_renewal_master():
             state = 'request'
 
         csr_file = paths.IPA_CA_CSR
@@ -473,7 +474,9 @@ def renew_ca_cert(reuse_existing, **kwargs):
 def main():
     kwargs = {
         'reuse_existing': False,
+        'force_self_signed': False,
     }
+
     try:
         sys.argv.remove('--reuse-existing')
     except ValueError:
@@ -481,6 +484,13 @@ def main():
     else:
         kwargs['reuse_existing'] = True
 
+    try:
+        sys.argv.remove('--force-self-signed')
+    except ValueError:
+        pass
+    else:
+        kwargs['force_self_signed'] = True
+
     operation = os.environ.get('CERTMONGER_OPERATION')
     if operation not in ('SUBMIT', 'POLL'):
         return OPERATION_NOT_SUPPORTED_BY_HELPER
diff --git a/ipalib/constants.py b/ipalib/constants.py
index 047991198e..e73a5b9dd4 100644
--- a/ipalib/constants.py
+++ b/ipalib/constants.py
@@ -310,6 +310,7 @@
 IPA_CA_NICKNAME = 'caSigningCert cert-pki-ca'
 RENEWAL_CA_NAME = 'dogtag-ipa-ca-renew-agent'
 RENEWAL_REUSE_CA_NAME = 'dogtag-ipa-ca-renew-agent-reuse'
+RENEWAL_SELFSIGNED_CA_NAME = 'dogtag-ipa-ca-renew-agent-selfsigned'
 # The RA agent cert is used for client cert authentication. In the past IPA
 # used caServerCert profile, which adds clientAuth and serverAuth EKU. The
 # serverAuth EKU caused trouble with NamedConstraints, see RHBZ#1670239.
diff --git a/ipaserver/install/cainstance.py b/ipaserver/install/cainstance.py
index 252a29f840..fe63229af1 100644
--- a/ipaserver/install/cainstance.py
+++ b/ipaserver/install/cainstance.py
@@ -424,7 +424,7 @@ def configure_instance(self, host_name, dm_password, admin_password,
         if self.external != 1:
             if not has_ra_cert:
                 self.step("configure certmonger for renewals",
-                          self.configure_certmonger_renewal)
+                          self.configure_certmonger_renewal_helpers)
                 if not self.clone:
                     self.step("requesting RA certificate from CA", self.__request_ra_certificate)
                 elif promote:
@@ -998,7 +998,7 @@ def uninstall(self):
         obj = bus.get_object('org.fedorahosted.certmonger',
                              '/org/fedorahosted/certmonger')
         iface = dbus.Interface(obj, 'org.fedorahosted.certmonger')
-        for suffix in ['', '-reuse']:
+        for suffix in ['', '-reuse', '-selfsigned']:
             name = ipalib.constants.RENEWAL_CA_NAME + suffix
             path = iface.find_ca_by_nickname(name)
             if path:
diff --git a/ipaserver/install/dogtaginstance.py b/ipaserver/install/dogtaginstance.py
index b60fe7f376..f82cb5abc9 100644
--- a/ipaserver/install/dogtaginstance.py
+++ b/ipaserver/install/dogtaginstance.py
@@ -290,7 +290,7 @@ def http_proxy(self):
             fd.write(template)
             os.fchmod(fd.fileno(), 0o644)
 
-    def configure_certmonger_renewal(self):
+    def configure_certmonger_renewal_helpers(self):
         """
         Create a new CA type for certmonger that will retrieve updated
         certificates from the dogtag master server.
@@ -306,7 +306,11 @@ def configure_certmonger_renewal(self):
         obj = bus.get_object('org.fedorahosted.certmonger',
                              '/org/fedorahosted/certmonger')
         iface = dbus.Interface(obj, 'org.fedorahosted.certmonger')
-        for suffix, args in [('', ''), ('-reuse', ' --reuse-existing')]:
+        for suffix, args in [
+            ('', ''),
+            ('-reuse', ' --reuse-existing'),
+            ('-selfsigned', ' --force-self-signed'),
+        ]:
             name = RENEWAL_CA_NAME + suffix
             path = iface.find_ca_by_nickname(name)
             if not path:
diff --git a/ipaserver/install/ipa_cacert_manage.py b/ipaserver/install/ipa_cacert_manage.py
index 37dcc2befa..5e07e1d060 100644
--- a/ipaserver/install/ipa_cacert_manage.py
+++ b/ipaserver/install/ipa_cacert_manage.py
@@ -24,7 +24,9 @@
 from optparse import OptionGroup  # pylint: disable=deprecated-module
 import gssapi
 
-from ipalib.constants import RENEWAL_CA_NAME, RENEWAL_REUSE_CA_NAME, IPA_CA_CN
+from ipalib.constants import (
+    RENEWAL_CA_NAME, RENEWAL_REUSE_CA_NAME, RENEWAL_SELFSIGNED_CA_NAME,
+    IPA_CA_CN)
 from ipalib.install import certmonger, certstore
 from ipapython import admintool, ipautil
 from ipapython.certdb import (EMPTY_TRUST_FLAGS,
@@ -210,7 +212,7 @@ def renew_self_signed(self, ca):
         except errors.NotFound:
             raise admintool.ScriptError("CA renewal master not found")
 
-        self.resubmit_request()
+        self.resubmit_request(RENEWAL_SELFSIGNED_CA_NAME)
 
         db = certs.CertDB(api.env.realm, nssdir=paths.PKI_TOMCAT_ALIAS_DIR)
         cert = db.get_cert_from_db(self.cert_nickname)
diff --git a/ipaserver/install/krainstance.py b/ipaserver/install/krainstance.py
index c23f73ac5d..09efdcad9c 100644
--- a/ipaserver/install/krainstance.py
+++ b/ipaserver/install/krainstance.py
@@ -131,7 +131,7 @@ def configure_instance(self, realm_name, host_name, dm_password,
         self.step("enabling ephemeral requests", self.enable_ephemeral)
         self.step("restarting KRA", self.restart_instance)
         self.step("configure certmonger for renewals",
-                  self.configure_certmonger_renewal)
+                  self.configure_certmonger_renewal_helpers)
         self.step("configure certificate renewals", self.configure_renewal)
         self.step("configure HTTP to proxy connections",
                   self.http_proxy)
diff --git a/ipaserver/install/server/upgrade.py b/ipaserver/install/server/upgrade.py
index aa48ac74d4..15c47fd077 100644
--- a/ipaserver/install/server/upgrade.py
+++ b/ipaserver/install/server/upgrade.py
@@ -1032,6 +1032,9 @@ def certificate_renewal_update(ca, kra, ds, http):
     Update certmonger certificate renewal configuration.
     """
 
+    # First ensure the renewal helpers are defined.
+    ca.configure_certmonger_renewal_helpers()
+
     template = paths.CERTMONGER_COMMAND_TEMPLATE
     serverid = ipaldap.realm_to_serverid(api.env.realm)
 
@@ -1148,7 +1151,6 @@ def certificate_renewal_update(ca, kra, ds, http):
             logger.info("Removing %s", filename)
             ipautil.remove_file(filename)
 
-    ca.configure_certmonger_renewal()
     ca.configure_renewal()
     ca.configure_agent_renewal()
     ca.add_lightweight_ca_tracking_requests()
_______________________________________________
FreeIPA-devel mailing list -- freeipa-devel@lists.fedorahosted.org
To unsubscribe send an email to freeipa-devel-le...@lists.fedorahosted.org
Fedora Code of Conduct: 
https://docs.fedoraproject.org/en-US/project/code-of-conduct/
List Guidelines: https://fedoraproject.org/wiki/Mailing_list_guidelines
List Archives: 
https://lists.fedorahosted.org/archives/list/freeipa-devel@lists.fedorahosted.org

Reply via email to