Egal, ob Sie eine Testumgebung möglichst realitätsnah gestalten wollen, Checkmk im Intranet (besser) absichern wollen, oder eine intern mit TLD ohne Registrar aufgebaute Netzwerkumgebung (beispielsweise ein Windows-Netz mit Samba Active Directory) es erzwingt: Eine eigene Certificate Authority kombiniert Sicherheit und Flexibilität. Die grundlegende Infrastruktur ist in weniger als einer Stunde aufgebaut.

Der Weg, SSL-/TLS-Zertifikate mit einer internen CA auszustellen, ist vor allem für Testumgebungen oder abgeschottete Checkmk-Server mit überschaubarer Nutzerzahl sinnvoll. Sie ist zudem die einzige Möglichkeit, Zertifikate zu erhalten, wenn Sie intern eine der fünf reservierten TLDs .example, .invalid, .local, .localhost, oder .test verwenden, wie es in Windows- (Samba-) Umgebungen häufig der Standard ist, um sowohl Namensauflösung im Internet als auch Routing ins Internet zu verhindern. Für diese Domains gibt es keine Registrare, sodass sich keine Inhaberschaft bestätigen lässt.

In diesem Artikel zeigen wir Ihnen, wie Sie Ihre eigene CA aufbauen können. Das geht mit Linux-Bordmitteln und erfordert wenig Vorkenntnisse. Unser Beispiel verwendet eine Domain in der TLD .test, Sie können mit Ihrer eigenen CA jedoch Zertifikate für beliebige (auch fremde!) Domains ausstellen.

Auch wenn eine Person auf einem Rechner alle Schritte durchführen kann: Um die Rollenverteilung im Zertifizierungsprozess zu verdeutlichen, nutzen wir Carla als Verwalterin der Certificate Authority, Bob als Betreuer des Intermediate Keys und schließlich Alice, die Administratorin, die Server-Zertifikate signieren lässt. Die Zahl der Intermediate Ebenen können Sie je nach Anforderungen beliebig erhöhen.

Sicherheitshinweise

  • Diese Anleitung verzichtet auf die Verwendung einer Certificate Revocation List. In größeren Produktivumgebungen sollten Sie jedoch eine verwenden, um kompromittierten Schlüsseln schnell das Vertrauen entziehen zu können!
  • Auch in Testumgebungen gilt, dass starke Passwörter verwendet und private Schlüssel gut gesichert werden müssen, denn  mit dem verwendeten CA-Schlüssel lassen sich Zertifikate für beliebige Domains erstellen. Systeme, die dem Zertifikat eines "verlorenen" Schlüssels vertrauen, sind damit anfällig für (Wo)man-in-the-Middle-Angriffe!

Schlüssel für die CA und Root-Zertifikat erstellen

Carla nutzt für die Arbeit mit ihrer CA aus Sicherheitsgründen ein Notebook ohne Internetverbindung. Mit der Lagerung im Tresor schließt sie aus, dass eine dritte Person einen (Hardware-) Keylogger installieren kann.

Da man im Laufe der Arbeit mit der CA einige Dateien mit verschiedenen Verwendungszwecken erstellt, ist es ratsam, hierfür eine eindeutig benannte Verzeichnisstruktur zu verwenden. Diese erstellt Carla unter /home/carla/ca:

carla@nb:~$ for d in certs newcerts crl private ; do mkdir -p ~/ca/$d ; done
carla@nb:~$ for f in index.txt serial ; do touch ~/ca/$f ; done

Im Ordner ~/ca/ legt sie eine Datei ca.cnf ab, von der wir ein Beispiel vorbereitet und am Ende dieses Artikels angehängt haben. Anschließend erstellt Carla den privaten Schlüssel der CA, den sie AES256-verschlüsselt ablegt und mit einer langen Passphrase versieht:

carla@nb:~$ cd ca
carla@nb:~/ca$ openssl genrsa -aes256 -out private/ca.key.pem 4096
Generating RSA private key, 4096 bit long modulus (2 primes)
.............++++
..........++++
e is 65537 (0x010001)
Enter pass phrase for private/ca.key.pem:
Verifying - Enter pass phrase for private/ca.key.pem:

Es folgt das Root-Zertifikat, hier mit einer Gültigkeit von zwölf Jahren und zwei Wochen – mehr zur Wahl der Gültigkeitszeiträume weiter unten. Die relevanten Parameter für Ort und Unternehmen übernimmt sie aus der Konfigurationsdatei ca.cnf. Common Name und Email Address sind auf sinnvolle Werte zu setzen:

carla@nb:~/ca$ openssl req -config ca.cnf  -new \
    -key private/ca.key.pem -x509 -days 4398 \
    -sha256 -extensions v3_ca -out certs/ca.cert.pem
Enter pass phrase for private/ca.key.pem:

You are about to be asked to enter information that will be incorporated into your certificate request. What you are about to enter is what is called a Distinguished Name or a DN.

There are quite a few fields, but you can leave some blank. For some fields there will be a default value, if you enter '.', the field will be left blank.

---
Country Name (2 letter code) [DE]:
State or Province Name [Bavaria]:
Locality Name [Munich]:
Organization Name [Stark Industries Ltd.]:
Organizational Unit Name []:
Common Name []: Stark Industries Root Certificate
Email Address []: carla@starkindustries.test

Anschließend prüft Carla das Root-Zertifikat mit dem folgenden Befehl:

carla@nb:~/ca$ openssl x509 -noout -text -in certs/ca.cert.pem
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            25:a0:77:02:e7:29:07:f7:b5:d5:ba:b5:a3:4e:2b:eb:b3:e7:a6:c0
        Signature Algorithm: sha256WithRSAEncryption
        Issuer: C = DE, ST = Bavaria, L = Munich, O = Stark Industries Ltd., CN = Stark Industries Root Certificate, emailAddress = carla@starkindustries.test
        Validity
            Not Before: Feb 15 14:52:12 2022 GMT
            Not After : Mar 2 14:52:12 2034 GMT
        Subject: C = DE, ST = Bavaria, L = Munich, O = Stark Industries Ltd., CN = Stark Industries Root Certificate, emailAddress = carla@starkindustries.test
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                RSA Public-Key: (4096 bit)
                Modulus:
                    00:d7:a9:89:94:dd:02:66:bf:fd:8e:c2:70:4b:d0:
[…]

Carla kopiert jetzt die Konfigurationsdatei ca.cnf und stellt sie dem Kollegen Bob als Vorlage zur Verfügung. Dadurch hat Bob die passenden Parameter sowie Unternehmensnamen und -standort in der richtigen Schreibweise vorliegen.

Das Intermediate-Zertifikat

Bob ist derjenige, der die tägliche Arbeit mit Zertifikaten für das lokale Netzwerk durchführt. Seine Aufgabe ist es, mit einem Intermediate-Zertifikat die Server-Schlüssel zu signieren, die Administratorinnen und Administratoren an ihn herantragen. Dazu erstellt er zunächst eine Verzeichnisstruktur und verwendet dafür den Ordner im (wie intermediate) in seinem Heimatverzeichnis:

bob@pc:~$ for d in certs newcerts crl private ; do mkdir -p ~/im/$d ; done
bob@pc:~$ for f in index.txt serial ; do touch ~/im/$f ; done

Im Ordner im legt er die von Carla erhaltene Konfigurationsdatei als im.cnf ab und passt darin die Standardpfade auf sein Heimatverzeichnis und seine Rolle an. Anschließend erstellt auch er einen Private Key, mit dem er die nächsten Jahre arbeiten wird:

bob@pc:~$ cd im
bob@pc:~/im$ openssl genrsa -aes256 -out private/im.key.pem 4096

Im nächsten Schritt erstellt er das Certificate Signing Request (CSR) für diesen Schlüssel, hier ist das Dateinamensuffix .csr üblich:

bob@pc:~/im$ openssl req -config im.cnf -new -sha256 \
    -key private/im.key.pem -out certs/imbob.csr

[…]
Country Name (2 letter code) [DE]:
State or Province Name [Bavaria]:
Locality Name [Munich]:
Organization Name [Stark Industries Ltd.]:
Organizational Unit Name []:
Common Name []: Stark Industries Bobs Intermediate Certificate
Email Address []: bob@starkindustries.test

Der Common Name muss sich hier von dem des Root-Zertifikates unterscheiden. Und auch hier sollte man eine erreichbare E-Mail-Adresse verwenden. Mit der Datei imbob.csr geht Bob auf einen Kaffee zu Carla ins Büro. Diese holt das Notebook mit dem CA-Schlüssel aus dem Tresor, kopiert Bobs CSR in ihren Ordner certs und signiert Bobs CSR – hier mit einer Laufzeit von vier Jahren und zwei Wochen:

carla@nb:~$ cd ca
carla@nb:~/ca$ openssl ca -config ca.cnf \
    -extensions v3_intermediate_ca \
    -days 1476 -rand_serial -notext -md sha256 \
    -in certs/imbob.csr -out certs/imbob.pem

Nun wird die Passphrase des Schlüssels abgefragt, der Inhalt des Certificate Signing Requests angezeigt und nach Bestätigung das Intermediate Certificate erstellt. Carla gibt Bob nun die beiden PEM-Dateien ca.cert.pem (das PEM kodierte Zertifikat der Certificate Authority) und imbob.pem (das Intermediate Certificate) mit, fährt das Notebook wieder herunter und verschließt es im Tresor. Zurück an seinem Rechner legt Bob beide Dateien in den Ordner ~/im/certs ab.

Schlüssel für die Checkmk Instanz erstellen

Alice ist Administratorin der internen Checkmk Server bei Stark Industries Ltd. Für die Absicherung eines neuen Checkmk Servers erstellt sie zunächst den Server-Schlüssel. Hier ist es pragmatisch, keine Passphrase zu verwenden, also auf -des3 oder -aes256 zu verzichten. Ansonsten muss man diese Passphrase bei jedem Start des Servers erneut eingeben. Als Dateiname ist der Host-Name des Servers sinnvoll.

alice@pc:~$ openssl genrsa -out checkmk.starkindustries.test.key 2048
Generating RSA private key, 2048 bit long modulus (2 primes)
.................................++++
.......++++
e is 65537 (0x010001)

Es folgt die Erstellung des CSR. Wieder müssen die Fragen nach Firma und Abteilung beantwortet werden. Wichtig ist hier der Common Name, der dem primären Host-Namen des Servers entsprechen sollte. Um den Überblick zu behalten, benennt Alice Schlüssel- und CSR-Datei nach dem Server, auf dem beide eingesetzt werden. Eine Konfigurationsdatei ist für Alice optional, hier verzichtet sie darauf:

alice@pc:~$ openssl req -new -key checkmk.starkindustries.test.key \
    -out checkmk.starkindustries.test.csr

[...]
Country Name (2 letter code) [DE]:
State or Province Name [Bavaria]:
Locality Name [Munich]:
Organization Name [Stark Industries Ltd.]:
Organizational Unit Name []:
Common Name (e.g. server FQDN or YOUR name) []: checkmk.starkindustries.test
Email Address []: alice@starkindustries.test

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:

Das Challenge-Passwort darf leer bleiben. Nun erstellt Alice eine X509 V3 certificate extension Konfigurationsdatei checkmk.starkindustries.test.ext:

/home/alice/checkmk.starkindustries.test.ext

authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
subjectAltName = @alt_names

[alt_names]
DNS.1 = checkmk.starkindustries.test
DNS.2 = monitoring.starkindustries.test

Wichtig: Auch wenn man ein Zertifikat nur für einen einzigen Host-Namen verwenden will, ist die Extension-Datei für alle modernen Browser Pflicht. Sie enthält dann gegebenenfalls unter [alt_names] nur eine Zeile.

Signieren eines Zertifikates

Mit den beiden Dateien checkmk.starkindustries.test.csr und checkmk.starkindustries.test.ext im Gepäck lädt sich Alice bei Bob auf einen Becher Macha-Tee in dessen Büro ein. Bob signiert nun mit seinem Intermediate-Zertifikat das mitgebrachte CSR mit hier einem Jahr Gültigkeit:

bob@pc:~$ cd im
bob@pc:~/im$ openssl x509 -CAcreateserial -req \
    -in certs/checkmk.starkindustries.test.csr \
    -CA certs/imbob.pem -CAkey private/im.key.pem \
    -out certs/checkmk.starkindustries.test.crt -days 365 \
    -sha256 -extfile certs/checkmk.starkindustries.test.ext

Alice erhält von Bob im Gegenzug drei Dateien: ca.cert.pem und imbob.pem stellen die Zertifikatskette dar und checkmk.starkindustries.test.crt ist das zum Server-Schlüssel checkmk.starkindustries.test.key gehörende Zertifikat. Diese Dateien kann sie nun auf dem Server ausrollen:

/etc/apache2/sites-enabled/default-ssl.conf
SSLEngine on
SSLCertificateKeyFile /etc/certs/checkmk.starkindustries.test.key
SSLCertificateChainFile /etc/certs/imbob.pem
SSLCertificateFile /etc/certs/checkmk.starkindustries.test.crt

Importieren der CA

Die Wege, ein CA Zertifikat als vertrauenswürdig zu importieren, unterscheiden sich von Browser zu Browser. Meist genügt es, das Zertifikat ca.cert.pem unter Einstellungen > Datenschutz und Sicherheit > Zertifikate > Importieren hinzuzufügen.

Damit die Zertifikatsverwaltung kein Stolperstein beim automatischen Update von Checkmk Agenten darstellt, haben wir in der Agentenbäckerei die Möglichkeit vorgesehen, ein eigenes CA-Zertifikat zu übergeben, das nur für Agenten-Updates benutzt wird. Die Systemzertifikate bleiben hierbei unangetastet, Agenten-Updates sind dennoch möglich.

Alternativ zur Verteilung per Agenten-Update können Sie das Root-Zertifikat in der lokalen CA-Datenbank des Hosts integrieren. Kopieren Sie dafür die Datei ca.cert.pem nach /usr/local/share/ca-certificates/starkindustries.crt. Anschließend generieren Sie den Cache neu:

root@linux# update-ca-certificates

Unter Windows ist es möglich, die Systemzertifikate über das MMC-Snap-In "Certificates" zu verwalten. Dies ist beispielsweise nötig, wenn Sie einen Microsoft-Browser verwenden wollen, um auf ein mit eigener CA abgesichertes Checkmk zuzugreifen. Das genaue Vorgehen können Sie im Microsofts Knowledge Base Artikel PKI nachlesen. Alternativ können Sie Zertifikate per Intune verteilen.

Zertifikatslaufzeit und -kaskaden

Die gesamte Zertifikatskaskade funktioniert nur, während alle Zertifikate gültig sind. Daher sollten Sie über Laufzeiten Buch führen und an jeder Stelle der Kette rechtzeitig ein neues Zertifikat erstellen. Wenn die Laufzeit von Carlas Root-Zertifikat zwölf Jahre beträgt und sie damit maximal vier Jahre gültige Intermediate-Zertifikate für Bob ausstellt, muss sie sich rechtzeitig vor Ablauf von acht Jahren ein neues Root-Zertifikat ausstellen und künftig dieses zum Signieren benutzen. Bob wiederum, der maximal zwei Jahre gültige Zertifikate ausstellt, muss alle zwei Jahre auf einen Kaffee bei Carla vorbeischauen, um ein neues, vier Jahre gültiges Zertifikat zu erhalten.

Alice weiß, dass Bob nur zwei Jahre gültige Server-Zertifikate ausstellen kann. Sollte Alice im Zuge der Expansion von Stark Industries sehr viele Server-Zertifikate benötigen, kann Bob als Inhaber eines Intermediate-Zertifikats für Alice ein weiteres Intermediate-Zertifikat mit zwei Jahren Gültigkeit erstellen. So kann Alice dann in die Rolle einer ihm untergeordneten CA schlüpfen, die Zertifikate mit einem Jahr Gültigkeit ausstellt. In diesem Fall muss sie jährlich bei Bob vorbeischauen.

Im unten angehängten Konfigurationsbeispiel muss dann als SSLCertificateChainFile nicht Bobs Intermediate-Zertifikat auf dem Server platziert werden, sondern eine Konkatenation aus Bobs und Alice’ Intermediate-Zertifikaten.

Und kompromittierte Zertifikate?

Die Sicherheitsmaßnahmen von Carla mögen Ihnen auf den ersten Blick etwas paranoid vorkommen, aber kompromittierten Root-Zertifikaten ist schwer beizukommen, weil man letztlich das Zertifikat auf allen Clients, die es nutzen, entfernen muss. Aus diesem Grund raten wir auch in vergleichsweise kleinen Testumgebungen dazu, das Root-Zertifikat wegzuschließen – das muss kein eigenes Notebook sein, oft ist der USB-Stick im Tresor sicher genug. Die regelmäßige Signierung erfolgt dann mit dem Intermediate Zertifikat.

In überschaubaren Umgebungen kann Bob eine Liste der mit einem bestimmten Intermediate Zertifikat signierten Zertifikate führen und die betroffenen Server-Admins darüber informieren, dass sie neue Zertifikate benötigen, wenn ein IM-Zertifikat kompromittiert wurde.

Das ist schwieriger, wenn sich Bob selbst als nicht vertrauenswürdig herausstellt, weil er beispielsweise Zertifikate für fremde Domains ausgestellt hat, um den Datenverkehr der Buchhaltung auszuspionieren. Daher ist in wachsenden Umgebungen das Führen einer Certificate Revocation List eine gute Idee. Die zusätzlichen Schritte beschreibt Jamie Nguyen sehr gut in seinem Blog.

Appendix: Die Konfigurationsdatei ca.cnf

Die Konfigurationsdatei /home/carla/ca/ca.cnf kopiert (und überschreibt damit) viele Abschnitte der systemweiten openssl.cnf. Kopieren Sie diese Datei als Basis für die eigene CA-Konfiguration (zurück zur Schlüsselerzeugung). Passen Sie dann zunächst die Verzeichnisse (im Abschnitt [ CA_default ]) und die Firmendaten (im Abschnitt [ req_distinguished_name ]) an.

/home/carla/ca/ca.cnf
# OpenSSL root CA configuration file.
# Copy to `/home/username/ca/ca.cnf`.

[ ca ]
# `man ca`
default_ca = CA_default

[ CA_default ]
# Directory and file locations.
dir               = /home/carla/ca
certs             = $dir/certs
crl_dir           = $dir/crl
new_certs_dir     = $dir/newcerts
database          = $dir/index.txt
serial            = $dir/serial
RANDFILE          = $dir/private/.rand

# The root key and root certificate.
private_key       = $dir/private/ca.key.pem
certificate       = $dir/certs/ca.cert.pem

# For certificate revocation lists.
crlnumber         = $dir/crlnumber
crl               = $dir/crl/ca.crl.pem
crl_extensions    = crl_ext
default_crl_days  = 30

# SHA-1 is deprecated, so use SHA-2 instead.
default_md        = sha256

name_opt          = ca_default
cert_opt          = ca_default
default_days      = 375
preserve          = no
policy            = policy_strict

[ policy_strict ]
# The root CA should only sign intermediate certificates that match.
# See the POLICY FORMAT section of `man ca`.
countryName             = match
stateOrProvinceName     = match
organizationName        = match
organizationalUnitName  = optional
commonName              = supplied
emailAddress            = optional

[ policy_loose ]
# Allow the intermediate CA to sign a more diverse range of certificates.
# See the POLICY FORMAT section of the `ca` man page.
countryName             = optional
stateOrProvinceName     = optional
localityName            = optional
organizationName        = optional
organizationalUnitName  = optional
commonName              = supplied
emailAddress            = optional

[ req ]
# Options for the `req` tool (`man req`).
default_bits        = 2048
distinguished_name  = req_distinguished_name
string_mask         = utf8only

# SHA-1 is deprecated, so use SHA-2 instead.
default_md          = sha256

# Extension to add when the -x509 option is used.
x509_extensions     = v3_ca

[ req_distinguished_name ]
# See <https://en.wikipedia.org/wiki/Certificate_signing_request>.
countryName                     = Country Name (2 letter code)
stateOrProvinceName             = State or Province Name
localityName                    = Locality Name
0.organizationName              = Organization Name
organizationalUnitName          = Organizational Unit Name
commonName                      = Common Name
emailAddress                    = Email Address

# Optionally, specify some defaults.
countryName_default             = DE
stateOrProvinceName_default     = Bavaria
localityName_default            = Munich
0.organizationName_default      = Stark Industries Ltd.
organizationalUnitName_default  =
emailAddress_default            =

[ v3_ca ]
# Extensions for a typical CA (`man x509v3_config`).
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer
basicConstraints = critical, CA:true
keyUsage = critical, digitalSignature, cRLSign, keyCertSign

[ v3_intermediate_ca ]
# Extensions for a typical intermediate CA (`man x509v3_config`).
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer
basicConstraints = critical, CA:true, pathlen:0
keyUsage = critical, digitalSignature, cRLSign, keyCertSign

[ usr_cert ]
# Extensions for client certificates (`man x509v3_config`).
basicConstraints = CA:FALSE
nsCertType = client, email
nsComment = "OpenSSL Generated Client Certificate"
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer
keyUsage = critical, nonRepudiation, digitalSignature, keyEncipherment
extendedKeyUsage = clientAuth, emailProtection

[ server_cert ]
# Extensions for server certificates (`man x509v3_config`).
basicConstraints = CA:FALSE
nsCertType = server
nsComment = "OpenSSL Generated Server Certificate"
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer:always
keyUsage = critical, digitalSignature, keyEncipherment
extendedKeyUsage = serverAuth

[ crl_ext ]
# Extension for CRLs (`man x509v3_config`).
authorityKeyIdentifier=keyid:always

[ ocsp ]
# Extension for OCSP signing certificates (`man ocsp`).
basicConstraints = CA:FALSE
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer
keyUsage = critical, digitalSignature
extendedKeyUsage = critical, OCSPSigning