From Fedora Project Wiki
(→‎Create and Sign a Service Certificate: Randomize the service serial)
(Match current page)
 
(35 intermediate revisions by 5 users not shown)
Line 1: Line 1:
{{admon/warning|This page is a DRAFT and is currently under development}}
{{admon/warning|This page is a DRAFT and is currently under development. [https://fedorahosted.org/fpc/ticket/506 FPC ticket 506]}}
== Services which may be enabled by Default ==
Only services that meet the criteria below are permitted to be enabled by default on package installation.


= First-time Service Setup =
For the purposes of this document, a "service" is defined as one or more of:
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.
* A daemon or process started using a [http://www.freedesktop.org/software/systemd/man/systemd.service.html systemd service unit].
* A daemon or process that is invoked by socket activation, either by using a [http://www.freedesktop.org/software/systemd/man/systemd.socket.html systemd socket unit], [http://standards.freedesktop.org/desktop-entry-spec/1.1/ar01s07.html D-BUS activation] or similar behavior.
* A [http://www.freedesktop.org/software/systemd/man/systemd.timer.html systemd timer unit] that runs periodically.


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).
=== Locally running services ===
If a service does not require manual configuration to be functional and does not listen on a network socket for connections originating on a separate physical or virtual machine, it may be enabled by default (but is not required to do so).


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.
Example: Local D-BUS services


This guideline describes a mechanism that can be used for both traditional and cloud-based deployment styles.
=== Non-persistent services ===
In addition, any service which does not remain persistent on the system (aka, it "runs once then goes away"), does not listen to incoming connections during initialization, and does not require configuration to be functional may be enabled by default (but is not required to do so).


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.
Example: iptables


== Defining System-Specific Setup ==
=== Approved Exceptions ===
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 of system-specific configuration:
Some services which are permitted to be enabled by default as specific exceptions. Services that should be enabled by default throughout all of Fedora must be approved by [https://fedorahosted.org/fesco/newticket FESCo]. Services that should be enabled or disabled by default only on one or more of the Fedora Editions must be approved by those Editions' [https://fedoraproject.org/wiki/Fedora.next#Working_groups Working Groups].
* 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


A few examples that should '''not''' be considered system-specific configuration:
Example:
* Creating a service user and/or group. This is safe to copy to clones of the system.
* FESCo approves openssh-server to run by default on Fedora in general.
* Anything automatically generated by the service when it is started and recreated if it gets deleted.
* Workstation WG approves openssh-server to be disabled by default on the Workstation Edition.
* Creation of a framework for runtime data (such as an empty database or log directory). ''Note: these cases should be documented, since they may *become* populated with additional data that should be cleaned out before cloning.''


== Common Guidelines ==
For all system-specific cases, we will take advantage of systemd's [http://www.freedesktop.org/software/systemd/man/systemd.service.html#ExecStartPre= ExecStartPre] functionality.


{{admon/warning|TODO: decide if this is the right location for scripts}}
== Current list of enabled/disabled services ==
Packagers will create a script in <code>/usr/lib/systemd/system-init/</code> named after the package that it initializes. So for sshd, the script file would be <code>/usr/lib/systemd/system-init/openssh-server</code> (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:
* [https://pagure.io/fedora-release/blob/master/f/90-default.preset Fedora general]
# 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).
* [https://pagure.io/fedora-release/blob/master/f/80-server.preset Fedora Server]
# 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.
* [https://pagure.io/fedora-release/blob/master/f/80-workstation.preset Fedora Workstation]


The service's systemd unit file must be modified to include the following line within the <code>[Service]</code> section:
== How to enable a service by default ==
<pre>
ExecStartPre=/usr/lib/systemd/system-init/<packagename>
</pre>


== Special Case: Self-signed Certificate Generation ==
Unit files must correspond to the Fedora Packaging [[Packaging:ScriptletSnippets#Systemd|Guidelines]]. Services are enabled or disabled by default through [http://www.freedesktop.org/software/systemd/man/systemd.preset.html systemd preset files]. Preset files can be overridden by a local administrator, but a set of defaults are provided by Fedora.


If the service should be enabled by default, it must be added to one of the distribution presets files (see above).


=== OpenSSL and PEM Certificates ===
For services which meet one of the conditions listed above, a ticket should be filed against the
 
[https://bugzilla.redhat.com/enter_bug.cgi?product=Fedora&component=fedora-release&short_desc=PRESETS:+enable+...+by+default&version=rawhide fedora-release package]. If the preset should be changed for versions other than rawhide, indicate that in the ticket.
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.
 
(Note: for any instance of <code>$package</code> below, substitute the name of your package)
 
==== 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                      = Private CA for $project on <real_fqdn> at <date>
OU                    = $package
CN                    = $package.<real_fqdn>
[ 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>$package.<real_fqdn></code>. Additionally, the Organization (O) field should remain as in the example so that it provides clues to administrators who may wish to import the public CA certificate. The date field should match the output of <code>date -u +'%Y-%m-%d %H:%M:%S'</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/owner can read the files we create'''. 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
</pre>
Note: it is *highly* recommended to use a 2048-bit or greater key. Any package that is not compatible with 2048-bit keys should have a bug open to track this shortcoming.
 
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.
 
==== Create and Sign a Service Certificate ====
Similar to the CA certificate generation, we need to create an OpenSSL configuration file for the service certificate as below:
<pre>
[ req ]
distinguished_name    = req_distinguished_name
prompt                = no
req_extensions        = v3_req
[ req_distinguished_name ]
C                      = --
ST                    = SomeState
L                      = SomeCity
O                      = The Fedora Project
OU                    = $package
CN                    = <real FQDN>
[ v3_req ]
basicConstraints      = CA:FALSE
</pre>
 
Note the specific differences from the CA certificate configuration file: the <code>v3_ca</code> reference and section has been replaced by a <code>v3_req</code> section which asserts that this certificate is '''not''' a Certificate Authority (and cannot be used to sign other certificates). Also note that unlike the CA certificate, this configuration requires the CN to match the machine's real fully-qualified hostname. If you do not provide this, clients will be unable to validate this machine's certificate.
 
Save this file as <code>$package-ssl-service.cnf</code> in the same location as the CA configuration. As with that configuration, this file can be removed after processing is complete.
 
Next, we will generate a secure private key for the service certificate. This key '''must''' be retained and provided in the location that the service expects it for SSL to function properly. Substitute the correct location for your package below:
<pre>
/usr/bin/openssl genrsa -out /path/to/service/key 2048
</pre>
 
As above, this generates a 2048-bit key. This should be considered the recommended minimum key strength. If a package does not support 2048-bit or higher keys, a bug should be opened.
 
Next, we will create a signing request for this key and sign it with our temporary CA.
<pre>
/usr/bin/openssl req -new \
                    -config /path/to/$package-ssl-service.cnf \
                    -key /path/to/service/key \
                    -out /path/to/$package-ssl.csr
 
/usr/bin/openssl x509 -req -days 3650 \
                      -in /path/to/$package-ssl.csr \
                      -CA /path/to/$package-ssl-ca.crt \
                      -CAkey $TMPKEY \
                      -CAcreateserial \
                      -set_serial 0x`/usr/bin/openssl rand -hex 8` \
                      -out /path/to/service/certificate \
                      -extfile /path/to/$package-ssl-ca.cnf
</pre>
 
'''Carefully note the "-ca" suffixes there'''; it can be tricky to see where to use the CA certificate information vs. the service certificate information.
 
The last step is to clean up the resulting files, as they are all owned by root with restrictive permissions:
<pre>
# Delete the temporary CA key so nothing else can be signed with it
# We'll also overwrite it with zeros before deleting it, just in case.
dd if=/dev/zero of=$TMPKEY bs=1k count=16
rm -f $TMPKEY
 
# Optionally delete unneeded CSR and the OpenSSL Configuration Files
rm -f /path/to/$package-ssl.csr \
      /path/to/$package-ssl-ca.cnf \
      /path/to/$package-ssl-service.cnf
 
# Restore the original umask
umask $OLDUMASK
 
chown pkguser:pkguser /path/to/service/certificate \
                      /path/to/service/key
# Appropriate chmod() calls here
</pre>
 
 
As a final, optional step, the private temporary CA certificate can be added to the local root CA list so that requests from the local machine will be able to connect as trusted clients without having to skip validation (as would be normal for self-signed certificates). Unlike traditional self-signed certificates, since this temporary CA cannot be used to sign anything else, this does not open your system to a risk of the service certificate being used to falsely sign something.
 
<pre>
cp /path/to/$package-ssl-ca.crt /etc/pki/ca-trust/source/anchors/
update-ca-trust extract
</pre>
 
=== Mozilla NSS Certificate Database ===
TODO
 
== Open Questions ==
* Should we change the Organization in the service certificate configuration examples? Kai Engert raises the following point: "I think the owner of the private key, and thus the one who is responsible for the actions that will be taken with that private key, isn't the fedora project... we're not making certificates for the package, but for a service instance"

Latest revision as of 13:22, 27 January 2016

Warning.png
This page is a DRAFT and is currently under development. FPC ticket 506

Services which may be enabled by Default

Only services that meet the criteria below are permitted to be enabled by default on package installation.

For the purposes of this document, a "service" is defined as one or more of:

Locally running services

If a service does not require manual configuration to be functional and does not listen on a network socket for connections originating on a separate physical or virtual machine, it may be enabled by default (but is not required to do so).

Example: Local D-BUS services

Non-persistent services

In addition, any service which does not remain persistent on the system (aka, it "runs once then goes away"), does not listen to incoming connections during initialization, and does not require configuration to be functional may be enabled by default (but is not required to do so).

Example: iptables

Approved Exceptions

Some services which are permitted to be enabled by default as specific exceptions. Services that should be enabled by default throughout all of Fedora must be approved by FESCo. Services that should be enabled or disabled by default only on one or more of the Fedora Editions must be approved by those Editions' Working Groups.

Example:

  • FESCo approves openssh-server to run by default on Fedora in general.
  • Workstation WG approves openssh-server to be disabled by default on the Workstation Edition.


Current list of enabled/disabled services

How to enable a service by default

Unit files must correspond to the Fedora Packaging Guidelines. Services are enabled or disabled by default through systemd preset files. Preset files can be overridden by a local administrator, but a set of defaults are provided by Fedora.

If the service should be enabled by default, it must be added to one of the distribution presets files (see above).

For services which meet one of the conditions listed above, a ticket should be filed against the fedora-release package. If the preset should be changed for versions other than rawhide, indicate that in the ticket.