-
Notifications
You must be signed in to change notification settings - Fork 9.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Initial Scaffolding of the AWS Network ACL Entry resource
- Loading branch information
Showing
2 changed files
with
199 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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())) | ||
} |