From Fedora Project Wiki
No edit summary
Line 37: Line 37:


==== OpenSSL and PEM Certificates ====
==== OpenSSL and PEM Certificates ====
This tutorial will provide the steps to produce something akin to a self-signed certificate, except that the resulting service certificate cannot be used to sign further certificates (thus closing a potential security issue). In broad terms, what we are doing is creating a short-lived certificate authority, using that to sign a service certificate and then destroying the key material for the temporary authority.
===== Create Short-Lived Certificate Authority =====
First, create an OpenSSL configuration file for the CA certificate. It should be similar to this:
<pre>
[ req ]
distinguished_name    = req_distinguished_name
prompt                = no
x509_extensions        = v3_ca
[ req_distinguished_name ]
C                      = --
ST                    = SomeState
L                      = SomeCity
O                      = The Fedora Project
OU                    = MyPackage
CN                    = fedora.local
[ v3_ca ]
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid:always,issuer
basicConstraints = CA:TRUE
</pre>
Most of the organizational values above can be changed, but CN must be <code>fedora.local</code>. Create this file with the name <code>$package-ssl-ca.cnf</code> in a location owned by your package. You may retain or destroy this file later as you prefer.
Next, we will generate the private key for this temporary Certificate Authority. '''Set the umask so that only root can read it'''. Then create the key file with the <code>openssl</code> command. We will create the temporary key file in <code>/dev/shm</code> so that it is unlikely to ever be written to persistent media.
<pre>
OLDUMASK=`umask`
umask 0077
TMPKEY=`mktemp --tmpdir=/dev/shm XXXXXXXXXXXX`
/usr/bin/openssl genrsa -out $TMPKEY 2048
umask $OLDUMASK
</pre>
Next, we will use this private key to create the temporary CA Certificate:
<pre>
    /usr/bin/openssl req -new -x509 -days 3650 \
                        -config /path/to/$package-ssl-ca.cnf \
                        -key $TMPKEY \
                        -out /path/to/$package-ssl-ca.crt
</pre>
You can adjust the value of -days as you prefer. Store the <code>$package-ssl-ca.crt</code> file in the same location as the <code>$package-ssl-ca.cnf</code>. Now we have a certificate authority available to sign our service certificate.


==== Mozilla NSS Certificate Database ====
==== Mozilla NSS Certificate Database ====

Revision as of 20:18, 26 February 2015

This page is a DRAFT and is currently under development

First-time Service Setup

Many system services require some amount of initial setup before they can run properly for the first time. Common examples are the generation of private keys and certificates or a unique, system-specific identifier.

Traditionally, this was done by RPM scriptlets as part of the installation or upgrade of a package. This was sensible for a time when the majority of installations were performed by attended or unattended installers (such as anaconda and kickstart).

Today we see an increased reliance on generating virtual machine images for use in both traditional and cloud-computing environments. In those cases, having system-specific data created at package installation time is problematic. It means that the production of such images need to have significant care applied to remove any system-specific information about them and then additional tools written to apply the corrected information post-deployment.

This guideline describes a mechanism that can be used for both traditional and cloud-based deployment styles.

Note: this requirement can be waived if the equivalent functionality is incorporated as part of the service's own standard startup. These guidelines are meant to address services that require setup before the service can be started.

Defining System-Specific Setup

A particular setup task is defined thusly: "Any action that must be performed on the system where the service will be run that is not common to all systems running that service."

Some non-exhaustive examples:

  • The SSH daemon generates a public/private host key
  • The mod_ssl httpd module creates a self-signed certificate for the machine's hostname
  • A remote logging service creates a UUID to represent this machine

Common Guidelines

For all system-specific cases, we will take advantage of systemd's ExecStartPre functionality.

TODO: decide if this is the right location for scripts

Packagers will create a script in /usr/lib/systemd/system-init/ named after the package that it initializes. So for sshd, the script file would be /usr/lib/systemd/system-init/openssh-server (note that the language of the script is up to the packager, but the file must be executable). This script must implement all of the following steps:

  1. Perform a test for whether the initialization has already completed. This may be a simple test of file existence or a more complicated examination of the configuration, as needed. If the initialization has already occurred, the script must immediately return zero (success).
  2. Perform whatever steps are necessary to generate the configuration. If this cannot be accomplished, the script must return with a non-zero error code. This will prevent systemd from attempting to start the actual service. If this completes successfully, it must satisfy any and all requirements for the first step to to pass. On success, it must return zero.

The service's systemd unit file must be modified to include the following line within the [Service] section:

ExecStartPre=/usr/lib/systemd/system-init/<packagename>

Special Case: Self-signed Certificate Generation

OpenSSL and PEM Certificates

This tutorial will provide the steps to produce something akin to a self-signed certificate, except that the resulting service certificate cannot be used to sign further certificates (thus closing a potential security issue). In broad terms, what we are doing is creating a short-lived certificate authority, using that to sign a service certificate and then destroying the key material for the temporary authority.

Create Short-Lived Certificate Authority

First, create an OpenSSL configuration file for the CA certificate. It should be similar to this:

[ req ]
distinguished_name     = req_distinguished_name
prompt                 = no
x509_extensions        = v3_ca
[ req_distinguished_name ]
C                      = --
ST                     = SomeState
L                      = SomeCity
O                      = The Fedora Project
OU                     = MyPackage
CN                     = fedora.local
[ v3_ca ]
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid:always,issuer
basicConstraints = CA:TRUE

Most of the organizational values above can be changed, but CN must be fedora.local. Create this file with the name $package-ssl-ca.cnf in a location owned by your package. You may retain or destroy this file later as you prefer.

Next, we will generate the private key for this temporary Certificate Authority. Set the umask so that only root can read it. Then create the key file with the openssl command. We will create the temporary key file in /dev/shm so that it is unlikely to ever be written to persistent media.

OLDUMASK=`umask`
umask 0077

TMPKEY=`mktemp --tmpdir=/dev/shm XXXXXXXXXXXX`
/usr/bin/openssl genrsa -out $TMPKEY 2048

umask $OLDUMASK

Next, we will use this private key to create the temporary CA Certificate:

    /usr/bin/openssl req -new -x509 -days 3650 \
                         -config /path/to/$package-ssl-ca.cnf \
                         -key $TMPKEY \
                         -out /path/to/$package-ssl-ca.crt

You can adjust the value of -days as you prefer. Store the $package-ssl-ca.crt file in the same location as the $package-ssl-ca.cnf. Now we have a certificate authority available to sign our service certificate.

Mozilla NSS Certificate Database