Certificats X.509
Vue d’ensemble
Configuration et génération de certificats X.509 pour sécuriser les services de l’infrastructure, notamment le portail Incus.
Génération de clé privée ED25519
La courbe elliptique ED25519 offre une sécurité élevée avec des clés plus courtes et des performances optimisées.
Création de la clé privée
openssl genpkey -algorithm ED25519 -out incusPortal.key
Extraction de la clé publique
openssl pkey -in incusPortal.key -pubout -out incusPortal.pub
Avantages d’ED25519
- Performance : Signature et vérification rapides
- Sécurité : Résistance aux attaques par canaux cachés
- Taille : Clés et signatures compactes (32 bytes pour la clé publique)
Configuration de la demande de certificat
Fichier de configuration req.conf
[ req ]
default_bits = 256
default_keyfile = portal.key
distinguished_name = req_distinguished_name
req_extensions = req_ext
string_mask = utf8only
[ req_distinguished_name ]
countryName = Country Name (2 letter code)
countryName_default = FR
stateOrProvinceName = State or Province Name (full name)
stateOrProvinceName_default = Ile-de-France
localityName = Locality Name (eg, city)
localityName_default = Paris
organizationName = Organization Name (eg, company)
organizationName_default = OCF
commonName = Common Name (e.g. server FQDN or YOUR name)
commonName_default = rougy.net
[ req_ext ]
subjectAltName = @alt_names
[ alt_names ]
DNS.1 = rougy.net
DNS.2 = portal.rougy.net
DNS.3 = incus.rougy.net
IP.1 = 192.168.1.100
Paramètres importants
- subjectAltName : Permet d’utiliser le certificat pour plusieurs domaines
- string_mask = utf8only : Assure la compatibilité Unicode
- default_bits = 256 : Adapté pour ED25519
Création de la demande de certificat
Génération du CSR
openssl req -new -key incusPortal.key -out incusPortal.csr -config req.conf -batch
Vérification du CSR
# Affichage du contenu du CSR
openssl req -in incusPortal.csr -text -noout
# Vérification des extensions
openssl req -in incusPortal.csr -text -noout | grep -A 3 "Subject Alternative Name"
Signature du certificat
Auto-signature (développement)
openssl x509 -req -days 365 -in incusPortal.csr -signkey incusPortal.key -out incusPortal.crt -extensions req_ext -extfile req.conf
Signature par CA interne
# Si vous avez une CA interne
openssl x509 -req -in incusPortal.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out incusPortal.crt -days 365 -extensions req_ext -extfile req.conf
Validation et tests
Vérification du certificat
# Affichage des détails du certificat
openssl x509 -in incusPortal.crt -text -noout
# Vérification de la correspondance clé/certificat
openssl pkey -in incusPortal.key -pubout | openssl md5
openssl x509 -in incusPortal.crt -pubkey -noout | openssl md5
Test de la chaîne complète
# Test avec s_client
openssl s_client -connect portal.rougy.net:443 -servername portal.rougy.net
# Vérification de la date d'expiration
openssl x509 -in incusPortal.crt -noout -dates
Déploiement
Structure des fichiers
/etc/ssl/private/
├── incusPortal.key # Clé privée (600, root:root)
└── ca-key.pem # Clé CA si applicable
/etc/ssl/certs/
├── incusPortal.crt # Certificat public (644, root:root)
├── incusPortal.pem # Chaîne complète si nécessaire
└── ca-certificates.crt # Certificats CA système
Configuration Nginx
server {
listen 443 ssl http2;
server_name portal.rougy.net;
ssl_certificate /etc/ssl/certs/incusPortal.crt;
ssl_certificate_key /etc/ssl/private/incusPortal.key;
# Configuration SSL moderne
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256;
ssl_prefer_server_ciphers off;
# HSTS
add_header Strict-Transport-Security "max-age=63072000" always;
location / {
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
Automatisation
Script de renouvellement
#!/bin/bash
# renew-cert.sh
CERT_PATH="/etc/ssl/certs/incusPortal.crt"
KEY_PATH="/etc/ssl/private/incusPortal.key"
CSR_PATH="/tmp/incusPortal.csr"
CONFIG_PATH="/etc/ssl/req.conf"
# Vérification de l'expiration (30 jours)
if openssl x509 -checkend 2592000 -noout -in $CERT_PATH; then
echo "Certificat encore valide"
exit 0
fi
echo "Renouvellement du certificat nécessaire"
# Génération nouveau CSR
openssl req -new -key $KEY_PATH -out $CSR_PATH -config $CONFIG_PATH -batch
# Auto-signature (adapter selon votre CA)
openssl x509 -req -days 365 -in $CSR_PATH -signkey $KEY_PATH -out $CERT_PATH -extensions req_ext -extfile $CONFIG_PATH
# Redémarrage des services
systemctl reload nginx
systemctl restart incus-portal
echo "Certificat renouvelé avec succès"
Tâche cron
# Ajout dans la crontab
0 2 * * 0 /opt/scripts/renew-cert.sh >> /var/log/cert-renewal.log 2>&1
Monitoring
Surveillance de l’expiration
# Script de monitoring
#!/bin/bash
CERT_FILE="/etc/ssl/certs/incusPortal.crt"
ALERT_DAYS=30
EXPIRY_DATE=$(openssl x509 -in $CERT_FILE -noout -enddate | cut -d= -f2)
EXPIRY_TIMESTAMP=$(date -d "$EXPIRY_DATE" +%s)
CURRENT_TIMESTAMP=$(date +%s)
DAYS_LEFT=$(( ($EXPIRY_TIMESTAMP - $CURRENT_TIMESTAMP) / 86400 ))
if [ $DAYS_LEFT -lt $ALERT_DAYS ]; then
echo "ALERTE: Certificat expire dans $DAYS_LEFT jours"
# Envoyer notification (mail, webhook, etc.)
fi
Métriques collectées
- Date d’expiration
- Algorithme de signature
- Longueur de clé
- Domaines couverts (SAN)
- État de validation
Troubleshooting
Erreurs courantes
Erreur de correspondance clé/certificat :
# Vérification des hash
openssl pkey -in private.key -pubout | openssl sha256
openssl x509 -in certificate.crt -pubkey -noout | openssl sha256
Extensions SAN manquantes :
# Vérifier que -extensions req_ext -extfile req.conf sont spécifiés
openssl x509 -in certificate.crt -text -noout | grep -A 3 "Subject Alternative Name"
Problème de format :
# Conversion PEM vers autres formats si nécessaire
openssl x509 -in cert.pem -outform DER -out cert.der
openssl pkcs12 -export -in cert.pem -inkey private.key -out cert.p12
Ressources
Dernière mise à jour : 2 avril 2025