provider/aws: AWS WAF Regional IPSet + ByteMatchSet support (#13705)

* provider/aws: AWS WAF Regional ByteMatchSet support

* providor/aws: AWS WAF Regional IPSet support

* fix typo

* Nested ByteMatchTuples of WAF Regional support

* fix name byte_match_tuple singular WAF Regional

* update wafregional_byte_match_set doc

* fix wafregional ipset to look descriptor

* Add wafregional_byte_match_set test

* fix wafregional_ipset_descriptor to be singular

* fix newWafRegionalRetryer to receive region

* fix updateSetWR argument

* fix wafregional_ipset_descriptor doc

* Separate out logic into flatteners

* Fix failing test
This commit is contained in:
Yusuke Goto 2017-05-14 05:01:27 +09:00 committed by Radek Simko
parent 5367f2607e
commit 3b14fc90d9
10 changed files with 1444 additions and 0 deletions

View File

@ -66,6 +66,7 @@ import (
"github.com/aws/aws-sdk-go/service/ssm" "github.com/aws/aws-sdk-go/service/ssm"
"github.com/aws/aws-sdk-go/service/sts" "github.com/aws/aws-sdk-go/service/sts"
"github.com/aws/aws-sdk-go/service/waf" "github.com/aws/aws-sdk-go/service/waf"
"github.com/aws/aws-sdk-go/service/wafregional"
"github.com/davecgh/go-spew/spew" "github.com/davecgh/go-spew/spew"
"github.com/hashicorp/errwrap" "github.com/hashicorp/errwrap"
"github.com/hashicorp/go-cleanhttp" "github.com/hashicorp/go-cleanhttp"
@ -172,6 +173,7 @@ type AWSClient struct {
sfnconn *sfn.SFN sfnconn *sfn.SFN
ssmconn *ssm.SSM ssmconn *ssm.SSM
wafconn *waf.WAF wafconn *waf.WAF
wafregionalconn *wafregional.WAFRegional
} }
func (c *AWSClient) S3() *s3.S3 { func (c *AWSClient) S3() *s3.S3 {
@ -379,6 +381,7 @@ func (c *Config) Client() (interface{}, error) {
client.sqsconn = sqs.New(awsSqsSess) client.sqsconn = sqs.New(awsSqsSess)
client.ssmconn = ssm.New(sess) client.ssmconn = ssm.New(sess)
client.wafconn = waf.New(sess) client.wafconn = waf.New(sess)
client.wafregionalconn = wafregional.New(sess)
return &client, nil return &client, nil
} }

View File

@ -457,6 +457,8 @@ func Provider() terraform.ResourceProvider {
"aws_waf_web_acl": resourceAwsWafWebAcl(), "aws_waf_web_acl": resourceAwsWafWebAcl(),
"aws_waf_xss_match_set": resourceAwsWafXssMatchSet(), "aws_waf_xss_match_set": resourceAwsWafXssMatchSet(),
"aws_waf_sql_injection_match_set": resourceAwsWafSqlInjectionMatchSet(), "aws_waf_sql_injection_match_set": resourceAwsWafSqlInjectionMatchSet(),
"aws_wafregional_byte_match_set": resourceAwsWafRegionalByteMatchSet(),
"aws_wafregional_ipset": resourceAwsWafRegionalIPSet(),
}, },
ConfigureFunc: providerConfigure, ConfigureFunc: providerConfigure,
} }

View File

@ -0,0 +1,266 @@
package aws
import (
"log"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/service/waf"
"github.com/aws/aws-sdk-go/service/wafregional"
"github.com/hashicorp/errwrap"
"github.com/hashicorp/terraform/helper/schema"
)
func resourceAwsWafRegionalByteMatchSet() *schema.Resource {
return &schema.Resource{
Create: resourceAwsWafRegionalByteMatchSetCreate,
Read: resourceAwsWafRegionalByteMatchSetRead,
Update: resourceAwsWafRegionalByteMatchSetUpdate,
Delete: resourceAwsWafRegionalByteMatchSetDelete,
Schema: map[string]*schema.Schema{
"name": &schema.Schema{
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"byte_match_tuple": &schema.Schema{
Type: schema.TypeSet,
Optional: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"field_to_match": {
Type: schema.TypeSet,
Required: true,
MaxItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"data": {
Type: schema.TypeString,
Optional: true,
},
"type": {
Type: schema.TypeString,
Required: true,
},
},
},
},
"positional_constraint": &schema.Schema{
Type: schema.TypeString,
Required: true,
},
"target_string": &schema.Schema{
Type: schema.TypeString,
Optional: true,
},
"text_transformation": &schema.Schema{
Type: schema.TypeString,
Required: true,
},
},
},
},
},
}
}
func resourceAwsWafRegionalByteMatchSetCreate(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AWSClient).wafregionalconn
region := meta.(*AWSClient).region
log.Printf("[INFO] Creating ByteMatchSet: %s", d.Get("name").(string))
wr := newWafRegionalRetryer(conn, region)
out, err := wr.RetryWithToken(func(token *string) (interface{}, error) {
params := &waf.CreateByteMatchSetInput{
ChangeToken: token,
Name: aws.String(d.Get("name").(string)),
}
return conn.CreateByteMatchSet(params)
})
if err != nil {
return errwrap.Wrapf("[ERROR] Error creating ByteMatchSet: {{err}}", err)
}
resp := out.(*waf.CreateByteMatchSetOutput)
d.SetId(*resp.ByteMatchSet.ByteMatchSetId)
return resourceAwsWafRegionalByteMatchSetUpdate(d, meta)
}
func resourceAwsWafRegionalByteMatchSetRead(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AWSClient).wafregionalconn
log.Printf("[INFO] Reading ByteMatchSet: %s", d.Get("name").(string))
params := &waf.GetByteMatchSetInput{
ByteMatchSetId: aws.String(d.Id()),
}
resp, err := conn.GetByteMatchSet(params)
if err != nil {
if awsErr, ok := err.(awserr.Error); ok && awsErr.Code() == "WAFNonexistentItemException" {
log.Printf("[WARN] WAF IPSet (%s) not found, error code (404)", d.Id())
d.SetId("")
return nil
}
return err
}
d.Set("byte_match_tuple", flattenWafByteMatchTuplesWR(resp.ByteMatchSet.ByteMatchTuples))
d.Set("name", resp.ByteMatchSet.Name)
return nil
}
func flattenWafByteMatchTuplesWR(in []*waf.ByteMatchTuple) []interface{} {
tuples := make([]interface{}, len(in), len(in))
for i, tuple := range in {
field_to_match := tuple.FieldToMatch
m := map[string]interface{}{
"type": *field_to_match.Type,
}
if field_to_match.Data == nil {
m["data"] = ""
} else {
m["data"] = *field_to_match.Data
}
var ms []map[string]interface{}
ms = append(ms, m)
tuple := map[string]interface{}{
"field_to_match": ms,
"positional_constraint": *tuple.PositionalConstraint,
"target_string": tuple.TargetString,
"text_transformation": *tuple.TextTransformation,
}
tuples[i] = tuple
}
return tuples
}
func resourceAwsWafRegionalByteMatchSetUpdate(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AWSClient).wafregionalconn
region := meta.(*AWSClient).region
log.Printf("[INFO] Updating ByteMatchSet: %s", d.Get("name").(string))
if d.HasChange("byte_match_tuple") {
o, n := d.GetChange("byte_match_tuple")
oldT, newT := o.(*schema.Set).List(), n.(*schema.Set).List()
err := updateByteMatchSetResourceWR(d, oldT, newT, conn, region)
if err != nil {
return errwrap.Wrapf("[ERROR] Error updating ByteMatchSet: {{err}}", err)
}
}
return resourceAwsWafRegionalByteMatchSetRead(d, meta)
}
func resourceAwsWafRegionalByteMatchSetDelete(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AWSClient).wafregionalconn
region := meta.(*AWSClient).region
log.Printf("[INFO] Deleting ByteMatchSet: %s", d.Get("name").(string))
oldT := d.Get("byte_match_tuple").(*schema.Set).List()
if len(oldT) > 0 {
var newT []interface{}
err := updateByteMatchSetResourceWR(d, oldT, newT, conn, region)
if err != nil {
return errwrap.Wrapf("[ERROR] Error deleting ByteMatchSet: {{err}}", err)
}
}
wr := newWafRegionalRetryer(conn, region)
_, err := wr.RetryWithToken(func(token *string) (interface{}, error) {
req := &waf.DeleteByteMatchSetInput{
ChangeToken: token,
ByteMatchSetId: aws.String(d.Id()),
}
return conn.DeleteByteMatchSet(req)
})
if err != nil {
return errwrap.Wrapf("[ERROR] Error deleting ByteMatchSet: {{err}}", err)
}
return nil
}
func updateByteMatchSetResourceWR(d *schema.ResourceData, oldT, newT []interface{}, conn *wafregional.WAFRegional, region string) error {
wr := newWafRegionalRetryer(conn, region)
_, err := wr.RetryWithToken(func(token *string) (interface{}, error) {
req := &waf.UpdateByteMatchSetInput{
ChangeToken: token,
ByteMatchSetId: aws.String(d.Id()),
Updates: diffByteMatchSetTuple(oldT, newT),
}
return conn.UpdateByteMatchSet(req)
})
if err != nil {
return errwrap.Wrapf("[ERROR] Error updating ByteMatchSet: {{err}}", err)
}
return nil
}
func expandFieldToMatchWR(d map[string]interface{}) *waf.FieldToMatch {
return &waf.FieldToMatch{
Type: aws.String(d["type"].(string)),
Data: aws.String(d["data"].(string)),
}
}
func flattenFieldToMatchWR(fm *waf.FieldToMatch) map[string]interface{} {
m := make(map[string]interface{})
m["data"] = *fm.Data
m["type"] = *fm.Type
return m
}
func diffByteMatchSetTuple(oldT, newT []interface{}) []*waf.ByteMatchSetUpdate {
updates := make([]*waf.ByteMatchSetUpdate, 0)
for _, ot := range oldT {
tuple := ot.(map[string]interface{})
if idx, contains := sliceContainsMap(newT, tuple); contains {
newT = append(newT[:idx], newT[idx+1:]...)
continue
}
updates = append(updates, &waf.ByteMatchSetUpdate{
Action: aws.String(waf.ChangeActionDelete),
ByteMatchTuple: &waf.ByteMatchTuple{
FieldToMatch: expandFieldToMatch(tuple["field_to_match"].(*schema.Set).List()[0].(map[string]interface{})),
PositionalConstraint: aws.String(tuple["positional_constraint"].(string)),
TargetString: []byte(tuple["target_string"].(string)),
TextTransformation: aws.String(tuple["text_transformation"].(string)),
},
})
}
for _, nt := range newT {
tuple := nt.(map[string]interface{})
updates = append(updates, &waf.ByteMatchSetUpdate{
Action: aws.String(waf.ChangeActionInsert),
ByteMatchTuple: &waf.ByteMatchTuple{
FieldToMatch: expandFieldToMatch(tuple["field_to_match"].(*schema.Set).List()[0].(map[string]interface{})),
PositionalConstraint: aws.String(tuple["positional_constraint"].(string)),
TargetString: []byte(tuple["target_string"].(string)),
TextTransformation: aws.String(tuple["text_transformation"].(string)),
},
})
}
return updates
}

View File

@ -0,0 +1,437 @@
package aws
import (
"fmt"
"testing"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/service/waf"
"github.com/hashicorp/errwrap"
"github.com/hashicorp/terraform/helper/acctest"
)
func TestAccAWSWafRegionalByteMatchSet_basic(t *testing.T) {
var v waf.ByteMatchSet
byteMatchSet := fmt.Sprintf("byteMatchSet-%s", acctest.RandString(5))
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckAWSWafRegionalByteMatchSetDestroy,
Steps: []resource.TestStep{
resource.TestStep{
Config: testAccAWSWafRegionalByteMatchSetConfig(byteMatchSet),
Check: resource.ComposeTestCheckFunc(
testAccCheckAWSWafRegionalByteMatchSetExists("aws_wafregional_byte_match_set.byte_set", &v),
resource.TestCheckResourceAttr(
"aws_wafregional_byte_match_set.byte_set", "name", byteMatchSet),
resource.TestCheckResourceAttr(
"aws_wafregional_byte_match_set.byte_set", "byte_match_tuple.#", "2"),
resource.TestCheckResourceAttr(
"aws_wafregional_byte_match_set.byte_set", "byte_match_tuple.2174619346.field_to_match.2991901334.data", "referer"),
resource.TestCheckResourceAttr(
"aws_wafregional_byte_match_set.byte_set", "byte_match_tuple.2174619346.field_to_match.2991901334.type", "HEADER"),
resource.TestCheckResourceAttr(
"aws_wafregional_byte_match_set.byte_set", "byte_match_tuple.2174619346.positional_constraint", "CONTAINS"),
resource.TestCheckResourceAttr(
"aws_wafregional_byte_match_set.byte_set", "byte_match_tuple.2174619346.target_string", "badrefer1"),
resource.TestCheckResourceAttr(
"aws_wafregional_byte_match_set.byte_set", "byte_match_tuple.2174619346.text_transformation", "NONE"),
resource.TestCheckResourceAttr(
"aws_wafregional_byte_match_set.byte_set", "byte_match_tuple.839525137.field_to_match.2991901334.data", "referer"),
resource.TestCheckResourceAttr(
"aws_wafregional_byte_match_set.byte_set", "byte_match_tuple.839525137.field_to_match.2991901334.type", "HEADER"),
resource.TestCheckResourceAttr(
"aws_wafregional_byte_match_set.byte_set", "byte_match_tuple.839525137.positional_constraint", "CONTAINS"),
resource.TestCheckResourceAttr(
"aws_wafregional_byte_match_set.byte_set", "byte_match_tuple.839525137.target_string", "badrefer2"),
resource.TestCheckResourceAttr(
"aws_wafregional_byte_match_set.byte_set", "byte_match_tuple.839525137.text_transformation", "NONE"),
),
},
},
})
}
func TestAccAWSWafRegionalByteMatchSet_changeNameForceNew(t *testing.T) {
var before, after waf.ByteMatchSet
byteMatchSet := fmt.Sprintf("byteMatchSet-%s", acctest.RandString(5))
byteMatchSetNewName := fmt.Sprintf("byteMatchSet-%s", acctest.RandString(5))
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckAWSWafRegionalByteMatchSetDestroy,
Steps: []resource.TestStep{
{
Config: testAccAWSWafRegionalByteMatchSetConfig(byteMatchSet),
Check: resource.ComposeTestCheckFunc(
testAccCheckAWSWafRegionalByteMatchSetExists("aws_wafregional_byte_match_set.byte_set", &before),
resource.TestCheckResourceAttr(
"aws_wafregional_byte_match_set.byte_set", "name", byteMatchSet),
resource.TestCheckResourceAttr(
"aws_wafregional_byte_match_set.byte_set", "byte_match_tuple.#", "2"),
resource.TestCheckResourceAttr(
"aws_wafregional_byte_match_set.byte_set", "byte_match_tuple.2174619346.field_to_match.2991901334.data", "referer"),
resource.TestCheckResourceAttr(
"aws_wafregional_byte_match_set.byte_set", "byte_match_tuple.2174619346.field_to_match.2991901334.type", "HEADER"),
resource.TestCheckResourceAttr(
"aws_wafregional_byte_match_set.byte_set", "byte_match_tuple.2174619346.positional_constraint", "CONTAINS"),
resource.TestCheckResourceAttr(
"aws_wafregional_byte_match_set.byte_set", "byte_match_tuple.2174619346.target_string", "badrefer1"),
resource.TestCheckResourceAttr(
"aws_wafregional_byte_match_set.byte_set", "byte_match_tuple.2174619346.text_transformation", "NONE"),
resource.TestCheckResourceAttr(
"aws_wafregional_byte_match_set.byte_set", "byte_match_tuple.839525137.field_to_match.2991901334.data", "referer"),
resource.TestCheckResourceAttr(
"aws_wafregional_byte_match_set.byte_set", "byte_match_tuple.839525137.field_to_match.2991901334.type", "HEADER"),
resource.TestCheckResourceAttr(
"aws_wafregional_byte_match_set.byte_set", "byte_match_tuple.839525137.positional_constraint", "CONTAINS"),
resource.TestCheckResourceAttr(
"aws_wafregional_byte_match_set.byte_set", "byte_match_tuple.839525137.target_string", "badrefer2"),
resource.TestCheckResourceAttr(
"aws_wafregional_byte_match_set.byte_set", "byte_match_tuple.839525137.text_transformation", "NONE"),
),
},
{
Config: testAccAWSWafRegionalByteMatchSetConfigChangeName(byteMatchSetNewName),
Check: resource.ComposeTestCheckFunc(
testAccCheckAWSWafRegionalByteMatchSetExists("aws_wafregional_byte_match_set.byte_set", &after),
resource.TestCheckResourceAttr(
"aws_wafregional_byte_match_set.byte_set", "name", byteMatchSetNewName),
resource.TestCheckResourceAttr(
"aws_wafregional_byte_match_set.byte_set", "byte_match_tuple.#", "2"),
resource.TestCheckResourceAttr(
"aws_wafregional_byte_match_set.byte_set", "byte_match_tuple.2174619346.field_to_match.2991901334.data", "referer"),
resource.TestCheckResourceAttr(
"aws_wafregional_byte_match_set.byte_set", "byte_match_tuple.2174619346.field_to_match.2991901334.type", "HEADER"),
resource.TestCheckResourceAttr(
"aws_wafregional_byte_match_set.byte_set", "byte_match_tuple.2174619346.positional_constraint", "CONTAINS"),
resource.TestCheckResourceAttr(
"aws_wafregional_byte_match_set.byte_set", "byte_match_tuple.2174619346.target_string", "badrefer1"),
resource.TestCheckResourceAttr(
"aws_wafregional_byte_match_set.byte_set", "byte_match_tuple.2174619346.text_transformation", "NONE"),
resource.TestCheckResourceAttr(
"aws_wafregional_byte_match_set.byte_set", "byte_match_tuple.839525137.field_to_match.2991901334.data", "referer"),
resource.TestCheckResourceAttr(
"aws_wafregional_byte_match_set.byte_set", "byte_match_tuple.839525137.field_to_match.2991901334.type", "HEADER"),
resource.TestCheckResourceAttr(
"aws_wafregional_byte_match_set.byte_set", "byte_match_tuple.839525137.positional_constraint", "CONTAINS"),
resource.TestCheckResourceAttr(
"aws_wafregional_byte_match_set.byte_set", "byte_match_tuple.839525137.target_string", "badrefer2"),
resource.TestCheckResourceAttr(
"aws_wafregional_byte_match_set.byte_set", "byte_match_tuple.839525137.text_transformation", "NONE"),
),
},
},
})
}
func TestAccAWSWafRegionalByteMatchSet_changeByteMatchTuple(t *testing.T) {
var before, after waf.ByteMatchSet
byteMatchSetName := fmt.Sprintf("byte-batch-set-%s", acctest.RandString(5))
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckAWSWafRegionalByteMatchSetDestroy,
Steps: []resource.TestStep{
{
Config: testAccAWSWafRegionalByteMatchSetConfig(byteMatchSetName),
Check: resource.ComposeTestCheckFunc(
testAccCheckAWSWafRegionalByteMatchSetExists("aws_wafregional_byte_match_set.byte_set", &before),
resource.TestCheckResourceAttr(
"aws_wafregional_byte_match_set.byte_set", "name", byteMatchSetName),
resource.TestCheckResourceAttr(
"aws_wafregional_byte_match_set.byte_set", "byte_match_tuple.#", "2"),
resource.TestCheckResourceAttr(
"aws_wafregional_byte_match_set.byte_set", "byte_match_tuple.2174619346.field_to_match.2991901334.data", "referer"),
resource.TestCheckResourceAttr(
"aws_wafregional_byte_match_set.byte_set", "byte_match_tuple.2174619346.field_to_match.2991901334.type", "HEADER"),
resource.TestCheckResourceAttr(
"aws_wafregional_byte_match_set.byte_set", "byte_match_tuple.2174619346.positional_constraint", "CONTAINS"),
resource.TestCheckResourceAttr(
"aws_wafregional_byte_match_set.byte_set", "byte_match_tuple.2174619346.target_string", "badrefer1"),
resource.TestCheckResourceAttr(
"aws_wafregional_byte_match_set.byte_set", "byte_match_tuple.2174619346.text_transformation", "NONE"),
resource.TestCheckResourceAttr(
"aws_wafregional_byte_match_set.byte_set", "byte_match_tuple.839525137.field_to_match.2991901334.data", "referer"),
resource.TestCheckResourceAttr(
"aws_wafregional_byte_match_set.byte_set", "byte_match_tuple.839525137.field_to_match.2991901334.type", "HEADER"),
resource.TestCheckResourceAttr(
"aws_wafregional_byte_match_set.byte_set", "byte_match_tuple.839525137.positional_constraint", "CONTAINS"),
resource.TestCheckResourceAttr(
"aws_wafregional_byte_match_set.byte_set", "byte_match_tuple.839525137.target_string", "badrefer2"),
resource.TestCheckResourceAttr(
"aws_wafregional_byte_match_set.byte_set", "byte_match_tuple.839525137.text_transformation", "NONE"),
),
},
{
Config: testAccAWSWafRegionalByteMatchSetConfigChangeByteMatchTuple(byteMatchSetName),
Check: resource.ComposeTestCheckFunc(
testAccCheckAWSWafRegionalByteMatchSetExists("aws_wafregional_byte_match_set.byte_set", &after),
resource.TestCheckResourceAttr(
"aws_wafregional_byte_match_set.byte_set", "name", byteMatchSetName),
resource.TestCheckResourceAttr(
"aws_wafregional_byte_match_set.byte_set", "byte_match_tuple.#", "2"),
resource.TestCheckResourceAttr(
"aws_wafregional_byte_match_set.byte_set", "byte_match_tuple.2397850647.field_to_match.4253810390.data", "GET"),
resource.TestCheckResourceAttr(
"aws_wafregional_byte_match_set.byte_set", "byte_match_tuple.2397850647.field_to_match.4253810390.type", "METHOD"),
resource.TestCheckResourceAttr(
"aws_wafregional_byte_match_set.byte_set", "byte_match_tuple.2397850647.positional_constraint", "STARTS_WITH"),
resource.TestCheckResourceAttr(
"aws_wafregional_byte_match_set.byte_set", "byte_match_tuple.2397850647.target_string", "badrefer1+"),
resource.TestCheckResourceAttr(
"aws_wafregional_byte_match_set.byte_set", "byte_match_tuple.2397850647.text_transformation", "LOWERCASE"),
resource.TestCheckResourceAttr(
"aws_wafregional_byte_match_set.byte_set", "byte_match_tuple.4153613423.field_to_match.3756326843.data", ""),
resource.TestCheckResourceAttr(
"aws_wafregional_byte_match_set.byte_set", "byte_match_tuple.4153613423.field_to_match.3756326843.type", "URI"),
resource.TestCheckResourceAttr(
"aws_wafregional_byte_match_set.byte_set", "byte_match_tuple.4153613423.positional_constraint", "ENDS_WITH"),
resource.TestCheckResourceAttr(
"aws_wafregional_byte_match_set.byte_set", "byte_match_tuple.4153613423.target_string", "badrefer2+"),
resource.TestCheckResourceAttr(
"aws_wafregional_byte_match_set.byte_set", "byte_match_tuple.4153613423.text_transformation", "LOWERCASE"),
),
},
},
})
}
func TestAccAWSWafRegionalByteMatchSet_noByteMatchTuples(t *testing.T) {
var byteMatchSet waf.ByteMatchSet
byteMatchSetName := fmt.Sprintf("byte-batch-set-%s", acctest.RandString(5))
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckAWSWafRegionalByteMatchSetDestroy,
Steps: []resource.TestStep{
{
Config: testAccAWSWafRegionalByteMatchSetConfig_noDescriptors(byteMatchSetName),
Check: resource.ComposeAggregateTestCheckFunc(
testAccCheckAWSWafRegionalByteMatchSetExists("aws_wafregional_byte_match_set.byte_match_set", &byteMatchSet),
resource.TestCheckResourceAttr("aws_wafregional_byte_match_set.byte_match_set", "name", byteMatchSetName),
resource.TestCheckResourceAttr("aws_wafregional_byte_match_set.byte_match_set", "byte_match_tuple.#", "0"),
),
},
},
})
}
func TestAccAWSWafRegionalByteMatchSet_disappears(t *testing.T) {
var v waf.ByteMatchSet
byteMatchSet := fmt.Sprintf("byteMatchSet-%s", acctest.RandString(5))
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckAWSWafRegionalByteMatchSetDestroy,
Steps: []resource.TestStep{
{
Config: testAccAWSWafRegionalByteMatchSetConfig(byteMatchSet),
Check: resource.ComposeTestCheckFunc(
testAccCheckAWSWafRegionalByteMatchSetExists("aws_wafregional_byte_match_set.byte_set", &v),
testAccCheckAWSWafRegionalByteMatchSetDisappears(&v),
),
ExpectNonEmptyPlan: true,
},
},
})
}
func testAccCheckAWSWafRegionalByteMatchSetDisappears(v *waf.ByteMatchSet) resource.TestCheckFunc {
return func(s *terraform.State) error {
conn := testAccProvider.Meta().(*AWSClient).wafregionalconn
region := testAccProvider.Meta().(*AWSClient).region
wr := newWafRegionalRetryer(conn, region)
_, err := wr.RetryWithToken(func(token *string) (interface{}, error) {
req := &waf.UpdateByteMatchSetInput{
ChangeToken: token,
ByteMatchSetId: v.ByteMatchSetId,
}
for _, ByteMatchTuple := range v.ByteMatchTuples {
ByteMatchUpdate := &waf.ByteMatchSetUpdate{
Action: aws.String("DELETE"),
ByteMatchTuple: &waf.ByteMatchTuple{
FieldToMatch: ByteMatchTuple.FieldToMatch,
PositionalConstraint: ByteMatchTuple.PositionalConstraint,
TargetString: ByteMatchTuple.TargetString,
TextTransformation: ByteMatchTuple.TextTransformation,
},
}
req.Updates = append(req.Updates, ByteMatchUpdate)
}
return conn.UpdateByteMatchSet(req)
})
if err != nil {
return errwrap.Wrapf("[ERROR] Error updating ByteMatchSet: {{err}}", err)
}
_, err = wr.RetryWithToken(func(token *string) (interface{}, error) {
opts := &waf.DeleteByteMatchSetInput{
ChangeToken: token,
ByteMatchSetId: v.ByteMatchSetId,
}
return conn.DeleteByteMatchSet(opts)
})
if err != nil {
return errwrap.Wrapf("[ERROR] Error deleting ByteMatchSet: {{err}}", err)
}
return nil
}
}
func testAccCheckAWSWafRegionalByteMatchSetExists(n string, v *waf.ByteMatchSet) resource.TestCheckFunc {
return func(s *terraform.State) error {
rs, ok := s.RootModule().Resources[n]
if !ok {
return fmt.Errorf("Not found: %s", n)
}
if rs.Primary.ID == "" {
return fmt.Errorf("No WAF ByteMatchSet ID is set")
}
conn := testAccProvider.Meta().(*AWSClient).wafregionalconn
resp, err := conn.GetByteMatchSet(&waf.GetByteMatchSetInput{
ByteMatchSetId: aws.String(rs.Primary.ID),
})
if err != nil {
return err
}
if *resp.ByteMatchSet.ByteMatchSetId == rs.Primary.ID {
*v = *resp.ByteMatchSet
return nil
}
return fmt.Errorf("WAF ByteMatchSet (%s) not found", rs.Primary.ID)
}
}
func testAccCheckAWSWafRegionalByteMatchSetDestroy(s *terraform.State) error {
for _, rs := range s.RootModule().Resources {
if rs.Type != "aws_wafregional_byte_match_set" {
continue
}
conn := testAccProvider.Meta().(*AWSClient).wafregionalconn
resp, err := conn.GetByteMatchSet(
&waf.GetByteMatchSetInput{
ByteMatchSetId: aws.String(rs.Primary.ID),
})
if err == nil {
if *resp.ByteMatchSet.ByteMatchSetId == rs.Primary.ID {
return fmt.Errorf("WAF ByteMatchSet %s still exists", rs.Primary.ID)
}
}
// Return nil if the ByteMatchSet is already destroyed
if awsErr, ok := err.(awserr.Error); ok {
if awsErr.Code() == "WAFNonexistentItemException" {
return nil
}
}
return err
}
return nil
}
func testAccAWSWafRegionalByteMatchSetConfig(name string) string {
return fmt.Sprintf(`
resource "aws_wafregional_byte_match_set" "byte_set" {
name = "%s"
byte_match_tuple {
text_transformation = "NONE"
target_string = "badrefer1"
positional_constraint = "CONTAINS"
field_to_match {
type = "HEADER"
data = "referer"
}
}
byte_match_tuple {
text_transformation = "NONE"
target_string = "badrefer2"
positional_constraint = "CONTAINS"
field_to_match {
type = "HEADER"
data = "referer"
}
}
}`, name)
}
func testAccAWSWafRegionalByteMatchSetConfigChangeName(name string) string {
return fmt.Sprintf(`
resource "aws_wafregional_byte_match_set" "byte_set" {
name = "%s"
byte_match_tuple {
text_transformation = "NONE"
target_string = "badrefer1"
positional_constraint = "CONTAINS"
field_to_match {
type = "HEADER"
data = "referer"
}
}
byte_match_tuple {
text_transformation = "NONE"
target_string = "badrefer2"
positional_constraint = "CONTAINS"
field_to_match {
type = "HEADER"
data = "referer"
}
}
}`, name)
}
func testAccAWSWafRegionalByteMatchSetConfig_noDescriptors(name string) string {
return fmt.Sprintf(`
resource "aws_wafregional_byte_match_set" "byte_match_set" {
name = "%s"
}`, name)
}
func testAccAWSWafRegionalByteMatchSetConfigChangeByteMatchTuple(name string) string {
return fmt.Sprintf(`
resource "aws_wafregional_byte_match_set" "byte_set" {
name = "%s"
byte_match_tuple {
text_transformation = "LOWERCASE"
target_string = "badrefer1+"
positional_constraint = "STARTS_WITH"
field_to_match {
type = "METHOD"
data = "GET"
}
}
byte_match_tuple {
text_transformation = "LOWERCASE"
target_string = "badrefer2+"
positional_constraint = "ENDS_WITH"
field_to_match {
type = "URI"
}
}
}`, name)
}

View File

@ -0,0 +1,170 @@
package aws
import (
"fmt"
"log"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/service/waf"
"github.com/aws/aws-sdk-go/service/wafregional"
"github.com/hashicorp/terraform/helper/schema"
)
func resourceAwsWafRegionalIPSet() *schema.Resource {
return &schema.Resource{
Create: resourceAwsWafRegionalIPSetCreate,
Read: resourceAwsWafRegionalIPSetRead,
Update: resourceAwsWafRegionalIPSetUpdate,
Delete: resourceAwsWafRegionalIPSetDelete,
Schema: map[string]*schema.Schema{
"name": &schema.Schema{
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"ip_set_descriptor": &schema.Schema{
Type: schema.TypeSet,
Optional: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"type": &schema.Schema{
Type: schema.TypeString,
Required: true,
},
"value": &schema.Schema{
Type: schema.TypeString,
Required: true,
},
},
},
},
},
}
}
func resourceAwsWafRegionalIPSetCreate(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AWSClient).wafregionalconn
region := meta.(*AWSClient).region
wr := newWafRegionalRetryer(conn, region)
out, err := wr.RetryWithToken(func(token *string) (interface{}, error) {
params := &waf.CreateIPSetInput{
ChangeToken: token,
Name: aws.String(d.Get("name").(string)),
}
return conn.CreateIPSet(params)
})
if err != nil {
return err
}
resp := out.(*waf.CreateIPSetOutput)
d.SetId(*resp.IPSet.IPSetId)
return resourceAwsWafRegionalIPSetUpdate(d, meta)
}
func resourceAwsWafRegionalIPSetRead(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AWSClient).wafregionalconn
params := &waf.GetIPSetInput{
IPSetId: aws.String(d.Id()),
}
resp, err := conn.GetIPSet(params)
if err != nil {
if awsErr, ok := err.(awserr.Error); ok && awsErr.Code() == "WAFNonexistentItemException" {
log.Printf("[WARN] WAF IPSet (%s) not found, error code (404)", d.Id())
d.SetId("")
return nil
}
return err
}
d.Set("ip_set_descriptor", flattenWafIpSetDescriptorWR(resp.IPSet.IPSetDescriptors))
d.Set("name", resp.IPSet.Name)
return nil
}
func flattenWafIpSetDescriptorWR(in []*waf.IPSetDescriptor) []interface{} {
descriptors := make([]interface{}, len(in), len(in))
for i, descriptor := range in {
d := map[string]interface{}{
"type": *descriptor.Type,
"value": *descriptor.Value,
}
descriptors[i] = d
}
return descriptors
}
func resourceAwsWafRegionalIPSetUpdate(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AWSClient).wafregionalconn
region := meta.(*AWSClient).region
if d.HasChange("ip_set_descriptor") {
o, n := d.GetChange("ip_set_descriptor")
oldD, newD := o.(*schema.Set).List(), n.(*schema.Set).List()
err := updateIPSetResourceWR(d.Id(), oldD, newD, conn, region)
if err != nil {
return fmt.Errorf("Error Updating WAF IPSet: %s", err)
}
}
return resourceAwsWafRegionalIPSetRead(d, meta)
}
func resourceAwsWafRegionalIPSetDelete(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AWSClient).wafregionalconn
region := meta.(*AWSClient).region
oldD := d.Get("ip_set_descriptor").(*schema.Set).List()
if len(oldD) > 0 {
noD := []interface{}{}
err := updateIPSetResourceWR(d.Id(), oldD, noD, conn, region)
if err != nil {
return fmt.Errorf("Error Removing IPSetDescriptors: %s", err)
}
}
wr := newWafRegionalRetryer(conn, region)
_, err := wr.RetryWithToken(func(token *string) (interface{}, error) {
req := &waf.DeleteIPSetInput{
ChangeToken: token,
IPSetId: aws.String(d.Id()),
}
log.Printf("[INFO] Deleting WAF IPSet")
return conn.DeleteIPSet(req)
})
if err != nil {
return fmt.Errorf("Error Deleting WAF IPSet: %s", err)
}
return nil
}
func updateIPSetResourceWR(id string, oldD, newD []interface{}, conn *wafregional.WAFRegional, region string) error {
wr := newWafRegionalRetryer(conn, region)
_, err := wr.RetryWithToken(func(token *string) (interface{}, error) {
req := &waf.UpdateIPSetInput{
ChangeToken: token,
IPSetId: aws.String(id),
Updates: diffWafIpSetDescriptors(oldD, newD),
}
log.Printf("[INFO] Updating IPSet descriptor: %s", req)
return conn.UpdateIPSet(req)
})
if err != nil {
return fmt.Errorf("Error Updating WAF IPSet: %s", err)
}
return nil
}

View File

@ -0,0 +1,402 @@
package aws
import (
"fmt"
"reflect"
"testing"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/service/waf"
"github.com/aws/aws-sdk-go/service/wafregional"
"github.com/hashicorp/terraform/helper/acctest"
)
func TestAccAWSWafRegionalIPSet_basic(t *testing.T) {
var v waf.IPSet
ipsetName := fmt.Sprintf("ip-set-%s", acctest.RandString(5))
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckAWSWafRegionalIPSetDestroy,
Steps: []resource.TestStep{
resource.TestStep{
Config: testAccAWSWafRegionalIPSetConfig(ipsetName),
Check: resource.ComposeTestCheckFunc(
testAccCheckAWSWafRegionalIPSetExists("aws_wafregional_ipset.ipset", &v),
resource.TestCheckResourceAttr(
"aws_wafregional_ipset.ipset", "name", ipsetName),
resource.TestCheckResourceAttr(
"aws_wafregional_ipset.ipset", "ip_set_descriptor.4037960608.type", "IPV4"),
resource.TestCheckResourceAttr(
"aws_wafregional_ipset.ipset", "ip_set_descriptor.4037960608.value", "192.0.7.0/24"),
),
},
},
})
}
func TestAccAWSWafRegionalIPSet_disappears(t *testing.T) {
var v waf.IPSet
ipsetName := fmt.Sprintf("ip-set-%s", acctest.RandString(5))
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckAWSWafRegionalIPSetDestroy,
Steps: []resource.TestStep{
{
Config: testAccAWSWafRegionalIPSetConfig(ipsetName),
Check: resource.ComposeTestCheckFunc(
testAccCheckAWSWafRegionalIPSetExists("aws_wafregional_ipset.ipset", &v),
testAccCheckAWSWafRegionalIPSetDisappears(&v),
),
ExpectNonEmptyPlan: true,
},
},
})
}
func TestAccAWSWafRegionalIPSet_changeNameForceNew(t *testing.T) {
var before, after waf.IPSet
ipsetName := fmt.Sprintf("ip-set-%s", acctest.RandString(5))
ipsetNewName := fmt.Sprintf("ip-set-new-%s", acctest.RandString(5))
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckAWSWafRegionalIPSetDestroy,
Steps: []resource.TestStep{
{
Config: testAccAWSWafRegionalIPSetConfig(ipsetName),
Check: resource.ComposeAggregateTestCheckFunc(
testAccCheckAWSWafRegionalIPSetExists("aws_wafregional_ipset.ipset", &before),
resource.TestCheckResourceAttr(
"aws_wafregional_ipset.ipset", "name", ipsetName),
resource.TestCheckResourceAttr(
"aws_wafregional_ipset.ipset", "ip_set_descriptor.4037960608.type", "IPV4"),
resource.TestCheckResourceAttr(
"aws_wafregional_ipset.ipset", "ip_set_descriptor.4037960608.value", "192.0.7.0/24"),
),
},
{
Config: testAccAWSWafRegionalIPSetConfigChangeName(ipsetNewName),
Check: resource.ComposeAggregateTestCheckFunc(
testAccCheckAWSWafRegionalIPSetExists("aws_wafregional_ipset.ipset", &after),
resource.TestCheckResourceAttr(
"aws_wafregional_ipset.ipset", "name", ipsetNewName),
resource.TestCheckResourceAttr(
"aws_wafregional_ipset.ipset", "ip_set_descriptor.4037960608.type", "IPV4"),
resource.TestCheckResourceAttr(
"aws_wafregional_ipset.ipset", "ip_set_descriptor.4037960608.value", "192.0.7.0/24"),
),
},
},
})
}
func TestAccAWSWafRegionalIPSet_changeDescriptors(t *testing.T) {
var before, after waf.IPSet
ipsetName := fmt.Sprintf("ip-set-%s", acctest.RandString(5))
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckAWSWafRegionalIPSetDestroy,
Steps: []resource.TestStep{
{
Config: testAccAWSWafRegionalIPSetConfig(ipsetName),
Check: resource.ComposeAggregateTestCheckFunc(
testAccCheckAWSWafRegionalIPSetExists("aws_wafregional_ipset.ipset", &before),
resource.TestCheckResourceAttr(
"aws_wafregional_ipset.ipset", "name", ipsetName),
resource.TestCheckResourceAttr(
"aws_wafregional_ipset.ipset", "ip_set_descriptor.#", "1"),
resource.TestCheckResourceAttr(
"aws_wafregional_ipset.ipset", "ip_set_descriptor.4037960608.type", "IPV4"),
resource.TestCheckResourceAttr(
"aws_wafregional_ipset.ipset", "ip_set_descriptor.4037960608.value", "192.0.7.0/24"),
),
},
{
Config: testAccAWSWafRegionalIPSetConfigChangeIPSetDescriptors(ipsetName),
Check: resource.ComposeAggregateTestCheckFunc(
testAccCheckAWSWafRegionalIPSetExists("aws_wafregional_ipset.ipset", &after),
resource.TestCheckResourceAttr(
"aws_wafregional_ipset.ipset", "name", ipsetName),
resource.TestCheckResourceAttr(
"aws_wafregional_ipset.ipset", "ip_set_descriptor.#", "1"),
resource.TestCheckResourceAttr(
"aws_wafregional_ipset.ipset", "ip_set_descriptor.115741513.type", "IPV4"),
resource.TestCheckResourceAttr(
"aws_wafregional_ipset.ipset", "ip_set_descriptor.115741513.value", "192.0.8.0/24"),
),
},
},
})
}
func TestAccAWSWafRegionalIPSet_noDescriptors(t *testing.T) {
var ipset waf.IPSet
ipsetName := fmt.Sprintf("ip-set-%s", acctest.RandString(5))
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckAWSWafRegionalIPSetDestroy,
Steps: []resource.TestStep{
{
Config: testAccAWSWafRegionalIPSetConfig_noDescriptors(ipsetName),
Check: resource.ComposeAggregateTestCheckFunc(
testAccCheckAWSWafRegionalIPSetExists("aws_wafregional_ipset.ipset", &ipset),
resource.TestCheckResourceAttr(
"aws_wafregional_ipset.ipset", "name", ipsetName),
resource.TestCheckResourceAttr(
"aws_wafregional_ipset.ipset", "ip_set_descriptor.#", "0"),
),
},
},
})
}
func TestDiffWafRegionalIpSetDescriptors(t *testing.T) {
testCases := []struct {
Old []interface{}
New []interface{}
ExpectedUpdates []*waf.IPSetUpdate
}{
{
// Change
Old: []interface{}{
map[string]interface{}{"type": "IPV4", "value": "192.0.7.0/24"},
},
New: []interface{}{
map[string]interface{}{"type": "IPV4", "value": "192.0.8.0/24"},
},
ExpectedUpdates: []*waf.IPSetUpdate{
&waf.IPSetUpdate{
Action: aws.String(wafregional.ChangeActionDelete),
IPSetDescriptor: &waf.IPSetDescriptor{
Type: aws.String("IPV4"),
Value: aws.String("192.0.7.0/24"),
},
},
&waf.IPSetUpdate{
Action: aws.String(wafregional.ChangeActionInsert),
IPSetDescriptor: &waf.IPSetDescriptor{
Type: aws.String("IPV4"),
Value: aws.String("192.0.8.0/24"),
},
},
},
},
{
// Fresh IPSet
Old: []interface{}{},
New: []interface{}{
map[string]interface{}{"type": "IPV4", "value": "10.0.1.0/24"},
map[string]interface{}{"type": "IPV4", "value": "10.0.2.0/24"},
map[string]interface{}{"type": "IPV4", "value": "10.0.3.0/24"},
},
ExpectedUpdates: []*waf.IPSetUpdate{
&waf.IPSetUpdate{
Action: aws.String(wafregional.ChangeActionInsert),
IPSetDescriptor: &waf.IPSetDescriptor{
Type: aws.String("IPV4"),
Value: aws.String("10.0.1.0/24"),
},
},
&waf.IPSetUpdate{
Action: aws.String(wafregional.ChangeActionInsert),
IPSetDescriptor: &waf.IPSetDescriptor{
Type: aws.String("IPV4"),
Value: aws.String("10.0.2.0/24"),
},
},
&waf.IPSetUpdate{
Action: aws.String(wafregional.ChangeActionInsert),
IPSetDescriptor: &waf.IPSetDescriptor{
Type: aws.String("IPV4"),
Value: aws.String("10.0.3.0/24"),
},
},
},
},
{
// Deletion
Old: []interface{}{
map[string]interface{}{"type": "IPV4", "value": "192.0.7.0/24"},
map[string]interface{}{"type": "IPV4", "value": "192.0.8.0/24"},
},
New: []interface{}{},
ExpectedUpdates: []*waf.IPSetUpdate{
&waf.IPSetUpdate{
Action: aws.String(wafregional.ChangeActionDelete),
IPSetDescriptor: &waf.IPSetDescriptor{
Type: aws.String("IPV4"),
Value: aws.String("192.0.7.0/24"),
},
},
&waf.IPSetUpdate{
Action: aws.String(wafregional.ChangeActionDelete),
IPSetDescriptor: &waf.IPSetDescriptor{
Type: aws.String("IPV4"),
Value: aws.String("192.0.8.0/24"),
},
},
},
},
}
for i, tc := range testCases {
t.Run(fmt.Sprintf("%d", i), func(t *testing.T) {
updates := diffWafIpSetDescriptors(tc.Old, tc.New)
if !reflect.DeepEqual(updates, tc.ExpectedUpdates) {
t.Fatalf("IPSet updates don't match.\nGiven: %s\nExpected: %s",
updates, tc.ExpectedUpdates)
}
})
}
}
func testAccCheckAWSWafRegionalIPSetDisappears(v *waf.IPSet) resource.TestCheckFunc {
return func(s *terraform.State) error {
conn := testAccProvider.Meta().(*AWSClient).wafregionalconn
region := testAccProvider.Meta().(*AWSClient).region
wr := newWafRegionalRetryer(conn, region)
_, err := wr.RetryWithToken(func(token *string) (interface{}, error) {
req := &waf.UpdateIPSetInput{
ChangeToken: token,
IPSetId: v.IPSetId,
}
for _, IPSetDescriptor := range v.IPSetDescriptors {
IPSetUpdate := &waf.IPSetUpdate{
Action: aws.String("DELETE"),
IPSetDescriptor: &waf.IPSetDescriptor{
Type: IPSetDescriptor.Type,
Value: IPSetDescriptor.Value,
},
}
req.Updates = append(req.Updates, IPSetUpdate)
}
return conn.UpdateIPSet(req)
})
if err != nil {
return fmt.Errorf("Error Updating WAF IPSet: %s", err)
}
_, err = wr.RetryWithToken(func(token *string) (interface{}, error) {
opts := &waf.DeleteIPSetInput{
ChangeToken: token,
IPSetId: v.IPSetId,
}
return conn.DeleteIPSet(opts)
})
if err != nil {
return fmt.Errorf("Error Deleting WAF IPSet: %s", err)
}
return nil
}
}
func testAccCheckAWSWafRegionalIPSetDestroy(s *terraform.State) error {
for _, rs := range s.RootModule().Resources {
if rs.Type != "aws_wafregional_ipset" {
continue
}
conn := testAccProvider.Meta().(*AWSClient).wafregionalconn
resp, err := conn.GetIPSet(
&waf.GetIPSetInput{
IPSetId: aws.String(rs.Primary.ID),
})
if err == nil {
if *resp.IPSet.IPSetId == rs.Primary.ID {
return fmt.Errorf("WAF IPSet %s still exists", rs.Primary.ID)
}
}
// Return nil if the IPSet is already destroyed
if awsErr, ok := err.(awserr.Error); ok {
if awsErr.Code() == "WAFNonexistentItemException" {
return nil
}
}
return err
}
return nil
}
func testAccCheckAWSWafRegionalIPSetExists(n string, v *waf.IPSet) resource.TestCheckFunc {
return func(s *terraform.State) error {
rs, ok := s.RootModule().Resources[n]
if !ok {
return fmt.Errorf("Not found: %s", n)
}
if rs.Primary.ID == "" {
return fmt.Errorf("No WAF IPSet ID is set")
}
conn := testAccProvider.Meta().(*AWSClient).wafregionalconn
resp, err := conn.GetIPSet(&waf.GetIPSetInput{
IPSetId: aws.String(rs.Primary.ID),
})
if err != nil {
return err
}
if *resp.IPSet.IPSetId == rs.Primary.ID {
*v = *resp.IPSet
return nil
}
return fmt.Errorf("WAF IPSet (%s) not found", rs.Primary.ID)
}
}
func testAccAWSWafRegionalIPSetConfig(name string) string {
return fmt.Sprintf(`
resource "aws_wafregional_ipset" "ipset" {
name = "%s"
ip_set_descriptor {
type = "IPV4"
value = "192.0.7.0/24"
}
}`, name)
}
func testAccAWSWafRegionalIPSetConfigChangeName(name string) string {
return fmt.Sprintf(`resource "aws_wafregional_ipset" "ipset" {
name = "%s"
ip_set_descriptor {
type = "IPV4"
value = "192.0.7.0/24"
}
}`, name)
}
func testAccAWSWafRegionalIPSetConfigChangeIPSetDescriptors(name string) string {
return fmt.Sprintf(`resource "aws_wafregional_ipset" "ipset" {
name = "%s"
ip_set_descriptor {
type = "IPV4"
value = "192.0.8.0/24"
}
}`, name)
}
func testAccAWSWafRegionalIPSetConfig_noDescriptors(name string) string {
return fmt.Sprintf(`resource "aws_wafregional_ipset" "ipset" {
name = "%s"
}`, name)
}

View File

@ -0,0 +1,50 @@
package aws
import (
"time"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/service/waf"
"github.com/aws/aws-sdk-go/service/wafregional"
"github.com/hashicorp/errwrap"
"github.com/hashicorp/terraform/helper/resource"
)
type WafRegionalRetryer struct {
Connection *wafregional.WAFRegional
Region string
}
type withRegionalTokenFunc func(token *string) (interface{}, error)
func (t *WafRegionalRetryer) RetryWithToken(f withRegionalTokenFunc) (interface{}, error) {
awsMutexKV.Lock(t.Region)
defer awsMutexKV.Unlock(t.Region)
var out interface{}
err := resource.Retry(15*time.Minute, func() *resource.RetryError {
var err error
var tokenOut *waf.GetChangeTokenOutput
tokenOut, err = t.Connection.GetChangeToken(&waf.GetChangeTokenInput{})
if err != nil {
return resource.NonRetryableError(errwrap.Wrapf("Failed to acquire change token: {{err}}", err))
}
out, err = f(tokenOut.ChangeToken)
if err != nil {
awsErr, ok := err.(awserr.Error)
if ok && awsErr.Code() == "WAFStaleDataException" {
return resource.RetryableError(err)
}
return resource.NonRetryableError(err)
}
return nil
})
return out, err
}
func newWafRegionalRetryer(conn *wafregional.WAFRegional, region string) *WafRegionalRetryer {
return &WafRegionalRetryer{Connection: conn, Region: region}
}

View File

@ -0,0 +1,55 @@
---
layout: "aws"
page_title: "AWS: wafregional_byte_match_set"
sidebar_current: "docs-aws-resource-wafregional-bytematchset"
description: |-
Provides a AWS WAF Regional ByteMatchSet resource for use with ALB.
---
# aws\_wafregional\_byte\_match\_set
Provides a WAF Regional Byte Match Set Resource for use with Application Load Balancer.
## Example Usage
```
resource "aws_wafregional_byte_match_set" "byte_set" {
name = "tf_waf_byte_match_set"
byte_match_tuple {
text_transformation = "NONE"
target_string = "badrefer1"
positional_constraint = "CONTAINS"
field_to_match {
type = "HEADER"
data = "referer"
}
}
}
```
## Argument Reference
The following arguments are supported:
* `name` - (Required) The name or description of the ByteMatchSet.
* `byte_match_tuple` - (Optional)Settings for the ByteMatchSet, such as the bytes (typically a string that corresponds with ASCII characters) that you want AWS WAF to search for in web requests. ByteMatchTuple documented below.
ByteMatchTuple(byte_match_tuple) support the following:
* `field_to_match` - (Required) Settings for the ByteMatchTuple. FieldToMatch documented below.
* `positional_constraint` - (Required) Within the portion of a web request that you want to search.
* `target_string` - (Required) The value that you want AWS WAF to search for. The maximum length of the value is 50 bytes.
* `text_transformation` - (Required) The formatting way for web request.
FieldToMatch(field_to_match) support following:
* `data` - (Optional) When the value of Type is HEADER, enter the name of the header that you want AWS WAF to search, for example, User-Agent or Referer. If the value of Type is any other value, omit Data.
* `type` - (Required) The part of the web request that you want AWS WAF to search for a specified string.
## Remarks
## Attributes Reference
The following attributes are exported:
* `id` - The ID of the WAF ByteMatchSet.

View File

@ -0,0 +1,44 @@
---
layout: "aws"
page_title: "AWS: wafregional_ipset"
sidebar_current: "docs-aws-resource-wafregional-ipset"
description: |-
Provides a AWS WAF Regional IPSet resource for use with ALB.
---
# aws\_wafregional\_ipset
Provides a WAF Regional IPSet Resource for use with Application Load Balancer.
## Example Usage
```
resource "aws_wafregional_ipset" "ipset" {
name = "tfIPSet"
ip_set_descriptor {
type = "IPV4"
value = "192.0.7.0/24"
}
}
```
## Argument Reference
The following arguments are supported:
* `name` - (Required) The name or description of the IPSet.
* `ip_set_descriptor` - (Optional) The IP address type and IP address range (in CIDR notation) from which web requests originate.
IPSetDescriptor(ip_set_descriptor) support following:
* `type` - (Required) The string like IPV4 or IPV6.
* `value` - (Required) The CIDR notation.
## Remarks
## Attributes Reference
The following attributes are exported:
* `id` - The ID of the WAF IPSet.

View File

@ -1122,6 +1122,21 @@
</ul> </ul>
</li> </li>
<li<%= sidebar_current(/^docs-aws-resource-wafregional/) %>>
<a href="#">WAF Regional Resources</a>
<ul class="nav nav-visible">
<li<%= sidebar_current("docs-aws-resource-wafregional-bytematchset") %>>
<a href="/docs/providers/aws/r/wafregional_byte_match_set.html">aws_wafregional_byte_match_set</a>
</li>
<li<%= sidebar_current("docs-aws-resource-wafregional-ipset") %>>
<a href="/docs/providers/aws/r/wafregional_ipset.html">aws_wafregional_ipset</a>
</li>
</ul>
</li>
<li<%= sidebar_current("docs-aws-resource-route53") %>> <li<%= sidebar_current("docs-aws-resource-route53") %>>
<a href="#">Route53 Resources</a> <a href="#">Route53 Resources</a>