Skip to content

Commit bb46855

Browse files
Create AWS resources to host the CTF (#1)
1 parent cefa260 commit bb46855

16 files changed

+1016
-1
lines changed

.github/CODEOWNERS

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
* @rewindio/appsec

.github/dependabot.yml

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
version: 2
2+
3+
updates:
4+
# Maintain dependencies for GitHub Actions
5+
- package-ecosystem: "github-actions"
6+
directory: "/"
7+
schedule:
8+
interval: "daily"
9+
reviewers:
10+
- "rewindio/devops"
11+
labels:
12+
- "appsec"
13+
open-pull-requests-limit: 10

.github/workflows/checkov.yml

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
name: checkov
2+
concurrency: checkov
3+
4+
on: [pull_request, workflow_call]
5+
6+
permissions: read-all
7+
8+
jobs:
9+
checkov-static-analysis:
10+
name: "checkov"
11+
runs-on: ubuntu-latest
12+
steps:
13+
- name: Checkout
14+
uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
15+
16+
- name: Checkov static analysis
17+
id: static-analysis
18+
uses: bridgecrewio/checkov-action@99bb2caf247dfd9f03cf984373bc6043d4e32ebf # v12.1347.0
19+
with:
20+
directory: .
21+
framework: terraform
22+
hard_fail_on: CRITICAL
23+
skip_check: CKV_TF_1
24+
output_format: cli

.terraform.lock.hcl

+25
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

README.md

+10-1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,11 @@
1-
# trust-ctf
1+
# Capture the Flag (CTF) Repo
2+
23
Trust's capture the Flag (CTF) resources for Cybersecurity Awareness month.
4+
5+
This repository contains the Terraform that can be used to deploy an instance of OWASP Juice Shop on EC2 instance along with CFTd app to help manage the CTF event.
6+
7+
## OWASP Juice Shop & CTFd
8+
9+
![Juice Shop](https://raw.githubusercontent.com/juice-shop/juice-shop/develop/frontend/src/assets/public/images/JuiceShop_Logo_100px.png) [OWASP Juice Shop](https://owasp.org/www-project-juice-shop/) is probably the most modern and sophisticated insecure web application!
10+
11+
![CTFd](https://ctfd.io/static/img/ctfd.svg) [CTFd](https://ctfd.io/) is a Capture The Flag (CTF) framework designed for ease of use.

cloudwatch.tf

+126
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
data "aws_caller_identity" "current" {}
2+
data "aws_region" "current" {}
3+
#
4+
# Based on AWS documentation: Encrypt log data in CloudWatch Logs using AWS Key Management Service
5+
# https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/encrypt-log-data-kms.html
6+
#
7+
data "aws_iam_policy_document" "cloudwatch_waf_kms" {
8+
# checkov:skip=CKV_AWS_109: Allow `*` resources
9+
# checkov:skip=CKV_AWS_111: Allow `kms:*` actions
10+
# checkov:skip=CKV_AWS_356: Allow `kms:*` actions
11+
statement {
12+
principals {
13+
type = "AWS"
14+
identifiers = [
15+
"arn:aws:iam::${data.aws_caller_identity.current.account_id}:root",
16+
]
17+
}
18+
19+
effect = "Allow"
20+
actions = ["kms:*"]
21+
resources = ["*"]
22+
}
23+
24+
statement {
25+
principals {
26+
type = "Service"
27+
identifiers = ["logs.${data.aws_region.current.name}.amazonaws.com"]
28+
}
29+
30+
actions = [
31+
"kms:Encrypt*",
32+
"kms:Decrypt*",
33+
"kms:ReEncrypt*",
34+
"kms:GenerateDataKey*",
35+
"kms:Describe*",
36+
]
37+
38+
resources = ["*"]
39+
40+
condition {
41+
test = "ArnLike"
42+
variable = "kms:EncryptionContext:aws:logs:arn"
43+
44+
values = ["arn:aws:logs:*:${data.aws_caller_identity.current.account_id}:log-group:aws-waf-logs-*"]
45+
}
46+
}
47+
}
48+
49+
resource "aws_kms_key" "cloudwatch_waf" {
50+
description = "aws-waf-logs-ctf-key"
51+
key_usage = "ENCRYPT_DECRYPT"
52+
multi_region = true
53+
enable_key_rotation = true
54+
55+
policy = data.aws_iam_policy_document.cloudwatch_waf_kms.json
56+
}
57+
58+
resource "aws_kms_alias" "cloudwatch_waf" {
59+
name = "alias/aws-waf-logs-ctf-key"
60+
target_key_id = aws_kms_key.cloudwatch_waf.key_id
61+
}
62+
63+
resource "aws_cloudwatch_log_group" "waf" {
64+
# checkov:skip=CKV_AWS_338: Ensure CloudWatch log groups retains logs for at least 1 year
65+
66+
name = "aws-waf-logs-ctf"
67+
retention_in_days = 7
68+
kms_key_id = aws_kms_key.cloudwatch_waf.arn
69+
}
70+
71+
###=============== CloudWatch Log Insights - Queries =============== ###
72+
73+
resource "aws_cloudwatch_query_definition" "tail" {
74+
name = "WAF/Tail View (ctf)"
75+
76+
log_group_names = [aws_cloudwatch_log_group.waf.name]
77+
78+
query_string = <<EOF
79+
fields @timestamp as Timestamp,
80+
action as Action,
81+
terminatingRuleId as Rule,
82+
httpRequest.clientIp as Request_IP,
83+
httpRequest.country as Request_Country,
84+
httpRequest.httpMethod as Request_Method,
85+
httpRequest.uri as URI
86+
| sort @timestamp desc
87+
| limit 100
88+
EOF
89+
}
90+
91+
resource "aws_cloudwatch_query_definition" "filter_by_clientip" {
92+
name = "WAF/Filter by Client IP (ctf)"
93+
94+
log_group_names = [aws_cloudwatch_log_group.waf.name]
95+
96+
query_string = <<EOF
97+
fields @timestamp as Timestamp,
98+
action as Action,
99+
httpRequest.country as Request_Country,
100+
httpRequest.httpMethod as Request_Method,
101+
httpRequest.uri as URI,
102+
labels.0.name as WAF_Rule,
103+
terminatingRuleId as WAF_RuleID
104+
| sort @timestamp desc
105+
| filter httpRequest.clientIp LIKE "8.8.8.8"
106+
EOF
107+
}
108+
109+
resource "aws_cloudwatch_query_definition" "filter_by_rule" {
110+
name = "WAF/Filter by Rule (ctf)"
111+
112+
log_group_names = [aws_cloudwatch_log_group.waf.name]
113+
114+
query_string = <<EOF
115+
fields @timestamp as Timestamp,
116+
action as Action,
117+
terminatingRuleId as Rule,
118+
httpRequest.clientIp as Request_IP,
119+
httpRequest.country as Request_Country,
120+
httpRequest.httpMethod as Request_Method,
121+
httpRequest.uri as URI
122+
| sort @timestamp desc
123+
| filter action not like "ALLOW" and
124+
| terminatingRuleId in ["AWSManagedRulesAmazonIpReputationList", "AWSManagedRulesCommonRuleSet", "AWSManagedRulesKnownBadInputsRuleSet", "AWSManagedRulesSQLiRuleSet", "AWSManagedRulesLinuxRuleSet"]
125+
EOF
126+
}

ec2.tf

+79
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
data "aws_ami" "amzn-linux-2023-ami" {
2+
most_recent = true
3+
owners = ["amazon"]
4+
5+
filter {
6+
name = "name"
7+
values = ["al2023-ami-2023.*-x86_64"]
8+
}
9+
}
10+
11+
###======================== CTFd EC2 ====================== ###
12+
13+
resource "aws_instance" "ctfd" {
14+
#checkov:skip=CKV_AWS_8:Ensure all data stored in the Launch configuration or instance Elastic Blocks Store is securely encrypted
15+
#checkov:skip=CKV_AWS_126:Ensure that detailed monitoring is enabled for EC2 instances
16+
#checkov:skip=CKV_AWS_135:Ensure that EC2 is EBS optimized
17+
18+
ami = data.aws_ami.amzn-linux-2023-ami.id
19+
instance_type = var.instance_type
20+
availability_zone = var.aws_availability_zone_a
21+
22+
subnet_id = aws_subnet.ctfd.id
23+
associate_public_ip_address = false
24+
25+
vpc_security_group_ids = [
26+
aws_security_group.ctf.id
27+
]
28+
29+
metadata_options {
30+
http_endpoint = "enabled"
31+
http_tokens = "required"
32+
http_put_response_hop_limit = 1
33+
}
34+
35+
root_block_device {
36+
volume_size = 40
37+
}
38+
39+
iam_instance_profile = aws_iam_instance_profile.ctf.id
40+
41+
tags = {
42+
Name = "CTFd"
43+
}
44+
}
45+
46+
###================= OWASP Juice Shop EC2 ================= ###
47+
48+
resource "aws_instance" "owaspjs" {
49+
#checkov:skip=CKV_AWS_8:Ensure all data stored in the Launch configuration or instance Elastic Blocks Store is securely encrypted
50+
#checkov:skip=CKV_AWS_126:Ensure that detailed monitoring is enabled for EC2 instances
51+
#checkov:skip=CKV_AWS_135:Ensure that EC2 is EBS optimized
52+
53+
ami = data.aws_ami.amzn-linux-2023-ami.id
54+
instance_type = var.instance_type
55+
availability_zone = var.aws_availability_zone_a
56+
57+
subnet_id = aws_subnet.owaspjs.id
58+
associate_public_ip_address = false
59+
60+
vpc_security_group_ids = [
61+
aws_security_group.ctf.id
62+
]
63+
64+
metadata_options {
65+
http_endpoint = "enabled"
66+
http_tokens = "required"
67+
http_put_response_hop_limit = 1
68+
}
69+
70+
root_block_device {
71+
volume_size = 40
72+
}
73+
74+
iam_instance_profile = aws_iam_instance_profile.ctf.id
75+
76+
tags = {
77+
Name = "OWASP Juice Shop"
78+
}
79+
}

iam.tf

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
resource "aws_iam_instance_profile" "ctf" {
2+
name = "ctf_ec2_instance_profile"
3+
role = aws_iam_role.ctf_role.name
4+
}
5+
6+
data "aws_iam_policy_document" "ctf_assume_role" {
7+
statement {
8+
effect = "Allow"
9+
10+
principals {
11+
type = "Service"
12+
identifiers = ["ec2.amazonaws.com"]
13+
}
14+
15+
actions = ["sts:AssumeRole"]
16+
}
17+
}
18+
19+
resource "aws_iam_role" "ctf_role" {
20+
name = "ctf_ec2_role"
21+
path = "/"
22+
23+
assume_role_policy = data.aws_iam_policy_document.ctf_assume_role.json
24+
25+
managed_policy_arns = [
26+
"arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore"
27+
]
28+
}

0 commit comments

Comments
 (0)