Trying to associate APiGateway and WAF | cdk deploy error: AWS WAF couldn't perform the operation because the resource doesn't exist.

0

I'm trying to place a WAF in front of my CloudFront and API Gateway respectively. My code(stack code in the 1st comment in the answers) sets up the API Gateway, CloudFront and 2 Web ACLs and tries to associate the ACLs with the respective resource(CF or Gateway).

The cdk deploy on this stack errors out saying:

1:46:25 PM | CREATE_FAILED | AWS::WAFv2::WebACLAssociation | StarterAppApiGatewayWebAclAssociation Resource handler returned message: "AWS WAF couldn?t perform the operation because your resource doesn?t exist. (Service: Wafv2, Status Code: 400, Request ID: 9c536f17-0a26-42a1-af6f-f36fa3bbc724)" (Reque stToken: 9057ae6c-a087-d8a6-fd49-0c1cdd60e9a1, HandlerErrorCode: NotFound)

❌ StarterAppStack failed: Error: The stack named StarterAppStack failed creation, it may need to be manually deleted from the AWS console: ROLLBACK_COMPLETE: Resource handler returned message: "AWS WAF couldn?t perform the operation because your resource doesn?t exist. (Service: Wafv2, Status Code: 400, Request ID: 9c536f17-0a26-42a1-af6f-f36fa3bbc724)" (RequestToken: 9057ae6c-a087-d8a6-fd49-0c1cdd60e9a1, HandlerErrorCode: NotFound) at FullCloudFormationDeployment.monitorDeployment (/home/ec2-user/.nvm/versions/node/v16.20.0/lib/node_modules/aws-cdk/lib/index.js:443:10236) at runMicrotasks (<anonymous>) at processTicksAndRejections (node:internal/process/task_queues:96:5) at async Object.deployStack2 [as deployStack] (/home/ec2-user/.nvm/versions/node/v16.20.0/lib/node_modules/aws-cdk/lib/index.js:446:154181) at async /home/ec2-user/.nvm/versions/node/v16.20.0/lib/node_modules/aws-cdk/lib/index.js:446:137444

❌ Deployment failed: Error: The stack named StarterAppStack failed creation, it may need to be manually deleted from the AWS console: ROLLBACK_COMPLETE: Resource handler returned message: "AWS WAF couldn?t perform the operation because your resource doesn?t exist. (Service: Wafv2, Status Code: 400, Request ID: 9c536f17-0a26-42a1-af6f-f36fa3bbc724)" (RequestToken: 9057ae6c-a087-d8a6-fd49-0c1cdd60e9a1, HandlerErrorCode: NotFound) at FullCloudFormationDeployment.monitorDeployment (/home/ec2-user/.nvm/versions/node/v16.20.0/lib/node_modules/aws-cdk/lib/index.js:443:10236) at runMicrotasks (<anonymous>) at processTicksAndRejections (node:internal/process/task_queues:96:5) at async Object.deployStack2 [as deployStack] (/home/ec2-user/.nvm/versions/node/v16.20.0/lib/node_modules/aws-cdk/lib/index.js:446:154181) at async /home/ec2-user/.nvm/versions/node/v16.20.0/lib/node_modules/aws-cdk/lib/index.js:446:137444

The WAF for the CloudFront is being successfully created with all the rules associated. The WAF for the API is created successfully with all the rules but failed to associate itself with the API gateway. The strange observation has been is that if I take out the rules parameter then the API Gateway Web Acl association is created successfully. But as soon as I put the AWS managed rules in it errors out. I've done my best to double check for any syntax or typos or missing parameters or the naming of the AWS managed rule set but haven't come up on a solution.

1 Answer
0

Code snapshot for the question:

    // API Gateway with Lambda integration
    const devStageName = "dev";
    const prodStageName = "prod";
    const api = new apigateway.LambdaRestApi(this, "StarterAppApi", {
      handler: postLambdaFunction, // default in case no other HTTP methods are specified via addMethod()
      description: "API Gateway for Lambda",
      proxy: false, // Ensuring the API Gateway is not a proxy
      endpointTypes: [apigateway.EndpointType.REGIONAL],
    });
    const deployment = new apigateway.Deployment(this, "Deployment", {
      api: api,
    });
    new apigateway.Stage(this, "Stage", {
      deployment: deployment,
      stageName: devStageName,
    });


// Setup WAF for CloudFront
    const cloudFrontWebAcl = new wafv2.CfnWebACL(
      this,
      "StarterAppCloudFrontWebAcl",
      {
        name: "StarterAppCloudFrontWebAcl",
        defaultAction: {
          allow: {},
        },
        scope: "CLOUDFRONT", // Use CLOUDFRONT for CloudFront distributions
        visibilityConfig: {
          cloudWatchMetricsEnabled: true,
          sampledRequestsEnabled: true,
          metricName: "webAclMetric",
        },
        rules: [
          {
            name: "AWSManagedRulesCommonRuleSet",
            priority: 1,
            overrideAction: { none: {} }, // No override action
            statement: {
              managedRuleGroupStatement: {
                name: "AWSManagedRulesCommonRuleSet", // AWS managed rule group name
                vendorName: "AWS", // Vendor name should be AWS
              },
            },
            visibilityConfig: {
              cloudWatchMetricsEnabled: true,
              metricName: "AWSManagedRulesCommonRuleSet",
              sampledRequestsEnabled: true,
            },
          },
          {
            name: "AWSManagedRulesAdminProtectionRuleSet",
            priority: 2,
            overrideAction: { none: {} }, // No override action
            statement: {
              managedRuleGroupStatement: {
                name: "AWSManagedRulesAdminProtectionRuleSet",
                vendorName: "AWS",
              },
            },
            visibilityConfig: {
              cloudWatchMetricsEnabled: true,
              metricName: "AWSManagedRulesAdminProtectionRuleSet",
              sampledRequestsEnabled: true,
            },
          },
          {
            name: "AWSManagedRulesKnownBadInputsRuleSet",
            priority: 3,
            overrideAction: { none: {} }, // No override action
            statement: {
              managedRuleGroupStatement: {
                name: "AWSManagedRulesKnownBadInputsRuleSet",
                vendorName: "AWS",
              },
            },
            visibilityConfig: {
              cloudWatchMetricsEnabled: true,
              metricName: "AWSManagedRulesKnownBadInputsRuleSet",
              sampledRequestsEnabled: true,
            },
          },
        ],
      },
    );

    // Create a CloudFront distribution with the S3 bucket as the origin, use the OAI and associate the CloudFront WAF
    const distribution = new cloudfront.Distribution(
      this,
      "StarterAppCloudFrontDistribution",
      {
        defaultBehavior: {
          origin: new cloudfrontorigins.S3Origin(frontendBucket, {
            originAccessIdentity: oai, // Use the OAI for this origin
          }),
          viewerProtocolPolicy:
            cloudfront.ViewerProtocolPolicy.REDIRECT_TO_HTTPS,
        },
        defaultRootObject: "index.html",
        certificate: certificate,
        domainNames: [`${subDomain}.${domainName}`],
        webAclId: cloudFrontWebAcl.attrArn,
      },
    );

    // Setup WAF for API Gateway
    const apiGatewayWebAcl = new wafv2.CfnWebACL(
      this,
      "StarterAppApiGatewayWebAcl",
      {
        name: "StarterAppApiGatewayWebAcl",
        defaultAction: {
          allow: {},
        },
        scope: "REGIONAL",
        visibilityConfig: {
          cloudWatchMetricsEnabled: true,
          sampledRequestsEnabled: true,
          metricName: "starterAppApiGatewayWebAclMetric",
        },
        rules: [
          {
            name: "AWSManagedRulesCommonRuleSet",
            priority: 1,
            overrideAction: { none: {} }, // No override action
            statement: {
              managedRuleGroupStatement: {
                name: "AWSManagedRulesCommonRuleSet", // AWS managed rule group name
                vendorName: "AWS", // Vendor name should be AWS
              },
            },
            visibilityConfig: {
              cloudWatchMetricsEnabled: true,
              metricName: "AWSManagedRulesCommonRuleSet",
              sampledRequestsEnabled: true,
            },
          },
          {
            name: "AWSManagedRulesAdminProtectionRuleSet",
            priority: 2,
            overrideAction: { none: {} }, // No override action
            statement: {
              managedRuleGroupStatement: {
                name: "AWSManagedRulesAdminProtectionRuleSet",
                vendorName: "AWS",
              },
            },
            visibilityConfig: {
              cloudWatchMetricsEnabled: true,
              metricName: "AWSManagedRulesAdminProtectionRuleSet",
              sampledRequestsEnabled: true,
            },
          },
          {
            name: "AWSManagedRulesKnownBadInputsRuleSet",
            priority: 3,
            overrideAction: { none: {} }, // No override action
            statement: {
              managedRuleGroupStatement: {
                name: "AWSManagedRulesKnownBadInputsRuleSet",
                vendorName: "AWS",
              },
            },
            visibilityConfig: {
              cloudWatchMetricsEnabled: true,
              metricName: "AWSManagedRulesKnownBadInputsRuleSet",
              sampledRequestsEnabled: true,
            },
          },
        ],
      },
    );

    // Associate above WAF with API Gateway PROD stage
    new wafv2.CfnWebACLAssociation(
      this,
      "StarterAppApiGatewayWebAclAssociation",
      {
        webAclArn: apiGatewayWebAcl.attrArn,
        resourceArn: `arn:aws:apigateway:${this.region}::/restapis/${api.restApiId}/stages/${prodStageName}`,
      },
    );
answered 7 months ago

You are not logged in. Log in to post an answer.

A good answer clearly answers the question and provides constructive feedback and encourages professional growth in the question asker.

Guidelines for Answering Questions