github.com/koding/terraform@v0.6.4-0.20170608090606-5d7e0339779d/builtin/providers/aws/resource_aws_waf_rule_test.go (about)

     1  package aws
     2  
     3  import (
     4  	"fmt"
     5  	"testing"
     6  
     7  	"github.com/hashicorp/terraform/helper/resource"
     8  	"github.com/hashicorp/terraform/helper/schema"
     9  	"github.com/hashicorp/terraform/terraform"
    10  
    11  	"github.com/aws/aws-sdk-go/aws"
    12  	"github.com/aws/aws-sdk-go/aws/awserr"
    13  	"github.com/aws/aws-sdk-go/service/waf"
    14  	"github.com/hashicorp/terraform/helper/acctest"
    15  )
    16  
    17  func TestAccAWSWafRule_basic(t *testing.T) {
    18  	var v waf.Rule
    19  	wafRuleName := fmt.Sprintf("wafrule%s", acctest.RandString(5))
    20  	resource.Test(t, resource.TestCase{
    21  		PreCheck:     func() { testAccPreCheck(t) },
    22  		Providers:    testAccProviders,
    23  		CheckDestroy: testAccCheckAWSWafRuleDestroy,
    24  		Steps: []resource.TestStep{
    25  			resource.TestStep{
    26  				Config: testAccAWSWafRuleConfig(wafRuleName),
    27  				Check: resource.ComposeTestCheckFunc(
    28  					testAccCheckAWSWafRuleExists("aws_waf_rule.wafrule", &v),
    29  					resource.TestCheckResourceAttr(
    30  						"aws_waf_rule.wafrule", "name", wafRuleName),
    31  					resource.TestCheckResourceAttr(
    32  						"aws_waf_rule.wafrule", "predicates.#", "1"),
    33  					resource.TestCheckResourceAttr(
    34  						"aws_waf_rule.wafrule", "metric_name", wafRuleName),
    35  				),
    36  			},
    37  		},
    38  	})
    39  }
    40  
    41  func TestAccAWSWafRule_changeNameForceNew(t *testing.T) {
    42  	var before, after waf.Rule
    43  	wafRuleName := fmt.Sprintf("wafrule%s", acctest.RandString(5))
    44  	wafRuleNewName := fmt.Sprintf("wafrulenew%s", acctest.RandString(5))
    45  
    46  	resource.Test(t, resource.TestCase{
    47  		PreCheck:     func() { testAccPreCheck(t) },
    48  		Providers:    testAccProviders,
    49  		CheckDestroy: testAccCheckAWSWafIPSetDestroy,
    50  		Steps: []resource.TestStep{
    51  			{
    52  				Config: testAccAWSWafRuleConfig(wafRuleName),
    53  				Check: resource.ComposeTestCheckFunc(
    54  					testAccCheckAWSWafRuleExists("aws_waf_rule.wafrule", &before),
    55  					resource.TestCheckResourceAttr(
    56  						"aws_waf_rule.wafrule", "name", wafRuleName),
    57  					resource.TestCheckResourceAttr(
    58  						"aws_waf_rule.wafrule", "predicates.#", "1"),
    59  					resource.TestCheckResourceAttr(
    60  						"aws_waf_rule.wafrule", "metric_name", wafRuleName),
    61  				),
    62  			},
    63  			{
    64  				Config: testAccAWSWafRuleConfigChangeName(wafRuleNewName),
    65  				Check: resource.ComposeTestCheckFunc(
    66  					testAccCheckAWSWafRuleExists("aws_waf_rule.wafrule", &after),
    67  					resource.TestCheckResourceAttr(
    68  						"aws_waf_rule.wafrule", "name", wafRuleNewName),
    69  					resource.TestCheckResourceAttr(
    70  						"aws_waf_rule.wafrule", "predicates.#", "1"),
    71  					resource.TestCheckResourceAttr(
    72  						"aws_waf_rule.wafrule", "metric_name", wafRuleNewName),
    73  				),
    74  			},
    75  		},
    76  	})
    77  }
    78  
    79  func TestAccAWSWafRule_disappears(t *testing.T) {
    80  	var v waf.Rule
    81  	wafRuleName := fmt.Sprintf("wafrule%s", acctest.RandString(5))
    82  	resource.Test(t, resource.TestCase{
    83  		PreCheck:     func() { testAccPreCheck(t) },
    84  		Providers:    testAccProviders,
    85  		CheckDestroy: testAccCheckAWSWafRuleDestroy,
    86  		Steps: []resource.TestStep{
    87  			{
    88  				Config: testAccAWSWafRuleConfig(wafRuleName),
    89  				Check: resource.ComposeTestCheckFunc(
    90  					testAccCheckAWSWafRuleExists("aws_waf_rule.wafrule", &v),
    91  					testAccCheckAWSWafRuleDisappears(&v),
    92  				),
    93  				ExpectNonEmptyPlan: true,
    94  			},
    95  		},
    96  	})
    97  }
    98  
    99  func TestAccAWSWafRule_changePredicates(t *testing.T) {
   100  	var ipset waf.IPSet
   101  	var byteMatchSet waf.ByteMatchSet
   102  
   103  	var before, after waf.Rule
   104  	var idx int
   105  	ruleName := fmt.Sprintf("wafrule%s", acctest.RandString(5))
   106  
   107  	resource.Test(t, resource.TestCase{
   108  		PreCheck:     func() { testAccPreCheck(t) },
   109  		Providers:    testAccProviders,
   110  		CheckDestroy: testAccCheckAWSWafRuleDestroy,
   111  		Steps: []resource.TestStep{
   112  			{
   113  				Config: testAccAWSWafRuleConfig(ruleName),
   114  				Check: resource.ComposeAggregateTestCheckFunc(
   115  					testAccCheckAWSWafIPSetExists("aws_waf_ipset.ipset", &ipset),
   116  					testAccCheckAWSWafRuleExists("aws_waf_rule.wafrule", &before),
   117  					resource.TestCheckResourceAttr("aws_waf_rule.wafrule", "name", ruleName),
   118  					resource.TestCheckResourceAttr("aws_waf_rule.wafrule", "predicates.#", "1"),
   119  					computeWafRulePredicateWithIpSet(&ipset, false, "IPMatch", &idx),
   120  					testCheckResourceAttrWithIndexesAddr("aws_waf_rule.wafrule", "predicates.%d.negated", &idx, "false"),
   121  					testCheckResourceAttrWithIndexesAddr("aws_waf_rule.wafrule", "predicates.%d.type", &idx, "IPMatch"),
   122  				),
   123  			},
   124  			{
   125  				Config: testAccAWSWafRuleConfig_changePredicates(ruleName),
   126  				Check: resource.ComposeAggregateTestCheckFunc(
   127  					testAccCheckAWSWafByteMatchSetExists("aws_waf_byte_match_set.set", &byteMatchSet),
   128  					testAccCheckAWSWafRuleExists("aws_waf_rule.wafrule", &after),
   129  					resource.TestCheckResourceAttr("aws_waf_rule.wafrule", "name", ruleName),
   130  					resource.TestCheckResourceAttr("aws_waf_rule.wafrule", "predicates.#", "1"),
   131  					computeWafRulePredicateWithByteMatchSet(&byteMatchSet, true, "ByteMatch", &idx),
   132  					testCheckResourceAttrWithIndexesAddr("aws_waf_rule.wafrule", "predicates.%d.negated", &idx, "true"),
   133  					testCheckResourceAttrWithIndexesAddr("aws_waf_rule.wafrule", "predicates.%d.type", &idx, "ByteMatch"),
   134  				),
   135  			},
   136  		},
   137  	})
   138  }
   139  
   140  // computeWafRulePredicateWithIpSet calculates index
   141  // which isn't static because dataId is generated as part of the test
   142  func computeWafRulePredicateWithIpSet(ipSet *waf.IPSet, negated bool, pType string, idx *int) resource.TestCheckFunc {
   143  	return func(s *terraform.State) error {
   144  		predicateResource := resourceAwsWafRule().Schema["predicates"].Elem.(*schema.Resource)
   145  
   146  		m := map[string]interface{}{
   147  			"data_id": *ipSet.IPSetId,
   148  			"negated": negated,
   149  			"type":    pType,
   150  		}
   151  
   152  		f := schema.HashResource(predicateResource)
   153  		*idx = f(m)
   154  
   155  		return nil
   156  	}
   157  }
   158  
   159  // computeWafRulePredicateWithByteMatchSet calculates index
   160  // which isn't static because dataId is generated as part of the test
   161  func computeWafRulePredicateWithByteMatchSet(set *waf.ByteMatchSet, negated bool, pType string, idx *int) resource.TestCheckFunc {
   162  	return func(s *terraform.State) error {
   163  		predicateResource := resourceAwsWafRule().Schema["predicates"].Elem.(*schema.Resource)
   164  
   165  		m := map[string]interface{}{
   166  			"data_id": *set.ByteMatchSetId,
   167  			"negated": negated,
   168  			"type":    pType,
   169  		}
   170  
   171  		f := schema.HashResource(predicateResource)
   172  		*idx = f(m)
   173  
   174  		return nil
   175  	}
   176  }
   177  
   178  func testCheckResourceAttrWithIndexesAddr(name, format string, idx *int, value string) resource.TestCheckFunc {
   179  	return func(s *terraform.State) error {
   180  		return resource.TestCheckResourceAttr(name, fmt.Sprintf(format, *idx), value)(s)
   181  	}
   182  }
   183  
   184  func TestAccAWSWafRule_noPredicates(t *testing.T) {
   185  	var rule waf.Rule
   186  	ruleName := fmt.Sprintf("wafrule%s", acctest.RandString(5))
   187  
   188  	resource.Test(t, resource.TestCase{
   189  		PreCheck:     func() { testAccPreCheck(t) },
   190  		Providers:    testAccProviders,
   191  		CheckDestroy: testAccCheckAWSWafRuleDestroy,
   192  		Steps: []resource.TestStep{
   193  			{
   194  				Config: testAccAWSWafRuleConfig_noPredicates(ruleName),
   195  				Check: resource.ComposeAggregateTestCheckFunc(
   196  					testAccCheckAWSWafRuleExists("aws_waf_rule.wafrule", &rule),
   197  					resource.TestCheckResourceAttr(
   198  						"aws_waf_rule.wafrule", "name", ruleName),
   199  					resource.TestCheckResourceAttr(
   200  						"aws_waf_rule.wafrule", "predicates.#", "0"),
   201  				),
   202  			},
   203  		},
   204  	})
   205  }
   206  
   207  func testAccCheckAWSWafRuleDisappears(v *waf.Rule) resource.TestCheckFunc {
   208  	return func(s *terraform.State) error {
   209  		conn := testAccProvider.Meta().(*AWSClient).wafconn
   210  
   211  		wr := newWafRetryer(conn, "global")
   212  		_, err := wr.RetryWithToken(func(token *string) (interface{}, error) {
   213  			req := &waf.UpdateRuleInput{
   214  				ChangeToken: token,
   215  				RuleId:      v.RuleId,
   216  			}
   217  
   218  			for _, Predicate := range v.Predicates {
   219  				Predicate := &waf.RuleUpdate{
   220  					Action: aws.String("DELETE"),
   221  					Predicate: &waf.Predicate{
   222  						Negated: Predicate.Negated,
   223  						Type:    Predicate.Type,
   224  						DataId:  Predicate.DataId,
   225  					},
   226  				}
   227  				req.Updates = append(req.Updates, Predicate)
   228  			}
   229  
   230  			return conn.UpdateRule(req)
   231  		})
   232  		if err != nil {
   233  			return fmt.Errorf("Error Updating WAF Rule: %s", err)
   234  		}
   235  
   236  		_, err = wr.RetryWithToken(func(token *string) (interface{}, error) {
   237  			opts := &waf.DeleteRuleInput{
   238  				ChangeToken: token,
   239  				RuleId:      v.RuleId,
   240  			}
   241  			return conn.DeleteRule(opts)
   242  		})
   243  		if err != nil {
   244  			return fmt.Errorf("Error Deleting WAF Rule: %s", err)
   245  		}
   246  		return nil
   247  	}
   248  }
   249  
   250  func testAccCheckAWSWafRuleDestroy(s *terraform.State) error {
   251  	for _, rs := range s.RootModule().Resources {
   252  		if rs.Type != "aws_waf_rule" {
   253  			continue
   254  		}
   255  
   256  		conn := testAccProvider.Meta().(*AWSClient).wafconn
   257  		resp, err := conn.GetRule(
   258  			&waf.GetRuleInput{
   259  				RuleId: aws.String(rs.Primary.ID),
   260  			})
   261  
   262  		if err == nil {
   263  			if *resp.Rule.RuleId == rs.Primary.ID {
   264  				return fmt.Errorf("WAF Rule %s still exists", rs.Primary.ID)
   265  			}
   266  		}
   267  
   268  		// Return nil if the Rule is already destroyed
   269  		if awsErr, ok := err.(awserr.Error); ok {
   270  			if awsErr.Code() == "WAFNonexistentItemException" {
   271  				return nil
   272  			}
   273  		}
   274  
   275  		return err
   276  	}
   277  
   278  	return nil
   279  }
   280  
   281  func testAccCheckAWSWafRuleExists(n string, v *waf.Rule) resource.TestCheckFunc {
   282  	return func(s *terraform.State) error {
   283  		rs, ok := s.RootModule().Resources[n]
   284  		if !ok {
   285  			return fmt.Errorf("Not found: %s", n)
   286  		}
   287  
   288  		if rs.Primary.ID == "" {
   289  			return fmt.Errorf("No WAF Rule ID is set")
   290  		}
   291  
   292  		conn := testAccProvider.Meta().(*AWSClient).wafconn
   293  		resp, err := conn.GetRule(&waf.GetRuleInput{
   294  			RuleId: aws.String(rs.Primary.ID),
   295  		})
   296  
   297  		if err != nil {
   298  			return err
   299  		}
   300  
   301  		if *resp.Rule.RuleId == rs.Primary.ID {
   302  			*v = *resp.Rule
   303  			return nil
   304  		}
   305  
   306  		return fmt.Errorf("WAF Rule (%s) not found", rs.Primary.ID)
   307  	}
   308  }
   309  
   310  func testAccAWSWafRuleConfig(name string) string {
   311  	return fmt.Sprintf(`
   312  resource "aws_waf_ipset" "ipset" {
   313    name = "%s"
   314    ip_set_descriptors {
   315      type = "IPV4"
   316      value = "192.0.7.0/24"
   317    }
   318  }
   319  
   320  resource "aws_waf_rule" "wafrule" {
   321    depends_on = ["aws_waf_ipset.ipset"]
   322    name = "%s"
   323    metric_name = "%s"
   324    predicates {
   325      data_id = "${aws_waf_ipset.ipset.id}"
   326      negated = false
   327      type = "IPMatch"
   328    }
   329  }`, name, name, name)
   330  }
   331  
   332  func testAccAWSWafRuleConfigChangeName(name string) string {
   333  	return fmt.Sprintf(`
   334  resource "aws_waf_ipset" "ipset" {
   335    name = "%s"
   336    ip_set_descriptors {
   337      type = "IPV4"
   338      value = "192.0.7.0/24"
   339    }
   340  }
   341  
   342  resource "aws_waf_rule" "wafrule" {
   343    depends_on = ["aws_waf_ipset.ipset"]
   344    name = "%s"
   345    metric_name = "%s"
   346    predicates {
   347      data_id = "${aws_waf_ipset.ipset.id}"
   348      negated = false
   349      type = "IPMatch"
   350    }
   351  }`, name, name, name)
   352  }
   353  
   354  func testAccAWSWafRuleConfig_changePredicates(name string) string {
   355  	return fmt.Sprintf(`
   356  resource "aws_waf_ipset" "ipset" {
   357    name = "%s"
   358    ip_set_descriptors {
   359      type = "IPV4"
   360      value = "192.0.7.0/24"
   361    }
   362  }
   363  
   364  resource "aws_waf_byte_match_set" "set" {
   365    name = "%s"
   366    byte_match_tuples {
   367      text_transformation   = "NONE"
   368      target_string         = "badrefer1"
   369      positional_constraint = "CONTAINS"
   370  
   371      field_to_match {
   372        type = "HEADER"
   373        data = "referer"
   374      }
   375    }
   376  }
   377  
   378  resource "aws_waf_rule" "wafrule" {
   379    name = "%s"
   380    metric_name = "%s"
   381    predicates {
   382      data_id = "${aws_waf_byte_match_set.set.id}"
   383      negated = true
   384      type = "ByteMatch"
   385    }
   386  }`, name, name, name, name)
   387  }
   388  
   389  func testAccAWSWafRuleConfig_noPredicates(name string) string {
   390  	return fmt.Sprintf(`
   391  resource "aws_waf_rule" "wafrule" {
   392    name = "%s"
   393    metric_name = "%s"
   394  }`, name, name)
   395  }