github.com/leeprovoost/terraform@v0.6.10-0.20160119085442-96f3f76118e7/builtin/providers/aws/resource_aws_network_acl_rule.go (about) 1 package aws 2 3 import ( 4 "bytes" 5 "fmt" 6 "log" 7 "strconv" 8 9 "github.com/aws/aws-sdk-go/aws" 10 "github.com/aws/aws-sdk-go/service/ec2" 11 "github.com/hashicorp/terraform/helper/hashcode" 12 "github.com/hashicorp/terraform/helper/schema" 13 ) 14 15 func resourceAwsNetworkAclRule() *schema.Resource { 16 return &schema.Resource{ 17 Create: resourceAwsNetworkAclRuleCreate, 18 Read: resourceAwsNetworkAclRuleRead, 19 Delete: resourceAwsNetworkAclRuleDelete, 20 21 Schema: map[string]*schema.Schema{ 22 "network_acl_id": &schema.Schema{ 23 Type: schema.TypeString, 24 Required: true, 25 ForceNew: true, 26 }, 27 "rule_number": &schema.Schema{ 28 Type: schema.TypeInt, 29 Required: true, 30 ForceNew: true, 31 }, 32 "egress": &schema.Schema{ 33 Type: schema.TypeBool, 34 Optional: true, 35 ForceNew: true, 36 Default: false, 37 }, 38 "protocol": &schema.Schema{ 39 Type: schema.TypeString, 40 Required: true, 41 ForceNew: true, 42 }, 43 "rule_action": &schema.Schema{ 44 Type: schema.TypeString, 45 Required: true, 46 ForceNew: true, 47 }, 48 "cidr_block": &schema.Schema{ 49 Type: schema.TypeString, 50 Required: true, 51 ForceNew: true, 52 }, 53 "from_port": &schema.Schema{ 54 Type: schema.TypeInt, 55 Optional: true, 56 ForceNew: true, 57 }, 58 "to_port": &schema.Schema{ 59 Type: schema.TypeInt, 60 Optional: true, 61 ForceNew: true, 62 }, 63 "icmp_type": &schema.Schema{ 64 Type: schema.TypeInt, 65 Optional: true, 66 ForceNew: true, 67 }, 68 "icmp_code": &schema.Schema{ 69 Type: schema.TypeInt, 70 Optional: true, 71 ForceNew: true, 72 }, 73 }, 74 } 75 } 76 77 func resourceAwsNetworkAclRuleCreate(d *schema.ResourceData, meta interface{}) error { 78 conn := meta.(*AWSClient).ec2conn 79 80 protocol := d.Get("protocol").(string) 81 p, protocolErr := strconv.Atoi(protocol) 82 if protocolErr != nil { 83 var ok bool 84 p, ok = protocolIntegers()[protocol] 85 if !ok { 86 return fmt.Errorf("Invalid Protocol %s for rule %#v", protocol, d.Get("rule_number").(int)) 87 } 88 } 89 log.Printf("[INFO] Transformed Protocol %s into %d", protocol, p) 90 91 params := &ec2.CreateNetworkAclEntryInput{ 92 NetworkAclId: aws.String(d.Get("network_acl_id").(string)), 93 Egress: aws.Bool(d.Get("egress").(bool)), 94 RuleNumber: aws.Int64(int64(d.Get("rule_number").(int))), 95 Protocol: aws.String(strconv.Itoa(p)), 96 CidrBlock: aws.String(d.Get("cidr_block").(string)), 97 RuleAction: aws.String(d.Get("rule_action").(string)), 98 PortRange: &ec2.PortRange{ 99 From: aws.Int64(int64(d.Get("from_port").(int))), 100 To: aws.Int64(int64(d.Get("to_port").(int))), 101 }, 102 } 103 104 // Specify additional required fields for ICMP 105 if p == 1 { 106 params.IcmpTypeCode = &ec2.IcmpTypeCode{} 107 if v, ok := d.GetOk("icmp_code"); ok { 108 params.IcmpTypeCode.Code = aws.Int64(int64(v.(int))) 109 } 110 if v, ok := d.GetOk("icmp_type"); ok { 111 params.IcmpTypeCode.Type = aws.Int64(int64(v.(int))) 112 } 113 } 114 115 log.Printf("[INFO] Creating Network Acl Rule: %d (%t)", d.Get("rule_number").(int), d.Get("egress").(bool)) 116 _, err := conn.CreateNetworkAclEntry(params) 117 if err != nil { 118 return fmt.Errorf("Error Creating Network Acl Rule: %s", err.Error()) 119 } 120 d.SetId(networkAclIdRuleNumberEgressHash(d.Get("network_acl_id").(string), d.Get("rule_number").(int), d.Get("egress").(bool), d.Get("protocol").(string))) 121 return resourceAwsNetworkAclRuleRead(d, meta) 122 } 123 124 func resourceAwsNetworkAclRuleRead(d *schema.ResourceData, meta interface{}) error { 125 resp, err := findNetworkAclRule(d, meta) 126 if err != nil { 127 return err 128 } 129 130 d.Set("rule_number", resp.RuleNumber) 131 d.Set("cidr_block", resp.CidrBlock) 132 d.Set("egress", resp.Egress) 133 if resp.IcmpTypeCode != nil { 134 d.Set("icmp_code", resp.IcmpTypeCode.Code) 135 d.Set("icmp_type", resp.IcmpTypeCode.Type) 136 } 137 if resp.PortRange != nil { 138 d.Set("from_port", resp.PortRange.From) 139 d.Set("to_port", resp.PortRange.To) 140 } 141 142 d.Set("rule_action", resp.RuleAction) 143 144 p, protocolErr := strconv.Atoi(*resp.Protocol) 145 log.Printf("[INFO] Converting the protocol %v", p) 146 if protocolErr == nil { 147 var ok bool 148 protocol, ok := protocolStrings(protocolIntegers())[p] 149 if !ok { 150 return fmt.Errorf("Invalid Protocol %s for rule %#v", *resp.Protocol, d.Get("rule_number").(int)) 151 } 152 log.Printf("[INFO] Transformed Protocol %s back into %s", *resp.Protocol, protocol) 153 d.Set("protocol", protocol) 154 } 155 156 return nil 157 } 158 159 func resourceAwsNetworkAclRuleDelete(d *schema.ResourceData, meta interface{}) error { 160 conn := meta.(*AWSClient).ec2conn 161 162 params := &ec2.DeleteNetworkAclEntryInput{ 163 NetworkAclId: aws.String(d.Get("network_acl_id").(string)), 164 RuleNumber: aws.Int64(int64(d.Get("rule_number").(int))), 165 Egress: aws.Bool(d.Get("egress").(bool)), 166 } 167 168 log.Printf("[INFO] Deleting Network Acl Rule: %s", d.Id()) 169 _, err := conn.DeleteNetworkAclEntry(params) 170 if err != nil { 171 return fmt.Errorf("Error Deleting Network Acl Rule: %s", err.Error()) 172 } 173 174 return nil 175 } 176 177 func findNetworkAclRule(d *schema.ResourceData, meta interface{}) (*ec2.NetworkAclEntry, error) { 178 conn := meta.(*AWSClient).ec2conn 179 180 filters := make([]*ec2.Filter, 0, 2) 181 ruleNumberFilter := &ec2.Filter{ 182 Name: aws.String("entry.rule-number"), 183 Values: []*string{aws.String(fmt.Sprintf("%v", d.Get("rule_number").(int)))}, 184 } 185 filters = append(filters, ruleNumberFilter) 186 egressFilter := &ec2.Filter{ 187 Name: aws.String("entry.egress"), 188 Values: []*string{aws.String(fmt.Sprintf("%v", d.Get("egress").(bool)))}, 189 } 190 filters = append(filters, egressFilter) 191 params := &ec2.DescribeNetworkAclsInput{ 192 NetworkAclIds: []*string{aws.String(d.Get("network_acl_id").(string))}, 193 Filters: filters, 194 } 195 196 log.Printf("[INFO] Describing Network Acl: %s", d.Get("network_acl_id").(string)) 197 log.Printf("[INFO] Describing Network Acl with the Filters %#v", params) 198 resp, err := conn.DescribeNetworkAcls(params) 199 if err != nil { 200 return nil, fmt.Errorf("Error Finding Network Acl Rule %d: %s", d.Get("rule_number").(int), err.Error()) 201 } 202 203 if resp == nil || len(resp.NetworkAcls) != 1 || resp.NetworkAcls[0] == nil { 204 return nil, fmt.Errorf( 205 "Expected to find one Network ACL, got: %#v", 206 resp.NetworkAcls) 207 } 208 networkAcl := resp.NetworkAcls[0] 209 if networkAcl.Entries != nil { 210 for _, i := range networkAcl.Entries { 211 if *i.RuleNumber == int64(d.Get("rule_number").(int)) && *i.Egress == d.Get("egress").(bool) { 212 return i, nil 213 } 214 } 215 } 216 return nil, fmt.Errorf( 217 "Expected the Network ACL to have Entries, got: %#v", 218 networkAcl) 219 220 } 221 222 func networkAclIdRuleNumberEgressHash(networkAclId string, ruleNumber int, egress bool, protocol string) string { 223 var buf bytes.Buffer 224 buf.WriteString(fmt.Sprintf("%s-", networkAclId)) 225 buf.WriteString(fmt.Sprintf("%d-", ruleNumber)) 226 buf.WriteString(fmt.Sprintf("%t-", egress)) 227 buf.WriteString(fmt.Sprintf("%s-", protocol)) 228 return fmt.Sprintf("nacl-%d", hashcode.String(buf.String())) 229 }