How do I sign a new FreeIPA Server's internal CA with my organizational internal CA?
My organization has an internal Certificate Authority (CA) which we have already generated many internal certificates and have installed on machines.
I am setting up a FreeIPA LDAP/Kerberos server and after the initial install, it has generated an internal CA of it's own which I can see in the web interface.
I'd like to sign the FreeIPA CA with the existing organization's CA to establish a certificate trust chain. I am following the FreeIPA instructions for Renewing an Externally-Signed IdM CA Certificate Manually which I believe cover signing the FreeIPA CA with an external CA. This produced a CSR which I signed using the existing CA to produce a new signed FreeIPA CA.
However, I got stuck trying to re-import the newly signed CA + Certificate Chain using the ipa-cacert-manage renew --external-cert-file
command. When I run that as the instructions say to, I get an error that the CA certificate chain is incomplete because it's missing one of the certificates in the chain:
[root@lockandkey ~]# ipa-cacert-manage renew --external-cert-file=/tmp/LockAndKey_FreeIPA_CA.crt --external-cert-file=/tmp/dfca.crt --external-cert-file=/tmp/jgca.crt
Importing the renewed CA certificate, please wait
CA certificate chain in /tmp/LockAndKey_FreeIPA_CA.crt,
/tmp/dfca.crt, /tmp/jgca.crt is incomplete: missing certificate with subject
'[email protected],CN=ca.digitalfruition.com,OU=Internal CA,O=Digital Fruition\, LLC,L=Newland,ST=North Carolina,C=US'
The ipa-cacert-manage command failed.
However, that certificate was provided in one of the --external-cert-file
arguments. I also tried with a "CA Bundle" file (multiple certificates in one file) and the result was the same.
Digging in further, the issue actually appears to be from load_external_cert
in installutils.py
trust_chain = list(reversed(nssdb.get_trust_chain(ca_nickname)))
ca_cert_chain = []
for nickname in trust_chain:
cert, subject, issuer = cache[nickname]
ca_cert_chain.append(cert)
if subject == issuer:
break
else:
raise ScriptError(
"CA certificate chain in %s is incomplete: "
"missing certificate with subject '%s'" %
(", ".join(files), issuer))
Running ipa-cacert-manage renew
in verbose mode shows that it does find all certificates in the chain but when it gets to the [art where trust_chain
is formed, the trust_chain
only contains the FreeIPA certificate and not the rest of teh chain. I was able to reproduce the scenario by unwinding the commands and replaying them in my terminal. Here's where it breaks down:
FreeIPA's ipa-cacert-manage renew
is calling on certutil
to "Print the certificate chain" using the -O
option, as follows:
[root@lockandkey ~]# /usr/bin/certutil -d dbm:/tmp/tmppTphXX -O -n 'CN=Certificate Authority,O=FARCRY.SITEPALETTE.COM' -f /tmp/tmppTphXX/pwdfile.txt
"CN=Certificate Authority,O=FARCRY.SITEPALETTE.COM" [CN=Certificate Authority,O=FARCRY.SITEPALETTE.COM]
However certutil
is not printing the entire chain, even though the certificate is signed by another CA which is in the truststore. You can see that certutil
does show the proper chain when I call it on the intermediate CA:
[root@lockandkey ~]# /usr/bin/certutil -d dbm:/tmp/tmppTphXX -O -n '[email protected],CN=ca.digitalfruition.com,OU=Internal CA,O=Digital Fruition\, LLC,L=Newland,ST=North Carolina,C=US' -f /tmp/tmppTphXX/pwdfile.txt
"[email protected],CN=Joshua Gitlin,OU=ca.josh.gitlin.name,O=Personal Certificate Authority,L=Newland,ST=North Carolina,C=US" [[email protected],CN=Joshua Gitlin,OU=ca.josh.gitlin.name,O=Personal Certificate Authority,L=Newland,ST=North Carolina,C=US]
"[email protected],CN=ca.digitalfruition.com,OU=Internal CA,O=Digital Fruition\, LLC,L=Newland,ST=North Carolina,C=US" [[email protected],CN=ca.digitalfruition.com,OU=Internal CA,O="Digital Fruition, LLC",L=Newland,ST=North Carolina,C=US]
So I believe this is an issue with certutil
, but this is as far as I've gotten so far.
Debugging this further I have decided that for some reason certutil
doesn't like the certificate I generated, so it may be an issue with something on that CSR. Other certificates validate fine...
Am I doing something wrong? What's the proper way to sign a FreeIPA Certificate Authority with another internal CA?
I found the problem. The CSR generated by FreeIPA includes the "X509v3 Authority Key Identifier" extension set to the key ID of the FreeIPA private key. This causes certutil
to believe the CA is self-signed and does not follow the certificate chain.
When signing a CSR from FreeIPA, do not copy the X509v3 Authority Key Identifier extension. Then the validation will be successful.
(Also: make sure the signed CA certificate used UTF8 for encoding the subject name; see Subject name encoding mismatch in the documentation)