-
Notifications
You must be signed in to change notification settings - Fork 0
secrets management
All secrets go through AWS Secrets Manager. KMS encryption is optional.
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 encrypts its internal secrets (stored in the database) using one of two providers:
- 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
}
}- 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
}
}| 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.
brms = {
secrets_provider = {
type = "aws-kms"
create_kms_key = false
kms_key_arn = "arn:aws:kms:us-east-1:123456789012:key/abc-123"
}
}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]
- Task definition references secret ARNs
- ECS agent (via execution role) calls
secretsmanager:GetSecretValue - Values injected as env vars at container start
The execution role gets a dynamically-built secrets_read policy, see IAM Architecture.
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]
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]
See Database Module for the Lambda setup and IAM Architecture for the connect policy.
No credentials needed, S3 access via task role. See IAM Architecture.
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.
-
prevent_destroy = falseon 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_stringandrandom_password, not the write-onlysecret_string_wovariant, so anyone with read access toterraform.tfstatecan read every generated secret. Encrypt the state backend at rest and restrict access. - No automatic secret rotation configured