Allow creation of subnets from secondary VPC IPv4 CIDR blocks (#3391)

* allow subnets to be created from secondary vpc cidr block

* add additional test case for invalid cidr
This commit is contained in:
davidaah 2020-10-16 11:02:01 -04:00 committed by GitHub
parent 28c1690fc2
commit 2fe3aee359
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 76 additions and 7 deletions

View File

@ -3465,19 +3465,30 @@ class SubnetBackend(object):
vpc = self.get_vpc(
vpc_id
) # Validate VPC exists and the supplied CIDR block is a subnet of the VPC's
vpc_cidr_block = ipaddress.IPv4Network(
six.text_type(vpc.cidr_block), strict=False
)
vpc_cidr_blocks = [
ipaddress.IPv4Network(
six.text_type(cidr_block_association["cidr_block"]), strict=False
)
for cidr_block_association in vpc.get_cidr_block_association_set()
]
try:
subnet_cidr_block = ipaddress.IPv4Network(
six.text_type(cidr_block), strict=False
)
except ValueError:
raise InvalidCIDRBlockParameterError(cidr_block)
if not (
vpc_cidr_block.network_address <= subnet_cidr_block.network_address
and vpc_cidr_block.broadcast_address >= subnet_cidr_block.broadcast_address
):
subnet_in_vpc_cidr_range = False
for vpc_cidr_block in vpc_cidr_blocks:
if (
vpc_cidr_block.network_address <= subnet_cidr_block.network_address
and vpc_cidr_block.broadcast_address
>= subnet_cidr_block.broadcast_address
):
subnet_in_vpc_cidr_range = True
break
if not subnet_in_vpc_cidr_range:
raise InvalidSubnetRangeError(cidr_block)
for subnet in self.get_all_subnets(filters={"vpc-id": vpc_id}):

View File

@ -417,6 +417,24 @@ def test_create_subnet_with_invalid_cidr_range():
)
@mock_ec2
def test_create_subnet_with_invalid_cidr_range_multiple_vpc_cidr_blocks():
ec2 = boto3.resource("ec2", region_name="us-west-1")
vpc = ec2.create_vpc(CidrBlock="10.0.0.0/16")
ec2.meta.client.associate_vpc_cidr_block(CidrBlock="10.1.0.0/16", VpcId=vpc.id)
vpc.reload()
vpc.is_default.shouldnt.be.ok
subnet_cidr_block = "10.2.0.0/20"
with assert_raises(ClientError) as ex:
subnet = ec2.create_subnet(VpcId=vpc.id, CidrBlock=subnet_cidr_block)
str(ex.exception).should.equal(
"An error occurred (InvalidSubnet.Range) when calling the CreateSubnet "
"operation: The CIDR '{}' is invalid.".format(subnet_cidr_block)
)
@mock_ec2
def test_create_subnet_with_invalid_cidr_block_parameter():
ec2 = boto3.resource("ec2", region_name="us-west-1")
@ -436,6 +454,46 @@ def test_create_subnet_with_invalid_cidr_block_parameter():
)
@mock_ec2
def test_create_subnets_with_multiple_vpc_cidr_blocks():
ec2 = boto3.resource("ec2", region_name="us-west-1")
client = boto3.client("ec2", region_name="us-west-1")
vpc = ec2.create_vpc(CidrBlock="10.0.0.0/16")
ec2.meta.client.associate_vpc_cidr_block(CidrBlock="10.1.0.0/16", VpcId=vpc.id)
vpc.reload()
vpc.is_default.shouldnt.be.ok
subnet_cidr_block_primary = "10.0.0.0/24"
subnet_primary = ec2.create_subnet(
VpcId=vpc.id, CidrBlock=subnet_cidr_block_primary
)
subnet_cidr_block_secondary = "10.1.0.0/24"
subnet_secondary = ec2.create_subnet(
VpcId=vpc.id, CidrBlock=subnet_cidr_block_secondary
)
subnets = client.describe_subnets(
SubnetIds=[subnet_primary.id, subnet_secondary.id]
)["Subnets"]
subnets.should.have.length_of(2)
for subnet in subnets:
subnet.should.have.key("AvailabilityZone")
subnet.should.have.key("AvailabilityZoneId")
subnet.should.have.key("AvailableIpAddressCount")
subnet.should.have.key("CidrBlock")
subnet.should.have.key("State")
subnet.should.have.key("SubnetId")
subnet.should.have.key("VpcId")
subnet.shouldnt.have.key("Tags")
subnet.should.have.key("DefaultForAz").which.should.equal(False)
subnet.should.have.key("MapPublicIpOnLaunch").which.should.equal(False)
subnet.should.have.key("OwnerId")
subnet.should.have.key("AssignIpv6AddressOnCreation").which.should.equal(False)
@mock_ec2
def test_create_subnets_with_overlapping_cidr_blocks():
ec2 = boto3.resource("ec2", region_name="us-west-1")