Skip to content

Commit

Permalink
provider/aws: Add support for IPv6 to aws_network_acl (#12641)
Browse files Browse the repository at this point in the history
```
% make testacc TEST=./builtin/providers/aws TESTARGS='-run=TestAccAWSNetworkAcl_'              2 ↵ ✭
==> Checking that code complies with gofmt requirements...
go generate $(go list ./... | grep -v /terraform/vendor/)
2017/03/13 14:04:41 Generated command/internal_plugin_list.go
TF_ACC=1 go test ./builtin/providers/aws -v -run=TestAccAWSNetworkAcl_ -timeout 120m
=== RUN   TestAccAWSNetworkAcl_importBasic
--- PASS: TestAccAWSNetworkAcl_importBasic (55.44s)
=== RUN   TestAccAWSNetworkAcl_EgressAndIngressRules
--- PASS: TestAccAWSNetworkAcl_EgressAndIngressRules (48.19s)
=== RUN   TestAccAWSNetworkAcl_OnlyIngressRules_basic
--- PASS: TestAccAWSNetworkAcl_OnlyIngressRules_basic (65.29s)
=== RUN   TestAccAWSNetworkAcl_OnlyIngressRules_update
--- PASS: TestAccAWSNetworkAcl_OnlyIngressRules_update (103.19s)
=== RUN   TestAccAWSNetworkAcl_OnlyEgressRules
--- PASS: TestAccAWSNetworkAcl_OnlyEgressRules (59.65s)
=== RUN   TestAccAWSNetworkAcl_SubnetChange
--- PASS: TestAccAWSNetworkAcl_SubnetChange (93.90s)
=== RUN   TestAccAWSNetworkAcl_Subnets
--- PASS: TestAccAWSNetworkAcl_Subnets (103.51s)
=== RUN   TestAccAWSNetworkAcl_ipv6Rules
--- PASS: TestAccAWSNetworkAcl_ipv6Rules (56.67s)
=== RUN   TestAccAWSNetworkAcl_espProtocol
--- PASS: TestAccAWSNetworkAcl_espProtocol (51.40s)
PASS
ok  	github.com/hashicorp/terraform/builtin/providers/aws	637.283s
```
  • Loading branch information
stack72 authored Mar 14, 2017
1 parent 1cd566e commit ff7df7b
Show file tree
Hide file tree
Showing 4 changed files with 199 additions and 95 deletions.
35 changes: 26 additions & 9 deletions builtin/providers/aws/network_acl_entry.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,14 @@ func expandNetworkAclEntries(configured []interface{}, entryType string) ([]*ec2
Egress: aws.Bool(entryType == "egress"),
RuleAction: aws.String(data["action"].(string)),
RuleNumber: aws.Int64(int64(data["rule_no"].(int))),
CidrBlock: aws.String(data["cidr_block"].(string)),
}

if v, ok := data["ipv6_cidr_block"]; ok {
e.Ipv6CidrBlock = aws.String(v.(string))
}

if v, ok := data["cidr_block"]; ok {
e.CidrBlock = aws.String(v.(string))
}

// Specify additional required fields for ICMP
Expand All @@ -55,14 +62,24 @@ func flattenNetworkAclEntries(list []*ec2.NetworkAclEntry) []map[string]interfac
entries := make([]map[string]interface{}, 0, len(list))

for _, entry := range list {
entries = append(entries, map[string]interface{}{
"from_port": *entry.PortRange.From,
"to_port": *entry.PortRange.To,
"action": *entry.RuleAction,
"rule_no": *entry.RuleNumber,
"protocol": *entry.Protocol,
"cidr_block": *entry.CidrBlock,
})

newEntry := map[string]interface{}{
"from_port": *entry.PortRange.From,
"to_port": *entry.PortRange.To,
"action": *entry.RuleAction,
"rule_no": *entry.RuleNumber,
"protocol": *entry.Protocol,
}

if entry.CidrBlock != nil {
newEntry["cidr_block"] = *entry.CidrBlock
}

if entry.Ipv6CidrBlock != nil {
newEntry["ipv6_cidr_block"] = *entry.Ipv6CidrBlock
}

entries = append(entries, newEntry)
}

return entries
Expand Down
103 changes: 66 additions & 37 deletions builtin/providers/aws/resource_aws_network_acl.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,106 +28,114 @@ func resourceAwsNetworkAcl() *schema.Resource {
},

Schema: map[string]*schema.Schema{
"vpc_id": &schema.Schema{
"vpc_id": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
Computed: false,
},
"subnet_id": &schema.Schema{
"subnet_id": {
Type: schema.TypeString,
Optional: true,
ForceNew: true,
Computed: false,
Deprecated: "Attribute subnet_id is deprecated on network_acl resources. Use subnet_ids instead",
},
"subnet_ids": &schema.Schema{
"subnet_ids": {
Type: schema.TypeSet,
Optional: true,
Computed: true,
ConflictsWith: []string{"subnet_id"},
Elem: &schema.Schema{Type: schema.TypeString},
Set: schema.HashString,
},
"ingress": &schema.Schema{
"ingress": {
Type: schema.TypeSet,
Required: false,
Optional: true,
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"from_port": &schema.Schema{
"from_port": {
Type: schema.TypeInt,
Required: true,
},
"to_port": &schema.Schema{
"to_port": {
Type: schema.TypeInt,
Required: true,
},
"rule_no": &schema.Schema{
"rule_no": {
Type: schema.TypeInt,
Required: true,
},
"action": &schema.Schema{
"action": {
Type: schema.TypeString,
Required: true,
},
"protocol": &schema.Schema{
"protocol": {
Type: schema.TypeString,
Required: true,
},
"cidr_block": &schema.Schema{
"cidr_block": {
Type: schema.TypeString,
Optional: true,
},
"icmp_type": &schema.Schema{
"ipv6_cidr_block": {
Type: schema.TypeString,
Optional: true,
},
"icmp_type": {
Type: schema.TypeInt,
Optional: true,
},
"icmp_code": &schema.Schema{
"icmp_code": {
Type: schema.TypeInt,
Optional: true,
},
},
},
Set: resourceAwsNetworkAclEntryHash,
},
"egress": &schema.Schema{
"egress": {
Type: schema.TypeSet,
Required: false,
Optional: true,
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"from_port": &schema.Schema{
"from_port": {
Type: schema.TypeInt,
Required: true,
},
"to_port": &schema.Schema{
"to_port": {
Type: schema.TypeInt,
Required: true,
},
"rule_no": &schema.Schema{
"rule_no": {
Type: schema.TypeInt,
Required: true,
},
"action": &schema.Schema{
"action": {
Type: schema.TypeString,
Required: true,
},
"protocol": &schema.Schema{
"protocol": {
Type: schema.TypeString,
Required: true,
},
"cidr_block": &schema.Schema{
"cidr_block": {
Type: schema.TypeString,
Optional: true,
},
"icmp_type": &schema.Schema{
"ipv6_cidr_block": {
Type: schema.TypeString,
Optional: true,
},
"icmp_type": {
Type: schema.TypeInt,
Optional: true,
},
"icmp_code": &schema.Schema{
"icmp_code": {
Type: schema.TypeInt,
Optional: true,
},
Expand Down Expand Up @@ -389,25 +397,36 @@ func updateNetworkAclEntries(d *schema.ResourceData, entryType string, conn *ec2
}
}

// AWS mutates the CIDR block into a network implied by the IP and
// mask provided. This results in hashing inconsistencies between
// the local config file and the state returned by the API. Error
// if the user provides a CIDR block with an inappropriate mask
if err := validateCIDRBlock(*add.CidrBlock); err != nil {
return err
if add.CidrBlock != nil {
// AWS mutates the CIDR block into a network implied by the IP and
// mask provided. This results in hashing inconsistencies between
// the local config file and the state returned by the API. Error
// if the user provides a CIDR block with an inappropriate mask
if err := validateCIDRBlock(*add.CidrBlock); err != nil {
return err
}
}

// Add new Acl entry
_, connErr := conn.CreateNetworkAclEntry(&ec2.CreateNetworkAclEntryInput{
createOpts := &ec2.CreateNetworkAclEntryInput{
NetworkAclId: aws.String(d.Id()),
CidrBlock: add.CidrBlock,
Egress: add.Egress,
PortRange: add.PortRange,
Protocol: add.Protocol,
RuleAction: add.RuleAction,
RuleNumber: add.RuleNumber,
IcmpTypeCode: add.IcmpTypeCode,
})
}

if add.CidrBlock != nil {
createOpts.CidrBlock = add.CidrBlock
}

if add.Ipv6CidrBlock != nil {
createOpts.Ipv6CidrBlock = add.Ipv6CidrBlock
}

// Add new Acl entry
_, connErr := conn.CreateNetworkAclEntry(createOpts)
if connErr != nil {
return fmt.Errorf("Error creating %s entry: %s", entryType, connErr)
}
Expand Down Expand Up @@ -520,7 +539,13 @@ func resourceAwsNetworkAclEntryHash(v interface{}) int {
buf.WriteString(fmt.Sprintf("%s-", protocol))
}

buf.WriteString(fmt.Sprintf("%s-", m["cidr_block"].(string)))
if v, ok := m["cidr_block"]; ok {
buf.WriteString(fmt.Sprintf("%s-", v.(string)))
}

if v, ok := m["ipv6_cidr_block"]; ok {
buf.WriteString(fmt.Sprintf("%s-", v.(string)))
}

if v, ok := m["ssl_certificate_id"]; ok {
buf.WriteString(fmt.Sprintf("%s-", v.(string)))
Expand All @@ -539,11 +564,11 @@ func resourceAwsNetworkAclEntryHash(v interface{}) int {
func getDefaultNetworkAcl(vpc_id string, conn *ec2.EC2) (defaultAcl *ec2.NetworkAcl, err error) {
resp, err := conn.DescribeNetworkAcls(&ec2.DescribeNetworkAclsInput{
Filters: []*ec2.Filter{
&ec2.Filter{
{
Name: aws.String("default"),
Values: []*string{aws.String("true")},
},
&ec2.Filter{
{
Name: aws.String("vpc-id"),
Values: []*string{aws.String(vpc_id)},
},
Expand All @@ -559,7 +584,7 @@ func getDefaultNetworkAcl(vpc_id string, conn *ec2.EC2) (defaultAcl *ec2.Network
func findNetworkAclAssociation(subnetId string, conn *ec2.EC2) (networkAclAssociation *ec2.NetworkAclAssociation, err error) {
resp, err := conn.DescribeNetworkAcls(&ec2.DescribeNetworkAclsInput{
Filters: []*ec2.Filter{
&ec2.Filter{
{
Name: aws.String("association.subnet-id"),
Values: []*string{aws.String(subnetId)},
},
Expand Down Expand Up @@ -587,8 +612,12 @@ func networkAclEntriesToMapList(networkAcls []*ec2.NetworkAclEntry) []map[string
acl := make(map[string]interface{})
acl["rule_no"] = *entry.RuleNumber
acl["action"] = *entry.RuleAction
acl["cidr_block"] = *entry.CidrBlock

if entry.CidrBlock != nil {
acl["cidr_block"] = *entry.CidrBlock
}
if entry.Ipv6CidrBlock != nil {
acl["ipv6_cidr_block"] = *entry.Ipv6CidrBlock
}
// The AWS network ACL API only speaks protocol numbers, and
// that's all we record.
if _, err := strconv.Atoi(*entry.Protocol); err != nil {
Expand Down
Loading

0 comments on commit ff7df7b

Please sign in to comment.