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:
parent
5367f2607e
commit
3b14fc90d9
|
@ -66,6 +66,7 @@ import (
|
|||
"github.com/aws/aws-sdk-go/service/ssm"
|
||||
"github.com/aws/aws-sdk-go/service/sts"
|
||||
"github.com/aws/aws-sdk-go/service/waf"
|
||||
"github.com/aws/aws-sdk-go/service/wafregional"
|
||||
"github.com/davecgh/go-spew/spew"
|
||||
"github.com/hashicorp/errwrap"
|
||||
"github.com/hashicorp/go-cleanhttp"
|
||||
|
@ -172,6 +173,7 @@ type AWSClient struct {
|
|||
sfnconn *sfn.SFN
|
||||
ssmconn *ssm.SSM
|
||||
wafconn *waf.WAF
|
||||
wafregionalconn *wafregional.WAFRegional
|
||||
}
|
||||
|
||||
func (c *AWSClient) S3() *s3.S3 {
|
||||
|
@ -379,6 +381,7 @@ func (c *Config) Client() (interface{}, error) {
|
|||
client.sqsconn = sqs.New(awsSqsSess)
|
||||
client.ssmconn = ssm.New(sess)
|
||||
client.wafconn = waf.New(sess)
|
||||
client.wafregionalconn = wafregional.New(sess)
|
||||
|
||||
return &client, nil
|
||||
}
|
||||
|
|
|
@ -457,6 +457,8 @@ func Provider() terraform.ResourceProvider {
|
|||
"aws_waf_web_acl": resourceAwsWafWebAcl(),
|
||||
"aws_waf_xss_match_set": resourceAwsWafXssMatchSet(),
|
||||
"aws_waf_sql_injection_match_set": resourceAwsWafSqlInjectionMatchSet(),
|
||||
"aws_wafregional_byte_match_set": resourceAwsWafRegionalByteMatchSet(),
|
||||
"aws_wafregional_ipset": resourceAwsWafRegionalIPSet(),
|
||||
},
|
||||
ConfigureFunc: providerConfigure,
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
|
@ -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)
|
||||
}
|
|
@ -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
|
||||
}
|
|
@ -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)
|
||||
}
|
|
@ -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}
|
||||
}
|
|
@ -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.
|
|
@ -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.
|
|
@ -1122,6 +1122,21 @@
|
|||
</ul>
|
||||
</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") %>>
|
||||
<a href="#">Route53 Resources</a>
|
||||
|
|
Loading…
Reference in New Issue