Certificats X.509

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

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

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

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