The aws:wafv2/webAclRuleGroupAssociation:WebAclRuleGroupAssociation resource, part of the Pulumi AWS provider, associates WAFv2 rule groups (custom or AWS-managed) with Web ACLs by creating a rule that references the entire rule group. This guide focuses on three capabilities: custom rule group association, AWS-managed rule group integration, and rule action overrides for testing and customization.
Associations require existing Web ACLs and, for custom rule groups, existing rule group resources. Web ACLs must use lifecycle.ignore_changes to prevent configuration drift when this resource modifies rules. The examples are intentionally small. Combine them with your own Web ACLs and rule groups.
Associate a custom rule group with a Web ACL
Most WAF deployments attach custom rule groups to Web ACLs, allowing you to reuse rule definitions across multiple Web ACLs without duplicating configuration.
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
// Web ACL must use lifecycle.ignore_changes to prevent drift from this resource
const example = new aws.wafv2.WebAcl("example", {
name: "example-web-acl",
scope: "REGIONAL",
defaultAction: {
allow: {},
},
visibilityConfig: {
cloudwatchMetricsEnabled: true,
metricName: "example-web-acl",
sampledRequestsEnabled: true,
},
});
// Associate a custom rule group
const exampleWebAclRuleGroupAssociation = new aws.wafv2.WebAclRuleGroupAssociation("example", {
ruleName: "example-rule-group-rule",
priority: 100,
webAclArn: example.arn,
ruleGroupReference: {
arn: exampleAwsWafv2RuleGroup.arn,
},
});
import pulumi
import pulumi_aws as aws
# Web ACL must use lifecycle.ignore_changes to prevent drift from this resource
example = aws.wafv2.WebAcl("example",
name="example-web-acl",
scope="REGIONAL",
default_action={
"allow": {},
},
visibility_config={
"cloudwatch_metrics_enabled": True,
"metric_name": "example-web-acl",
"sampled_requests_enabled": True,
})
# Associate a custom rule group
example_web_acl_rule_group_association = aws.wafv2.WebAclRuleGroupAssociation("example",
rule_name="example-rule-group-rule",
priority=100,
web_acl_arn=example.arn,
rule_group_reference={
"arn": example_aws_wafv2_rule_group["arn"],
})
package main
import (
"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/wafv2"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
// Web ACL must use lifecycle.ignore_changes to prevent drift from this resource
example, err := wafv2.NewWebAcl(ctx, "example", &wafv2.WebAclArgs{
Name: pulumi.String("example-web-acl"),
Scope: pulumi.String("REGIONAL"),
DefaultAction: &wafv2.WebAclDefaultActionArgs{
Allow: &wafv2.WebAclDefaultActionAllowArgs{},
},
VisibilityConfig: &wafv2.WebAclVisibilityConfigArgs{
CloudwatchMetricsEnabled: pulumi.Bool(true),
MetricName: pulumi.String("example-web-acl"),
SampledRequestsEnabled: pulumi.Bool(true),
},
})
if err != nil {
return err
}
// Associate a custom rule group
_, err = wafv2.NewWebAclRuleGroupAssociation(ctx, "example", &wafv2.WebAclRuleGroupAssociationArgs{
RuleName: pulumi.String("example-rule-group-rule"),
Priority: pulumi.Int(100),
WebAclArn: example.Arn,
RuleGroupReference: &wafv2.WebAclRuleGroupAssociationRuleGroupReferenceArgs{
Arn: pulumi.Any(exampleAwsWafv2RuleGroup.Arn),
},
})
if err != nil {
return err
}
return nil
})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Aws = Pulumi.Aws;
return await Deployment.RunAsync(() =>
{
// Web ACL must use lifecycle.ignore_changes to prevent drift from this resource
var example = new Aws.WafV2.WebAcl("example", new()
{
Name = "example-web-acl",
Scope = "REGIONAL",
DefaultAction = new Aws.WafV2.Inputs.WebAclDefaultActionArgs
{
Allow = null,
},
VisibilityConfig = new Aws.WafV2.Inputs.WebAclVisibilityConfigArgs
{
CloudwatchMetricsEnabled = true,
MetricName = "example-web-acl",
SampledRequestsEnabled = true,
},
});
// Associate a custom rule group
var exampleWebAclRuleGroupAssociation = new Aws.WafV2.WebAclRuleGroupAssociation("example", new()
{
RuleName = "example-rule-group-rule",
Priority = 100,
WebAclArn = example.Arn,
RuleGroupReference = new Aws.WafV2.Inputs.WebAclRuleGroupAssociationRuleGroupReferenceArgs
{
Arn = exampleAwsWafv2RuleGroup.Arn,
},
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.wafv2.WebAcl;
import com.pulumi.aws.wafv2.WebAclArgs;
import com.pulumi.aws.wafv2.inputs.WebAclDefaultActionArgs;
import com.pulumi.aws.wafv2.inputs.WebAclDefaultActionAllowArgs;
import com.pulumi.aws.wafv2.inputs.WebAclVisibilityConfigArgs;
import com.pulumi.aws.wafv2.WebAclRuleGroupAssociation;
import com.pulumi.aws.wafv2.WebAclRuleGroupAssociationArgs;
import com.pulumi.aws.wafv2.inputs.WebAclRuleGroupAssociationRuleGroupReferenceArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
public class App {
public static void main(String[] args) {
Pulumi.run(App::stack);
}
public static void stack(Context ctx) {
// Web ACL must use lifecycle.ignore_changes to prevent drift from this resource
var example = new WebAcl("example", WebAclArgs.builder()
.name("example-web-acl")
.scope("REGIONAL")
.defaultAction(WebAclDefaultActionArgs.builder()
.allow(WebAclDefaultActionAllowArgs.builder()
.build())
.build())
.visibilityConfig(WebAclVisibilityConfigArgs.builder()
.cloudwatchMetricsEnabled(true)
.metricName("example-web-acl")
.sampledRequestsEnabled(true)
.build())
.build());
// Associate a custom rule group
var exampleWebAclRuleGroupAssociation = new WebAclRuleGroupAssociation("exampleWebAclRuleGroupAssociation", WebAclRuleGroupAssociationArgs.builder()
.ruleName("example-rule-group-rule")
.priority(100)
.webAclArn(example.arn())
.ruleGroupReference(WebAclRuleGroupAssociationRuleGroupReferenceArgs.builder()
.arn(exampleAwsWafv2RuleGroup.arn())
.build())
.build());
}
}
resources:
# Web ACL must use lifecycle.ignore_changes to prevent drift from this resource
example:
type: aws:wafv2:WebAcl
properties:
name: example-web-acl
scope: REGIONAL
defaultAction:
allow: {}
visibilityConfig:
cloudwatchMetricsEnabled: true
metricName: example-web-acl
sampledRequestsEnabled: true
# Associate a custom rule group
exampleWebAclRuleGroupAssociation:
type: aws:wafv2:WebAclRuleGroupAssociation
name: example
properties:
ruleName: example-rule-group-rule
priority: 100
webAclArn: ${example.arn}
ruleGroupReference:
arn: ${exampleAwsWafv2RuleGroup.arn}
The ruleGroupReference property points to your custom rule group by ARN. The priority determines evaluation order (lower numbers first). The Web ACL must include lifecycle { ignore_changes = [rule] } to prevent drift, since this resource modifies the Web ACL’s rules outside its direct management.
Apply AWS-managed rule sets to a Web ACL
AWS provides pre-configured managed rule groups that protect against common threats like SQL injection and cross-site scripting.
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
const example = new aws.wafv2.WebAclRuleGroupAssociation("example", {
ruleName: "aws-common-rule-set",
priority: 50,
webAclArn: exampleAwsWafv2WebAcl.arn,
managedRuleGroup: {
name: "AWSManagedRulesCommonRuleSet",
vendorName: "AWS",
},
});
import pulumi
import pulumi_aws as aws
example = aws.wafv2.WebAclRuleGroupAssociation("example",
rule_name="aws-common-rule-set",
priority=50,
web_acl_arn=example_aws_wafv2_web_acl["arn"],
managed_rule_group={
"name": "AWSManagedRulesCommonRuleSet",
"vendor_name": "AWS",
})
package main
import (
"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/wafv2"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
_, err := wafv2.NewWebAclRuleGroupAssociation(ctx, "example", &wafv2.WebAclRuleGroupAssociationArgs{
RuleName: pulumi.String("aws-common-rule-set"),
Priority: pulumi.Int(50),
WebAclArn: pulumi.Any(exampleAwsWafv2WebAcl.Arn),
ManagedRuleGroup: &wafv2.WebAclRuleGroupAssociationManagedRuleGroupArgs{
Name: pulumi.String("AWSManagedRulesCommonRuleSet"),
VendorName: pulumi.String("AWS"),
},
})
if err != nil {
return err
}
return nil
})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Aws = Pulumi.Aws;
return await Deployment.RunAsync(() =>
{
var example = new Aws.WafV2.WebAclRuleGroupAssociation("example", new()
{
RuleName = "aws-common-rule-set",
Priority = 50,
WebAclArn = exampleAwsWafv2WebAcl.Arn,
ManagedRuleGroup = new Aws.WafV2.Inputs.WebAclRuleGroupAssociationManagedRuleGroupArgs
{
Name = "AWSManagedRulesCommonRuleSet",
VendorName = "AWS",
},
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.wafv2.WebAclRuleGroupAssociation;
import com.pulumi.aws.wafv2.WebAclRuleGroupAssociationArgs;
import com.pulumi.aws.wafv2.inputs.WebAclRuleGroupAssociationManagedRuleGroupArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
public class App {
public static void main(String[] args) {
Pulumi.run(App::stack);
}
public static void stack(Context ctx) {
var example = new WebAclRuleGroupAssociation("example", WebAclRuleGroupAssociationArgs.builder()
.ruleName("aws-common-rule-set")
.priority(50)
.webAclArn(exampleAwsWafv2WebAcl.arn())
.managedRuleGroup(WebAclRuleGroupAssociationManagedRuleGroupArgs.builder()
.name("AWSManagedRulesCommonRuleSet")
.vendorName("AWS")
.build())
.build());
}
}
resources:
example:
type: aws:wafv2:WebAclRuleGroupAssociation
properties:
ruleName: aws-common-rule-set
priority: 50
webAclArn: ${exampleAwsWafv2WebAcl.arn}
managedRuleGroup:
name: AWSManagedRulesCommonRuleSet
vendorName: AWS
The managedRuleGroup property specifies the rule group by name and vendorName instead of ARN. AWS-managed rule groups are maintained by AWS and automatically updated with new threat signatures.
Override managed rule actions for testing or monitoring
When deploying managed rule groups, teams often test rules in count mode before enforcing blocks, or customize actions for specific rules.
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
const example = new aws.wafv2.WebAclRuleGroupAssociation("example", {
ruleName: "aws-common-rule-set-with-overrides",
priority: 70,
webAclArn: exampleAwsWafv2WebAcl.arn,
managedRuleGroup: {
name: "AWSManagedRulesCommonRuleSet",
vendorName: "AWS",
ruleActionOverrides: [
{
name: "GenericRFI_BODY",
actionToUse: {
count: {
customRequestHandling: {
insertHeaders: [{
name: "X-RFI-Override",
value: "counted",
}],
},
},
},
},
{
name: "SizeRestrictions_BODY",
actionToUse: {
captcha: {},
},
},
],
},
});
import pulumi
import pulumi_aws as aws
example = aws.wafv2.WebAclRuleGroupAssociation("example",
rule_name="aws-common-rule-set-with-overrides",
priority=70,
web_acl_arn=example_aws_wafv2_web_acl["arn"],
managed_rule_group={
"name": "AWSManagedRulesCommonRuleSet",
"vendor_name": "AWS",
"rule_action_overrides": [
{
"name": "GenericRFI_BODY",
"action_to_use": {
"count": {
"custom_request_handling": {
"insert_headers": [{
"name": "X-RFI-Override",
"value": "counted",
}],
},
},
},
},
{
"name": "SizeRestrictions_BODY",
"action_to_use": {
"captcha": {},
},
},
],
})
package main
import (
"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/wafv2"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
_, err := wafv2.NewWebAclRuleGroupAssociation(ctx, "example", &wafv2.WebAclRuleGroupAssociationArgs{
RuleName: pulumi.String("aws-common-rule-set-with-overrides"),
Priority: pulumi.Int(70),
WebAclArn: pulumi.Any(exampleAwsWafv2WebAcl.Arn),
ManagedRuleGroup: &wafv2.WebAclRuleGroupAssociationManagedRuleGroupArgs{
Name: pulumi.String("AWSManagedRulesCommonRuleSet"),
VendorName: pulumi.String("AWS"),
RuleActionOverrides: wafv2.WebAclRuleGroupAssociationManagedRuleGroupRuleActionOverrideArray{
&wafv2.WebAclRuleGroupAssociationManagedRuleGroupRuleActionOverrideArgs{
Name: pulumi.String("GenericRFI_BODY"),
ActionToUse: &wafv2.WebAclRuleGroupAssociationManagedRuleGroupRuleActionOverrideActionToUseArgs{
Count: &wafv2.WebAclRuleGroupAssociationManagedRuleGroupRuleActionOverrideActionToUseCountArgs{
CustomRequestHandling: &wafv2.WebAclRuleGroupAssociationManagedRuleGroupRuleActionOverrideActionToUseCountCustomRequestHandlingArgs{
InsertHeaders: wafv2.WebAclRuleGroupAssociationManagedRuleGroupRuleActionOverrideActionToUseCountCustomRequestHandlingInsertHeaderArray{
&wafv2.WebAclRuleGroupAssociationManagedRuleGroupRuleActionOverrideActionToUseCountCustomRequestHandlingInsertHeaderArgs{
Name: pulumi.String("X-RFI-Override"),
Value: pulumi.String("counted"),
},
},
},
},
},
},
&wafv2.WebAclRuleGroupAssociationManagedRuleGroupRuleActionOverrideArgs{
Name: pulumi.String("SizeRestrictions_BODY"),
ActionToUse: &wafv2.WebAclRuleGroupAssociationManagedRuleGroupRuleActionOverrideActionToUseArgs{
Captcha: &wafv2.WebAclRuleGroupAssociationManagedRuleGroupRuleActionOverrideActionToUseCaptchaArgs{},
},
},
},
},
})
if err != nil {
return err
}
return nil
})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Aws = Pulumi.Aws;
return await Deployment.RunAsync(() =>
{
var example = new Aws.WafV2.WebAclRuleGroupAssociation("example", new()
{
RuleName = "aws-common-rule-set-with-overrides",
Priority = 70,
WebAclArn = exampleAwsWafv2WebAcl.Arn,
ManagedRuleGroup = new Aws.WafV2.Inputs.WebAclRuleGroupAssociationManagedRuleGroupArgs
{
Name = "AWSManagedRulesCommonRuleSet",
VendorName = "AWS",
RuleActionOverrides = new[]
{
new Aws.WafV2.Inputs.WebAclRuleGroupAssociationManagedRuleGroupRuleActionOverrideArgs
{
Name = "GenericRFI_BODY",
ActionToUse = new Aws.WafV2.Inputs.WebAclRuleGroupAssociationManagedRuleGroupRuleActionOverrideActionToUseArgs
{
Count = new Aws.WafV2.Inputs.WebAclRuleGroupAssociationManagedRuleGroupRuleActionOverrideActionToUseCountArgs
{
CustomRequestHandling = new Aws.WafV2.Inputs.WebAclRuleGroupAssociationManagedRuleGroupRuleActionOverrideActionToUseCountCustomRequestHandlingArgs
{
InsertHeaders = new[]
{
new Aws.WafV2.Inputs.WebAclRuleGroupAssociationManagedRuleGroupRuleActionOverrideActionToUseCountCustomRequestHandlingInsertHeaderArgs
{
Name = "X-RFI-Override",
Value = "counted",
},
},
},
},
},
},
new Aws.WafV2.Inputs.WebAclRuleGroupAssociationManagedRuleGroupRuleActionOverrideArgs
{
Name = "SizeRestrictions_BODY",
ActionToUse = new Aws.WafV2.Inputs.WebAclRuleGroupAssociationManagedRuleGroupRuleActionOverrideActionToUseArgs
{
Captcha = null,
},
},
},
},
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.wafv2.WebAclRuleGroupAssociation;
import com.pulumi.aws.wafv2.WebAclRuleGroupAssociationArgs;
import com.pulumi.aws.wafv2.inputs.WebAclRuleGroupAssociationManagedRuleGroupArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
public class App {
public static void main(String[] args) {
Pulumi.run(App::stack);
}
public static void stack(Context ctx) {
var example = new WebAclRuleGroupAssociation("example", WebAclRuleGroupAssociationArgs.builder()
.ruleName("aws-common-rule-set-with-overrides")
.priority(70)
.webAclArn(exampleAwsWafv2WebAcl.arn())
.managedRuleGroup(WebAclRuleGroupAssociationManagedRuleGroupArgs.builder()
.name("AWSManagedRulesCommonRuleSet")
.vendorName("AWS")
.ruleActionOverrides(
WebAclRuleGroupAssociationManagedRuleGroupRuleActionOverrideArgs.builder()
.name("GenericRFI_BODY")
.actionToUse(WebAclRuleGroupAssociationManagedRuleGroupRuleActionOverrideActionToUseArgs.builder()
.count(WebAclRuleGroupAssociationManagedRuleGroupRuleActionOverrideActionToUseCountArgs.builder()
.customRequestHandling(WebAclRuleGroupAssociationManagedRuleGroupRuleActionOverrideActionToUseCountCustomRequestHandlingArgs.builder()
.insertHeaders(WebAclRuleGroupAssociationManagedRuleGroupRuleActionOverrideActionToUseCountCustomRequestHandlingInsertHeaderArgs.builder()
.name("X-RFI-Override")
.value("counted")
.build())
.build())
.build())
.build())
.build(),
WebAclRuleGroupAssociationManagedRuleGroupRuleActionOverrideArgs.builder()
.name("SizeRestrictions_BODY")
.actionToUse(WebAclRuleGroupAssociationManagedRuleGroupRuleActionOverrideActionToUseArgs.builder()
.captcha(WebAclRuleGroupAssociationManagedRuleGroupRuleActionOverrideActionToUseCaptchaArgs.builder()
.build())
.build())
.build())
.build())
.build());
}
}
resources:
example:
type: aws:wafv2:WebAclRuleGroupAssociation
properties:
ruleName: aws-common-rule-set-with-overrides
priority: 70
webAclArn: ${exampleAwsWafv2WebAcl.arn}
managedRuleGroup:
name: AWSManagedRulesCommonRuleSet
vendorName: AWS
ruleActionOverrides:
- name: GenericRFI_BODY
actionToUse:
count:
customRequestHandling:
insertHeaders:
- name: X-RFI-Override
value: counted
- name: SizeRestrictions_BODY
actionToUse:
captcha: {}
The ruleActionOverrides array lets you change individual rule actions. Each override specifies the exact rule name and the actionToUse (count, captcha, allow, or block). Rule names must exactly match the case-sensitive names in the managed rule group; WAF silently ignores invalid names for managed rule groups.
Set count mode for all custom rule group rules
During testing or troubleshooting, you can override all rules in a custom rule group to count matches instead of blocking.
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
const example = new aws.wafv2.WebAclRuleGroupAssociation("example", {
ruleName: "example-rule-group-rule",
priority: 100,
webAclArn: exampleAwsWafv2WebAcl.arn,
overrideAction: "count",
ruleGroupReference: {
arn: exampleAwsWafv2RuleGroup.arn,
},
});
import pulumi
import pulumi_aws as aws
example = aws.wafv2.WebAclRuleGroupAssociation("example",
rule_name="example-rule-group-rule",
priority=100,
web_acl_arn=example_aws_wafv2_web_acl["arn"],
override_action="count",
rule_group_reference={
"arn": example_aws_wafv2_rule_group["arn"],
})
package main
import (
"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/wafv2"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
_, err := wafv2.NewWebAclRuleGroupAssociation(ctx, "example", &wafv2.WebAclRuleGroupAssociationArgs{
RuleName: pulumi.String("example-rule-group-rule"),
Priority: pulumi.Int(100),
WebAclArn: pulumi.Any(exampleAwsWafv2WebAcl.Arn),
OverrideAction: pulumi.String("count"),
RuleGroupReference: &wafv2.WebAclRuleGroupAssociationRuleGroupReferenceArgs{
Arn: pulumi.Any(exampleAwsWafv2RuleGroup.Arn),
},
})
if err != nil {
return err
}
return nil
})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Aws = Pulumi.Aws;
return await Deployment.RunAsync(() =>
{
var example = new Aws.WafV2.WebAclRuleGroupAssociation("example", new()
{
RuleName = "example-rule-group-rule",
Priority = 100,
WebAclArn = exampleAwsWafv2WebAcl.Arn,
OverrideAction = "count",
RuleGroupReference = new Aws.WafV2.Inputs.WebAclRuleGroupAssociationRuleGroupReferenceArgs
{
Arn = exampleAwsWafv2RuleGroup.Arn,
},
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.wafv2.WebAclRuleGroupAssociation;
import com.pulumi.aws.wafv2.WebAclRuleGroupAssociationArgs;
import com.pulumi.aws.wafv2.inputs.WebAclRuleGroupAssociationRuleGroupReferenceArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
public class App {
public static void main(String[] args) {
Pulumi.run(App::stack);
}
public static void stack(Context ctx) {
var example = new WebAclRuleGroupAssociation("example", WebAclRuleGroupAssociationArgs.builder()
.ruleName("example-rule-group-rule")
.priority(100)
.webAclArn(exampleAwsWafv2WebAcl.arn())
.overrideAction("count")
.ruleGroupReference(WebAclRuleGroupAssociationRuleGroupReferenceArgs.builder()
.arn(exampleAwsWafv2RuleGroup.arn())
.build())
.build());
}
}
resources:
example:
type: aws:wafv2:WebAclRuleGroupAssociation
properties:
ruleName: example-rule-group-rule
priority: 100
webAclArn: ${exampleAwsWafv2WebAcl.arn}
overrideAction: count
ruleGroupReference:
arn: ${exampleAwsWafv2RuleGroup.arn}
The overrideAction property applies to all rules in the rule group. Setting it to “count” overrides every rule’s action to count mode, useful for testing without blocking traffic. This differs from ruleActionOverrides, which targets specific rules.
Override individual custom rule actions with headers
For granular control, you can override specific rules within a custom rule group and add custom headers to track which overrides were applied.
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
const example = new aws.wafv2.WebAclRuleGroupAssociation("example", {
ruleName: "example-rule-group-rule",
priority: 100,
webAclArn: exampleAwsWafv2WebAcl.arn,
ruleGroupReference: {
arn: exampleAwsWafv2RuleGroup.arn,
ruleActionOverrides: [
{
name: "geo-block-rule",
actionToUse: {
count: {
customRequestHandling: {
insertHeaders: [{
name: "X-Geo-Block-Override",
value: "counted",
}],
},
},
},
},
{
name: "rate-limit-rule",
actionToUse: {
captcha: {
customRequestHandling: {
insertHeaders: [{
name: "X-Rate-Limit-Override",
value: "captcha-required",
}],
},
},
},
},
],
},
});
import pulumi
import pulumi_aws as aws
example = aws.wafv2.WebAclRuleGroupAssociation("example",
rule_name="example-rule-group-rule",
priority=100,
web_acl_arn=example_aws_wafv2_web_acl["arn"],
rule_group_reference={
"arn": example_aws_wafv2_rule_group["arn"],
"rule_action_overrides": [
{
"name": "geo-block-rule",
"action_to_use": {
"count": {
"custom_request_handling": {
"insert_headers": [{
"name": "X-Geo-Block-Override",
"value": "counted",
}],
},
},
},
},
{
"name": "rate-limit-rule",
"action_to_use": {
"captcha": {
"custom_request_handling": {
"insert_headers": [{
"name": "X-Rate-Limit-Override",
"value": "captcha-required",
}],
},
},
},
},
],
})
package main
import (
"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/wafv2"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
_, err := wafv2.NewWebAclRuleGroupAssociation(ctx, "example", &wafv2.WebAclRuleGroupAssociationArgs{
RuleName: pulumi.String("example-rule-group-rule"),
Priority: pulumi.Int(100),
WebAclArn: pulumi.Any(exampleAwsWafv2WebAcl.Arn),
RuleGroupReference: &wafv2.WebAclRuleGroupAssociationRuleGroupReferenceArgs{
Arn: pulumi.Any(exampleAwsWafv2RuleGroup.Arn),
RuleActionOverrides: wafv2.WebAclRuleGroupAssociationRuleGroupReferenceRuleActionOverrideArray{
&wafv2.WebAclRuleGroupAssociationRuleGroupReferenceRuleActionOverrideArgs{
Name: pulumi.String("geo-block-rule"),
ActionToUse: &wafv2.WebAclRuleGroupAssociationRuleGroupReferenceRuleActionOverrideActionToUseArgs{
Count: &wafv2.WebAclRuleGroupAssociationRuleGroupReferenceRuleActionOverrideActionToUseCountArgs{
CustomRequestHandling: &wafv2.WebAclRuleGroupAssociationRuleGroupReferenceRuleActionOverrideActionToUseCountCustomRequestHandlingArgs{
InsertHeaders: wafv2.WebAclRuleGroupAssociationRuleGroupReferenceRuleActionOverrideActionToUseCountCustomRequestHandlingInsertHeaderArray{
&wafv2.WebAclRuleGroupAssociationRuleGroupReferenceRuleActionOverrideActionToUseCountCustomRequestHandlingInsertHeaderArgs{
Name: pulumi.String("X-Geo-Block-Override"),
Value: pulumi.String("counted"),
},
},
},
},
},
},
&wafv2.WebAclRuleGroupAssociationRuleGroupReferenceRuleActionOverrideArgs{
Name: pulumi.String("rate-limit-rule"),
ActionToUse: &wafv2.WebAclRuleGroupAssociationRuleGroupReferenceRuleActionOverrideActionToUseArgs{
Captcha: &wafv2.WebAclRuleGroupAssociationRuleGroupReferenceRuleActionOverrideActionToUseCaptchaArgs{
CustomRequestHandling: &wafv2.WebAclRuleGroupAssociationRuleGroupReferenceRuleActionOverrideActionToUseCaptchaCustomRequestHandlingArgs{
InsertHeaders: wafv2.WebAclRuleGroupAssociationRuleGroupReferenceRuleActionOverrideActionToUseCaptchaCustomRequestHandlingInsertHeaderArray{
&wafv2.WebAclRuleGroupAssociationRuleGroupReferenceRuleActionOverrideActionToUseCaptchaCustomRequestHandlingInsertHeaderArgs{
Name: pulumi.String("X-Rate-Limit-Override"),
Value: pulumi.String("captcha-required"),
},
},
},
},
},
},
},
},
})
if err != nil {
return err
}
return nil
})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Aws = Pulumi.Aws;
return await Deployment.RunAsync(() =>
{
var example = new Aws.WafV2.WebAclRuleGroupAssociation("example", new()
{
RuleName = "example-rule-group-rule",
Priority = 100,
WebAclArn = exampleAwsWafv2WebAcl.Arn,
RuleGroupReference = new Aws.WafV2.Inputs.WebAclRuleGroupAssociationRuleGroupReferenceArgs
{
Arn = exampleAwsWafv2RuleGroup.Arn,
RuleActionOverrides = new[]
{
new Aws.WafV2.Inputs.WebAclRuleGroupAssociationRuleGroupReferenceRuleActionOverrideArgs
{
Name = "geo-block-rule",
ActionToUse = new Aws.WafV2.Inputs.WebAclRuleGroupAssociationRuleGroupReferenceRuleActionOverrideActionToUseArgs
{
Count = new Aws.WafV2.Inputs.WebAclRuleGroupAssociationRuleGroupReferenceRuleActionOverrideActionToUseCountArgs
{
CustomRequestHandling = new Aws.WafV2.Inputs.WebAclRuleGroupAssociationRuleGroupReferenceRuleActionOverrideActionToUseCountCustomRequestHandlingArgs
{
InsertHeaders = new[]
{
new Aws.WafV2.Inputs.WebAclRuleGroupAssociationRuleGroupReferenceRuleActionOverrideActionToUseCountCustomRequestHandlingInsertHeaderArgs
{
Name = "X-Geo-Block-Override",
Value = "counted",
},
},
},
},
},
},
new Aws.WafV2.Inputs.WebAclRuleGroupAssociationRuleGroupReferenceRuleActionOverrideArgs
{
Name = "rate-limit-rule",
ActionToUse = new Aws.WafV2.Inputs.WebAclRuleGroupAssociationRuleGroupReferenceRuleActionOverrideActionToUseArgs
{
Captcha = new Aws.WafV2.Inputs.WebAclRuleGroupAssociationRuleGroupReferenceRuleActionOverrideActionToUseCaptchaArgs
{
CustomRequestHandling = new Aws.WafV2.Inputs.WebAclRuleGroupAssociationRuleGroupReferenceRuleActionOverrideActionToUseCaptchaCustomRequestHandlingArgs
{
InsertHeaders = new[]
{
new Aws.WafV2.Inputs.WebAclRuleGroupAssociationRuleGroupReferenceRuleActionOverrideActionToUseCaptchaCustomRequestHandlingInsertHeaderArgs
{
Name = "X-Rate-Limit-Override",
Value = "captcha-required",
},
},
},
},
},
},
},
},
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.wafv2.WebAclRuleGroupAssociation;
import com.pulumi.aws.wafv2.WebAclRuleGroupAssociationArgs;
import com.pulumi.aws.wafv2.inputs.WebAclRuleGroupAssociationRuleGroupReferenceArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
public class App {
public static void main(String[] args) {
Pulumi.run(App::stack);
}
public static void stack(Context ctx) {
var example = new WebAclRuleGroupAssociation("example", WebAclRuleGroupAssociationArgs.builder()
.ruleName("example-rule-group-rule")
.priority(100)
.webAclArn(exampleAwsWafv2WebAcl.arn())
.ruleGroupReference(WebAclRuleGroupAssociationRuleGroupReferenceArgs.builder()
.arn(exampleAwsWafv2RuleGroup.arn())
.ruleActionOverrides(
WebAclRuleGroupAssociationRuleGroupReferenceRuleActionOverrideArgs.builder()
.name("geo-block-rule")
.actionToUse(WebAclRuleGroupAssociationRuleGroupReferenceRuleActionOverrideActionToUseArgs.builder()
.count(WebAclRuleGroupAssociationRuleGroupReferenceRuleActionOverrideActionToUseCountArgs.builder()
.customRequestHandling(WebAclRuleGroupAssociationRuleGroupReferenceRuleActionOverrideActionToUseCountCustomRequestHandlingArgs.builder()
.insertHeaders(WebAclRuleGroupAssociationRuleGroupReferenceRuleActionOverrideActionToUseCountCustomRequestHandlingInsertHeaderArgs.builder()
.name("X-Geo-Block-Override")
.value("counted")
.build())
.build())
.build())
.build())
.build(),
WebAclRuleGroupAssociationRuleGroupReferenceRuleActionOverrideArgs.builder()
.name("rate-limit-rule")
.actionToUse(WebAclRuleGroupAssociationRuleGroupReferenceRuleActionOverrideActionToUseArgs.builder()
.captcha(WebAclRuleGroupAssociationRuleGroupReferenceRuleActionOverrideActionToUseCaptchaArgs.builder()
.customRequestHandling(WebAclRuleGroupAssociationRuleGroupReferenceRuleActionOverrideActionToUseCaptchaCustomRequestHandlingArgs.builder()
.insertHeaders(WebAclRuleGroupAssociationRuleGroupReferenceRuleActionOverrideActionToUseCaptchaCustomRequestHandlingInsertHeaderArgs.builder()
.name("X-Rate-Limit-Override")
.value("captcha-required")
.build())
.build())
.build())
.build())
.build())
.build())
.build());
}
}
resources:
example:
type: aws:wafv2:WebAclRuleGroupAssociation
properties:
ruleName: example-rule-group-rule
priority: 100
webAclArn: ${exampleAwsWafv2WebAcl.arn}
ruleGroupReference:
arn: ${exampleAwsWafv2RuleGroup.arn}
ruleActionOverrides:
- name: geo-block-rule
actionToUse:
count:
customRequestHandling:
insertHeaders:
- name: X-Geo-Block-Override
value: counted
- name: rate-limit-rule
actionToUse:
captcha:
customRequestHandling:
insertHeaders:
- name: X-Rate-Limit-Override
value: captcha-required
The ruleActionOverrides array works with custom rule groups too. The customRequestHandling block adds headers to requests that match the rule, useful for tracking which overrides triggered. Unlike managed rule groups, invalid rule names in custom rule groups cause Web ACL updates to fail.
Beyond these examples
These snippets focus on specific rule group association features: custom and managed rule group association, rule action overrides and count mode, and priority-based rule ordering. They’re intentionally minimal rather than full WAF configurations.
The examples reference pre-existing infrastructure such as Web ACLs with lifecycle.ignore_changes for rules, and custom rule groups for custom rule group examples. They focus on associating rule groups rather than creating the underlying Web ACLs or rule groups.
To keep things focused, common association patterns are omitted, including:
- Visibility configuration (visibilityConfig for CloudWatch metrics)
- Managed rule group versioning (version property)
- Managed rule group configs (ACFP, ATP, Bot Control settings)
- CloudFront-specific Web ACL associations
These omissions are intentional: the goal is to illustrate how each rule group association feature is wired, not provide drop-in WAF modules. See the WAFv2 WebAclRuleGroupAssociation resource reference for all available configuration options.
Let's configure AWS WAFv2 Web ACL Rule Group Associations
Get started with Pulumi Cloud, then follow our quick setup guide to deploy this infrastructure.
Try Pulumi Cloud for FREEFrequently Asked Questions
Common Errors & Pitfalls
lifecycle { ignore_changes = [rule] } to your Web ACL resource configuration to prevent drift.Rule Groups & Configuration
managedRuleGroup with name and vendorName). Custom rule groups are user-created within your AWS account (use ruleGroupReference with the rule group’s ARN). These properties are mutually exclusive.managedRuleGroup with name and vendorName. For example, name: "AWSManagedRulesCommonRuleSet" and vendorName: "AWS". You can optionally specify a version.ruleGroupReference with the arn of your custom rule group.overrideAction applies to the entire rule group (set to count to override all rules to count mode). ruleActionOverrides targets individual rules within the group, allowing you to override specific rule actions like changing a block to count or captcha.ruleActionOverrides within either managedRuleGroup or ruleGroupReference. Specify the rule name and the actionToUse (such as count or captcha).Priority & Evaluation
priority parameter to control when this rule group is evaluated relative to other rules in the Web ACL.version property within managedRuleGroup to pin to a specific version (e.g., version: "Version_1.0"). If omitted, the default version is used.