provider/aws: Add support for IPv6 to aws_security_group_rule (#12645)

```
% make testacc TEST=./builtin/providers/aws TESTARGS='-run=TestAccAWSSecurityGroupRule_'         ✹ ✭
==> Checking that code complies with gofmt requirements...
go generate $(go list ./... | grep -v /terraform/vendor/)
2017/03/13 15:40:39 Generated command/internal_plugin_list.go
TF_ACC=1 go test ./builtin/providers/aws -v -run=TestAccAWSSecurityGroupRule_ -timeout 120m
=== RUN   TestAccAWSSecurityGroupRule_Ingress_VPC
--- PASS: TestAccAWSSecurityGroupRule_Ingress_VPC (53.36s)
=== RUN   TestAccAWSSecurityGroupRule_Ingress_Protocol
--- PASS: TestAccAWSSecurityGroupRule_Ingress_Protocol (85.22s)
=== RUN   TestAccAWSSecurityGroupRule_Ingress_Ipv6
--- PASS: TestAccAWSSecurityGroupRule_Ingress_Ipv6 (87.55s)
=== RUN   TestAccAWSSecurityGroupRule_Ingress_Classic
--- PASS: TestAccAWSSecurityGroupRule_Ingress_Classic (50.58s)
=== RUN   TestAccAWSSecurityGroupRule_MultiIngress
--- PASS: TestAccAWSSecurityGroupRule_MultiIngress (47.98s)
=== RUN   TestAccAWSSecurityGroupRule_Egress
--- PASS: TestAccAWSSecurityGroupRule_Egress (50.48s)
=== RUN   TestAccAWSSecurityGroupRule_SelfReference
--- PASS: TestAccAWSSecurityGroupRule_SelfReference (82.45s)
=== RUN   TestAccAWSSecurityGroupRule_ExpectInvalidTypeError
--- PASS: TestAccAWSSecurityGroupRule_ExpectInvalidTypeError (0.01s)
=== RUN   TestAccAWSSecurityGroupRule_PartialMatching_basic
--- PASS: TestAccAWSSecurityGroupRule_PartialMatching_basic (95.55s)
=== RUN   TestAccAWSSecurityGroupRule_PartialMatching_Source
--- PASS: TestAccAWSSecurityGroupRule_PartialMatching_Source (95.65s)
=== RUN   TestAccAWSSecurityGroupRule_Issue5310
--- PASS: TestAccAWSSecurityGroupRule_Issue5310 (45.91s)
=== RUN   TestAccAWSSecurityGroupRule_Race
--- PASS: TestAccAWSSecurityGroupRule_Race (697.79s)
=== RUN   TestAccAWSSecurityGroupRule_SelfSource
--- PASS: TestAccAWSSecurityGroupRule_SelfSource (96.19s)
=== RUN   TestAccAWSSecurityGroupRule_PrefixListEgress
--- PASS: TestAccAWSSecurityGroupRule_PrefixListEgress (97.51s)
PASS
ok  	github.com/hashicorp/terraform/builtin/providers/aws	1586.248s
```
This commit is contained in:
Paul Stack 2017-03-14 12:37:59 +02:00 committed by GitHub
parent 9fe61d0f1e
commit d87cc0721f
3 changed files with 130 additions and 10 deletions

View File

@ -61,6 +61,13 @@ func resourceAwsSecurityGroupRule() *schema.Resource {
Elem: &schema.Schema{Type: schema.TypeString}, Elem: &schema.Schema{Type: schema.TypeString},
}, },
"ipv6_cidr_blocks": {
Type: schema.TypeList,
Optional: true,
ForceNew: true,
Elem: &schema.Schema{Type: schema.TypeString},
},
"prefix_list_ids": { "prefix_list_ids": {
Type: schema.TypeList, Type: schema.TypeList,
Optional: true, Optional: true,
@ -400,6 +407,19 @@ func findRuleMatch(p *ec2.IpPermission, rules []*ec2.IpPermission, isVPC bool) *
continue continue
} }
remaining = len(p.Ipv6Ranges)
for _, ipv6 := range p.Ipv6Ranges {
for _, ipv6ip := range r.Ipv6Ranges {
if *ipv6.CidrIpv6 == *ipv6ip.CidrIpv6 {
remaining--
}
}
}
if remaining > 0 {
continue
}
remaining = len(p.PrefixListIds) remaining = len(p.PrefixListIds)
for _, pl := range p.PrefixListIds { for _, pl := range p.PrefixListIds {
for _, rpl := range r.PrefixListIds { for _, rpl := range r.PrefixListIds {
@ -463,6 +483,18 @@ func ipPermissionIDHash(sg_id, ruleType string, ip *ec2.IpPermission) string {
} }
} }
if len(ip.Ipv6Ranges) > 0 {
s := make([]string, len(ip.Ipv6Ranges))
for i, r := range ip.Ipv6Ranges {
s[i] = *r.CidrIpv6
}
sort.Strings(s)
for _, v := range s {
buf.WriteString(fmt.Sprintf("%s-", v))
}
}
if len(ip.PrefixListIds) > 0 { if len(ip.PrefixListIds) > 0 {
s := make([]string, len(ip.PrefixListIds)) s := make([]string, len(ip.PrefixListIds))
for i, pl := range ip.PrefixListIds { for i, pl := range ip.PrefixListIds {
@ -555,6 +587,18 @@ func expandIPPerm(d *schema.ResourceData, sg *ec2.SecurityGroup) (*ec2.IpPermiss
} }
} }
if raw, ok := d.GetOk("ipv6_cidr_blocks"); ok {
list := raw.([]interface{})
perm.Ipv6Ranges = make([]*ec2.Ipv6Range, len(list))
for i, v := range list {
cidrIP, ok := v.(string)
if !ok {
return nil, fmt.Errorf("empty element found in ipv6_cidr_blocks - consider using the compact function")
}
perm.Ipv6Ranges[i] = &ec2.Ipv6Range{CidrIpv6: aws.String(cidrIP)}
}
}
if raw, ok := d.GetOk("prefix_list_ids"); ok { if raw, ok := d.GetOk("prefix_list_ids"); ok {
list := raw.([]interface{}) list := raw.([]interface{})
perm.PrefixListIds = make([]*ec2.PrefixListId, len(list)) perm.PrefixListIds = make([]*ec2.PrefixListId, len(list))
@ -584,6 +628,12 @@ func setFromIPPerm(d *schema.ResourceData, sg *ec2.SecurityGroup, rule *ec2.IpPe
d.Set("cidr_blocks", cb) d.Set("cidr_blocks", cb)
var ipv6 []string
for _, ip := range rule.Ipv6Ranges {
ipv6 = append(ipv6, *ip.CidrIpv6)
}
d.Set("ipv6_cidr_blocks", ipv6)
var pl []string var pl []string
for _, p := range rule.PrefixListIds { for _, p := range rule.PrefixListIds {
pl = append(pl, *p.PrefixListId) pl = append(pl, *p.PrefixListId)
@ -603,15 +653,16 @@ func setFromIPPerm(d *schema.ResourceData, sg *ec2.SecurityGroup, rule *ec2.IpPe
return nil return nil
} }
// Validates that either 'cidr_blocks', 'self', or 'source_security_group_id' is set // Validates that either 'cidr_blocks', 'ipv6_cidr_blocks', 'self', or 'source_security_group_id' is set
func validateAwsSecurityGroupRule(d *schema.ResourceData) error { func validateAwsSecurityGroupRule(d *schema.ResourceData) error {
_, blocksOk := d.GetOk("cidr_blocks") _, blocksOk := d.GetOk("cidr_blocks")
_, ipv6Ok := d.GetOk("ipv6_cidr_blocks")
_, sourceOk := d.GetOk("source_security_group_id") _, sourceOk := d.GetOk("source_security_group_id")
_, selfOk := d.GetOk("self") _, selfOk := d.GetOk("self")
_, prefixOk := d.GetOk("prefix_list_ids") _, prefixOk := d.GetOk("prefix_list_ids")
if !blocksOk && !sourceOk && !selfOk && !prefixOk { if !blocksOk && !sourceOk && !selfOk && !prefixOk && !ipv6Ok {
return fmt.Errorf( return fmt.Errorf(
"One of ['cidr_blocks', 'self', 'source_security_group_id', 'prefix_list_ids'] must be set to create an AWS Security Group Rule") "One of ['cidr_blocks', 'ipv6_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

@ -52,15 +52,15 @@ func TestIpPermissionIDHash(t *testing.T) {
FromPort: aws.Int64(int64(80)), FromPort: aws.Int64(int64(80)),
ToPort: aws.Int64(int64(8000)), ToPort: aws.Int64(int64(8000)),
UserIdGroupPairs: []*ec2.UserIdGroupPair{ UserIdGroupPairs: []*ec2.UserIdGroupPair{
&ec2.UserIdGroupPair{ {
UserId: aws.String("987654321"), UserId: aws.String("987654321"),
GroupId: aws.String("sg-12345678"), GroupId: aws.String("sg-12345678"),
}, },
&ec2.UserIdGroupPair{ {
UserId: aws.String("123456789"), UserId: aws.String("123456789"),
GroupId: aws.String("sg-987654321"), GroupId: aws.String("sg-987654321"),
}, },
&ec2.UserIdGroupPair{ {
UserId: aws.String("123456789"), UserId: aws.String("123456789"),
GroupId: aws.String("sg-12345678"), GroupId: aws.String("sg-12345678"),
}, },
@ -72,15 +72,15 @@ func TestIpPermissionIDHash(t *testing.T) {
FromPort: aws.Int64(int64(80)), FromPort: aws.Int64(int64(80)),
ToPort: aws.Int64(int64(8000)), ToPort: aws.Int64(int64(8000)),
UserIdGroupPairs: []*ec2.UserIdGroupPair{ UserIdGroupPairs: []*ec2.UserIdGroupPair{
&ec2.UserIdGroupPair{ {
UserId: aws.String("987654321"), UserId: aws.String("987654321"),
GroupName: aws.String("my-security-group"), GroupName: aws.String("my-security-group"),
}, },
&ec2.UserIdGroupPair{ {
UserId: aws.String("123456789"), UserId: aws.String("123456789"),
GroupName: aws.String("my-security-group"), GroupName: aws.String("my-security-group"),
}, },
&ec2.UserIdGroupPair{ {
UserId: aws.String("123456789"), UserId: aws.String("123456789"),
GroupName: aws.String("my-other-security-group"), GroupName: aws.String("my-other-security-group"),
}, },
@ -183,6 +183,46 @@ func TestAccAWSSecurityGroupRule_Ingress_Protocol(t *testing.T) {
}) })
} }
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) { func TestAccAWSSecurityGroupRule_Ingress_Classic(t *testing.T) {
var group ec2.SecurityGroup var group ec2.SecurityGroup
rInt := acctest.RandInt() rInt := acctest.RandInt()
@ -376,7 +416,7 @@ func TestAccAWSSecurityGroupRule_PartialMatching_Source(t *testing.T) {
ToPort: aws.Int64(80), ToPort: aws.Int64(80),
IpProtocol: aws.String("tcp"), IpProtocol: aws.String("tcp"),
UserIdGroupPairs: []*ec2.UserIdGroupPair{ UserIdGroupPairs: []*ec2.UserIdGroupPair{
&ec2.UserIdGroupPair{GroupId: nat.GroupId}, {GroupId: nat.GroupId},
}, },
} }
@ -696,6 +736,34 @@ func testAccAWSSecurityGroupRuleIngressConfig(rInt int) string {
}`, rInt) }`, 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 = ` 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"

View File

@ -42,6 +42,7 @@ The following arguments are supported:
* `type` - (Required) The type of rule being created. Valid options are `ingress` (inbound) * `type` - (Required) The type of rule being created. Valid options are `ingress` (inbound)
or `egress` (outbound). or `egress` (outbound).
* `cidr_blocks` - (Optional) List of CIDR blocks. Cannot be specified with `source_security_group_id`. * `cidr_blocks` - (Optional) List of CIDR blocks. Cannot be specified with `source_security_group_id`.
* `ipv6_cidr_blocks` - (Optional) List of IPv6 CIDR blocks.
* `prefix_list_ids` - (Optional) List of prefix list IDs (for allowing access to VPC endpoints). * `prefix_list_ids` - (Optional) List of prefix list IDs (for allowing access to VPC endpoints).
Only valid with `egress`. Only valid with `egress`.
* `from_port` - (Required) The start port (or ICMP type number if protocol is "icmp"). * `from_port` - (Required) The start port (or ICMP type number if protocol is "icmp").