Skip to content

tomarv2/terraform-aws-waf

Repository files navigation

Terraform module for Amazon WAFv2

Versions

  • Module tested for Terraform 1.0.1.
  • AWS provider version 4.35.
  • main branch: Provider versions not pinned to keep up with Terraform releases.
  • tags releases: Tags are pinned with versions (use in your releases).

Usage

Option 1:

terrafrom init
terraform plan -var='teamid=tryme' -var='prjid=project1'
terraform apply -var='teamid=tryme' -var='prjid=project1'
terraform destroy -var='teamid=tryme' -var='prjid=project1'

Note: With this option please take care of remote state storage

Option 2:

Recommended method (stores remote state in remote backend(S3, Azure storage, or Google bucket) using prjid and teamid to create directory structure):
  • Create python 3.8+ virtual environment
python3 -m venv <venv name>
  • Install package:
pip install tfremote --upgrade
  • Set below environment variables:
export TF_AWS_BUCKET=<remote state bucket name>
export TF_AWS_BUCKET_REGION=us-west-2
export TF_AWS_PROFILE=<profile from ~/.ws/credentials>

or

  • Set below environment variables:
export TF_AWS_BUCKET=<remote state bucket name>
export TF_AWS_BUCKET_REGION=us-west-2
export AWS_ACCESS_KEY_ID=<aws_access_key_id>
export AWS_SECRET_ACCESS_KEY=<aws_secret_access_key>
  • Updated examples directory with required values.

  • Run and verify the output before deploying:

tf -c=aws plan -var='teamid=foo' -var='prjid=bar'
  • Run below to deploy:
tf -c=aws apply -var='teamid=foo' -var='prjid=bar'
  • Run below to destroy:
tf -c=aws destroy -var='teamid=foo' -var='prjid=bar'

Note: Read more on tfremote

WAF with custom IP and AND rule
terraform {
  required_version = ">= 1.0.1"
  required_providers {
    aws = {
      version = "~> 4.35"
    }
  }
}

provider "aws" {
  region = var.region
}

module "common" {
  source = "git::[email protected]:tomarv2/terraform-global.git//common?ref=v0.0.1"
}

#####
# IP set resources
#####
resource "aws_wafv2_ip_set" "custom_ip_set" {
  name = "${var.name_prefix}-custom-ip-set"

  scope              = "REGIONAL"
  ip_address_version = "IPV4"

  addresses = module.common.cidr_for_sec_grp_access
}

module "waf" {
  source = "../.."

  allow_default_action = false
  scope = "REGIONAL"
  alb_arn = "arn:aws:elasticloadbalancing:us-west-2:12345789012:loadbalancer/app/demo-app/abcdef"
  visibility_config = {
    cloudwatch_metrics_enabled = false
    metric_name                = "${var.name_prefix}-waf-setup-waf-main-metrics"
    sampled_requests_enabled   = false
  }

  rules = [
    # Custom ip addresses
    {
      name     = "allow-custom-ip-set"
      priority = 1
      action   = "allow"
      ip_set_reference_statement = {
        arn = aws_wafv2_ip_set.custom_ip_set.arn
      }
      visibility_config = {
        cloudwatch_metrics_enabled = false
        metric_name                = "allow-custom-ip-set-metric"
        sampled_requests_enabled   = false
      }
    },
    {
      ### AND rule
      name     = "allow-specific-uri-path-from-webhook"
      priority = 5
      action   = "allow"
      and_statement = {
        statements = [ # 2 or more statements are required for AND
          {
            byte_match_statement = {
              field_to_match = {
                uri_path = "{}"
              }
              positional_constraint = "STARTS_WITH"
              search_string         = "/webhook"
              priority              = 0
              type                  = "NONE"
            }
          },
          {
            byte_match_statement = {
              field_to_match = {
                single_header = {"name": "x-demo"}
              }
              positional_constraint = "EXACTLY"
              search_string         = "hello_world"
              priority              = 0
              type                  = "NONE"
            }
          }
        ]
      }
      visibility_config = {
        cloudwatch_metrics_enabled = false
        sampled_requests_enabled   = false
      }
    }
  ]
  teamid = var.teamid
  prjid = var.prjid
}

Please refer to examples directory link for references.

Requirements

Name Version
terraform >= 1.0.1
aws ~> 4.35

Providers

Name Version
aws ~> 4.35

Modules

No modules.

Resources

Name Type
aws_wafv2_web_acl.main resource
aws_wafv2_web_acl_association.main resource

Inputs

Name Description Type Default Required
alb_arn Application Load Balancer ARN string null no
allow_default_action Set to true for WAF to allow requests by default. Set to false for WAF to block requests by default. bool false no
create_alb_association Whether to create alb association with WAF web acl bool true no
create_logging_configuration Whether to create logging configuration in order start logging from a WAFv2 Web ACL to Amazon Kinesis Data Firehose. bool false no
description A friendly description of the WebACL string null no
enabled Whether to create the resources. Set to false to prevent the module from creating any resources bool true no
extra_tags Additional tags to associate map(string) {} no
log_destination_configs The Amazon Kinesis Data Firehose Amazon Resource Name (ARNs) that you want to associate with the web ACL. Currently, only 1 ARN is supported. list(string) [] no
logging_filter A configuration block that specifies which web requests are kept in the logs and which are dropped. You can filter on the rule action and on the web request labels that were applied by matching rules during web ACL evaluation. any {} no
name Name used to create resources. string null no
prjid Name of the project/stack e.g: mystack, nifieks, demoaci. Should not be changed after running 'tf apply' any n/a yes
redacted_fields The parts of the request that you want to keep out of the logs. Up to 100 redacted_fields blocks are supported. any [] no
rules List of WAF rules. any [] no
scope Specifies whether this is for an AWS CloudFront distribution or for a regional application. Valid values are CLOUDFRONT or REGIONAL. To work with CloudFront, you must also specify the region us-east-1 (N. Virginia) on the AWS provider. string "REGIONAL" no
teamid Name of the team/group e.g. devops, dataengineering. Should not be changed after running 'tf apply' any n/a yes
visibility_config Visibility config for WAFv2 web acl. https://www.terraform.io/docs/providers/aws/r/wafv2_web_acl.html#visibility-configuration map(string) {} no

Outputs

Name Description
web_acl_arn The ARN of the WAFv2 WebACL.
web_acl_assoc_acl_arn The ARN of the Web ACL attached to the Web ACL Association
web_acl_assoc_id The ID of the Web ACL Association
web_acl_assoc_resource_arn The ARN of the ALB attached to the Web ACL Association
web_acl_capacity The web ACL capacity units (WCUs) currently being used by this web ACL.
web_acl_id The ID of the WAFv2 WebACL.
web_acl_name The name of the WAFv2 WebACL.
web_acl_rule_names List of created rule names