From c445cefacf7713746f0bb0399d33b3f4008b71b4 Mon Sep 17 00:00:00 2001 From: Fraser Tweedale Date: Jun 07 2020 07:38:27 +0000 Subject: upgrade: add ipa-ca.$DOMAIN alias to HTTP certificate For detailed discussion on the purpose of this change and the design decisions made, see `git log -1 $THIS_COMMIT~3`. If the HTTP certificate does not have the ipa-ca.$DOMAIN dNSName, resubmit the certificate request to add the name. This action is performed after the tracking request has already been updated. Note: due to https://pagure.io/certmonger/issue/143, the resubmitted request, if it does not immediately succeed (fairly likely during ipa-server-upgrade) and if the notAfter date of the current cert is still far off (also likely), then Certmonger will wait 7 days before trying again (unless restarted). There is not much we can do about that in the middle of ipa-server-upgrade. Part of: https://pagure.io/freeipa/issue/8186 Reviewed-By: Rob Crittenden Reviewed-By: Rob Crittenden --- diff --git a/ipaserver/install/server/upgrade.py b/ipaserver/install/server/upgrade.py index 6dbae52..89731cb 100644 --- a/ipaserver/install/server/upgrade.py +++ b/ipaserver/install/server/upgrade.py @@ -13,6 +13,7 @@ import glob import shutil import pwd import fileinput +import ssl import stat import sys import tempfile @@ -21,7 +22,7 @@ from augeas import Augeas import dns.exception from ipalib import api, x509 -from ipalib.constants import RENEWAL_CA_NAME, RA_AGENT_PROFILE +from ipalib.constants import RENEWAL_CA_NAME, RA_AGENT_PROFILE, IPA_CA_RECORD from ipalib.install import certmonger, sysrestore import SSSDConfig import ipalib.util @@ -1121,6 +1122,10 @@ def certificate_renewal_update(ca, kra, ds, http): 'key-file': paths.HTTPD_KEY_FILE, 'ca-name': 'IPA', 'cert-postsave-command': template % 'restart_httpd', + 'template-hostname': [ + http.fqdn, + f'{IPA_CA_RECORD}.{ipautil.format_netloc(api.env.domain)}', + ], } ) @@ -1202,6 +1207,58 @@ def certificate_renewal_update(ca, kra, ds, http): logger.info("Certmonger certificate renewal configuration updated") return True + +def http_certificate_ensure_ipa_ca_dnsname(http): + """ + Ensure the HTTP service certificate has the ipa-ca.$DOMAIN SAN dNSName. + + This subroutine should be executed *after* ``certificate_renewal_update``, + which adds the name to the tracking request. It assumes that the tracking + request already has the ipa-ca.$DOMAIN DNS name set, and all that is needed + is to resubmit the request. + + If HTTP certificate is issued by a third party, print manual remediation + steps. + + """ + logger.info('[Adding ipa-ca alias to HTTP certificate]') + + expect = f'{IPA_CA_RECORD}.{ipautil.format_netloc(api.env.domain)}' + cert = x509.load_certificate_from_file(paths.HTTPD_CERT_FILE) + + try: + cert.match_hostname(expect) + except ssl.SSLCertVerificationError: + if certs.is_ipa_issued_cert(api, cert): + request_id = certmonger.get_request_id( + {'cert-file': paths.HTTPD_CERT_FILE}) + if request_id is None: + # shouldn't happen + logger.error('Could not find HTTP cert tracking request.') + else: + logger.info('Resubmitting HTTP cert tracking request') + certmonger.resubmit_request(request_id) + # NOTE: due to https://pagure.io/certmonger/issue/143, the + # resubmitted request, if it does not immediately succeed + # (fairly likely during ipa-server-upgrade) and if the notAfter + # date of the current cert is still far off (also likely), then + # Certmonger will wait 7 days before trying again (unless + # restarted). There is not much we can do about that here, in + # the middle of ipa-server-upgrade. + else: + logger.error('HTTP certificate is issued by third party.') + logger.error( + 'Obtain a new certificate with the following DNS names, \n' + 'and install via ipa-server-certinstall(1):\n' + ' - %s\n' + ' - %s', + http.fqdn, + expect, + ) + else: + logger.info('Certificate is OK; nothing to do') + + def copy_crl_file(old_path, new_path=None): """ Copy CRL to new location, update permissions and SELinux context @@ -2231,6 +2288,10 @@ def upgrade_configuration(): setup_pkinit(krb) enable_server_snippet() + # Must be executed after certificate_renewal_update + # (see function docstring for details) + http_certificate_ensure_ipa_ca_dnsname(http) + if not ds_running: ds.stop(ds.serverid)