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