github.com/danp/terraform@v0.9.5-0.20170426144147-39d740081351/builtin/providers/aws/resource_aws_security_group_rule_test.go (about) 1 package aws 2 3 import ( 4 "bytes" 5 "fmt" 6 "log" 7 "regexp" 8 "testing" 9 10 "github.com/aws/aws-sdk-go/aws" 11 "github.com/aws/aws-sdk-go/aws/awserr" 12 "github.com/aws/aws-sdk-go/service/ec2" 13 "github.com/hashicorp/terraform/helper/acctest" 14 "github.com/hashicorp/terraform/helper/resource" 15 "github.com/hashicorp/terraform/terraform" 16 ) 17 18 func TestIpPermissionIDHash(t *testing.T) { 19 simple := &ec2.IpPermission{ 20 IpProtocol: aws.String("tcp"), 21 FromPort: aws.Int64(int64(80)), 22 ToPort: aws.Int64(int64(8000)), 23 IpRanges: []*ec2.IpRange{ 24 { 25 CidrIp: aws.String("10.0.0.0/8"), 26 }, 27 }, 28 } 29 30 egress := &ec2.IpPermission{ 31 IpProtocol: aws.String("tcp"), 32 FromPort: aws.Int64(int64(80)), 33 ToPort: aws.Int64(int64(8000)), 34 IpRanges: []*ec2.IpRange{ 35 { 36 CidrIp: aws.String("10.0.0.0/8"), 37 }, 38 }, 39 } 40 41 egress_all := &ec2.IpPermission{ 42 IpProtocol: aws.String("-1"), 43 IpRanges: []*ec2.IpRange{ 44 { 45 CidrIp: aws.String("10.0.0.0/8"), 46 }, 47 }, 48 } 49 50 vpc_security_group_source := &ec2.IpPermission{ 51 IpProtocol: aws.String("tcp"), 52 FromPort: aws.Int64(int64(80)), 53 ToPort: aws.Int64(int64(8000)), 54 UserIdGroupPairs: []*ec2.UserIdGroupPair{ 55 { 56 UserId: aws.String("987654321"), 57 GroupId: aws.String("sg-12345678"), 58 }, 59 { 60 UserId: aws.String("123456789"), 61 GroupId: aws.String("sg-987654321"), 62 }, 63 { 64 UserId: aws.String("123456789"), 65 GroupId: aws.String("sg-12345678"), 66 }, 67 }, 68 } 69 70 security_group_source := &ec2.IpPermission{ 71 IpProtocol: aws.String("tcp"), 72 FromPort: aws.Int64(int64(80)), 73 ToPort: aws.Int64(int64(8000)), 74 UserIdGroupPairs: []*ec2.UserIdGroupPair{ 75 { 76 UserId: aws.String("987654321"), 77 GroupName: aws.String("my-security-group"), 78 }, 79 { 80 UserId: aws.String("123456789"), 81 GroupName: aws.String("my-security-group"), 82 }, 83 { 84 UserId: aws.String("123456789"), 85 GroupName: aws.String("my-other-security-group"), 86 }, 87 }, 88 } 89 90 // hardcoded hashes, to detect future change 91 cases := []struct { 92 Input *ec2.IpPermission 93 Type string 94 Output string 95 }{ 96 {simple, "ingress", "sgrule-3403497314"}, 97 {egress, "egress", "sgrule-1173186295"}, 98 {egress_all, "egress", "sgrule-766323498"}, 99 {vpc_security_group_source, "egress", "sgrule-351225364"}, 100 {security_group_source, "egress", "sgrule-2198807188"}, 101 } 102 103 for _, tc := range cases { 104 actual := ipPermissionIDHash("sg-12345", tc.Type, tc.Input) 105 if actual != tc.Output { 106 t.Errorf("input: %s - %s\noutput: %s", tc.Type, tc.Input, actual) 107 } 108 } 109 } 110 111 func TestAccAWSSecurityGroupRule_Ingress_VPC(t *testing.T) { 112 var group ec2.SecurityGroup 113 rInt := acctest.RandInt() 114 115 testRuleCount := func(*terraform.State) error { 116 if len(group.IpPermissions) != 1 { 117 return fmt.Errorf("Wrong Security Group rule count, expected %d, got %d", 118 1, len(group.IpPermissions)) 119 } 120 121 rule := group.IpPermissions[0] 122 if *rule.FromPort != int64(80) { 123 return fmt.Errorf("Wrong Security Group port setting, expected %d, got %d", 124 80, int(*rule.FromPort)) 125 } 126 127 return nil 128 } 129 130 resource.Test(t, resource.TestCase{ 131 PreCheck: func() { testAccPreCheck(t) }, 132 Providers: testAccProviders, 133 CheckDestroy: testAccCheckAWSSecurityGroupRuleDestroy, 134 Steps: []resource.TestStep{ 135 { 136 Config: testAccAWSSecurityGroupRuleIngressConfig(rInt), 137 Check: resource.ComposeTestCheckFunc( 138 testAccCheckAWSSecurityGroupRuleExists("aws_security_group.web", &group), 139 testAccCheckAWSSecurityGroupRuleAttributes("aws_security_group_rule.ingress_1", &group, nil, "ingress"), 140 resource.TestCheckResourceAttr( 141 "aws_security_group_rule.ingress_1", "from_port", "80"), 142 testRuleCount, 143 ), 144 }, 145 }, 146 }) 147 } 148 149 func TestAccAWSSecurityGroupRule_Ingress_Protocol(t *testing.T) { 150 var group ec2.SecurityGroup 151 152 testRuleCount := func(*terraform.State) error { 153 if len(group.IpPermissions) != 1 { 154 return fmt.Errorf("Wrong Security Group rule count, expected %d, got %d", 155 1, len(group.IpPermissions)) 156 } 157 158 rule := group.IpPermissions[0] 159 if *rule.FromPort != int64(80) { 160 return fmt.Errorf("Wrong Security Group port setting, expected %d, got %d", 161 80, int(*rule.FromPort)) 162 } 163 164 return nil 165 } 166 167 resource.Test(t, resource.TestCase{ 168 PreCheck: func() { testAccPreCheck(t) }, 169 Providers: testAccProviders, 170 CheckDestroy: testAccCheckAWSSecurityGroupRuleDestroy, 171 Steps: []resource.TestStep{ 172 { 173 Config: testAccAWSSecurityGroupRuleIngress_protocolConfig, 174 Check: resource.ComposeTestCheckFunc( 175 testAccCheckAWSSecurityGroupRuleExists("aws_security_group.web", &group), 176 testAccCheckAWSSecurityGroupRuleAttributes("aws_security_group_rule.ingress_1", &group, nil, "ingress"), 177 resource.TestCheckResourceAttr( 178 "aws_security_group_rule.ingress_1", "from_port", "80"), 179 testRuleCount, 180 ), 181 }, 182 }, 183 }) 184 } 185 186 func TestAccAWSSecurityGroupRule_Ingress_Ipv6(t *testing.T) { 187 var group ec2.SecurityGroup 188 189 testRuleCount := func(*terraform.State) error { 190 if len(group.IpPermissions) != 1 { 191 return fmt.Errorf("Wrong Security Group rule count, expected %d, got %d", 192 1, len(group.IpPermissions)) 193 } 194 195 rule := group.IpPermissions[0] 196 if *rule.FromPort != int64(80) { 197 return fmt.Errorf("Wrong Security Group port setting, expected %d, got %d", 198 80, int(*rule.FromPort)) 199 } 200 201 ipv6Address := rule.Ipv6Ranges[0] 202 if *ipv6Address.CidrIpv6 != "::/0" { 203 return fmt.Errorf("Wrong Security Group IPv6 address, expected %s, got %s", 204 "::/0", *ipv6Address.CidrIpv6) 205 } 206 207 return nil 208 } 209 210 resource.Test(t, resource.TestCase{ 211 PreCheck: func() { testAccPreCheck(t) }, 212 Providers: testAccProviders, 213 CheckDestroy: testAccCheckAWSSecurityGroupRuleDestroy, 214 Steps: []resource.TestStep{ 215 { 216 Config: testAccAWSSecurityGroupRuleIngress_ipv6Config, 217 Check: resource.ComposeTestCheckFunc( 218 testAccCheckAWSSecurityGroupRuleExists("aws_security_group.web", &group), 219 testRuleCount, 220 ), 221 }, 222 }, 223 }) 224 } 225 226 func TestAccAWSSecurityGroupRule_Ingress_Classic(t *testing.T) { 227 var group ec2.SecurityGroup 228 rInt := acctest.RandInt() 229 230 testRuleCount := func(*terraform.State) error { 231 if len(group.IpPermissions) != 1 { 232 return fmt.Errorf("Wrong Security Group rule count, expected %d, got %d", 233 1, len(group.IpPermissions)) 234 } 235 236 rule := group.IpPermissions[0] 237 if *rule.FromPort != int64(80) { 238 return fmt.Errorf("Wrong Security Group port setting, expected %d, got %d", 239 80, int(*rule.FromPort)) 240 } 241 242 return nil 243 } 244 245 resource.Test(t, resource.TestCase{ 246 PreCheck: func() { testAccPreCheck(t) }, 247 Providers: testAccProviders, 248 CheckDestroy: testAccCheckAWSSecurityGroupRuleDestroy, 249 Steps: []resource.TestStep{ 250 { 251 Config: testAccAWSSecurityGroupRuleIngressClassicConfig(rInt), 252 Check: resource.ComposeTestCheckFunc( 253 testAccCheckAWSSecurityGroupRuleExists("aws_security_group.web", &group), 254 testAccCheckAWSSecurityGroupRuleAttributes("aws_security_group_rule.ingress_1", &group, nil, "ingress"), 255 resource.TestCheckResourceAttr( 256 "aws_security_group_rule.ingress_1", "from_port", "80"), 257 testRuleCount, 258 ), 259 }, 260 }, 261 }) 262 } 263 264 func TestAccAWSSecurityGroupRule_MultiIngress(t *testing.T) { 265 var group ec2.SecurityGroup 266 267 testMultiRuleCount := func(*terraform.State) error { 268 if len(group.IpPermissions) != 2 { 269 return fmt.Errorf("Wrong Security Group rule count, expected %d, got %d", 270 2, len(group.IpPermissions)) 271 } 272 273 var rule *ec2.IpPermission 274 for _, r := range group.IpPermissions { 275 if *r.FromPort == int64(80) { 276 rule = r 277 } 278 } 279 280 if *rule.ToPort != int64(8000) { 281 return fmt.Errorf("Wrong Security Group port 2 setting, expected %d, got %d", 282 8000, int(*rule.ToPort)) 283 } 284 285 return nil 286 } 287 288 resource.Test(t, resource.TestCase{ 289 PreCheck: func() { testAccPreCheck(t) }, 290 Providers: testAccProviders, 291 CheckDestroy: testAccCheckAWSSecurityGroupRuleDestroy, 292 Steps: []resource.TestStep{ 293 { 294 Config: testAccAWSSecurityGroupRuleConfigMultiIngress, 295 Check: resource.ComposeTestCheckFunc( 296 testAccCheckAWSSecurityGroupRuleExists("aws_security_group.web", &group), 297 testMultiRuleCount, 298 ), 299 }, 300 }, 301 }) 302 } 303 304 func TestAccAWSSecurityGroupRule_Egress(t *testing.T) { 305 var group ec2.SecurityGroup 306 rInt := acctest.RandInt() 307 308 resource.Test(t, resource.TestCase{ 309 PreCheck: func() { testAccPreCheck(t) }, 310 Providers: testAccProviders, 311 CheckDestroy: testAccCheckAWSSecurityGroupRuleDestroy, 312 Steps: []resource.TestStep{ 313 { 314 Config: testAccAWSSecurityGroupRuleEgressConfig(rInt), 315 Check: resource.ComposeTestCheckFunc( 316 testAccCheckAWSSecurityGroupRuleExists("aws_security_group.web", &group), 317 testAccCheckAWSSecurityGroupRuleAttributes("aws_security_group_rule.egress_1", &group, nil, "egress"), 318 ), 319 }, 320 }, 321 }) 322 } 323 324 func TestAccAWSSecurityGroupRule_SelfReference(t *testing.T) { 325 var group ec2.SecurityGroup 326 327 resource.Test(t, resource.TestCase{ 328 PreCheck: func() { testAccPreCheck(t) }, 329 Providers: testAccProviders, 330 CheckDestroy: testAccCheckAWSSecurityGroupRuleDestroy, 331 Steps: []resource.TestStep{ 332 { 333 Config: testAccAWSSecurityGroupRuleConfigSelfReference, 334 Check: resource.ComposeTestCheckFunc( 335 testAccCheckAWSSecurityGroupRuleExists("aws_security_group.web", &group), 336 ), 337 }, 338 }, 339 }) 340 } 341 342 func TestAccAWSSecurityGroupRule_ExpectInvalidTypeError(t *testing.T) { 343 rInt := acctest.RandInt() 344 resource.Test(t, resource.TestCase{ 345 PreCheck: func() { testAccPreCheck(t) }, 346 Providers: testAccProviders, 347 CheckDestroy: testAccCheckAWSSecurityGroupRuleDestroy, 348 Steps: []resource.TestStep{ 349 { 350 Config: testAccAWSSecurityGroupRuleExpectInvalidType(rInt), 351 ExpectError: regexp.MustCompile(`\\"type\\" contains an invalid Security Group Rule type \\"foobar\\"`), 352 }, 353 }, 354 }) 355 } 356 357 func TestAccAWSSecurityGroupRule_ExpectInvalidCIDR(t *testing.T) { 358 rInt := acctest.RandInt() 359 resource.Test(t, resource.TestCase{ 360 PreCheck: func() { testAccPreCheck(t) }, 361 Providers: testAccProviders, 362 CheckDestroy: testAccCheckAWSSecurityGroupRuleDestroy, 363 Steps: []resource.TestStep{ 364 { 365 Config: testAccAWSSecurityGroupRuleInvalidIPv4CIDR(rInt), 366 ExpectError: regexp.MustCompile("invalid CIDR address: 1.2.3.4/33"), 367 }, 368 { 369 Config: testAccAWSSecurityGroupRuleInvalidIPv6CIDR(rInt), 370 ExpectError: regexp.MustCompile("invalid CIDR address: ::/244"), 371 }, 372 }, 373 }) 374 } 375 376 // testing partial match implementation 377 func TestAccAWSSecurityGroupRule_PartialMatching_basic(t *testing.T) { 378 var group ec2.SecurityGroup 379 rInt := acctest.RandInt() 380 381 p := ec2.IpPermission{ 382 FromPort: aws.Int64(80), 383 ToPort: aws.Int64(80), 384 IpProtocol: aws.String("tcp"), 385 IpRanges: []*ec2.IpRange{ 386 {CidrIp: aws.String("10.0.2.0/24")}, 387 {CidrIp: aws.String("10.0.3.0/24")}, 388 {CidrIp: aws.String("10.0.4.0/24")}, 389 }, 390 } 391 392 o := ec2.IpPermission{ 393 FromPort: aws.Int64(80), 394 ToPort: aws.Int64(80), 395 IpProtocol: aws.String("tcp"), 396 IpRanges: []*ec2.IpRange{ 397 {CidrIp: aws.String("10.0.5.0/24")}, 398 }, 399 } 400 401 resource.Test(t, resource.TestCase{ 402 PreCheck: func() { testAccPreCheck(t) }, 403 Providers: testAccProviders, 404 CheckDestroy: testAccCheckAWSSecurityGroupRuleDestroy, 405 Steps: []resource.TestStep{ 406 { 407 Config: testAccAWSSecurityGroupRulePartialMatching(rInt), 408 Check: resource.ComposeTestCheckFunc( 409 testAccCheckAWSSecurityGroupRuleExists("aws_security_group.web", &group), 410 testAccCheckAWSSecurityGroupRuleAttributes("aws_security_group_rule.ingress", &group, &p, "ingress"), 411 testAccCheckAWSSecurityGroupRuleAttributes("aws_security_group_rule.other", &group, &o, "ingress"), 412 testAccCheckAWSSecurityGroupRuleAttributes("aws_security_group_rule.nat_ingress", &group, &o, "ingress"), 413 ), 414 }, 415 }, 416 }) 417 } 418 419 func TestAccAWSSecurityGroupRule_PartialMatching_Source(t *testing.T) { 420 var group ec2.SecurityGroup 421 var nat ec2.SecurityGroup 422 var p ec2.IpPermission 423 rInt := acctest.RandInt() 424 425 // This function creates the expected IPPermission with the group id from an 426 // external security group, needed because Security Group IDs are generated on 427 // AWS side and can't be known ahead of time. 428 setupSG := func(*terraform.State) error { 429 if nat.GroupId == nil { 430 return fmt.Errorf("Error: nat group has nil GroupID") 431 } 432 433 p = ec2.IpPermission{ 434 FromPort: aws.Int64(80), 435 ToPort: aws.Int64(80), 436 IpProtocol: aws.String("tcp"), 437 UserIdGroupPairs: []*ec2.UserIdGroupPair{ 438 {GroupId: nat.GroupId}, 439 }, 440 } 441 442 return nil 443 } 444 445 resource.Test(t, resource.TestCase{ 446 PreCheck: func() { testAccPreCheck(t) }, 447 Providers: testAccProviders, 448 CheckDestroy: testAccCheckAWSSecurityGroupRuleDestroy, 449 Steps: []resource.TestStep{ 450 { 451 Config: testAccAWSSecurityGroupRulePartialMatching_Source(rInt), 452 Check: resource.ComposeTestCheckFunc( 453 testAccCheckAWSSecurityGroupRuleExists("aws_security_group.web", &group), 454 testAccCheckAWSSecurityGroupRuleExists("aws_security_group.nat", &nat), 455 setupSG, 456 testAccCheckAWSSecurityGroupRuleAttributes("aws_security_group_rule.source_ingress", &group, &p, "ingress"), 457 ), 458 }, 459 }, 460 }) 461 } 462 463 func TestAccAWSSecurityGroupRule_Issue5310(t *testing.T) { 464 var group ec2.SecurityGroup 465 466 resource.Test(t, resource.TestCase{ 467 PreCheck: func() { testAccPreCheck(t) }, 468 Providers: testAccProviders, 469 CheckDestroy: testAccCheckAWSSecurityGroupRuleDestroy, 470 Steps: []resource.TestStep{ 471 { 472 Config: testAccAWSSecurityGroupRuleIssue5310, 473 Check: resource.ComposeTestCheckFunc( 474 testAccCheckAWSSecurityGroupRuleExists("aws_security_group.issue_5310", &group), 475 ), 476 }, 477 }, 478 }) 479 } 480 481 func TestAccAWSSecurityGroupRule_Race(t *testing.T) { 482 var group ec2.SecurityGroup 483 484 resource.Test(t, resource.TestCase{ 485 PreCheck: func() { testAccPreCheck(t) }, 486 Providers: testAccProviders, 487 CheckDestroy: testAccCheckAWSSecurityGroupRuleDestroy, 488 Steps: []resource.TestStep{ 489 { 490 Config: testAccAWSSecurityGroupRuleRace, 491 Check: resource.ComposeTestCheckFunc( 492 testAccCheckAWSSecurityGroupRuleExists("aws_security_group.race", &group), 493 ), 494 }, 495 }, 496 }) 497 } 498 499 func TestAccAWSSecurityGroupRule_SelfSource(t *testing.T) { 500 var group ec2.SecurityGroup 501 rInt := acctest.RandInt() 502 503 resource.Test(t, resource.TestCase{ 504 PreCheck: func() { testAccPreCheck(t) }, 505 Providers: testAccProviders, 506 CheckDestroy: testAccCheckAWSSecurityGroupRuleDestroy, 507 Steps: []resource.TestStep{ 508 { 509 Config: testAccAWSSecurityGroupRuleSelfInSource(rInt), 510 Check: resource.ComposeTestCheckFunc( 511 testAccCheckAWSSecurityGroupRuleExists("aws_security_group.web", &group), 512 ), 513 }, 514 }, 515 }) 516 } 517 518 func TestAccAWSSecurityGroupRule_PrefixListEgress(t *testing.T) { 519 var group ec2.SecurityGroup 520 var endpoint ec2.VpcEndpoint 521 var p ec2.IpPermission 522 523 // This function creates the expected IPPermission with the prefix list ID from 524 // the VPC Endpoint created in the test 525 setupSG := func(*terraform.State) error { 526 conn := testAccProvider.Meta().(*AWSClient).ec2conn 527 prefixListInput := &ec2.DescribePrefixListsInput{ 528 Filters: []*ec2.Filter{ 529 {Name: aws.String("prefix-list-name"), Values: []*string{endpoint.ServiceName}}, 530 }, 531 } 532 533 log.Printf("[DEBUG] Reading VPC Endpoint prefix list: %s", prefixListInput) 534 prefixListsOutput, err := conn.DescribePrefixLists(prefixListInput) 535 536 if err != nil { 537 _, ok := err.(awserr.Error) 538 if !ok { 539 return fmt.Errorf("Error reading VPC Endpoint prefix list: %s", err.Error()) 540 } 541 } 542 543 if len(prefixListsOutput.PrefixLists) != 1 { 544 return fmt.Errorf("There are multiple prefix lists associated with the service name '%s'. Unexpected", prefixListsOutput) 545 } 546 547 p = ec2.IpPermission{ 548 IpProtocol: aws.String("-1"), 549 PrefixListIds: []*ec2.PrefixListId{ 550 {PrefixListId: prefixListsOutput.PrefixLists[0].PrefixListId}, 551 }, 552 } 553 554 return nil 555 } 556 557 resource.Test(t, resource.TestCase{ 558 PreCheck: func() { testAccPreCheck(t) }, 559 Providers: testAccProviders, 560 CheckDestroy: testAccCheckAWSSecurityGroupRuleDestroy, 561 Steps: []resource.TestStep{ 562 { 563 Config: testAccAWSSecurityGroupRulePrefixListEgressConfig, 564 Check: resource.ComposeTestCheckFunc( 565 testAccCheckAWSSecurityGroupRuleExists("aws_security_group.egress", &group), 566 // lookup info on the VPC Endpoint created, to populate the expected 567 // IP Perm 568 testAccCheckVpcEndpointExists("aws_vpc_endpoint.s3-us-west-2", &endpoint), 569 setupSG, 570 testAccCheckAWSSecurityGroupRuleAttributes("aws_security_group_rule.egress_1", &group, &p, "egress"), 571 ), 572 }, 573 }, 574 }) 575 } 576 577 func testAccCheckAWSSecurityGroupRuleDestroy(s *terraform.State) error { 578 conn := testAccProvider.Meta().(*AWSClient).ec2conn 579 580 for _, rs := range s.RootModule().Resources { 581 if rs.Type != "aws_security_group" { 582 continue 583 } 584 585 // Retrieve our group 586 req := &ec2.DescribeSecurityGroupsInput{ 587 GroupIds: []*string{aws.String(rs.Primary.ID)}, 588 } 589 resp, err := conn.DescribeSecurityGroups(req) 590 if err == nil { 591 if len(resp.SecurityGroups) > 0 && *resp.SecurityGroups[0].GroupId == rs.Primary.ID { 592 return fmt.Errorf("Security Group (%s) still exists.", rs.Primary.ID) 593 } 594 595 return nil 596 } 597 598 ec2err, ok := err.(awserr.Error) 599 if !ok { 600 return err 601 } 602 // Confirm error code is what we want 603 if ec2err.Code() != "InvalidGroup.NotFound" { 604 return err 605 } 606 } 607 608 return nil 609 } 610 611 func testAccCheckAWSSecurityGroupRuleExists(n string, group *ec2.SecurityGroup) resource.TestCheckFunc { 612 return func(s *terraform.State) error { 613 rs, ok := s.RootModule().Resources[n] 614 if !ok { 615 return fmt.Errorf("Not found: %s", n) 616 } 617 618 if rs.Primary.ID == "" { 619 return fmt.Errorf("No Security Group is set") 620 } 621 622 conn := testAccProvider.Meta().(*AWSClient).ec2conn 623 req := &ec2.DescribeSecurityGroupsInput{ 624 GroupIds: []*string{aws.String(rs.Primary.ID)}, 625 } 626 resp, err := conn.DescribeSecurityGroups(req) 627 if err != nil { 628 return err 629 } 630 631 if len(resp.SecurityGroups) > 0 && *resp.SecurityGroups[0].GroupId == rs.Primary.ID { 632 *group = *resp.SecurityGroups[0] 633 return nil 634 } 635 636 return fmt.Errorf("Security Group not found") 637 } 638 } 639 640 func testAccCheckAWSSecurityGroupRuleAttributes(n string, group *ec2.SecurityGroup, p *ec2.IpPermission, ruleType string) resource.TestCheckFunc { 641 return func(s *terraform.State) error { 642 rs, ok := s.RootModule().Resources[n] 643 if !ok { 644 return fmt.Errorf("Security Group Rule Not found: %s", n) 645 } 646 647 if rs.Primary.ID == "" { 648 return fmt.Errorf("No Security Group Rule is set") 649 } 650 651 if p == nil { 652 p = &ec2.IpPermission{ 653 FromPort: aws.Int64(80), 654 ToPort: aws.Int64(8000), 655 IpProtocol: aws.String("tcp"), 656 IpRanges: []*ec2.IpRange{{CidrIp: aws.String("10.0.0.0/8")}}, 657 } 658 } 659 660 var matchingRule *ec2.IpPermission 661 var rules []*ec2.IpPermission 662 if ruleType == "ingress" { 663 rules = group.IpPermissions 664 } else { 665 rules = group.IpPermissionsEgress 666 } 667 668 if len(rules) == 0 { 669 return fmt.Errorf("No IPPerms") 670 } 671 672 for _, r := range rules { 673 if r.ToPort != nil && *p.ToPort != *r.ToPort { 674 continue 675 } 676 677 if r.FromPort != nil && *p.FromPort != *r.FromPort { 678 continue 679 } 680 681 if r.IpProtocol != nil && *p.IpProtocol != *r.IpProtocol { 682 continue 683 } 684 685 remaining := len(p.IpRanges) 686 for _, ip := range p.IpRanges { 687 for _, rip := range r.IpRanges { 688 if *ip.CidrIp == *rip.CidrIp { 689 remaining-- 690 } 691 } 692 } 693 694 if remaining > 0 { 695 continue 696 } 697 698 remaining = len(p.UserIdGroupPairs) 699 for _, ip := range p.UserIdGroupPairs { 700 for _, rip := range r.UserIdGroupPairs { 701 if *ip.GroupId == *rip.GroupId { 702 remaining-- 703 } 704 } 705 } 706 707 if remaining > 0 { 708 continue 709 } 710 711 remaining = len(p.PrefixListIds) 712 for _, pip := range p.PrefixListIds { 713 for _, rpip := range r.PrefixListIds { 714 if *pip.PrefixListId == *rpip.PrefixListId { 715 remaining-- 716 } 717 } 718 } 719 720 if remaining > 0 { 721 continue 722 } 723 724 matchingRule = r 725 } 726 727 if matchingRule != nil { 728 log.Printf("[DEBUG] Matching rule found : %s", matchingRule) 729 return nil 730 } 731 732 return fmt.Errorf("Error here\n\tlooking for %s, wasn't found in %s", p, rules) 733 } 734 } 735 736 func testAccAWSSecurityGroupRuleIngressConfig(rInt int) string { 737 return fmt.Sprintf(` 738 resource "aws_security_group" "web" { 739 name = "terraform_test_%d" 740 description = "Used in the terraform acceptance tests" 741 742 tags { 743 Name = "tf-acc-test" 744 } 745 } 746 747 resource "aws_security_group_rule" "ingress_1" { 748 type = "ingress" 749 protocol = "tcp" 750 from_port = 80 751 to_port = 8000 752 cidr_blocks = ["10.0.0.0/8"] 753 754 security_group_id = "${aws_security_group.web.id}" 755 }`, rInt) 756 } 757 758 const testAccAWSSecurityGroupRuleIngress_ipv6Config = ` 759 resource "aws_vpc" "tftest" { 760 cidr_block = "10.0.0.0/16" 761 762 tags { 763 Name = "tf-testing" 764 } 765 } 766 767 resource "aws_security_group" "web" { 768 vpc_id = "${aws_vpc.tftest.id}" 769 770 tags { 771 Name = "tf-acc-test" 772 } 773 } 774 775 resource "aws_security_group_rule" "ingress_1" { 776 type = "ingress" 777 protocol = "6" 778 from_port = 80 779 to_port = 8000 780 ipv6_cidr_blocks = ["::/0"] 781 782 security_group_id = "${aws_security_group.web.id}" 783 } 784 ` 785 786 const testAccAWSSecurityGroupRuleIngress_protocolConfig = ` 787 resource "aws_vpc" "tftest" { 788 cidr_block = "10.0.0.0/16" 789 790 tags { 791 Name = "tf-testing" 792 } 793 } 794 795 resource "aws_security_group" "web" { 796 vpc_id = "${aws_vpc.tftest.id}" 797 798 tags { 799 Name = "tf-acc-test" 800 } 801 } 802 803 resource "aws_security_group_rule" "ingress_1" { 804 type = "ingress" 805 protocol = "6" 806 from_port = 80 807 to_port = 8000 808 cidr_blocks = ["10.0.0.0/8"] 809 810 security_group_id = "${aws_security_group.web.id}" 811 } 812 813 ` 814 815 const testAccAWSSecurityGroupRuleIssue5310 = ` 816 provider "aws" { 817 region = "us-east-1" 818 } 819 820 resource "aws_security_group" "issue_5310" { 821 name = "terraform-test-issue_5310" 822 description = "SG for test of issue 5310" 823 } 824 825 resource "aws_security_group_rule" "issue_5310" { 826 type = "ingress" 827 from_port = 0 828 to_port = 65535 829 protocol = "tcp" 830 security_group_id = "${aws_security_group.issue_5310.id}" 831 self = true 832 } 833 ` 834 835 func testAccAWSSecurityGroupRuleIngressClassicConfig(rInt int) string { 836 return fmt.Sprintf(` 837 provider "aws" { 838 region = "us-east-1" 839 } 840 841 resource "aws_security_group" "web" { 842 name = "terraform_test_%d" 843 description = "Used in the terraform acceptance tests" 844 845 tags { 846 Name = "tf-acc-test" 847 } 848 } 849 850 resource "aws_security_group_rule" "ingress_1" { 851 type = "ingress" 852 protocol = "tcp" 853 from_port = 80 854 to_port = 8000 855 cidr_blocks = ["10.0.0.0/8"] 856 857 security_group_id = "${aws_security_group.web.id}" 858 }`, rInt) 859 } 860 861 func testAccAWSSecurityGroupRuleEgressConfig(rInt int) string { 862 return fmt.Sprintf(` 863 resource "aws_security_group" "web" { 864 name = "terraform_test_%d" 865 description = "Used in the terraform acceptance tests" 866 867 tags { 868 Name = "tf-acc-test" 869 } 870 } 871 872 resource "aws_security_group_rule" "egress_1" { 873 type = "egress" 874 protocol = "tcp" 875 from_port = 80 876 to_port = 8000 877 cidr_blocks = ["10.0.0.0/8"] 878 879 security_group_id = "${aws_security_group.web.id}" 880 }`, rInt) 881 } 882 883 const testAccAWSSecurityGroupRuleConfigMultiIngress = ` 884 resource "aws_security_group" "web" { 885 name = "terraform_acceptance_test_example_2" 886 description = "Used in the terraform acceptance tests" 887 } 888 889 resource "aws_security_group" "worker" { 890 name = "terraform_acceptance_test_example_worker" 891 description = "Used in the terraform acceptance tests" 892 } 893 894 895 resource "aws_security_group_rule" "ingress_1" { 896 type = "ingress" 897 protocol = "tcp" 898 from_port = 22 899 to_port = 22 900 cidr_blocks = ["10.0.0.0/8"] 901 902 security_group_id = "${aws_security_group.web.id}" 903 } 904 905 resource "aws_security_group_rule" "ingress_2" { 906 type = "ingress" 907 protocol = "tcp" 908 from_port = 80 909 to_port = 8000 910 self = true 911 912 security_group_id = "${aws_security_group.web.id}" 913 } 914 ` 915 916 // check for GH-1985 regression 917 const testAccAWSSecurityGroupRuleConfigSelfReference = ` 918 provider "aws" { 919 region = "us-west-2" 920 } 921 922 resource "aws_vpc" "main" { 923 cidr_block = "10.0.0.0/16" 924 tags { 925 Name = "sg-self-test" 926 } 927 } 928 929 resource "aws_security_group" "web" { 930 name = "main" 931 vpc_id = "${aws_vpc.main.id}" 932 tags { 933 Name = "sg-self-test" 934 } 935 } 936 937 resource "aws_security_group_rule" "self" { 938 type = "ingress" 939 protocol = "-1" 940 from_port = 0 941 to_port = 0 942 self = true 943 security_group_id = "${aws_security_group.web.id}" 944 } 945 ` 946 947 func testAccAWSSecurityGroupRulePartialMatching(rInt int) string { 948 return fmt.Sprintf(` 949 resource "aws_vpc" "default" { 950 cidr_block = "10.0.0.0/16" 951 tags { 952 Name = "tf-sg-rule-bug" 953 } 954 } 955 956 resource "aws_security_group" "web" { 957 name = "tf-other-%d" 958 vpc_id = "${aws_vpc.default.id}" 959 tags { 960 Name = "tf-other-sg" 961 } 962 } 963 964 resource "aws_security_group" "nat" { 965 name = "tf-nat-%d" 966 vpc_id = "${aws_vpc.default.id}" 967 tags { 968 Name = "tf-nat-sg" 969 } 970 } 971 972 resource "aws_security_group_rule" "ingress" { 973 type = "ingress" 974 from_port = 80 975 to_port = 80 976 protocol = "tcp" 977 cidr_blocks = ["10.0.2.0/24", "10.0.3.0/24", "10.0.4.0/24"] 978 979 security_group_id = "${aws_security_group.web.id}" 980 } 981 982 resource "aws_security_group_rule" "other" { 983 type = "ingress" 984 from_port = 80 985 to_port = 80 986 protocol = "tcp" 987 cidr_blocks = ["10.0.5.0/24"] 988 989 security_group_id = "${aws_security_group.web.id}" 990 } 991 992 // same a above, but different group, to guard against bad hashing 993 resource "aws_security_group_rule" "nat_ingress" { 994 type = "ingress" 995 from_port = 80 996 to_port = 80 997 protocol = "tcp" 998 cidr_blocks = ["10.0.2.0/24", "10.0.3.0/24", "10.0.4.0/24"] 999 1000 security_group_id = "${aws_security_group.nat.id}" 1001 }`, rInt, rInt) 1002 } 1003 1004 func testAccAWSSecurityGroupRulePartialMatching_Source(rInt int) string { 1005 return fmt.Sprintf(` 1006 resource "aws_vpc" "default" { 1007 cidr_block = "10.0.0.0/16" 1008 tags { 1009 Name = "tf-sg-rule-bug" 1010 } 1011 } 1012 1013 resource "aws_security_group" "web" { 1014 name = "tf-other-%d" 1015 vpc_id = "${aws_vpc.default.id}" 1016 tags { 1017 Name = "tf-other-sg" 1018 } 1019 } 1020 1021 resource "aws_security_group" "nat" { 1022 name = "tf-nat-%d" 1023 vpc_id = "${aws_vpc.default.id}" 1024 tags { 1025 Name = "tf-nat-sg" 1026 } 1027 } 1028 1029 resource "aws_security_group_rule" "source_ingress" { 1030 type = "ingress" 1031 from_port = 80 1032 to_port = 80 1033 protocol = "tcp" 1034 1035 source_security_group_id = "${aws_security_group.nat.id}" 1036 security_group_id = "${aws_security_group.web.id}" 1037 } 1038 1039 resource "aws_security_group_rule" "other_ingress" { 1040 type = "ingress" 1041 from_port = 80 1042 to_port = 80 1043 protocol = "tcp" 1044 cidr_blocks = ["10.0.2.0/24", "10.0.3.0/24", "10.0.4.0/24"] 1045 1046 security_group_id = "${aws_security_group.web.id}" 1047 }`, rInt, rInt) 1048 } 1049 1050 var testAccAWSSecurityGroupRuleRace = func() string { 1051 var b bytes.Buffer 1052 iterations := 50 1053 b.WriteString(fmt.Sprintf(` 1054 resource "aws_vpc" "default" { 1055 cidr_block = "10.0.0.0/16" 1056 tags { Name = "tf-sg-rule-race" } 1057 } 1058 1059 resource "aws_security_group" "race" { 1060 name = "tf-sg-rule-race-group-%d" 1061 vpc_id = "${aws_vpc.default.id}" 1062 } 1063 `, acctest.RandInt())) 1064 for i := 1; i < iterations; i++ { 1065 b.WriteString(fmt.Sprintf(` 1066 resource "aws_security_group_rule" "ingress%d" { 1067 security_group_id = "${aws_security_group.race.id}" 1068 type = "ingress" 1069 from_port = %d 1070 to_port = %d 1071 protocol = "tcp" 1072 cidr_blocks = ["10.0.0.%d/32"] 1073 } 1074 1075 resource "aws_security_group_rule" "egress%d" { 1076 security_group_id = "${aws_security_group.race.id}" 1077 type = "egress" 1078 from_port = %d 1079 to_port = %d 1080 protocol = "tcp" 1081 cidr_blocks = ["10.0.0.%d/32"] 1082 } 1083 `, i, i, i, i, i, i, i, i)) 1084 } 1085 return b.String() 1086 }() 1087 1088 const testAccAWSSecurityGroupRulePrefixListEgressConfig = ` 1089 1090 resource "aws_vpc" "tf_sg_prefix_list_egress_test" { 1091 cidr_block = "10.0.0.0/16" 1092 tags { 1093 Name = "tf_sg_prefix_list_egress_test" 1094 } 1095 } 1096 1097 resource "aws_route_table" "default" { 1098 vpc_id = "${aws_vpc.tf_sg_prefix_list_egress_test.id}" 1099 } 1100 1101 resource "aws_vpc_endpoint" "s3-us-west-2" { 1102 vpc_id = "${aws_vpc.tf_sg_prefix_list_egress_test.id}" 1103 service_name = "com.amazonaws.us-west-2.s3" 1104 route_table_ids = ["${aws_route_table.default.id}"] 1105 policy = <<POLICY 1106 { 1107 "Version": "2012-10-17", 1108 "Statement": [ 1109 { 1110 "Sid":"AllowAll", 1111 "Effect":"Allow", 1112 "Principal":"*", 1113 "Action":"*", 1114 "Resource":"*" 1115 } 1116 ] 1117 } 1118 POLICY 1119 } 1120 1121 resource "aws_security_group" "egress" { 1122 name = "terraform_acceptance_test_prefix_list_egress" 1123 description = "Used in the terraform acceptance tests" 1124 vpc_id = "${aws_vpc.tf_sg_prefix_list_egress_test.id}" 1125 } 1126 1127 resource "aws_security_group_rule" "egress_1" { 1128 type = "egress" 1129 protocol = "-1" 1130 from_port = 0 1131 to_port = 0 1132 prefix_list_ids = ["${aws_vpc_endpoint.s3-us-west-2.prefix_list_id}"] 1133 security_group_id = "${aws_security_group.egress.id}" 1134 } 1135 ` 1136 1137 func testAccAWSSecurityGroupRuleSelfInSource(rInt int) string { 1138 return fmt.Sprintf(` 1139 resource "aws_vpc" "foo" { 1140 cidr_block = "10.1.0.0/16" 1141 1142 tags { 1143 Name = "tf_sg_rule_self_group" 1144 } 1145 } 1146 1147 resource "aws_security_group" "web" { 1148 name = "allow_all-%d" 1149 description = "Allow all inbound traffic" 1150 vpc_id = "${aws_vpc.foo.id}" 1151 } 1152 1153 resource "aws_security_group_rule" "allow_self" { 1154 type = "ingress" 1155 from_port = 0 1156 to_port = 0 1157 protocol = "-1" 1158 security_group_id = "${aws_security_group.web.id}" 1159 source_security_group_id = "${aws_security_group.web.id}" 1160 }`, rInt) 1161 } 1162 1163 func testAccAWSSecurityGroupRuleExpectInvalidType(rInt int) string { 1164 return fmt.Sprintf(` 1165 resource "aws_vpc" "foo" { 1166 cidr_block = "10.1.0.0/16" 1167 1168 tags { 1169 Name = "tf_sg_rule_self_group" 1170 } 1171 } 1172 1173 resource "aws_security_group" "web" { 1174 name = "allow_all-%d" 1175 description = "Allow all inbound traffic" 1176 vpc_id = "${aws_vpc.foo.id}" 1177 } 1178 1179 resource "aws_security_group_rule" "allow_self" { 1180 type = "foobar" 1181 from_port = 0 1182 to_port = 0 1183 protocol = "-1" 1184 security_group_id = "${aws_security_group.web.id}" 1185 source_security_group_id = "${aws_security_group.web.id}" 1186 }`, rInt) 1187 } 1188 1189 func testAccAWSSecurityGroupRuleInvalidIPv4CIDR(rInt int) string { 1190 return fmt.Sprintf(` 1191 resource "aws_security_group" "foo" { 1192 name = "testing-failure-%d" 1193 } 1194 1195 resource "aws_security_group_rule" "ing" { 1196 type = "ingress" 1197 from_port = 0 1198 to_port = 0 1199 protocol = "-1" 1200 cidr_blocks = ["1.2.3.4/33"] 1201 security_group_id = "${aws_security_group.foo.id}" 1202 }`, rInt) 1203 } 1204 1205 func testAccAWSSecurityGroupRuleInvalidIPv6CIDR(rInt int) string { 1206 return fmt.Sprintf(` 1207 resource "aws_security_group" "foo" { 1208 name = "testing-failure-%d" 1209 } 1210 1211 resource "aws_security_group_rule" "ing" { 1212 type = "egress" 1213 from_port = 0 1214 to_port = 0 1215 protocol = "-1" 1216 ipv6_cidr_blocks = ["::/244"] 1217 security_group_id = "${aws_security_group.foo.id}" 1218 }`, rInt) 1219 }