# Assigning a rate-based rule to WebACL in WAF classic on AWS

You can assign rules to your WebACL in your WAF classic but what you can also do are assign [rate-based rules](https://docs.aws.amazon.com/waf/latest/developerguide/waf-rule-statement-type-rate-based.html) to it. You will use this when you need to apply rate-limiting at your WAF level.

And if you are trying to do it via Cloudformation like below:

```yaml
WebACL:
  Type: "AWS::WAFRegional::WebACL"
  Properties:
    DefaultAction:
      Type: BLOCK
    MetricName: "MyWebACL"
    Name: MyWebACL
    Rules:
      - Action:
          Type: ALLOW
        Priority: 1
        RuleId: !Ref RateBasedRule


RateBasedRule:
  Type: "AWS::WAFRegional::RateBasedRule"
  Properties:
    Name: MyRateBasedRule
    MetricName: "MyRateBasedRule"
    RateKey: "IP"
    RateLimit: 2000
    MatchPredicates:
      - DataId: !Ref IPSet
        Negated: false
        Type: "IPMatch"
```

This is not going to work since [rate-based rule creation is supported via Cloudformation but association is not](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-wafregional-ratebasedrule.html#:~:text=Note%20you%20can%20only%20create%20rate%2Dbased%20rules%20using%20an%20AWS%20CloudFormation%20template.%20To%20add%20the%20rate%2Dbased%20rules%20created%20through%20AWS%20CloudFormation%20to%20a%20web%20ACL%2C%20use%20the%20AWS%20WAF%20console%2C%20API%2C%20or%20command%20line%20interface%20(CLI).). This is a [known issue](https://github.com/aws-cloudformation/cloudformation-coverage-roadmap/issues/940) at AWS end.

You can either do the association via console or else use AWS cli for the same if it is part of an automation.

You will need to first fetch a change token which gets associated with the change you are making to the WebACL.

> *When you want to create, update, or delete AWS WAF objects, get a change token and include the change token in the create, update, or delete request. Change tokens ensure that your application doesn't submit conflicting requests to AWS WAF.*
> 
> *Each create, update, or delete request must use a unique change token. If your application submits a* `GetChangeToken` request and then submits a second `GetChangeToken` request before submitting a create, update, or delete request, the second `GetChangeToken` request returns the same value as the first `GetChangeToken` request.
> 
> *When you use a change token in a create, update, or delete request, the status of the change token changes to* `PENDING` , which indicates that AWS WAF is propagating the change to all AWS WAF servers. Use `GetChangeTokenStatus` to determine the status of your change token.

```bash
$ change_token=$(aws waf-regional get-change-token --output text) # this line is needed so that the output stored in the variable isn't enclosed in quotes
$ aws waf-regional update-web-acl --web-acl-id ${web_acl_id} --change-token ${change_token} --updates Action="INSERT",ActivatedRule="{Priority=1,RuleId=${rule_id},Action={Type=\"BLOCK\"},Type=\"RATE_BASED\"}"
```

### References

[https://docs.aws.amazon.com/cli/latest/reference/waf-regional/get-change-token.html](https://docs.aws.amazon.com/cli/latest/reference/waf-regional/get-change-token.html)

[https://docs.aws.amazon.com/cli/latest/reference/waf-regional/update-web-acl.html](https://docs.aws.amazon.com/cli/latest/reference/waf-regional/update-web-acl.html)
