How to Move a Plaintext Secret to AWS Secrets Manager

An env var like DB_PASSWORD shows up in your deployment manifest, every container layer, and docker inspect output - all potential leak surfaces. AWS Secrets Manager keeps the secret out of all of those. Here's how to refactor the fetch.

Security Engineerawssecretsmanagersecrets

Why env vars are the wrong place for secrets

When you write DB_PASSWORD=supersecret in a Kubernetes manifest or a docker run -e command, that value is now in:

AWS Secrets Manager centralizes secrets, scopes access via IAM, and supports rotation. The app fetches the secret at boot - the plaintext never lives in a deployment config.

The refactor

Replace the env-var read with a boto3 call:

import os
import boto3

def load_password() -> str:
    sm = boto3.client(
        "secretsmanager",
        endpoint_url=os.environ.get("AWS_ENDPOINT_URL"),  # moto in dev
        region_name=os.environ.get("AWS_DEFAULT_REGION", "us-east-1"),
    )
    return sm.get_secret_value(SecretId="app/db/password")["SecretString"]

Call load_password() once at startup and cache the result - not on every request. The endpoint_url parameter lets you point at a local mock (moto) during development and real AWS in production without changing the code.

Create the secret (one-time setup)

aws secretsmanager create-secret \
    --name app/db/password \
    --secret-string "supersecret"

Verify it was stored correctly:

aws secretsmanager get-secret-value --secret-id app/db/password

IAM policy (least privilege)

The pod's IAM role should grant GetSecretValue on the specific secret ARN only - not a wildcard over all secrets in the account:

{
  "Effect": "Allow",
  "Action": "secretsmanager:GetSecretValue",
  "Resource": "arn:aws:secretsmanager:us-east-1:123456789012:secret:app/db/password-*"
}

Caching and rotation

Fetch once at boot and cache in a module-level variable. For long-running services, refresh periodically (every few minutes) so the app picks up rotated secrets without a redeploy:

import time

_cached_password = None
_fetched_at = 0
TTL = 300  # 5 minutes

def get_password() -> str:
    global _cached_password, _fetched_at
    if time.time() - _fetched_at > TTL:
        _cached_password = load_password()
        _fetched_at = time.time()
    return _cached_password

Storing structured secrets

Secrets Manager supports JSON strings, which lets you store multiple fields under one secret:

aws secretsmanager create-secret \
    --name app/db \
    --secret-string '{"host":"db.internal","port":5432,"password":"supersecret"}'

Parse it with json.loads(value) after fetching.

Want to try it hands-on? HeyDevJob gives you this exact setup in a live cloud workspace in your browser - edit it, run it, and see it work. Free, nothing to install.

Try it in a workspace →

What you'll practice

FAQ

Why is storing a DB password in an environment variable a security risk?

Env vars appear in deployment manifests, docker inspect output, CI logs, and crash dumps - any of these can leak the plaintext secret. AWS Secrets Manager keeps the secret out of all of those and scopes access via IAM.

How do I fetch a secret from AWS Secrets Manager in Python?

Use boto3: boto3.client('secretsmanager').get_secret_value(SecretId='app/db/password')['SecretString']. Fetch once at startup and cache it - do not call this on every request.

How do I test AWS Secrets Manager locally without a real AWS account?

Use moto, a Python library that mocks AWS APIs locally. Set AWS_ENDPOINT_URL=http://localhost:5000 and pass it as endpoint_url to boto3.client - the same code works against real AWS in production.

What is AWS Secrets Manager?

AWS Secrets Manager stores secrets like database passwords and API keys, encrypts them with KMS, controls access with IAM, and can rotate them automatically. Apps fetch the secret at runtime instead of hardcoding it.

What is the difference between AWS KMS and Secrets Manager?

KMS manages encryption keys and performs encrypt/decrypt; Secrets Manager stores the actual secret values and uses KMS to encrypt them. Use KMS for keys, Secrets Manager for the secrets themselves.

Keep learning

Close a SQL Injection in a Search EndpointSecurity projectNeutralize a Stored XSS in CommentsSecurity projectRemove Hardcoded Credentials From Source CodeSecurity projectSecurity roadmapStep by step to hiredSecurity interview questionsSTAR answersAll Security projectsProjects hub

Learn it by doing. Open this in a live cloud workspace, make the change yourself, and keep a record of the work you can share.

Open the workspace →