TL;DR — Résumé Rapide
step-ca transforme n'importe quel serveur en AC privée pour TLS interne, mTLS et certificats SSH. Guide complet installation, provisioners, ACME et production.
step-ca est une autorité de certification privée open source de Smallstep qui vous permet d’exploiter votre propre PKI pour le TLS interne, le mTLS entre microservices et les certificats SSH, sans envoyer de trafic vers une AC publique. Si vous avez déjà eu des difficultés avec Let’s Encrypt sur des domaines privés, des avertissements de certificats auto-signés ou la distribution de la confiance sur des dizaines de services, step-ca résout chacun de ces problèmes avec une conception moderne orientée automatisation. Ce guide couvre le cycle complet : pourquoi vous avez besoin d’une AC privée, l’architecture, l’installation, les provisioners, ACME pour le renouvellement automatique, les certificats SSH et un déploiement HA en production.
Pourquoi une AC Privée ?
Les AC publiques comme Let’s Encrypt exigent la validation du domaine sur l’internet public. Cela exclut immédiatement :
- Noms d’hôtes internes —
postgres.internal,api.corpou tout domaine.local/.corp - mTLS pour les microservices — le mTLS exige que chaque service présente un certificat client ; émettre des milliers de certificats de service de courte durée depuis une AC publique est impraticable et coûteux
- Réseaux à confiance zéro — chaque connexion authentifiée par certificat, pas par position réseau
- Environnements air-gapped — aucun accès à l’internet public
- Service mesh sans sidecars — TLS natif entre services utilisant des certificats step-ca, évitant la surcharge d’un déploiement Istio ou Linkerd complet
step-ca comble ce vide avec un serveur compatible ACME, des durées de vie courtes (24 heures par défaut), des daemons de renouvellement automatique et une intégration de premier plan avec Kubernetes via le webhook autocert et le step-issuer de cert-manager.
Architecture
┌─────────────────────────────────────────────┐
│ serveur step-ca │
│ ┌──────────┐ ┌─────────────┐ │
│ │ AC Racine│→ │AC Intermédiaire │
│ │(hors ligne│ │ │ │
│ └──────────┘ └──────┬──────┘ │
│ │ signe │
│ ┌────────────────────▼──────────────────┐ │
│ │ Provisioners │ │
│ │ JWK │ ACME │ OIDC │ AWS │ K8sSA │… │ │
│ └───────────────────────────────────────┘ │
└─────────────────────────────────────────────┘
↑ API HTTPS (port 9000)
┌────┴────┐
│step CLI │ certbot Caddy Traefik cert-manager
└─────────┘
L’AC racine signe uniquement le certificat de l’AC intermédiaire. En production, conservez la clé racine hors ligne. L’AC intermédiaire est celle avec laquelle step-ca fonctionne au quotidien. Les provisioners sont les mécanismes d’authentification qui contrôlent l’émission des certificats.
Installation
Binaire (Linux/macOS)
# step CLI
wget https://github.com/smallstep/cli/releases/latest/download/step_linux_amd64.tar.gz
tar xzf step_linux_amd64.tar.gz && sudo mv step /usr/local/bin/
# step-ca serveur
wget https://github.com/smallstep/certificates/releases/latest/download/step-ca_linux_amd64.tar.gz
tar xzf step-ca_linux_amd64.tar.gz && sudo mv step-ca /usr/local/bin/
macOS (Homebrew)
brew install step
brew install step-ca
Docker
docker run -v step:/home/step \
-p 9000:9000 \
-e "DOCKER_STEPCA_INIT_NAME=AC Interne" \
-e "DOCKER_STEPCA_INIT_DNS_NAMES=ca.internal,localhost" \
-e "DOCKER_STEPCA_INIT_REMOTE_MANAGEMENT=true" \
smallstep/step-ca
Kubernetes (Helm + autocert)
helm repo add smallstep https://smallstep.github.io/helm-charts
helm install step-certificates smallstep/step-certificates \
--set ca.name="AC Interne" \
--set ca.dns="step-certificates.default.svc.cluster.local"
Configuration Initiale : step ca init
step ca init \
--name "AC Corporative" \
--dns ca.corp.internal \
--address :9000 \
--provisioner admin@corp.internal
Cela crée sous $(step path)/ :
certs/root_ca.crt— certificat AC racine (à distribuer à tous les clients)certs/intermediate_ca.crt— certificat intermédiairesecrets/root_ca_key— clé privée AC racine (à conserver hors ligne)secrets/intermediate_ca_key— clé intermédiaire (utilisée par le serveur)config/ca.json— configuration du serveur
Démarrez le serveur :
step-ca $(step path)/config/ca.json
Pour la production, créez une unité systemd :
[Unit]
Description=Smallstep CA
After=network.target
[Service]
User=step
ExecStart=/usr/local/bin/step-ca /etc/step-ca/config/ca.json
Restart=always
RestartSec=5
Environment=STEPPATH=/etc/step-ca
[Install]
WantedBy=multi-user.target
Provisioners
Les provisioners sont des plugins d’authentification. Ajoutez-en avec :
step ca provisioner add <nom> --type <TYPE>
JWK — Interactif / Basé sur des Scripts
Le provisioner par défaut. Les clients s’authentifient avec un JSON Web Token :
step ca certificate api.internal api.crt api.key
ACME — Automatisé (Caddy, Nginx, certbot)
step ca provisioner add acme --type ACME
Exemple avec certbot :
certbot certonly \
--server https://ca.internal:9000/acme/acme/directory \
--standalone \
-d api.internal \
--agree-tos -m admin@corp.internal
Caddy dans le Caddyfile :
api.internal {
tls {
ca https://ca.internal:9000/acme/acme/directory
}
reverse_proxy localhost:8080
}
OIDC — Basé sur le SSO
step ca provisioner add google --type OIDC \
--client-id <GOOGLE_CLIENT_ID> \
--client-secret <SECRET> \
--configuration-endpoint https://accounts.google.com/.well-known/openid-configuration
Identité d’Instance Cloud (AWS / GCP / Azure)
step ca provisioner add aws --type AWS --aws-account 123456789012
step ca provisioner add gcp --type GCP --gcp-project mon-projet
step ca provisioner add azure --type Azure --azure-tenant <TENANT_ID>
Comptes de Service Kubernetes (K8sSA)
step ca provisioner add k8s --type K8sSA \
--public-key /var/run/secrets/kubernetes.io/serviceaccount/public-key.pub
Émission de Certificats
# ECDSA P-256 (par défaut) avec SANs
step ca certificate api.internal api.crt api.key \
--san api.corp --san 10.0.1.50
# Ed25519
step ca certificate api.internal api.crt api.key --kty OKP --crv Ed25519
# RSA 4096 (compatibilité legacy)
step ca certificate api.internal api.crt api.key --kty RSA --size 4096
# Certificat de courte durée (1 heure)
step ca certificate api.internal api.crt api.key --not-after 1h
Certificats SSH
# Certificat utilisateur SSH
step ssh certificate utilisateur@corp.internal id_ecdsa --provisioner google
# Certificat hôte SSH
step ssh certificate --host api.internal ssh_host_ecdsa_key --provisioner aws
Configurez sshd :
TrustedUserCAKeys /etc/ssh/step_user_ca.pub
HostCertificate /etc/ssh/ssh_host_ecdsa_key-cert.pub
HostKey /etc/ssh/ssh_host_ecdsa_key
Renouvellement et Révocation
Renouvellement Automatique (—daemon)
step ca renew --daemon api.crt api.key
Dans un service systemd :
ExecStartPost=/usr/local/bin/step ca renew --daemon \
/etc/tls/service.crt /etc/tls/service.key \
--exec "systemctl reload mon-service"
Révocation
Révocation passive — la courte durée de vie des certificats rend la révocation implicite.
Révocation active :
step ca revoke --serial 1234567890abcdef
Backends de Base de Données et Haute Disponibilité
| Backend | Par défaut | HA | Cas d’usage |
|---|---|---|---|
| Badger | Oui | Non | Instance unique, dev/petites équipes |
| PostgreSQL | Non | Oui | Production multi-répliques |
| MySQL | Non | Oui | Production multi-répliques |
"db": {
"type": "postgresql",
"dataSource": "postgresql://stepca:password@pg.internal:5432/stepca?sslmode=require"
}
Comparaison : Options d’AC Privée
| Outil | Serveur ACME | Certs SSH | Provisioners | HA | Facilité | Licence |
|---|---|---|---|---|---|---|
| step-ca | Oui (intégré) | Oui | 8 types | Oui (BD ext.) | Haute | Apache 2 |
| CFSSL | Non | Non | Aucun | Oui | Moyenne | BSD |
| Vault PKI | Via plugin | Via Vault SSH | Via Vault auth | Oui (Raft) | Faible | BSL |
| EJBCA | Oui | Non | Nombreux | Oui | Très faible | LGPL / EE |
| Let’s Encrypt | Oui (public) | Non | ACME seulement | N/A | Très haute | N/A |
| mkcert | Non | Non | Aucun | Non | Très haute | MIT |
Pièges et Cas Particuliers
Décalage d’horloge — step-ca rejette les CSR si l’horloge du client diffère de plus de quelques minutes. Assurez-vous que NTP est actif sur tous les nœuds.
Protection de la clé AC racine — après step ca init, déplacez root_ca_key hors ligne. La clé intermédiaire est tout ce dont step-ca a besoin pour fonctionner.
ACME et SANs d’adresse IP — les challenges ACME HTTP-01 et DNS-01 fonctionnent pour les noms de domaine. Pour les SANs d’adresse IP, utilisez directement le step CLI.
Transparence des certificats — contrairement aux AC publiques, step-ca ne soumet pas les certificats aux journaux CT. C’est souhaitable pour l’infrastructure interne.
Gestion des mots de passe de provisioner — stockez les mots de passe dans un gestionnaire de secrets. Ne les codez jamais en dur dans les scripts.
Résumé
- step-ca exécute une PKI privée complète : AC racine, AC intermédiaire et API REST pour l’émission de certificats
- Utilisez des certificats de courte durée (24h par défaut) et le renouvellement avec
--daemonplutôt que CRL/OCSP - Le provisioner ACME fait de step-ca une AC interne compatible avec Caddy, Nginx, Traefik et certbot
- Les provisioners cloud (AWS, GCP, Azure) permettent le bootstrap d’identité workload sans secrets partagés
- K8sSA et l’intégration cert-manager automatisent le TLS par pod dans Kubernetes sans sidecars
- Les certificats SSH de step-ca éliminent la gestion individuelle de known_hosts par serveur
- Pour la HA, passez le backend à PostgreSQL et exécutez plusieurs répliques derrière un répartiteur de charge
- Conservez la clé AC racine hors ligne ; faites pivoter la clé intermédiaire indépendamment si compromise