Skip to content

Commit

Permalink
Initial Scaffolding of the AWS Network ACL Entry resource
Browse files Browse the repository at this point in the history
  • Loading branch information
stack72 committed Dec 13, 2015
1 parent 38b125a commit 91ccdf1
Show file tree
Hide file tree
Showing 2 changed files with 199 additions and 0 deletions.
1 change: 1 addition & 0 deletions builtin/providers/aws/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,7 @@ func Provider() terraform.ResourceProvider {
"aws_lb_cookie_stickiness_policy": resourceAwsLBCookieStickinessPolicy(),
"aws_main_route_table_association": resourceAwsMainRouteTableAssociation(),
"aws_network_acl": resourceAwsNetworkAcl(),
"aws_network_acl_rule": resourceAwsNetworkAclRule(),
"aws_network_interface": resourceAwsNetworkInterface(),
"aws_opsworks_stack": resourceAwsOpsworksStack(),
"aws_opsworks_java_app_layer": resourceAwsOpsworksJavaAppLayer(),
Expand Down
198 changes: 198 additions & 0 deletions builtin/providers/aws/resource_aws_network_acl_rule.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,198 @@
package aws

import (
"bytes"
"fmt"
"log"

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/ec2"
"github.com/hashicorp/terraform/helper/hashcode"
"github.com/hashicorp/terraform/helper/schema"
)

func resourceAwsNetworkAclRule() *schema.Resource {
return &schema.Resource{
Create: resourceAwsNetworkAclRuleCreate,
Read: resourceAwsNetworkAclRuleRead,
Delete: resourceAwsNetworkAclRuleDelete,

Schema: map[string]*schema.Schema{
"network_acl_id": &schema.Schema{
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"rule_number": &schema.Schema{
Type: schema.TypeInt,
Required: true,
ForceNew: true,
},
"egress": &schema.Schema{
Type: schema.TypeBool,
Optional: true,
ForceNew: true,
Default: false,
},
"protocol": &schema.Schema{
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"rule_action": &schema.Schema{
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"cidr_block": &schema.Schema{
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"from_port": &schema.Schema{
Type: schema.TypeInt,
Optional: true,
ForceNew: true,
},
"to_port": &schema.Schema{
Type: schema.TypeInt,
Optional: true,
ForceNew: true,
},
"icmp_type": &schema.Schema{
Type: schema.TypeInt,
Optional: true,
ForceNew: true,
},
"icmp_code": &schema.Schema{
Type: schema.TypeInt,
Optional: true,
ForceNew: true,
},
},
}
}

func resourceAwsNetworkAclRuleCreate(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AWSClient).ec2conn
params := &ec2.CreateNetworkAclEntryInput{
NetworkAclId: aws.String(d.Get("network_acl_id").(string)),
Egress: aws.Bool(d.Get("egress").(bool)),
RuleNumber: aws.Int64(int64(d.Get("rule_number").(int))),
Protocol: aws.String(d.Get("protocol").(string)),
CidrBlock: aws.String(d.Get("cidr_block").(string)),
RuleAction: aws.String(d.Get("rule_action").(string)),
}

_, fromOk := d.Get("from_port").(int)
_, toOk := d.Get("to_port").(int)
if fromOk && toOk {
params.PortRange = &ec2.PortRange{
From: aws.Int64(int64(d.Get("from_port").(int))),
To: aws.Int64(int64(d.Get("to_port").(int))),
}
}

_, icmpTypeOk := d.Get("icmp_type").(int)
_, icmpCodeOk := d.Get("icmp_code").(int)
if icmpTypeOk && icmpCodeOk {
params.IcmpTypeCode = &ec2.IcmpTypeCode{
Type: aws.Int64(int64(d.Get("icmp_type").(int))),
Code: aws.Int64(int64(d.Get("icmp_code").(int))),
}
}

log.Printf("[INFO] Creating Network Acl Rule: %d (%s)", d.Get("rule_number").(int), d.Get("egress").(bool))
_, err := conn.CreateNetworkAclEntry(params)
if err != nil {
return fmt.Errorf("Error Creating Network Acl Rule: %s", err.Error())
}
d.SetId(networkAclIdRuleNumberEgressHash(d.Get("network_acl_id").(string), d.Get("rule_number").(int), d.Get("egress").(bool)))
return resourceAwsNetworkAclRuleRead(d, meta)
}

func resourceAwsNetworkAclRuleRead(d *schema.ResourceData, meta interface{}) error {
resp, err := findNetworkAclRule(d, meta)
if err != nil {
return err
}

d.Set("rule_number", resp.RuleNumber)
d.Set("cidr_block", resp.CidrBlock)
d.Set("egress", resp.Egress)
d.Set("icmp_code", resp.IcmpTypeCode.Code)
d.Set("icmp_type", resp.IcmpTypeCode.Type)
d.Set("from_port", resp.PortRange.From)
d.Set("to_port", resp.PortRange.To)
d.Set("rule_action", resp.RuleAction)
d.Set("protocol", resp.Protocol)

return nil
}

func resourceAwsNetworkAclRuleDelete(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AWSClient).ec2conn

params := &ec2.DeleteNetworkAclEntryInput{
NetworkAclId: aws.String(d.Get("network_acl_id").(string)),
RuleNumber: aws.Int64(int64(d.Get("rule_number").(int))),
Egress: aws.Bool(d.Get("egress").(bool)),
}

log.Printf("[INFO] Deleting Network Acl Rule: %s", d.Id())
_, err := conn.DeleteNetworkAclEntry(params)
if err != nil {
return fmt.Errorf("Error Deleting Network Acl Rule: %s", err.Error())
}

return nil
}

func findNetworkAclRule(d *schema.ResourceData, meta interface{}) (*ec2.NetworkAclEntry, error) {
conn := meta.(*AWSClient).ec2conn

filters := make([]*ec2.Filter, 0, 2)
ruleNumberFilter := &ec2.Filter{
Name: aws.String("entry.rule-number"),
Values: []*string{aws.String(fmt.Sprintf("%v", d.Get("rule_number").(int)))},
}
filters = append(filters, ruleNumberFilter)
egressFilter := &ec2.Filter{
Name: aws.String("entry.egress"),
Values: []*string{aws.String(fmt.Sprintf("%v", d.Get("egress").(bool)))},
}
filters = append(filters, egressFilter)
params := &ec2.DescribeNetworkAclsInput{
NetworkAclIds: []*string{aws.String(d.Get("network_acl_id").(string))},
Filters: filters,
}

log.Printf("[INFO] Describing Network Acl: %s", d.Get("network_acl_id").(string))
resp, err := conn.DescribeNetworkAcls(params)
if err != nil {
return nil, fmt.Errorf("Error Finding Network Acl Rule %d: %s", d.Get("rule_number").(int), err.Error())
}

if resp == nil || len(resp.NetworkAcls) != 1 || resp.NetworkAcls[0] == nil {
return nil, fmt.Errorf(
"Expected to find one Network ACL, got: %#v",
resp.NetworkAcls)
}
networkAcl := resp.NetworkAcls[0]
if len(networkAcl.Entries) != 1 || networkAcl.Entries[0] == nil {
return nil, fmt.Errorf(
"Expected Network ACL to have a Network ACL Rule, got: %#v",
networkAcl.Entries)

}
return networkAcl.Entries[0], nil

}

func networkAclIdRuleNumberEgressHash(networkAclId string, ruleNumber int, egress bool) string {
var buf bytes.Buffer
buf.WriteString(fmt.Sprintf("%s-", networkAclId))
buf.WriteString(fmt.Sprintf("%d-", ruleNumber))
buf.WriteString(fmt.Sprintf("%t-", egress))
return fmt.Sprintf("nacl-%d", hashcode.String(buf.String()))
}

0 comments on commit 91ccdf1

Please sign in to comment.