Sign in
Menu
Sign up
Docs
Adopt in an existing estateCompliance starter kits

B2B SaaS - SOC 2

For a B2B SaaS team heading toward a SOC 2 Type I or Type II report. The kit deploys the infrastructure layer the auditor asks about, from the soc2.compliance.tf registry host: encrypted data stores, private subnets, HTTPS-only endpoints, access logging and Multi-AZ databases. When you finish, the stack is applied and every SOC 2 control its modules enforce has passed terraform plan.

Repository: compliancetf/starter-kit-saas-soc2 · About 107 resources

Before you start

  • The shared prerequisites on Compliance starter kits: an account whose plan includes SOC 2, Terraform at a version every module accepts, AWS credentials, a Route 53 hosted zone, the replication role and destination bucket, and account-level CloudTrail.
  • The replication pair supports the SOC 2 A1.2 availability criterion; the kit's data and logs buckets replicate to it.

Deploy

git clone https://github.com/compliancetf/starter-kit-saas-soc2.git
cd starter-kit-saas-soc2

cp terraform.tfvars.example terraform.tfvars
# Set project_name, domain_name, route53_zone_id, availability_zones,
# s3_replication_role_arn and s3_replication_destination_bucket_arn

terraform login soc2.compliance.tf

terraform init
terraform plan
terraform apply

If a value in terraform.tfvars breaks a SOC 2 control, terraform plan fails with an error that names the control and the module. Fix the value and plan again.

What it deploys

SOC 2 SaaS infrastructure architecture

A public ALB with WAF in front of a private EKS cluster, an Aurora PostgreSQL database in dedicated database subnets, and shared services: S3, DynamoDB, ElastiCache and SQS. VPC flow logs and CloudWatch log groups support CC7.1.

ModuleVersionPurposeSOC 2 criteria
vpc~> 6.0Network isolation, flow logs, database subnetsCC6.1, CC7.1
alb~> 10.0HTTPS load balancing, access logsCC6.6, CC6.7
waf~> 1.0Web Application Firewall (OWASP Top 10, IP reputation)CC6.6
acm~> 6.0TLS certificate (DNS-validated)CC6.7
kms~> 4.0Customer-managed key for EKS log encryptionCC6.1
eks~> 21.0Kubernetes cluster, private subnets, KMS-encrypted logsCC6.1, CC7.1
rds_aurora~> 10.0Aurora PostgreSQL, Multi-AZ, encrypted, IAM authCC6.1, A1.2
s3_bucket_data~> 5.0Application data, cross-region replicationCC6.1, CC7.2, A1.2
s3_bucket_logs~> 5.0Centralized access logs (ALB + S3), cross-region replicationCC7.1, CC8.1, A1.2
dynamodb~> 5.0Key-value store, point-in-time recoveryCC6.1, A1.2
elasticache~> 1.0Redis, encrypted at rest and in transit, auth, failoverCC6.1, A1.2
sqs~> 5.0Message queue, dead-letter queueCC6.1, CC7.2
cloudwatch~> 5.0Application log groupCC7.1, CC7.2

Control coverage

SOC 2 criterionDescriptionModulesWhat the kit configures
CC6.1Logical access securityKMS, RDS Aurora, S3, EKS, ElastiCache, DynamoDB, SQSEncryption at rest (customer-managed key for EKS logs), no public access, IAM authentication
CC6.6Logical access security measures against threats from outside system boundariesALB, WAFTLS 1.2+ (TLS 1.3 policy), HTTPS-only, WAF with OWASP Top 10 and IP reputation rules
CC6.7Restriction of data transmission to authorized users and processesALB, ElastiCacheHTTPS-only listeners, transit encryption enabled
CC7.1Detection of configuration changes that introduce vulnerabilities and susceptibilities to newly discovered vulnerabilitiesVPC, ALB, RDS Aurora, CloudWatch, S3 (logs)VPC flow logs, ALB access logs, PostgreSQL log exports, CloudWatch log groups
CC7.2Monitoring of system components and controls on an ongoing basis to detect anomalies indicating malicious acts or errorsS3, SQS, CloudWatchS3 versioning, dead-letter queues, log retention policies
CC8.1Change management controlsAll modulesInfrastructure changes tracked in Terraform state and version control, deletion protection (prod)
A1.2Data backup processes, recovery infrastructure, and environmental protectionsRDS Aurora, ElastiCache, S3 (data + logs)Multi-AZ deployment, automatic failover, automated backups (7-14 days), S3 cross-region replication

Settings that a module enforces as a control fail the plan if you change them. The rest are kit defaults you can change. The SOC 2 framework page lists the controls modules enforce and the mapped-only controls that stay with your team.

What you own

The kit configures the infrastructure settings above. These stay with you:

  • Application-level authentication, authorization and session management
  • Identity provider configuration and MFA enforcement
  • HR policies: background checks, security awareness training
  • Vendor management and third-party risk assessments
  • Incident response procedures and runbooks
  • Business continuity planning
  • Access reviews and user lifecycle management
  • Application-level audit logging for business events

The auditor still tests the infrastructure controls, such as Aurora encryption and S3 public access blocking, against your evidence, and assesses the organizational controls above separately. Audit evidence lists what compliance.tf gives them.

Vanta and Drata checks

Compliance.tf has no Vanta or Drata integration. These checks, which both platforms run against your AWS account, look at settings the kit configures:

Platform checkSOC 2 criterionWhat the kit sets
Encryption at rest (databases)CC6.1RDS Aurora, DynamoDB, ElastiCache, S3 encrypted with KMS
HTTPS enforced on load balancersCC6.6, CC6.7ALB HTTPS-only listener, TLS 1.2+ policy
S3 buckets not publicly accessibleCC6.1S3 module blocks all public access by default
RDS not publicly accessibleCC6.1Aurora deployed in private database subnets, no public endpoint
VPC flow logs enabledCC7.1VPC module enables flow logs by default
Multi-AZ for RDSA1.2Aurora writer + reader across multiple availability zones
S3 versioning enabledCC7.2S3 data bucket has versioning enabled by default

To scope evidence collection, point your compliance platform at the AWS resource tags: every module in the kit tags resources with Project, Environment and ManagedBy = "terraform".

Customize

Swap EKS for ECS

Remove the eks module block from main.tf and add the ecs module from soc2.compliance.tf, then point the ALB target group at your ECS service instead of the EKS pods:

module "ecs" {
  source  = "soc2.compliance.tf/terraform-aws-modules/ecs/aws"
  version = "~> 6.0"

  cluster_name = local.name

  # Capacity providers and services: see the module page
  tags = var.tags
}

The ECS module page lists its inputs.

Add a second region for disaster recovery

The data and logs buckets already replicate through s3_replication_role_arn and s3_replication_destination_bucket_arn. To extend DR to compute and the database, add a provider alias for the second region and duplicate the relevant module blocks; use Aurora Global Database for the database.

provider "aws" {
  alias  = "dr"
  region = "us-west-2"
}

Adjust instance sizes

Every instance size is a variable. Override them in terraform.tfvars:

eks_node_instance_types = ["m6i.xlarge"]
eks_node_min_size       = 3
eks_node_max_size       = 10

aurora_instance_class   = "db.r6g.xlarge"
redis_node_type         = "cache.r6g.large"

Remove a module

If the application does not use DynamoDB or SQS, delete those module blocks from main.tf and their outputs. The other modules do not depend on them.

Turn off a control

Use the HTTPS source with ?disable=:

module "s3_bucket_data" {
  source = "https://soc2.compliance.tf/terraform-aws-modules/s3-bucket/aws?version=5.0.0&disable=s3_bucket_object_lock_enabled"
  # ...
}

Only a control the module enforces can be turned off; Turn controls on and off explains the limits and how to record the reason.

Cost

ComponentDevProd
VPC + NAT Gateway~$35~$100
ALB~$25~$25+
EKS control plane~$75~$75
EKS nodes (t3.medium)~$60~$120+
Aurora PostgreSQL (db.r6g.large)~$200~$400
S3 (data + logs)~$5~$5+
DynamoDB (on-demand)~$0~$0+
ElastiCache (cache.t4g.micro)~$10~$20
SQS~$0~$0+
CloudWatch Logs~$5~$10+
WAF~$5~$5+
KMS~$1~$1+
Total of the rows~$421~$761+

The total is the sum of the rows above. Usage charges come on top: data transfer, NAT gateway data processing, log ingestion, and KMS and WAF requests. Actual costs depend on usage, data transfer and region. Infracost estimates them from your own terraform plan.

Next steps

On this page

Ask AI about this

Help improve this page