DEV Community

Yash
Yash

Posted on

Secrets management in AWS: the right architecture at each scale

Secrets management in AWS: the right architecture at each scale

Most teams start with environment variables. By year two, it's a liability.

Stage 2: AWS Secrets Manager (prod-ready)

resource "aws_secretsmanager_secret" "db" {
  name = "/${var.env}/${var.project}/database/password"
  recovery_window_in_days = 7
}
resource "aws_secretsmanager_secret_rotation" "db" {
  secret_id = aws_secretsmanager_secret.db.id
  rotation_lambda_arn = aws_lambda_function.rotation.arn
  rotation_rules { automatically_after_days = 30 }
}
Enter fullscreen mode Exit fullscreen mode

Read at runtime (not deploy time):

import boto3, json

def get_secret(name: str) -> dict:
    return json.loads(
        boto3.client("secretsmanager").get_secret_value(SecretId=name)["SecretString"]
    )

db = get_secret("/prod/payment-api/database/password")
Enter fullscreen mode Exit fullscreen mode

IAM policy (least privilege):

resource "aws_iam_role_policy" "read_secrets" {
  role = aws_iam_role.app.id
  policy = jsonencode({ Statement = [{
    Effect = "Allow"
    Action = ["secretsmanager:GetSecretValue"]
    Resource = ["arn:aws:secretsmanager:*:*:secret:/${var.env}/${var.project}/*"]
  }]})
}
Enter fullscreen mode Exit fullscreen mode

Parameter Store vs Secrets Manager

Parameter Store: non-sensitive config — FREE (standard tier)
Secrets Manager: actual secrets — ~$0.40/secret/month + auto-rotation
Enter fullscreen mode Exit fullscreen mode

Most common mistakes

  1. Fetching secrets at container start (not runtime) — rotation doesn't take effect until restart
  2. secretsmanager:* instead of GetSecretValue only — over-permissioned
  3. No resource-based policy for cross-account access
  4. Not using KMS CMK

Step2Dev creates the Secrets Manager namespace and wires task IAM policies for every project.

👉 step2dev.com

What secrets management issue has caused you the most pain?

Top comments (0)