【免费下载链接】aws-cdk-examples
Example projects using the AWS CDK
本篇技术指南以 typescript/waf 示例为对象,讲解如何通过 AWS CDK 以基础设施即代码的方式创建两个 WAFv2 Web ACL:一个用于 CloudFront 分发,一个用于 Application Load Balancer 等 Regional 资源。读完本文,你将掌握 WAF 栈的构建与部署流程、AWS 托管规则组与自定义规则(地理限制、速率限制)的配置写法、CloudFormation Export 导出机制,以及如何把 WAF 关联到 CloudFront 分发与 AppSync API。
示例概览:一份代码,两种作用域
示例的核心思路是创建两个“几乎完全相同”的 WAF 栈,分别服务于两类防护场景:
- waf-cloudfront.ts(
WafCloudFrontStack):创建scope为CLOUDFRONT的 Web ACL,用于 CloudFront 分发; - waf-regional.ts(
WafRegionalStack):创建scope为REGIONAL的 Web ACL,用于 Application Load Balancer、API Gateway、AppSync 等 Regional 资源。
两个栈共用一个makeRules()方法生成规则列表,仅在scope、命名和描述上做了针对性定制。入口文件 app.ts 同时实例化两个栈,并统一指定部署区域为us-east-1:
const app = new cdk.App(); new WafRegionalStack(app, 'WafRegionalStack', {env:{region:"us-east-1"}, description:"WAF Regional"}); new WafCloudFrontStack(app, 'WafCloudFrontStack', {env:{region:"us-east-1"}, description:"WAF CloudFront"});这里有一个关键的 AWS 约束:当scope为CLOUDFRONT时,WAFv2 资源必须创建在 us-east-1(美国东部弗吉尼亚北部)区域。源码注释中对此有明确说明,这也是示例统一使用us-east-1的原因。
注意:示例 README 顶部带有 Experimental 稳定性标记,其基于标记为“Experimental”的 Construct 库编写,可能不随最新破坏性变更同步更新;如果构建失败,可到仓库提交 issue 反馈问题。
环境准备与构建
在示例根目录typescript/waf下依次执行以下命令完成构建:
npm install -g aws-cdk npm install cdk synth- 第一条命令全局安装 AWS CDK CLI;
- 第二条命令安装示例自身的依赖(对应 package.json 中声明的
aws-cdk-lib、constructs、typescript、jest等); - 第三条命令
cdk synth将 CDK 代码合成为 CloudFormation 模板,产物输出到cdk.out目录。
如果想要单独查看某个栈的 YAML 格式模板,可以把栈名作为参数传给cdk synth:
cdk synth WafCloudFrontStack cdk synth WafRegionalStack当前示例的 cdk.json 配置了启动命令npx tsc && npx tsx app.ts,即先由 TypeScript 编译器检查编译,再通过 tsx 直接运行app.ts生成应用定义。需要说明的是:示例代码使用 CDK v2 的aws-cdk-lib导入方式,而 README 中遗留的关联代码片段仍为 CDK v1 风格(@aws-cdk/core),实际使用时请以仓库内 waf-cloudfront.ts 的 v2 写法为准。
部署
在示例目录下执行:
cdk deploy该命令会将栈部署(或重新部署)到你的 AWS 账户。部署完成后,生成的 WAF Web ACL 不会自动挂载到任何资源,需要你手动将 WAF 关联到 CloudFront 或 Load Balancer(关联方式见后文“将 WAF 关联到其他资源”一节)。
WAF 规则详解
AWS 托管规则组:开箱即用的基线防护
示例规则列表以 AWS 托管规则组为主体。在 waf-cloudfront.ts 中,通过listOfRules数组声明了 6 个托管规则组,每个规则组包含name、priority、overrideAction和excludedRules四个字段:
| 规则组名称 | 优先级 | 防护能力 |
|---|---|---|
AWSManagedRulesCommonRuleSet | 10 | 通用规则集,覆盖 OWASP 常见攻击模式 |
AWSManagedRulesAmazonIpReputationList | 20 | AWS 威胁情报 IP 信誉列表 |
AWSManagedRulesKnownBadInputsRuleSet | 30 | 已知恶意输入规则集 |
AWSManagedRulesAnonymousIpList | 40 | 匿名 IP(VPN、代理、Tor 出口节点等) |
AWSManagedRulesLinuxRuleSet | 50 | Linux 操作系统特定攻击 |
AWSManagedRulesUnixRuleSet | 60 | Unix 操作系统特定攻击 |
优先级数字越小执行越靠前,示例中按 10~60 依次排列,保证托管规则先于自定义规则被评估。两个栈的托管规则组列表完全一致,只是作用域不同。
托管规则组会持续更新,可用 AWS CLI 快速查询当前账户可用的完整列表:
aws wafv2 list-available-managed-rule-groups --scope CLOUDFRONT aws wafv2 list-available-managed-rule-groups --scope REGIONAL其中--scope的取值与 Web ACL 的scope一一对应:CLOUDFRONT列出可用于 CloudFront 的规则组,REGIONAL列出可用于 Regional 资源的规则组。查询结果可作为扩充或替换示例规则组列表的依据。
基于国家/地区码的连接限制(GeoMatch)
示例代码内置了一条基于源 IP 地理位置的规则,逻辑是:如果源 IP 不在下面的国家/地区列表中,则阻断该连接。实现方式是notStatement包裹geoMatchStatement,即“不在名单内 → 阻断”。
let ruleGeoMatch: wafv2.CfnWebACL.RuleProperty = { name: 'GeoMatch', priority: 0, action: { block: {} // To disable, change to *count* }, statement: { notStatement: { statement: { geoMatchStatement: { // block connection if source not in the below country list countryCodes: [ "AR", // Argentina "BO", // Bolivia "BR", // Brazil "CL", // Chile "CO", // Colombia "EC", // Ecuador "FK", // Falkland Islands "GF", // French Guiana "GY", // Guiana "GY", // Guyana "PY", // Paraguay "PE", // Peru "SR", // Suriname "UY", // Uruguay "VE", // Venezuela ] } } } }, ... };这段代码(见 waf-cloudfront.ts)默认放行南美洲区域的国家/地区(阿根廷、玻利维亚、巴西、智利、哥伦比亚、厄瓜多尔、秘鲁、乌拉圭、委内瑞拉等),其余地区的请求一律block。源码注释给出了一个重要的调试技巧:如需临时观察命中情况而非直接阻断,把block: {}改为count: {},WAF 会转为计数模式,仅统计命中请求而不断言拒绝。
countryCodes使用 ISO 3166-1 alpha-2 国家/地区代码,你可以按业务需求自由增删列表项。
基于请求速率的连接限制(Rate Limit)
示例还内置了一条速率限制规则,默认行为是:单个 IP 在 5 分钟窗口内请求数超过 100 次即被阻断。
let ruleLimitRequests100: wafv2.CfnWebACL.RuleProperty = { name: 'LimitRequests100', priority: 1, action: { block: {} // To disable, change to *count* }, statement: { rateBasedStatement: { limit: 100, aggregateKeyType: "IP" } }, ... };该规则(见 waf-cloudfront.ts)使用rateBasedStatement,核心参数说明如下:
limit:单 IP 在评估窗口内允许的最大请求数,示例设为 100;aggregateKeyType: "IP":按源 IP 维度聚合统计请求速率。
源码注释对速率限制的语义有精确描述:limit 是单个 IP 在五分钟周期内允许的最大请求数;该值会被持续评估,一旦达到上限请求即被阻断,当速率回落到限制以下后 IP 会被自动解除阻断。也就是说这是一个动态评估、自动恢复的限流机制,无需人工干预解封。同样的,想先观察再启用,可把action从block改为count。
makeRules():规则工厂方法
两个栈的规则构建逻辑集中在makeRules()方法中(waf-cloudfront.ts 与 waf-regional.ts),输入listOfRules数组,返回可直接挂到 Web ACL 上的RuleProperty[]。其处理流程为:
- 遍历托管规则组数组,为每个规则组构造
managedRuleGroupStatement(vendorName固定为"AWS"); - 设置
overrideAction: { none: {} },表示不覆盖托管规则组的默认动作; - 为每条规则开启
visibilityConfig,即sampledRequestsEnabled(采样请求)与cloudWatchMetricsEnabled(CloudWatch 指标)均设为true,metricName与规则同名,便于在 CloudWatch 中按规则维度观测; - 依次追加
GeoMatch(priority 0)与LimitRequests100(priority 1)两条自定义规则; - 返回完整规则数组。
Web ACL 本身在 waf-cloudfront.ts 中创建:
const wafAclCloudFront = new wafv2.CfnWebACL(this, "WafCloudFront", { defaultAction: { allow: {} }, scope: "CLOUDFRONT", visibilityConfig: { cloudWatchMetricsEnabled: true, metricName: "waf-cloudfront", sampledRequestsEnabled: true }, description: "WAFv2 ACL for CloudFront", name: "waf-cloudfront", rules: this.makeRules(managedRules), });关键属性说明:
defaultAction: { allow: {} }:未命中任何规则的请求默认放行(Web ACL 默认只拦截“命中规则”的流量,属于白名单/黑名单之外的兜底策略);scope:CLOUDFRONT或REGIONAL,决定 Web ACL 可关联的资源类型与部署区域要求;visibilityConfig:开启 Web ACL 级别的 CloudWatch 指标与请求采样;rules:即makeRules()产出的全部规则。
创建完成后,代码还为 Web ACL 打上了三组标签(Tag):Name=waf-cloudfront、Purpose=CloudFront、CreatedBy=CloudFormation(见 waf-cloudfront.ts),方便在控制台与成本报告中识别资源归属。waf-regional.ts中的结构完全一致,仅将scope换成REGIONAL、命名改为waf-regional。
将 WAF 关联到其他资源
通过 CloudFormation Export 导出 WAF ARN
每个 WAF 栈都会产生一个 CloudFormation Export,把 Web ACL 的 ARN 导出到账户级别,供其他栈跨栈引用:
WafCloudFrontStack:WafAclCloudFrontArnWafRegionalStack:WafAclRegionalArn
导出逻辑在 waf-cloudfront.ts 中实现:
new cdk.CfnOutput(this, "wafAclCloudFrontArn", { value: wafAclCloudFront.attrArn, description: " WAF CloudFront arn", exportName: "WafCloudFrontStack:WafAclCloudFrontArn" });attrArn是CfnWebACL暴露的 CloudFormation 属性,可直接获得 Web ACL 的 ARN。其他栈通过cdk.Fn.importValue()按导出名导入即可使用。
关联到 CloudFront 分发
在创建 CloudFront 分发的栈中,先导入 WAF ARN,再通过webACLId参数挂载:
import * as cdk from '@aws-cdk/core'; WafAclCloudFrontArn = cdk.Fn.importValue("WafCloudFrontStack:WafAclCloudFrontArn"); new cloudfront.CloudFrontWebDistribution(this, 'frontendDistribution', { ... webACLId: wafAclCloudFrontArn });webACLId接受 WAF(含 WAFv2)Web ACL 的 ARN。注意上述片段为 README 中的 CDK v1 写法,实际使用 CDK v2 时应通过aws-cdk-lib的Fn.importValue与cloudfront.Distribution(或CloudFrontWebDistribution)完成同等配置。
关联到 AppSync GraphQL API
Regional 类型的 WAF 可以用CfnWebACLAssociation关联到 AppSync GraphQL API。README 给出了完整模式:先导入 Regional WAF 的 ARN,再创建关联资源:
import * as cdk from '@aws-cdk/core'; import * as appsync from '@aws-cdk/aws-appsync' WafAclAppSyncArn = cdk.Fn.importValue("WafRegionalStack:WafAclAppSyncArn"); const gql = new appsync.GraphqlApi(this, 'NeptuneGraphQLApi', { ... }); new wafv2.CfnWebACLAssociation(this, 'NeptuneGraphQLApiWaf', { resourceArn: gql.arn, webAclArn: wafAclAppSyncArn });CfnWebACLAssociation接收两个关键参数:
resourceArn:被防护资源的 ARN,这里取 GraphQL API 的arn;webAclArn:Web ACL 的 ARN,这里导入自WafRegionalStack:WafAclAppSyncArn。
同样的关联方式也适用于 Application Load Balancer、API Gateway REST API、Amazon Cognito 用户池等支持 WAFv2 关联的 Regional 资源,只需把resourceArn替换为对应资源的 ARN 即可。
使用注意事项
- 区域约束:
CLOUDFRONT作用域的 Web ACL 必须在 us-east-1 创建;Regional 类型的 WAF 也应与目标资源同区域。 - 默认放行策略:Web ACL 的
defaultAction为allow,实际拦截能力完全由规则决定;上线前建议先把block临时改为count,观察 CloudWatch 指标与请求采样确认无误后再启用阻断。 - Experimental 状态:示例基于 Experimental 标记的构造库编写,若遇到构建失败,建议核对 package.json 中的
aws-cdk-lib版本与本地环境,或向仓库提交 issue。 - 手动关联:
cdk deploy只创建 WAF 本身,不自动挂载到 CloudFront 或负载均衡器,关联动作需在部署完成后按上文方式在目标资源栈中完成。
通过本文的配置,你可以在同一套代码里同时获得 CloudFront 与 Regional 两种防护能力:托管规则组覆盖常见攻击面,GeoMatch 实现区域封禁,速率限制抵御单 IP 高频请求,CloudFormation Export 则让 WAF 可以跨栈复用到任意目标资源上。
【免费下载链接】aws-cdk-examples
Example projects using the AWS CDK
相关推荐
aws-cdk-examples 实战:用 AWS CDK(TypeScript)在现有 VPC 中创建 MySQL RDS 实例
aws cdk examples 实战:用 AWS CDK(TypeScript)在现有 VPC 中创建 MySQL RDS 实例 导读 本文以 aws cdk
AWS CDK 实战:用 CloudFront Functions 在边缘侧改造请求与响应(aws-cdk-examples 之 demo-cloudfront-functions 详解)
AWS CDK 实战:用 CloudFront Functions 在边缘侧改造请求与响应(aws cdk examples 之 demo cloudfront
AWS CDK 实战:用 S3 + CloudFront + Route53 + ACM 搭建全链路 HTTPS 静态网站(aws-cdk-examples static-site 示例深度解析)
AWS CDK 实战:用 S3 + CloudFront + Route53 + ACM 搭建全链路 HTTPS 静态网站(aws cdk examples s
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考