Une équipe plateforme qui se standardise sur AWS en 2026 trie 300 secrets entre staging et production — mots de passe de bases, clés API tierces, clés de signature JWT, jetons internes service-à-service, secrets clients OAuth, secrets de signature de webhooks. L’état courant est un mélange de fichiers .env, de Kubernetes secrets, et d’un HashiCorp Vault à moitié cassé que quelqu’un a installé il y a deux ans et que personne ne maintient. AWS a deux services qui résolvent le problème — Secrets Manager et SSM Parameter Store — et l’équipe a sans cesse le même débat : Parameter Store est gratuit, donc pourquoi payer Secrets Manager. La réponse, c’est que les deux services ne sont pas interchangeables. La décision est par secret, et le mauvais appel revient soit à gaspiller de l’argent sur Secrets Manager pour des choses qui ne tournent pas, soit à perdre la rotation sur des choses qui devraient tourner.
Ce qui se passe
Secrets Manager et Parameter Store permettent tous deux à une application de récupérer un secret au runtime via un appel d’API authentifié IAM, tous deux chiffrent au repos avec KMS, tous deux journalisent les accès via CloudTrail. Les différences qui comptent vraiment :
| Dimension | Secrets Manager | Parameter Store (SecureString) |
|---|---|---|
| Modèle de coût | Par secret par mois + par appel API | Gratuit en standard tier ; advanced tier (>4Ko ou haut débit) facturé |
| Rotation native | Oui — Lambda pour RDS, Aurora, Redshift, DocumentDB, générique | Pas de rotation native |
| Hiérarchie | Nommage plat avec / autorisé (pas de vraie sémantique de chemin) | Vrais chemins hiérarchiques avec GetParametersByPath |
| Partage inter-comptes | Oui — politiques de ressources sur le secret | Oui pour advanced tier ; via référence ARN de paramètre |
| Taille max de la valeur | 64 Ko | 4 Ko (standard) / 8 Ko (advanced) |
| Réplication | Réplication inter-régions intégrée | Pas de réplication native |
| Versioning | Oui — IDs de version + labels (AWSCURRENT/AWSPENDING) | Oui — numéros de version séquentiels |
| SDK de cache | AWS fournit une bibliothèque de cache côté client | Pas de cache officiel — à implémenter vous-même |
La règle qui clôt le débat : si le secret doit tourner (identifiants de base de données, clés API tierces avec politique de rotation, tout ce qui est réglementé), Secrets Manager. S’il ne tourne pas (feature flags, configuration interne, secrets clients OAuth qui changent une fois par an à la main), Parameter Store SecureString. Le coût mensuel par secret sur Secrets Manager est modeste, mais il s’accumule vite sur des centaines de valeurs qui n’avaient pas besoin de rotation. Inversement, construire la rotation par Lambda au-dessus de Parameter Store est un projet ; Secrets Manager l’a en case à cocher pour RDS.
Un point subtil : la réplication inter-régions. Si la charge est multi-régions active-active, répliquer les secrets Secrets Manager vers la seconde région est intégré. Avec Parameter Store, le secret doit être dupliqué par votre propre outillage (Terraform, CDK, une étape CI) et les deux copies peuvent dériver. Pour les charges multi-régions, cela pousse les identifiants de base de données vers Secrets Manager indépendamment de la cadence de rotation.
Comment vérifier
La passe de classification — pour l’inventaire de 300 secrets :
# tout dans Parameter Store sous /prod
aws ssm get-parameters-by-path \
--path /prod/ \
--recursive \
--with-decryption \
--query 'Parameters[].[Name,Type,LastModifiedDate]' \
--output table
# chaque secret Secrets Manager, avec drapeau de rotation
aws secretsmanager list-secrets \
--query 'SecretList[].[Name,RotationEnabled,LastRotatedDate,LastChangedDate]' \
--output table
Deux patrons à repérer :
- Entrées Parameter Store où
LastModifiedDateest à plus de 365 jours et le paramètre est un mot de passe de base. Ce secret n’a pas tourné depuis un an. Sa place est dans Secrets Manager avec rotation activée. - Secrets dans Secrets Manager où
RotationEnabledestfalseetLastChangedDateest vieux de plusieurs années. Vous payez la charge mensuelle par secret pour une valeur qui aurait pu vivre gratuitement dans Parameter Store SecureString.
Pour le découpage de la politique IAM, lister chaque rôle qui touche à un secret :
aws cloudtrail lookup-events \
--lookup-attributes AttributeKey=EventName,AttributeValue=GetSecretValue \
--start-time $(date -u -v-30d +%Y-%m-%dT%H:%M:%S) \
--query 'Events[].Username' \
--output text | sort -u
Si un rôle lit des secrets qui appartiennent à une autre équipe (le rôle de l’app web lit le mot de passe de la base d’analytique), la politique IAM est trop large. Chaque rôle ne doit lire que les secrets dont sa charge est propriétaire.
La correction
La règle de classification que nous appliquons sur chaque mission de nettoyage de secrets :
Utiliser Secrets Manager quand :
- Le secret tourne (ou devrait). Mots de passe RDS, Aurora, Redshift, DocumentDB sont le cas canonique — Lambda de rotation natif, aucun code à écrire.
- Le secret est répliqué inter-régions. Bascule multi-régions avec une seule copie gérée de l’identifiant.
- Le secret est partagé entre comptes via les politiques de ressources. Secret centralisé dans le compte sécurité, autorisation IAM accordée à des rôles spécifiques dans les comptes de charge.
- La taille compte — valeurs au-delà de 4 Ko (clés privées multilignes, chaînes de certificats volumineuses).
Utiliser Parameter Store quand :
- La valeur ne tourne pas — configuration interne, IDs clients OAuth (l’ID, pas le secret), feature flags, URLs publiques.
- L’organisation hiérarchique compte. Parameter Store a une vraie sémantique de chemin —
aws ssm get-parameters-by-path --path /prod/app/ --recursiveretourne l’arbre entier en un appel. Secrets Manager non. - La valeur est référencée depuis CloudFormation/CDK au déploiement comme paramètre SSM — intégration de première classe avec CFN.
Le piège « la rotation casse l’application » est celui qui mord les équipes nouvelles à Secrets Manager. Lorsque la rotation s’exécute, Secrets Manager crée une nouvelle version du mot de passe sous le label AWSPENDING, appelle la Lambda de rotation pour appliquer le nouveau mot de passe à la base, et seulement ensuite promeut AWSPENDING à AWSCURRENT. Une application qui récupère le secret une fois au démarrage et le cache pour toujours ne voit pas le mot de passe tourné avant un redémarrage. Le pool de connexions reçoit des erreurs Authentication failed quelques heures après la rotation, et l’astreinte est perplexe parce que le secret dans la console a l’air correct — AWSCURRENT est bien le nouveau mot de passe, mais l’app utilise encore la valeur mise en cache avant rotation.
Le correctif est le TTL du cache. Les bibliothèques de cache fournies par AWS (aws-secretsmanager-caching-java, aws-secretsmanager-caching-python) rafraîchissent sur TTL configurable — 15 minutes est un défaut raisonnable. L’application reçoit le nouveau mot de passe dans les 15 minutes suivant la rotation, sans redémarrer. Sans cache, chaque connexion à la base coûte un appel GetSecretValue. Sans TTL sur le cache, la rotation casse l’app.
Le découpage de la politique IAM est le second morceau. Le principe du moindre privilège est violé par défaut si un rôle a secretsmanager:GetSecretValue sur Resource: "*". La bonne politique se lit :
{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Action": ["secretsmanager:GetSecretValue"],
"Resource": [
"arn:aws:secretsmanager:us-east-1:123456789012:secret:prod/app-x/db-*",
"arn:aws:secretsmanager:us-east-1:123456789012:secret:prod/app-x/api-keys-*"
]
}]
}
Le * final sur l’ARN de ressource correspond au suffixe que Secrets Manager ajoute à chaque nom de secret. Le préfixe de chemin (prod/app-x/) signifie que le rôle ne peut lire que les secrets de sa propre application. Les secrets inter-équipes nécessitent leur propre autorisation IAM.
Pour Parameter Store, même patron, avec ssm:GetParameter et ssm:GetParametersByPath. La permission KMS Decrypt est distincte — si SecureString utilise une CMK gérée par le client, le rôle a aussi besoin de kms:Decrypt sur l’ARN de la clé, scopée via la condition kms:EncryptionContext:PARAMETER_ARN.
Trois règles sur chaque mission de nettoyage de secrets :
Classifier avant de migrer. Un tableur avec chaque secret, son emplacement actuel, sa cadence de rotation, son service cible. La migration est mécanique une fois la matrice remplie.
Cacher avec un TTL, jamais cacher pour toujours. Le piège de la rotation est la plus grosse cause d’incidents post-migration.
ARN de ressource dans la politique IAM, pas wildcard. La permission d’un rôle à lire les secrets doit lister les préfixes de chemin exacts qu’il possède. Le rayon de souffle d’un rôle compromis chute drastiquement quand la politique IAM est précise.
La migration sur un inventaire de 300 secrets tient en une semaine concentrée — l’essentiel est le tableur de classification, pas les appels d’API. Bien faite, l’équipe a la rotation sur les identifiants qui en ont besoin et zéro coût récurrent sur ceux qui n’en ont pas besoin.
Stack Harbor opère le nettoyage IAM, la baseline CloudWatch, AWS Backup et le rythme de contrôle des coûts dans le cadre de Gestion AWS et des Environnements infogérés en continu. Si votre hygiène de secrets est un dossier de fichiers .env et un Vault que personne ne maintient, commencez par une consultation d’infrastructure.