Skip to content

Terraform Module For Configures an AWS Web Application Firewall.

License

Notifications You must be signed in to change notification settings

oozou/terraform-aws-waf

Repository files navigation

AWS WAF Terraform Module

Terraform module with create vpc and subnet resources on AWS.

Custom Rules Usage

waf_custom_rules = [
  {
    name            = "match-originate-from-an-ip-addresses-in-rule" #
    priority        = 10                                             ##
    action          = "count"                                        # {count, allow, block}
    expression_type = "match-statement"                              ##
    statements = [                                                   ##
      {
        inspect    = "originate-from-an-ip-addresses-in" ##
        ip_set_key = "oozou-vpn-ipv4-set"                # Match above
      }
    ]
  },
  {
    name            = "match-originate-from-a-country-in-rule" #
    priority        = 20                                       ##
    action          = "count"                                  # {count, allow, block}
    expression_type = "match-statement"                        ##
    statements = [                                             ##
      {
        inspect       = "originate-from-a-country-in" ##
        country_codes = ["TH"]
      }
    ]
  },
  {
    name            = "match-has-a-label-rule" #
    priority        = 30                       ##
    action          = "count"                  # {count, allow, block}
    expression_type = "match-statement"        ##
    statements = [                             ##
      {
        inspect = "has-a-label" ##
        scope   = "LABEL"
        key     = "awswaf:managed:aws:core-rule-set:GenericLFI_URIPath"
      }
    ]
  },
  /* -------------------------------------------------------------------------- */
  /*                       Strgin Match Condition Example                       */
  /* -------------------------------------------------------------------------- */
  {
    name            = "match-request-component-single-header-rule" #
    priority        = 40                                           ##
    action          = "count"                                      # {count, allow, block}
    expression_type = "match-statement"                            ##
    statements = [                                                 ##
      {
        inspect               = "single-header" ##
        header_name           = "host"
        positional_constraint = "CONTAINS"
        search_string         = "STRING_TO_SEARCH"
      }
    ]
  },
  {
    ## Not available (just for test case)
    name            = "match-request-component-all-headers-rule" #
    priority        = 41                                         ##
    action          = "count"                                    # {count, allow, block}
    expression_type = "match-statement"                          ##
    statements = [                                               ##
      {
        inspect               = "all-headers" ##
        positional_constraint = "CONTAINS"
        search_string         = "STRING_TO_SEARCH"
      }
    ]
  },
  {
    ## Not available (just for test case)
    name            = "match-request-component-cookies-rule" #
    priority        = 42                                     ##
    action          = "count"                                # {count, allow, block}
    expression_type = "match-statement"                      ##
    statements = [                                           ##
      {
        inspect               = "cookies" ##
        positional_constraint = "CONTAINS"
        search_string         = "STRING_TO_SEARCH"
      }
    ]
  },
  {
    name            = "match-request-component-single-query-parameter-rule" #
    priority        = 43                                                    ##
    action          = "count"                                               # {count, allow, block}
    expression_type = "match-statement"                                     ##
    statements = [                                                          ##
      {
        inspect               = "single-query-parameter" ##
        positional_constraint = "CONTAINS"
        search_string         = "STRING_TO_SEARCH"
        query_string_name     = "user"
      }
    ]
  },
  {
    name            = "match-request-component-all-query-parameters-rule" #
    priority        = 44                                                  ##
    action          = "count"                                             # {count, allow, block}
    expression_type = "match-statement"                                   ##
    statements = [                                                        ##
      {
        inspect               = "all-query-parameters" ##
        positional_constraint = "CONTAINS"
        search_string         = "STRING_TO_SEARCH"
      }
    ]
  },
  {
    name            = "match-request-component-uri-path-rule" #
    priority        = 45                                      ##
    action          = "count"                                 # {count, allow, block}
    expression_type = "match-statement"                       ##
    statements = [                                            ##
      {
        inspect               = "uri-path" ##
        positional_constraint = "CONTAINS"
        search_string         = "STRING_TO_SEARCH"
      }
    ]
  },
  {
    name            = "match-request-component-query-string-rule" #
    priority        = 46                                          ##
    action          = "count"                                     # {count, allow, block}
    expression_type = "match-statement"                           ##
    statements = [                                                ##
      {
        inspect               = "query-string" ##
        positional_constraint = "CONTAINS"
        search_string         = "STRING_TO_SEARCH"
      }
    ]
  },
  ## Not available (just for test case)
  {
    name            = "match-request-component-body-rule" #
    priority        = 47                                  ##
    action          = "count"                             # {count, allow, block}
    expression_type = "match-statement"                   ##
    statements = [                                        ##
      {
        inspect               = "body" ##
        positional_constraint = "CONTAINS"
        search_string         = "STRING_TO_SEARCH"
      }
    ]
  },
  {
    ## Not available (just for test case)
    name            = "match-request-component-json-body-rule" #
    priority        = 48                                       ##
    action          = "count"                                  # {count, allow, block}
    expression_type = "match-statement"                        ##
    statements = [                                             ##
      {
        inspect               = "json-body" ##
        positional_constraint = "CONTAINS"
        search_string         = "STRING_TO_SEARCH"
      }
    ]
  },
  {
    name            = "match-request-component-http-method-rule" #
    priority        = 49                                         ##
    action          = "count"                                    # {count, allow, block}
    expression_type = "match-statement"                          ##
    statements = [                                               ##
      {
        inspect               = "http-method" ##
        positional_constraint = "CONTAINS"
        search_string         = "post"
      }
    ]
  },
  /* -------------------------------------------------------------------------- */
  /*                                And Statement                               */
  /* -------------------------------------------------------------------------- */
  {
    name            = "match-request-component-http-method-rule" #
    priority        = 50                                         ##
    action          = "count"                                    # {count, allow, block}
    expression_type = "and-statements"                           ##
    statements = [                                               ##
      {
        inspect               = "http-method" ##
        is_negated_statement  = false
        positional_constraint = "CONTAINS"
        search_string         = "post"
      },
      {
        inspect               = "single-header" ##
        header_name           = "host"
        is_negated_statement  = true
        positional_constraint = "CONTAINS"
        search_string         = "STRING_TO_SEARCH"
      },
      {
        inspect    = "originate-from-an-ip-addresses-in" ##
        ip_set_key = "oozou-vpn-ipv4-set"
      },
      {
        inspect       = "originate-from-a-country-in" ##
        country_codes = ["TH"]
      }
    ]
  },
]

Requirements

Name Version
terraform >= 1.0.0
aws >= 4.0.0

Providers

Name Version
aws >= 4.0.0

Modules

No modules.

Resources

Name Type
aws_wafv2_ip_set.ipset resource
aws_wafv2_ip_set.this resource
aws_wafv2_web_acl.this resource
aws_wafv2_web_acl_association.this resource

Inputs

Name Description Type Default Required
association_resources ARN of the ALB, CloudFront, Etc to be associated with the WAFv2 ACL. list(string) [] no
cloudwatch_log_kms_key_id The ARN for the KMS encryption key. string null no
cloudwatch_log_retention_in_days Specifies the number of days you want to retain log events Possible values are: 1, 3, 5, 7, 14, 30, 60, 90, 120, 150, 180, 365, 400, 545, 731, 1827, 3653, and 0. If you select 0, the events in the log group are always retained and never expire number 90 no
custom_response_body (optional) Define custom response body list(any) [] no
custom_rules Find the example for these structure any [] no
default_action The action to perform if none of the rules contained in the WebACL match. string "block" no
environment Environment Variable used as a prefix string n/a yes
ip_rate_based_rule A rate-based rule tracks the rate of requests for each originating IP address, and triggers the rule action when the rate exceeds a limit that you specify on the number of requests in any 5-minute time span
object({
name = string
priority = number
action = string
limit = number
})
null no
ip_set To create IP set ex.
ip_sets = {
"oozou-vpn-ipv4-set" = {
ip_addresses = ["127.0.01/32"]
ip_address_version = "IPV4"
},
"oozou-vpn-ipv6-set" = {
ip_addresses = ["2403:6200:88a2:a6f8:2096:9b42:31f8:61fd/128"]
ip_address_version = "IPV6"
}
}
map(object({
ip_addresses = list(string)
ip_address_version = string
}))
{} no
ip_sets_rule A rule to detect web requests coming from particular IP addresses or address ranges.
list(object({
name = string
priority = number
ip_set = list(string)
action = string
ip_address_version = string
}))
[] no
is_create_logging_configuration Whether to create logging configuration in order start logging from a WAFv2 Web ACL to CloudWatch bool true no
is_enable_cloudwatch_metrics The action to perform if none of the rules contained in the WebACL match. bool true no
is_enable_default_rule If true with enable default rule (detail in locals.tf) bool true no
is_enable_sampled_requests Whether AWS WAF should store a sampling of the web requests that match the rules. You can view the sampled requests through the AWS WAF console. bool true 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
managed_rules List of Managed WAF rules.
list(object({
name = string
priority = number
override_action = string
excluded_rules = list(string)
}))
[] no
name A friendly name of the WebACL. string n/a yes
prefix The prefix name of customer to be displayed in AWS console and resource string 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
scope Specifies whether this is for an AWS CloudFront distribution or for a regional application.
Possible 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 n/a yes
tags A mapping of tags to assign to the WAFv2 ACL. map(string) {} no

Outputs

Name Description
web_acl_id The ARN of the WAF WebACL.