Skip to content

Commit e9f7b3c

Browse files
authored
Merge pull request #30340 from tamiros/f-wafv2-tokendomains-30312
feat: add `token_domains` to WAFv2 Web ACL
2 parents 136277f + cbb5d85 commit e9f7b3c

File tree

4 files changed

+103
-8
lines changed

4 files changed

+103
-8
lines changed

.changelog/30340.txt

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
```release-note:enhancement
2+
resource/aws_wafv2_web_acl: Add `token_domains` argument
3+
```

internal/service/wafv2/web_acl.go

+23-2
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import (
1616
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
1717
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
1818
"github.com/hashicorp/terraform-provider-aws/internal/conns"
19+
"github.com/hashicorp/terraform-provider-aws/internal/flex"
1920
tftags "github.com/hashicorp/terraform-provider-aws/internal/tags"
2021
"github.com/hashicorp/terraform-provider-aws/internal/tfresource"
2122
"github.com/hashicorp/terraform-provider-aws/internal/verify"
@@ -145,8 +146,19 @@ func ResourceWebACL() *schema.Resource {
145146
ForceNew: true,
146147
ValidateFunc: validation.StringInSlice(wafv2.Scope_Values(), false),
147148
},
148-
names.AttrTags: tftags.TagsSchema(),
149-
names.AttrTagsAll: tftags.TagsSchemaComputed(),
149+
names.AttrTags: tftags.TagsSchema(),
150+
names.AttrTagsAll: tftags.TagsSchemaComputed(),
151+
"token_domains": {
152+
Type: schema.TypeSet,
153+
Optional: true,
154+
Elem: &schema.Schema{
155+
Type: schema.TypeString,
156+
ValidateFunc: validation.All(
157+
validation.StringLenBetween(1, 253),
158+
validation.StringMatch(regexp.MustCompile(`^[\w\.\-/]+$`), "must contain only alphanumeric, hyphen, dot, underscore and forward-slash characters"),
159+
),
160+
},
161+
},
150162
"visibility_config": visibilityConfigSchema(),
151163
},
152164

@@ -176,6 +188,10 @@ func resourceWebACLCreate(ctx context.Context, d *schema.ResourceData, meta inte
176188
input.Description = aws.String(v.(string))
177189
}
178190

191+
if v, ok := d.GetOk("token_domains"); ok && v.(*schema.Set).Len() > 0 {
192+
input.TokenDomains = flex.ExpandStringSet(v.(*schema.Set))
193+
}
194+
179195
outputRaw, err := tfresource.RetryWhenAWSErrCodeEquals(ctx, webACLCreateTimeout, func() (interface{}, error) {
180196
return conn.CreateWebACLWithContext(ctx, input)
181197
}, wafv2.ErrCodeWAFUnavailableEntityException)
@@ -226,6 +242,7 @@ func resourceWebACLRead(ctx context.Context, d *schema.ResourceData, meta interf
226242
if err := d.Set("rule", flattenWebACLRules(rules)); err != nil {
227243
return diag.Errorf("setting rule: %s", err)
228244
}
245+
d.Set("token_domains", aws.StringValueSlice(webACL.TokenDomains))
229246
if err := d.Set("visibility_config", flattenVisibilityConfig(webACL.VisibilityConfig)); err != nil {
230247
return diag.Errorf("setting visibility_config: %s", err)
231248
}
@@ -256,6 +273,10 @@ func resourceWebACLUpdate(ctx context.Context, d *schema.ResourceData, meta inte
256273
input.Description = aws.String(v.(string))
257274
}
258275

276+
if v, ok := d.GetOk("token_domains"); ok {
277+
input.TokenDomains = flex.ExpandStringSet(v.(*schema.Set))
278+
}
279+
259280
_, err := tfresource.RetryWhenAWSErrCodeEquals(ctx, webACLUpdateTimeout, func() (interface{}, error) {
260281
return conn.UpdateWebACLWithContext(ctx, input)
261282
}, wafv2.ErrCodeWAFUnavailableEntityException)

internal/service/wafv2/web_acl_test.go

+74-6
Original file line numberDiff line numberDiff line change
@@ -42,22 +42,23 @@ func TestAccWAFV2WebACL_basic(t *testing.T) {
4242
Steps: []resource.TestStep{
4343
{
4444
Config: testAccWebACLConfig_basic(webACLName),
45-
Check: resource.ComposeTestCheckFunc(
45+
Check: resource.ComposeAggregateTestCheckFunc(
4646
testAccCheckWebACLExists(ctx, resourceName, &v),
4747
acctest.MatchResourceAttrRegionalARN(resourceName, "arn", "wafv2", regexp.MustCompile(`regional/webacl/.+$`)),
48-
resource.TestCheckResourceAttr(resourceName, "name", webACLName),
49-
resource.TestCheckResourceAttr(resourceName, "description", webACLName),
50-
resource.TestCheckResourceAttr(resourceName, "rule.#", "0"),
51-
resource.TestCheckResourceAttr(resourceName, "scope", wafv2.ScopeRegional),
5248
resource.TestCheckResourceAttr(resourceName, "captcha_config.#", "0"),
5349
resource.TestCheckResourceAttr(resourceName, "default_action.#", "1"),
5450
resource.TestCheckResourceAttr(resourceName, "default_action.0.allow.#", "1"),
5551
resource.TestCheckResourceAttr(resourceName, "default_action.0.block.#", "0"),
52+
resource.TestCheckResourceAttr(resourceName, "description", webACLName),
53+
resource.TestCheckResourceAttr(resourceName, "name", webACLName),
54+
resource.TestCheckResourceAttr(resourceName, "rule.#", "0"),
55+
resource.TestCheckResourceAttr(resourceName, "scope", wafv2.ScopeRegional),
56+
resource.TestCheckResourceAttr(resourceName, "tags.%", "0"),
57+
resource.TestCheckResourceAttr(resourceName, "token_domains.#", "0"),
5658
resource.TestCheckResourceAttr(resourceName, "visibility_config.#", "1"),
5759
resource.TestCheckResourceAttr(resourceName, "visibility_config.0.cloudwatch_metrics_enabled", "false"),
5860
resource.TestCheckResourceAttr(resourceName, "visibility_config.0.metric_name", "friendly-metric-name"),
5961
resource.TestCheckResourceAttr(resourceName, "visibility_config.0.sampled_requests_enabled", "false"),
60-
resource.TestCheckResourceAttr(resourceName, "tags.%", "0"),
6162
),
6263
},
6364
{
@@ -2339,6 +2340,52 @@ func TestAccWAFV2WebACL_Operators_maxNested(t *testing.T) {
23392340
})
23402341
}
23412342

2343+
func TestAccWAFV2WebACL_tokenDomains(t *testing.T) {
2344+
ctx := acctest.Context(t)
2345+
var v wafv2.WebACL
2346+
webACLName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix)
2347+
domain1 := "mywebsite.com"
2348+
domain2 := "myotherwebsite.com"
2349+
resourceName := "aws_wafv2_web_acl.test"
2350+
2351+
resource.ParallelTest(t, resource.TestCase{
2352+
PreCheck: func() { acctest.PreCheck(ctx, t); testAccPreCheckScopeRegional(ctx, t) },
2353+
ErrorCheck: acctest.ErrorCheck(t, wafv2.EndpointsID),
2354+
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories,
2355+
CheckDestroy: testAccCheckWebACLDestroy(ctx),
2356+
Steps: []resource.TestStep{
2357+
{
2358+
Config: testAccWebACLConfig_tokenDomains(webACLName, domain1, domain2),
2359+
Check: resource.ComposeTestCheckFunc(
2360+
testAccCheckWebACLExists(ctx, resourceName, &v),
2361+
acctest.MatchResourceAttrRegionalARN(resourceName, "arn", "wafv2", regexp.MustCompile(`regional/webacl/.+$`)),
2362+
resource.TestCheckResourceAttr(resourceName, "name", webACLName),
2363+
resource.TestCheckResourceAttr(resourceName, "description", webACLName),
2364+
resource.TestCheckResourceAttr(resourceName, "rule.#", "0"),
2365+
resource.TestCheckResourceAttr(resourceName, "scope", wafv2.ScopeRegional),
2366+
resource.TestCheckResourceAttr(resourceName, "default_action.#", "1"),
2367+
resource.TestCheckResourceAttr(resourceName, "default_action.0.allow.#", "1"),
2368+
resource.TestCheckResourceAttr(resourceName, "default_action.0.block.#", "0"),
2369+
resource.TestCheckResourceAttr(resourceName, "token_domains.#", "2"),
2370+
resource.TestCheckTypeSetElemAttr(resourceName, "token_domains.*", domain1),
2371+
resource.TestCheckTypeSetElemAttr(resourceName, "token_domains.*", domain2),
2372+
resource.TestCheckResourceAttr(resourceName, "visibility_config.#", "1"),
2373+
resource.TestCheckResourceAttr(resourceName, "visibility_config.0.cloudwatch_metrics_enabled", "false"),
2374+
resource.TestCheckResourceAttr(resourceName, "visibility_config.0.metric_name", "friendly-metric-name"),
2375+
resource.TestCheckResourceAttr(resourceName, "visibility_config.0.sampled_requests_enabled", "false"),
2376+
resource.TestCheckResourceAttr(resourceName, "tags.%", "0"),
2377+
),
2378+
},
2379+
{
2380+
ResourceName: resourceName,
2381+
ImportState: true,
2382+
ImportStateVerify: true,
2383+
ImportStateIdFunc: testAccWebACLImportStateIdFunc(resourceName),
2384+
},
2385+
},
2386+
})
2387+
}
2388+
23422389
func testAccCheckWebACLDestroy(ctx context.Context) resource.TestCheckFunc {
23432390
return func(s *terraform.State) error {
23442391
for _, rs := range s.RootModule().Resources {
@@ -4567,3 +4614,24 @@ resource "aws_wafv2_web_acl" "test" {
45674614
}
45684615
`, name)
45694616
}
4617+
4618+
func testAccWebACLConfig_tokenDomains(name, domain1, domain2 string) string {
4619+
return fmt.Sprintf(`
4620+
resource "aws_wafv2_web_acl" "test" {
4621+
name = %[1]q
4622+
description = %[1]q
4623+
scope = "REGIONAL"
4624+
4625+
default_action {
4626+
allow {}
4627+
}
4628+
4629+
token_domains = [%[2]q, %[3]q]
4630+
visibility_config {
4631+
cloudwatch_metrics_enabled = false
4632+
metric_name = "friendly-metric-name"
4633+
sampled_requests_enabled = false
4634+
}
4635+
}
4636+
`, name, domain1, domain2)
4637+
}

website/docs/r/wafv2_web_acl.html.markdown

+3
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,8 @@ resource "aws_wafv2_web_acl" "example" {
6565
}
6666
}
6767
68+
token_domains = ["mywebsite.com", "myotherwebsite.com"]
69+
6870
visibility_config {
6971
cloudwatch_metrics_enabled = false
7072
metric_name = "friendly-rule-metric-name"
@@ -345,6 +347,7 @@ The following arguments are supported:
345347
* `rule` - (Optional) Rule blocks used to identify the web requests that you want to `allow`, `block`, or `count`. See [`rule`](#rule) below for details.
346348
* `scope` - (Required) Specifies whether this is for an AWS CloudFront distribution or for a regional application. Valid values are `CLOUDFRONT` or `REGIONAL`. To work with CloudFront, you must also specify the region `us-east-1` (N. Virginia) on the AWS provider.
347349
* `tags` - (Optional) Map of key-value pairs to associate with the resource. If configured with a provider [`default_tags` configuration block](https://registry.terraform.io/providers/hashicorp/aws/latest/docs#default_tags-configuration-block) present, tags with matching keys will overwrite those defined at the provider-level.
350+
* `token_domains` - (Optional) Specifies the domains that AWS WAF should accept in a web request token. This enables the use of tokens across multiple protected websites. When AWS WAF provides a token, it uses the domain of the AWS resource that the web ACL is protecting. If you don't specify a list of token domains, AWS WAF accepts tokens only for the domain of the protected resource. With a token domain list, AWS WAF accepts the resource's host domain plus all domains in the token domain list, including their prefixed subdomains.
348351
* `visibility_config` - (Required) Defines and enables Amazon CloudWatch metrics and web request sample collection. See [`visibility_config`](#visibility_config) below for details.
349352

350353
### `custom_response_body`

0 commit comments

Comments
 (0)