devotica-labs/terraform-aws-wafv2
GitHub: devotica-labs/terraform-aws-wafv2
面向金融科技场景的 AWS WAFv2 Web ACL Terraform 模块,提供预置托管规则与速率限制以快速实现边缘安全防护。
Stars: 0 | Forks: 0
# terraform-aws-wafv2
[](https://github.com/devotica-labs/terraform-aws-wafv2/actions/workflows/ci.yml)
[](https://github.com/devotica-labs/terraform-aws-wafv2/actions/workflows/release.yml)
[](LICENSE)
## 介绍
用于 AWS **WAFv2 Web ACL** 的 Terraform module —— 即公共边缘的 Web 应用防火墙。它提供了一套自带的、适用于金融科技的默认规则集,可附加到 REGIONAL 资源(ALB / API Gateway / AppSync),或为 CloudFront 分发暴露其 ARN。
它不是一个可以随意传递规则的引擎,而是为边缘至关重要的规则类型提供了专注的输入项:AWS 托管规则组、速率限制、IP 允许/阻止集以及地理位置匹配。
## 用法
```
module "wafv2" {
source = "devotica-labs/wafv2/aws"
version = "~> 0.1"
namespace = "dvtca"
stage = "prod"
name = "edge"
scope = "REGIONAL"
# Attach to the public ALB.
association_resource_arns = [module.alb.alb_arn]
# Defaults: AWS managed baseline (Common, KnownBadInputs, SQLi, IP reputation)
# in block mode + a 2000-req/5-min rate limit + CloudWatch metrics.
tags = {
Environment = "production"
Project = "edge"
Owner = "platform@example.com"
CostCenter = "PLATFORM"
ManagedBy = "Terraform"
}
}
```
## 示例
- [`examples/basic`](examples/basic/main.tf) — ALB 上的托管规则 + 速率限制基线。
- [`examples/complete`](examples/complete/main.tf) — 每个规则的覆盖设置、计数模式的规则组、更严格的速率限制、IP 允许/阻止集、地理封锁以及带有脱敏 header 的 Firehose 日志记录。
## 重要的默认设置
在 [`variables.tf`](variables.tf) 中标注了 `# Devotica fintech default`:
- **托管规则基线,阻止模式** — `AWSManagedRulesCommonRuleSet`、`KnownBadInputsRuleSet`、`SQLiRuleSet`、`AmazonIpReputationList`,全部处于阻止模式。在调试时可将每个规则覆盖为 `count`,或添加更多规则组。
- **开启速率限制** — 每个 IP 在 5 分钟窗口内 2000 次请求,超出即阻止。设置 `rate_limit = null` 可禁用。
- **`default_action = allow`** — WAF 通过规则阻止已知的恶意流量;仅在明确的白名单策略下才切换为 `block`。
- **开启指标 + 采样请求** — 每个规则和 ACL 都会发出 CloudWatch 指标,并保留请求样本以供调查。
一个 `check` 块确保规则的优先级在托管组、速率限制、IP 集和地理规则中保持唯一。
## 这如何融入 Devotica 目录
```
internet
│
▼
terraform-aws-wafv2 (Web ACL: managed rules + rate limit + IP/geo)
│ associates with (REGIONAL) │ or web_acl_id (CLOUDFRONT)
▼ ▼
terraform-aws-alb CloudFront distribution
│
▼
terraform-aws-ecs-fargate / eks workloads
```
将 Web ACL 附加到 `terraform-aws-alb` 的 ARN (`association_resource_arns`),或者将 `web_acl_arn` 传递给 CloudFront 分发的 `web_acl_id`。将日志流式传输到 `aws-waf-logs-*` CloudWatch 日志组 / Firehose / S3 存储桶。
## Makefile 目标
```
make init # terraform init (no backend)
make validate # terraform fmt -check + validate
make lint # tflint
make test # terraform test (unit + contract, against Terraform 1.9.5)
make readme # regenerate the terraform-docs section of README.md
```

由 `.github/workflows/architecture-diagram.yml` 在每次推送到 main 分支时生成。请勿手动编辑此图像 —— 修改 `examples/complete/` 中的 Terraform 代码,机器人会自动重新生成它。
## 治理
- CI 运行来自 `devotica-labs/terraform-shared-config` 的中央可重用工作流:fmt、validate、tflint、tfsec/trivy、gitleaks、terraform-docs、针对 `devotica-labs/terraform-policies` 的 conftest、terraform test、checkov 以及示例构建。
- 版本由 `release-please` 基于 Conventional Commits 进行发布。每个版本都通过 cosign 进行无密钥签名,并附带 CycloneDX SBOM。
- 一旦 CI 通过,Dependabot PR 将自动批准并自动合并。
## 用法
### 基础
```
# ---------------------------------------------------------------------------
# Provider block — 对 CI 友好的 skip flags + non-AWS-shaped placeholder creds。
# ---------------------------------------------------------------------------
provider "aws" {
region = "ap-south-1"
access_key = "not-a-real-aws-key"
secret_key = "not-a-real-aws-secret"
skip_credentials_validation = true
skip_metadata_api_check = true
skip_requesting_account_id = true
}
# 开发期间使用 local path。
# 首次发布后更改为 Registry source:
# source = "devotica-labs/wafv2/aws"
# version = "~> 0.1"
module "wafv2" {
source = "../.."
# Web ACL name composes to: dvtca-sandbox-edge
namespace = "dvtca"
stage = "sandbox"
name = "edge"
scope = "REGIONAL"
# Attach to a public ALB (terraform-aws-alb output).
association_resource_arns = [
"arn:aws:elasticloadbalancing:ap-south-1:111122223333:loadbalancer/app/dvtca-sandbox/0123456789abcdef",
]
# Fintech defaults cover the rest: AWS managed rule baseline (Common,
# KnownBadInputs, SQLi, IP reputation) in block mode, a 2000-req/5-min
# rate limit, and CloudWatch metrics + sampled requests on.
tags = {
Environment = "sandbox"
Project = "terraform-aws-wafv2"
Owner = "platform@devotica.com"
CostCenter = "PLATFORM-OSS"
ManagedBy = "Terraform"
Repo = "https://github.com/devotica-labs/terraform-aws-wafv2"
}
}
```
### 完整
```
# ---------------------------------------------------------------------------
# Provider block — 对 CI 友好的 skip flags + non-AWS-shaped placeholder creds。
# ---------------------------------------------------------------------------
provider "aws" {
region = "ap-south-1"
access_key = "not-a-real-aws-key"
secret_key = "not-a-real-aws-secret"
skip_credentials_validation = true
skip_metadata_api_check = true
skip_requesting_account_id = true
}
# 开发期间使用 local path。
# 首次发布后更改为 Registry source:
# source = "devotica-labs/wafv2/aws"
# version = "~> 0.1"
module "wafv2" {
source = "../.."
# Web ACL name composes to: dvtca-aps1-prod-payments
namespace = "dvtca"
environment = "aps1"
stage = "prod"
name = "payments"
scope = "REGIONAL"
# Managed rule baseline, with one in count mode and a per-rule override.
managed_rule_groups = [
{
name = "AWSManagedRulesCommonRuleSet"
priority = 10
# Let large request bodies through (the API uploads documents).
rule_action_overrides = {
SizeRestrictions_BODY = "count"
}
},
{ name = "AWSManagedRulesKnownBadInputsRuleSet", priority = 20 },
{ name = "AWSManagedRulesSQLiRuleSet", priority = 30 },
{ name = "AWSManagedRulesAmazonIpReputationList", priority = 40 },
# Observe-only while tuning.
{ name = "AWSManagedRulesLinuxRuleSet", priority = 50, count_only = true },
]
# Tighter rate limit for the payments edge.
rate_limit = {
limit = 1000
priority = 100
}
# Always allow the office/VPN ranges; block a known-bad set.
ip_allow_list = {
addresses = ["203.0.113.0/24"]
priority = 1
}
ip_block_list = {
addresses = ["198.51.100.7/32"]
priority = 2
}
# Block sanctioned jurisdictions.
geo_block = {
country_codes = ["KP", "IR", "SY", "CU"]
priority = 5
}
# Stream logs to a Firehose (name must start with aws-waf-logs-), redacting
# the Authorization header.
log_destination_configs = [
"arn:aws:firehose:ap-south-1:111122223333:deliverystream/aws-waf-logs-payments",
]
redacted_fields = [
{ single_header = ["authorization"] },
]
# Attach to the public ALB.
association_resource_arns = [
"arn:aws:elasticloadbalancing:ap-south-1:111122223333:loadbalancer/app/dvtca-prod-payments/0123456789abcdef",
]
tags = {
Environment = "production"
Project = "payments"
Owner = "platform@devotica.com"
CostCenter = "PLATFORM"
ManagedBy = "Terraform"
Repo = "https://github.com/devotica-labs/terraform-aws-wafv2"
}
}
```
## 要求
| 名称 | 版本 |
|------|---------|
| [terraform](#requirement\_terraform) | >= 1.5.0 |
| [aws](#requirement\_aws) | >= 5.0.0 |
## Providers
| 名称 | 版本 |
|------|---------|
| [aws](#provider\_aws) | >= 5.0.0 |
## 资源
| 名称 | 类型 |
|------|------|
| [aws_wafv2_ip_set.allow](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/wafv2_ip_set) | resource |
| [aws_wafv2_ip_set.block](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/wafv2_ip_set) | resource |
| [aws_wafv2_web_acl.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/wafv2_web_acl) | resource |
| [aws_wafv2_web_acl_association.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/wafv2_web_acl_association) | resource |
| [aws_wafv2_web_acl_logging_configuration.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/wafv2_web_acl_logging_configuration) | resource |
## 输入
| 名称 | 描述 | 类型 | 默认值 | 必填 |
|------|-------------|------|---------|:--------:|
| [association\_resource\_arns](#input\_association\_resource\_arns) | 仅限 REGIONAL:要与此 Web ACL 关联的资源(例如 ALB)的 ARN。对于 CloudFront,请在分发上设置 web\_acl\_id。 | `list(string)` | `[]` | no |
| [attributes](#input\_attributes) | 附加到 id 后的额外属性(例如 ["workers"])。 | `list(string)` | `[]` | no |
| [cloudwatch\_metrics\_enabled](#input\_cloudwatch\_metrics\_enabled) | 为 Web ACL 及其每个规则发出 CloudWatch 指标。 | `bool` | `true` | no |
| [default\_action](#input\_default\_action) | 对于不匹配任何规则的请求采取的操作:允许或阻止。金融科技的默认设置是 allow —— 规则会阻止已知的恶意流量;仅在白名单策略下才切换为 block。 | `string` | `"allow"` | no |
| [delimiter](#input\_delimiter) | 连接 id 各段的分隔符。 | `string` | `"-"` | no |
| [description](#input\_description) | Web ACL 的描述。默认为组合的名称。 | `string` | `null` | no |
| [enabled](#input\_enabled) | 设置为 false 可使此 module 成为空操作(不创建任何资源)。 | `bool` | `true` | no |
| [environment](#input\_environment) | 环境段(例如简短的区域代码)。 | `string` | `null` | no |
| [geo\_allow](#input\_geo\_allow) | 仅允许这些国家/地区 —— 阻止所有其他请求(default\_action 应保持 allow;此规则通过 NOT 匹配阻止未列出的国家/地区)。 |
object({
country_codes = list(string)
priority = number
}) | `null` | no |
| [geo\_block](#input\_geo\_block) | 阻止来自这些 ISO-3166 国家/地区代码的请求(例如 ["KP","IR"])。 | object({
country_codes = list(string)
priority = number
}) | `null` | no |
| [id\_length\_limit](#input\_id\_length\_limit) | 将组合的 id 截断为最多此字符数。0 表示无限制。 | `number` | `0` | no |
| [ip\_allow\_list](#input\_ip\_allow\_list) | 创建一个 IP 集以及一个允许这些 CIDR 的规则(在给定的优先级下先于托管规则进行评估)。 | object({
addresses = list(string)
priority = number
ip_version = optional(string, "IPV4")
}) | `null` | no |
| [ip\_block\_list](#input\_ip\_block\_list) | 创建一个 IP 集以及一个阻止这些 CIDR 的规则。 | object({
addresses = list(string)
priority = number
ip_version = optional(string, "IPV4")
}) | `null` | no |
| [label\_order](#input\_label\_order) | 用于构建 id 的标签段顺序。允许的键:namespace、environment、stage、name、attributes。 | `list(string)` | [| no | | [label\_value\_case](#input\_label\_value\_case) | 应用于组合 id 的大小写:lower、upper 或 none。 | `string` | `"lower"` | no | | [log\_destination\_configs](#input\_log\_destination\_configs) | 日志记录目标的 ARN(CloudWatch 日志组 / Kinesis Firehose / S3)—— 每个名称必须以 `aws-waf-logs-` 开头。为空将禁用日志记录。 | `list(string)` | `[]` | no | | [managed\_rule\_groups](#input\_managed\_rule\_groups) | 要附加的 AWS(或市场)托管规则组。默认为金融科技基线:Common、KnownBadInputs、SQLi 和 Amazon IP 信誉列表 —— 全部处于阻止模式。 |
"namespace",
"environment",
"stage",
"name",
"attributes"
]
list(object({
name = string
vendor_name = optional(string, "AWS")
priority = number
# Set true to run the group in count mode (observe only, no blocking).
count_only = optional(bool, false)
# Per-rule action overrides within the group (rule_name => "count"|"allow"|"block").
rule_action_overrides = optional(map(string), {})
})) | [| no | | [name](#input\_name) | 解决方案 / 基础名称(例如 "app")。 | `string` | `null` | no | | [namespace](#input\_namespace) | 命名空间 / 组织前缀(例如 "dvtca")。 | `string` | `null` | no | | [rate\_limit](#input\_rate\_limit) | 基于速率的规则:阻止在任何 5 分钟窗口内超过 `limit` 次请求的 IP。设置为 null 可禁用。 |
{
"name": "AWSManagedRulesCommonRuleSet",
"priority": 10
},
{
"name": "AWSManagedRulesKnownBadInputsRuleSet",
"priority": 20
},
{
"name": "AWSManagedRulesSQLiRuleSet",
"priority": 30
},
{
"name": "AWSManagedRulesAmazonIpReputationList",
"priority": 40
}
]
object({
limit = optional(number, 2000)
priority = optional(number, 100)
aggregate_key_type = optional(string, "IP")
action = optional(string, "block")
}) | `{}` | no |
| [redacted\_fields](#input\_redacted\_fields) | 日志中脱敏的字段(例如 Authorization header)。 | list(object({
method = optional(bool, false)
query_string = optional(bool, false)
uri_path = optional(bool, false)
single_header = optional(list(string))
})) | `[]` | no |
| [regex\_replace\_chars](#input\_regex\_replace\_chars) | 从每个 id 段中剥离的字符正则表达式(格式为 /.../)。 | `string` |"/[^-a-zA-Z0-9]/"` | no |
| [sampled\_requests\_enabled](#input\_sampled\_requests\_enabled) | 为每个规则存储已检查请求的样本(可在控制台中查看)。 | `bool` | `true` | no |
| [scope](#input\_scope) | REGIONAL(ALB / API Gateway / AppSync)或 CLOUDFRONT。CLOUDFRONT Web ACL 必须在 us-east-1 中创建。 | `string` | `"REGIONAL"` | no |
| [stage](#input\_stage) | 阶段 / 账户段(例如 "prod")。 | `string` | `null` | no |
| [tags](#input\_tags) | 合并到每个可标记资源的额外标签。 | `map(string)` | `{}` | no |
## 输出
| 名称 | 描述 |
|------|-------------|
| [ip\_set\_allow\_arn](#output\_ip\_set\_allow\_arn) | 允许列表 IP 集的 ARN(如果没有则为 null)。 |
| [ip\_set\_block\_arn](#output\_ip\_set\_block\_arn) | 阻止列表 IP 集的 ARN(如果没有则为 null)。 |
| [logging\_configuration\_id](#output\_logging\_configuration\_id) | Web ACL 日志记录配置的 ID(如果禁用日志记录则为 null)。 |
| [web\_acl\_arn](#output\_web\_acl\_arn) | WAFv2 Web ACL 的 ARN。对于 CloudFront,将此项设置为分发的 web\_acl\_id。 |
| [web\_acl\_capacity](#output\_web\_acl\_capacity) | 规则消耗的 Web ACL 容量单位 (WCU)。 |
| [web\_acl\_id](#output\_web\_acl\_id) | WAFv2 Web ACL 的 ID。 |
| [web\_acl\_name](#output\_web\_acl\_name) | Web ACL 的名称。 |
## 相关项目
- [terraform-aws-alb](https://github.com/devotica-labs/terraform-aws-alb) — 此 Web ACL 所保护的公共 ALB。
## 参考
- [AWS WAF Web ACLs](https://docs.aws.amazon.com/waf/latest/developerguide/web-acl.html)
- [AWS Managed Rule Groups](https://docs.aws.amazon.com/waf/latest/developerguide/aws-managed-rule-groups-list.html)
- [Rate-based rules](https://docs.aws.amazon.com/waf/latest/developerguide/waf-rule-statement-type-rate-based.html)
## 许可证
Apache-2.0。详见 [`LICENSE`](LICENSE) 和 [`NOTICE`](NOTICE)。标签:AWS, DPI, ECS, Terraform, WAF, WAF规则