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 }