mirror of
https://github.com/opentofu/opentofu.git
synced 2025-01-08 15:13:56 -06:00
925265016b
Adds plan-level validation for both IPv4 and IPv6 CIDR Blocks in an AWS SecurityGroup resource, as well as the AWS Security Group Rule resource. ``` $ make testacc TEST=./builtin/providers/aws TESTARGS='-run=TestAccAWSSecurityGroup_invalidCIDRBlock' ==> Checking that code complies with gofmt requirements... go generate $(go list ./... | grep -v /terraform/vendor/) 2017/03/16 11:32:54 Generated command/internal_plugin_list.go TF_ACC=1 go test ./builtin/providers/aws -v -run=TestAccAWSSecurityGroup_invalidCIDRBlock -timeout 120m === RUN TestAccAWSSecurityGroup_invalidCIDRBlock --- PASS: TestAccAWSSecurityGroup_invalidCIDRBlock (0.01s) PASS ok github.com/hashicorp/terraform/builtin/providers/aws 0.017s ``` ``` $ make testacc TEST=./builtin/providers/aws TESTARGS='-run=TestAccAWSSecurityGroupRule_ExpectInvalidCIDR' ==> Checking that code complies with gofmt requirements... go generate $(go list ./... | grep -v /terraform/vendor/) 2017/03/16 11:46:21 Generated command/internal_plugin_list.go TF_ACC=1 go test ./builtin/providers/aws -v -run=TestAccAWSSecurityGroupRule_ExpectInvalidCIDR -timeout 120m === RUN TestAccAWSSecurityGroupRule_ExpectInvalidCIDR --- PASS: TestAccAWSSecurityGroupRule_ExpectInvalidCIDR (0.01s) PASS ok github.com/hashicorp/terraform/builtin/providers/aws 0.016s ```
1220 lines
30 KiB
Go
1220 lines
30 KiB
Go
package aws
|
|
|
|
import (
|
|
"bytes"
|
|
"fmt"
|
|
"log"
|
|
"regexp"
|
|
"testing"
|
|
|
|
"github.com/aws/aws-sdk-go/aws"
|
|
"github.com/aws/aws-sdk-go/aws/awserr"
|
|
"github.com/aws/aws-sdk-go/service/ec2"
|
|
"github.com/hashicorp/terraform/helper/acctest"
|
|
"github.com/hashicorp/terraform/helper/resource"
|
|
"github.com/hashicorp/terraform/terraform"
|
|
)
|
|
|
|
func TestIpPermissionIDHash(t *testing.T) {
|
|
simple := &ec2.IpPermission{
|
|
IpProtocol: aws.String("tcp"),
|
|
FromPort: aws.Int64(int64(80)),
|
|
ToPort: aws.Int64(int64(8000)),
|
|
IpRanges: []*ec2.IpRange{
|
|
{
|
|
CidrIp: aws.String("10.0.0.0/8"),
|
|
},
|
|
},
|
|
}
|
|
|
|
egress := &ec2.IpPermission{
|
|
IpProtocol: aws.String("tcp"),
|
|
FromPort: aws.Int64(int64(80)),
|
|
ToPort: aws.Int64(int64(8000)),
|
|
IpRanges: []*ec2.IpRange{
|
|
{
|
|
CidrIp: aws.String("10.0.0.0/8"),
|
|
},
|
|
},
|
|
}
|
|
|
|
egress_all := &ec2.IpPermission{
|
|
IpProtocol: aws.String("-1"),
|
|
IpRanges: []*ec2.IpRange{
|
|
{
|
|
CidrIp: aws.String("10.0.0.0/8"),
|
|
},
|
|
},
|
|
}
|
|
|
|
vpc_security_group_source := &ec2.IpPermission{
|
|
IpProtocol: aws.String("tcp"),
|
|
FromPort: aws.Int64(int64(80)),
|
|
ToPort: aws.Int64(int64(8000)),
|
|
UserIdGroupPairs: []*ec2.UserIdGroupPair{
|
|
{
|
|
UserId: aws.String("987654321"),
|
|
GroupId: aws.String("sg-12345678"),
|
|
},
|
|
{
|
|
UserId: aws.String("123456789"),
|
|
GroupId: aws.String("sg-987654321"),
|
|
},
|
|
{
|
|
UserId: aws.String("123456789"),
|
|
GroupId: aws.String("sg-12345678"),
|
|
},
|
|
},
|
|
}
|
|
|
|
security_group_source := &ec2.IpPermission{
|
|
IpProtocol: aws.String("tcp"),
|
|
FromPort: aws.Int64(int64(80)),
|
|
ToPort: aws.Int64(int64(8000)),
|
|
UserIdGroupPairs: []*ec2.UserIdGroupPair{
|
|
{
|
|
UserId: aws.String("987654321"),
|
|
GroupName: aws.String("my-security-group"),
|
|
},
|
|
{
|
|
UserId: aws.String("123456789"),
|
|
GroupName: aws.String("my-security-group"),
|
|
},
|
|
{
|
|
UserId: aws.String("123456789"),
|
|
GroupName: aws.String("my-other-security-group"),
|
|
},
|
|
},
|
|
}
|
|
|
|
// hardcoded hashes, to detect future change
|
|
cases := []struct {
|
|
Input *ec2.IpPermission
|
|
Type string
|
|
Output string
|
|
}{
|
|
{simple, "ingress", "sgrule-3403497314"},
|
|
{egress, "egress", "sgrule-1173186295"},
|
|
{egress_all, "egress", "sgrule-766323498"},
|
|
{vpc_security_group_source, "egress", "sgrule-351225364"},
|
|
{security_group_source, "egress", "sgrule-2198807188"},
|
|
}
|
|
|
|
for _, tc := range cases {
|
|
actual := ipPermissionIDHash("sg-12345", tc.Type, tc.Input)
|
|
if actual != tc.Output {
|
|
t.Errorf("input: %s - %s\noutput: %s", tc.Type, tc.Input, actual)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestAccAWSSecurityGroupRule_Ingress_VPC(t *testing.T) {
|
|
var group ec2.SecurityGroup
|
|
rInt := acctest.RandInt()
|
|
|
|
testRuleCount := func(*terraform.State) error {
|
|
if len(group.IpPermissions) != 1 {
|
|
return fmt.Errorf("Wrong Security Group rule count, expected %d, got %d",
|
|
1, len(group.IpPermissions))
|
|
}
|
|
|
|
rule := group.IpPermissions[0]
|
|
if *rule.FromPort != int64(80) {
|
|
return fmt.Errorf("Wrong Security Group port setting, expected %d, got %d",
|
|
80, int(*rule.FromPort))
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
resource.Test(t, resource.TestCase{
|
|
PreCheck: func() { testAccPreCheck(t) },
|
|
Providers: testAccProviders,
|
|
CheckDestroy: testAccCheckAWSSecurityGroupRuleDestroy,
|
|
Steps: []resource.TestStep{
|
|
{
|
|
Config: testAccAWSSecurityGroupRuleIngressConfig(rInt),
|
|
Check: resource.ComposeTestCheckFunc(
|
|
testAccCheckAWSSecurityGroupRuleExists("aws_security_group.web", &group),
|
|
testAccCheckAWSSecurityGroupRuleAttributes("aws_security_group_rule.ingress_1", &group, nil, "ingress"),
|
|
resource.TestCheckResourceAttr(
|
|
"aws_security_group_rule.ingress_1", "from_port", "80"),
|
|
testRuleCount,
|
|
),
|
|
},
|
|
},
|
|
})
|
|
}
|
|
|
|
func TestAccAWSSecurityGroupRule_Ingress_Protocol(t *testing.T) {
|
|
var group ec2.SecurityGroup
|
|
|
|
testRuleCount := func(*terraform.State) error {
|
|
if len(group.IpPermissions) != 1 {
|
|
return fmt.Errorf("Wrong Security Group rule count, expected %d, got %d",
|
|
1, len(group.IpPermissions))
|
|
}
|
|
|
|
rule := group.IpPermissions[0]
|
|
if *rule.FromPort != int64(80) {
|
|
return fmt.Errorf("Wrong Security Group port setting, expected %d, got %d",
|
|
80, int(*rule.FromPort))
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
resource.Test(t, resource.TestCase{
|
|
PreCheck: func() { testAccPreCheck(t) },
|
|
Providers: testAccProviders,
|
|
CheckDestroy: testAccCheckAWSSecurityGroupRuleDestroy,
|
|
Steps: []resource.TestStep{
|
|
{
|
|
Config: testAccAWSSecurityGroupRuleIngress_protocolConfig,
|
|
Check: resource.ComposeTestCheckFunc(
|
|
testAccCheckAWSSecurityGroupRuleExists("aws_security_group.web", &group),
|
|
testAccCheckAWSSecurityGroupRuleAttributes("aws_security_group_rule.ingress_1", &group, nil, "ingress"),
|
|
resource.TestCheckResourceAttr(
|
|
"aws_security_group_rule.ingress_1", "from_port", "80"),
|
|
testRuleCount,
|
|
),
|
|
},
|
|
},
|
|
})
|
|
}
|
|
|
|
func TestAccAWSSecurityGroupRule_Ingress_Ipv6(t *testing.T) {
|
|
var group ec2.SecurityGroup
|
|
|
|
testRuleCount := func(*terraform.State) error {
|
|
if len(group.IpPermissions) != 1 {
|
|
return fmt.Errorf("Wrong Security Group rule count, expected %d, got %d",
|
|
1, len(group.IpPermissions))
|
|
}
|
|
|
|
rule := group.IpPermissions[0]
|
|
if *rule.FromPort != int64(80) {
|
|
return fmt.Errorf("Wrong Security Group port setting, expected %d, got %d",
|
|
80, int(*rule.FromPort))
|
|
}
|
|
|
|
ipv6Address := rule.Ipv6Ranges[0]
|
|
if *ipv6Address.CidrIpv6 != "::/0" {
|
|
return fmt.Errorf("Wrong Security Group IPv6 address, expected %s, got %s",
|
|
"::/0", *ipv6Address.CidrIpv6)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
resource.Test(t, resource.TestCase{
|
|
PreCheck: func() { testAccPreCheck(t) },
|
|
Providers: testAccProviders,
|
|
CheckDestroy: testAccCheckAWSSecurityGroupRuleDestroy,
|
|
Steps: []resource.TestStep{
|
|
{
|
|
Config: testAccAWSSecurityGroupRuleIngress_ipv6Config,
|
|
Check: resource.ComposeTestCheckFunc(
|
|
testAccCheckAWSSecurityGroupRuleExists("aws_security_group.web", &group),
|
|
testRuleCount,
|
|
),
|
|
},
|
|
},
|
|
})
|
|
}
|
|
|
|
func TestAccAWSSecurityGroupRule_Ingress_Classic(t *testing.T) {
|
|
var group ec2.SecurityGroup
|
|
rInt := acctest.RandInt()
|
|
|
|
testRuleCount := func(*terraform.State) error {
|
|
if len(group.IpPermissions) != 1 {
|
|
return fmt.Errorf("Wrong Security Group rule count, expected %d, got %d",
|
|
1, len(group.IpPermissions))
|
|
}
|
|
|
|
rule := group.IpPermissions[0]
|
|
if *rule.FromPort != int64(80) {
|
|
return fmt.Errorf("Wrong Security Group port setting, expected %d, got %d",
|
|
80, int(*rule.FromPort))
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
resource.Test(t, resource.TestCase{
|
|
PreCheck: func() { testAccPreCheck(t) },
|
|
Providers: testAccProviders,
|
|
CheckDestroy: testAccCheckAWSSecurityGroupRuleDestroy,
|
|
Steps: []resource.TestStep{
|
|
{
|
|
Config: testAccAWSSecurityGroupRuleIngressClassicConfig(rInt),
|
|
Check: resource.ComposeTestCheckFunc(
|
|
testAccCheckAWSSecurityGroupRuleExists("aws_security_group.web", &group),
|
|
testAccCheckAWSSecurityGroupRuleAttributes("aws_security_group_rule.ingress_1", &group, nil, "ingress"),
|
|
resource.TestCheckResourceAttr(
|
|
"aws_security_group_rule.ingress_1", "from_port", "80"),
|
|
testRuleCount,
|
|
),
|
|
},
|
|
},
|
|
})
|
|
}
|
|
|
|
func TestAccAWSSecurityGroupRule_MultiIngress(t *testing.T) {
|
|
var group ec2.SecurityGroup
|
|
|
|
testMultiRuleCount := func(*terraform.State) error {
|
|
if len(group.IpPermissions) != 2 {
|
|
return fmt.Errorf("Wrong Security Group rule count, expected %d, got %d",
|
|
2, len(group.IpPermissions))
|
|
}
|
|
|
|
var rule *ec2.IpPermission
|
|
for _, r := range group.IpPermissions {
|
|
if *r.FromPort == int64(80) {
|
|
rule = r
|
|
}
|
|
}
|
|
|
|
if *rule.ToPort != int64(8000) {
|
|
return fmt.Errorf("Wrong Security Group port 2 setting, expected %d, got %d",
|
|
8000, int(*rule.ToPort))
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
resource.Test(t, resource.TestCase{
|
|
PreCheck: func() { testAccPreCheck(t) },
|
|
Providers: testAccProviders,
|
|
CheckDestroy: testAccCheckAWSSecurityGroupRuleDestroy,
|
|
Steps: []resource.TestStep{
|
|
{
|
|
Config: testAccAWSSecurityGroupRuleConfigMultiIngress,
|
|
Check: resource.ComposeTestCheckFunc(
|
|
testAccCheckAWSSecurityGroupRuleExists("aws_security_group.web", &group),
|
|
testMultiRuleCount,
|
|
),
|
|
},
|
|
},
|
|
})
|
|
}
|
|
|
|
func TestAccAWSSecurityGroupRule_Egress(t *testing.T) {
|
|
var group ec2.SecurityGroup
|
|
rInt := acctest.RandInt()
|
|
|
|
resource.Test(t, resource.TestCase{
|
|
PreCheck: func() { testAccPreCheck(t) },
|
|
Providers: testAccProviders,
|
|
CheckDestroy: testAccCheckAWSSecurityGroupRuleDestroy,
|
|
Steps: []resource.TestStep{
|
|
{
|
|
Config: testAccAWSSecurityGroupRuleEgressConfig(rInt),
|
|
Check: resource.ComposeTestCheckFunc(
|
|
testAccCheckAWSSecurityGroupRuleExists("aws_security_group.web", &group),
|
|
testAccCheckAWSSecurityGroupRuleAttributes("aws_security_group_rule.egress_1", &group, nil, "egress"),
|
|
),
|
|
},
|
|
},
|
|
})
|
|
}
|
|
|
|
func TestAccAWSSecurityGroupRule_SelfReference(t *testing.T) {
|
|
var group ec2.SecurityGroup
|
|
|
|
resource.Test(t, resource.TestCase{
|
|
PreCheck: func() { testAccPreCheck(t) },
|
|
Providers: testAccProviders,
|
|
CheckDestroy: testAccCheckAWSSecurityGroupRuleDestroy,
|
|
Steps: []resource.TestStep{
|
|
{
|
|
Config: testAccAWSSecurityGroupRuleConfigSelfReference,
|
|
Check: resource.ComposeTestCheckFunc(
|
|
testAccCheckAWSSecurityGroupRuleExists("aws_security_group.web", &group),
|
|
),
|
|
},
|
|
},
|
|
})
|
|
}
|
|
|
|
func TestAccAWSSecurityGroupRule_ExpectInvalidTypeError(t *testing.T) {
|
|
rInt := acctest.RandInt()
|
|
resource.Test(t, resource.TestCase{
|
|
PreCheck: func() { testAccPreCheck(t) },
|
|
Providers: testAccProviders,
|
|
CheckDestroy: testAccCheckAWSSecurityGroupRuleDestroy,
|
|
Steps: []resource.TestStep{
|
|
{
|
|
Config: testAccAWSSecurityGroupRuleExpectInvalidType(rInt),
|
|
ExpectError: regexp.MustCompile(`\\"type\\" contains an invalid Security Group Rule type \\"foobar\\"`),
|
|
},
|
|
},
|
|
})
|
|
}
|
|
|
|
func TestAccAWSSecurityGroupRule_ExpectInvalidCIDR(t *testing.T) {
|
|
rInt := acctest.RandInt()
|
|
resource.Test(t, resource.TestCase{
|
|
PreCheck: func() { testAccPreCheck(t) },
|
|
Providers: testAccProviders,
|
|
CheckDestroy: testAccCheckAWSSecurityGroupRuleDestroy,
|
|
Steps: []resource.TestStep{
|
|
{
|
|
Config: testAccAWSSecurityGroupRuleInvalidIPv4CIDR(rInt),
|
|
ExpectError: regexp.MustCompile("invalid CIDR address: 1.2.3.4/33"),
|
|
},
|
|
{
|
|
Config: testAccAWSSecurityGroupRuleInvalidIPv6CIDR(rInt),
|
|
ExpectError: regexp.MustCompile("invalid CIDR address: ::/244"),
|
|
},
|
|
},
|
|
})
|
|
}
|
|
|
|
// testing partial match implementation
|
|
func TestAccAWSSecurityGroupRule_PartialMatching_basic(t *testing.T) {
|
|
var group ec2.SecurityGroup
|
|
rInt := acctest.RandInt()
|
|
|
|
p := ec2.IpPermission{
|
|
FromPort: aws.Int64(80),
|
|
ToPort: aws.Int64(80),
|
|
IpProtocol: aws.String("tcp"),
|
|
IpRanges: []*ec2.IpRange{
|
|
{CidrIp: aws.String("10.0.2.0/24")},
|
|
{CidrIp: aws.String("10.0.3.0/24")},
|
|
{CidrIp: aws.String("10.0.4.0/24")},
|
|
},
|
|
}
|
|
|
|
o := ec2.IpPermission{
|
|
FromPort: aws.Int64(80),
|
|
ToPort: aws.Int64(80),
|
|
IpProtocol: aws.String("tcp"),
|
|
IpRanges: []*ec2.IpRange{
|
|
{CidrIp: aws.String("10.0.5.0/24")},
|
|
},
|
|
}
|
|
|
|
resource.Test(t, resource.TestCase{
|
|
PreCheck: func() { testAccPreCheck(t) },
|
|
Providers: testAccProviders,
|
|
CheckDestroy: testAccCheckAWSSecurityGroupRuleDestroy,
|
|
Steps: []resource.TestStep{
|
|
{
|
|
Config: testAccAWSSecurityGroupRulePartialMatching(rInt),
|
|
Check: resource.ComposeTestCheckFunc(
|
|
testAccCheckAWSSecurityGroupRuleExists("aws_security_group.web", &group),
|
|
testAccCheckAWSSecurityGroupRuleAttributes("aws_security_group_rule.ingress", &group, &p, "ingress"),
|
|
testAccCheckAWSSecurityGroupRuleAttributes("aws_security_group_rule.other", &group, &o, "ingress"),
|
|
testAccCheckAWSSecurityGroupRuleAttributes("aws_security_group_rule.nat_ingress", &group, &o, "ingress"),
|
|
),
|
|
},
|
|
},
|
|
})
|
|
}
|
|
|
|
func TestAccAWSSecurityGroupRule_PartialMatching_Source(t *testing.T) {
|
|
var group ec2.SecurityGroup
|
|
var nat ec2.SecurityGroup
|
|
var p ec2.IpPermission
|
|
rInt := acctest.RandInt()
|
|
|
|
// This function creates the expected IPPermission with the group id from an
|
|
// external security group, needed because Security Group IDs are generated on
|
|
// AWS side and can't be known ahead of time.
|
|
setupSG := func(*terraform.State) error {
|
|
if nat.GroupId == nil {
|
|
return fmt.Errorf("Error: nat group has nil GroupID")
|
|
}
|
|
|
|
p = ec2.IpPermission{
|
|
FromPort: aws.Int64(80),
|
|
ToPort: aws.Int64(80),
|
|
IpProtocol: aws.String("tcp"),
|
|
UserIdGroupPairs: []*ec2.UserIdGroupPair{
|
|
{GroupId: nat.GroupId},
|
|
},
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
resource.Test(t, resource.TestCase{
|
|
PreCheck: func() { testAccPreCheck(t) },
|
|
Providers: testAccProviders,
|
|
CheckDestroy: testAccCheckAWSSecurityGroupRuleDestroy,
|
|
Steps: []resource.TestStep{
|
|
{
|
|
Config: testAccAWSSecurityGroupRulePartialMatching_Source(rInt),
|
|
Check: resource.ComposeTestCheckFunc(
|
|
testAccCheckAWSSecurityGroupRuleExists("aws_security_group.web", &group),
|
|
testAccCheckAWSSecurityGroupRuleExists("aws_security_group.nat", &nat),
|
|
setupSG,
|
|
testAccCheckAWSSecurityGroupRuleAttributes("aws_security_group_rule.source_ingress", &group, &p, "ingress"),
|
|
),
|
|
},
|
|
},
|
|
})
|
|
}
|
|
|
|
func TestAccAWSSecurityGroupRule_Issue5310(t *testing.T) {
|
|
var group ec2.SecurityGroup
|
|
|
|
resource.Test(t, resource.TestCase{
|
|
PreCheck: func() { testAccPreCheck(t) },
|
|
Providers: testAccProviders,
|
|
CheckDestroy: testAccCheckAWSSecurityGroupRuleDestroy,
|
|
Steps: []resource.TestStep{
|
|
{
|
|
Config: testAccAWSSecurityGroupRuleIssue5310,
|
|
Check: resource.ComposeTestCheckFunc(
|
|
testAccCheckAWSSecurityGroupRuleExists("aws_security_group.issue_5310", &group),
|
|
),
|
|
},
|
|
},
|
|
})
|
|
}
|
|
|
|
func TestAccAWSSecurityGroupRule_Race(t *testing.T) {
|
|
var group ec2.SecurityGroup
|
|
|
|
resource.Test(t, resource.TestCase{
|
|
PreCheck: func() { testAccPreCheck(t) },
|
|
Providers: testAccProviders,
|
|
CheckDestroy: testAccCheckAWSSecurityGroupRuleDestroy,
|
|
Steps: []resource.TestStep{
|
|
{
|
|
Config: testAccAWSSecurityGroupRuleRace,
|
|
Check: resource.ComposeTestCheckFunc(
|
|
testAccCheckAWSSecurityGroupRuleExists("aws_security_group.race", &group),
|
|
),
|
|
},
|
|
},
|
|
})
|
|
}
|
|
|
|
func TestAccAWSSecurityGroupRule_SelfSource(t *testing.T) {
|
|
var group ec2.SecurityGroup
|
|
rInt := acctest.RandInt()
|
|
|
|
resource.Test(t, resource.TestCase{
|
|
PreCheck: func() { testAccPreCheck(t) },
|
|
Providers: testAccProviders,
|
|
CheckDestroy: testAccCheckAWSSecurityGroupRuleDestroy,
|
|
Steps: []resource.TestStep{
|
|
{
|
|
Config: testAccAWSSecurityGroupRuleSelfInSource(rInt),
|
|
Check: resource.ComposeTestCheckFunc(
|
|
testAccCheckAWSSecurityGroupRuleExists("aws_security_group.web", &group),
|
|
),
|
|
},
|
|
},
|
|
})
|
|
}
|
|
|
|
func TestAccAWSSecurityGroupRule_PrefixListEgress(t *testing.T) {
|
|
var group ec2.SecurityGroup
|
|
var endpoint ec2.VpcEndpoint
|
|
var p ec2.IpPermission
|
|
|
|
// This function creates the expected IPPermission with the prefix list ID from
|
|
// the VPC Endpoint created in the test
|
|
setupSG := func(*terraform.State) error {
|
|
conn := testAccProvider.Meta().(*AWSClient).ec2conn
|
|
prefixListInput := &ec2.DescribePrefixListsInput{
|
|
Filters: []*ec2.Filter{
|
|
{Name: aws.String("prefix-list-name"), Values: []*string{endpoint.ServiceName}},
|
|
},
|
|
}
|
|
|
|
log.Printf("[DEBUG] Reading VPC Endpoint prefix list: %s", prefixListInput)
|
|
prefixListsOutput, err := conn.DescribePrefixLists(prefixListInput)
|
|
|
|
if err != nil {
|
|
_, ok := err.(awserr.Error)
|
|
if !ok {
|
|
return fmt.Errorf("Error reading VPC Endpoint prefix list: %s", err.Error())
|
|
}
|
|
}
|
|
|
|
if len(prefixListsOutput.PrefixLists) != 1 {
|
|
return fmt.Errorf("There are multiple prefix lists associated with the service name '%s'. Unexpected", prefixListsOutput)
|
|
}
|
|
|
|
p = ec2.IpPermission{
|
|
IpProtocol: aws.String("-1"),
|
|
PrefixListIds: []*ec2.PrefixListId{
|
|
{PrefixListId: prefixListsOutput.PrefixLists[0].PrefixListId},
|
|
},
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
resource.Test(t, resource.TestCase{
|
|
PreCheck: func() { testAccPreCheck(t) },
|
|
Providers: testAccProviders,
|
|
CheckDestroy: testAccCheckAWSSecurityGroupRuleDestroy,
|
|
Steps: []resource.TestStep{
|
|
{
|
|
Config: testAccAWSSecurityGroupRulePrefixListEgressConfig,
|
|
Check: resource.ComposeTestCheckFunc(
|
|
testAccCheckAWSSecurityGroupRuleExists("aws_security_group.egress", &group),
|
|
// lookup info on the VPC Endpoint created, to populate the expected
|
|
// IP Perm
|
|
testAccCheckVpcEndpointExists("aws_vpc_endpoint.s3-us-west-2", &endpoint),
|
|
setupSG,
|
|
testAccCheckAWSSecurityGroupRuleAttributes("aws_security_group_rule.egress_1", &group, &p, "egress"),
|
|
),
|
|
},
|
|
},
|
|
})
|
|
}
|
|
|
|
func testAccCheckAWSSecurityGroupRuleDestroy(s *terraform.State) error {
|
|
conn := testAccProvider.Meta().(*AWSClient).ec2conn
|
|
|
|
for _, rs := range s.RootModule().Resources {
|
|
if rs.Type != "aws_security_group" {
|
|
continue
|
|
}
|
|
|
|
// Retrieve our group
|
|
req := &ec2.DescribeSecurityGroupsInput{
|
|
GroupIds: []*string{aws.String(rs.Primary.ID)},
|
|
}
|
|
resp, err := conn.DescribeSecurityGroups(req)
|
|
if err == nil {
|
|
if len(resp.SecurityGroups) > 0 && *resp.SecurityGroups[0].GroupId == rs.Primary.ID {
|
|
return fmt.Errorf("Security Group (%s) still exists.", rs.Primary.ID)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
ec2err, ok := err.(awserr.Error)
|
|
if !ok {
|
|
return err
|
|
}
|
|
// Confirm error code is what we want
|
|
if ec2err.Code() != "InvalidGroup.NotFound" {
|
|
return err
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func testAccCheckAWSSecurityGroupRuleExists(n string, group *ec2.SecurityGroup) 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 Security Group is set")
|
|
}
|
|
|
|
conn := testAccProvider.Meta().(*AWSClient).ec2conn
|
|
req := &ec2.DescribeSecurityGroupsInput{
|
|
GroupIds: []*string{aws.String(rs.Primary.ID)},
|
|
}
|
|
resp, err := conn.DescribeSecurityGroups(req)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if len(resp.SecurityGroups) > 0 && *resp.SecurityGroups[0].GroupId == rs.Primary.ID {
|
|
*group = *resp.SecurityGroups[0]
|
|
return nil
|
|
}
|
|
|
|
return fmt.Errorf("Security Group not found")
|
|
}
|
|
}
|
|
|
|
func testAccCheckAWSSecurityGroupRuleAttributes(n string, group *ec2.SecurityGroup, p *ec2.IpPermission, ruleType string) resource.TestCheckFunc {
|
|
return func(s *terraform.State) error {
|
|
rs, ok := s.RootModule().Resources[n]
|
|
if !ok {
|
|
return fmt.Errorf("Security Group Rule Not found: %s", n)
|
|
}
|
|
|
|
if rs.Primary.ID == "" {
|
|
return fmt.Errorf("No Security Group Rule is set")
|
|
}
|
|
|
|
if p == nil {
|
|
p = &ec2.IpPermission{
|
|
FromPort: aws.Int64(80),
|
|
ToPort: aws.Int64(8000),
|
|
IpProtocol: aws.String("tcp"),
|
|
IpRanges: []*ec2.IpRange{{CidrIp: aws.String("10.0.0.0/8")}},
|
|
}
|
|
}
|
|
|
|
var matchingRule *ec2.IpPermission
|
|
var rules []*ec2.IpPermission
|
|
if ruleType == "ingress" {
|
|
rules = group.IpPermissions
|
|
} else {
|
|
rules = group.IpPermissionsEgress
|
|
}
|
|
|
|
if len(rules) == 0 {
|
|
return fmt.Errorf("No IPPerms")
|
|
}
|
|
|
|
for _, r := range rules {
|
|
if r.ToPort != nil && *p.ToPort != *r.ToPort {
|
|
continue
|
|
}
|
|
|
|
if r.FromPort != nil && *p.FromPort != *r.FromPort {
|
|
continue
|
|
}
|
|
|
|
if r.IpProtocol != nil && *p.IpProtocol != *r.IpProtocol {
|
|
continue
|
|
}
|
|
|
|
remaining := len(p.IpRanges)
|
|
for _, ip := range p.IpRanges {
|
|
for _, rip := range r.IpRanges {
|
|
if *ip.CidrIp == *rip.CidrIp {
|
|
remaining--
|
|
}
|
|
}
|
|
}
|
|
|
|
if remaining > 0 {
|
|
continue
|
|
}
|
|
|
|
remaining = len(p.UserIdGroupPairs)
|
|
for _, ip := range p.UserIdGroupPairs {
|
|
for _, rip := range r.UserIdGroupPairs {
|
|
if *ip.GroupId == *rip.GroupId {
|
|
remaining--
|
|
}
|
|
}
|
|
}
|
|
|
|
if remaining > 0 {
|
|
continue
|
|
}
|
|
|
|
remaining = len(p.PrefixListIds)
|
|
for _, pip := range p.PrefixListIds {
|
|
for _, rpip := range r.PrefixListIds {
|
|
if *pip.PrefixListId == *rpip.PrefixListId {
|
|
remaining--
|
|
}
|
|
}
|
|
}
|
|
|
|
if remaining > 0 {
|
|
continue
|
|
}
|
|
|
|
matchingRule = r
|
|
}
|
|
|
|
if matchingRule != nil {
|
|
log.Printf("[DEBUG] Matching rule found : %s", matchingRule)
|
|
return nil
|
|
}
|
|
|
|
return fmt.Errorf("Error here\n\tlooking for %s, wasn't found in %s", p, rules)
|
|
}
|
|
}
|
|
|
|
func testAccAWSSecurityGroupRuleIngressConfig(rInt int) string {
|
|
return fmt.Sprintf(`
|
|
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)
|
|
}
|
|
|
|
const testAccAWSSecurityGroupRuleIngress_ipv6Config = `
|
|
resource "aws_vpc" "tftest" {
|
|
cidr_block = "10.0.0.0/16"
|
|
|
|
tags {
|
|
Name = "tf-testing"
|
|
}
|
|
}
|
|
|
|
resource "aws_security_group" "web" {
|
|
vpc_id = "${aws_vpc.tftest.id}"
|
|
|
|
tags {
|
|
Name = "tf-acc-test"
|
|
}
|
|
}
|
|
|
|
resource "aws_security_group_rule" "ingress_1" {
|
|
type = "ingress"
|
|
protocol = "6"
|
|
from_port = 80
|
|
to_port = 8000
|
|
ipv6_cidr_blocks = ["::/0"]
|
|
|
|
security_group_id = "${aws_security_group.web.id}"
|
|
}
|
|
`
|
|
|
|
const testAccAWSSecurityGroupRuleIngress_protocolConfig = `
|
|
resource "aws_vpc" "tftest" {
|
|
cidr_block = "10.0.0.0/16"
|
|
|
|
tags {
|
|
Name = "tf-testing"
|
|
}
|
|
}
|
|
|
|
resource "aws_security_group" "web" {
|
|
vpc_id = "${aws_vpc.tftest.id}"
|
|
|
|
tags {
|
|
Name = "tf-acc-test"
|
|
}
|
|
}
|
|
|
|
resource "aws_security_group_rule" "ingress_1" {
|
|
type = "ingress"
|
|
protocol = "6"
|
|
from_port = 80
|
|
to_port = 8000
|
|
cidr_blocks = ["10.0.0.0/8"]
|
|
|
|
security_group_id = "${aws_security_group.web.id}"
|
|
}
|
|
|
|
`
|
|
|
|
const testAccAWSSecurityGroupRuleIssue5310 = `
|
|
provider "aws" {
|
|
region = "us-east-1"
|
|
}
|
|
|
|
resource "aws_security_group" "issue_5310" {
|
|
name = "terraform-test-issue_5310"
|
|
description = "SG for test of issue 5310"
|
|
}
|
|
|
|
resource "aws_security_group_rule" "issue_5310" {
|
|
type = "ingress"
|
|
from_port = 0
|
|
to_port = 65535
|
|
protocol = "tcp"
|
|
security_group_id = "${aws_security_group.issue_5310.id}"
|
|
self = true
|
|
}
|
|
`
|
|
|
|
func testAccAWSSecurityGroupRuleIngressClassicConfig(rInt int) string {
|
|
return fmt.Sprintf(`
|
|
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)
|
|
}
|
|
|
|
func testAccAWSSecurityGroupRuleEgressConfig(rInt int) string {
|
|
return fmt.Sprintf(`
|
|
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" "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)
|
|
}
|
|
|
|
const testAccAWSSecurityGroupRuleConfigMultiIngress = `
|
|
resource "aws_security_group" "web" {
|
|
name = "terraform_acceptance_test_example_2"
|
|
description = "Used in the terraform acceptance tests"
|
|
}
|
|
|
|
resource "aws_security_group" "worker" {
|
|
name = "terraform_acceptance_test_example_worker"
|
|
description = "Used in the terraform acceptance tests"
|
|
}
|
|
|
|
|
|
resource "aws_security_group_rule" "ingress_1" {
|
|
type = "ingress"
|
|
protocol = "tcp"
|
|
from_port = 22
|
|
to_port = 22
|
|
cidr_blocks = ["10.0.0.0/8"]
|
|
|
|
security_group_id = "${aws_security_group.web.id}"
|
|
}
|
|
|
|
resource "aws_security_group_rule" "ingress_2" {
|
|
type = "ingress"
|
|
protocol = "tcp"
|
|
from_port = 80
|
|
to_port = 8000
|
|
self = true
|
|
|
|
security_group_id = "${aws_security_group.web.id}"
|
|
}
|
|
`
|
|
|
|
// check for GH-1985 regression
|
|
const testAccAWSSecurityGroupRuleConfigSelfReference = `
|
|
provider "aws" {
|
|
region = "us-west-2"
|
|
}
|
|
|
|
resource "aws_vpc" "main" {
|
|
cidr_block = "10.0.0.0/16"
|
|
tags {
|
|
Name = "sg-self-test"
|
|
}
|
|
}
|
|
|
|
resource "aws_security_group" "web" {
|
|
name = "main"
|
|
vpc_id = "${aws_vpc.main.id}"
|
|
tags {
|
|
Name = "sg-self-test"
|
|
}
|
|
}
|
|
|
|
resource "aws_security_group_rule" "self" {
|
|
type = "ingress"
|
|
protocol = "-1"
|
|
from_port = 0
|
|
to_port = 0
|
|
self = true
|
|
security_group_id = "${aws_security_group.web.id}"
|
|
}
|
|
`
|
|
|
|
func testAccAWSSecurityGroupRulePartialMatching(rInt int) string {
|
|
return fmt.Sprintf(`
|
|
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-%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)
|
|
}
|
|
|
|
func testAccAWSSecurityGroupRulePartialMatching_Source(rInt int) string {
|
|
return fmt.Sprintf(`
|
|
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-%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)
|
|
}
|
|
|
|
var testAccAWSSecurityGroupRuleRace = func() string {
|
|
var b bytes.Buffer
|
|
iterations := 50
|
|
b.WriteString(fmt.Sprintf(`
|
|
resource "aws_vpc" "default" {
|
|
cidr_block = "10.0.0.0/16"
|
|
tags { Name = "tf-sg-rule-race" }
|
|
}
|
|
|
|
resource "aws_security_group" "race" {
|
|
name = "tf-sg-rule-race-group-%d"
|
|
vpc_id = "${aws_vpc.default.id}"
|
|
}
|
|
`, acctest.RandInt()))
|
|
for i := 1; i < iterations; i++ {
|
|
b.WriteString(fmt.Sprintf(`
|
|
resource "aws_security_group_rule" "ingress%d" {
|
|
security_group_id = "${aws_security_group.race.id}"
|
|
type = "ingress"
|
|
from_port = %d
|
|
to_port = %d
|
|
protocol = "tcp"
|
|
cidr_blocks = ["10.0.0.%d/32"]
|
|
}
|
|
|
|
resource "aws_security_group_rule" "egress%d" {
|
|
security_group_id = "${aws_security_group.race.id}"
|
|
type = "egress"
|
|
from_port = %d
|
|
to_port = %d
|
|
protocol = "tcp"
|
|
cidr_blocks = ["10.0.0.%d/32"]
|
|
}
|
|
`, i, i, i, i, i, i, i, i))
|
|
}
|
|
return b.String()
|
|
}()
|
|
|
|
const testAccAWSSecurityGroupRulePrefixListEgressConfig = `
|
|
|
|
resource "aws_vpc" "tf_sg_prefix_list_egress_test" {
|
|
cidr_block = "10.0.0.0/16"
|
|
tags {
|
|
Name = "tf_sg_prefix_list_egress_test"
|
|
}
|
|
}
|
|
|
|
resource "aws_route_table" "default" {
|
|
vpc_id = "${aws_vpc.tf_sg_prefix_list_egress_test.id}"
|
|
}
|
|
|
|
resource "aws_vpc_endpoint" "s3-us-west-2" {
|
|
vpc_id = "${aws_vpc.tf_sg_prefix_list_egress_test.id}"
|
|
service_name = "com.amazonaws.us-west-2.s3"
|
|
route_table_ids = ["${aws_route_table.default.id}"]
|
|
policy = <<POLICY
|
|
{
|
|
"Version": "2012-10-17",
|
|
"Statement": [
|
|
{
|
|
"Sid":"AllowAll",
|
|
"Effect":"Allow",
|
|
"Principal":"*",
|
|
"Action":"*",
|
|
"Resource":"*"
|
|
}
|
|
]
|
|
}
|
|
POLICY
|
|
}
|
|
|
|
resource "aws_security_group" "egress" {
|
|
name = "terraform_acceptance_test_prefix_list_egress"
|
|
description = "Used in the terraform acceptance tests"
|
|
vpc_id = "${aws_vpc.tf_sg_prefix_list_egress_test.id}"
|
|
}
|
|
|
|
resource "aws_security_group_rule" "egress_1" {
|
|
type = "egress"
|
|
protocol = "-1"
|
|
from_port = 0
|
|
to_port = 0
|
|
prefix_list_ids = ["${aws_vpc_endpoint.s3-us-west-2.prefix_list_id}"]
|
|
security_group_id = "${aws_security_group.egress.id}"
|
|
}
|
|
`
|
|
|
|
func testAccAWSSecurityGroupRuleSelfInSource(rInt int) string {
|
|
return fmt.Sprintf(`
|
|
resource "aws_vpc" "foo" {
|
|
cidr_block = "10.1.0.0/16"
|
|
|
|
tags {
|
|
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)
|
|
}
|
|
|
|
func testAccAWSSecurityGroupRuleExpectInvalidType(rInt int) string {
|
|
return fmt.Sprintf(`
|
|
resource "aws_vpc" "foo" {
|
|
cidr_block = "10.1.0.0/16"
|
|
|
|
tags {
|
|
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 = "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)
|
|
}
|
|
|
|
func testAccAWSSecurityGroupRuleInvalidIPv4CIDR(rInt int) string {
|
|
return fmt.Sprintf(`
|
|
resource "aws_security_group" "foo" {
|
|
name = "testing-failure-%d"
|
|
}
|
|
|
|
resource "aws_security_group_rule" "ing" {
|
|
type = "ingress"
|
|
from_port = 0
|
|
to_port = 0
|
|
protocol = "-1"
|
|
cidr_blocks = ["1.2.3.4/33"]
|
|
security_group_id = "${aws_security_group.foo.id}"
|
|
}`, rInt)
|
|
}
|
|
|
|
func testAccAWSSecurityGroupRuleInvalidIPv6CIDR(rInt int) string {
|
|
return fmt.Sprintf(`
|
|
resource "aws_security_group" "foo" {
|
|
name = "testing-failure-%d"
|
|
}
|
|
|
|
resource "aws_security_group_rule" "ing" {
|
|
type = "egress"
|
|
from_port = 0
|
|
to_port = 0
|
|
protocol = "-1"
|
|
ipv6_cidr_blocks = ["::/244"]
|
|
security_group_id = "${aws_security_group.foo.id}"
|
|
}`, rInt)
|
|
}
|