Skip to content

secrets management

Aleksej Komnenovic edited this page Jun 30, 2026 · 3 revisions

Secrets Management

All secrets go through AWS Secrets Manager. KMS encryption is optional.

Secrets Inventory

All secrets are stored in AWS Secrets Manager and referenced by ARN in task definitions, so values are injected at container runtime rather than embedded in the task definition. Secret values ARE written to Terraform state in plaintext, because the modules use the standard secret_string attribute and random_password resources rather than the write-only (secret_string_wo / ephemeral) variants. Protect your state backend accordingly with encryption at rest and restricted access. See Known Issues below.

Secret Created By Purpose Conditional
Database master credentials Database Module Aurora admin login Always (if DB enabled)
S3 access keys Storage Module IAM user credentials storage.auth = "secrets"
BRMS license key User-provided GoRules license Always (BRMS enabled)
Cookie secret ECS Module Session management Always (BRMS enabled)
Secrets master key ECS Module BRMS internal encryption secrets_provider = "env"
AI API key User-provided LLM provider authentication AI enabled (not bedrock)

BRMS Secrets Encryption Provider

BRMS encrypts its internal secrets (stored in the database) using one of two providers:

ENV Provider (default: type = "env")

  • Auto-generates a SECRETS_MASTER_KEY (random, 64 chars by default, min 32)
  • Stored in Secrets Manager
  • BRMS reads it at startup and uses it for AES encryption
  • Simpler setup, key lives in Secrets Manager
brms = {
  secrets_provider = {
    type              = "env"
    master_key_length = 64  # min 32
  }
}

AWS-KMS Provider (type = "aws-kms")

  • Creates (or uses existing) customer-managed KMS key
  • BRMS calls KMS API for encrypt/decrypt operations
  • Better audit trail via CloudTrail
  • Key rotation enabled automatically
brms = {
  secrets_provider = {
    type                = "aws-kms"
    create_kms_key      = true
    kms_key_alias       = "brms-secrets"
    kms_deletion_window = 30  # 7-30 days
  }
}

KMS Resources Created

Resource Purpose
aws_kms_key.brms_secrets Customer-managed encryption key
aws_kms_alias.brms_secrets Optional human-readable alias

KMS access policy attached to BRMS task role, see IAM Architecture.

When type = "aws-kms", the root module also adds a kms interface VPC endpoint so tasks in private subnets can reach the KMS API without a NAT gateway. See VPC Module.

Using Existing KMS Key

brms = {
  secrets_provider = {
    type           = "aws-kms"
    create_kms_key = false
    kms_key_arn    = "arn:aws:kms:us-east-1:123456789012:key/abc-123"
  }
}

How Secrets Reach ECS Tasks

ECS uses the secrets block in container definitions to inject Secrets Manager values as environment variables at runtime:

flowchart LR
    SM[Secrets Manager] --> ExecRole[ECS Task Execution Role] --> Container[Container Environment]
Loading
  1. Task definition references secret ARNs
  2. ECS agent (via execution role) calls secretsmanager:GetSecretValue
  3. Values injected as env vars at container start

The execution role gets a dynamically-built secrets_read policy, see IAM Architecture.

Database Credentials Flow

Secrets Auth (default)

flowchart TD
    A[Aurora master password] -->|stored in Secrets Manager\nby Database module| B[ECS execution role reads at startup]
    B -->|injected as| C[DB_PASSWORD env var]
    C --> D[BRMS connects with username/password]
Loading

IAM Auth

flowchart TD
    A[Lambda creates IAM PostgreSQL user] --> B[BRMS task role has rds-db:connect permission]
    B --> C["BRMS sets DB_CREDENTIALS_PROVIDER=aws-iam"]
    C --> D[BRMS uses IAM temporary credentials\nno password needed]
Loading

See Database Module for the Lambda setup and IAM Architecture for the connect policy.

Storage Credentials Flow

IAM Auth (default)

No credentials needed, S3 access via task role. See IAM Architecture.

Secrets Auth

IAM user with access keys stored in Secrets Manager:

{
  "access_key_id": "AKIA...",
  "secret_access_key": "...",
  "bucket_name": "gorules-prod-rules-abc123",
  "region": "us-east-1"
}

See Storage Module for details.

Known Issues

  • prevent_destroy = false on KMS keys and secrets master keys despite "DO NOT DELETE" comments in the code
  • Secret values are stored in Terraform state in plaintext. The modules use secret_string and random_password, not the write-only secret_string_wo variant, so anyone with read access to terraform.tfstate can read every generated secret. Encrypt the state backend at rest and restrict access.
  • No automatic secret rotation configured

Clone this wiki locally