The aws:wafv2/webAclRuleGroupAssociation:WebAclRuleGroupAssociation resource, part of the Pulumi AWS provider, associates rule groups with Web ACLs by creating a rule that references the entire group. This guide focuses on three capabilities: custom rule group association, AWS-managed rule group integration, and rule action overrides for tuning.
This resource references existing Web ACLs and rule groups rather than creating them. The Web ACL resource needs lifecycle { ignore_changes = [rule] } to avoid configuration drift, since this resource modifies the Web ACL’s rules outside its direct management. The examples are intentionally small. Combine them with your own Web ACL and rule group definitions.
Associate a custom rule group with a Web ACL
Teams building custom WAF protection create rule groups to organize related rules, then attach those groups to Web ACLs protecting specific applications.
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
const example = new aws.wafv2.RuleGroup("example", {
name: "example-rule-group",
scope: "REGIONAL",
capacity: 10,
rules: [{
name: "block-suspicious-requests",
priority: 1,
action: {
block: {},
},
statement: {
geoMatchStatement: {
countryCodes: [
"CN",
"RU",
],
},
},
visibilityConfig: {
cloudwatchMetricsEnabled: true,
metricName: "block-suspicious-requests",
sampledRequestsEnabled: true,
},
}],
visibilityConfig: {
cloudwatchMetricsEnabled: true,
metricName: "example-rule-group",
sampledRequestsEnabled: true,
},
});
const exampleWebAcl = new aws.wafv2.WebAcl("example", {
name: "example-web-acl",
scope: "REGIONAL",
defaultAction: {
allow: {},
},
visibilityConfig: {
cloudwatchMetricsEnabled: true,
metricName: "example-web-acl",
sampledRequestsEnabled: true,
},
});
const exampleWebAclRuleGroupAssociation = new aws.wafv2.WebAclRuleGroupAssociation("example", {
ruleName: "example-rule-group-rule",
priority: 100,
webAclArn: exampleWebAcl.arn,
ruleGroupReference: {
arn: example.arn,
},
});
import pulumi
import pulumi_aws as aws
example = aws.wafv2.RuleGroup("example",
name="example-rule-group",
scope="REGIONAL",
capacity=10,
rules=[{
"name": "block-suspicious-requests",
"priority": 1,
"action": {
"block": {},
},
"statement": {
"geo_match_statement": {
"country_codes": [
"CN",
"RU",
],
},
},
"visibility_config": {
"cloudwatch_metrics_enabled": True,
"metric_name": "block-suspicious-requests",
"sampled_requests_enabled": True,
},
}],
visibility_config={
"cloudwatch_metrics_enabled": True,
"metric_name": "example-rule-group",
"sampled_requests_enabled": True,
})
example_web_acl = 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,
})
example_web_acl_rule_group_association = aws.wafv2.WebAclRuleGroupAssociation("example",
rule_name="example-rule-group-rule",
priority=100,
web_acl_arn=example_web_acl.arn,
rule_group_reference={
"arn": example.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 {
example, err := wafv2.NewRuleGroup(ctx, "example", &wafv2.RuleGroupArgs{
Name: pulumi.String("example-rule-group"),
Scope: pulumi.String("REGIONAL"),
Capacity: pulumi.Int(10),
Rules: wafv2.RuleGroupRuleArray{
&wafv2.RuleGroupRuleArgs{
Name: pulumi.String("block-suspicious-requests"),
Priority: pulumi.Int(1),
Action: &wafv2.RuleGroupRuleActionArgs{
Block: &wafv2.RuleGroupRuleActionBlockArgs{},
},
Statement: &wafv2.RuleGroupRuleStatementArgs{
GeoMatchStatement: &wafv2.RuleGroupRuleStatementGeoMatchStatementArgs{
CountryCodes: pulumi.StringArray{
pulumi.String("CN"),
pulumi.String("RU"),
},
},
},
VisibilityConfig: &wafv2.RuleGroupRuleVisibilityConfigArgs{
CloudwatchMetricsEnabled: pulumi.Bool(true),
MetricName: pulumi.String("block-suspicious-requests"),
SampledRequestsEnabled: pulumi.Bool(true),
},
},
},
VisibilityConfig: &wafv2.RuleGroupVisibilityConfigArgs{
CloudwatchMetricsEnabled: pulumi.Bool(true),
MetricName: pulumi.String("example-rule-group"),
SampledRequestsEnabled: pulumi.Bool(true),
},
})
if err != nil {
return err
}
exampleWebAcl, 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
}
_, err = wafv2.NewWebAclRuleGroupAssociation(ctx, "example", &wafv2.WebAclRuleGroupAssociationArgs{
RuleName: pulumi.String("example-rule-group-rule"),
Priority: pulumi.Int(100),
WebAclArn: exampleWebAcl.Arn,
RuleGroupReference: &wafv2.WebAclRuleGroupAssociationRuleGroupReferenceArgs{
Arn: example.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.RuleGroup("example", new()
{
Name = "example-rule-group",
Scope = "REGIONAL",
Capacity = 10,
Rules = new[]
{
new Aws.WafV2.Inputs.RuleGroupRuleArgs
{
Name = "block-suspicious-requests",
Priority = 1,
Action = new Aws.WafV2.Inputs.RuleGroupRuleActionArgs
{
Block = null,
},
Statement = new Aws.WafV2.Inputs.RuleGroupRuleStatementArgs
{
GeoMatchStatement = new Aws.WafV2.Inputs.RuleGroupRuleStatementGeoMatchStatementArgs
{
CountryCodes = new[]
{
"CN",
"RU",
},
},
},
VisibilityConfig = new Aws.WafV2.Inputs.RuleGroupRuleVisibilityConfigArgs
{
CloudwatchMetricsEnabled = true,
MetricName = "block-suspicious-requests",
SampledRequestsEnabled = true,
},
},
},
VisibilityConfig = new Aws.WafV2.Inputs.RuleGroupVisibilityConfigArgs
{
CloudwatchMetricsEnabled = true,
MetricName = "example-rule-group",
SampledRequestsEnabled = true,
},
});
var exampleWebAcl = 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,
},
});
var exampleWebAclRuleGroupAssociation = new Aws.WafV2.WebAclRuleGroupAssociation("example", new()
{
RuleName = "example-rule-group-rule",
Priority = 100,
WebAclArn = exampleWebAcl.Arn,
RuleGroupReference = new Aws.WafV2.Inputs.WebAclRuleGroupAssociationRuleGroupReferenceArgs
{
Arn = example.Arn,
},
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.wafv2.RuleGroup;
import com.pulumi.aws.wafv2.RuleGroupArgs;
import com.pulumi.aws.wafv2.inputs.RuleGroupRuleArgs;
import com.pulumi.aws.wafv2.inputs.RuleGroupRuleActionArgs;
import com.pulumi.aws.wafv2.inputs.RuleGroupRuleActionBlockArgs;
import com.pulumi.aws.wafv2.inputs.RuleGroupRuleStatementArgs;
import com.pulumi.aws.wafv2.inputs.RuleGroupRuleStatementGeoMatchStatementArgs;
import com.pulumi.aws.wafv2.inputs.RuleGroupRuleVisibilityConfigArgs;
import com.pulumi.aws.wafv2.inputs.RuleGroupVisibilityConfigArgs;
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) {
var example = new RuleGroup("example", RuleGroupArgs.builder()
.name("example-rule-group")
.scope("REGIONAL")
.capacity(10)
.rules(RuleGroupRuleArgs.builder()
.name("block-suspicious-requests")
.priority(1)
.action(RuleGroupRuleActionArgs.builder()
.block(RuleGroupRuleActionBlockArgs.builder()
.build())
.build())
.statement(RuleGroupRuleStatementArgs.builder()
.geoMatchStatement(RuleGroupRuleStatementGeoMatchStatementArgs.builder()
.countryCodes(
"CN",
"RU")
.build())
.build())
.visibilityConfig(RuleGroupRuleVisibilityConfigArgs.builder()
.cloudwatchMetricsEnabled(true)
.metricName("block-suspicious-requests")
.sampledRequestsEnabled(true)
.build())
.build())
.visibilityConfig(RuleGroupVisibilityConfigArgs.builder()
.cloudwatchMetricsEnabled(true)
.metricName("example-rule-group")
.sampledRequestsEnabled(true)
.build())
.build());
var exampleWebAcl = new WebAcl("exampleWebAcl", 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());
var exampleWebAclRuleGroupAssociation = new WebAclRuleGroupAssociation("exampleWebAclRuleGroupAssociation", WebAclRuleGroupAssociationArgs.builder()
.ruleName("example-rule-group-rule")
.priority(100)
.webAclArn(exampleWebAcl.arn())
.ruleGroupReference(WebAclRuleGroupAssociationRuleGroupReferenceArgs.builder()
.arn(example.arn())
.build())
.build());
}
}
resources:
example:
type: aws:wafv2:RuleGroup
properties:
name: example-rule-group
scope: REGIONAL
capacity: 10
rules:
- name: block-suspicious-requests
priority: 1
action:
block: {}
statement:
geoMatchStatement:
countryCodes:
- CN
- RU
visibilityConfig:
cloudwatchMetricsEnabled: true
metricName: block-suspicious-requests
sampledRequestsEnabled: true
visibilityConfig:
cloudwatchMetricsEnabled: true
metricName: example-rule-group
sampledRequestsEnabled: true
exampleWebAcl:
type: aws:wafv2:WebAcl
name: example
properties:
name: example-web-acl
scope: REGIONAL
defaultAction:
allow: {}
visibilityConfig:
cloudwatchMetricsEnabled: true
metricName: example-web-acl
sampledRequestsEnabled: true
exampleWebAclRuleGroupAssociation:
type: aws:wafv2:WebAclRuleGroupAssociation
name: example
properties:
ruleName: example-rule-group-rule
priority: 100
webAclArn: ${exampleWebAcl.arn}
ruleGroupReference:
arn: ${example.arn}
The ruleGroupReference property points to your custom rule group’s ARN. The priority determines evaluation order within the Web ACL (lower numbers first). The ruleName identifies this association within the Web ACL. When requests match rules in the group, WAF applies the actions defined in those rules.
Apply AWS-managed rule sets to a Web ACL
AWS provides pre-configured rule groups that protect against common threats without requiring custom rule definitions.
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
const example = new aws.wafv2.WebAcl("example", {
name: "example-web-acl",
scope: "REGIONAL",
defaultAction: {
allow: {},
},
visibilityConfig: {
cloudwatchMetricsEnabled: true,
metricName: "example-web-acl",
sampledRequestsEnabled: true,
},
});
const managedExample = new aws.wafv2.WebAclRuleGroupAssociation("managed_example", {
ruleName: "aws-common-rule-set",
priority: 50,
webAclArn: example.arn,
managedRuleGroup: {
name: "AWSManagedRulesCommonRuleSet",
vendorName: "AWS",
},
});
import pulumi
import pulumi_aws as aws
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,
})
managed_example = aws.wafv2.WebAclRuleGroupAssociation("managed_example",
rule_name="aws-common-rule-set",
priority=50,
web_acl_arn=example.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 {
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
}
_, err = wafv2.NewWebAclRuleGroupAssociation(ctx, "managed_example", &wafv2.WebAclRuleGroupAssociationArgs{
RuleName: pulumi.String("aws-common-rule-set"),
Priority: pulumi.Int(50),
WebAclArn: example.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.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,
},
});
var managedExample = new Aws.WafV2.WebAclRuleGroupAssociation("managed_example", new()
{
RuleName = "aws-common-rule-set",
Priority = 50,
WebAclArn = example.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.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.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 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());
var managedExample = new WebAclRuleGroupAssociation("managedExample", WebAclRuleGroupAssociationArgs.builder()
.ruleName("aws-common-rule-set")
.priority(50)
.webAclArn(example.arn())
.managedRuleGroup(WebAclRuleGroupAssociationManagedRuleGroupArgs.builder()
.name("AWSManagedRulesCommonRuleSet")
.vendorName("AWS")
.build())
.build());
}
}
resources:
example:
type: aws:wafv2:WebAcl
properties:
name: example-web-acl
scope: REGIONAL
defaultAction:
allow: {}
visibilityConfig:
cloudwatchMetricsEnabled: true
metricName: example-web-acl
sampledRequestsEnabled: true
managedExample:
type: aws:wafv2:WebAclRuleGroupAssociation
name: managed_example
properties:
ruleName: aws-common-rule-set
priority: 50
webAclArn: ${example.arn}
managedRuleGroup:
name: AWSManagedRulesCommonRuleSet
vendorName: AWS
The managedRuleGroup property specifies which AWS-managed rule set to use. The vendorName is “AWS” for AWS-provided rules; third-party vendors use their own names. The name identifies the specific rule set (here, AWSManagedRulesCommonRuleSet for baseline protection). Priority controls when this rule group evaluates relative to other rules in the Web ACL.
Override specific rules in managed rule groups
Managed rule groups sometimes trigger false positives. You can override individual rules to count matches instead of blocking, or add custom headers for debugging.
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
const managedWithOverrides = new aws.wafv2.WebAclRuleGroupAssociation("managed_with_overrides", {
ruleName: "aws-common-rule-set-with-overrides",
priority: 70,
webAclArn: example.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
managed_with_overrides = aws.wafv2.WebAclRuleGroupAssociation("managed_with_overrides",
rule_name="aws-common-rule-set-with-overrides",
priority=70,
web_acl_arn=example["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, "managed_with_overrides", &wafv2.WebAclRuleGroupAssociationArgs{
RuleName: pulumi.String("aws-common-rule-set-with-overrides"),
Priority: pulumi.Int(70),
WebAclArn: pulumi.Any(example.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 managedWithOverrides = new Aws.WafV2.WebAclRuleGroupAssociation("managed_with_overrides", new()
{
RuleName = "aws-common-rule-set-with-overrides",
Priority = 70,
WebAclArn = example.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 managedWithOverrides = new WebAclRuleGroupAssociation("managedWithOverrides", WebAclRuleGroupAssociationArgs.builder()
.ruleName("aws-common-rule-set-with-overrides")
.priority(70)
.webAclArn(example.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:
managedWithOverrides:
type: aws:wafv2:WebAclRuleGroupAssociation
name: managed_with_overrides
properties:
ruleName: aws-common-rule-set-with-overrides
priority: 70
webAclArn: ${example.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 behavior for specific rules within the managed group. Each override specifies the rule name (case-sensitive, must match exactly) and the actionToUse. Here, GenericRFI_BODY switches to count mode with a custom header, while SizeRestrictions_BODY uses CAPTCHA challenge. Invalid rule names are silently ignored for managed groups, so verify names carefully.
Test custom rule groups in count mode
Before enforcing custom rules in production, deploy them in count mode to observe match patterns without blocking traffic.
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 set to “count” overrides all actions in the rule group, converting blocks to counts. This lets you validate rule behavior and tune thresholds before enforcement. Set to “none” (default) to use the rule group’s defined actions.
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 and custom rule groups, and AWS-managed rule group catalogs. They focus on associating rule groups rather than defining the Web ACL or rule group contents.
To keep things focused, common association patterns are omitted, including:
- Version pinning for managed rule groups (version property)
- Scope labels and label matching
- Custom request/response handling
- Web ACL lifecycle configuration (ignore_changes)
These omissions are intentional: the goal is to illustrate how rule group associations are wired, not provide drop-in WAF modules. See the 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 Issues & Gotchas
lifecycle { ignore_changes = [rule] } to your Web ACL resource configuration to prevent drift.Configuration & Setup
ruleGroupReference) are user-created rule groups you manage in your AWS account. Managed rule groups (managedRuleGroup) are pre-configured rule groups from AWS or third-party vendors. You must use one or the other, not both.ruleGroupReference with the ARN of your custom rule group. Specify ruleName, priority, and webAclArn as required properties.managedRuleGroup with name (e.g., AWSManagedRulesCommonRuleSet) and vendorName (e.g., AWS). Specify ruleName, priority, and webAclArn as required properties.priority 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 like Version_1.0.Rule Overrides & Actions
overrideAction controls how the entire rule group behaves. Valid values are none (default, uses rule group’s defined actions) and count (overrides all rule actions to count matches instead of blocking or allowing).ruleActionOverrides within managedRuleGroup to specify individual rule names and their override actions (e.g., count, captcha). This is only available for managed rule groups.