#9272 Install CA certificates only for PKINIT or TLS client auth
Opened a year ago by cheimes. Modified 8 months ago

Request for enhancement

As an admin, I want to install CA certificates so that they are only used for Kerberos KDC + PKINIT or for TLS client cert authentication with Apache HTTPd.

IPA can manage and distribute additional CA certificates to clients and servers. Root and intermediate CA certs can be installed and removed from LDAP with ipa-cacert-manage. The ipa-certupdate tool retrieves the CA certificates from LDAP and updates various trust stores and PEM bundles:

  • IPA_CA_CRT = "/etc/ipa/ca.crt"
  • KDC_CA_BUNDLE_PEM = "/var/lib/ipa-client/pki/kdc-ca-bundle.pem"
  • CA_BUNDLE_PEM = "/var/lib/ipa-client/pki/ca-bundle.pem"
  • IPA_NSSDB_DIR = "/etc/ipa/nssdb" (NSSDB)
  • system-wide trust store
  • /etc/dirsrv/slapd-%s (389-DS NSSDB)
  • PKI_TOMCAT_ALIAS_DIR = "/etc/pki/pki-tomcat/alias" (Dogtag NSSDB)
  • certmonger (???)
  • CA_CRT = "/usr/share/ipa/html/ca.crt"
  • CACERT_PEM = "/var/kerberos/krb5kdc/cacert.pem"

Currently any CA installed with ipa-cacert-manage install is added to all files, databases, and installed as a system-wide trusted CA. I have a use case where I want to trust a private CA chain only for a specific scope like PKINIT or TLS client cert auth (Apache HTTPd config SSLCACertificateFile). The existing ipaKeyTrust and ipaKeyExtUsage settings are not sufficient to limit the scope. An additional scope/purpose attribute is needed.


Related:

Why does IPA configure /etc/krb5.conf with different bundle files for anchors and pool? Shouldn't KRB5 use the same file for trust anchors and intermediate certs?

  pkinit_anchors = FILE:/var/lib/ipa-client/pki/kdc-ca-bundle.pem
  pkinit_pool = FILE:/var/lib/ipa-client/pki/ca-bundle.pem

https://web.mit.edu/kerberos/krb5-1.19/doc/admin/conf_files/krb5_conf.html#pkinit-krb5-conf-options

See https://pagure.io/freeipa/issue/6831:

In order to fully support PKINIT configuration in CA-less deployments, the tools that manipulate
3rd party certificates must be extended to also install PKINIT server certificates and update KDC's
PKINIT anchors when 3rd party CA certificates are to be used.

I still do not understand why IPA configures KRB5 to use two different bundle files. ipa-certupdate keeps both files in sync anyway. KRB5 loads root + intermediate certs from "pkinit_anchors" and only intermediate CAs from "pkinit_pool". The "pkinit_anchors" option can be overridden on the CLI, "pkinit_pool" can not.

Why do we have a file that can only provide intermediates?

Because that's what pkinit_pool is for. From krb5 documentation:

Specifies the location of intermediate certificates which may be
used by the KDC to complete the trust chain between a client(aqs
certificate and a trusted anchor. This option may be specified
multiple times.

for pkinit_anchors the krb5 documentation says:

Specifies the location of trusted anchor (root) certificates which
the client trusts to sign KDC certificates. This option may be
specified multiple times. These values from the config file are
not used if the user specifies X509_anchors on the command line.

When using these certificate bundles, krb5 will load pkinit_pool into the OpenSSL certstore it builds first with X509_STORE_CTX_init() and then adds a trusted stack of pkinit_anchors with X509_STORE_CTX_trusted_stack(). E.g. pkinit_pool certificates aren't trusted implicitly.

Apache mod_ssl uses IPA_CA_CRT = "/etc/ipa/ca.crt" for trust anchors for TLS client cert auth. The same file is also used by IPA to verify host certificates. If we want to separate server and client verification, then we need to create a new cert bundle for Apache.

The tricky part is how to make the feature compatible with older clients and servers. We (probably) do not want older IPA versions to install certificates with limited purpose. The certificates must be stored in LDAP such that old clients ignore them.

Options
1. store the certificates in a different part of the LDAP tree
2. use different object classes (get_ca_certs filters on (&(objectClass=ipaCertificate)(objectClass=pkiCA)))
3. set ipaKeyTrust to distrusted

Option (1) would make implementation more complicated and Option (2) is hacky. Option (3) in combination with an additional ipaKeyExtTrust multi-valued attribute could do the trick.

  • When ipaKeyTrust is set to trusted, then the cert is installed in system trust store with P11-Kit setting trusted: true, added to PEM file bundles, and added to NSS DBs as trusted CA (depending on EKU values).
  • When the value of ipaKeyTrust is distrusted, then the cert is added to system trust store with P11-Kit setting x-distrusted: true, not added to any PEM file bundles, and added to NSS DBs as valid peer (trust flag p). I don't know what p means.
  • All other values are parsed as trusted=None, which installs the cert in system trust store without trusted or x-distrusted flag, adds them to all PEM bundles, and to NSS DBs with empty trust flags.

We could do something sneaky, e.g. ipaKeyTrust: distrusted, ipaKeyExtTrust: pkinit would install the cert as trusted CA for PKINIT on new systems and not install the cert at all on old systems.

references
https://github.com/freeipa/freeipa/blob/master/ipapython/certdb.py#L137
https://github.com/freeipa/freeipa/blob/master/ipaclient/install/ipa_certupdate.py#L260 (c[2] is not False, c[2] is the trusted flag)

We cannot use the the distrusted approach. Bug https://pagure.io/freeipa/issue/9302 causes distrusted to break IPA servers.

master:

  • 8f25b2a Refactor CA file handling in replica installer

Login to comment on this ticket.

Metadata