The aws:wafv2/ruleGroup:RuleGroup resource, part of the Pulumi AWS provider, defines a WAFv2 rule group that evaluates web requests against filtering rules and takes actions (allow, block, count). This guide focuses on three capabilities: geographic filtering, logical operators for complex conditions, and raw JSON for deeply nested rules.
Rule groups operate independently but are attached to WebACLs for enforcement. They may reference IpSet and RegexPatternSet resources for pattern matching. The examples are intentionally small. Combine them with your own WebACL configuration and additional rule statements.
Block or allow requests by geographic location
Many applications restrict access based on request origin to comply with data residency requirements or reduce regional exposure.
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
const example = new aws.wafv2.RuleGroup("example", {
name: "example-rule",
scope: "REGIONAL",
capacity: 2,
rules: [{
name: "rule-1",
priority: 1,
action: {
allow: {},
},
statement: {
geoMatchStatement: {
countryCodes: [
"US",
"NL",
],
},
},
visibilityConfig: {
cloudwatchMetricsEnabled: false,
metricName: "friendly-rule-metric-name",
sampledRequestsEnabled: false,
},
}],
visibilityConfig: {
cloudwatchMetricsEnabled: false,
metricName: "friendly-metric-name",
sampledRequestsEnabled: false,
},
});
import pulumi
import pulumi_aws as aws
example = aws.wafv2.RuleGroup("example",
name="example-rule",
scope="REGIONAL",
capacity=2,
rules=[{
"name": "rule-1",
"priority": 1,
"action": {
"allow": {},
},
"statement": {
"geo_match_statement": {
"country_codes": [
"US",
"NL",
],
},
},
"visibility_config": {
"cloudwatch_metrics_enabled": False,
"metric_name": "friendly-rule-metric-name",
"sampled_requests_enabled": False,
},
}],
visibility_config={
"cloudwatch_metrics_enabled": False,
"metric_name": "friendly-metric-name",
"sampled_requests_enabled": False,
})
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.NewRuleGroup(ctx, "example", &wafv2.RuleGroupArgs{
Name: pulumi.String("example-rule"),
Scope: pulumi.String("REGIONAL"),
Capacity: pulumi.Int(2),
Rules: wafv2.RuleGroupRuleArray{
&wafv2.RuleGroupRuleArgs{
Name: pulumi.String("rule-1"),
Priority: pulumi.Int(1),
Action: &wafv2.RuleGroupRuleActionArgs{
Allow: &wafv2.RuleGroupRuleActionAllowArgs{},
},
Statement: &wafv2.RuleGroupRuleStatementArgs{
GeoMatchStatement: &wafv2.RuleGroupRuleStatementGeoMatchStatementArgs{
CountryCodes: pulumi.StringArray{
pulumi.String("US"),
pulumi.String("NL"),
},
},
},
VisibilityConfig: &wafv2.RuleGroupRuleVisibilityConfigArgs{
CloudwatchMetricsEnabled: pulumi.Bool(false),
MetricName: pulumi.String("friendly-rule-metric-name"),
SampledRequestsEnabled: pulumi.Bool(false),
},
},
},
VisibilityConfig: &wafv2.RuleGroupVisibilityConfigArgs{
CloudwatchMetricsEnabled: pulumi.Bool(false),
MetricName: pulumi.String("friendly-metric-name"),
SampledRequestsEnabled: pulumi.Bool(false),
},
})
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",
Scope = "REGIONAL",
Capacity = 2,
Rules = new[]
{
new Aws.WafV2.Inputs.RuleGroupRuleArgs
{
Name = "rule-1",
Priority = 1,
Action = new Aws.WafV2.Inputs.RuleGroupRuleActionArgs
{
Allow = null,
},
Statement = new Aws.WafV2.Inputs.RuleGroupRuleStatementArgs
{
GeoMatchStatement = new Aws.WafV2.Inputs.RuleGroupRuleStatementGeoMatchStatementArgs
{
CountryCodes = new[]
{
"US",
"NL",
},
},
},
VisibilityConfig = new Aws.WafV2.Inputs.RuleGroupRuleVisibilityConfigArgs
{
CloudwatchMetricsEnabled = false,
MetricName = "friendly-rule-metric-name",
SampledRequestsEnabled = false,
},
},
},
VisibilityConfig = new Aws.WafV2.Inputs.RuleGroupVisibilityConfigArgs
{
CloudwatchMetricsEnabled = false,
MetricName = "friendly-metric-name",
SampledRequestsEnabled = false,
},
});
});
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.RuleGroupRuleActionAllowArgs;
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 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")
.scope("REGIONAL")
.capacity(2)
.rules(RuleGroupRuleArgs.builder()
.name("rule-1")
.priority(1)
.action(RuleGroupRuleActionArgs.builder()
.allow(RuleGroupRuleActionAllowArgs.builder()
.build())
.build())
.statement(RuleGroupRuleStatementArgs.builder()
.geoMatchStatement(RuleGroupRuleStatementGeoMatchStatementArgs.builder()
.countryCodes(
"US",
"NL")
.build())
.build())
.visibilityConfig(RuleGroupRuleVisibilityConfigArgs.builder()
.cloudwatchMetricsEnabled(false)
.metricName("friendly-rule-metric-name")
.sampledRequestsEnabled(false)
.build())
.build())
.visibilityConfig(RuleGroupVisibilityConfigArgs.builder()
.cloudwatchMetricsEnabled(false)
.metricName("friendly-metric-name")
.sampledRequestsEnabled(false)
.build())
.build());
}
}
resources:
example:
type: aws:wafv2:RuleGroup
properties:
name: example-rule
scope: REGIONAL
capacity: 2
rules:
- name: rule-1
priority: 1
action:
allow: {}
statement:
geoMatchStatement:
countryCodes:
- US
- NL
visibilityConfig:
cloudwatchMetricsEnabled: false
metricName: friendly-rule-metric-name
sampledRequestsEnabled: false
visibilityConfig:
cloudwatchMetricsEnabled: false
metricName: friendly-metric-name
sampledRequestsEnabled: false
The geoMatchStatement checks the request’s source country against the countryCodes list. The action property determines what happens when the rule matches: allow permits the request, block rejects it, and count logs it without taking action. The visibilityConfig enables CloudWatch metrics for monitoring rule behavior.
Combine multiple conditions with logical operators
Real-world filtering often requires combining multiple checks: blocking requests that match certain patterns while allowing others.
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
const test = new aws.wafv2.IpSet("test", {
name: "test",
scope: "REGIONAL",
ipAddressVersion: "IPV4",
addresses: [
"1.1.1.1/32",
"2.2.2.2/32",
],
});
const testRegexPatternSet = new aws.wafv2.RegexPatternSet("test", {
name: "test",
scope: "REGIONAL",
regularExpressions: [{
regexString: "one",
}],
});
const example = new aws.wafv2.RuleGroup("example", {
name: "complex-example",
description: "An rule group containing all statements",
scope: "REGIONAL",
capacity: 500,
rules: [
{
name: "rule-1",
priority: 1,
action: {
block: {},
},
statement: {
notStatement: {
statements: [{
andStatement: {
statements: [
{
geoMatchStatement: {
countryCodes: ["US"],
},
},
{
byteMatchStatement: {
positionalConstraint: "CONTAINS",
searchString: "word",
fieldToMatch: {
allQueryArguments: {},
},
textTransformations: [
{
priority: 5,
type: "CMD_LINE",
},
{
priority: 2,
type: "LOWERCASE",
},
],
},
},
],
},
}],
},
},
visibilityConfig: {
cloudwatchMetricsEnabled: false,
metricName: "rule-1",
sampledRequestsEnabled: false,
},
},
{
name: "rule-2",
priority: 2,
action: {
count: {},
},
statement: {
orStatement: {
statements: [
{
regexMatchStatement: {
regexString: "a-z?",
fieldToMatch: {
singleHeader: {
name: "user-agent",
},
},
textTransformations: [{
priority: 6,
type: "NONE",
}],
},
},
{
sqliMatchStatement: {
fieldToMatch: {
body: {},
},
textTransformations: [
{
priority: 5,
type: "URL_DECODE",
},
{
priority: 4,
type: "HTML_ENTITY_DECODE",
},
{
priority: 3,
type: "COMPRESS_WHITE_SPACE",
},
],
},
},
{
xssMatchStatement: {
fieldToMatch: {
method: {},
},
textTransformations: [{
priority: 2,
type: "NONE",
}],
},
},
],
},
},
visibilityConfig: {
cloudwatchMetricsEnabled: false,
metricName: "rule-2",
sampledRequestsEnabled: false,
},
captchaConfig: {
immunityTimeProperty: {
immunityTime: 240,
},
},
},
{
name: "rule-3",
priority: 3,
action: {
block: {},
},
statement: {
sizeConstraintStatement: {
comparisonOperator: "GT",
size: 100,
fieldToMatch: {
singleQueryArgument: {
name: "username",
},
},
textTransformations: [{
priority: 5,
type: "NONE",
}],
},
},
visibilityConfig: {
cloudwatchMetricsEnabled: false,
metricName: "rule-3",
sampledRequestsEnabled: false,
},
},
{
name: "rule-4",
priority: 4,
action: {
block: {},
},
statement: {
orStatement: {
statements: [
{
ipSetReferenceStatement: {
arn: test.arn,
},
},
{
regexPatternSetReferenceStatement: {
arn: testRegexPatternSet.arn,
fieldToMatch: {
singleHeader: {
name: "referer",
},
},
textTransformations: [{
priority: 2,
type: "NONE",
}],
},
},
],
},
},
visibilityConfig: {
cloudwatchMetricsEnabled: false,
metricName: "rule-4",
sampledRequestsEnabled: false,
},
},
],
visibilityConfig: {
cloudwatchMetricsEnabled: false,
metricName: "friendly-metric-name",
sampledRequestsEnabled: false,
},
captchaConfig: [{
immunityTimeProperty: [{
immunityTime: 120,
}],
}],
tags: {
Name: "example-and-statement",
Code: "123456",
},
});
import pulumi
import pulumi_aws as aws
test = aws.wafv2.IpSet("test",
name="test",
scope="REGIONAL",
ip_address_version="IPV4",
addresses=[
"1.1.1.1/32",
"2.2.2.2/32",
])
test_regex_pattern_set = aws.wafv2.RegexPatternSet("test",
name="test",
scope="REGIONAL",
regular_expressions=[{
"regex_string": "one",
}])
example = aws.wafv2.RuleGroup("example",
name="complex-example",
description="An rule group containing all statements",
scope="REGIONAL",
capacity=500,
rules=[
{
"name": "rule-1",
"priority": 1,
"action": {
"block": {},
},
"statement": {
"not_statement": {
"statements": [{
"and_statement": {
"statements": [
{
"geo_match_statement": {
"country_codes": ["US"],
},
},
{
"byte_match_statement": {
"positional_constraint": "CONTAINS",
"search_string": "word",
"field_to_match": {
"all_query_arguments": {},
},
"text_transformations": [
{
"priority": 5,
"type": "CMD_LINE",
},
{
"priority": 2,
"type": "LOWERCASE",
},
],
},
},
],
},
}],
},
},
"visibility_config": {
"cloudwatch_metrics_enabled": False,
"metric_name": "rule-1",
"sampled_requests_enabled": False,
},
},
{
"name": "rule-2",
"priority": 2,
"action": {
"count": {},
},
"statement": {
"or_statement": {
"statements": [
{
"regex_match_statement": {
"regex_string": "a-z?",
"field_to_match": {
"single_header": {
"name": "user-agent",
},
},
"text_transformations": [{
"priority": 6,
"type": "NONE",
}],
},
},
{
"sqli_match_statement": {
"field_to_match": {
"body": {},
},
"text_transformations": [
{
"priority": 5,
"type": "URL_DECODE",
},
{
"priority": 4,
"type": "HTML_ENTITY_DECODE",
},
{
"priority": 3,
"type": "COMPRESS_WHITE_SPACE",
},
],
},
},
{
"xss_match_statement": {
"field_to_match": {
"method": {},
},
"text_transformations": [{
"priority": 2,
"type": "NONE",
}],
},
},
],
},
},
"visibility_config": {
"cloudwatch_metrics_enabled": False,
"metric_name": "rule-2",
"sampled_requests_enabled": False,
},
"captcha_config": {
"immunity_time_property": {
"immunity_time": 240,
},
},
},
{
"name": "rule-3",
"priority": 3,
"action": {
"block": {},
},
"statement": {
"size_constraint_statement": {
"comparison_operator": "GT",
"size": 100,
"field_to_match": {
"single_query_argument": {
"name": "username",
},
},
"text_transformations": [{
"priority": 5,
"type": "NONE",
}],
},
},
"visibility_config": {
"cloudwatch_metrics_enabled": False,
"metric_name": "rule-3",
"sampled_requests_enabled": False,
},
},
{
"name": "rule-4",
"priority": 4,
"action": {
"block": {},
},
"statement": {
"or_statement": {
"statements": [
{
"ip_set_reference_statement": {
"arn": test.arn,
},
},
{
"regex_pattern_set_reference_statement": {
"arn": test_regex_pattern_set.arn,
"field_to_match": {
"single_header": {
"name": "referer",
},
},
"text_transformations": [{
"priority": 2,
"type": "NONE",
}],
},
},
],
},
},
"visibility_config": {
"cloudwatch_metrics_enabled": False,
"metric_name": "rule-4",
"sampled_requests_enabled": False,
},
},
],
visibility_config={
"cloudwatch_metrics_enabled": False,
"metric_name": "friendly-metric-name",
"sampled_requests_enabled": False,
},
captcha_config=[{
"immunityTimeProperty": [{
"immunityTime": 120,
}],
}],
tags={
"Name": "example-and-statement",
"Code": "123456",
})
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 {
test, err := wafv2.NewIpSet(ctx, "test", &wafv2.IpSetArgs{
Name: pulumi.String("test"),
Scope: pulumi.String("REGIONAL"),
IpAddressVersion: pulumi.String("IPV4"),
Addresses: pulumi.StringArray{
pulumi.String("1.1.1.1/32"),
pulumi.String("2.2.2.2/32"),
},
})
if err != nil {
return err
}
testRegexPatternSet, err := wafv2.NewRegexPatternSet(ctx, "test", &wafv2.RegexPatternSetArgs{
Name: pulumi.String("test"),
Scope: pulumi.String("REGIONAL"),
RegularExpressions: wafv2.RegexPatternSetRegularExpressionArray{
&wafv2.RegexPatternSetRegularExpressionArgs{
RegexString: pulumi.String("one"),
},
},
})
if err != nil {
return err
}
_, err = wafv2.NewRuleGroup(ctx, "example", &wafv2.RuleGroupArgs{
Name: pulumi.String("complex-example"),
Description: pulumi.String("An rule group containing all statements"),
Scope: pulumi.String("REGIONAL"),
Capacity: pulumi.Int(500),
Rules: wafv2.RuleGroupRuleArray{
&wafv2.RuleGroupRuleArgs{
Name: pulumi.String("rule-1"),
Priority: pulumi.Int(1),
Action: &wafv2.RuleGroupRuleActionArgs{
Block: &wafv2.RuleGroupRuleActionBlockArgs{},
},
Statement: &wafv2.RuleGroupRuleStatementArgs{
NotStatement: &wafv2.RuleGroupRuleStatementNotStatementArgs{
Statements: wafv2.RuleGroupRuleStatementArray{
&wafv2.RuleGroupRuleStatementArgs{
AndStatement: &wafv2.RuleGroupRuleStatementAndStatementArgs{
Statements: wafv2.RuleGroupRuleStatementArray{
&wafv2.RuleGroupRuleStatementArgs{
GeoMatchStatement: &wafv2.RuleGroupRuleStatementGeoMatchStatementArgs{
CountryCodes: pulumi.StringArray{
pulumi.String("US"),
},
},
},
&wafv2.RuleGroupRuleStatementArgs{
ByteMatchStatement: &wafv2.RuleGroupRuleStatementByteMatchStatementArgs{
PositionalConstraint: pulumi.String("CONTAINS"),
SearchString: pulumi.String("word"),
FieldToMatch: &wafv2.RuleGroupRuleStatementByteMatchStatementFieldToMatchArgs{
AllQueryArguments: &wafv2.RuleGroupRuleStatementByteMatchStatementFieldToMatchAllQueryArgumentsArgs{},
},
TextTransformations: wafv2.RuleGroupRuleStatementByteMatchStatementTextTransformationArray{
&wafv2.RuleGroupRuleStatementByteMatchStatementTextTransformationArgs{
Priority: pulumi.Int(5),
Type: pulumi.String("CMD_LINE"),
},
&wafv2.RuleGroupRuleStatementByteMatchStatementTextTransformationArgs{
Priority: pulumi.Int(2),
Type: pulumi.String("LOWERCASE"),
},
},
},
},
},
},
},
},
},
},
VisibilityConfig: &wafv2.RuleGroupRuleVisibilityConfigArgs{
CloudwatchMetricsEnabled: pulumi.Bool(false),
MetricName: pulumi.String("rule-1"),
SampledRequestsEnabled: pulumi.Bool(false),
},
},
&wafv2.RuleGroupRuleArgs{
Name: pulumi.String("rule-2"),
Priority: pulumi.Int(2),
Action: &wafv2.RuleGroupRuleActionArgs{
Count: &wafv2.RuleGroupRuleActionCountArgs{},
},
Statement: &wafv2.RuleGroupRuleStatementArgs{
OrStatement: &wafv2.RuleGroupRuleStatementOrStatementArgs{
Statements: wafv2.RuleGroupRuleStatementArray{
&wafv2.RuleGroupRuleStatementArgs{
RegexMatchStatement: &wafv2.RuleGroupRuleStatementRegexMatchStatementArgs{
RegexString: pulumi.String("a-z?"),
FieldToMatch: &wafv2.RuleGroupRuleStatementRegexMatchStatementFieldToMatchArgs{
SingleHeader: &wafv2.RuleGroupRuleStatementRegexMatchStatementFieldToMatchSingleHeaderArgs{
Name: pulumi.String("user-agent"),
},
},
TextTransformations: wafv2.RuleGroupRuleStatementRegexMatchStatementTextTransformationArray{
&wafv2.RuleGroupRuleStatementRegexMatchStatementTextTransformationArgs{
Priority: pulumi.Int(6),
Type: pulumi.String("NONE"),
},
},
},
},
&wafv2.RuleGroupRuleStatementArgs{
SqliMatchStatement: &wafv2.RuleGroupRuleStatementSqliMatchStatementArgs{
FieldToMatch: &wafv2.RuleGroupRuleStatementSqliMatchStatementFieldToMatchArgs{
Body: &wafv2.RuleGroupRuleStatementSqliMatchStatementFieldToMatchBodyArgs{},
},
TextTransformations: wafv2.RuleGroupRuleStatementSqliMatchStatementTextTransformationArray{
&wafv2.RuleGroupRuleStatementSqliMatchStatementTextTransformationArgs{
Priority: pulumi.Int(5),
Type: pulumi.String("URL_DECODE"),
},
&wafv2.RuleGroupRuleStatementSqliMatchStatementTextTransformationArgs{
Priority: pulumi.Int(4),
Type: pulumi.String("HTML_ENTITY_DECODE"),
},
&wafv2.RuleGroupRuleStatementSqliMatchStatementTextTransformationArgs{
Priority: pulumi.Int(3),
Type: pulumi.String("COMPRESS_WHITE_SPACE"),
},
},
},
},
&wafv2.RuleGroupRuleStatementArgs{
XssMatchStatement: &wafv2.RuleGroupRuleStatementXssMatchStatementArgs{
FieldToMatch: &wafv2.RuleGroupRuleStatementXssMatchStatementFieldToMatchArgs{
Method: &wafv2.RuleGroupRuleStatementXssMatchStatementFieldToMatchMethodArgs{},
},
TextTransformations: wafv2.RuleGroupRuleStatementXssMatchStatementTextTransformationArray{
&wafv2.RuleGroupRuleStatementXssMatchStatementTextTransformationArgs{
Priority: pulumi.Int(2),
Type: pulumi.String("NONE"),
},
},
},
},
},
},
},
VisibilityConfig: &wafv2.RuleGroupRuleVisibilityConfigArgs{
CloudwatchMetricsEnabled: pulumi.Bool(false),
MetricName: pulumi.String("rule-2"),
SampledRequestsEnabled: pulumi.Bool(false),
},
CaptchaConfig: &wafv2.RuleGroupRuleCaptchaConfigArgs{
ImmunityTimeProperty: &wafv2.RuleGroupRuleCaptchaConfigImmunityTimePropertyArgs{
ImmunityTime: pulumi.Int(240),
},
},
},
&wafv2.RuleGroupRuleArgs{
Name: pulumi.String("rule-3"),
Priority: pulumi.Int(3),
Action: &wafv2.RuleGroupRuleActionArgs{
Block: &wafv2.RuleGroupRuleActionBlockArgs{},
},
Statement: &wafv2.RuleGroupRuleStatementArgs{
SizeConstraintStatement: &wafv2.RuleGroupRuleStatementSizeConstraintStatementArgs{
ComparisonOperator: pulumi.String("GT"),
Size: pulumi.Int(100),
FieldToMatch: &wafv2.RuleGroupRuleStatementSizeConstraintStatementFieldToMatchArgs{
SingleQueryArgument: &wafv2.RuleGroupRuleStatementSizeConstraintStatementFieldToMatchSingleQueryArgumentArgs{
Name: pulumi.String("username"),
},
},
TextTransformations: wafv2.RuleGroupRuleStatementSizeConstraintStatementTextTransformationArray{
&wafv2.RuleGroupRuleStatementSizeConstraintStatementTextTransformationArgs{
Priority: pulumi.Int(5),
Type: pulumi.String("NONE"),
},
},
},
},
VisibilityConfig: &wafv2.RuleGroupRuleVisibilityConfigArgs{
CloudwatchMetricsEnabled: pulumi.Bool(false),
MetricName: pulumi.String("rule-3"),
SampledRequestsEnabled: pulumi.Bool(false),
},
},
&wafv2.RuleGroupRuleArgs{
Name: pulumi.String("rule-4"),
Priority: pulumi.Int(4),
Action: &wafv2.RuleGroupRuleActionArgs{
Block: &wafv2.RuleGroupRuleActionBlockArgs{},
},
Statement: &wafv2.RuleGroupRuleStatementArgs{
OrStatement: &wafv2.RuleGroupRuleStatementOrStatementArgs{
Statements: wafv2.RuleGroupRuleStatementArray{
&wafv2.RuleGroupRuleStatementArgs{
IpSetReferenceStatement: &wafv2.RuleGroupRuleStatementIpSetReferenceStatementArgs{
Arn: test.Arn,
},
},
&wafv2.RuleGroupRuleStatementArgs{
RegexPatternSetReferenceStatement: &wafv2.RuleGroupRuleStatementRegexPatternSetReferenceStatementArgs{
Arn: testRegexPatternSet.Arn,
FieldToMatch: &wafv2.RuleGroupRuleStatementRegexPatternSetReferenceStatementFieldToMatchArgs{
SingleHeader: &wafv2.RuleGroupRuleStatementRegexPatternSetReferenceStatementFieldToMatchSingleHeaderArgs{
Name: pulumi.String("referer"),
},
},
TextTransformations: wafv2.RuleGroupRuleStatementRegexPatternSetReferenceStatementTextTransformationArray{
&wafv2.RuleGroupRuleStatementRegexPatternSetReferenceStatementTextTransformationArgs{
Priority: pulumi.Int(2),
Type: pulumi.String("NONE"),
},
},
},
},
},
},
},
VisibilityConfig: &wafv2.RuleGroupRuleVisibilityConfigArgs{
CloudwatchMetricsEnabled: pulumi.Bool(false),
MetricName: pulumi.String("rule-4"),
SampledRequestsEnabled: pulumi.Bool(false),
},
},
},
VisibilityConfig: &wafv2.RuleGroupVisibilityConfigArgs{
CloudwatchMetricsEnabled: pulumi.Bool(false),
MetricName: pulumi.String("friendly-metric-name"),
SampledRequestsEnabled: pulumi.Bool(false),
},
CaptchaConfig: []map[string]interface{}{
map[string]interface{}{
"immunityTimeProperty": []map[string]interface{}{
map[string]interface{}{
"immunityTime": 120,
},
},
},
},
Tags: pulumi.StringMap{
"Name": pulumi.String("example-and-statement"),
"Code": pulumi.String("123456"),
},
})
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 test = new Aws.WafV2.IpSet("test", new()
{
Name = "test",
Scope = "REGIONAL",
IpAddressVersion = "IPV4",
Addresses = new[]
{
"1.1.1.1/32",
"2.2.2.2/32",
},
});
var testRegexPatternSet = new Aws.WafV2.RegexPatternSet("test", new()
{
Name = "test",
Scope = "REGIONAL",
RegularExpressions = new[]
{
new Aws.WafV2.Inputs.RegexPatternSetRegularExpressionArgs
{
RegexString = "one",
},
},
});
var example = new Aws.WafV2.RuleGroup("example", new()
{
Name = "complex-example",
Description = "An rule group containing all statements",
Scope = "REGIONAL",
Capacity = 500,
Rules = new[]
{
new Aws.WafV2.Inputs.RuleGroupRuleArgs
{
Name = "rule-1",
Priority = 1,
Action = new Aws.WafV2.Inputs.RuleGroupRuleActionArgs
{
Block = null,
},
Statement = new Aws.WafV2.Inputs.RuleGroupRuleStatementArgs
{
NotStatement = new Aws.WafV2.Inputs.RuleGroupRuleStatementNotStatementArgs
{
Statements = new[]
{
new Aws.WafV2.Inputs.RuleGroupRuleStatementArgs
{
AndStatement = new Aws.WafV2.Inputs.RuleGroupRuleStatementAndStatementArgs
{
Statements = new[]
{
new Aws.WafV2.Inputs.RuleGroupRuleStatementArgs
{
GeoMatchStatement = new Aws.WafV2.Inputs.RuleGroupRuleStatementGeoMatchStatementArgs
{
CountryCodes = new[]
{
"US",
},
},
},
new Aws.WafV2.Inputs.RuleGroupRuleStatementArgs
{
ByteMatchStatement = new Aws.WafV2.Inputs.RuleGroupRuleStatementByteMatchStatementArgs
{
PositionalConstraint = "CONTAINS",
SearchString = "word",
FieldToMatch = new Aws.WafV2.Inputs.RuleGroupRuleStatementByteMatchStatementFieldToMatchArgs
{
AllQueryArguments = null,
},
TextTransformations = new[]
{
new Aws.WafV2.Inputs.RuleGroupRuleStatementByteMatchStatementTextTransformationArgs
{
Priority = 5,
Type = "CMD_LINE",
},
new Aws.WafV2.Inputs.RuleGroupRuleStatementByteMatchStatementTextTransformationArgs
{
Priority = 2,
Type = "LOWERCASE",
},
},
},
},
},
},
},
},
},
},
VisibilityConfig = new Aws.WafV2.Inputs.RuleGroupRuleVisibilityConfigArgs
{
CloudwatchMetricsEnabled = false,
MetricName = "rule-1",
SampledRequestsEnabled = false,
},
},
new Aws.WafV2.Inputs.RuleGroupRuleArgs
{
Name = "rule-2",
Priority = 2,
Action = new Aws.WafV2.Inputs.RuleGroupRuleActionArgs
{
Count = null,
},
Statement = new Aws.WafV2.Inputs.RuleGroupRuleStatementArgs
{
OrStatement = new Aws.WafV2.Inputs.RuleGroupRuleStatementOrStatementArgs
{
Statements = new[]
{
new Aws.WafV2.Inputs.RuleGroupRuleStatementArgs
{
RegexMatchStatement = new Aws.WafV2.Inputs.RuleGroupRuleStatementRegexMatchStatementArgs
{
RegexString = "a-z?",
FieldToMatch = new Aws.WafV2.Inputs.RuleGroupRuleStatementRegexMatchStatementFieldToMatchArgs
{
SingleHeader = new Aws.WafV2.Inputs.RuleGroupRuleStatementRegexMatchStatementFieldToMatchSingleHeaderArgs
{
Name = "user-agent",
},
},
TextTransformations = new[]
{
new Aws.WafV2.Inputs.RuleGroupRuleStatementRegexMatchStatementTextTransformationArgs
{
Priority = 6,
Type = "NONE",
},
},
},
},
new Aws.WafV2.Inputs.RuleGroupRuleStatementArgs
{
SqliMatchStatement = new Aws.WafV2.Inputs.RuleGroupRuleStatementSqliMatchStatementArgs
{
FieldToMatch = new Aws.WafV2.Inputs.RuleGroupRuleStatementSqliMatchStatementFieldToMatchArgs
{
Body = null,
},
TextTransformations = new[]
{
new Aws.WafV2.Inputs.RuleGroupRuleStatementSqliMatchStatementTextTransformationArgs
{
Priority = 5,
Type = "URL_DECODE",
},
new Aws.WafV2.Inputs.RuleGroupRuleStatementSqliMatchStatementTextTransformationArgs
{
Priority = 4,
Type = "HTML_ENTITY_DECODE",
},
new Aws.WafV2.Inputs.RuleGroupRuleStatementSqliMatchStatementTextTransformationArgs
{
Priority = 3,
Type = "COMPRESS_WHITE_SPACE",
},
},
},
},
new Aws.WafV2.Inputs.RuleGroupRuleStatementArgs
{
XssMatchStatement = new Aws.WafV2.Inputs.RuleGroupRuleStatementXssMatchStatementArgs
{
FieldToMatch = new Aws.WafV2.Inputs.RuleGroupRuleStatementXssMatchStatementFieldToMatchArgs
{
Method = null,
},
TextTransformations = new[]
{
new Aws.WafV2.Inputs.RuleGroupRuleStatementXssMatchStatementTextTransformationArgs
{
Priority = 2,
Type = "NONE",
},
},
},
},
},
},
},
VisibilityConfig = new Aws.WafV2.Inputs.RuleGroupRuleVisibilityConfigArgs
{
CloudwatchMetricsEnabled = false,
MetricName = "rule-2",
SampledRequestsEnabled = false,
},
CaptchaConfig = new Aws.WafV2.Inputs.RuleGroupRuleCaptchaConfigArgs
{
ImmunityTimeProperty = new Aws.WafV2.Inputs.RuleGroupRuleCaptchaConfigImmunityTimePropertyArgs
{
ImmunityTime = 240,
},
},
},
new Aws.WafV2.Inputs.RuleGroupRuleArgs
{
Name = "rule-3",
Priority = 3,
Action = new Aws.WafV2.Inputs.RuleGroupRuleActionArgs
{
Block = null,
},
Statement = new Aws.WafV2.Inputs.RuleGroupRuleStatementArgs
{
SizeConstraintStatement = new Aws.WafV2.Inputs.RuleGroupRuleStatementSizeConstraintStatementArgs
{
ComparisonOperator = "GT",
Size = 100,
FieldToMatch = new Aws.WafV2.Inputs.RuleGroupRuleStatementSizeConstraintStatementFieldToMatchArgs
{
SingleQueryArgument = new Aws.WafV2.Inputs.RuleGroupRuleStatementSizeConstraintStatementFieldToMatchSingleQueryArgumentArgs
{
Name = "username",
},
},
TextTransformations = new[]
{
new Aws.WafV2.Inputs.RuleGroupRuleStatementSizeConstraintStatementTextTransformationArgs
{
Priority = 5,
Type = "NONE",
},
},
},
},
VisibilityConfig = new Aws.WafV2.Inputs.RuleGroupRuleVisibilityConfigArgs
{
CloudwatchMetricsEnabled = false,
MetricName = "rule-3",
SampledRequestsEnabled = false,
},
},
new Aws.WafV2.Inputs.RuleGroupRuleArgs
{
Name = "rule-4",
Priority = 4,
Action = new Aws.WafV2.Inputs.RuleGroupRuleActionArgs
{
Block = null,
},
Statement = new Aws.WafV2.Inputs.RuleGroupRuleStatementArgs
{
OrStatement = new Aws.WafV2.Inputs.RuleGroupRuleStatementOrStatementArgs
{
Statements = new[]
{
new Aws.WafV2.Inputs.RuleGroupRuleStatementArgs
{
IpSetReferenceStatement = new Aws.WafV2.Inputs.RuleGroupRuleStatementIpSetReferenceStatementArgs
{
Arn = test.Arn,
},
},
new Aws.WafV2.Inputs.RuleGroupRuleStatementArgs
{
RegexPatternSetReferenceStatement = new Aws.WafV2.Inputs.RuleGroupRuleStatementRegexPatternSetReferenceStatementArgs
{
Arn = testRegexPatternSet.Arn,
FieldToMatch = new Aws.WafV2.Inputs.RuleGroupRuleStatementRegexPatternSetReferenceStatementFieldToMatchArgs
{
SingleHeader = new Aws.WafV2.Inputs.RuleGroupRuleStatementRegexPatternSetReferenceStatementFieldToMatchSingleHeaderArgs
{
Name = "referer",
},
},
TextTransformations = new[]
{
new Aws.WafV2.Inputs.RuleGroupRuleStatementRegexPatternSetReferenceStatementTextTransformationArgs
{
Priority = 2,
Type = "NONE",
},
},
},
},
},
},
},
VisibilityConfig = new Aws.WafV2.Inputs.RuleGroupRuleVisibilityConfigArgs
{
CloudwatchMetricsEnabled = false,
MetricName = "rule-4",
SampledRequestsEnabled = false,
},
},
},
VisibilityConfig = new Aws.WafV2.Inputs.RuleGroupVisibilityConfigArgs
{
CloudwatchMetricsEnabled = false,
MetricName = "friendly-metric-name",
SampledRequestsEnabled = false,
},
CaptchaConfig = new[]
{
{
{ "immunityTimeProperty", new[]
{
{
{ "immunityTime", 120 },
},
} },
},
},
Tags =
{
{ "Name", "example-and-statement" },
{ "Code", "123456" },
},
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.wafv2.IpSet;
import com.pulumi.aws.wafv2.IpSetArgs;
import com.pulumi.aws.wafv2.RegexPatternSet;
import com.pulumi.aws.wafv2.RegexPatternSetArgs;
import com.pulumi.aws.wafv2.inputs.RegexPatternSetRegularExpressionArgs;
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.RuleGroupRuleStatementNotStatementArgs;
import com.pulumi.aws.wafv2.inputs.RuleGroupRuleVisibilityConfigArgs;
import com.pulumi.aws.wafv2.inputs.RuleGroupRuleActionCountArgs;
import com.pulumi.aws.wafv2.inputs.RuleGroupRuleStatementOrStatementArgs;
import com.pulumi.aws.wafv2.inputs.RuleGroupRuleCaptchaConfigArgs;
import com.pulumi.aws.wafv2.inputs.RuleGroupRuleCaptchaConfigImmunityTimePropertyArgs;
import com.pulumi.aws.wafv2.inputs.RuleGroupRuleStatementSizeConstraintStatementArgs;
import com.pulumi.aws.wafv2.inputs.RuleGroupRuleStatementSizeConstraintStatementFieldToMatchArgs;
import com.pulumi.aws.wafv2.inputs.RuleGroupRuleStatementSizeConstraintStatementFieldToMatchSingleQueryArgumentArgs;
import com.pulumi.aws.wafv2.inputs.RuleGroupVisibilityConfigArgs;
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 test = new IpSet("test", IpSetArgs.builder()
.name("test")
.scope("REGIONAL")
.ipAddressVersion("IPV4")
.addresses(
"1.1.1.1/32",
"2.2.2.2/32")
.build());
var testRegexPatternSet = new RegexPatternSet("testRegexPatternSet", RegexPatternSetArgs.builder()
.name("test")
.scope("REGIONAL")
.regularExpressions(RegexPatternSetRegularExpressionArgs.builder()
.regexString("one")
.build())
.build());
var example = new RuleGroup("example", RuleGroupArgs.builder()
.name("complex-example")
.description("An rule group containing all statements")
.scope("REGIONAL")
.capacity(500)
.rules(
RuleGroupRuleArgs.builder()
.name("rule-1")
.priority(1)
.action(RuleGroupRuleActionArgs.builder()
.block(RuleGroupRuleActionBlockArgs.builder()
.build())
.build())
.statement(RuleGroupRuleStatementArgs.builder()
.notStatement(Map.of("statements", Map.of("andStatement", Map.of("statements",
RuleGroupRuleStatementArgs.builder()
.geoMatchStatement(RuleGroupRuleStatementGeoMatchStatementArgs.builder()
.countryCodes("US")
.build())
.build(),
RuleGroupRuleStatementArgs.builder()
.byteMatchStatement(RuleGroupRuleStatementByteMatchStatementArgs.builder()
.positionalConstraint("CONTAINS")
.searchString("word")
.fieldToMatch(RuleGroupRuleStatementByteMatchStatementFieldToMatchArgs.builder()
.allQueryArguments(RuleGroupRuleStatementByteMatchStatementFieldToMatchAllQueryArgumentsArgs.builder()
.build())
.build())
.textTransformations(
RuleGroupRuleStatementByteMatchStatementTextTransformationArgs.builder()
.priority(5)
.type("CMD_LINE")
.build(),
RuleGroupRuleStatementByteMatchStatementTextTransformationArgs.builder()
.priority(2)
.type("LOWERCASE")
.build())
.build())
.build()))))
.build())
.visibilityConfig(RuleGroupRuleVisibilityConfigArgs.builder()
.cloudwatchMetricsEnabled(false)
.metricName("rule-1")
.sampledRequestsEnabled(false)
.build())
.build(),
RuleGroupRuleArgs.builder()
.name("rule-2")
.priority(2)
.action(RuleGroupRuleActionArgs.builder()
.count(RuleGroupRuleActionCountArgs.builder()
.build())
.build())
.statement(Map.of("orStatement", Map.of("statements",
RuleGroupRuleStatementArgs.builder()
.regexMatchStatement(RuleGroupRuleStatementRegexMatchStatementArgs.builder()
.regexString("a-z?")
.fieldToMatch(RuleGroupRuleStatementRegexMatchStatementFieldToMatchArgs.builder()
.singleHeader(RuleGroupRuleStatementRegexMatchStatementFieldToMatchSingleHeaderArgs.builder()
.name("user-agent")
.build())
.build())
.textTransformations(RuleGroupRuleStatementRegexMatchStatementTextTransformationArgs.builder()
.priority(6)
.type("NONE")
.build())
.build())
.build(),
RuleGroupRuleStatementArgs.builder()
.sqliMatchStatement(RuleGroupRuleStatementSqliMatchStatementArgs.builder()
.fieldToMatch(RuleGroupRuleStatementSqliMatchStatementFieldToMatchArgs.builder()
.body(RuleGroupRuleStatementSqliMatchStatementFieldToMatchBodyArgs.builder()
.build())
.build())
.textTransformations(
RuleGroupRuleStatementSqliMatchStatementTextTransformationArgs.builder()
.priority(5)
.type("URL_DECODE")
.build(),
RuleGroupRuleStatementSqliMatchStatementTextTransformationArgs.builder()
.priority(4)
.type("HTML_ENTITY_DECODE")
.build(),
RuleGroupRuleStatementSqliMatchStatementTextTransformationArgs.builder()
.priority(3)
.type("COMPRESS_WHITE_SPACE")
.build())
.build())
.build(),
RuleGroupRuleStatementArgs.builder()
.xssMatchStatement(RuleGroupRuleStatementXssMatchStatementArgs.builder()
.fieldToMatch(RuleGroupRuleStatementXssMatchStatementFieldToMatchArgs.builder()
.method(RuleGroupRuleStatementXssMatchStatementFieldToMatchMethodArgs.builder()
.build())
.build())
.textTransformations(RuleGroupRuleStatementXssMatchStatementTextTransformationArgs.builder()
.priority(2)
.type("NONE")
.build())
.build())
.build())))
.visibilityConfig(RuleGroupRuleVisibilityConfigArgs.builder()
.cloudwatchMetricsEnabled(false)
.metricName("rule-2")
.sampledRequestsEnabled(false)
.build())
.captchaConfig(RuleGroupRuleCaptchaConfigArgs.builder()
.immunityTimeProperty(RuleGroupRuleCaptchaConfigImmunityTimePropertyArgs.builder()
.immunityTime(240)
.build())
.build())
.build(),
RuleGroupRuleArgs.builder()
.name("rule-3")
.priority(3)
.action(RuleGroupRuleActionArgs.builder()
.block(RuleGroupRuleActionBlockArgs.builder()
.build())
.build())
.statement(RuleGroupRuleStatementArgs.builder()
.sizeConstraintStatement(RuleGroupRuleStatementSizeConstraintStatementArgs.builder()
.comparisonOperator("GT")
.size(100)
.fieldToMatch(RuleGroupRuleStatementSizeConstraintStatementFieldToMatchArgs.builder()
.singleQueryArgument(RuleGroupRuleStatementSizeConstraintStatementFieldToMatchSingleQueryArgumentArgs.builder()
.name("username")
.build())
.build())
.textTransformations(RuleGroupRuleStatementSizeConstraintStatementTextTransformationArgs.builder()
.priority(5)
.type("NONE")
.build())
.build())
.build())
.visibilityConfig(RuleGroupRuleVisibilityConfigArgs.builder()
.cloudwatchMetricsEnabled(false)
.metricName("rule-3")
.sampledRequestsEnabled(false)
.build())
.build(),
RuleGroupRuleArgs.builder()
.name("rule-4")
.priority(4)
.action(RuleGroupRuleActionArgs.builder()
.block(RuleGroupRuleActionBlockArgs.builder()
.build())
.build())
.statement(RuleGroupRuleStatementArgs.builder()
.orStatement(Map.of("statements",
RuleGroupRuleStatementArgs.builder()
.ipSetReferenceStatement(RuleGroupRuleStatementIpSetReferenceStatementArgs.builder()
.arn(test.arn())
.build())
.build(),
RuleGroupRuleStatementArgs.builder()
.regexPatternSetReferenceStatement(RuleGroupRuleStatementRegexPatternSetReferenceStatementArgs.builder()
.arn(testRegexPatternSet.arn())
.fieldToMatch(RuleGroupRuleStatementRegexPatternSetReferenceStatementFieldToMatchArgs.builder()
.singleHeader(RuleGroupRuleStatementRegexPatternSetReferenceStatementFieldToMatchSingleHeaderArgs.builder()
.name("referer")
.build())
.build())
.textTransformations(RuleGroupRuleStatementRegexPatternSetReferenceStatementTextTransformationArgs.builder()
.priority(2)
.type("NONE")
.build())
.build())
.build()))
.build())
.visibilityConfig(RuleGroupRuleVisibilityConfigArgs.builder()
.cloudwatchMetricsEnabled(false)
.metricName("rule-4")
.sampledRequestsEnabled(false)
.build())
.build())
.visibilityConfig(RuleGroupVisibilityConfigArgs.builder()
.cloudwatchMetricsEnabled(false)
.metricName("friendly-metric-name")
.sampledRequestsEnabled(false)
.build())
.captchaConfig(List.of(Map.of("immunityTimeProperty", List.of(Map.of("immunityTime", 120)))))
.tags(Map.ofEntries(
Map.entry("Name", "example-and-statement"),
Map.entry("Code", "123456")
))
.build());
}
}
resources:
test:
type: aws:wafv2:IpSet
properties:
name: test
scope: REGIONAL
ipAddressVersion: IPV4
addresses:
- 1.1.1.1/32
- 2.2.2.2/32
testRegexPatternSet:
type: aws:wafv2:RegexPatternSet
name: test
properties:
name: test
scope: REGIONAL
regularExpressions:
- regexString: one
example:
type: aws:wafv2:RuleGroup
properties:
name: complex-example
description: An rule group containing all statements
scope: REGIONAL
capacity: 500
rules:
- name: rule-1
priority: 1
action:
block: {}
statement:
notStatement:
statements:
- andStatement:
statements:
- geoMatchStatement:
countryCodes:
- US
- byteMatchStatement:
positionalConstraint: CONTAINS
searchString: word
fieldToMatch:
allQueryArguments: {}
textTransformations:
- priority: 5
type: CMD_LINE
- priority: 2
type: LOWERCASE
visibilityConfig:
cloudwatchMetricsEnabled: false
metricName: rule-1
sampledRequestsEnabled: false
- name: rule-2
priority: 2
action:
count: {}
statement:
orStatement:
statements:
- regexMatchStatement:
regexString: a-z?
fieldToMatch:
singleHeader:
name: user-agent
textTransformations:
- priority: 6
type: NONE
- sqliMatchStatement:
fieldToMatch:
body: {}
textTransformations:
- priority: 5
type: URL_DECODE
- priority: 4
type: HTML_ENTITY_DECODE
- priority: 3
type: COMPRESS_WHITE_SPACE
- xssMatchStatement:
fieldToMatch:
method: {}
textTransformations:
- priority: 2
type: NONE
visibilityConfig:
cloudwatchMetricsEnabled: false
metricName: rule-2
sampledRequestsEnabled: false
captchaConfig:
immunityTimeProperty:
immunityTime: 240
- name: rule-3
priority: 3
action:
block: {}
statement:
sizeConstraintStatement:
comparisonOperator: GT
size: 100
fieldToMatch:
singleQueryArgument:
name: username
textTransformations:
- priority: 5
type: NONE
visibilityConfig:
cloudwatchMetricsEnabled: false
metricName: rule-3
sampledRequestsEnabled: false
- name: rule-4
priority: 4
action:
block: {}
statement:
orStatement:
statements:
- ipSetReferenceStatement:
arn: ${test.arn}
- regexPatternSetReferenceStatement:
arn: ${testRegexPatternSet.arn}
fieldToMatch:
singleHeader:
name: referer
textTransformations:
- priority: 2
type: NONE
visibilityConfig:
cloudwatchMetricsEnabled: false
metricName: rule-4
sampledRequestsEnabled: false
visibilityConfig:
cloudwatchMetricsEnabled: false
metricName: friendly-metric-name
sampledRequestsEnabled: false
captchaConfig:
- immunityTimeProperty:
- immunityTime: 120
tags:
Name: example-and-statement
Code: '123456'
Logical operators nest statements to build complex conditions. The andStatement requires all nested statements to match; orStatement requires at least one; notStatement inverts the result. Each statement can inspect different request components via fieldToMatch (headers, body, query arguments) and apply textTransformations to normalize data before matching. The capacity property must be large enough to accommodate nested statement complexity; this example uses 500 WCUs.
Define deeply nested rules with raw JSON
WAFv2’s structured rule syntax has a three-level nesting limit. For more complex logic, rulesJson accepts raw JSON that bypasses this constraint.
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: 100,
rulesJson: JSON.stringify([{
Name: "rule-1",
Priority: 1,
Action: {
Count: {},
},
Statement: {
ByteMatchStatement: {
SearchString: "badbot",
FieldToMatch: {
UriPath: {},
},
TextTransformations: [{
Priority: 1,
Type: "NONE",
}],
PositionalConstraint: "CONTAINS",
},
},
VisibilityConfig: {
CloudwatchMetricsEnabled: false,
MetricName: "friendly-rule-metric-name",
SampledRequestsEnabled: false,
},
}]),
visibilityConfig: {
cloudwatchMetricsEnabled: false,
metricName: "friendly-metric-name",
sampledRequestsEnabled: false,
},
});
import pulumi
import json
import pulumi_aws as aws
example = aws.wafv2.RuleGroup("example",
name="example-rule-group",
scope="REGIONAL",
capacity=100,
rules_json=json.dumps([{
"Name": "rule-1",
"Priority": 1,
"Action": {
"Count": {},
},
"Statement": {
"ByteMatchStatement": {
"SearchString": "badbot",
"FieldToMatch": {
"UriPath": {},
},
"TextTransformations": [{
"Priority": 1,
"Type": "NONE",
}],
"PositionalConstraint": "CONTAINS",
},
},
"VisibilityConfig": {
"CloudwatchMetricsEnabled": False,
"MetricName": "friendly-rule-metric-name",
"SampledRequestsEnabled": False,
},
}]),
visibility_config={
"cloudwatch_metrics_enabled": False,
"metric_name": "friendly-metric-name",
"sampled_requests_enabled": False,
})
package main
import (
"encoding/json"
"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 {
tmpJSON0, err := json.Marshal([]map[string]interface{}{
map[string]interface{}{
"Name": "rule-1",
"Priority": 1,
"Action": map[string]interface{}{
"Count": map[string]interface{}{},
},
"Statement": map[string]interface{}{
"ByteMatchStatement": map[string]interface{}{
"SearchString": "badbot",
"FieldToMatch": map[string]interface{}{
"UriPath": map[string]interface{}{},
},
"TextTransformations": []map[string]interface{}{
map[string]interface{}{
"Priority": 1,
"Type": "NONE",
},
},
"PositionalConstraint": "CONTAINS",
},
},
"VisibilityConfig": map[string]interface{}{
"CloudwatchMetricsEnabled": false,
"MetricName": "friendly-rule-metric-name",
"SampledRequestsEnabled": false,
},
},
})
if err != nil {
return err
}
json0 := string(tmpJSON0)
_, err = wafv2.NewRuleGroup(ctx, "example", &wafv2.RuleGroupArgs{
Name: pulumi.String("example-rule-group"),
Scope: pulumi.String("REGIONAL"),
Capacity: pulumi.Int(100),
RulesJson: pulumi.String(json0),
VisibilityConfig: &wafv2.RuleGroupVisibilityConfigArgs{
CloudwatchMetricsEnabled: pulumi.Bool(false),
MetricName: pulumi.String("friendly-metric-name"),
SampledRequestsEnabled: pulumi.Bool(false),
},
})
if err != nil {
return err
}
return nil
})
}
using System.Collections.Generic;
using System.Linq;
using System.Text.Json;
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 = 100,
RulesJson = JsonSerializer.Serialize(new[]
{
new Dictionary<string, object?>
{
["Name"] = "rule-1",
["Priority"] = 1,
["Action"] = new Dictionary<string, object?>
{
["Count"] = new Dictionary<string, object?>
{
},
},
["Statement"] = new Dictionary<string, object?>
{
["ByteMatchStatement"] = new Dictionary<string, object?>
{
["SearchString"] = "badbot",
["FieldToMatch"] = new Dictionary<string, object?>
{
["UriPath"] = new Dictionary<string, object?>
{
},
},
["TextTransformations"] = new[]
{
new Dictionary<string, object?>
{
["Priority"] = 1,
["Type"] = "NONE",
},
},
["PositionalConstraint"] = "CONTAINS",
},
},
["VisibilityConfig"] = new Dictionary<string, object?>
{
["CloudwatchMetricsEnabled"] = false,
["MetricName"] = "friendly-rule-metric-name",
["SampledRequestsEnabled"] = false,
},
},
}),
VisibilityConfig = new Aws.WafV2.Inputs.RuleGroupVisibilityConfigArgs
{
CloudwatchMetricsEnabled = false,
MetricName = "friendly-metric-name",
SampledRequestsEnabled = false,
},
});
});
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.RuleGroupVisibilityConfigArgs;
import static com.pulumi.codegen.internal.Serialization.*;
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(100)
.rulesJson(serializeJson(
jsonArray(jsonObject(
jsonProperty("Name", "rule-1"),
jsonProperty("Priority", 1),
jsonProperty("Action", jsonObject(
jsonProperty("Count", jsonObject(
))
)),
jsonProperty("Statement", jsonObject(
jsonProperty("ByteMatchStatement", jsonObject(
jsonProperty("SearchString", "badbot"),
jsonProperty("FieldToMatch", jsonObject(
jsonProperty("UriPath", jsonObject(
))
)),
jsonProperty("TextTransformations", jsonArray(jsonObject(
jsonProperty("Priority", 1),
jsonProperty("Type", "NONE")
))),
jsonProperty("PositionalConstraint", "CONTAINS")
))
)),
jsonProperty("VisibilityConfig", jsonObject(
jsonProperty("CloudwatchMetricsEnabled", false),
jsonProperty("MetricName", "friendly-rule-metric-name"),
jsonProperty("SampledRequestsEnabled", false)
))
))))
.visibilityConfig(RuleGroupVisibilityConfigArgs.builder()
.cloudwatchMetricsEnabled(false)
.metricName("friendly-metric-name")
.sampledRequestsEnabled(false)
.build())
.build());
}
}
resources:
example:
type: aws:wafv2:RuleGroup
properties:
name: example-rule-group
scope: REGIONAL
capacity: 100
rulesJson:
fn::toJSON:
- Name: rule-1
Priority: 1
Action:
Count: {}
Statement:
ByteMatchStatement:
SearchString: badbot
FieldToMatch:
UriPath: {}
TextTransformations:
- Priority: 1
Type: NONE
PositionalConstraint: CONTAINS
VisibilityConfig:
CloudwatchMetricsEnabled: false
MetricName: friendly-rule-metric-name
SampledRequestsEnabled: false
visibilityConfig:
cloudwatchMetricsEnabled: false
metricName: friendly-metric-name
sampledRequestsEnabled: false
The rulesJson property takes a JSON string that follows the AWS WAFv2 API structure. This approach trades drift detection for flexibility: Pulumi cannot detect changes made outside your configuration. Use this only when the three-level nesting limit blocks your requirements.
Beyond these examples
These snippets focus on specific rule group features: geographic and pattern-based filtering, logical operators, and text transformations and field matching. They’re intentionally minimal rather than full WAF configurations.
The examples may reference pre-existing infrastructure such as IpSet and RegexPatternSet resources for the complex example. They focus on rule group configuration rather than provisioning supporting resources or WebACL attachment.
To keep things focused, common rule group patterns are omitted, including:
- Custom response bodies (customResponseBodies)
- CAPTCHA configuration and immunity periods
- Rate-based rules and bot control
- Managed rule group references
These omissions are intentional: the goal is to illustrate how each rule group feature is wired, not provide drop-in WAF modules. See the WAFv2 RuleGroup resource reference for all available configuration options.
Let's create AWS WAFv2 Rule Groups
Get started with Pulumi Cloud, then follow our quick setup guide to deploy this infrastructure.
Try Pulumi Cloud for FREEFrequently Asked Questions
Configuration & Scope
capacity, name, namePrefix, and scope properties are immutable and require resource replacement if changed.us-east-1 (N. Virginia) region. Set scope to CLOUDFRONT and configure your AWS provider with region = "us-east-1".CLOUDFRONT for AWS CloudFront distributions (requires us-east-1 region) and REGIONAL for regional applications like ALB or API Gateway.Rules & Statements
rulesJson only when you need more than 3 levels of nested statements. For standard configurations, use rules to maintain drift detection.rules attribute supports up to 3 levels of nested statements. For deeper nesting, use rulesJson instead.ipSetReferenceStatement with the IP set’s ARN, or regexPatternSetReferenceStatement with the regex pattern set’s ARN, as shown in the complex example.Drift Detection & State Management
rulesJson, drift detection is not supported. Manual changes won’t be detected or reconciled. Switch to rules if you need drift detection and have 3 or fewer nested statement levels.rulesJson set causes a one-time in-place update as the remote configuration is written to the rule attribute. This is expected behavior.Monitoring & Visibility
visibilityConfig is required at both the rule group level and for each individual rule to enable CloudWatch metrics and request sampling at different granularities.