Ubuntu - Certificats self-signed avec sa propre autorité de certification

Logo

Introduction

Même à des fins de développements ou pour tester des produits, on veut installer HTTPS, surtout si on veut que les paquets soient encryptés sur le réseau internet.

Créer un certificat auto-signé est assez simple avec une méthode quelque peu "quick and dirty" (certificat public + clé privée) :

$ openssl req -x509 -out VPSFRSQLPAC.crt -keyout VPSFRSQLPAC.key \
  -newkey rsa:2048 -nodes -sha256 -days 3650 \
  -subj '/CN=VPSFRSQLPAC' -extensions EXT -config <( \
  printf "[dn]\nCN=VPSFRSQLPAC\n[req]\ndistinguished_name = dn\n[EXT]\nsubjectAltName=DNS:VPSFRSQLPAC\nkeyUsage=digitalSignature\nextendedKeyUsage=serverAuth")

Dans l’exemple ci-dessus, un certificat auto-signé est créé pour l’hôte vpsfrsqlpac.

  • -days 3650 : 10 ans (à des fins de développement, ça devrait suffire…).
  • VPSFRSQLPAC.key : clé privée.
  • VPSFRSQLPAC.crt : certificat public.

Le produit pour lequel on veut HTTPS est alors démarré avec les certificats, par exemple InfluxDB :

influxdb.toml
tls-cert = "/etc/ssl/VPSFRSQLPAC.crt"
tls-key = "/etc/ssl/VPSFRSQLPAC.key"

Sur la machine cliente, le certificat public (VPSFRSQLPAC.crt) est importé dans le magasin des certificats des autorités de confiance racine.

https://vpsfrsqlpac:8086 fonctionne très bien sur le client jusqu’au moment où des commandes plus sophistiquées sont nécessaires et invoquées, commandes qui remontent alors des erreurs x509 :

x509: certificate signed by unknown authority

Des options existent pour empêcher les vérifications jusqu’à l’autorité de certificats : curl --insecure, influx --skip verify. Au fil du temps, on ne veut pas utiliser ces options partout, notamment dans des scripts de maintenance.

Voyons comment créer sa petite autorité de certificats fictive (SQLPAC dans cet article).

Dans la suite, par souci de concision, autorité de certificats sera souvent désignée par l’abbréviation CA (Certificate Authority).

SSL CA architecture

Création de l’autorité de certificats SQLPAC

Pour l’autorité de certificats SQLPAC fictive, une clé privée sqlpac.key, d’une longueur de 2048 bytes, est créée dans le répertoire /etc/ssl/sqlpac :

$ openssl genrsa -out /etc/ssl/sqlpac/sqlpac.key 2048
Generating RSA private key, 2048 bit long modulus (2 primes)
............................................+++++
..............+++++
e is 65537 (0x010001)

Pour appliquer un mot de passe si besoin, ajouter l’option -des3 ou -aes256. Le mot de passe sera demandé à la génération de la clé.

Le certificat public associé sqlpac.crt est généré :

openssl req -x509 -new -nodes \
    -key /etc/ssl/sqlpac/sqlpac.key \
    -sha256 \
    -days 3650 \
    -out /etc/ssl/sqlpac/sqlpac.crt \
    -subj "/O=SQLPAC/CN=SQLPAC - Certificate authority/OU=SQLPAC - Certificate authority"
  • -x509 : demande de génération d’un certificat de type X.509.
  • -days 3650 : période d’expiration du certificat.
  • -sha256 : algorithme d’encryption SHA-256 (par défaut l’algorithme SHA-1 est utilisé, plus faible d’un point de vue sécurité).
  • -new : génération d’un nouveau certificat public.
  • -nodes : pas de mot de passe.
  • -key sqlpac.key : clé privée RSA de l’autorité de certificats, générée précédemment.
  • -out sqlpac.crt : fichier du certificat public de l’autorité de certificats en sortie.
  • -subj "/O=SQLPAC/CN=SQLPAC - Certificate authority" : spécifie l’organisation (/O=SQLPAC) et le nom commun (/CN=SQLPAC - Certificate authority). Si ils sont absents, openssl les demande.

Le nom commun (CN) est le nom affiché dans les magasins des certificats des clients.

Déploiement du certicat public de l’autorité de certificats CA sur les clients

Le certificat public sqlpac.crt est alors déployé dans les magasins de certificats des clients.

Windows

Sur Windows, pour importer le certificat public sqlpac.crt, ouvrir Microsoft Management Console (MMC) :

MMC Fichier Ajouter/Supprimer un composant logiciel enfichable… Certificats

MMC Snap In Certificats

Importer le certificat public de l’autorité de certification (sqlpac.crt) dans le magasin "Autorités de certification racines de confiance" à partir du menu contextuel Certificats Toutes les tâches Importer… :

MMC Certificat - import MMC Certificat - import details

Ubuntu

Sur Ubuntu, en tant que root, copier le certificat public du CA dans le répertoire /usr/local/share/ca-certificates :

$ cp /etc/ssl/sqlpac/sqlpac.crt /usr/local/share/ca-certificates/extra

Lancer update-ca-certificates :

$ update-ca-certificates
Updating certificates in /etc/ssl/certs...
1 added, 0 removed; done.
Running hooks in /etc/ca-certificates/update.d...
done.

Les clients sont prêts.

Génération de la clé privée pour https://vpsfrsqlpac et de la demande de signature

L’autorité de certificats SQLPAC est prête. Une clé privée pour https://vpsfrsqlpac est créée : VPSFRSQLPAC.key.

openssl req -new -sha256 -nodes \
     -out /etc/ssl/VPSFRSQLPAC.csr \
     -newkey rsa:2048 -keyout /etc/ssl/VPSFRSQLPAC.key \
     -subj "/O=SQLPAC/CN=VPSFRSQLPAC"
Generating a RSA private key
.............................................................+++++
.............+++++
writing new private key to '/etc/ssl/VPSFRSQLPAC.key'
-----

L’option -out /etc/ssl/VPSFRSQLPAC.csr produit un fichier de demande de signature (CSR - Common Signing Request). Ce CSR sera soumis plus tard à l’autorité de certificats SQLPAC afin d’obtenir en retour le certificat public associé signé par le CA.

Le paramètre CN doit être le même que le nom du host dans l’URL.
CN=VPSFRSQLPAC      https://vpsfrsqlpac

Si la clé privée est générée avec le compte root, ne pas oublier de modifier les permissions. Par défaut openssl créé le fichier de la clé RSA en lecture seule au compte utilisé.

$ chmod o+r VPSFRSQLPAC.key

Obtention du certificat public signé

Dernière étape, le certificat public associé VPSFRSQLPAC.crt, signé par le CA SQLPAC, est généré.

openssl x509 -req \
    -in /etc/ssl/VPSFRSQLPAC.csr \
    -CAkey /etc/ssl/sqlpac/sqlpac.key \
    -CA /etc/ssl/sqlpac/sqlpac.crt \
    -CAcreateserial -CAserial /etc/ssl/VPSFRSQLPAC.serial \
    -out /etc/ssl/VPSFRSQLPAC.crt \
    -days 3650 \
    -sha256 \
    -extfile /etc/ssl/VPSFRSQLPAC.sslv3.txt
Signature ok
subject=O = SQLPAC, CN = VPSFRSQLPAC
Getting CA Private Key
  • -in /etc/ssl/VPSFRSQLPAC.csr : la demande de signature en entrée.
  • -CAkey /etc/ssl/sqlpac/sqlpac.key : la clé privée RSA du CA.
  • -CA /etc/ssl/sqlpac/sqlpac.crt : le certificat public du CA.
  • -CAcreateserial -CAserial /etc/ssl/VPSFRSQLPAC.serial : optionnel, génération d’un serial number.
  • -out /etc/ssl/VPSFRSQLPAC.crt : le certificat public signé en sortie.

Dans le fichier /etc/ssl/VPSFRSQLPAC.sslv3.txt envoyé avec l’argument -extfile, quelques paramètres SSL v3 sont spécifiés, tout particulièrement les noms DNS alternatifs (https://<DNS names>)

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

[alt_names]
DNS.1 = vpsfrsqlpac

C’est une directive importante. Pour Apache, les noms alternatifs alt_names ressembleront à l’exemple ci-dessous pour toutes les URLs possibles (https://fr.sqlpac.uat, https://sqlpac.uat…) :

[alt_names]
DNS.1 = sqlpac.uat
DNS.2 = *.sqlpac.uat

Étapes finales, vérifications

C’est fini, tout est prêt. Redémarrer les softs qui utilisent les adresses https://vpsfrsqlpac:* avec la clé privée et le certificat public :

influxdb.toml
grafana.ini
…
http-bind-address = "vpsfrsqlpac2:8086"
tls-cert = "/etc/ssl/VPSFRSQLPAC.crt"
tls-key = "/etc/ssl/VPSFRSQLPAC.key"
…
…
http_port = 20002
…
# https certs & key file
cert_file = /etc/ssl/VPSFRSQLPAC2.crt
cert_key = /etc/ssl/VPSFRSQLPAC2.key
…

Plus besoin d’ajouter des options supplémentaires aux lignes de commandes (curl --insecure, influx --skip-verify…) afin d’empêcher la vérification du CA.

Comment tester le mécanisme de validation avec le CA ? Utiliser openssl avec l’option s_client, le chemin de validation est affiché :

$ openssl s_client -connect vpsfrsqlpac:8086 
CONNECTED(00000005)
…
---
Certificate chain
 0 s:O = SQLPAC, CN = VPSFRSQLPAC
   i:O = SQLPAC, CN = SQLPAC - Certificate authority, OU = SQLPAC - Certificate authority
---
…
SSL handshake has read 1615 bytes and written 793 bytes
Verification: OK
…
New, TLSv1.3, Cipher is TLS_AES_128_GCM_SHA256
…
Verify return code: 0 (ok)