Bug 2022561

Summary: ipa-healthcheck CADogtagCertsConfigCheck fail to process the scenario of renewed IPA CA certificates ( ipa get_cert_from_db() )
Product: Red Hat Enterprise Linux 8 Reporter: Marc Sauton <msauton>
Component: pki-coreAssignee: Chris Kelley <ckelley>
Status: CLOSED ERRATA QA Contact: idm-cs-qe-bugs
Severity: medium Docs Contact:
Priority: high    
Version: 8.4CC: ckelley, dcamilof, edewata, jmagne, pcech, prisingh, rcritten, skhandel, tmihinto
Target Milestone: rcKeywords: Triaged
Target Release: ---   
Hardware: All   
OS: Linux   
Whiteboard:
Fixed In Version: pki-core-10.6-8080020230203154518.c5b4fe3c Doc Type: If docs needed, set a value
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 2023-05-16 08:36:02 UTC Type: Bug
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:

Description Marc Sauton 2021-11-12 01:09:36 UTC
Description of problem:

this could be a bug report for the ipa component in ipaserver/install/certs.py
    def get_cert_from_db(self, nickname):

instead of ipa-healthcheck


the ipa-healthcheck with source pki.server.healthcheck.meta.csconfig and check CADogtagCertsConfigCheck fails to handle the scenario with any of the IPA CA internal certificates that are renewed.

the IPA CA NSS db and IPA PKI LDAP backend can have multiple records for the same subject DN and nickname, this is valid as long as the serial numbers are different ( so the certificates are different)

examples of the check error messages:

ERROR: pki.server.healthcheck.meta.csconfig.CADogtagCertsConfigCheck.ca_ocsp_signing: Certificate 'ocspSigningCert cert-pki-ca' does not match the value of ca.ocsp_signing.cert in /var/lib/pki/pki-tomcat/ca/conf/CS.cfg
ERROR: pki.server.healthcheck.meta.csconfig.CADogtagCertsConfigCheck.ca_signing: Certificate 'caSigningCert cert-pki-ca' does not match the value of ca.signing.cert in /var/lib/pki/pki-tomcat/ca/conf/CS.cfg

or
      "msg": "Certificate 'caSigningCert cert-pki-ca' does not match the value of ca.signing.cert in /var/lib/pki/pki-tomcat/ca/conf/CS.cfg"

this happens because the class DogtagCertsConfigCheck from ipahealthcheck/dogtag/ca.py calls get_cert_from_db(nickname) from ipaserver/install/certs.py which is simply a wrapper to a certutil -L command, and it does not know how to handle multiple base64 records.

in the IPA CA internal certificate renewal scenario, like for example with a "ipa-cacert-manage renew --self-signed" for the IPA CA signing certificate, or a certmonger resubmit for the other IPA CA certs like OCSP, audit, subsystem, it is a legitimate condition to have several IPA CA signing certificates in the IPA CA's NSS db as well as in the IPA PKI LDAP backend.

but the Python tool was not told how to handle those multiple records, and it blindly take the first one that does not correspond to the records in the IPA CA's /var/lib/pki/pki-tomcat/ca/conf/CS.cfg configuration file, and the tool claims this is an error.

get_cert_from_db() does not seem to do the right actions.

there are problably other side effects elsewhere.


Version-Release number of selected component (if applicable):

RHEL-8.4
ipa-healthcheck-0.7-3.module+el8.4.0+9007+5084bdd8.noarch


How reproducible:
on demand


Steps to Reproduce:

1. have an IPA replica up and running

2. there is one CA signing certificate in the IPA CA NSS db
certutil -L -d /etc/pki/pki-tomcat/alias/ -n "caSigningCert cert-pki-ca" | egrep umber:
        Serial Number: 1 (0x1)

3. there is one CA signing certificate in the IPA LDAP backend
ldapsearch -LLLxD "cn=directory manager" -w password -b ou=certificateRepository,ou=ca,o=ipaca subjectName="CN=Certificate Authority,O=IDM.EXAMPLE.TEST" dn subjectName issuerName serialno userCertificate

4. run a ipa-healthcheck source pki.server.healthcheck.meta.csconfig and check CADogtagCertsConfigCheck passes ok
time ipa-healthcheck --verbose --source pki.server.healthcheck.meta.csconfig --check CADogtagCertsConfigCheck
[]

5. renew the IPA CA signing cert
ipa-cacert-manage renew --self-signed

6. there are now 2 CA signing certificates in the IPA CA NSS db, and this is a legitimate condition
certutil -L -d /etc/pki/pki-tomcat/alias/ -n "caSigningCert cert-pki-ca" | egrep umber:
        Serial Number: 15 (0xf)
        Serial Number: 1 (0x1)

7. there are now 2 CA signing certificates in the IPA PKI LDAP backend, and this is a legitimate condition
ldapsearch -LLLxD "cn=directory manager" -w password -b ou=certificateRepository,ou=ca,o=ipaca subjectName="CN=Certificate Authority,O=IDM.EXAMPLE.TEST" dn subjectName issuerName serialno userCertificate | less

8. run a ipa-healthcheck source pki.server.healthcheck.meta.csconfig and check CADogtagCertsConfigCheck , it now FAILs
time ipa-healthcheck --verbose --source pki.server.healthcheck.meta.csconfig --check CADogtagCertsConfigCheck


Actual results:

[
  {
    "source": "pki.server.healthcheck.meta.csconfig",
    "check": "CADogtagCertsConfigCheck",
    "result": "ERROR",
    "uuid": "f606a702-2fd2-4ea6-8d1f-0219c3140cdc",
    "when": "20211111155711Z",
    "duration": "0.169711",
    "kw": {
      "key": "ca_signing",
      "nickname": "caSigningCert cert-pki-ca",
      "directive": "ca.signing.cert",
      "configfile": "/var/lib/pki/pki-tomcat/ca/conf/CS.cfg",
      "msg": "Certificate 'caSigningCert cert-pki-ca' does not match the value of ca.signing.cert in /var/lib/pki/pki-tomcat/ca/conf/CS.cfg"
    }
  }
]

real    0m2.468s
user    0m2.110s
sys     0m0.214s
[root@ipaserver1 ~]#


Expected results:
yes


Additional info:

src/ipahealthcheck/dogtag/ca.py

@registry
class DogtagCertsConfigCheck(DogtagPlugin):
...
            cert = db.get_cert_from_db(nickname)
            pem = cert.public_bytes(Encoding.PEM).decode()
            pem = pem.replace('\n', '')
            pem = pem.replace('-----BEGIN CERTIFICATE-----', '')
            pem = pem.replace('-----END CERTIFICATE-----', '')

            if pem.strip() != val:
                yield Result(self, constants.ERROR,
                             key=nickname,
                             directive=blobs[nickname],
                             configfile=paths.CA_CS_CFG_PATH,
                             msg='Certificate \'%s\' does not match the value '
                             'of %s in %s' %
                             (nickname, blobs[nickname], paths.CA_CS_CFG_PATH))
            else:
                yield Result(self, constants.SUCCESS,


and


ipaserver/install/certs.py
...
    def get_cert_from_db(self, nickname):
        """
        Retrieve a certificate from the current NSS database for nickname.
        """
        try:
            args = ["-L", "-n", nickname, "-a"]
            result = self.run_certutil(args, capture_output=True)
            return x509.load_pem_x509_certificate(result.raw_output)
        except ipautil.CalledProcessError:
            return None
...

Comment 1 Rob Crittenden 2021-11-12 14:05:17 UTC
Easily reproducible following the steps.

This check is provided by pki/server/healthcheck/meta/csconfig.py and not IPA/healthcheck code.

cert_nssdb contains a base64-blob representing both certificates. I converted the blob to DER and use derdump and both are there.

Re-assigning product.

Comment 21 errata-xmlrpc 2023-05-16 08:36:02 UTC
Since the problem described in this bug report should be
resolved in a recent advisory, it has been closed with a
resolution of ERRATA.

For information on the advisory (pki-core:10.6 bug fix and enhancement update), and where to find the updated
files, follow the link below.

If the solution does not work for you, open a new bug report.

https://access.redhat.com/errata/RHBA-2023:2826