5c8636
From a0626e09b3eaf5d030982e2ff03e95841ad1b4b9 Mon Sep 17 00:00:00 2001
5c8636
From: Rob Crittenden <rcritten@redhat.com>
5c8636
Date: Wed, 3 Feb 2021 15:52:05 -0500
5c8636
Subject: [PATCH] ipa-cert-fix: Don't hardcode the NSS certificate nickname
5c8636
5c8636
The nickname of the 389-ds certificate was hardcoded as
5c8636
Server-Cert which failed if the user had installed a
5c8636
third-party certificate using ipa-server-certinstall.
5c8636
5c8636
Instead pull the nickname from the DS configuration and
5c8636
retrieve it based on that.
5c8636
5c8636
https://pagure.io/freeipa/issue/8600
5c8636
5c8636
Signed-off-by: Rob Crittenden <rcritten@redhat.com>
5c8636
Reviewed-By: Florence Blanc-Renaud <flo@redhat.com>
5c8636
---
5c8636
 ipaserver/install/ipa_cert_fix.py | 17 +++++++++++------
5c8636
 1 file changed, 11 insertions(+), 6 deletions(-)
5c8636
5c8636
diff --git a/ipaserver/install/ipa_cert_fix.py b/ipaserver/install/ipa_cert_fix.py
5c8636
index 2f2c15613..29af89cd5 100644
5c8636
--- a/ipaserver/install/ipa_cert_fix.py
5c8636
+++ b/ipaserver/install/ipa_cert_fix.py
5c8636
@@ -203,9 +203,12 @@ def expired_ipa_certs(now):
5c8636
         certs.append((IPACertType.HTTPS, cert))
5c8636
 
5c8636
     # LDAPS
5c8636
-    ds_dbdir = dsinstance.config_dirname(realm_to_serverid(api.env.realm))
5c8636
+    serverid = realm_to_serverid(api.env.realm)
5c8636
+    ds = dsinstance.DsInstance(realm_name=api.env.realm)
5c8636
+    ds_dbdir = dsinstance.config_dirname(serverid)
5c8636
+    ds_nickname = ds.get_server_cert_nickname(serverid)
5c8636
     db = NSSDatabase(nssdir=ds_dbdir)
5c8636
-    cert = db.get_cert('Server-Cert')
5c8636
+    cert = db.get_cert(ds_nickname)
5c8636
     if cert.not_valid_after <= now:
5c8636
         certs.append((IPACertType.LDAPS, cert))
5c8636
 
5c8636
@@ -344,11 +347,13 @@ def install_ipa_certs(subject_base, ca_subject_dn, certs):
5c8636
         elif certtype is IPACertType.HTTPS:
5c8636
             shutil.copyfile(cert_path, paths.HTTPD_CERT_FILE)
5c8636
         elif certtype is IPACertType.LDAPS:
5c8636
-            ds_dbdir = dsinstance.config_dirname(
5c8636
-                realm_to_serverid(api.env.realm))
5c8636
+            serverid = realm_to_serverid(api.env.realm)
5c8636
+            ds = dsinstance.DsInstance(realm_name=api.env.realm)
5c8636
+            ds_dbdir = dsinstance.config_dirname(serverid)
5c8636
             db = NSSDatabase(nssdir=ds_dbdir)
5c8636
-            db.delete_cert('Server-Cert')
5c8636
-            db.import_pem_cert('Server-Cert', EMPTY_TRUST_FLAGS, cert_path)
5c8636
+            ds_nickname = ds.get_server_cert_nickname(serverid)
5c8636
+            db.delete_cert(ds_nickname)
5c8636
+            db.import_pem_cert(ds_nickname, EMPTY_TRUST_FLAGS, cert_path)
5c8636
         elif certtype is IPACertType.KDC:
5c8636
             shutil.copyfile(cert_path, paths.KDC_CERT)
5c8636
 
5c8636
-- 
5c8636
2.29.2
5c8636
5c8636
From 660507fda2394b17d709c47a05ce5df548a47990 Mon Sep 17 00:00:00 2001
5c8636
From: Rob Crittenden <rcritten@redhat.com>
5c8636
Date: Thu, 4 Feb 2021 08:25:48 -0500
5c8636
Subject: [PATCH] ipatests: test third-party 389-ds cert with ipa-cert-fix
5c8636
5c8636
ipa-cert-fix was hardcoded to use Server-Cert as the nickname
5c8636
so would fail if a third-party certificate was installed for DS.
5c8636
5c8636
https://pagure.io/freeipa/issue/8600
5c8636
5c8636
Signed-off-by: Rob Crittenden <rcritten@redhat.com>
5c8636
Reviewed-By: Florence Blanc-Renaud <flo@redhat.com>
5c8636
---
5c8636
 .../test_integration/test_ipa_cert_fix.py     | 57 +++++++++++++++++++
5c8636
 1 file changed, 57 insertions(+)
5c8636
5c8636
diff --git a/ipatests/test_integration/test_ipa_cert_fix.py b/ipatests/test_integration/test_ipa_cert_fix.py
5c8636
index 2f7de5526..f9e5fe6e2 100644
5c8636
--- a/ipatests/test_integration/test_ipa_cert_fix.py
5c8636
+++ b/ipatests/test_integration/test_ipa_cert_fix.py
5c8636
@@ -11,6 +11,17 @@ import time
5c8636
 from ipaplatform.paths import paths
5c8636
 from ipatests.pytest_ipa.integration import tasks
5c8636
 from ipatests.test_integration.base import IntegrationTest
5c8636
+from ipatests.test_integration.test_caless import CALessBase, ipa_certs_cleanup
5c8636
+
5c8636
+
5c8636
+def server_install_teardown(func):
5c8636
+    def wrapped(*args):
5c8636
+        master = args[0].master
5c8636
+        try:
5c8636
+            func(*args)
5c8636
+        finally:
5c8636
+            ipa_certs_cleanup(master)
5c8636
+    return wrapped
5c8636
 
5c8636
 
5c8636
 class TestIpaCertFix(IntegrationTest):
5c8636
@@ -94,3 +105,49 @@ class TestIpaCertFix(IntegrationTest):
5c8636
             else:
5c8636
                 # timeout
5c8636
                 raise AssertionError('Timeout: Failed to renew all the certs')
5c8636
+
5c8636
+
5c8636
+class TestIpaCertFixThirdParty(CALessBase):
5c8636
+    """
5c8636
+    Test that ipa-cert-fix works with an installation with custom certs.
5c8636
+    """
5c8636
+
5c8636
+    @classmethod
5c8636
+    def install(cls, mh):
5c8636
+        cls.nickname = 'ca1/server'
5c8636
+
5c8636
+        super(TestIpaCertFixThirdParty, cls).install(mh)
5c8636
+        tasks.install_master(cls.master, setup_dns=True)
5c8636
+
5c8636
+    @server_install_teardown
5c8636
+    def test_third_party_certs(self):
5c8636
+        self.create_pkcs12(self.nickname,
5c8636
+                           password=self.cert_password,
5c8636
+                           filename='server.p12')
5c8636
+        self.prepare_cacert('ca1')
5c8636
+
5c8636
+        # We have a chain length of one. If this is extended then the
5c8636
+        # additional cert names will need to be calculated.
5c8636
+        nick_chain = self.nickname.split('/')
5c8636
+        ca_cert = '%s.crt' % nick_chain[0]
5c8636
+
5c8636
+        # Add the CA to the IPA store
5c8636
+        self.copy_cert(self.master, ca_cert)
5c8636
+        self.master.run_command(['ipa-cacert-manage', 'install', ca_cert])
5c8636
+
5c8636
+        # Apply the new cert chain otherwise ipa-server-certinstall will fail
5c8636
+        self.master.run_command(['ipa-certupdate'])
5c8636
+
5c8636
+        # Install the updated certs and restart the world
5c8636
+        self.copy_cert(self.master, 'server.p12')
5c8636
+        args = ['ipa-server-certinstall',
5c8636
+                '-p', self.master.config.dirman_password,
5c8636
+                '--pin', self.master.config.admin_password,
5c8636
+                '-d', 'server.p12']
5c8636
+        self.master.run_command(args)
5c8636
+        self.master.run_command(['ipactl', 'restart',])
5c8636
+
5c8636
+        # Run ipa-cert-fix. This is basically a no-op but tests that
5c8636
+        # the DS nickname is used and not a hardcoded value.
5c8636
+        result = self.master.run_command(['ipa-cert-fix', '-v'],)
5c8636
+        assert self.nickname in result.stderr_text
5c8636
-- 
5c8636
2.29.2
5c8636
5c8636
From 4cb6f0ba0df928eea60b20892a6fc85373627946 Mon Sep 17 00:00:00 2001
5c8636
From: Rob Crittenden <rcritten@redhat.com>
5c8636
Date: Fri, 5 Feb 2021 09:00:54 -0500
5c8636
Subject: [PATCH] Set pki-core dependency to 10.3.3 for pki-server cert-fix bug
5c8636
5c8636
Related: https://github.com/dogtagpki/pki/issues/3387
5c8636
Reviewed-By: Florence Blanc-Renaud <flo@redhat.com>
5c8636
---
5c8636
 freeipa.spec.in | 4 ++--
5c8636
 1 file changed, 2 insertions(+), 2 deletions(-)
5c8636
5c8636
diff --git a/freeipa.spec.in b/freeipa.spec.in
5c8636
index 93e473ac4..0e261285b 100755
5c8636
--- a/freeipa.spec.in
5c8636
+++ b/freeipa.spec.in
5c8636
@@ -128,11 +128,11 @@
5c8636
 %if 0%{?rhel} == 8
5c8636
 # PKIConnection has been modified to always validate certs.
5c8636
 # https://pagure.io/freeipa/issue/8379
5c8636
-%global pki_version 10.9.0-0.4
5c8636
+%global pki_version 10.10.4-1
5c8636
 %else
5c8636
 # New KRA profile, ACME support
5c8636
 # https://pagure.io/freeipa/issue/8545
5c8636
-%global pki_version 10.10.0-2
5c8636
+%global pki_version 10.10.3-1
5c8636
 %endif
5c8636
 
5c8636
 # RHEL 8.3+, F32+ has 0.79.13
5c8636
-- 
5c8636
2.29.2
5c8636
5c8636
From f3463728f2196589d36e14cedccb26c03730a7c0 Mon Sep 17 00:00:00 2001
5c8636
From: Rob Crittenden <rcritten@redhat.com>
5c8636
Date: Wed, 10 Feb 2021 16:07:13 -0500
5c8636
Subject: [PATCH] Don't renew non-IPA issued certs in ipa-cert-fix
5c8636
5c8636
If the Apache, 389-ds or KDC certificate was issued by
5c8636
a third party there is nothing we can do, regardless of
5c8636
whether it is expired or not.
5c8636
5c8636
Report which certificates will not be renewed so the
5c8636
admin can manually do do (likely in the event of a
5c8636
third-party certificate).
5c8636
5c8636
https://pagure.io/freeipa/issue/8600
5c8636
5c8636
Signed-off-by: Rob Crittenden <rcritten@redhat.com>
5c8636
Reviewed-By: Florence Blanc-Renaud <flo@redhat.com>
5c8636
---
5c8636
 ipaserver/install/ipa_cert_fix.py | 53 +++++++++++++++++++++++++------
5c8636
 1 file changed, 43 insertions(+), 10 deletions(-)
5c8636
5c8636
diff --git a/ipaserver/install/ipa_cert_fix.py b/ipaserver/install/ipa_cert_fix.py
5c8636
index 29af89cd5..210cf80f1 100644
5c8636
--- a/ipaserver/install/ipa_cert_fix.py
5c8636
+++ b/ipaserver/install/ipa_cert_fix.py
5c8636
@@ -43,6 +43,7 @@ from ipapython.certdb import NSSDatabase, EMPTY_TRUST_FLAGS
5c8636
 from ipapython.dn import DN
5c8636
 from ipapython.ipaldap import realm_to_serverid
5c8636
 from ipaserver.install import ca, cainstance, dsinstance
5c8636
+from ipaserver.install.certs import is_ipa_issued_cert
5c8636
 from ipapython import directivesetter
5c8636
 from ipapython import ipautil
5c8636
 
5c8636
@@ -104,6 +105,13 @@ class IPACertFix(AdminTool):
5c8636
 
5c8636
         api.bootstrap(in_server=True, confdir=paths.ETC_IPA)
5c8636
         api.finalize()
5c8636
+
5c8636
+        if not dsinstance.is_ds_running(realm_to_serverid(api.env.realm)):
5c8636
+            print(
5c8636
+                "The LDAP server is not running; cannot proceed."
5c8636
+            )
5c8636
+            return 1
5c8636
+
5c8636
         api.Backend.ldap2.connect()  # ensure DS is up
5c8636
 
5c8636
         subject_base = dsinstance.DsInstance().find_subject_base()
5c8636
@@ -113,7 +121,7 @@ class IPACertFix(AdminTool):
5c8636
         ca_subject_dn = ca.lookup_ca_subject(api, subject_base)
5c8636
 
5c8636
         now = datetime.datetime.now() + datetime.timedelta(weeks=2)
5c8636
-        certs, extra_certs = expired_certs(now)
5c8636
+        certs, extra_certs, non_renewed = expired_certs(now)
5c8636
 
5c8636
         if not certs and not extra_certs:
5c8636
             print("Nothing to do.")
5c8636
@@ -121,7 +129,7 @@ class IPACertFix(AdminTool):
5c8636
 
5c8636
         print(msg)
5c8636
 
5c8636
-        print_intentions(certs, extra_certs)
5c8636
+        print_intentions(certs, extra_certs, non_renewed)
5c8636
 
5c8636
         response = ipautil.user_input('Enter "yes" to proceed')
5c8636
         if response.lower() != 'yes':
5c8636
@@ -133,7 +141,10 @@ class IPACertFix(AdminTool):
5c8636
             fix_certreq_directives(certs)
5c8636
             run_cert_fix(certs, extra_certs)
5c8636
         except ipautil.CalledProcessError:
5c8636
-            if any(x[0] is IPACertType.LDAPS for x in extra_certs):
5c8636
+            if any(
5c8636
+                x[0] is IPACertType.LDAPS
5c8636
+                for x in extra_certs + non_renewed
5c8636
+            ):
5c8636
                 # The DS cert was expired.  This will cause
5c8636
                 # 'pki-server cert-fix' to fail at the final
5c8636
                 # restart.  Therefore ignore the CalledProcessError
5c8636
@@ -152,13 +163,15 @@ class IPACertFix(AdminTool):
5c8636
             print("Becoming renewal master.")
5c8636
             cainstance.CAInstance().set_renewal_master()
5c8636
 
5c8636
+        print("Restarting IPA")
5c8636
         ipautil.run(['ipactl', 'restart'], raiseonerr=True)
5c8636
 
5c8636
         return 0
5c8636
 
5c8636
 
5c8636
 def expired_certs(now):
5c8636
-    return expired_dogtag_certs(now), expired_ipa_certs(now)
5c8636
+    expired_ipa, non_renew_ipa = expired_ipa_certs(now)
5c8636
+    return expired_dogtag_certs(now), expired_ipa, non_renew_ipa
5c8636
 
5c8636
 
5c8636
 def expired_dogtag_certs(now):
5c8636
@@ -191,6 +204,7 @@ def expired_ipa_certs(now):
5c8636
 
5c8636
     """
5c8636
     certs = []
5c8636
+    non_renewed = []
5c8636
 
5c8636
     # IPA RA
5c8636
     cert = x509.load_certificate_from_file(paths.RA_AGENT_PEM)
5c8636
@@ -200,7 +214,10 @@ def expired_ipa_certs(now):
5c8636
     # Apache HTTPD
5c8636
     cert = x509.load_certificate_from_file(paths.HTTPD_CERT_FILE)
5c8636
     if cert.not_valid_after <= now:
5c8636
-        certs.append((IPACertType.HTTPS, cert))
5c8636
+        if not is_ipa_issued_cert(api, cert):
5c8636
+            non_renewed.append((IPACertType.HTTPS, cert))
5c8636
+        else:
5c8636
+            certs.append((IPACertType.HTTPS, cert))
5c8636
 
5c8636
     # LDAPS
5c8636
     serverid = realm_to_serverid(api.env.realm)
5c8636
@@ -210,18 +227,24 @@ def expired_ipa_certs(now):
5c8636
     db = NSSDatabase(nssdir=ds_dbdir)
5c8636
     cert = db.get_cert(ds_nickname)
5c8636
     if cert.not_valid_after <= now:
5c8636
-        certs.append((IPACertType.LDAPS, cert))
5c8636
+        if not is_ipa_issued_cert(api, cert):
5c8636
+            non_renewed.append((IPACertType.LDAPS, cert))
5c8636
+        else:
5c8636
+            certs.append((IPACertType.LDAPS, cert))
5c8636
 
5c8636
     # KDC
5c8636
     cert = x509.load_certificate_from_file(paths.KDC_CERT)
5c8636
     if cert.not_valid_after <= now:
5c8636
-        certs.append((IPACertType.KDC, cert))
5c8636
+        if not is_ipa_issued_cert(api, cert):
5c8636
+            non_renewed.append((IPACertType.HTTPS, cert))
5c8636
+        else:
5c8636
+            certs.append((IPACertType.KDC, cert))
5c8636
 
5c8636
-    return certs
5c8636
+    return certs, non_renewed
5c8636
 
5c8636
 
5c8636
-def print_intentions(dogtag_certs, ipa_certs):
5c8636
-    print("The following certificates will be renewed: ")
5c8636
+def print_intentions(dogtag_certs, ipa_certs, non_renewed):
5c8636
+    print("The following certificates will be renewed:")
5c8636
     print()
5c8636
 
5c8636
     for certid, cert in dogtag_certs:
5c8636
@@ -230,6 +253,16 @@ def print_intentions(dogtag_certs, ipa_certs):
5c8636
     for certtype, cert in ipa_certs:
5c8636
         print_cert_info("IPA", certtype.value, cert)
5c8636
 
5c8636
+    if non_renewed:
5c8636
+        print(
5c8636
+            "The following certificates will NOT be renewed because "
5c8636
+            "they were not issued by the IPA CA:"
5c8636
+        )
5c8636
+        print()
5c8636
+
5c8636
+        for certtype, cert in non_renewed:
5c8636
+            print_cert_info("IPA", certtype.value, cert)
5c8636
+
5c8636
 
5c8636
 def print_cert_info(context, desc, cert):
5c8636
     print("{} {} certificate:".format(context, desc))
5c8636
-- 
5c8636
2.29.2
5c8636