Database passwords, API keys, TLS certificates, and service tokens are secrets that grant access to sensitive systems. This article covers the architecture, rotation lifecycle, and best practices for managing secrets in cloud environments.
Sign in to mark this article as read and track your progress.
A secret is any credential that grants access: a database password, an API key, a TLS private key, an OAuth client secret, or an SSH private key. Secrets are fundamentally different from other configuration data:
The 2023 GitHub Secret Scanning report found 1.3 million secrets exposed in public repositories during the year. Most were AWS access keys, database credentials, and Google API tokens.
Before discussing proper secrets management, identify what to avoid:
| Anti-Pattern | Risk | Example |
|---|---|---|
| Hardcoded secrets | Leaked in git history; visible to anyone with repo access | const DB_PASS = "MyProd2024Pass" in source code |
| Environment variables | Visible in process list, CloudWatch Logs, crash dumps | DATABASE_URL=postgres://user:pass@host/db in .env |
| SSM Parameter Store plain text | No encryption at rest; no audit of access | Storing credentials as /app/prod/db_pass (not SecureString) |
AWS Secrets Manager is the recommended managed secrets store for production AWS workloads. It provides:
| Feature | Details |
|---|---|
| Encryption | All secrets encrypted using KMS (customer-managed or AWS-managed key) |
| Rotation | Built-in rotation for RDS, Redshift, DocumentDB, and custom Lambda-based rotation |
| Access control | IAM resource-based policy on the secret; condition keys for VPC, MFA |
| Audit trail | CloudTrail records every GetSecretValue, RotateSecret, DeleteSecret call |
| Cross-account | Secrets can be shared with other AWS accounts via resource policy |
| Cost | USD 0.40/secret/month + USD 0.05 per 10,000 API calls |
AWS Secrets Manager rotation for RDS works as follows:
Day 0: Secret created with current DB password
↓
Day 30: Rotation Lambda triggered automatically
↓
Lambda Step 1 (createSecret): Generate new random password in pending stage
↓
Lambda Step 2 (setSecret): Change RDS user password to new value
↓
Lambda Step 3 (testSecret): Attempt DB connection using new password
↓
Lambda Step 4 (finishSecret): Promote new password to current stage; demote old to previous
↓
Day 30+: Applications calling GetSecretValue automatically get new password
Applications using the AWS SDK for Secrets Manager automatically get the latest version — no restart required. The Secrets Manager SDK caches secrets locally (for 5 minutes by default) to reduce API call cost.
SSM Parameter Store is the lower-cost alternative for non-rotating secrets and configuration values:
| Tier | Type | Use Case |
|---|---|---|
| Standard | String | Public configuration (region names, feature flags) |
| Standard | SecureString | Low-sensitivity secrets (KMS-encrypted with aws/ssm key) |
| Advanced | SecureString | High-sensitivity secrets with larger size limit and parameter policies |
Parameter Store is integrated with many AWS services: ECS Task Definitions can pull parameters at launch; Lambda can load them at cold-start; EC2 instances can use AWS Systems Manager Agent to pull them at boot.
Cost: Standard Parameters are free for up to 10,000 parameters. SecureString Standard is free; SecureString Advanced is USD 0.05/parameter/month.
Secrets Manager vs Parameter Store — when to use which:
| Criterion | Secrets Manager | SSM Parameter Store (SecureString) |
|---|---|---|
| Automatic rotation | Yes (built-in Lambda rotation) | No (manual or custom automation) |
| Cross-account sharing | Yes (resource policy) | No |
| Secret size | Up to 64KB | Up to 8KB |
| Cost | USD 0.40/secret/month | Free (Standard) |
| Audit trail | CloudTrail | CloudTrail |
| Best for | Database credentials, API keys that rotate | Config values, non-rotating tokens |
HashiCorp Vault is an open-source secrets management platform that runs independently of any cloud provider, making it the standard choice for multi-cloud environments (AWS + Azure + GCP workloads managed centrally).
Key Vault features:
# Vault AWS Secrets Engine: generate a short-lived IAM access key
vault read aws/creds/my-role
# Output:
# access_key AKIAIOSFODNN7EXAMPLE
# secret_key wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
# lease_duration 768h ← configurable TTL
# lease_id aws/creds/my-role/abc123
# renewable true
The generated IAM credentials are automatically revoked by Vault when the lease expires. If the lease ID is revoked early (vault lease revoke aws/creds/my-role/abc123), the IAM access key is immediately deleted from AWS.
For containerised workloads on Kubernetes, the External Secrets Operator (ESO) synchronises secrets from Secrets Manager, Vault, or Azure Key Vault into Kubernetes Secrets — without embedding secrets in deployment manifests.
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: db-password
spec:
refreshInterval: 1h
secretStoreRef:
name: aws-secrets-manager
kind: SecretStore
target:
name: db-password
data:
- secretKey: password
remoteRef:
key: /prod/myapp/db_password
This creates a Kubernetes Secret named db-password that is automatically refreshed every hour from AWS Secrets Manager. Developers never see the secret value; pods mount it as an environment variable or file.