Skip to content

Terraform module for the salable deployment of CTFd on AWS

License

Notifications You must be signed in to change notification settings

1nval1dctf/terraform-aws-ctfd

Repository files navigation

CTFd AWS Terraform module

ci workflow Terraform module to deploy CTFd into scalable AWS infrastructure

This has been used in a moderately sized CTF > 1000 participants and performed well with a setup similar to the example below, though you may want to scale out a little.

Design

The CTFd setup Looks something like this:

flowchart TB

  subgraph "Uploads"
    S3Uploads[S3]
  end

  subgraph "Logs"
    S3Logs[S3]
  end

  subgraph "RDS (mysql -  Serverless or Provisioned)"
    RDS[RDS autoscale]
  end

  subgraph "ElasticCache (redis)"
    REDIS[REDIS] --> ElasticCache1[Instance 1]
    REDIS[REDIS] --> ElasticCache[...]
    REDIS[REDIS] --> ElasticCacheN[Instance n]
  end

  LB[ALB] --> Ingress

  subgraph ECS[ECS]
    Ingress --> Service[CTFd service]
    Service --> Instance1[CTFd Instance 1]
    Service --> Instance[CTFd Instance ...]
    Service --> InstanceN[CTFd Instance n - HorizontalAutoScaling]
    Instance1 --> RDS[RDS]
    Instance --> RDS
    InstanceN --> RDS
    Instance1 --> REDIS[REDIS]
    Instance --> REDIS
    InstanceN --> REDIS
    Instance1 --> S3Uploads
    Instance --> S3Uploads
    InstanceN --> S3Uploads
    end
  ECS --> S3Logs

Requirements

Name Version
terraform >= 1.7.3
aws >= 5.38.0
docker 3.0.2
random 3.6.0

Providers

Name Version
random 3.6.0

Inputs

Name Description Type Default Required
app_name Name of application (ex: "ctfd") string "ctfd" no
aws_region Region to deploy CTFd into string "us-east-1" no
create_cdn Whether to create a cloudfront CDN deployment. bool false no
create_in_aws Create AWS resources. If false an instance will be spun up locally with docker bool true no
ctf_domain Domain to use for the CTFd deployment. Only used if create_cdn is true string "" no
ctf_domain_zone_id zone id for the route53 zone for the ctf_domain. Only used if create_cdn is true string "" no
ctfd_image Docker image for the ctfd frontend. string "ctfd/ctfd" no
db_character_set The database character set. string "utf8mb4" no
db_cluster_instance_type Type of instances to create in the RDS cluster. Only used if db_serverless set to false string "db.r5.large" no
db_collation The database collation. string "utf8mb4_bin" no
db_deletion_protection If true database will not be able to be deleted without manual intervention bool true no
db_engine Engine for the RDS cluster string "aurora-mysql" no
db_engine_version Engine version for the RDS cluster string "8.0.mysql_aurora.3.04.1" no
db_name Name for the database in RDS string "ctfd" no
db_port Port to connect to the RDS cluster on number 3306 no
db_serverless Configure serverless RDS cluster bool true no
db_serverless_max_capacity Maximum capacity for serverless RDS. Only used if db_serverless set to true number 128 no
db_serverless_min_capacity Minimum capacity for serverless RDS. Only used if db_serverless set to true number 1 no
db_skip_final_snapshot If true database will not be snapshoted before deletion. bool false no
db_user Username for the RDS database string "ctfd" no
elasticache_cluster_instance_type Instance type for instance in ElastiCache cluster string "cache.r6g.large" no
elasticache_cluster_instances Number of instances in ElastiCache cluster number 3 no
elasticache_cluster_port Port to connect to the ElastiCache cluster on number 6379 no
elasticache_encryption_key_arn Encryption key for use with ElastiCache at-rest encryption. Unencrypted if this is empty. string "" no
force_destroy_challenge_bucket Whether the S3 bucket containing the CTFD challenge data should be force destroyed bool false no
force_destroy_log_bucket Whether the S3 bucket containing the logging data should be force destroyed bool false no
frontend_desired_count Desired number of task instances for the frontend service. number 2 no
frontend_maximum_percent health percent for the frontend service. number 150 no
frontend_minimum_healthy_percent Minimum health percent for the frontend service. number 75 no
https_certificate_arn SSL Certificate ARN to be used for the HTTPS server. string "" no
rds_encryption_key_arn Encryption key for use with RDS at-rest encryption. Unencrypted if this is empty. string "" no
registry_password Password for container registry. Needed if using a private registry for a custom CTFd image. string null no
registry_server Container registry server. Needed if using a private registry for a custom CTFd image. string "registry.gitlab.com" no
registry_username Username for container registry. Needed if using a private registry for a custom CTFd image. string null no
s3_encryption_key_arn Encryption key for use with S3 bucket at-rest encryption. Unencrypted if this is empty. string "" no

Outputs

Name Description
challenge_bucket_id Challenge bucket name
lb_dns_name DNS name for the Load Balancer
lb_port Port that CTFd is reachable on
log_bucket_id Logging bucket name
private_subnet_ids List of private subnets that contain backend infrastructure (RDS, ElastiCache, EC2)
public_subnet_ids List of public subnets that contain frontend infrastructure (ALB)
vpc_id Id for the VPC created for CTFd

Examples

AWS Example

terraform {
  required_version = ">= 1.7.3"
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = ">= 5.38.0"
    }
  }
}

provider "aws" {
  region = "us-east-1"
}

module "ctfd" {
  source                            = "../../" # Actually set to "1nval1dctf/ctfd/aws"
  db_deletion_protection            = false
  elasticache_cluster_instance_type = "cache.t2.micro"
  elasticache_cluster_instances     = 2
  db_serverless                     = true
}

Docker Example

terraform {
  required_version = ">= 1.7.3"
}

module "ctfd" {
  source        = "../../" # Actually set to "1nval1dctf/ctfd/aws"
  db_user       = "ctfd"
  db_name       = "ctfd"
  create_in_aws = false
}

Building / Contributing

Install prerequisites

Golang

wget https://dl.google.com/go/go1.19.5.linux-amd64.tar.gz
sudo tar -C /usr/local -xzf go1.19.5.linux-amd64.tar.gz
rm go1.19.5.linux-amd64.tar.gz

Terraform

LATEST_URL=$(curl https://releases.hashicorp.com/terraform/index.json | jq -r '.versions[].builds[].url | select(.|test("alpha|beta|rc")|not) | select(.|contains("linux_amd64"))' | sort -t. -k 1,1n -k 2,2n -k 3,3n | tail -1)
curl ${LATEST_URL} > /tmp/terraform.zip
(cd /tmp && unzip /tmp/terraform.zip && chmod +x /tmp/terraform && sudo mv /tmp/terraform /usr/local/bin/)

Pre-commit and tools

Follow: https://github.com/antonbabenko/pre-commit-terraform#how-to-install

Run tests

Default tests will run through various validation steps then spin up an instance with docker.

make

To test the AWS backed version run.

make test_aws

⚠️ Warning: This will spin up CTFd in AWS which will cost you some money.

About

Terraform module for the salable deployment of CTFd on AWS

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published