Skip to content

Instantly share code, notes, and snippets.

@jhrr
Forked from masayoshi644/_HowToSetupAWSWAFv2.md
Created July 3, 2023 22:13
Show Gist options
  • Save jhrr/693d3a38b2e3fc9da64778fbb159f0b4 to your computer and use it in GitHub Desktop.
Save jhrr/693d3a38b2e3fc9da64778fbb159f0b4 to your computer and use it in GitHub Desktop.
How to setup AWS WAFv2
resource "aws_wafv2_web_acl" "this" {
name = "${var.prefix}-${var.name}"
scope = "REGIONAL"
default_action {
allow {}
}
rule {
name = "AWSRateBasedRuleDomesticDOS"
priority = 1
action {
block {}
}
statement {
rate_based_statement {
limit = 2000
aggregate_key_type = "IP"
scope_down_statement {
geo_match_statement {
country_codes = ["JP"]
}
}
}
}
visibility_config {
cloudwatch_metrics_enabled = true
metric_name = "AWSRateBasedRuleDomesticDOS"
sampled_requests_enabled = true
}
}
rule {
name = "AWSRateBasedRuleGlobalDOS"
priority = 2
action {
block {}
}
statement {
rate_based_statement {
limit = 500
aggregate_key_type = "IP"
scope_down_statement {
not_statement {
statement {
geo_match_statement {
country_codes = ["JP"]
}
}
}
}
}
}
visibility_config {
cloudwatch_metrics_enabled = true
metric_name = "AWSRateBasedRuleGlobalDOS"
sampled_requests_enabled = true
}
}
rule {
name = "AWSIPBlackList"
priority = 3
action {
block {}
}
statement {
or_statement {
statement {
ip_set_reference_statement {
arn = var.alb_ipsets_v4
}
}
statement {
ip_set_reference_statement {
arn = var.alb_ipsets_v6
}
}
}
}
visibility_config {
cloudwatch_metrics_enabled = true
metric_name = "AWSIPBlackList"
sampled_requests_enabled = true
}
}
rule {
name = "AWSManagedRulesCommonRuleSet"
priority = 10
override_action {
count {}
}
statement {
managed_rule_group_statement {
name = "AWSManagedRulesCommonRuleSet"
vendor_name = "AWS"
}
}
visibility_config {
cloudwatch_metrics_enabled = true
metric_name = "AWSManagedRulesCommonRuleSetMetric"
sampled_requests_enabled = true
}
}
rule {
name = "AWSManagedRulesKnownBadInputsRuleSet"
priority = 20
override_action {
count {}
}
statement {
managed_rule_group_statement {
name = "AWSManagedRulesKnownBadInputsRuleSet"
vendor_name = "AWS"
}
}
visibility_config {
cloudwatch_metrics_enabled = true
metric_name = "AWSManagedRulesKnownBadInputsRuleSetMetric"
sampled_requests_enabled = true
}
}
rule {
name = "AWSManagedRulesAmazonIpReputationList"
priority = 30
override_action {
count {}
}
statement {
managed_rule_group_statement {
name = "AWSManagedRulesAmazonIpReputationList"
vendor_name = "AWS"
}
}
visibility_config {
cloudwatch_metrics_enabled = true
metric_name = "AWSManagedRulesAmazonIpReputationListMetric"
sampled_requests_enabled = true
}
}
rule {
name = "AWSManagedRulesAnonymousIpList"
priority = 40
override_action {
count {}
}
statement {
managed_rule_group_statement {
name = "AWSManagedRulesAnonymousIpList"
vendor_name = "AWS"
}
}
visibility_config {
cloudwatch_metrics_enabled = true
metric_name = "AWSManagedRulesAnonymousIpListMetric"
sampled_requests_enabled = true
}
}
rule {
name = "AWSManagedRulesSQLiRuleSet"
priority = 50
override_action {
count {}
}
statement {
managed_rule_group_statement {
name = "AWSManagedRulesSQLiRuleSet"
vendor_name = "AWS"
}
}
visibility_config {
cloudwatch_metrics_enabled = true
metric_name = "AWSManagedRulesSQLiRuleSetMetric"
sampled_requests_enabled = true
}
}
rule {
name = "AWSManagedRulesLinuxRuleSet"
priority = 60
override_action {
count {}
}
statement {
managed_rule_group_statement {
name = "AWSManagedRulesLinuxRuleSet"
vendor_name = "AWS"
}
}
visibility_config {
cloudwatch_metrics_enabled = true
metric_name = "AWSManagedRulesLinuxRuleSetMetric"
sampled_requests_enabled = true
}
}
rule {
name = "AWSManagedRulesUnixRuleSet"
priority = 70
override_action {
count {}
}
statement {
managed_rule_group_statement {
name = "AWSManagedRulesUnixRuleSet"
vendor_name = "AWS"
}
}
visibility_config {
cloudwatch_metrics_enabled = true
metric_name = "AWSManagedRulesUnixRuleSetMetric"
sampled_requests_enabled = true
}
}
tags = {
Name = "${var.prefix}-${var.name}"
}
visibility_config {
cloudwatch_metrics_enabled = true
metric_name = var.metric_name
sampled_requests_enabled = true
}
}
resource "aws_s3_bucket" "bucket" {
bucket = var.bucket
tags = {
Name = "${var.prefix}-${var.name}"
}
}
resource "aws_wafv2_web_acl_logging_configuration" "api_server_waf_log" {
log_destination_configs = [aws_s3_bucket.bucket.arn]
resource_arn = aws_wafv2_web_acl.this.arn
}
# OUTPUT
output "waf_arn" {
value = aws_wafv2_web_acl.this.arn
description = "IP sets arn"
}
output "s3_bucket_arn" {
value = aws_s3_bucket.bucket.arn
description = "S3 bucket arn"
}
# VARIABLE
variable "prefix" {
type = string
}
variable "name" {
type = string
}
variable "metric_name" {
type = string
}
variable "alb_ipsets_v4" {
type = string
}
variable "alb_ipsets_v6" {
type = string
}
variable "bucket" {
type = string
}
provider "aws" {
alias = "us-east-1"
region = "us-east-1"
}
resource "aws_wafv2_ip_set" "blacklist_alb_ipv4" {
name = "${var.prefix}-alb-ipv4"
scope = "REGIONAL"
ip_address_version = "IPV4"
addresses = ["127.0.0.1/32"]
tags = {
Name = "${var.prefix}-alb-ipv4"
}
}
resource "aws_wafv2_ip_set" "blacklist_cf_ipv4" {
name = "${var.prefix}-cf-ipv4"
scope = "CLOUDFRONT"
provider = aws.us-east-1
ip_address_version = "IPV4"
addresses = ["127.0.0.1/32"]
tags = {
Name = "${var.prefix}-cf-ipv4"
}
}
resource "aws_wafv2_ip_set" "blacklist_alb_ipv6" {
name = "${var.prefix}-alb-ipv6"
scope = "REGIONAL"
ip_address_version = "IPV6"
addresses = ["2001:0db8:0000:0000:0000:0000:0000:0001/128"]
tags = {
Name = "${var.prefix}-alb-ipv6"
}
}
resource "aws_wafv2_ip_set" "blacklist_cf_ipv6" {
name = "${var.prefix}-cf-ipv6"
scope = "CLOUDFRONT"
provider = aws.us-east-1
ip_address_version = "IPV6"
addresses = ["2001:0db8:0000:0000:0000:0000:0000:0001/128"]
tags = {
Name = "${var.prefix}-cf-ipv6"
}
}
// ARN
output "waf_ipsets_alb_ipv4_arn" {
value = aws_wafv2_ip_set.blacklist_alb_ipv4.arn
description = "IP sets arn"
}
# OUTPUT
output "waf_ipsets_cf_ipv4_arn" {
value = aws_wafv2_ip_set.blacklist_cf_ipv4.arn
description = "IP sets arn"
}
output "waf_ipsets_alb_ipv6_arn" {
value = aws_wafv2_ip_set.blacklist_alb_ipv6.arn
description = "IP sets arn"
}
output "waf_ipsets_cf_ipv6_arn" {
value = aws_wafv2_ip_set.blacklist_cf_ipv6.arn
description = "IP sets arn"
}
# VARIABLE
variable "prefix" {
type = string
}
variable "name" {
type = string
}
locals {
domain = "hoge"
environment = "fuga"
prefix = "${local.domain}-${local.environment}"
}
module "waf_alb" {
source = "../../modules/waf_alb"
prefix = local.prefix
name = "waf-alb"
metric_name = "waf-alb"
alb_ipsets_v4 = module.waf_ipsets.waf_ipsets_alb_ipv4_arn
alb_ipsets_v6 = module.waf_ipsets.waf_ipsets_alb_ipv6_arn
bucket = "aws-waf-logs-api-server-prd-blah-blah"
}
module "waf_ipsets" {
source = "../../modules/waf_ipsets"
prefix = local.prefix
name = "ip"
}
module "waf_cf" {
source = "../../modules/waf_cf"
prefix = local.prefix
name = "waf-teacher"
metric_name = "waf-teacher"
cf_ipsets_v4 = module.waf_ipsets.waf_ipsets_cf_ipv4_arn
cf_ipsets_v6 = module.waf_ipsets.waf_ipsets_cf_ipv6_arn
bucket = "aws-waf-logs-teacher-prd-blah-blah"
}
resource "aws_wafv2_web_acl_association" "api_server_waf" {
resource_arn = module.hoge_hoge_alb.alb_arn
web_acl_arn = module.waf_alb.waf_arn
}
# CloudFront associated with WAF(※Module is not listed here)
module "cloudfront_waf" {
source = "../../modules/cloudfront_spa_cdn"
prefix = local.prefix
name = "spa-frontend"
cloudfront_fqdn = local.hoge_teacher_web_frontend_fqdn
zone_id = module.route53_zone.zone_id
web_acl_id = module.waf_teacher.waf_arn
}
# ALB associated with WAF(※Module is not listed here)
module "hoge_hoge_alb" {
source = "../../modules/alb"
prefix = local.prefix
name = "api-alb"
vpc_id = module.main_vpc.vpc_id
zone_id = module.route53_zone.zone_id
alb_subnets = module.main_vpc.public_subnets
alb_fqdn = local.hoge_study_api_alb_fqdn
target_group_port = local.hoge_study_api_server_container_port
target_group_health_check_path = local.hoge_study_api_server_health_check_path
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment