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