Configure AWS WAFv2 Web ACL Rule Group Associations

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 FREE

Frequently Asked Questions

Common Issues & Gotchas
Why is my Web ACL showing configuration drift after adding this association?
This resource modifies the Web ACL’s rules outside the Web ACL resource’s direct management. Add lifecycle { ignore_changes = [rule] } to your Web ACL resource configuration to prevent drift.
What happens if I use an invalid rule name in my overrides?
With managed rule groups, WAF silently ignores overrides with invalid rule names. With custom rule groups, invalid rule names cause Web ACL updates to fail. Rule names must exactly match the case-sensitive names in the rule group.
Configuration & Setup
What's the difference between custom and managed rule groups?
Custom rule groups (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.
How do I associate a custom rule group with my Web ACL?
Use ruleGroupReference with the ARN of your custom rule group. Specify ruleName, priority, and webAclArn as required properties.
How do I associate a managed rule group with my Web ACL?
Use managedRuleGroup with name (e.g., AWSManagedRulesCommonRuleSet) and vendorName (e.g., AWS). Specify ruleName, priority, and webAclArn as required properties.
How does priority affect rule evaluation?
Rules are evaluated in order of priority, with lower numbers evaluated first. Set priority to control when this rule group is evaluated relative to other rules in the Web ACL.
Can I specify a version for a managed rule group?
Yes, use the version property within managedRuleGroup to pin to a specific version like Version_1.0.
Rule Overrides & Actions
What does the overrideAction property do?
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).
Can I override specific rules within a managed rule group?
Yes, use ruleActionOverrides within managedRuleGroup to specify individual rule names and their override actions (e.g., count, captcha). This is only available for managed rule groups.

Using a different cloud?

Explore security guides for other cloud providers: