使用AWS CDK时如何正确获取WAF的webACLId
获取WAF webACLId 关联CloudFront分发的正确方法
你原有自定义资源实现无法拿到预期结果,核心问题有3个:
- 未配置返回值提取路径,自定义资源不会自动存储SDK接口返回的ACL列表数据,后续无法引用
- 若你使用的是当前主流的WAFv2版本,调用旧版
WAF服务的ListWebACLs接口无法查询到v2版本的ACL资源 - 物理资源ID传入的是固定字符串
'Date.now().toString()',既没有实际执行时间戳生成逻辑,还会因为ID规则不合理触发不必要的资源更新
推荐方案:直接使用CDK内置方法查询(无需自定义资源)
关联CloudFront的WAF必须是部署在us-east-1区域、作用域为CLOUDFRONT的全局ACL,只要你知道目标ACL的名称,直接用CDK自带的fromLookup方法即可获取,稳定性远高于自定义写的查询逻辑:
import * as wafv2 from 'aws-cdk-lib/aws-wafv2'; import * as cloudfront from 'aws-cdk-lib/aws-cloudfront'; import * as origins from 'aws-cdk-lib/aws-cloudfront-origins'; // 查询目标WAFv2 ACL const targetWebAcl = wafv2.WebAcl.fromLookup(this, 'ImportCloudFrontWaf', { name: '替换成你自己的WebACL名称', scope: wafv2.Scope.CLOUDFRONT, }); // 创建CloudFront分发时直接关联 new cloudfront.Distribution(this, 'SiteDistribution', { // WAFv2关联CloudFront需要传入ACL的ARN,不是旧版WAF的短ID webAclId: targetWebAcl.arn, // 其余分发配置按实际需求填写 defaultBehavior: { origin: new origins.HttpOrigin('你的源站地址'), } });
备选方案:修正自定义资源实现
如果确实需要动态拉取ACL列表获取ID,按如下方式修正自定义资源配置即可,注意WAF版本对应正确的服务名:
import * as cr from 'aws-cdk-lib/custom-resources'; import * as iam from 'aws-cdk-lib/aws-iam'; // 给自定义资源配置WAF查询权限 const crRole = new iam.Role(this, 'WafQueryRole', { assumedBy: new iam.ServicePrincipal('lambda.amazonaws.com'), managedPolicies: [iam.ManagedPolicy.fromAwsManagedPolicyName('service-role/AWSLambdaBasicExecutionRole')], inlinePolicies: { WafQuery: new iam.PolicyDocument({ statements: [new iam.PolicyStatement({ actions: ['wafv2:ListWebACLs'], resources: ['*'], })] }) } }); const wafAclQuery = new cr.AwsCustomResource(this, 'QueryWafAclList', { // CloudFront关联的WAF接口必须在us-east-1区域调用 region: 'us-east-1', onUpdate: { service: 'WAFV2', action: 'listWebACLs', // SDK方法名是小驼峰格式 parameters: { Scope: 'CLOUDFRONT', Limit: 100, }, // 配置返回值提取路径,后续可通过getResponseField取值 outputPaths: ['WebACLs'], physicalResourceId: cr.PhysicalResourceId.of('cloudfront-waf-acl-list'), }, policy: cr.AwsCustomResourcePolicy.fromSdkCalls({ resources: cr.AwsCustomResourcePolicy.ANY_RESOURCE, }), role: crRole, }); // 例:取返回列表中第一个ACL的ARN const firstAclArn = wafAclQuery.getResponseField('WebACLs.0.ARN');
关键注意点
- 旧版经典WAF已经很少使用,新建WAF默认都是WAFv2版本,不要调用错服务接口
- 区域级WAF(Scope为REGIONAL)只能给对应区域的ALB、API Gateway等资源使用,无法关联CloudFront
- 不建议无筛选直接使用列表返回的第一个ACL,容易因为ACL顺序变化关联错资源,优先用明确名称查询的方式
内容的提问来源于stack exchange,提问作者HUY
相关产品推荐
相关产品推荐

