← retour aux snippets

openssl: certificat local pour data.pm.local

Générer un certificat TLS auto-signé (SAN) pour data.pm.local et tester en local.

bash sécurité #openssl#tls#cert#local

objectif

Créer un certificat et une clé pour data.pm.local avec SubjectAltName, puis tester un serveur local en HTTPS.

code minimal

# génère une clé et un certificat auto-signé pour data.pm.local (SAN)
cat > openssl-data.pm.local.cnf <<'EOF'
[ req ]
default_bits       = 2048
prompt             = no
default_md         = sha256
req_extensions     = req_ext
distinguished_name = dn

[ dn ]
CN = data.pm.local
O  = Dev
C  = FR

[ req_ext ]
subjectAltName = @alt_names

[ alt_names ]
DNS.1 = data.pm.local
DNS.2 = data.pm.local
EOF

openssl req -x509 -nodes -newkey rsa:2048 -days 365 \
  -keyout data.pm.local.key -out data.pm.local.crt \
  -config openssl-data.pm.local.cnf -extensions req_ext

utilisation

# lier data.pm.local à 127.0.0.1 si besoin
grep -q 'data.pm.local' /etc/hosts || echo "127.0.0.1 data.pm.local data.pm.local" | sudo tee -a /etc/hosts >/dev/null

# tester avec un serveur HTTPS simple (openssl s_server)
openssl s_server -quiet -accept 8443 -cert data.pm.local.crt -key data.pm.local.key -www &
pid=$!
sleep 1

# vérifier l'accès (cert auto-signé: -k pour ignorer la validation en local)
curl -k -sS https://data.pm.local:8443/ | head -n 3

# arrêter le serveur de test
kill -TERM "$pid" 2>/dev/null || true

variante(s) utile(s)

# ajouter d'autres SAN (ex: api.data.pm.local)
# éditez openssl-data.pm.local.cnf et ajoutez:
# DNS.3 = api.data.pm.local
# puis regénérez la paire

# version ECDSA (clé plus compacte)
openssl ecparam -name prime256v1 -genkey -noout -out data.pm.local.ec.key
openssl req -x509 -new -key data.pm.local.ec.key -days 365 \
  -subj "/CN=data.pm.local/O=Dev/C=FR" \
  -addext "subjectAltName=DNS:data.pm.local,DNS:data.pm.local" \
  -out data.pm.local.ec.crt

# utiliser le cert local avec un serveur python (requires Python 3.7+)
python3 - <<'PY'
import http.server, ssl, socketserver
PORT=8443
h=http.server.SimpleHTTPRequestHandler
with socketserver.TCPServer(("127.0.0.1", PORT), h) as httpd:
    httpd.socket = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER).wrap_socket(
        httpd.socket, server_side=True,
        certfile="data.pm.local.crt", keyfile="data.pm.local.key"
    )
    print(f"https://data.pm.local:{PORT}/")
    httpd.serve_forever()
PY

# tester le SNI vers data.pm (si résout localement)
openssl s_client -servername data.pm.local -connect data.pm.local:8443 < /dev/null 2>/dev/null \
  | openssl x509 -noout -subject -ext subjectAltName

notes

  • les navigateurs refuseront un cert auto-signé; pour un usage navigateur, créez une CA locale et installez-la ou utilisez un outil comme mkcert.
  • ajoutez toutes les variantes nécessaires dans subjectAltName.
  • ne jamais utiliser ces certificats en production; réservez-les aux environnements de dev locaux.