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