Skip to main content

Environment Variable Contract: Audit Log Backend

Variables

VariableRequiredDefaultValid valuesDescription
AUDIT_LOG_BACKENDNomongodbmongodb, local, s3Selects the active audit storage backend
AUDIT_LOG_LOCAL_PATHWhen AUDIT_LOG_BACKEND=local./audit-logsAny writable pathRoot directory for NDJSON audit files
AUDIT_LOG_S3_BUCKETWhen AUDIT_LOG_BACKEND=s3Valid S3 bucket nameTarget S3 bucket
AUDIT_LOG_S3_PREFIXWhen AUDIT_LOG_BACKEND=s3auditString (no leading /)S3 key prefix
AUDIT_LOG_S3_REGIONWhen AUDIT_LOG_BACKEND=s3us-east-1AWS region stringS3 region
AUDIT_LOG_S3_ENDPOINT_URLNoURLCustom endpoint (MinIO, GCS)

Credential variables (S3 backend only)

Standard AWS credential chain is used. No new variables introduced by this feature. Priority order (highest first):

MethodVariables / mechanismNotes
Static keysAWS_ACCESS_KEY_ID + AWS_SECRET_ACCESS_KEY (+ optional AWS_SESSION_TOKEN)Dev / CI only
IRSA (EKS)AWS_ROLE_ARN + AWS_WEB_IDENTITY_TOKEN_FILE — injected automatically by the EKS pod identity webhookPreferred for production
EC2 instance profileIMDSv2 (no env vars needed)EC2-based deployments
ECS task roleAWS_CONTAINER_CREDENTIALS_RELATIVE_URI — injected automaticallyECS deployments

IRSA setup (EKS)

Both boto3 and @aws-sdk/client-s3 pick up AWS_ROLE_ARN + AWS_WEB_IDENTITY_TOKEN_FILE automatically — no code change needed. To wire up IRSA via Helm:

# values.yaml
serviceAccount:
create: true
annotations:
eks.amazonaws.com/role-arn: "arn:aws:iam::<ACCOUNT_ID>:role/<ROLE_NAME>"

The IAM role needs the following minimum policy on the audit bucket:

{
"Effect": "Allow",
"Action": ["s3:PutObject"],
"Resource": "arn:aws:s3:::<AUDIT_BUCKET>/<AUDIT_PREFIX>/*"
}

The IRSA webhook injects AWS_ROLE_ARN and AWS_WEB_IDENTITY_TOKEN_FILE into the pod automatically — no manual env var configuration needed in the deployment.

Startup validation

At process startup, the factory:

  1. Reads AUDIT_LOG_BACKEND (default mongodb)
  2. For local: logs [audit] backend=local path=<path>
  3. For s3: logs [audit] backend=s3 bucket=<bucket> prefix=<prefix> (never logs credentials)
  4. For unknown value: raises ValueError (Python) / throws Error (TypeScript) — fail-fast, no silent fallback