aws: Force users to use valid network masks on ACL ingress/egress

AWS will accept any overly-specific IP/mask combination, such as
10.1.2.2/24, but will store it by its implied network: 10.1.2.0/24.
This results in hashing errors, because the remote API will return
hashing results out of sync with the local configuration file.

Enforce a stricter API rule than AWS. Force users to use valid masks,
and run a quick calculation on their input to discover their intent.
This commit is contained in:
Christopher Tiwald 2015-05-06 09:16:46 -04:00
parent b888b31e08
commit 8056b5f8f7
3 changed files with 45 additions and 2 deletions

View File

@ -2,6 +2,7 @@ package aws
import (
"fmt"
"net"
"strconv"
"github.com/awslabs/aws-sdk-go/aws"
@ -82,3 +83,17 @@ func validatePorts(to int64, from int64, expected expectedPortPair) bool {
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
}

View File

@ -152,3 +152,23 @@ func Test_validatePorts(t *testing.T) {
}
}
}
func Test_validateCIDRBlock(t *testing.T) {
for _, ts := range []struct {
cidr string
shouldErr bool
}{
{"10.2.2.0/24", false},
{"10.2.2.0/1234", true},
{"10/24", true},
{"10.2.2.2/24", true},
} {
err := validateCIDRBlock(ts.cidr)
if ts.shouldErr && err == nil {
t.Fatalf("Input '%s' should error but didn't!", ts.cidr)
}
if !ts.shouldErr && err != nil {
t.Fatalf("Got unexpected error for '%s' input: %s", ts.cidr, err)
}
}
}

View File

@ -284,8 +284,16 @@ 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
}
// Add new Acl entry
_, err := conn.CreateNetworkACLEntry(&ec2.CreateNetworkACLEntryInput{
_, connErr := conn.CreateNetworkACLEntry(&ec2.CreateNetworkACLEntryInput{
NetworkACLID: aws.String(d.Id()),
CIDRBlock: add.CIDRBlock,
Egress: add.Egress,
@ -294,7 +302,7 @@ func updateNetworkAclEntries(d *schema.ResourceData, entryType string, conn *ec2
RuleAction: add.RuleAction,
RuleNumber: add.RuleNumber,
})
if err != nil {
if connErr != nil {
return fmt.Errorf("Error creating %s entry: %s", entryType, err)
}
}