Background: Certificates

An X.509 certificate (also commonly known as an SSL certificate), basically,
contains a public key and an indication of to whom the key belongs (referred
to as the certificate's _subject_) that have been cryptographically signed.
By signing the certificate, the _issuer_ asserts that the key belongs to the
_subject_.

If the certificate is being used by an SSL-enabled server, for example, where
the public key is used to help set up the encryption, a client who verifies
the signature has verified that the issuer asserted that the party on the
other end of the connection, who used the public key, has a specific name.

If that name doesn't match the hostname that the client intended to connect
with, then cleary something has gone wrong.  The client may have connected to
the wrong server.  If the certificate isn't signed by an _issuer_ that the
client trusts to be honest about things, then the client can't trust that the
_subject_ name in the certificate isn't forged.

The _issuer_ who signs certificates is called a _certifying_ _authority_, or
alternately, a _certificate_ _authority_ (or more simply as a _CA_).  If
you're deploying an SSL-enabled service, the certificates it uses need to be
_issued_ (verified and signed) by a CA that your clients trust.

Background: Certificate Extensions

An X.509 certificate minimally needs to contain the subject's name and that
subject's public key.  An issuer is also free to embed arbitrary data into
a certificate in the certificate's _extensions_ field.  Extensions are
identified by OID and the data they contain is in a format specific to that
OID.

While this flexibility could allow for all sorts of hijinks, in order to be
useful, an extension needs to be understood by all of the parties that will
use the certificate in some way, so in practice most certificates will only
contain some of a number of widely-used extensions.

One of the more commonly-used extensions is the subjectAlternateName (also
known as subjectAltName, or SAN) extension.  It contains one or more names by
which the subject might also be known.  Because the _subject_ field of a
certificate is formatted as a _distinguished_ _name_, for example, SSL clients
typically have to extract the hostname from the subject field, which can be an
error-prone process, in order to compare them with the hostname that the
client attempted to use.  A SAN of type _dnsName_ with the hostname as its
value removes all ambiguity.  The SAN extension can also contain other types
of names, for example IPv4 and IPv6 addresses, email addresses, and Kerberos
principal names.

Background: Certificate Requests

In order to obtain a certificate, the CA needs to obtain a copy of the public
key which should be recorded in the certificate.  Most often, this key is
combined with other requested information, such as a requested subject name,
into a _certificate_ _signing_ _request_ (a CSR) and submitted to the CA for
processing.  The CSR is usually signed with the submitter's private key.

A CSR can also contain arbitrary attributes, and one of those attributes can
be a set of requested extension values.  In this way, a client can supply
almost all of the contents of the certificate it desires as part of its
request.  While this can be very useful in some scenaries, it's important to
recognize that in assembling a certificate to be issued, the CA is free to
validate, reject, or simply discard any part of the client's request.

Where certmonger Fits In

The certmonger daemon, along with its command-line clients, attempts to
simplify the process of generating public/private key pairs and CSRs and
submitting CSRs to CAs for signing.

Perhaps the simplest use case is to generate a certificate which is signed by
the subject itself.  (They're not very useful in production, but they're great
for testing.)

   selfsign-getcert request -f /tmp/server.crt -k /tmp/server.key

What we've done above is to tell certmonger that we want a key to be stored in
the file /tmp/server.key, to get a corresponding certificate, and to store
that certificate in the file /tmp/server.crt.  (Using selfsign-getcert to tell
it that also implicitly tells it to go ahead and _self-sign_ the CSR, which it
generates and uses internally, with the subject's own key.)

What certmonger did was to check if there was already a key there, and since
there wasn't, to go ahead and generate one.  That done, it created a CSR and
then used the same key to produce a signed certificate.

The daemon usually runs with sufficient privileges to be able to read and
write to most locations that we might tell it to use for storing the
certificate and key.  However, as an added precaution, on systems where a
mandatory access control system is in use, the daemon will typically be
permitted to read and write only to a narrowly-defined set of locations.

For example, on systems using SELinux, certmonger will often not be allowed
to use /tmp because the directory is marked with the label "tmp_t".  We
would first need to create an alternate location with the label "cert_t" for
certmonger's use:

   mkdir -p /tmp/certs
   chcon -t cert_t /tmp/certs
   cd /tmp/certs
   selfsign-getcert request -f ./server.crt -k ./server.key

The example above used plain files for holding the key and the certificate,
but we could have specified storage using an NSS database by passing the
database's location and a nickname to give to the certificate, like so:

   selfsign-getcert request -d /tmp -n Testing-Certificate

Of course, we had to supply a certificate nickname, because certmonger isn't
all that creative.  We used a nickname of "Testing-Certificate" because, well,
why not?

We can tell certmonger to embed a specific _subject_ name into the CSR, and we
can tell it to include one or more of several types of SAN values, too:
   -N _subject_      -> specifies a subject name
   -K _principal_add -> specifies a Kerberos principal name SAN
   -D _hostname_     -> specifies a dnsName SAN
   -E _email_        -> specifies an rfc822address (email) SAN

Let's create another certificate:

   selfsign-getcert request -f /tmp/babs.crt -k /tmp/babs.key \
	-N "CN=Babs Jensen" -K bjensen@EXAMPLE.COM -E babs@example.com

For flat files, we can use OpenSSL to look at the certificate's contents.
Have a look at the first certificate we generated:

   openssl x509 -noout -text -in /tmp/server.crt

You'll notice that even though we didn't specify what to put in the
certificate, certmonger went ahead and added some things.  These are its
default settings.  Now look at the one we just generated for Babs:

   openssl x509 -noout -text -in /tmp/babs.crt

You'll see that the subject name is the one we requested, and that the email
address is being shown correctly.  As of this writing, the openssl command
doesn't know how to display Kerberos principal names, but that's okay.

While we're here, we can use NSS's certutil to examine the second certificate
we generated:

   certutil -d /tmp -L -n Testing-Certificate

The output format is a bit different, but the contents of the certificate
should be pretty much the same.

You may have noticed that in each case, the certificates had a validity time
associated with them -- after a certain point, they won't be considered valid
any more.  That's okay.  We can tell certmonger to go ahead and get a new
certificate when the existing one expires:

   selfsign-getcert start-tracking -f /tmp/server.crt -r

We could have added the "-r" when we initially requested the certificate and
skipped this step, but this is documentation, so sometimes we go the long way.

Using certmonger's Built-in "Toy" CA

Using a toy CA to sign certificates is slightly more useful than self-signing
certificates, because you can issue multiple certificates, all signed by a
single signing certificate, and only have to deal with distributing one copy of
the signing certificate to the various places where it'll be needed.

The certmonger package includes a "local" signer which uses a its own
self-signed certificate to sign certificates.  Using it instead of self-signing
is straightforward:

   local-getcert request -r \
	-f /etc/httpd/conf/ssl.crt/server.crt \
	-k /etc/httpd/conf/ssl.key/server.key \
	-F /etc/httpd/conf/ssl.crt/ca.crt \
	-N CN=`hostname --fqdn` \
	-D `hostname --fqdn` \
	-U id-kp-serverAuth

   local-getcert request -r \
	-f /etc/ldap/server.crt \
	-k /etc/ldap/server.key \
	-F /etc/ldap/ca.crt \
	-N CN=`hostname --fqdn` \
	-D `hostname --fqdn` \
	-U id-kp-serverAuth

In this example, both /etc/httpd/conf/ssl.crt/ca.crt and /etc/ldap/ca.crt will
contain copies of the same certificate, and a client connecting to either of
the two services will only need to be given a copy of one of the files in order
to verify the certificate used by either service.

The "local" signer doesn't support revoking certificates, whether in response
to a key compromise or for any of several less catastrophic reasons, so it's
not recommended for general use, either.

Using certmonger With Real CAs

Having certmonger send a CSR to a real CA rather than itself signing everything
is supposed to be trivial.  For example, certmonger already "knows" how to
interact with the CA component of an IPA system, so the only thing you'd do
differently is call "ipa-getcert" instead of "selfsign-getcert" or
"local-getcert".

   ipa-getcert request -r \
	-f /etc/httpd/conf/ssl.crt/server.crt \
	-k /etc/httpd/conf/ssl.key/server.key \
	-N CN=`hostname --fqdn` \
	-D `hostname --fqdn` \
	-U id-kp-serverAuth

That's all there is to it.  If there's more than that to it, that's a bug.
