Skip to content

Commit

Permalink
Firewall (#21)
Browse files Browse the repository at this point in the history
* add firewall module
* put firewall in front of load balancer
* bugfix: change already applied manually
  • Loading branch information
mbsimonovic authored Apr 12, 2022
1 parent bcb0ae0 commit 316fb9b
Show file tree
Hide file tree
Showing 5 changed files with 210 additions and 1 deletion.
25 changes: 25 additions & 0 deletions main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ locals {
###
# the cdn that serves videos from an s3 bucket, e.g. static.mentorpal.org
###

module "cdn_static" {
source = "git::https://github.com/cloudposse/terraform-aws-cloudfront-s3-cdn?ref=tags/0.74.0"
namespace = "static-${var.eb_env_namespace}"
Expand All @@ -115,6 +116,9 @@ module "cdn_static" {
dns_alias_enabled = true
parent_zone_name = var.aws_route53_zone_name
acm_certificate_arn = data.aws_acm_certificate.cdn.arn
# bugfix: required for video playback after upload
forward_query_string = true
query_string_cache_keys = ["v"]
}

# export s3 arn so serverless can pick it up to configure iam policies
Expand Down Expand Up @@ -317,6 +321,27 @@ resource "aws_lb_listener_rule" "redirect_http_to_https" {
}
}

#####
# Firewall
#
#####


module "firewall" {
source = "./modules/waf"
aws_region = var.aws_region
environment = var.eb_env_stage
top_level_domain = var.site_domain_name
rate_limit = 100
tags = var.eb_env_tags
}

resource "aws_wafv2_web_acl_association" "load_blancer_firewall" {
resource_arn = module.elastic_beanstalk_environment.load_balancers[0]
web_acl_arn = module.firewall.wafv2_webacl_arn
}


######
# Cloudwatch alarms
# - https://docs.aws.amazon.com/elasticloadbalancing/latest/application/load-balancer-cloudwatch-metrics.html
Expand Down
157 changes: 157 additions & 0 deletions modules/waf/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
resource "aws_wafv2_web_acl" "wafv2_webacl" {
name = "mentorpal-${var.environment}-wafv2-webacl"
scope = "REGIONAL"
tags = var.tags

default_action {
allow {}
}

rule {
name = "ip-rate-limit-rule"
priority = 2

action {
block {}
}

statement {
rate_based_statement {
aggregate_key_type = "IP"
limit = var.rate_limit
}
}

visibility_config {
cloudwatch_metrics_enabled = false
metric_name = "${var.rate_limit}-ip-rate-limit-rule"
sampled_requests_enabled = false
}
}

rule {
name = "bot-control"
priority = 3

override_action {
# in order to test, lets just collect stats before enabling rules on prod:
count {}
# none {}
}
statement {
managed_rule_group_statement {
# see https://docs.aws.amazon.com/waf/latest/developerguide/aws-managed-rule-groups-list.html#aws-managed-rule-groups-bot
name = "AWSManagedRulesBotControlRuleSet"
vendor_name = "AWS"
}
}

visibility_config {
cloudwatch_metrics_enabled = true
metric_name = "AWS-AWSBotControl-rule"
sampled_requests_enabled = true
}
}

visibility_config {
cloudwatch_metrics_enabled = true
metric_name = "mentorpal-${var.environment}-wafv2-webacl"
sampled_requests_enabled = true
}
}

resource "aws_ssm_parameter" "origin_acl_arn" {
name = "/mentorpal/${var.environment}/firewall/WEBACL_ARN"
type = "String"
value = aws_wafv2_web_acl.wafv2_webacl.arn

tags = var.tags
}

resource "aws_s3_bucket" "s3_logs" {
bucket = "mentorpal-aws-waf-logs-${var.aws_region}-${var.environment}"
acl = "private"
tags = var.tags
}

data "aws_iam_policy_document" "policy_assume_kinesis" {
statement {
actions = ["sts:AssumeRole"]

principals {
type = "Service"
identifiers = ["firehose.amazonaws.com"]
}
}
}

resource "aws_iam_role" "firehose_role" {
name = "mentorpal-firehose-aws-waf-logs-${var.aws_region}-${var.environment}"
assume_role_policy = data.aws_iam_policy_document.policy_assume_kinesis.json
tags = var.tags
}

# https://docs.aws.amazon.com/firehose/latest/dev/controlling-access.html#using-iam-s3
data "aws_iam_policy_document" "s3_policy_document" {
statement {
sid = "1"
actions = [
"s3:GetBucketLocation",
"s3:ListBucket",
"s3:ListBucketMultipartUploads",
]

resources = [
aws_s3_bucket.s3_logs.arn,
]
}

statement {
sid = "2"
actions = [
"s3:AbortMultipartUpload",
"s3:GetObject",
"s3:PutObject",
]

resources = [
"${aws_s3_bucket.s3_logs.arn}/*",
]
}
}

resource "aws_iam_policy" "s3_policy" {
name = "mentorpal-kinesis-s3-write-policy-${var.environment}"
policy = data.aws_iam_policy_document.s3_policy_document.json
}

resource "aws_iam_role_policy_attachment" "firehose_s3_policy_attachment" {
role = aws_iam_role.firehose_role.name
policy_arn = aws_iam_policy.s3_policy.arn
}

resource "aws_kinesis_firehose_delivery_stream" "waf_logs_kinesis_stream" {
# the name must begin with aws-waf-logs-
name = "aws-waf-logs-kinesis-stream-mentorpal-${var.environment}"
destination = "s3"
s3_configuration {
role_arn = aws_iam_role.firehose_role.arn
bucket_arn = aws_s3_bucket.s3_logs.arn
compression_format = "GZIP"
}
tags = var.tags
}

resource "aws_wafv2_web_acl_logging_configuration" "waf_logging_conf_staging" {
log_destination_configs = [aws_kinesis_firehose_delivery_stream.waf_logs_kinesis_stream.arn]
resource_arn = aws_wafv2_web_acl.wafv2_webacl.arn
redacted_fields {
single_header {
name = "authorization"
}
}
}

output "wafv2_webacl_arn" {
value = aws_wafv2_web_acl.wafv2_webacl.arn
}
21 changes: 21 additions & 0 deletions modules/waf/vars.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
variable "aws_region" {
type = string
description = "AWS region"
}

variable "environment" {
type = string
}
variable "top_level_domain" {
type = string
default = "mentorpal.org"
}

variable "tags" {
type = map(string)
}

variable "rate_limit" {
type = number
default = 100 # minimum
}
6 changes: 6 additions & 0 deletions modules/waf/versions.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
terraform {
required_version = ">= 0.15.0"
required_providers {
aws = ">= 3.1"
}
}
2 changes: 1 addition & 1 deletion versions.tf
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
terraform {
required_version = ">= 0.14.0"
required_version = ">= 0.15.0"

required_providers {
aws = "~> 3.0"
Expand Down

0 comments on commit 316fb9b

Please sign in to comment.