Implementing and Securing OWASP Juice Shop with AWS WAF
AWS security engineering project implementing OWASP Juice Shop on ECS Fargate with AWS WAF protection, Terraform IaC, real-time Athena analytics, CI/CD security pipeline, and emergency response
This project demonstrates AWS security engineering by implementing and tuning OWASP Juice Shop with WAF protection. The work covers Infrastructure as Code deployment, automated testing, real-time analytics, and emergency response.
Objectives:
- Deploy security infrastructure using Infrastructure as Code
- Implement WAF protection with AWS WAF v2 and managed rule sets
- Build real-time security analytics
- Create automated CI/CD security pipeline with guardrails and compliance scanning
- Develop emergency response capabilities with sub-30-second threat mitigation
Tools
- AWS ECS Fargate - Container orchestration and hosting
- AWS Application Load Balancer - Traffic distribution and SSL termination
- AWS WAF v2 - Web application firewall and edge protection
- Terraform - Infrastructure as Code
- Amazon Kinesis Data Firehose - Real-time streaming to S3
- Amazon Athena - Serverless SQL analytics for WAF logs
- Amazon S3 - Log storage and data lake
- Amazon CloudWatch - Monitoring and dashboards
- GitHub Actions - CI/CD automation
- tfsec - Static security analysis for Terraform
- Checkov - Infrastructure security scanning
Phase 1: Infrastructure Deployment
Step 1: Terraform Infrastructure Setup
The deployment builds a multi-layered architecture using Infrastructure as Code, creating scalable, secure, and maintainable infrastructure components.
git clone https://github.com/ToluGIT/aws-waf-takeithome.git
cd aws-waf-takeithome
terraform init
terraform plan -var-file="terraform.tfvars"
terraform apply -var-file="terraform.tfvars"
Review terraform.tfvars for parameters like allowed_cidr_blocks, which you can modify to fit your requirements.

Step 2: WAF Module Implementation
The WAF implementation uses a modular design, with reusable components for security rules and configurations:
# terraform/modules/edge_waf/main.tf
resource "aws_wafv2_web_acl" "main" {
name = var.waf_name
scope = "CLOUDFRONT"
default_action {
allow {}
}
# AWS Managed Rules - Common Rule Set
rule {
name = "AWSManagedRulesCommonRuleSet"
priority = 1
override_action {
none {}
}
statement {
managed_rule_group_statement {
name = "AWSManagedRulesCommonRuleSet"
vendor_name = "AWS"
}
}
visibility_config {
cloudwatch_metrics_enabled = true
metric_name = "CommonRuleSetMetric"
sampled_requests_enabled = true
}
}
Important: For ALB/ECS, set WAF scope = REGIONAL in the same region. For CloudFront, use scope = CLOUDFRONT and manage it in us-east-1.
Step 3: ECS Infrastructure Verification
The ECS service deployment confirms multi-AZ distribution, healthy task status, and load balancer connectivity:

Step 4: Application Verification and Baseline Testing
This confirms deployment and establishes a baseline before security testing:

Phase 2: Security Testing and Analysis
Step 1: Security Testing Framework Development
The testing combines positive tests (legitimate traffic) with negative tests (attack vectors).
Positive Cases (Expected to Pass):
basic_homepage: GET /products_page: GET /#/productslogin_page: GET /#/loginlegitimate_search: GET /rest/products/search?q=apple
Negative Cases (Expected to Block):
juice_shop_sqli: GET /rest/products/search?q=’ OR 1=1—classic_sqli_union: GET /rest/products/search?q=apple’ UNION SELECT * FROM users—xss_script_tag: GET /rest/products/search?q=path_traversal: GET /../../etc/passwd
Step 2: Initial Security Assessment
Manual testing of path traversal shows the WAF blocking it:

Step 3: Automated Testing Execution
Run the automated testing framework:
# Install Python dependencies
pip3 install -r requirements.txt
python3 scripts/smoke_test.py --url $(terraform output -raw juice_shop_url)
The testing framework:
import requests
import json
from datetime import datetime
class SecurityTester:
def __init__(self, base_url):
self.base_url = base_url
self.results = {"positive": [], "negative": []}
def test_positive_cases(self):
"""traffic that should be allowed"""
positive_tests = [
{"name": "Homepage Access", "method": "GET", "path": "/"},
{"name": "Product Listing", "method": "GET", "path": "/rest/products"},
{"name": "User Login", "method": "POST", "path": "/rest/user/login",
"data": {"email": "test@test.com", "password": "test123"}},
{"name": "Product Search", "method": "GET", "path": "/rest/products/search?q=apple"}
]
def test_negative_cases(self):
"""attacks that should be blocked"""
attack_tests = [
{"name": "SQL Injection - Classic", "payload": "' OR 1=1--"},
{"name": "SQL Injection - Juice Shop", "payload": "')) OR true--"},
{"name": "XSS - Script Tag", "payload": "<script>alert('xss')</script>"},
{"name": "Command Injection", "payload": "; cat /etc/passwd"},
{"name": "Path Traversal", "payload": "../../../../../etc/passwd"},
{"name": "Remote File Inclusion", "payload": "http://evil.com/shell.php"}
]
Step 4: Initial Results Analysis
Initial testing revealed gaps, at 50% effectiveness:

Positive Tests: 4/4 passed (All legitimate traffic allowed)
Negative Tests: 3/10 passed (Only 3 attacks blocked)
GAPS IDENTIFIED:
Path traversal attacks: NOT BLOCKED
Command injection: NOT BLOCKED
Large headers: NOT BLOCKED
Step 5: WAF Configuration Optimization
Root cause: managed rules apply their vendor action unless overridden. Start new rules in Count mode for safe tuning, then switch to Block:
# terraform/modules/edge_waf/main.tf - Remove rule overrides
resource "aws_wafv2_web_acl" "main" {
# ... existing configuration ...
rule {
name = "AWSManagedRulesSQLiRuleSet"
priority = 2
# override_action { none {} } means "no override" - let managed rules apply their vendor action
override_action {
none {}
}
statement {
managed_rule_group_statement {
name = "AWSManagedRulesSQLiRuleSet"
vendor_name = "AWS"
}
}
}
}

Step 6: Security Effectiveness Validation
After tuning, the test suite was 100% blocked:

That gap shows why configuration validation matters when measuring security effectiveness.
Phase 3: Security Analytics Pipeline
Step 1: Athena Database Configuration
Navigate to Amazon Athena and launch the query editor:
CREATE DATABASE IF NOT EXISTS waf_analytics;

Step 2: Query Results Location Setup
Set the query results location to the existing WAF logs bucket:
s3://juice-shop-waf-logs-xxxxxx/athena-results/

Step 3: External Table Creation
Create the Athena external table for WAF log analysis. Modify create_table.sql with the correct S3 bucket location:
-- athena/queries/create_table.sql
LOCATION 's3://juice-shop-waf-logs-2od5y8gt/'
'storage.location.template'='s3://juice-shop-waf-logs-2od5y8gt/year=${year}/month=${month}/day=${day}/hour=${hour}/'
Retrieve the bucket name with:
terraform output s3_waf_logs_bucket

Step 4: Security KPI Analysis
Run the KPI metrics queries to generate security analytics:

The simple_kpi_metrics_single.sql query returns CORE_METRICS and TOP_ATTACK_VECTORS views for the last 24 hours.
Step 5: Real-Time Monitoring Implementation
Configure CloudWatch dashboard and WAF console monitoring:
CloudWatch WAF Dashboard:
- Navigate: CloudWatch → Dashboards → select the WAF dashboard
- Terraform provisions the dashboard as
juice-shop-waf-dashboard - Panels: Allowed vs Blocked requests, BlockedRequests by rule

WAF Console Monitoring:
- Navigate: WAF → Web ACLs →
juice-shop-web-acl→ Traffic Overview

Note: WAF logs reach S3 via a Firehose buffer (about 5 minutes or 5 MB), so expect a short delay before data appears in Athena.
Phase 4: CI/CD Security Pipeline
Step 1: GitHub Actions Workflow Implementation
The PR-based GitHub Actions pipeline (.github/workflows/edge-ci.yml) enforces security guardrails and produces deployable plans with approval gates.
Workflow Components:
- Change Detection: Runs only when Terraform, scripts, or workflow files change
- Security Scans: tfsec and Checkov scan the terraform/ directory and upload SARIF results
- Terraform Planning: Initializes Terraform, runs
terraform plan, and posts a summary to PR comments - Cost Analysis: Infracost calculates cost deltas (soft-fail for demonstration)
- Manual Approval Gate: Environment
production-approvalrequires approval before apply - Gated Apply: Runs
terraform apply -auto-approveafter approval
It also integrates:
- tfsec: Terraform static analysis with SARIF output
- Checkov: Infrastructure scanning with policy enforcement
- GitHub Security Tab: Automated findings integration

Phase 5: Emergency Response with Sub-30 Second Threat Mitigation
Step 1: Emergency Blocking Script Development
scripts/push_block.py enables rapid threat mitigation by deploying WAF rules programmatically:
# scripts/push_block.py - Emergency response automation
import boto3
import json
import sys
import ipaddress
from datetime import datetime, timezone
class EmergencyWAFBlocker:
def __init__(self, web_acl_name, web_acl_id, scope='CLOUDFRONT'):
self.waf_client = boto3.client('wafv2')
self.web_acl_name = web_acl_name
self.web_acl_id = web_acl_id
self.scope = scope
def validate_ip(self, ip_input):
"""Validate IP address or CIDR range"""
try:
# Handle both single IPs and CIDR ranges
ipaddress.ip_network(ip_input, strict=False)
return True
except ValueError:
return False
def get_web_acl_lock_token(self):
"""Get current lock token for WAF updates"""
try:
response = self.waf_client.get_web_acl(
Name=self.web_acl_name,
Scope=self.scope,
Id=self.web_acl_id
)
return response['LockToken'], response['WebACL']
except Exception as e:
raise Exception(f"Failed to get WAF lock token: {str(e)}")
def create_ip_block_rule(self, ip_address, rule_name=None, dry_run=True):
"""Create IP blocking rule"""
# Validate IP address
if not self.validate_ip(ip_address):
raise ValueError(f"Invalid IP address or CIDR: {ip_address}")
# Generate rule name if not provided
if not rule_name:
timestamp = datetime.now(timezone.utc).strftime("%Y%m%d_%H%M%S")
clean_ip = ip_address.replace('.', '_').replace('/', '_')
rule_name = f"EmergencyBlock_IP_{clean_ip}_{timestamp}"
# Prepare the new rule
new_rule = {
'Name': rule_name,
'Priority': 10, # High priority for emergency rules
'Statement': {
'IPSetReferenceStatement': {
'ARN': f'arn:aws:wafv2:us-east-1:{boto3.client("sts").get_caller_identity()["Account"]}:global/ipset/{rule_name}_ipset/{rule_name}'
}
},
'Action': {
'Block': {}
},
'VisibilityConfig': {
'SampledRequestsEnabled': True,
'CloudWatchMetricsEnabled': True,
'MetricName': rule_name
}
}
Step 2: Emergency Response Testing and Validation
Test the emergency blocking capabilities:
# Test IP blocking (dry-run mode)
python scripts/push_block.py --ip 192.168.1.100/32 --web-acl-id $(terraform output waf_web_acl_arn) --dry-run
# Test CIDR range blocking (dry-run mode)
python scripts/push_block.py --ip 10.0.0.0/24 --web-acl-id $(terraform output waf_web_acl_arn) --dry-run
# Test URI pattern blocking (dry-run mode)
python scripts/push_block.py --uri "/admin/*" $(terraform output waf_web_acl_arn) --dry-run
Step 3: IP Address Verification and Testing
Verify your current IP address:
curl https://checkip.amazonaws.com

Step 4: Dry Run Emergency Blocking
Run a dry run test to validate blocking:
python scripts/push_block.py --ip x.x.x.x/32 --web-acl-id $(terraform output waf_web_acl_arn) --dry-run

Step 5: Production Emergency Blocking Execution
Run it live, without the dry-run flag:
python scripts/push_block.py --ip x.x.x.x/32 --web-acl-id $(terraform output waf_web_acl_arn)
Results show sub-30-second response times:

Step 6: Verification of Rule Enforcement
Confirm rule enforcement in the AWS WAF Console:

Verify blocking effectiveness by trying to access the app:

Conclusion
Summary of Achievements
This project shows measurable results from building and tuning security infrastructure.
Infrastructure Automation: Full deployment via Infrastructure as Code, with modular, reusable components that adapt across applications.
Evidence-Based Optimization: Improvement from 50% to 100% effectiveness through iterative testing and rule refinement based on the attack payloads used in testing.
Operational Resilience: Emergency response with sub-30-second deployment times, safety controls, and audit logging for rapid threat mitigation without operational risk.
Lessons Learned
Configuration Validation is Critical: The gap between 50% and 100% effectiveness came down to one parameter. Managed rules apply their vendor action unless you override it, so correct configuration is what guarantees expected blocking.
Measurement Enables Optimization: Quantifiable metrics are the foundation for systematic, evidence-based improvement.
Automation Reduces Risk: Emergency response automation removes manual steps during incidents, cutting response time from minutes to seconds while keeping safety controls in place.