Merge pull request #11861 from hashicorp/b-fix-security-group-rule-regression

provider/aws: Fix SecurityGroupRule regression
This commit is contained in:
Jake Champlin 2017-02-10 13:53:47 -05:00 committed by GitHub
commit aa1c4cafa4
2 changed files with 223 additions and 208 deletions

View File

@ -608,9 +608,10 @@ func validateAwsSecurityGroupRule(d *schema.ResourceData) error {
_, blocksOk := d.GetOk("cidr_blocks") _, blocksOk := d.GetOk("cidr_blocks")
_, sourceOk := d.GetOk("source_security_group_id") _, sourceOk := d.GetOk("source_security_group_id")
_, selfOk := d.GetOk("self") _, selfOk := d.GetOk("self")
if !blocksOk && !sourceOk && !selfOk { _, prefixOk := d.GetOk("prefix_list_ids")
if !blocksOk && !sourceOk && !selfOk && !prefixOk {
return fmt.Errorf( return fmt.Errorf(
"One of ['cidr_blocks', 'self', 'source_security_group_id'] must be set to create an AWS Security Group Rule") "One of ['cidr_blocks', 'self', 'source_security_group_id', 'prefix_list_ids'] must be set to create an AWS Security Group Rule")
} }
return nil return nil
} }

View File

@ -4,6 +4,7 @@ import (
"bytes" "bytes"
"fmt" "fmt"
"log" "log"
"regexp"
"testing" "testing"
"github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws"
@ -12,7 +13,6 @@ import (
"github.com/hashicorp/terraform/helper/acctest" "github.com/hashicorp/terraform/helper/acctest"
"github.com/hashicorp/terraform/helper/resource" "github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform" "github.com/hashicorp/terraform/terraform"
"regexp"
) )
func TestIpPermissionIDHash(t *testing.T) { func TestIpPermissionIDHash(t *testing.T) {
@ -110,6 +110,7 @@ func TestIpPermissionIDHash(t *testing.T) {
func TestAccAWSSecurityGroupRule_Ingress_VPC(t *testing.T) { func TestAccAWSSecurityGroupRule_Ingress_VPC(t *testing.T) {
var group ec2.SecurityGroup var group ec2.SecurityGroup
rInt := acctest.RandInt()
testRuleCount := func(*terraform.State) error { testRuleCount := func(*terraform.State) error {
if len(group.IpPermissions) != 1 { if len(group.IpPermissions) != 1 {
@ -132,7 +133,7 @@ func TestAccAWSSecurityGroupRule_Ingress_VPC(t *testing.T) {
CheckDestroy: testAccCheckAWSSecurityGroupRuleDestroy, CheckDestroy: testAccCheckAWSSecurityGroupRuleDestroy,
Steps: []resource.TestStep{ Steps: []resource.TestStep{
{ {
Config: testAccAWSSecurityGroupRuleIngressConfig, Config: testAccAWSSecurityGroupRuleIngressConfig(rInt),
Check: resource.ComposeTestCheckFunc( Check: resource.ComposeTestCheckFunc(
testAccCheckAWSSecurityGroupRuleExists("aws_security_group.web", &group), testAccCheckAWSSecurityGroupRuleExists("aws_security_group.web", &group),
testAccCheckAWSSecurityGroupRuleAttributes("aws_security_group_rule.ingress_1", &group, nil, "ingress"), testAccCheckAWSSecurityGroupRuleAttributes("aws_security_group_rule.ingress_1", &group, nil, "ingress"),
@ -184,6 +185,7 @@ func TestAccAWSSecurityGroupRule_Ingress_Protocol(t *testing.T) {
func TestAccAWSSecurityGroupRule_Ingress_Classic(t *testing.T) { func TestAccAWSSecurityGroupRule_Ingress_Classic(t *testing.T) {
var group ec2.SecurityGroup var group ec2.SecurityGroup
rInt := acctest.RandInt()
testRuleCount := func(*terraform.State) error { testRuleCount := func(*terraform.State) error {
if len(group.IpPermissions) != 1 { if len(group.IpPermissions) != 1 {
@ -206,7 +208,7 @@ func TestAccAWSSecurityGroupRule_Ingress_Classic(t *testing.T) {
CheckDestroy: testAccCheckAWSSecurityGroupRuleDestroy, CheckDestroy: testAccCheckAWSSecurityGroupRuleDestroy,
Steps: []resource.TestStep{ Steps: []resource.TestStep{
{ {
Config: testAccAWSSecurityGroupRuleIngressClassicConfig, Config: testAccAWSSecurityGroupRuleIngressClassicConfig(rInt),
Check: resource.ComposeTestCheckFunc( Check: resource.ComposeTestCheckFunc(
testAccCheckAWSSecurityGroupRuleExists("aws_security_group.web", &group), testAccCheckAWSSecurityGroupRuleExists("aws_security_group.web", &group),
testAccCheckAWSSecurityGroupRuleAttributes("aws_security_group_rule.ingress_1", &group, nil, "ingress"), testAccCheckAWSSecurityGroupRuleAttributes("aws_security_group_rule.ingress_1", &group, nil, "ingress"),
@ -261,6 +263,7 @@ func TestAccAWSSecurityGroupRule_MultiIngress(t *testing.T) {
func TestAccAWSSecurityGroupRule_Egress(t *testing.T) { func TestAccAWSSecurityGroupRule_Egress(t *testing.T) {
var group ec2.SecurityGroup var group ec2.SecurityGroup
rInt := acctest.RandInt()
resource.Test(t, resource.TestCase{ resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) }, PreCheck: func() { testAccPreCheck(t) },
@ -268,7 +271,7 @@ func TestAccAWSSecurityGroupRule_Egress(t *testing.T) {
CheckDestroy: testAccCheckAWSSecurityGroupRuleDestroy, CheckDestroy: testAccCheckAWSSecurityGroupRuleDestroy,
Steps: []resource.TestStep{ Steps: []resource.TestStep{
{ {
Config: testAccAWSSecurityGroupRuleEgressConfig, Config: testAccAWSSecurityGroupRuleEgressConfig(rInt),
Check: resource.ComposeTestCheckFunc( Check: resource.ComposeTestCheckFunc(
testAccCheckAWSSecurityGroupRuleExists("aws_security_group.web", &group), testAccCheckAWSSecurityGroupRuleExists("aws_security_group.web", &group),
testAccCheckAWSSecurityGroupRuleAttributes("aws_security_group_rule.egress_1", &group, nil, "egress"), testAccCheckAWSSecurityGroupRuleAttributes("aws_security_group_rule.egress_1", &group, nil, "egress"),
@ -297,13 +300,14 @@ func TestAccAWSSecurityGroupRule_SelfReference(t *testing.T) {
} }
func TestAccAWSSecurityGroupRule_ExpectInvalidTypeError(t *testing.T) { func TestAccAWSSecurityGroupRule_ExpectInvalidTypeError(t *testing.T) {
rInt := acctest.RandInt()
resource.Test(t, resource.TestCase{ resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) }, PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders, Providers: testAccProviders,
CheckDestroy: testAccCheckAWSSecurityGroupRuleDestroy, CheckDestroy: testAccCheckAWSSecurityGroupRuleDestroy,
Steps: []resource.TestStep{ Steps: []resource.TestStep{
{ {
Config: testAccAWSSecurityGroupRuleExpectInvalidType, Config: testAccAWSSecurityGroupRuleExpectInvalidType(rInt),
ExpectError: regexp.MustCompile(`\\"type\\" contains an invalid Security Group Rule type \\"foobar\\"`), ExpectError: regexp.MustCompile(`\\"type\\" contains an invalid Security Group Rule type \\"foobar\\"`),
}, },
}, },
@ -313,6 +317,7 @@ func TestAccAWSSecurityGroupRule_ExpectInvalidTypeError(t *testing.T) {
// testing partial match implementation // testing partial match implementation
func TestAccAWSSecurityGroupRule_PartialMatching_basic(t *testing.T) { func TestAccAWSSecurityGroupRule_PartialMatching_basic(t *testing.T) {
var group ec2.SecurityGroup var group ec2.SecurityGroup
rInt := acctest.RandInt()
p := ec2.IpPermission{ p := ec2.IpPermission{
FromPort: aws.Int64(80), FromPort: aws.Int64(80),
@ -340,7 +345,7 @@ func TestAccAWSSecurityGroupRule_PartialMatching_basic(t *testing.T) {
CheckDestroy: testAccCheckAWSSecurityGroupRuleDestroy, CheckDestroy: testAccCheckAWSSecurityGroupRuleDestroy,
Steps: []resource.TestStep{ Steps: []resource.TestStep{
{ {
Config: testAccAWSSecurityGroupRulePartialMatching, Config: testAccAWSSecurityGroupRulePartialMatching(rInt),
Check: resource.ComposeTestCheckFunc( Check: resource.ComposeTestCheckFunc(
testAccCheckAWSSecurityGroupRuleExists("aws_security_group.web", &group), testAccCheckAWSSecurityGroupRuleExists("aws_security_group.web", &group),
testAccCheckAWSSecurityGroupRuleAttributes("aws_security_group_rule.ingress", &group, &p, "ingress"), testAccCheckAWSSecurityGroupRuleAttributes("aws_security_group_rule.ingress", &group, &p, "ingress"),
@ -356,6 +361,7 @@ func TestAccAWSSecurityGroupRule_PartialMatching_Source(t *testing.T) {
var group ec2.SecurityGroup var group ec2.SecurityGroup
var nat ec2.SecurityGroup var nat ec2.SecurityGroup
var p ec2.IpPermission var p ec2.IpPermission
rInt := acctest.RandInt()
// This function creates the expected IPPermission with the group id from an // This function creates the expected IPPermission with the group id from an
// external security group, needed because Security Group IDs are generated on // external security group, needed because Security Group IDs are generated on
@ -383,7 +389,7 @@ func TestAccAWSSecurityGroupRule_PartialMatching_Source(t *testing.T) {
CheckDestroy: testAccCheckAWSSecurityGroupRuleDestroy, CheckDestroy: testAccCheckAWSSecurityGroupRuleDestroy,
Steps: []resource.TestStep{ Steps: []resource.TestStep{
{ {
Config: testAccAWSSecurityGroupRulePartialMatching_Source, Config: testAccAWSSecurityGroupRulePartialMatching_Source(rInt),
Check: resource.ComposeTestCheckFunc( Check: resource.ComposeTestCheckFunc(
testAccCheckAWSSecurityGroupRuleExists("aws_security_group.web", &group), testAccCheckAWSSecurityGroupRuleExists("aws_security_group.web", &group),
testAccCheckAWSSecurityGroupRuleExists("aws_security_group.nat", &nat), testAccCheckAWSSecurityGroupRuleExists("aws_security_group.nat", &nat),
@ -433,6 +439,7 @@ func TestAccAWSSecurityGroupRule_Race(t *testing.T) {
func TestAccAWSSecurityGroupRule_SelfSource(t *testing.T) { func TestAccAWSSecurityGroupRule_SelfSource(t *testing.T) {
var group ec2.SecurityGroup var group ec2.SecurityGroup
rInt := acctest.RandInt()
resource.Test(t, resource.TestCase{ resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) }, PreCheck: func() { testAccPreCheck(t) },
@ -440,7 +447,7 @@ func TestAccAWSSecurityGroupRule_SelfSource(t *testing.T) {
CheckDestroy: testAccCheckAWSSecurityGroupRuleDestroy, CheckDestroy: testAccCheckAWSSecurityGroupRuleDestroy,
Steps: []resource.TestStep{ Steps: []resource.TestStep{
{ {
Config: testAccAWSSecurityGroupRuleSelfInSource, Config: testAccAWSSecurityGroupRuleSelfInSource(rInt),
Check: resource.ComposeTestCheckFunc( Check: resource.ComposeTestCheckFunc(
testAccCheckAWSSecurityGroupRuleExists("aws_security_group.web", &group), testAccCheckAWSSecurityGroupRuleExists("aws_security_group.web", &group),
), ),
@ -667,27 +674,28 @@ func testAccCheckAWSSecurityGroupRuleAttributes(n string, group *ec2.SecurityGro
} }
} }
const testAccAWSSecurityGroupRuleIngressConfig = ` func testAccAWSSecurityGroupRuleIngressConfig(rInt int) string {
resource "aws_security_group" "web" { return fmt.Sprintf(`
name = "terraform_acceptance_test_example" resource "aws_security_group" "web" {
description = "Used in the terraform acceptance tests" name = "terraform_test_%d"
description = "Used in the terraform acceptance tests"
tags { tags {
Name = "tf-acc-test" Name = "tf-acc-test"
} }
}
resource "aws_security_group_rule" "ingress_1" {
type = "ingress"
protocol = "tcp"
from_port = 80
to_port = 8000
cidr_blocks = ["10.0.0.0/8"]
security_group_id = "${aws_security_group.web.id}"
}`, rInt)
} }
resource "aws_security_group_rule" "ingress_1" {
type = "ingress"
protocol = "tcp"
from_port = 80
to_port = 8000
cidr_blocks = ["10.0.0.0/8"]
security_group_id = "${aws_security_group.web.id}"
}
`
const testAccAWSSecurityGroupRuleIngress_protocolConfig = ` const testAccAWSSecurityGroupRuleIngress_protocolConfig = `
resource "aws_vpc" "tftest" { resource "aws_vpc" "tftest" {
cidr_block = "10.0.0.0/16" cidr_block = "10.0.0.0/16"
@ -737,52 +745,54 @@ resource "aws_security_group_rule" "issue_5310" {
} }
` `
const testAccAWSSecurityGroupRuleIngressClassicConfig = ` func testAccAWSSecurityGroupRuleIngressClassicConfig(rInt int) string {
provider "aws" { return fmt.Sprintf(`
region = "us-east-1" provider "aws" {
region = "us-east-1"
}
resource "aws_security_group" "web" {
name = "terraform_test_%d"
description = "Used in the terraform acceptance tests"
tags {
Name = "tf-acc-test"
}
}
resource "aws_security_group_rule" "ingress_1" {
type = "ingress"
protocol = "tcp"
from_port = 80
to_port = 8000
cidr_blocks = ["10.0.0.0/8"]
security_group_id = "${aws_security_group.web.id}"
}`, rInt)
} }
resource "aws_security_group" "web" { func testAccAWSSecurityGroupRuleEgressConfig(rInt int) string {
name = "terraform_acceptance_test_example" return fmt.Sprintf(`
description = "Used in the terraform acceptance tests" resource "aws_security_group" "web" {
name = "terraform_test_%d"
description = "Used in the terraform acceptance tests"
tags { tags {
Name = "tf-acc-test" Name = "tf-acc-test"
} }
}
resource "aws_security_group_rule" "egress_1" {
type = "egress"
protocol = "tcp"
from_port = 80
to_port = 8000
cidr_blocks = ["10.0.0.0/8"]
security_group_id = "${aws_security_group.web.id}"
}`, rInt)
} }
resource "aws_security_group_rule" "ingress_1" {
type = "ingress"
protocol = "tcp"
from_port = 80
to_port = 8000
cidr_blocks = ["10.0.0.0/8"]
security_group_id = "${aws_security_group.web.id}"
}
`
const testAccAWSSecurityGroupRuleEgressConfig = `
resource "aws_security_group" "web" {
name = "terraform_acceptance_test_example"
description = "Used in the terraform acceptance tests"
tags {
Name = "tf-acc-test"
}
}
resource "aws_security_group_rule" "egress_1" {
type = "egress"
protocol = "tcp"
from_port = 80
to_port = 8000
cidr_blocks = ["10.0.0.0/8"]
security_group_id = "${aws_security_group.web.id}"
}
`
const testAccAWSSecurityGroupRuleConfigMultiIngress = ` const testAccAWSSecurityGroupRuleConfigMultiIngress = `
resource "aws_security_group" "web" { resource "aws_security_group" "web" {
name = "terraform_acceptance_test_example_2" name = "terraform_acceptance_test_example_2"
@ -847,107 +857,109 @@ resource "aws_security_group_rule" "self" {
} }
` `
const testAccAWSSecurityGroupRulePartialMatching = ` func testAccAWSSecurityGroupRulePartialMatching(rInt int) string {
resource "aws_vpc" "default" { return fmt.Sprintf(`
cidr_block = "10.0.0.0/16" resource "aws_vpc" "default" {
tags { cidr_block = "10.0.0.0/16"
Name = "tf-sg-rule-bug" tags {
} Name = "tf-sg-rule-bug"
}
}
resource "aws_security_group" "web" {
name = "tf-other-%d"
vpc_id = "${aws_vpc.default.id}"
tags {
Name = "tf-other-sg"
}
}
resource "aws_security_group" "nat" {
name = "tf-nat-%d"
vpc_id = "${aws_vpc.default.id}"
tags {
Name = "tf-nat-sg"
}
}
resource "aws_security_group_rule" "ingress" {
type = "ingress"
from_port = 80
to_port = 80
protocol = "tcp"
cidr_blocks = ["10.0.2.0/24", "10.0.3.0/24", "10.0.4.0/24"]
security_group_id = "${aws_security_group.web.id}"
}
resource "aws_security_group_rule" "other" {
type = "ingress"
from_port = 80
to_port = 80
protocol = "tcp"
cidr_blocks = ["10.0.5.0/24"]
security_group_id = "${aws_security_group.web.id}"
}
// same a above, but different group, to guard against bad hashing
resource "aws_security_group_rule" "nat_ingress" {
type = "ingress"
from_port = 80
to_port = 80
protocol = "tcp"
cidr_blocks = ["10.0.2.0/24", "10.0.3.0/24", "10.0.4.0/24"]
security_group_id = "${aws_security_group.nat.id}"
}`, rInt, rInt)
} }
resource "aws_security_group" "web" { func testAccAWSSecurityGroupRulePartialMatching_Source(rInt int) string {
name = "tf-other" return fmt.Sprintf(`
vpc_id = "${aws_vpc.default.id}" resource "aws_vpc" "default" {
tags { cidr_block = "10.0.0.0/16"
Name = "tf-other-sg" tags {
} Name = "tf-sg-rule-bug"
}
}
resource "aws_security_group" "web" {
name = "tf-other-%d"
vpc_id = "${aws_vpc.default.id}"
tags {
Name = "tf-other-sg"
}
}
resource "aws_security_group" "nat" {
name = "tf-nat-%d"
vpc_id = "${aws_vpc.default.id}"
tags {
Name = "tf-nat-sg"
}
}
resource "aws_security_group_rule" "source_ingress" {
type = "ingress"
from_port = 80
to_port = 80
protocol = "tcp"
source_security_group_id = "${aws_security_group.nat.id}"
security_group_id = "${aws_security_group.web.id}"
}
resource "aws_security_group_rule" "other_ingress" {
type = "ingress"
from_port = 80
to_port = 80
protocol = "tcp"
cidr_blocks = ["10.0.2.0/24", "10.0.3.0/24", "10.0.4.0/24"]
security_group_id = "${aws_security_group.web.id}"
}`, rInt, rInt)
} }
resource "aws_security_group" "nat" {
name = "tf-nat"
vpc_id = "${aws_vpc.default.id}"
tags {
Name = "tf-nat-sg"
}
}
resource "aws_security_group_rule" "ingress" {
type = "ingress"
from_port = 80
to_port = 80
protocol = "tcp"
cidr_blocks = ["10.0.2.0/24", "10.0.3.0/24", "10.0.4.0/24"]
security_group_id = "${aws_security_group.web.id}"
}
resource "aws_security_group_rule" "other" {
type = "ingress"
from_port = 80
to_port = 80
protocol = "tcp"
cidr_blocks = ["10.0.5.0/24"]
security_group_id = "${aws_security_group.web.id}"
}
// same a above, but different group, to guard against bad hashing
resource "aws_security_group_rule" "nat_ingress" {
type = "ingress"
from_port = 80
to_port = 80
protocol = "tcp"
cidr_blocks = ["10.0.2.0/24", "10.0.3.0/24", "10.0.4.0/24"]
security_group_id = "${aws_security_group.nat.id}"
}
`
const testAccAWSSecurityGroupRulePartialMatching_Source = `
resource "aws_vpc" "default" {
cidr_block = "10.0.0.0/16"
tags {
Name = "tf-sg-rule-bug"
}
}
resource "aws_security_group" "web" {
name = "tf-other"
vpc_id = "${aws_vpc.default.id}"
tags {
Name = "tf-other-sg"
}
}
resource "aws_security_group" "nat" {
name = "tf-nat"
vpc_id = "${aws_vpc.default.id}"
tags {
Name = "tf-nat-sg"
}
}
resource "aws_security_group_rule" "source_ingress" {
type = "ingress"
from_port = 80
to_port = 80
protocol = "tcp"
source_security_group_id = "${aws_security_group.nat.id}"
security_group_id = "${aws_security_group.web.id}"
}
resource "aws_security_group_rule" "other_ingress" {
type = "ingress"
from_port = 80
to_port = 80
protocol = "tcp"
cidr_blocks = ["10.0.2.0/24", "10.0.3.0/24", "10.0.4.0/24"]
security_group_id = "${aws_security_group.web.id}"
}
`
var testAccAWSSecurityGroupRuleRace = func() string { var testAccAWSSecurityGroupRuleRace = func() string {
var b bytes.Buffer var b bytes.Buffer
iterations := 50 iterations := 50
@ -1035,52 +1047,54 @@ resource "aws_security_group_rule" "egress_1" {
} }
` `
const testAccAWSSecurityGroupRuleSelfInSource = ` func testAccAWSSecurityGroupRuleSelfInSource(rInt int) string {
resource "aws_vpc" "foo" { return fmt.Sprintf(`
cidr_block = "10.1.0.0/16" resource "aws_vpc" "foo" {
cidr_block = "10.1.0.0/16"
tags { tags {
Name = "tf_sg_rule_self_group" Name = "tf_sg_rule_self_group"
} }
}
resource "aws_security_group" "web" {
name = "allow_all-%d"
description = "Allow all inbound traffic"
vpc_id = "${aws_vpc.foo.id}"
}
resource "aws_security_group_rule" "allow_self" {
type = "ingress"
from_port = 0
to_port = 0
protocol = "-1"
security_group_id = "${aws_security_group.web.id}"
source_security_group_id = "${aws_security_group.web.id}"
}`, rInt)
} }
resource "aws_security_group" "web" { func testAccAWSSecurityGroupRuleExpectInvalidType(rInt int) string {
name = "allow_all" return fmt.Sprintf(`
description = "Allow all inbound traffic" resource "aws_vpc" "foo" {
vpc_id = "${aws_vpc.foo.id}" cidr_block = "10.1.0.0/16"
}
resource "aws_security_group_rule" "allow_self" { tags {
type = "ingress" Name = "tf_sg_rule_self_group"
from_port = 0 }
to_port = 0 }
protocol = "-1"
security_group_id = "${aws_security_group.web.id}"
source_security_group_id = "${aws_security_group.web.id}"
}
`
const testAccAWSSecurityGroupRuleExpectInvalidType = ` resource "aws_security_group" "web" {
resource "aws_vpc" "foo" { name = "allow_all-%d"
cidr_block = "10.1.0.0/16" description = "Allow all inbound traffic"
vpc_id = "${aws_vpc.foo.id}"
}
tags { resource "aws_security_group_rule" "allow_self" {
Name = "tf_sg_rule_self_group" type = "foobar"
} from_port = 0
to_port = 0
protocol = "-1"
security_group_id = "${aws_security_group.web.id}"
source_security_group_id = "${aws_security_group.web.id}"
}`, rInt)
} }
resource "aws_security_group" "web" {
name = "allow_all"
description = "Allow all inbound traffic"
vpc_id = "${aws_vpc.foo.id}"
}
resource "aws_security_group_rule" "allow_self" {
type = "foobar"
from_port = 0
to_port = 0
protocol = "-1"
security_group_id = "${aws_security_group.web.id}"
source_security_group_id = "${aws_security_group.web.id}"
}
`