Federal stack
An illustrative GovCloud stack that turns on customer managed keys, FIPS TLS, container hardening, and 90 day log retention.
examples/federal shows the same kind of app as the full stack example, configured for a federal deployment in AWS GovCloud (us-gov-west-1). It adds one customer managed KMS key for the whole stack and turns on the federal settings of each module.
Illustrative, not deployable as is
This example uses placeholders on purpose. The VPC CIDRs are 10.X.0.0/16, which fail at plan until you claim a real range in the README's CIDR allocation table. The certificate ARN contains ACCOUNT_ID and CERTIFICATE_ID, and the AWS profile and state bucket names are placeholders for your own account. The load balancer is internet facing and the stack has no WAF.
What it builds
| Piece | Federal setting |
|---|---|
aws_kms_key | One customer managed key with rotation on, used by every encrypted resource (SC-13) |
| networking | Flow log group encrypted with the key |
| alb | ssl_policy = "ELBSecurityPolicy-TLS13-1-2-FIPS-2023-04" for FIPS 140-3 TLS |
| ecs-cluster | Fargate capacity providers and ECS Exec logging on |
| ecs-service | Chainguard -fips image, read only root filesystem, UID 65532, all Linux capabilities dropped, encrypted logs kept 90 days (AU-11) |
| rds-postgres | Storage and Performance Insights on the key, log export and DDL audit logging on |
| redis | At rest encryption on the key, slow and engine logs kept 90 days |
| s3-bucket | Logs bucket on the key, TLS only requests (SC-8), bucket owner enforced |
The provider sets use_fips_endpoint = true, and the Terraform state backend encrypts state with a customer managed key alias.
Files
provider.tf # aws ~> 5.0, use_fips_endpoint = true, KMS encrypted S3 state backend
locals.tf # us-gov-west-1, sizes, and the federal map of overrides
main.tf # KMS key, module calls, SSM secrets on the key
outputs.tf # alb_dns, kms_key_arn, rds_host, logs_bucket, vpc_idKey excerpts
All federal overrides live in one map, so a reviewer can see in one place what "federal" means for this stack.
federal = {
# FedRAMP SC-13: customer-managed KMS for data + logs.
kms_key_id = aws_kms_key.this.arn
# FIPS-validated TLS on the ALB listener (FIPS 140-3).
ssl_policy = "ELBSecurityPolicy-TLS13-1-2-FIPS-2023-04"
# Container hardening defaults (Chainguard distroless convention).
container_user = "65532"
readonly_root_filesystem = true
drop_all_capabilities = true
}Each module call then reads from that map.
module "ecs_service" {
source = "git::ssh://git@github.com/the-kaizen-labs/terraform-modules.git//ecs-service?ref=v1.7.0"
# ... networking, image, and load balancer inputs ...
readonly_root_filesystem = local.federal.readonly_root_filesystem
container_user = local.federal.container_user
drop_all_capabilities = local.federal.drop_all_capabilities
log_group_kms_key_arn = local.federal.kms_key_id
log_retention_days = 90
}
module "s3_logs" {
source = "git::ssh://git@github.com/the-kaizen-labs/terraform-modules.git//s3-bucket?ref=v1.7.0"
bucket_name = local.logs_bucket
kms_key_id = local.federal.kms_key_id
enforce_bucket_owner = true
enforce_tls_requests_only = true
}The container image matters as much as the load balancer. The FIPS TLS policy covers traffic that arrives at the load balancer. The app's own outbound TLS, to the database or to third party APIs, uses FIPS validated cryptography only when the image ships it, which is why the example runs a Chainguard -fips image.
Before you adapt it
Claim a /16 for the account in the README's CIDR allocation table and replace every 10.X range.
Replace the certificate ARN, AWS profile, state bucket, lock table, and KMS alias in locals.tf and provider.tf with your account's values.
Store /<app>/db-password and /<app>/redis-auth-token in SSM as SecureString parameters.
Decide whether the load balancer should be internal and whether to add the waf module in front of it.