Troubleshooting Certmonger issues with FreeIPA

In a previous post I explained the basics for certmonger. This post will focus on troubleshooting the issues that certmonger can have with FreeIPA deployments.

Certificate Authorities used by FreeIPA

When certmonger is installed on a machine, it comes with pre-defined Certificate Authorities (that can be listed using certmonger list-cas): SelfSign, IPA, certmaster, and local.

The installation of FreeIPA configures additional Certificate Authorities: dogtag-ipa-renew-agent and dogtag-ipa-ca-renew-agent. FreeIPA is using 3 of those CAs for its certificates:

  • IPA
  • dogtag-ipa-renew-agent
  • dogtag-ipa-ca-renew-agent

The table below summarizes the tracked certificates and their associated CA:

Certificate nickname Location CA Purpose
auditSigningCert cert-pki-ca /etc/pki/pki-tomcat/alias dogtag-ipa-ca-renew-agent PKI
ocspSigningCert cert-pki-ca /etc/pki/pki-tomcat/alias dogtag-ipa-ca-renew-agent PKI
subsystemCert cert-pki-ca /etc/pki/pki-tomcat/alias dogtag-ipa-ca-renew-agent PKI
caSigningCert cert-pki-ca /etc/pki/pki-tomcat/alias dogtag-ipa-ca-renew-agent PKI Certificate Authority
Server-Cert cert-pki-ca /etc/pki/pki-tomcat/alias dogtag-ipa-renew-agent PKI Server
ipaCert /etc/httpd/alias dogtag-ipa-ca-renew-agent Renew Agent – authenticates renewal requests
Server-Cert /etc/httpd/alias IPA HTTPd server
Server-Cert /etc/dirsrv/slapd-DOMAIN-COM IPA LDAP server

Note: all the certificates tracked by dogtag-ipa-ca-renew-agent are identical on all the replicas. This means for instance that when ‘ocspSigningCert cert-pki-ca’ is renewed on the master, the new certificate must also be installed on the replicas.

The behavior is different for the Server-Cert certificates (for PKI, HTTPd and LDAP servers): each replica has its own certificate, which contains the hostname in its subject.

Potential issues with dogtag-ipa-ca-renew-agent helper

As stated in the previous post, it is possible to check the status of a certificate using getcert list. When each certificate is valid and properly tracked, the output should display status: MONITORING. If it is not the case, you may see an additional error message:

$ getcert list -n ipaCert
Number of certificates and requests being tracked: 10.
Request ID '20161214165502':
 status: CA_UNREACHABLE
 ca-error: Error 7 connecting to http://ipaserver.domain.com:8080/ca/ee/ca/profileSubmit: Couldn't connect to server.

So let’s try to understand what is happening. The helper dogtag-ipa-ca-renew-agent has a different behavior, whether it is running on the renewal master or not.

On the renewal master

Under normal circumstances, the helper dogtag-ipa-ca-renew-agent is contacting Dogtag server through http or https, issues the renewal command and then puts the new certificate in LDAP so that they can be retrieved by other replicas . Several issues can happen:

  • Dogtag server may be down. Easy to check with
    $ systemctl status pki-tomcatd@pki-tomcat.service
  • When renewing a certificate, the helper needs to authenticate through SSL. In order to do that, it uses the ipaCert certificate stored in /etc/httpd/alias and needs to read the PIN in /etc/httpd/alias/pwdfile.txt. You can check that the certificate is present and the PIN is up-to-date with
    $ certutil -L -d /etc/httpd/alias/ -n ipaCert
    $ certutil -K -d /etc/httpd/alias/ -f /etc/httpd/alias/pwdfile.txt
  • The helper needs to trust IPA CA in order to establish a SSL connection to Dogtag server. It is using /etc/ipa/ca.crt as certificate trust anchor. Check that this file is up-to-date.
  • When the certificate is renewed, the helper puts the certificate in LDAP below cn=nickname,cn=ca_renewal,cn=ipa,cn=etc,$BASEDN.

In order to find which step failed, you can first examine the journal:

$ journalctl -u certmonger --since today
[...] dogtag-ipa-ca-renew-agent-submit[14237]: Forwarding request to dogtag-ipa-renew-agent
[...] dogtag-ipa-ca-renew-agent-submit[14237]: dogtag-ipa-renew-agent returned 3
[...] certmonger[69651]: 2016-12-19 11:19:02 [69651] Error 7 connecting to http://ipaserver.domain.com:8080/ca/ee/ca/profileSubmit: Couldn't connect to server.

You can see that the request is forwarded to another helper (dogtag-ipa-renew-agent) and the logs display the result code returned by this other helper. The result codes are defined in certmonger API:

  • 0: certificate issued, success
  • 1: the client should wait. The helper outputs a cookie value that will be reused in the next call.
  • 2: request rejected
  • 3: error connecting to the CA
  • 4: the helper requires additional configuration data
  • 5: the client should wait. The helper outputs a delay and a cookie.
  • 6: the CA does not understand the request
  • 16: the helper needs SCEP data
  • 17: the client needs to try again using a different key pair

The log also displays when the pre-save and post-save commands are called, and finally the success of the operation.

When the operation fails, you can increase the debug level to get more information: edit (or create) /etc/ipa/server.conf and add the following:

[global]
debug = True

and modify the helper to put it in debug mode with the -vv option:

$ getcert modify-ca -c dogtag-ipa-ca-renew-agent -e '/usr/libexec/certmonger/dogtag-ipa-ca-renew-agent-submit -vv'

At this point, the helper will log information in /var/log/ipa/renew.log that may help diagnose the issue:

[...] ipa DEBUG Starting external process
[...] ipa DEBUG args=/usr/libexec/certmonger/dogtag-ipa-renew-agent-submit -vv --submit-option requestor_name=IPA
[...] ipa DEBUG Process finished, return code=3
[...] ipa DEBUG stdout=Error 7 connecting to http://ipaserver.domain.com:8080/ca/ee/ca/profileSubmit: Couldn't connect to server.

[...] ipa DEBUG stderr=* Trying 2620:52:0:224e:21a:4aff:fe23:14c7...
* connect to 2620:52:0:224e:21a:4aff:fe23:14c7 port 8080 failed: Connection refused
* Trying 10.34.58.51...
* connect to 10.34.58.51 port 8080 failed: Connection refused
* Failed to connect to ipaserver.domain.com port 8080: Connection refused
* Closing connection 0
GET "http://ipaserver.domain.com:8080/ca/ee/ca/profileSubmit?profileId=caServerCert&serial_num=14&renewal=true&xml=true&requestor_name=IPA"
code = 7
code_text = "Couldn't connect to server"
results = "(null)"

In this case the issue was simply that pki server was stopped. The solution was to restart and resubmit the certificate request.

 

On non-renewal master

The helper has a different behavior when it does not run on the renewal master. It connects to the local LDAP server and reads the renewed certificate below cn=nickname,cn=ca_renewal,cn=ipa,cn=etc,$BASEDN, then copies the certificate into the right location. It is easy to check the access log of the directory server and make sure that the LDAP search succeeded (/var/log/dirsrv/slapd-DOMAIN-COM/access):

[...] conn=1274 op=1 SRCH base="cn=subsystemCert cert-pki-ca,cn=ca_renewal,cn=ipa,cn=etc,dc=domain,dc=com" scope=0 filter="(objectClass=*)" attrs="userCertificate"
[...] conn=1274 op=1 RESULT err=0 tag=101 nentries=1 etime=0

In this log we can see that the renewed certificate ‘subsystemCert cert-pki-ca’ was found (nentries=1).

The certificate is not found if:

  • there are replication issues and the replica did not get cn=nickname,cn=ca_renewal,cn=ipa,cn=etc,$BASEDN updated
  • the renewal on the master did not succeed to upload the new certificate in LDAP

 

Potential issues with IPA helper

This helper is used to renew the server certificate for HTTPd, LDAP and PKI. The helper is communicating with FreeIPA server using XML-RPC (with the URI defined in /etc/ipa/default.conf as xmlrpc_uri), trusting the CA certificate in /etc/ipa/ca.crt. Note that the helper may connect to FreeIPA server running on a different host.

When FreeIPA server receives the request, it handles the operation by submitting the renewal to the PKI server through CA REST API, using the certificate ipaCert located in /etc/httpd/alias for authentication.

If the certificates are not up-to-date, the communication will fail with the following error:

Request ID '20161214165647':
 status: CA_UNREACHABLE
 ca-error: Server at https://vm-058-051.abc.idm.lab.eng.brq.redhat.com/ipa/xml failed request, will retry: 4016 (RPC failed at server. Failed to authenticate to CA REST API)

Sometimes just running $ ipa-certupdate and resubmitting the request will fix the issue. On a non-renewal master you may also need to update ipaCert using $ getcert resubmit -i requestID_for_ipaCert.

The log files that may help troubleshoot are the following:

  • /var/log/httpd/access_log and error_log: they should display the communication between the CA helper and FreeIPA server
  • /var/log/pki/pki-tomcat/ca/debug: this log will show PKI server handling the renewal requests, in multiple steps (profileSubmit, profileReview, profileProcess).
  • the journal

 

Potential issues with dogtag-ipa-renew-agent

This helper is used to renew PKI Server certificate. It is also using ipaCert to communicate with the PKI server and may fail on a replica when ipaCert is not up-to-date:

Request ID '20161219133932':
 status: MONITORING
 ca-error: Server at "https://ipareplica.domain.com:8443/ca/agent/ca/profileProcess" replied: 1: Invalid Credential.

In this case, start by renewing ipaCert. This command will download the new ipaCert from LDAP:

$ getcert list -n ipaCert | grep Request
Request ID '20161214210956':
$ getcert resubmit -i 20161214210956

When ipaCert has been updated, you can try to re-submit the request for PKI Server-Cert.

 

Advertisements

Using Certmonger to track certificates

When FreeIPA is installed with an integrated IdM CA, it is using certmonger to track and renew its certificates. But what does this exactly mean?

When the certificates are reaching their expiration date, certmonger detects that it needs to renew them and takes care of the renewal (request a renewed certificate, then install the new certificate at the right location and finally restart the service so that it picks up the new certificate). It means that the system administrator does not need to bother anymore with renewals!

Well… When everything works well it is really a great functionality. But sometimes a small problem can prevent the renewal and FreeIPA ends up with expired certificates and HTTP or LDAP services refusing to start. In this case, it is really difficult to understand what has gone wrong, and how to fix the issue.

In this post, I will explain what is happening behind the scene with certmonger, so that you understand where to look for if you need to troubleshoot.

Certmonger concepts

Certmonger daemon and CLI

Certmonger provides 2 main components:

  • the certmonger daemon that is the “engine” tracking the list of certificates and launching renewal commands
  • the command-line interface: getcert, that allows to send commands to the certmonger daemon (for instance request a new certificate, list the tracked certificates, start or stop tracking a certificate, renew a certificate…)

Certificate Authority

Certmonger provides a generic interface allowing to communicate with various certificate systems, such as Dogtag, FreeIPA… A simple definition for Certificate System would be a software solution able to deliver certificates. This allows to use the same certmonger command independently of the Certificate System that will actually handle the request. The getcert command just reads the additional argument -c to know with which Certificate authority to interface.

Then certmonger needs to know how to interface with each type of Certificate System. This is done by defining Certificate Authorities that can be listed with:

$ getcert list-cas
CA 'SelfSign':
 is-default: no
 ca-type: INTERNAL:SELF
 next-serial-number: 01
CA 'IPA':
 is-default: no
 ca-type: EXTERNAL
 helper-location: /usr/libexec/certmonger/ipa-submit
[...]

Each section starting with ‘CA’ defines a type of Certificate Authority that certmonger knows to handle. The output of the command also shows a helper-location, which is the command that certmonger will call to discuss with the Certificate Authority. For instance:

$ getcert list-cas -c IPA
CA 'IPA':
 is-default: no
 ca-type: EXTERNAL
 helper-location: /usr/libexec/certmonger/ipa-submit

shows that certmonger will run the command “/usr/libexec/certmonger/ipa-submit” when interfacing with IPA certificate authority.

Each helper command is following an interface imposed by certmonger. For instance, environment variables are set by certmonger to provide the operation to execute, the CSR etc…

Certificate tracking

List of tracked certificates

In order to know the list of certificates currently tracked by certmonger, the command getcert list can be used. It shows a lot of information:

  • the certificate location (for instance HTTP server cert is stored in the NSS database /etc/httpd/alias)
  • the certificate nickname
  • the file storing the pin
  • the Certificate Authority that will be used to renew the certificate
  • the expiration date
  • the status of the certificate (MONITORING when it is tracked and not expired)

For instance, to list all the tracking requests for certificates with a nickname “Server-Cert” stored in the NSS db /etc/httpd/alias:

$ getcert list -n Server-Cert -d /etc/httpd/alias/
Number of certificates and requests being tracked: 8.
Request ID '20161122101308':
 status: MONITORING
 stuck: no
 key pair storage: type=NSSDB,location='/etc/httpd/alias',nickname='Server-Cert',token='NSS Certificate DB',pinfile='/etc/httpd/alias/pwdfile.txt'
 certificate: type=NSSDB,location='/etc/httpd/alias',nickname='Server-Cert',token='NSS Certificate DB'
 CA: IPA
 issuer: CN=Certificate Authority,O=DOMAIN.COM
 subject: CN=ipaserver.domain.com,O=DOMAIN.COM
 expires: 2018-11-23 10:09:34 UTC
 key usage: digitalSignature,nonRepudiation,keyEncipherment,dataEncipherment
 eku: id-kp-serverAuth,id-kp-clientAuth
 pre-save command: 
 post-save command: /usr/lib64/ipa/certmonger/restart_httpd
 track: yes
 auto-renew: yes

Certificate renewal

When a certification is near its expiration date, certmonger daemon will automatically issue a renewal command using the CA helper, obtain a renewed certificate and replace the previous cert with the new one.

It is also possible to manually renew a certificate in advance by using the command getcert resubmit -i <id>, where <id> is the Request ID displayed by getcert list for the targetted certificate. This command will renew the certificate using the right helper command.

Start/Stop tracking a certificate

The commands getcert start-tracking and getcert stop-tracking enable or disable the monitoring of a certificate. It is important to understand that they do not manipulate the certificate (stop-tracking does not delete it or remove it from the NSS database) but simply add/remove the certificate to/from the list of monitored certificates.

Pre and post-save commands

When a certificate is tracked by certmonger, it can be useful to define pre-save and post-save commands that certmonger will call during the renewal process. For instance:

$ getcert list -n Server-Cert -d /etc/httpd/alias/
Number of certificates and requests being tracked: 8.
Request ID '20161122101308':
 status: MONITORING
 stuck: no
 key pair storage: type=NSSDB,location='/etc/httpd/alias',nickname='Server-Cert',token='NSS Certificate DB',pinfile='/etc/httpd/alias/pwdfile.txt'
 certificate: type=NSSDB,location='/etc/httpd/alias',nickname='Server-Cert',token='NSS Certificate DB'
[...]
 pre-save command: 
 post-save command: /usr/lib64/ipa/certmonger/restart_httpd
 track: yes
 auto-renew: yes

shows that the renewal of HTTPd Server Cert:

  • will be handled by IPA Certificate Authority. Remember, we can find the associated helper using getcert list-cas -c IPA
  • will also launch the command restart_httpd

This is useful when a service needs to be restarted in order to pick up the new certificate.

Troubleshooting

 Certmonger logs

Certmonger uses the journal log. For instance, when a certificate is near its expiration date, the journal will show:

$ sudo journalctl -xe -t certmonger | more
Nov 05 11:35:47 ipaserver.domain.com certmonger[59223]: Certificate named "auditSigningCert cert-pki-ca" in token "NSS Certificate DB" in database "/etc/pki/pki-tomcat/alias" will not be valid after 20161115150822.

And when the certificate has been automatically renewed, the journal will show:

$ journalctl -t certmonger | more
Nov 24 12:23:15 ipaserver.domain.com certmonger[36674]: Certificate named "ipaCert" in token "NSS Certificate DB" in database "/etc/httpd/alias" issued by CA and saved.

Output of getcert list

It is possible to check the status for each certificate using getcert list:

  • when the certificate is still valid, the status should be MONITORING.
  • when the certificate is near its expiration date, certmonger will request its renewal and the status will change from MONITORING to SUBMITTING and finally back to MONITORING (you may also see intermediate status PRE_SAVE_CERT and POST_SAVE_CERT).

When the renewal fails, getcert list will also show an error message. It will help determine which phase failed, and from there you will need to check the logs specific to the CA helper or to the pre-save or post-save commands.

In the next post, I will detail the errors that can arise with the helpers used with FreeIPA.