Certificats

De Banane Atomic
Aller à la navigationAller à la recherche

Généralités

Utilisé principalement pour identifier et authentifier une personne physique ou morale, mais aussi pour chiffrer des échanges.
Le certificat est une clé publique signée par une CA (Autorité de certification) qui certifie que la clé publique est bien celle de l'entreprise E.

Tuto

Formats

PEM (X509 base64)

Extensions .pem, .crt, .cer, .key
Fichier ASCII encodé en Base64.

-----BEGIN CERTIFICATE-----    -----END CERTIFICATE-----
-----BEGIN PRIVATE KEY-----    -----END PRIVATE KEY-----

Il peut contenir le certificat et la clé privée.
Habituellement la clé privée est dans un fichier séparé PrivateKey.key

DER

Équivalent au PEM mais au format binaire.

PKCS#12 / PFX – Personal Information Exchange

Extension .pfx, .p12
Fichier binaire chiffré. Utilisé sur Windows pour l'import et l'export des certificats.
Possibilité de convertir MonCertificat.p12 → MonCertificat.cer, puis de diviser se dernier en CACertificat.cer et PrivateKey.key

Let's Encrypt

Bash.svg
certbot certonly --email admin@domain.fr --webroot --webroot-path /usr/share/webapps/monsite --domains www.domain.fr --agree-tos --rsa-key-size 4096
# avec cette méthode le site doit être accessible sur le port 80 avec le même nom de server
# l'url http://monsite.domain.fr/.well-known doit être accessible
mkdir -p /var/lib/letsencrypt/.well-known
chgrp http /var/lib/letsencrypt
chmod g+s /var/lib/letsencrypt

#### méthode manuelle ####
certbot certonly --email moi@domain.fr --manual --domains www.domain.fr --agree-tos --rsa-key-size 4096

cd /usr/share/webapp/monsite
mkdir -p .well-known/acme-challenge
printf "%s" xxx.yyy > .well-known/acme-challenge/xxx
# vérifier que le fichier est accessible par Let's Encrypt validation server; +https://www.letsencrypt.org
# supprimer le dossier une fois la validation terminée
rm -r .well-known/acme-challenge

# display information about a certificat
openssl x509 -text -noout -in /etc/letsencrypt/live/domain.fr/cert.pem

4 fichiers sont créés dans /etc/letsencrypt/live/www.domain.fr

cert.pem
chain.pem
fullchain.pem certificat et chain
privkey.pem clé

1 fichier est créé dans /etc/letsencrypt/csr

xxxx_csr-letsencrypt.pem
/etc/nginx/nginx.conf
server {
    listen          80;
    server_name     monsite.domain.fr;
    return          301 https://$server_name$request_uri;
}

server {
    listen          443 ssl http2;
    listen [::]:443 ssl http2;       # Listen on IPv6
    ssl_certificate	    /etc/letsencrypt/live/www.domain.fr/fullchain.pem;
    ssl_certificate_key     /etc/letsencrypt/live/www.domain.fr/privkey.pem;

    include letsencrypt.conf;
/etc/nginx/letsencrypt.conf
location ^~ /.well-known/acme-challenge/ {
  allow all;
  root /var/lib/letsencrypt/;
  default_type "text/plain";
  try_files $uri =404;
}

Renouveler les certificats

Les certificats Let's Encrypt ont une durée de validité de 90 jours.
La commande renew les renouvelle s'ils expirent dans moins de 30 jours.
When run with a set of domains corresponding to an existing certificate, the certonly command attempts to renew that specific certificate. (Renewing certificates)
Une fois le certificat renouvelé, redémarrer le serveur web.

Cron

crontab
# try to renew let's encrypt certificates if needed every day at 00h01
1 0 * * * /path/scripts/renew-certificates.sh
renew-certificates.sh
#!/bin/bash

set -u
set -e
set -o pipefail

# renew for multiple domains
/usr/local/bin/certbot certonly \
    --dns-ovh \  # Obtain certificates using a DNS TXT record
    --dns-ovh-credentials /root/.ovh-api.ini \  # OVH credentials INI file
    --non-interactive \  # Run without ever asking for user input
    --agree-tos \  # Agree to the ACME Subscriber Agreement
    --email admin@domain.fr \  # Email used for registration and recovery contact
    --domains 'domain.fr,*.domain.fr'  # Domain names to apply
    # --dry-run  # Perform a test run of the client, obtaining test (invalid) certificates but not saving them to disk
Any executable files found in /etc/letsencrypt/renewal-hooks/deploy will be run only after a successful renewal.
/etc/letsencrypt/renewal-hooks/deploy/reload-nginx.sh
#!/bin/bash

set -e
set -o pipefail
set -u

systemctl reload nginx
/etc/letsencrypt/renewal-hooks/deploy/restart-apache.sh
#!/bin/bash

set -e
set -o pipefail
set -u

# restart apache
systemctl restart apache2

# Warning: The unit file, source configuration file or drop-ins of apache2.service changed on disk.
# Run 'systemctl daemon-reload' to reload units.
systemctl daemon-reload

Timer et Service

Voici un Timer units qui permet de renouveler les certificats tous les mois.

/etc/systemd/system/letsencrypt.timer
[Unit]
Description=Monthly renewal of Let's Encrypt's certificates

[Timer]
OnCalendar=monthly
Persistent=true

[Install]
WantedBy=timers.target
/etc/systemd/system/letsencrypt.service
[Unit]
Description=Let's Encrypt renewal

[Service]
Type=oneshot
ExecStart=/usr/bin/letsencrypt certonly --renew-by-default -m email@domain.fr --webroot -w /usr/share/webapps/monsite1 -d www1.domain.fr --rsa-key-size 4096
ExecStart=/usr/bin/letsencrypt certonly --renew-by-default -m email@domain.fr --webroot -w /usr/share/webapps/monsite2 -d www2.domain.fr --rsa-key-size 4096
ExecStartPost=/usr/sbin/systemctl restart nginx.service
Bash.svg
systemctl enable letsencrypt.timer
systemctl start letsencrypt.timer

systemctl list-timers

Wildcard certificate on OVH

Utiliser le plugin DNS OVH

Bash.svg
# with snap to get the latest version on Ubuntu
sudo snap install certbot --classic
sudo snap set certbot trust-plugin-with-root=ok  # needed to allow the 2 snaps to communicate
sudo snap install certbot-dns-ovh

# APT
sudo apt install python3-certbot-dns-ovh

# si le paquet n'est pas disponible
sudo apt install python3-pip
# avec root sans sudo
pip3 install certbot  # installer la version pip et désinstaller la version système si elle n'est pas compatible
pip3 install certbot-dns-ovh

Remplir le formulaire pour obtenir les API Keys

/root/.ovh-api.ini
# OVH API credentials used by Certbot
dns_ovh_endpoint = ovh-eu
dns_ovh_application_key = ???
dns_ovh_application_secret = ???
dns_ovh_consumer_key = ???
Bash.svg
sudo chmod 600 /root/.ovh-api.ini

Renouvellement du certificat

/usr/local/sbin/renew-certificate.sh
#!/bin/bash

set -e
set -o pipefail
set -u

/usr/bin/certbot certonly \
    --dns-ovh \
    --dns-ovh-credentials /root/.ovh-api.ini \
    --non-interactive \
    --agree-tos \
    --email admin@domain.fr \
    -d domain.fr,'*.domain.fr'

Si le certificat n'a pas besoin d'être renouvelé:

Cert not yet due for renewal
Keeping the existing certificate
Certificate not yet due for renewal; no action taken.

Erreurs

The currently selected ACME CA endpoint does not support issuing wildcard certificates

Bash.svg
# add this to the command line to use the ACME v2 API that supports Wildcard certificates.
--server https://acme-v02.api.letsencrypt.org/directory

Client with the currently selected authenticator does not support any combination of challenges that will satisfy the CA

Client with the currently selected authenticator does not support any combination of challenges that will satisfy the CA.
You may need to use an authenticator plugin that can do challenges over DNS.

Dans le cas d'une demande de certificat contenant un wildcard, il faut utiliser la v2 de l'API.
Ce qui oblige à utiliser le challenge DNS, qui n'est accessible qu'en manual ou avec les plugins DNS.
Changing the ACME Server

Bash.svg
# use manual
sudo certbot certonly --manual -d 'domain.fr,*.domain.fr'

Achat d'un certificat

Génération du CSR

La CA va utiliser le CSR pour créer le certificat. Elle n'a pas besoin de la clé privée.
Une clé privée est générée en même temps que le CSR.

Il est important de générer le CSR et la clé privée sur le serveur sur lequel on installera le certificat.
Bash.svg
# générer le CSR et la clé privée
openssl req -out CSR.csr -new -newkey rsa:2048 -nodes -keyout privateKey.key

# générer un CSR depuis une clé privée existante
openssl req -out CSR.csr -key privateKey.key -new

# générer un CSR depuis un certificat existant
openssl x509 -x509toreq -in certificate.crt -out CSR.csr -signkey privateKey.key

# décoder le CSR
openssl req -in server.csr -noout -text
Champs du CSR
Champs Exemple
Country Name Code ISO de 2 lettres FR, CH
State or Province Name Semble être obligatoire même hors US
Common Name L'url du site www.domaine.fr
CSR file.txt
-----BEGIN CERTIFICATE REQUEST-----
-----END CERTIFICATE REQUEST-----

Fichiers fournis

  • SSL certificate (ssl_certificate.cer): clé publique
  • Intermediate certificate (IntermediateCA.cer): émetteur du EndEntity certificate (aussi nommé CA/Chaining certificate)
  • Croos Root CA (crossRootCA.cer): certificat obsolète, utilisé pour des raisons de compatibilité

Correspondance entre clé RSA publique, privée et CSR

Bash.svg
# Certificate
openssl x509 -noout -modulus -in server.crt | openssl md5

# Private Key
openssl rsa -noout -modulus -in server.key | openssl md5

# CSR
openssl req -noout -modulus -in server.csr | openssl md5

Gestion des certificats installé dans Windows

Win → certmgr.msc

Convertion

Bash.svg
# Convert CER and Private Key to PFX
openssl pkcs12 -export -in certificatename.cer -inkey privateKey.key -out certificatename.pfx -certfile cacert.cer

unable to write 'random state'

Le dossier ~/.rnd n'est pas accessible.
Avec Cygwin, se produit si la console n'a jamais été lancée.

Erreurs

The profile for the user is a temporary profile

Les profils temporaires sont utilisés si le profil de l’utilisateur est inaccessible ou corrompu. [1]

Ou les profils temporaires sont utilisé car le poste (avec un terminal server) a été configuré ainsi. Dans ce cas, plusieurs solutions possibles :

  • Un fix windows
  • Installer le certificat sur le serveur où se connecte les clients et utiliser du coup le store windows plutôt que le fichier de certificat.