Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(): Add Ansible to mange installation of applications #7

Merged
merged 10 commits into from
Oct 25, 2023
28 changes: 28 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,31 @@ This repository contains the Terraform that can be used to deploy an instance of
![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!

![CTFd](https://ctfd.io/static/img/ctfd.svg) [CTFd](https://ctfd.io/) is a Capture The Flag (CTF) framework designed for ease of use.

# Usage Instructions

### Step 1: Provision AWS resources via Terraform

```
terraform init
terraform apply
```

### Step 2: Install applications via Ansible playbooks

- Replace the `s3://bucket-name` with the value of the `s3_bucket_name_ansible_playbooks` output from the Terraform apply.
- Replace the `--instance-ids` values with the corresponding `ec2_cftd_instance_id` and `ec2_owaspjs_instance_id` output values from the Terraform apply.

```
aws s3 sync ./ansible s3://bucket-name --include "*.yml"
# Install CFTd
aws ssm send-command --document-name "AWS-RunAnsiblePlaybook" --instance-ids "i-0xxxxxxxxxxxxxxxx" --max-errors 1 --parameters '{"extravars":["SSM=True"],"check":["False"],"playbookurl":["s3://bucket-name/playbook_cftd.yml"]}' --timeout-seconds 600 --region ca-central-1
# Install OWASP Juice Shop
aws ssm send-command --document-name "AWS-RunAnsiblePlaybook" --instance-ids "i-0xxxxxxxxxxxxxxxx" --max-errors 1 --parameters '{"extravars":["SSM=True"],"check":["False"],"playbookurl":["s3://bucket-name/playbook_owaspjs.yml"]}' --timeout-seconds 600 --region ca-central-1
```

### Step 3: Configure the Flags

[juice-shop-ctf-cli (OWASP Juice Shop CTF Extension)](https://www.npmjs.com/package/juice-shop-ctf-cli)

> The Node package juice-shop-ctf-cli helps you to prepare Capture the Flag events with the OWASP Juice Shop challenges for different popular CTF frameworks. This interactive utility allows you to populate a CTF game server in a matter of minutes.
81 changes: 81 additions & 0 deletions ansible/playbook_cftd.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
---

- name: CFTd
gather_facts: false
remote_user: ssm-user
become: true
hosts: all

tasks:
- name: Install Git
dnf:
name: git
state: present

- name: Install Docker
dnf:
name: docker
state: present

- name: Enable Docker service
ansible.builtin.systemd:
name: docker.service
state: started
enabled: true

- name: Add ssm-user user to docker group
ansible.builtin.user:
name: ssm-user
groups: docker
append: yes

- name: Create /opt/cftd directory
ansible.builtin.file:
path: /opt/cftd
state: directory
owner: ssm-user
group: ssm-user
mode: "0755"

- name: Workaround Git safe directory error
community.general.git_config:
name: safe.directory
value: /opt/cftd
scope: global
environment:
HOME: /home/ssm-user

- name: Read safe directory from git config
community.general.git_config:
name: safe.directory
scope: global
environment:
HOME: /home/ssm-user

- name: Git clone CFTd git repo
ansible.builtin.git:
repo: "https://github.com/CTFd/CTFd.git"
dest: /opt/cftd
clone: yes
environment:
HOME: /home/ssm-user

- name: Change ownership of CFTd directory
ansible.builtin.file:
path: /opt/cftd
state: directory
recurse: yes
owner: ssm-user
group: ssm-user

- name: Download docker-compose
become: true
ansible.builtin.get_url:
url: https://github.com/docker/compose/releases/download/v2.20.3/docker-compose-linux-x86_64
dest: /usr/bin/docker-compose
mode: "755"

- name: Run docker-compose to start cftd
ansible.builtin.command: /usr/bin/docker-compose up -d
args:
chdir: /opt/cftd
39 changes: 39 additions & 0 deletions ansible/playbook_juice.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
---
- name: OWASP Juice Shop
gather_facts: false
remote_user: ssm-user
become: true
hosts: all

tasks:
- name: Install Docker
become: true
dnf:
name: docker
state: present

- name: Enable Docker service
become: true
ansible.builtin.systemd:
name: docker.service
state: started
enabled: true

- name: Add ssm-user user to docker group
become: true
ansible.builtin.user:
name: ssm-user
groups: docker
append: yes

- name: Pull bkimminich/juice-shop docker image
community.docker.docker_image:
name: bkimminich/juice-shop
source: pull

- name: Launch OWASP Juice Shop container
community.docker.docker_container:
name: juice-shop
image: bkimminich/juice-shop
gregsienkiewicz marked this conversation as resolved.
Show resolved Hide resolved
ports:
- "80:3000"
4 changes: 2 additions & 2 deletions cloudwatch.tf
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ fields @timestamp as Timestamp,
httpRequest.httpMethod as Request_Method,
httpRequest.uri as URI
| sort @timestamp desc
| filter action not like "ALLOW" and
| terminatingRuleId in ["AWSManagedRulesAmazonIpReputationList", "AWSManagedRulesCommonRuleSet", "AWSManagedRulesKnownBadInputsRuleSet", "AWSManagedRulesSQLiRuleSet", "AWSManagedRulesLinuxRuleSet"]
| filter terminatingRuleId in ["AWSManagedRulesAmazonIpReputationList", "AWSManagedRulesCommonRuleSet", "AWSManagedRulesKnownBadInputsRuleSet", "AWSManagedRulesSQLiRuleSet", "AWSManagedRulesLinuxRuleSet"]
or nonTerminatingMatchingRules.0.ruleId in ["AWSManagedRulesAmazonIpReputationList", "AWSManagedRulesCommonRuleSet", "AWSManagedRulesKnownBadInputsRuleSet", "AWSManagedRulesSQLiRuleSet", "AWSManagedRulesLinuxRuleSet"]
EOF
}
12 changes: 12 additions & 0 deletions ec2.tf
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,12 @@ resource "aws_instance" "ctfd" {

iam_instance_profile = aws_iam_instance_profile.ctf.id

user_data = <<-EOF
#!/bin/bash
dnf update -y
dnf install -y ansible
EOF

tags = {
Name = "CTFd"
}
Expand Down Expand Up @@ -73,6 +79,12 @@ resource "aws_instance" "owaspjs" {

iam_instance_profile = aws_iam_instance_profile.ctf.id

user_data = <<-EOF
#!/bin/bash
dnf update -y
dnf install -y ansible
EOF

tags = {
Name = "OWASP Juice Shop"
}
Expand Down
18 changes: 9 additions & 9 deletions outputs.tf
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,17 @@ output "owaspjs_private_dns" {
value = aws_instance.owaspjs.private_dns
}

output "rds_hostname" {
description = "RDS instance hostname"
value = aws_db_instance.cftd.address
output "s3_bucket_name_ansible_playbooks" {
description = "The Ansible playbook S3 bucket name"
value = aws_s3_bucket.ansible.bucket
}

output "rds_port" {
description = "RDS instance port"
value = aws_db_instance.cftd.port
output "ec2_cftd_instance_id" {
description = "The EC2 instance ID of the CTFd instance"
value = aws_instance.ctfd.id
}

output "rds_username" {
description = "RDS instance username"
value = aws_db_instance.cftd.username
output "ec2_owaspjs_instance_id" {
description = "The EC2 instance ID of the OWASP Juice Shop instance"
value = aws_instance.owaspjs.id
}
40 changes: 0 additions & 40 deletions rds.tf

This file was deleted.

67 changes: 67 additions & 0 deletions s3.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
###======================== CTF S3 Ansible ====================== ###

resource "aws_s3_bucket" "ansible" {

Check failure on line 3 in s3.tf

View workflow job for this annotation

GitHub Actions / checkov

CKV2_AWS_6: "Ensure that S3 bucket has a Public Access block"
#checkov:skip=CKV2_AWS_61:Ensure that an S3 bucket has a lifecycle configuration
#checkov:skip=CKV_AWS_18:Ensure the S3 bucket has access logging enabled
#checkov:skip=CKV2_AWS_65:Ensure access control lists for S3 buckets are disabled
#checkov:skip=CKV2_AWS_62:Ensure S3 buckets should have event notifications enabled
#checkov:skip=CKV_AWS_145:Ensure that S3 buckets are encrypted with KMS by default
#checkov:skip=CKV_AWS_144:Ensure that S3 bucket has cross-region replication enabled

bucket = var.ansible_playbook_bucket_name
}

resource "aws_s3_bucket_versioning" "ansible" {
bucket = aws_s3_bucket.ansible.id
versioning_configuration {
status = "Enabled"
}
}

resource "aws_s3_bucket_server_side_encryption_configuration" "ansible" {
bucket = aws_s3_bucket.ansible.id

rule {
apply_server_side_encryption_by_default {
sse_algorithm = "AES256"
}
}
}

resource "aws_s3_bucket_ownership_controls" "ansible" {
bucket = aws_s3_bucket.ansible.id
rule {
object_ownership = "BucketOwnerEnforced"
}
}

resource "aws_s3_bucket_acl" "ansible" {
depends_on = [aws_s3_bucket_ownership_controls.ansible]

bucket = aws_s3_bucket.ansible.id
acl = "private"
}

resource "aws_s3_bucket_policy" "allow_access_from_ssm" {
bucket = aws_s3_bucket.ansible.id
policy = data.aws_iam_policy_document.allow_access_from_ssm.json
}

data "aws_iam_policy_document" "allow_access_from_ssm" {
statement {
principals {
type = "AWS"
identifiers = ["arn:aws:iam::${data.aws_caller_identity.current.account_id}:role/${aws_iam_instance_profile.ctf.role}"]
}

actions = [
"s3:GetObject",
"s3:ListBucket",
]

resources = [
aws_s3_bucket.ansible.arn,
"${aws_s3_bucket.ansible.arn}/*",
]
}
}
26 changes: 0 additions & 26 deletions sg.tf
Original file line number Diff line number Diff line change
Expand Up @@ -85,29 +85,3 @@ resource "aws_security_group" "alb" {
Name = "sg-ctf-alb"
}
}

resource "aws_security_group" "rds" {
name = "CTF RDS Security Group"
description = "CTF RDS Security Group"
vpc_id = aws_vpc.ctf.id

ingress {
description = "RDS from internal SG"
from_port = 3306
to_port = 3306
protocol = "tcp"
security_groups = [aws_security_group.ctf.id]
}

egress {
description = "Allow All Traffic Outbound"
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}

tags = {
Name = "sg-ctf-rds"
}
}
Loading
Loading