terraform/builtin/providers/aws/network_acl_entry.go

125 lines
3.1 KiB
Go

package aws
import (
"fmt"
"net"
"strconv"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/ec2"
)
func expandNetworkAclEntries(configured []interface{}, entryType string) ([]*ec2.NetworkAclEntry, error) {
entries := make([]*ec2.NetworkAclEntry, 0, len(configured))
for _, eRaw := range configured {
data := eRaw.(map[string]interface{})
protocol := data["protocol"].(string)
p, err := strconv.Atoi(protocol)
if err != nil {
var ok bool
p, ok = protocolIntegers()[protocol]
if !ok {
return nil, fmt.Errorf("Invalid Protocol %s for rule %#v", protocol, data)
}
}
e := &ec2.NetworkAclEntry{
Protocol: aws.String(strconv.Itoa(p)),
PortRange: &ec2.PortRange{
From: aws.Int64(int64(data["from_port"].(int))),
To: aws.Int64(int64(data["to_port"].(int))),
},
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)),
}
// Specify additional required fields for ICMP
if p == 1 {
e.IcmpTypeCode = &ec2.IcmpTypeCode{}
if v, ok := data["icmp_code"]; ok {
e.IcmpTypeCode.Code = aws.Int64(int64(v.(int)))
}
if v, ok := data["icmp_type"]; ok {
e.IcmpTypeCode.Type = aws.Int64(int64(v.(int)))
}
}
entries = append(entries, e)
}
return entries, nil
}
func flattenNetworkAclEntries(list []*ec2.NetworkAclEntry) []map[string]interface{} {
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,
})
}
return entries
}
func protocolStrings(protocolIntegers map[string]int) map[int]string {
protocolStrings := make(map[int]string, len(protocolIntegers))
for k, v := range protocolIntegers {
protocolStrings[v] = k
}
return protocolStrings
}
func protocolIntegers() map[string]int {
var protocolIntegers = make(map[string]int)
protocolIntegers = map[string]int{
// defined at https://www.iana.org/assignments/protocol-numbers/protocol-numbers.xhtml
"ah": 51,
"esp": 50,
"udp": 17,
"tcp": 6,
"icmp": 1,
"all": -1,
"vrrp": 112,
}
return protocolIntegers
}
// expectedPortPair stores a pair of ports we expect to see together.
type expectedPortPair struct {
to_port int64
from_port int64
}
// validatePorts ensures the ports and protocol match expected
// values.
func validatePorts(to int64, from int64, expected expectedPortPair) bool {
if to != expected.to_port || from != expected.from_port {
return false
}
return true
}
// validateCIDRBlock ensures the passed CIDR block represents an implied
// network, and not an overly-specified IP address.
func validateCIDRBlock(cidr string) error {
_, ipnet, err := net.ParseCIDR(cidr)
if err != nil {
return err
}
if ipnet.String() != cidr {
return fmt.Errorf("%s is not a valid mask; did you mean %s?", cidr, ipnet)
}
return nil
}