diff --git a/aws/resource_aws_wafregional_rate_based_rule.go b/aws/resource_aws_wafregional_rate_based_rule.go index e329751a4d6..a6fe9f72063 100644 --- a/aws/resource_aws_wafregional_rate_based_rule.go +++ b/aws/resource_aws_wafregional_rate_based_rule.go @@ -5,10 +5,12 @@ import ( "log" "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/aws/arn" "github.com/aws/aws-sdk-go/service/waf" "github.com/aws/aws-sdk-go/service/wafregional" "github.com/hashicorp/terraform-plugin-sdk/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/helper/validation" + "github.com/terraform-providers/terraform-provider-aws/aws/internal/keyvaluetags" ) func resourceAwsWafRegionalRateBasedRule() *schema.Resource { @@ -64,6 +66,11 @@ func resourceAwsWafRegionalRateBasedRule() *schema.Resource { Required: true, ValidateFunc: validation.IntAtLeast(100), }, + "tags": tagsSchema(), + "arn": { + Type: schema.TypeString, + Computed: true, + }, }, } } @@ -71,6 +78,7 @@ func resourceAwsWafRegionalRateBasedRule() *schema.Resource { func resourceAwsWafRegionalRateBasedRuleCreate(d *schema.ResourceData, meta interface{}) error { conn := meta.(*AWSClient).wafregionalconn region := meta.(*AWSClient).region + tags := keyvaluetags.New(d.Get("tags").(map[string]interface{})).IgnoreAws().WafregionalTags() wr := newWafRegionalRetryer(conn, region) out, err := wr.RetryWithToken(func(token *string) (interface{}, error) { @@ -82,6 +90,10 @@ func resourceAwsWafRegionalRateBasedRuleCreate(d *schema.ResourceData, meta inte RateLimit: aws.Int64(int64(d.Get("rate_limit").(int))), } + if len(tags) > 0 { + params.Tags = tags + } + return conn.CreateRateBasedRule(params) }) if err != nil { @@ -89,7 +101,17 @@ func resourceAwsWafRegionalRateBasedRuleCreate(d *schema.ResourceData, meta inte } resp := out.(*waf.CreateRateBasedRuleOutput) d.SetId(*resp.Rule.RuleId) - return resourceAwsWafRegionalRateBasedRuleUpdate(d, meta) + + newPredicates := d.Get("predicate").(*schema.Set).List() + if len(newPredicates) > 0 { + noPredicates := []interface{}{} + err := updateWafRateBasedRuleResourceWR(d.Id(), noPredicates, newPredicates, d.Get("rate_limit"), conn, region) + if err != nil { + return fmt.Errorf("Error Updating WAF Rate Based Rule: %s", err) + } + } + + return resourceAwsWafRegionalRateBasedRuleRead(d, meta) } func resourceAwsWafRegionalRateBasedRuleRead(d *schema.ResourceData, meta interface{}) error { @@ -119,6 +141,23 @@ func resourceAwsWafRegionalRateBasedRuleRead(d *schema.ResourceData, meta interf }) } + arn := arn.ARN{ + AccountID: meta.(*AWSClient).accountid, + Partition: meta.(*AWSClient).partition, + Region: meta.(*AWSClient).region, + Resource: fmt.Sprintf("ratebasedrule/%s", d.Id()), + Service: "waf-regional", + }.String() + d.Set("arn", arn) + + tagList, err := keyvaluetags.WafregionalListTags(conn, arn) + if err != nil { + return fmt.Errorf("Failed to get WAF Regional Rated Based Rule parameter tags for %s: %s", d.Get("name"), err) + } + if err := d.Set("tags", tagList.IgnoreAws().Map()); err != nil { + return fmt.Errorf("error setting tags: %s", err) + } + d.Set("predicate", predicates) d.Set("name", resp.Rule.Name) d.Set("metric_name", resp.Rule.MetricName) @@ -148,6 +187,14 @@ func resourceAwsWafRegionalRateBasedRuleUpdate(d *schema.ResourceData, meta inte } } + if d.HasChange("tags") { + o, n := d.GetChange("tags") + + if err := keyvaluetags.WafregionalUpdateTags(conn, d.Get("arn").(string), o, n); err != nil { + return fmt.Errorf("error updating tags: %s", err) + } + } + return resourceAwsWafRegionalRateBasedRuleRead(d, meta) } diff --git a/aws/resource_aws_wafregional_rate_based_rule_test.go b/aws/resource_aws_wafregional_rate_based_rule_test.go index 5157d2025cd..4c45493e926 100644 --- a/aws/resource_aws_wafregional_rate_based_rule_test.go +++ b/aws/resource_aws_wafregional_rate_based_rule_test.go @@ -3,6 +3,7 @@ package aws import ( "fmt" "log" + "regexp" "testing" "github.com/aws/aws-sdk-go/aws" @@ -130,12 +131,10 @@ func TestAccAWSWafRegionalRateBasedRule_basic(t *testing.T) { Config: testAccAWSWafRegionalRateBasedRuleConfig(wafRuleName), Check: resource.ComposeTestCheckFunc( testAccCheckAWSWafRegionalRateBasedRuleExists(resourceName, &v), - resource.TestCheckResourceAttr( - resourceName, "name", wafRuleName), - resource.TestCheckResourceAttr( - resourceName, "predicate.#", "1"), - resource.TestCheckResourceAttr( - resourceName, "metric_name", wafRuleName), + testAccMatchResourceAttrRegionalARN(resourceName, "arn", "waf-regional", regexp.MustCompile(`ratebasedrule/.+`)), + resource.TestCheckResourceAttr(resourceName, "name", wafRuleName), + resource.TestCheckResourceAttr(resourceName, "predicate.#", "1"), + resource.TestCheckResourceAttr(resourceName, "metric_name", wafRuleName), ), }, { @@ -147,6 +146,49 @@ func TestAccAWSWafRegionalRateBasedRule_basic(t *testing.T) { }) } +func TestAccAWSWafRegionalRateBasedRule_tags(t *testing.T) { + var v waf.RateBasedRule + resourceName := "aws_wafregional_rate_based_rule.wafrule" + wafRuleName := fmt.Sprintf("wafrule%s", acctest.RandString(5)) + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSWafRegionalRateBasedRuleDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAWSWafRegionalRateBasedRuleConfigTags1(wafRuleName, "key1", "value1"), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSWafRegionalRateBasedRuleExists(resourceName, &v), + resource.TestCheckResourceAttr(resourceName, "tags.%", "1"), + resource.TestCheckResourceAttr(resourceName, "tags.key1", "value1"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + { + Config: testAccAWSWafRegionalRateBasedRuleConfigTags2(wafRuleName, "key1", "value1updated", "key2", "value2"), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSWafRegionalRateBasedRuleExists(resourceName, &v), + resource.TestCheckResourceAttr(resourceName, "tags.%", "2"), + resource.TestCheckResourceAttr(resourceName, "tags.key1", "value1updated"), + resource.TestCheckResourceAttr(resourceName, "tags.key2", "value2"), + ), + }, + { + Config: testAccAWSWafRegionalRateBasedRuleConfigTags1(wafRuleName, "key2", "value2"), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSWafRegionalRateBasedRuleExists(resourceName, &v), + resource.TestCheckResourceAttr(resourceName, "tags.%", "1"), + resource.TestCheckResourceAttr(resourceName, "tags.key2", "value2"), + ), + }, + }, + }) +} + func TestAccAWSWafRegionalRateBasedRule_changeNameForceNew(t *testing.T) { var before, after waf.RateBasedRule resourceName := "aws_wafregional_rate_based_rule.wafrule" @@ -162,12 +204,9 @@ func TestAccAWSWafRegionalRateBasedRule_changeNameForceNew(t *testing.T) { Config: testAccAWSWafRegionalRateBasedRuleConfig(wafRuleName), Check: resource.ComposeTestCheckFunc( testAccCheckAWSWafRegionalRateBasedRuleExists(resourceName, &before), - resource.TestCheckResourceAttr( - resourceName, "name", wafRuleName), - resource.TestCheckResourceAttr( - resourceName, "predicate.#", "1"), - resource.TestCheckResourceAttr( - resourceName, "metric_name", wafRuleName), + resource.TestCheckResourceAttr(resourceName, "name", wafRuleName), + resource.TestCheckResourceAttr(resourceName, "predicate.#", "1"), + resource.TestCheckResourceAttr(resourceName, "metric_name", wafRuleName), ), }, { @@ -175,12 +214,9 @@ func TestAccAWSWafRegionalRateBasedRule_changeNameForceNew(t *testing.T) { Check: resource.ComposeTestCheckFunc( testAccCheckAWSWafRegionalRateBasedRuleExists(resourceName, &after), testAccCheckAWSWafRateBasedRuleIdDiffers(&before, &after), - resource.TestCheckResourceAttr( - resourceName, "name", wafRuleNewName), - resource.TestCheckResourceAttr( - resourceName, "predicate.#", "1"), - resource.TestCheckResourceAttr( - resourceName, "metric_name", wafRuleNewName), + resource.TestCheckResourceAttr(resourceName, "name", wafRuleNewName), + resource.TestCheckResourceAttr(resourceName, "predicate.#", "1"), + resource.TestCheckResourceAttr(resourceName, "metric_name", wafRuleNewName), ), }, { @@ -349,10 +385,8 @@ func TestAccAWSWafRegionalRateBasedRule_noPredicates(t *testing.T) { Config: testAccAWSWafRegionalRateBasedRuleConfig_noPredicates(ruleName), Check: resource.ComposeAggregateTestCheckFunc( testAccCheckAWSWafRegionalRateBasedRuleExists(resourceName, &rule), - resource.TestCheckResourceAttr( - resourceName, "name", ruleName), - resource.TestCheckResourceAttr( - resourceName, "predicate.#", "0"), + resource.TestCheckResourceAttr(resourceName, "name", ruleName), + resource.TestCheckResourceAttr(resourceName, "predicate.#", "0"), ), }, { @@ -479,7 +513,7 @@ func testAccCheckAWSWafRegionalRateBasedRuleExists(n string, v *waf.RateBasedRul func testAccAWSWafRegionalRateBasedRuleConfig(name string) string { return fmt.Sprintf(` resource "aws_wafregional_ipset" "ipset" { - name = "%s" + name = %[1]q ip_set_descriptor { type = "IPV4" @@ -488,8 +522,34 @@ resource "aws_wafregional_ipset" "ipset" { } resource "aws_wafregional_rate_based_rule" "wafrule" { - name = "%s" - metric_name = "%s" + name = %[1]q + metric_name = %[1]q + rate_key = "IP" + rate_limit = 2000 + + predicate { + data_id = "${aws_wafregional_ipset.ipset.id}" + negated = false + type = "IPMatch" + } +} +`, name) +} + +func testAccAWSWafRegionalRateBasedRuleConfigTags1(name, tagKey1, tagValue1 string) string { + return fmt.Sprintf(` +resource "aws_wafregional_ipset" "ipset" { + name = %[1]q + + ip_set_descriptor { + type = "IPV4" + value = "192.0.7.0/24" + } +} + +resource "aws_wafregional_rate_based_rule" "wafrule" { + name = %[1]q + metric_name = %[1]q rate_key = "IP" rate_limit = 2000 @@ -498,14 +558,49 @@ resource "aws_wafregional_rate_based_rule" "wafrule" { negated = false type = "IPMatch" } + + tags = { + %[2]q = %[3]q + } } -`, name, name, name) +`, name, tagKey1, tagValue1) +} + +func testAccAWSWafRegionalRateBasedRuleConfigTags2(name, tagKey1, tagValue1, tagKey2, tagValue2 string) string { + return fmt.Sprintf(` +resource "aws_wafregional_ipset" "ipset" { + name = %[1]q + + ip_set_descriptor { + type = "IPV4" + value = "192.0.7.0/24" + } +} + +resource "aws_wafregional_rate_based_rule" "wafrule" { + name = %[1]q + metric_name = %[1]q + rate_key = "IP" + rate_limit = 2000 + + predicate { + data_id = "${aws_wafregional_ipset.ipset.id}" + negated = false + type = "IPMatch" + } + + tags = { + %[2]q = %[3]q + %[4]q = %[5]q + } +} +`, name, tagKey1, tagValue1, tagKey2, tagValue2) } func testAccAWSWafRegionalRateBasedRuleConfigChangeName(name string) string { return fmt.Sprintf(` resource "aws_wafregional_ipset" "ipset" { - name = "%s" + name = %[1]q ip_set_descriptor { type = "IPV4" @@ -514,8 +609,8 @@ resource "aws_wafregional_ipset" "ipset" { } resource "aws_wafregional_rate_based_rule" "wafrule" { - name = "%s" - metric_name = "%s" + name = %[1]q + metric_name = %[1]q rate_key = "IP" rate_limit = 2000 @@ -525,13 +620,13 @@ resource "aws_wafregional_rate_based_rule" "wafrule" { type = "IPMatch" } } -`, name, name, name) +`, name) } func testAccAWSWafRegionalRateBasedRuleConfig_changePredicates(name string) string { return fmt.Sprintf(` resource "aws_wafregional_ipset" "ipset" { - name = "%s" + name = %[1]q ip_set_descriptor { type = "IPV4" @@ -540,7 +635,7 @@ resource "aws_wafregional_ipset" "ipset" { } resource "aws_wafregional_byte_match_set" "set" { - name = "%s" + name = %[1]q byte_match_tuples { text_transformation = "NONE" @@ -555,8 +650,8 @@ resource "aws_wafregional_byte_match_set" "set" { } resource "aws_wafregional_rate_based_rule" "wafrule" { - name = "%s" - metric_name = "%s" + name = %[1]q + metric_name = %[1]q rate_key = "IP" rate_limit = 2000 @@ -566,18 +661,18 @@ resource "aws_wafregional_rate_based_rule" "wafrule" { type = "ByteMatch" } } -`, name, name, name, name) +`, name) } func testAccAWSWafRegionalRateBasedRuleConfig_noPredicates(name string) string { return fmt.Sprintf(` resource "aws_wafregional_rate_based_rule" "wafrule" { - name = "%s" - metric_name = "%s" + name = %[1]q + metric_name = %[1]q rate_key = "IP" rate_limit = 2000 } -`, name, name) +`, name) } func testAccAWSWafRegionalRateBasedRuleWithRateLimitConfig(name string, limit string) string { diff --git a/website/docs/r/wafregional_rate_based_rule.html.markdown b/website/docs/r/wafregional_rate_based_rule.html.markdown index bca2206b2a3..71f05a7ce0b 100644 --- a/website/docs/r/wafregional_rate_based_rule.html.markdown +++ b/website/docs/r/wafregional_rate_based_rule.html.markdown @@ -47,6 +47,7 @@ The following arguments are supported: * `rate_key` - (Required) Valid value is IP. * `rate_limit` - (Required) The maximum number of requests, which have an identical value in the field specified by the RateKey, allowed in a five-minute period. Minimum value is 100. * `predicate` - (Optional) The objects to include in a rule (documented below). +* `tags` - (Optional) Key-value mapping of resource tags ## Nested Blocks @@ -67,7 +68,8 @@ See the [WAF Documentation](https://docs.aws.amazon.com/waf/latest/APIReference/ In addition to all arguments above, the following attributes are exported: -* `id` - The ID of the WAF Regional rate based rule. +* `id` - The ID of the WAF Regional Rate Based Rule. +* `arn` - The ARN of the WAF Regional Rate Based Rule. ## Import