6

To secure our API, I'm trying to deploy a WAFRegional with a RateBasedRule. The API Gateway is located in a SAM template wherein I have also a nested stack for the child template holding the WAFRegional configurations. The child template for the WAFRegional configuration is provided below. What happens during the ExecuteChangeSet phase is the following:

  1. CamerasIpSet is created

  2. CamerasRateRule is created

  3. WAFCamerasWebACL CREATE_FAILED: The referenced item does not exist. (Service: AWSWAFRegional; Status Code: 400; Error Code: WAFNonexistentItemException

I found the following post from about 2 months ago where someone has the same issue when using Serverless: https://forum.serverless.com/t/dependon-api-gateway-deployment/7792

What am I missing out on here?

AWSTemplateFormatVersion: '2010-09-09'
Description: 'Template for WAF Configuration'
Parameters:
  CamerasApi:
    Description: "Arn of the Cameras Api"
    Type: String
    Default: cameras-api-dev
  StageName:
    Description: "Stage name of the Cameras Api"
    Type: String
    Default: v
  Blocking:
    Description: "Number of calls per 5 minutes for WAF IP blocking."
    Type: Number
    Default: 2000
  EnvironmentType:
    Type: String
    Default: "dev"
    Description: "Type of environment: dev, staging or prod."


Resources:
  WAFCamerasWebACL:
    Type: AWS::WAFRegional::WebACL
    DependsOn: CamerasRateRule
    Properties:
      DefaultAction:
        Type: ALLOW
      MetricName: !Join ['', ['IPBlockingMetric', !Ref EnvironmentType]]
      Name: !Join ['', ['IPBlockingACL', !Ref EnvironmentType]]
      Rules:
        -
          Action:
            Type: "BLOCK"
          Priority: 1
          RuleId: !Ref CamerasRateRule

  CamerasRateRule:
    Type: AWS::WAFRegional::RateBasedRule
    Properties:
      MetricName: UnallowedAccessCount
      Name: FiveMinuteRule
      RateKey: IP
      RateLimit: !Ref Blocking
      MatchPredicates:
      -
        DataId: !Ref CamerasIpSet
        Negated: false
        Type: "IPMatch"

  CamerasIpSet:
    Type: AWS::WAFRegional::IPSet
    Properties:
      Name: !Join ['-', ['IpBlacklist', !Ref EnvironmentType]]


  MyWebACLAssociation:
    Type: AWS::WAFRegional::WebACLAssociation
    Properties:
      ResourceArn: !Sub arn:aws:apigateway:${AWS::Region}::/restapis/${CamerasApi}/stages/${StageName}
      WebACLId: !Ref WAFCamerasWebACL

Outputs:
  WebACL:
    Description: Name of the web ACL
    Value: !Ref WAFCamerasWebACL


mibollma
  • 14,959
  • 6
  • 52
  • 69
MartinaW
  • 335
  • 3
  • 11
  • Unrelated but both joins in `WAFCamerasWebACL` can be written more simply and clearly using Sub: `MetricName: !Sub IPBlockingMetric${EnvironmentType}` – 404 Jun 20 '19 at 13:07
  • 1
    The problem will be solved when Cloudformation implements WAFv2 (which they recommend you use now). Ultimately we need Cloudformation to support creation and association (i.e. to an API Gateway or Load Balancer) so that other workarounds aren't put in place as they're not very transferable. The GitHub ticket is: https://github.com/aws-cloudformation/aws-cloudformation-coverage-roadmap/issues/344 – jamiem Jan 17 '20 at 10:53

4 Answers4

8

I finally resolved the issue with the help of the AWS customer service. This is a limitation they have with CloudFormation when dealing with AWS::WAFRegional::RateBasedRule.

Despite the fact that CloudFormation supports creating WAF regional rate-based rules, the association of them with a Web ACL is not currently supported. If you observe link [1] below, you will realize that: "To add the rate-based rules created through CloudFormation to a web ACL, use the AWS WAF console, API, or command line interface (CLI)."

[1] AWS::WAFRegional::RateBasedRule: https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-wafregional-ratebasedrule.html

I used the Cloudformation template to generate the WebACL, the RateBasedRule, and the association of the WebACL with my APIGW. Using CodeBuild in our CI/CD pipeline, I'm now adding the RateBasedRule to the WebACL by using the CLI command aws waf-regional update-web-acl.

MartinaW
  • 335
  • 3
  • 11
1

I ran in the same issue and I solve the problem with WAFv2

AWSTemplateFormatVersion: '2010-09-09'
Description: 'Template for WAF Configuration'
Parameters:
  CamerasApi:
    Description: "Arn of the Cameras Api"
    Type: String
    Default: YOUR-API-ID
  StageName:
    Description: "Stage name of the Cameras Api"
    Type: String
    Default: YOUR-Stage
  Blocking:
    Description: "Number of calls per 5 minutes for WAF IP blocking."
    Type: Number
    Default: 2000
  EnvironmentType:
    Type: String
    Default: Prod
    Description: "Type of environment: dev, staging or prod."


Resources:
  WAFCamerasWebACL:
    Type: AWS::WAFv2::WebACL
    Properties:
      Name: ExampleWebACL
      Description: This is an example WebACL
      Scope: REGIONAL
      DefaultAction: 
        Allow: {}
      VisibilityConfig:
        SampledRequestsEnabled: true
        CloudWatchMetricsEnabled: true
        MetricName: ExampleWebACLMetric
      Rules:
        - Name: RulesTest
          Priority: 0
          Action:
           Block: {}
          VisibilityConfig:
            SampledRequestsEnabled: true
            CloudWatchMetricsEnabled: true
            MetricName: test
          Statement:
            RateBasedStatement:
              Limit: 100
              AggregateKeyType: IP

  MyWebACLAssociation:
    Type: AWS::WAFv2::WebACLAssociation
    Properties:
      ResourceArn: !Sub arn:aws:apigateway:${AWS::Region}::/restapis/${CamerasApi}/stages/${StageName}
      WebACLArn: !GetAtt  WAFCamerasWebACL.Arn

Outputs:
  WebACL:
    Description: Name of the web ACL
    Value: !Ref WAFCamerasWebACL
Tay-4
  • 81
  • 4
0

Assuming a AWS::WAFRegional::WebACL and AWS::WAFRegional::RateBasedRule are defined in a Cloudformation stack, they can be attached using the following bash script:

CHANGE_TOKEN=$(aws waf-regional get-change-token --output text)
WEBACL_ID=$(aws waf-regional list-web-acls --query WebACLs[0].WebACLId --output text)
RULE_ID=$(aws waf-regional list-rate-based-rules --query Rules[0].RuleId --output text)
aws waf-regional update-web-acl --web-acl-id $WEBACL_ID --change-token $CHANGE_TOKEN \
    --updates Action="INSERT",ActivatedRule='{Priority=1,RuleId="'$RULE_ID'",Action={Type="BLOCK"},Type="RATE_BASED"}'

However unfortunately this leads to issues when deleting the Cloudformation stack

The following resource(s) failed to delete: [RateBasedRuleName].

Any ideas how to enable the stack to remove the rule when issueing aws cloudformation delete-stack?

mibollma
  • 14,959
  • 6
  • 52
  • 69
0
Resources:
  BlueWafAlbAssociation:
    Type: "AWS::WAFv2::WebACLAssociation"
    Properties:
      WebACLArn: arn:aws:wafv2:us-east-1:1234567890:regional/webacl/name-of-webacl/id-of-webacl
      ResourceArn: arn:aws:elasticloadbalancing:us-east-1:1234567890:loadbalancer/app/load-balancer-name/xxxxxxxxxxx
Mithun Biswas
  • 1,617
  • 1
  • 12
  • 19