SecurityGroup Improvements (#4183)
This commit is contained in:
parent
6a644850f6
commit
11a37c357b
@ -145,6 +145,7 @@ from .utils import (
|
||||
create_dns_entries,
|
||||
split_route_id,
|
||||
random_security_group_id,
|
||||
random_security_group_rule_id,
|
||||
random_snapshot_id,
|
||||
random_spot_fleet_request_id,
|
||||
random_spot_request_id,
|
||||
@ -161,6 +162,7 @@ from .utils import (
|
||||
get_prefix,
|
||||
simple_aws_filter_to_re,
|
||||
is_valid_cidr,
|
||||
is_valid_ipv6_cidr,
|
||||
filter_internet_gateways,
|
||||
filter_reservations,
|
||||
filter_iam_instance_profile_associations,
|
||||
@ -1999,16 +2001,47 @@ class RegionsAndZonesBackend(object):
|
||||
|
||||
|
||||
class SecurityRule(object):
|
||||
def __init__(self, ip_protocol, from_port, to_port, ip_ranges, source_groups):
|
||||
def __init__(
|
||||
self,
|
||||
ip_protocol,
|
||||
from_port,
|
||||
to_port,
|
||||
ip_ranges,
|
||||
source_groups,
|
||||
prefix_list_ids=None,
|
||||
):
|
||||
self.id = random_security_group_rule_id()
|
||||
self.ip_protocol = str(ip_protocol)
|
||||
self.ip_ranges = ip_ranges or []
|
||||
self.source_groups = source_groups
|
||||
self.prefix_list_ids = prefix_list_ids or []
|
||||
self.from_port = self.to_port = None
|
||||
|
||||
if self.ip_protocol != "-1":
|
||||
self.from_port = int(from_port)
|
||||
self.to_port = int(to_port)
|
||||
|
||||
ip_protocol_keywords = {
|
||||
"tcp": "tcp",
|
||||
"6": "tcp",
|
||||
"udp": "udp",
|
||||
"17": "udp",
|
||||
"all": "-1",
|
||||
"-1": "-1",
|
||||
"tCp": "tcp",
|
||||
"6": "tcp",
|
||||
"UDp": "udp",
|
||||
"17": "udp",
|
||||
"ALL": "-1",
|
||||
"icMp": "icmp",
|
||||
"1": "icmp",
|
||||
}
|
||||
self.ip_protocol = ip_protocol_keywords.get(self.ip_protocol)
|
||||
|
||||
@property
|
||||
def owner_id(self):
|
||||
return ACCOUNT_ID
|
||||
|
||||
def __eq__(self, other):
|
||||
if self.ip_protocol != other.ip_protocol:
|
||||
return False
|
||||
@ -2016,6 +2049,8 @@ class SecurityRule(object):
|
||||
return False
|
||||
if self.source_groups != other.source_groups:
|
||||
return False
|
||||
if self.prefix_list_ids != other.prefix_list_ids:
|
||||
return False
|
||||
if self.ip_protocol != "-1":
|
||||
if self.from_port != other.from_port:
|
||||
return False
|
||||
@ -2035,18 +2070,20 @@ class SecurityGroup(TaggedEC2Resource, CloudFormationModel):
|
||||
self.description = description
|
||||
self.ingress_rules = []
|
||||
self.egress_rules = [
|
||||
SecurityRule("-1", None, None, [{"CidrIp": "0.0.0.0/0"}], [])
|
||||
SecurityRule("-1", None, None, [{"CidrIp": "0.0.0.0/0"}], []),
|
||||
]
|
||||
self.enis = {}
|
||||
self.vpc_id = vpc_id
|
||||
self.owner_id = OWNER_ID
|
||||
self.owner_id = ACCOUNT_ID
|
||||
self.add_tags(tags or {})
|
||||
|
||||
# Append default IPv6 egress rule for VPCs with IPv6 support
|
||||
if vpc_id:
|
||||
vpc = self.ec2_backend.vpcs.get(vpc_id)
|
||||
if vpc and len(vpc.get_cidr_block_association_set(ipv6=True)) > 0:
|
||||
self.egress_rules.append(SecurityRule("-1", None, None, [], []))
|
||||
self.egress_rules.append(
|
||||
SecurityRule("-1", None, None, [{"CidrIpv6": "::/0"}], [])
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def cloudformation_name_type():
|
||||
@ -2077,7 +2114,7 @@ class SecurityGroup(TaggedEC2Resource, CloudFormationModel):
|
||||
security_group.add_tag(tag_key, tag_value)
|
||||
|
||||
for ingress_rule in properties.get("SecurityGroupIngress", []):
|
||||
source_group_id = ingress_rule.get("SourceSecurityGroupId")
|
||||
source_group_id = ingress_rule.get("SourceSecurityGroupId",)
|
||||
|
||||
ec2_backend.authorize_security_group_ingress(
|
||||
group_name_or_id=security_group.id,
|
||||
@ -2085,7 +2122,7 @@ class SecurityGroup(TaggedEC2Resource, CloudFormationModel):
|
||||
from_port=ingress_rule["FromPort"],
|
||||
to_port=ingress_rule["ToPort"],
|
||||
ip_ranges=ingress_rule.get("CidrIp"),
|
||||
source_group_ids=[source_group_id],
|
||||
source_group_ids=[source_group_id] if source_group_id else [],
|
||||
vpc_id=vpc_id,
|
||||
)
|
||||
|
||||
@ -2196,6 +2233,9 @@ class SecurityGroupBackend(object):
|
||||
def __init__(self):
|
||||
# the key in the dict group is the vpc_id or None (non-vpc)
|
||||
self.groups = defaultdict(dict)
|
||||
# This will help us in RuleLimitExceed errors.
|
||||
self.sg_old_ingress_ruls = {}
|
||||
self.sg_old_egress_ruls = {}
|
||||
|
||||
# Create the default security group
|
||||
self.create_security_group("default", "default group")
|
||||
@ -2289,6 +2329,7 @@ class SecurityGroupBackend(object):
|
||||
ip_ranges,
|
||||
source_group_names=None,
|
||||
source_group_ids=None,
|
||||
prefix_list_ids=None,
|
||||
vpc_id=None,
|
||||
):
|
||||
group = self.get_security_group_by_name_or_id(group_name_or_id, vpc_id)
|
||||
@ -2301,8 +2342,17 @@ class SecurityGroupBackend(object):
|
||||
ip_ranges = [json.loads(ip_ranges)]
|
||||
if ip_ranges:
|
||||
for cidr in ip_ranges:
|
||||
if (type(cidr) is dict and not is_valid_cidr(cidr["CidrIp"])) or (
|
||||
type(cidr) is str and not is_valid_cidr(cidr)
|
||||
if (
|
||||
type(cidr) is dict
|
||||
and not any(
|
||||
[
|
||||
is_valid_cidr(cidr.get("CidrIp", "")),
|
||||
is_valid_ipv6_cidr(cidr.get("CidrIpv6", "")),
|
||||
]
|
||||
)
|
||||
) or (
|
||||
type(cidr) is str
|
||||
and not any([is_valid_cidr(cidr), is_valid_ipv6_cidr(cidr)])
|
||||
):
|
||||
raise InvalidCIDRSubnetError(cidr=cidr)
|
||||
|
||||
@ -2320,21 +2370,24 @@ class SecurityGroupBackend(object):
|
||||
source_groups = []
|
||||
for source_group_name in source_group_names:
|
||||
source_group = self.get_security_group_from_name(source_group_name, vpc_id)
|
||||
# TODO raise exception if source_group is None?
|
||||
if source_group:
|
||||
source_groups.append(source_group)
|
||||
else:
|
||||
raise InvalidSecurityGroupNotFoundError(source_group_name)
|
||||
|
||||
# for VPCs
|
||||
for source_group_id in source_group_ids:
|
||||
source_group = self.get_security_group_from_id(source_group_id)
|
||||
# TODO raise exception if source_group is None?
|
||||
if source_group:
|
||||
source_groups.append(source_group)
|
||||
else:
|
||||
raise InvalidSecurityGroupNotFoundError(source_group_id)
|
||||
|
||||
security_rule = SecurityRule(
|
||||
ip_protocol, from_port, to_port, ip_ranges, source_groups
|
||||
ip_protocol, from_port, to_port, ip_ranges, source_groups, prefix_list_ids
|
||||
)
|
||||
group.add_ingress_rule(security_rule)
|
||||
return security_rule, group
|
||||
|
||||
def revoke_security_group_ingress(
|
||||
self,
|
||||
@ -2345,6 +2398,7 @@ class SecurityGroupBackend(object):
|
||||
ip_ranges,
|
||||
source_group_names=None,
|
||||
source_group_ids=None,
|
||||
prefix_list_ids=None,
|
||||
vpc_id=None,
|
||||
):
|
||||
|
||||
@ -2362,10 +2416,11 @@ class SecurityGroupBackend(object):
|
||||
source_groups.append(source_group)
|
||||
|
||||
security_rule = SecurityRule(
|
||||
ip_protocol, from_port, to_port, ip_ranges, source_groups
|
||||
ip_protocol, from_port, to_port, ip_ranges, source_groups, prefix_list_ids
|
||||
)
|
||||
if security_rule in group.ingress_rules:
|
||||
group.ingress_rules.remove(security_rule)
|
||||
self.sg_old_ingress_ruls[group.id] = group.ingress_rules.copy()
|
||||
return security_rule
|
||||
raise InvalidPermissionNotFoundError()
|
||||
|
||||
@ -2378,9 +2433,9 @@ class SecurityGroupBackend(object):
|
||||
ip_ranges,
|
||||
source_group_names=None,
|
||||
source_group_ids=None,
|
||||
prefix_list_ids=None,
|
||||
vpc_id=None,
|
||||
):
|
||||
|
||||
group = self.get_security_group_by_name_or_id(group_name_or_id, vpc_id)
|
||||
if group is None:
|
||||
raise InvalidSecurityGroupNotFoundError(group_name_or_id)
|
||||
@ -2392,15 +2447,26 @@ class SecurityGroupBackend(object):
|
||||
ip_ranges = [json.loads(ip_ranges)]
|
||||
if ip_ranges:
|
||||
for cidr in ip_ranges:
|
||||
if not is_valid_cidr(cidr["CidrIp"]):
|
||||
if (
|
||||
type(cidr) is dict
|
||||
and not any(
|
||||
[
|
||||
is_valid_cidr(cidr.get("CidrIp", "")),
|
||||
is_valid_ipv6_cidr(cidr.get("CidrIpv6", "")),
|
||||
]
|
||||
)
|
||||
) or (
|
||||
type(cidr) is str
|
||||
and not any([is_valid_cidr(cidr), is_valid_ipv6_cidr(cidr)])
|
||||
):
|
||||
raise InvalidCIDRSubnetError(cidr=cidr)
|
||||
|
||||
self._verify_group_will_respect_rule_count_limit(
|
||||
group,
|
||||
group.get_number_of_egress_rules(),
|
||||
ip_ranges,
|
||||
source_group_names,
|
||||
source_group_ids,
|
||||
egress=True,
|
||||
)
|
||||
|
||||
source_group_names = source_group_names if source_group_names else []
|
||||
@ -2418,10 +2484,18 @@ class SecurityGroupBackend(object):
|
||||
if source_group:
|
||||
source_groups.append(source_group)
|
||||
|
||||
if group.vpc_id:
|
||||
vpc = self.vpcs.get(group.vpc_id)
|
||||
if vpc and not len(vpc.get_cidr_block_association_set(ipv6=True)) > 0:
|
||||
for item in ip_ranges.copy():
|
||||
if "CidrIpv6" in item:
|
||||
ip_ranges.remove(item)
|
||||
|
||||
security_rule = SecurityRule(
|
||||
ip_protocol, from_port, to_port, ip_ranges, source_groups
|
||||
ip_protocol, from_port, to_port, ip_ranges, source_groups, prefix_list_ids
|
||||
)
|
||||
group.add_egress_rule(security_rule)
|
||||
return security_rule, group
|
||||
|
||||
def revoke_security_group_egress(
|
||||
self,
|
||||
@ -2432,6 +2506,7 @@ class SecurityGroupBackend(object):
|
||||
ip_ranges,
|
||||
source_group_names=None,
|
||||
source_group_ids=None,
|
||||
prefix_list_ids=None,
|
||||
vpc_id=None,
|
||||
):
|
||||
|
||||
@ -2455,11 +2530,19 @@ class SecurityGroupBackend(object):
|
||||
# for ip in ip_ranges:
|
||||
# ip_ranges = [ip.get("CidrIp") if ip.get("CidrIp") == "0.0.0.0/0" else ip]
|
||||
|
||||
if group.vpc_id:
|
||||
vpc = self.vpcs.get(group.vpc_id)
|
||||
if vpc and not len(vpc.get_cidr_block_association_set(ipv6=True)) > 0:
|
||||
for item in ip_ranges.copy():
|
||||
if "CidrIpv6" in item:
|
||||
ip_ranges.remove(item)
|
||||
|
||||
security_rule = SecurityRule(
|
||||
ip_protocol, from_port, to_port, ip_ranges, source_groups
|
||||
ip_protocol, from_port, to_port, ip_ranges, source_groups, prefix_list_ids
|
||||
)
|
||||
if security_rule in group.egress_rules:
|
||||
group.egress_rules.remove(security_rule)
|
||||
self.sg_old_egress_ruls[group.id] = group.egress_rules.copy()
|
||||
return security_rule
|
||||
raise InvalidPermissionNotFoundError()
|
||||
|
||||
@ -2470,6 +2553,7 @@ class SecurityGroupBackend(object):
|
||||
ip_ranges,
|
||||
source_group_names=None,
|
||||
source_group_ids=None,
|
||||
egress=False,
|
||||
):
|
||||
max_nb_rules = 50 if group.vpc_id else 100
|
||||
future_group_nb_rules = current_rule_nb
|
||||
@ -2480,6 +2564,10 @@ class SecurityGroupBackend(object):
|
||||
if source_group_names:
|
||||
future_group_nb_rules += len(source_group_names)
|
||||
if future_group_nb_rules > max_nb_rules:
|
||||
if group and not egress:
|
||||
group.ingress_rules = self.sg_old_ingress_ruls[group.id]
|
||||
if group and egress:
|
||||
group.egress_rules = self.sg_old_egress_ruls[group.id]
|
||||
raise RulesPerSecurityGroupLimitExceededError
|
||||
|
||||
|
||||
|
@ -2,7 +2,6 @@ from __future__ import unicode_literals
|
||||
|
||||
from moto.core.responses import BaseResponse
|
||||
from moto.ec2.utils import filters_from_querystring
|
||||
from moto.core import ACCOUNT_ID
|
||||
|
||||
|
||||
def try_parse_int(value, default=None):
|
||||
@ -26,6 +25,22 @@ def parse_sg_attributes_from_dict(sg_attributes):
|
||||
|
||||
ip_ranges.append(ip_range)
|
||||
|
||||
ip_ranges_tree = sg_attributes.get("Ipv6Ranges") or {}
|
||||
for ip_range_idx in sorted(ip_ranges_tree.keys()):
|
||||
ip_range = {"CidrIpv6": ip_ranges_tree[ip_range_idx]["CidrIpv6"][0]}
|
||||
if ip_ranges_tree[ip_range_idx].get("Description"):
|
||||
ip_range["Description"] = ip_ranges_tree[ip_range_idx].get("Description")[0]
|
||||
|
||||
ip_ranges.append(ip_range)
|
||||
|
||||
if "CidrIp" in sg_attributes:
|
||||
cidr_ip = sg_attributes.get("CidrIp")[0]
|
||||
ip_ranges.append({"CidrIp": cidr_ip})
|
||||
|
||||
if "CidrIpv6" in sg_attributes:
|
||||
cidr_ipv6 = sg_attributes.get("CidrIpv6")[0]
|
||||
ip_ranges.append({"CidrIpv6": cidr_ipv6})
|
||||
|
||||
source_groups = []
|
||||
source_group_ids = []
|
||||
groups_tree = sg_attributes.get("Groups") or {}
|
||||
@ -36,7 +51,26 @@ def parse_sg_attributes_from_dict(sg_attributes):
|
||||
elif "GroupName" in group_dict:
|
||||
source_groups.append(group_dict["GroupName"][0])
|
||||
|
||||
return ip_protocol, from_port, to_port, ip_ranges, source_groups, source_group_ids
|
||||
prefix_list_ids = []
|
||||
pl_tree = sg_attributes.get("PrefixListIds") or {}
|
||||
for pl_index in sorted(pl_tree):
|
||||
pl_dict = pl_tree.get(pl_index, {})
|
||||
pl_item = {}
|
||||
if "PrefixListId" in pl_dict:
|
||||
pl_item["PrefixListId"] = pl_dict.get("PrefixListId")[0]
|
||||
if "Description" in pl_dict:
|
||||
pl_item["Description"] = pl_dict.get("Description")[0]
|
||||
if pl_item:
|
||||
prefix_list_ids.append(pl_item)
|
||||
return (
|
||||
ip_protocol,
|
||||
from_port,
|
||||
to_port,
|
||||
ip_ranges,
|
||||
source_groups,
|
||||
source_group_ids,
|
||||
prefix_list_ids,
|
||||
)
|
||||
|
||||
|
||||
class SecurityGroups(BaseResponse):
|
||||
@ -64,6 +98,7 @@ class SecurityGroups(BaseResponse):
|
||||
ip_ranges,
|
||||
source_groups,
|
||||
source_group_ids,
|
||||
prefix_list_ids,
|
||||
) = parse_sg_attributes_from_dict(querytree)
|
||||
|
||||
yield (
|
||||
@ -74,6 +109,7 @@ class SecurityGroups(BaseResponse):
|
||||
ip_ranges,
|
||||
source_groups,
|
||||
source_group_ids,
|
||||
prefix_list_ids,
|
||||
)
|
||||
|
||||
ip_permissions = querytree.get("IpPermissions") or {}
|
||||
@ -87,6 +123,7 @@ class SecurityGroups(BaseResponse):
|
||||
ip_ranges,
|
||||
source_groups,
|
||||
source_group_ids,
|
||||
prefix_list_ids,
|
||||
) = parse_sg_attributes_from_dict(ip_permission)
|
||||
|
||||
yield (
|
||||
@ -97,19 +134,24 @@ class SecurityGroups(BaseResponse):
|
||||
ip_ranges,
|
||||
source_groups,
|
||||
source_group_ids,
|
||||
prefix_list_ids,
|
||||
)
|
||||
|
||||
def authorize_security_group_egress(self):
|
||||
if self.is_not_dryrun("GrantSecurityGroupEgress"):
|
||||
for args in self._process_rules_from_querystring():
|
||||
self.ec2_backend.authorize_security_group_egress(*args)
|
||||
return AUTHORIZE_SECURITY_GROUP_EGRESS_RESPONSE
|
||||
rule, group = self.ec2_backend.authorize_security_group_egress(*args)
|
||||
self.ec2_backend.sg_old_egress_ruls[group.id] = group.egress_rules.copy()
|
||||
template = self.response_template(AUTHORIZE_SECURITY_GROUP_EGRESS_RESPONSE)
|
||||
return template.render(rule=rule, group=group)
|
||||
|
||||
def authorize_security_group_ingress(self):
|
||||
if self.is_not_dryrun("GrantSecurityGroupIngress"):
|
||||
for args in self._process_rules_from_querystring():
|
||||
self.ec2_backend.authorize_security_group_ingress(*args)
|
||||
return AUTHORIZE_SECURITY_GROUP_INGRESS_RESPONSE
|
||||
rule, group = self.ec2_backend.authorize_security_group_ingress(*args)
|
||||
self.ec2_backend.sg_old_ingress_ruls[group.id] = group.ingress_rules.copy()
|
||||
template = self.response_template(AUTHORIZE_SECURITY_GROUP_INGRESS_RESPONSE)
|
||||
return template.render(rule=rule, group=group)
|
||||
|
||||
def create_security_group(self):
|
||||
name = self._get_param("GroupName")
|
||||
@ -124,6 +166,13 @@ class SecurityGroups(BaseResponse):
|
||||
group = self.ec2_backend.create_security_group(
|
||||
name, description, vpc_id=vpc_id, tags=tags
|
||||
)
|
||||
if group:
|
||||
self.ec2_backend.sg_old_ingress_ruls[
|
||||
group.id
|
||||
] = group.ingress_rules.copy()
|
||||
self.ec2_backend.sg_old_egress_ruls[
|
||||
group.id
|
||||
] = group.egress_rules.copy()
|
||||
template = self.response_template(CREATE_SECURITY_GROUP_RESPONSE)
|
||||
return template.render(group=group)
|
||||
|
||||
@ -181,15 +230,12 @@ DELETE_GROUP_RESPONSE = """<DeleteSecurityGroupResponse xmlns="http://ec2.amazon
|
||||
<return>true</return>
|
||||
</DeleteSecurityGroupResponse>"""
|
||||
|
||||
DESCRIBE_SECURITY_GROUPS_RESPONSE = (
|
||||
"""<DescribeSecurityGroupsResponse xmlns="http://ec2.amazonaws.com/doc/2013-10-15/">
|
||||
DESCRIBE_SECURITY_GROUPS_RESPONSE = """<DescribeSecurityGroupsResponse xmlns="http://ec2.amazonaws.com/doc/2013-10-15/">
|
||||
<requestId>59dbff89-35bd-4eac-99ed-be587EXAMPLE</requestId>
|
||||
<securityGroupInfo>
|
||||
{% for group in groups %}
|
||||
<item>
|
||||
<ownerId>"""
|
||||
+ ACCOUNT_ID
|
||||
+ """</ownerId>
|
||||
<ownerId>{{ group.owner_id }}</ownerId>
|
||||
<groupId>{{ group.id }}</groupId>
|
||||
<groupName>{{ group.name }}</groupName>
|
||||
<groupDescription>{{ group.description }}</groupDescription>
|
||||
@ -209,9 +255,7 @@ DESCRIBE_SECURITY_GROUPS_RESPONSE = (
|
||||
<groups>
|
||||
{% for source_group in rule.source_groups %}
|
||||
<item>
|
||||
<userId>"""
|
||||
+ ACCOUNT_ID
|
||||
+ """</userId>
|
||||
<userId>{{ source_group.owner_id }}</userId>
|
||||
<groupId>{{ source_group.id }}</groupId>
|
||||
<groupName>{{ source_group.name }}</groupName>
|
||||
</item>
|
||||
@ -219,14 +263,36 @@ DESCRIBE_SECURITY_GROUPS_RESPONSE = (
|
||||
</groups>
|
||||
<ipRanges>
|
||||
{% for ip_range in rule.ip_ranges %}
|
||||
{% if ip_range['CidrIp'] %}
|
||||
<item>
|
||||
<cidrIp>{{ ip_range['CidrIp'] }}</cidrIp>
|
||||
<cidrIp>{{ ip_range['CidrIp'] }}</cidrIp>
|
||||
{% if ip_range['Description'] %}
|
||||
<description>{{ ip_range['Description'] }}</description>
|
||||
<description>{{ ip_range['Description'] }}</description>
|
||||
{% endif %}
|
||||
</item>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</ipRanges>
|
||||
<ipv6Ranges>
|
||||
{% for ip_range in rule.ip_ranges %}
|
||||
{% if ip_range['CidrIpv6'] %}
|
||||
<item>
|
||||
<cidrIpv6>{{ ip_range['CidrIpv6'] }}</cidrIpv6>
|
||||
{% if ip_range['Description'] %}
|
||||
<description>{{ ip_range['Description'] }}</description>
|
||||
{% endif %}
|
||||
</item>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</ipv6Ranges>
|
||||
<prefixListIds>
|
||||
{% for prefix_list in rule.prefix_list_ids %}
|
||||
<item>
|
||||
<prefixListId>{{ prefix_list.PrefixListId }}</prefixListId>
|
||||
<description>{{ prefix_list.Description }}</description>
|
||||
</item>
|
||||
{% endfor %}
|
||||
</prefixListIds>
|
||||
</item>
|
||||
{% endfor %}
|
||||
</ipPermissions>
|
||||
@ -243,9 +309,7 @@ DESCRIBE_SECURITY_GROUPS_RESPONSE = (
|
||||
<groups>
|
||||
{% for source_group in rule.source_groups %}
|
||||
<item>
|
||||
<userId>"""
|
||||
+ ACCOUNT_ID
|
||||
+ """</userId>
|
||||
<userId>{{ source_group.owner_id }}</userId>
|
||||
<groupId>{{ source_group.id }}</groupId>
|
||||
<groupName>{{ source_group.name }}</groupName>
|
||||
</item>
|
||||
@ -253,22 +317,44 @@ DESCRIBE_SECURITY_GROUPS_RESPONSE = (
|
||||
</groups>
|
||||
<ipRanges>
|
||||
{% for ip_range in rule.ip_ranges %}
|
||||
{% if ip_range['CidrIp'] %}
|
||||
<item>
|
||||
<cidrIp>{{ ip_range['CidrIp'] }}</cidrIp>
|
||||
<cidrIp>{{ ip_range['CidrIp'] }}</cidrIp>
|
||||
{% if ip_range['Description'] %}
|
||||
<description>{{ ip_range['Description'] }}</description>
|
||||
<description>{{ ip_range['Description'] }}</description>
|
||||
{% endif %}
|
||||
</item>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</ipRanges>
|
||||
<ipv6Ranges>
|
||||
{% for ip_range in rule.ip_ranges %}
|
||||
{% if ip_range['CidrIpv6'] %}
|
||||
<item>
|
||||
<cidrIpv6>{{ ip_range['CidrIpv6'] }}</cidrIpv6>
|
||||
{% if ip_range['Description'] %}
|
||||
<description>{{ ip_range['Description'] }}</description>
|
||||
{% endif %}
|
||||
</item>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</ipv6Ranges>
|
||||
<prefixListIds>
|
||||
{% if rule.prefix_list_ids %}
|
||||
{% for prefix_list in rule.prefix_list_ids %}
|
||||
<item>
|
||||
<prefixListId>{{ prefix_list.PrefixListId }}</prefixListId>
|
||||
<description>{{ prefix_list.Description }}</description>
|
||||
</item>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
</prefixListIds>
|
||||
</item>
|
||||
{% endfor %}
|
||||
</ipPermissionsEgress>
|
||||
<tagSet>
|
||||
{% for tag in group.get_tags() %}
|
||||
<item>
|
||||
<resourceId>{{ tag.resource_id }}</resourceId>
|
||||
<resourceType>{{ tag.resource_type }}</resourceType>
|
||||
<key>{{ tag.key }}</key>
|
||||
<value>{{ tag.value }}</value>
|
||||
</item>
|
||||
@ -278,11 +364,51 @@ DESCRIBE_SECURITY_GROUPS_RESPONSE = (
|
||||
{% endfor %}
|
||||
</securityGroupInfo>
|
||||
</DescribeSecurityGroupsResponse>"""
|
||||
)
|
||||
|
||||
AUTHORIZE_SECURITY_GROUP_INGRESS_RESPONSE = """<AuthorizeSecurityGroupIngressResponse xmlns="http://ec2.amazonaws.com/doc/2013-10-15/">
|
||||
<requestId>59dbff89-35bd-4eac-99ed-be587EXAMPLE</requestId>
|
||||
<return>true</return>
|
||||
AUTHORIZE_SECURITY_GROUP_INGRESS_RESPONSE = """<AuthorizeSecurityGroupIngressResponse xmlns="http://ec2.amazonaws.com/doc/2016-11-15/">
|
||||
<requestId>b1f67202-c2c2-4ba4-8464-c8b1d8f5af7a</requestId>
|
||||
<return>true</return>
|
||||
<securityGroupRuleSet>
|
||||
{% for item in rule.ip_ranges %}
|
||||
<item>
|
||||
{% if item.CidrIp %}
|
||||
<cidrIpv4>{{ item.CidrIp }}</cidrIpv4>
|
||||
{% endif %}
|
||||
{% if item.CidrIpv6 %}
|
||||
<cidrIpv6>{{ item.CidrIpv6 }}</cidrIpv6>
|
||||
{% endif %}
|
||||
<description>{{ item.Description or '' }}</description>
|
||||
{% if rule.from_port is not none %}
|
||||
<fromPort>{{ rule.from_port }}</fromPort>
|
||||
{% endif %}
|
||||
<groupId>{{ group.id }}</groupId>
|
||||
<groupOwnerId>{{ rule.owner_id }}</groupOwnerId>
|
||||
<ipProtocol>{{ rule.ip_protocol }}</ipProtocol>
|
||||
<isEgress>false</isEgress>
|
||||
<securityGroupRuleId>{{ rule.id }}</securityGroupRuleId>
|
||||
{% if rule.to_port is not none %}
|
||||
<toPort>{{ rule.to_port }}</toPort>
|
||||
{% endif %}
|
||||
</item>
|
||||
{% endfor %}
|
||||
{% for item in rule.prefix_list_ids %}
|
||||
<item>
|
||||
<prefixListId>{{ item.PrefixListId }}</prefixListId>
|
||||
<description>{{ item.Description or '' }}</description>
|
||||
{% if rule.from_port is not none %}
|
||||
<fromPort>{{ rule.from_port }}</fromPort>
|
||||
{% endif %}
|
||||
<groupId>{{ group.id }}</groupId>
|
||||
<groupOwnerId>{{ rule.owner_id }}</groupOwnerId>
|
||||
<ipProtocol>{{ rule.ip_protocol }}</ipProtocol>
|
||||
<isEgress>false</isEgress>
|
||||
<securityGroupRuleId>{{ rule.id }}</securityGroupRuleId>
|
||||
{% if rule.to_port is not none %}
|
||||
<toPort>{{ rule.to_port }}</toPort>
|
||||
{% endif %}
|
||||
</item>
|
||||
{% endfor %}
|
||||
</securityGroupRuleSet>
|
||||
</AuthorizeSecurityGroupIngressResponse>"""
|
||||
|
||||
REVOKE_SECURITY_GROUP_INGRESS_RESPONSE = """<RevokeSecurityGroupIngressResponse xmlns="http://ec2.amazonaws.com/doc/2013-10-15/">
|
||||
@ -290,10 +416,50 @@ REVOKE_SECURITY_GROUP_INGRESS_RESPONSE = """<RevokeSecurityGroupIngressResponse
|
||||
<return>true</return>
|
||||
</RevokeSecurityGroupIngressResponse>"""
|
||||
|
||||
AUTHORIZE_SECURITY_GROUP_EGRESS_RESPONSE = """
|
||||
<AuthorizeSecurityGroupEgressResponse xmlns="http://ec2.amazonaws.com/doc/2013-10-15/">
|
||||
<requestId>59dbff89-35bd-4eac-99ed-be587EXAMPLE</requestId>
|
||||
<return>true</return>
|
||||
AUTHORIZE_SECURITY_GROUP_EGRESS_RESPONSE = """<AuthorizeSecurityGroupEgressResponse xmlns="http://ec2.amazonaws.com/doc/2016-11-15/">
|
||||
<requestId>b1f67202-c2c2-4ba4-8464-c8b1d8f5af7a</requestId>
|
||||
<return>true</return>
|
||||
<securityGroupRuleSet>
|
||||
{% for item in rule.ip_ranges %}
|
||||
<item>
|
||||
{% if item.CidrIp %}
|
||||
<cidrIpv4>{{ item.CidrIp }}</cidrIpv4>
|
||||
{% endif %}
|
||||
{% if item.CidrIpv6 %}
|
||||
<cidrIpv6>{{ item.CidrIpv6 }}</cidrIpv6>
|
||||
{% endif %}
|
||||
<description>{{ item.Description or '' }}</description>
|
||||
{% if rule.from_port is not none %}
|
||||
<fromPort>{{ rule.from_port }}</fromPort>
|
||||
{% endif %}
|
||||
<groupId>{{ group.id }}</groupId>
|
||||
<groupOwnerId>{{ rule.owner_id }}</groupOwnerId>
|
||||
<ipProtocol>{{ rule.ip_protocol }}</ipProtocol>
|
||||
<isEgress>true</isEgress>
|
||||
<securityGroupRuleId>{{ rule.id }}</securityGroupRuleId>
|
||||
{% if rule.to_port is not none %}
|
||||
<toPort>{{ rule.to_port }}</toPort>
|
||||
{% endif %}
|
||||
</item>
|
||||
{% endfor %}
|
||||
{% for item in rule.prefix_list_ids %}
|
||||
<item>
|
||||
<prefixListId>{{ item.PrefixListId }}</prefixListId>
|
||||
<description>{{ item.Description or '' }}</description>
|
||||
{% if rule.from_port is not none %}
|
||||
<fromPort>{{ rule.from_port }}</fromPort>
|
||||
{% endif %}
|
||||
<groupId>{{ group.id }}</groupId>
|
||||
<groupOwnerId>{{ rule.owner_id }}</groupOwnerId>
|
||||
<ipProtocol>{{ rule.ip_protocol }}</ipProtocol>
|
||||
<isEgress>true</isEgress>
|
||||
<securityGroupRuleId>{{ rule.id }}</securityGroupRuleId>
|
||||
{% if rule.to_port is not none %}
|
||||
<toPort>{{ rule.to_port }}</toPort>
|
||||
{% endif %}
|
||||
</item>
|
||||
{% endfor %}
|
||||
</securityGroupRuleSet>
|
||||
</AuthorizeSecurityGroupEgressResponse>"""
|
||||
|
||||
REVOKE_SECURITY_GROUP_EGRESS_RESPONSE = """<RevokeSecurityGroupEgressResponse xmlns="http://ec2.amazonaws.com/doc/2013-10-15/">
|
||||
|
@ -34,6 +34,7 @@ EC2_RESOURCE_TO_PREFIX = {
|
||||
"route-table": "rtb",
|
||||
"route-table-association": "rtbassoc",
|
||||
"security-group": "sg",
|
||||
"security-group-rule": "sgr",
|
||||
"snapshot": "snap",
|
||||
"spot-instance-request": "sir",
|
||||
"spot-fleet-request": "sfr",
|
||||
@ -82,6 +83,10 @@ def random_security_group_id():
|
||||
return random_id(prefix=EC2_RESOURCE_TO_PREFIX["security-group"])
|
||||
|
||||
|
||||
def random_security_group_rule_id():
|
||||
return random_id(prefix=EC2_RESOURCE_TO_PREFIX["security-group-rule"], size=17)
|
||||
|
||||
|
||||
def random_flow_log_id():
|
||||
return random_id(prefix=EC2_RESOURCE_TO_PREFIX["flow-logs"])
|
||||
|
||||
@ -590,6 +595,12 @@ def is_valid_cidr(cird):
|
||||
return cidr_pattern_re.match(cird) is not None
|
||||
|
||||
|
||||
def is_valid_ipv6_cidr(cird):
|
||||
cidr_pattern = r"^s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:)))(%.+)?s*(\/([0-9]|[1-9][0-9]|1[0-1][0-9]|12[0-8]))?$"
|
||||
cidr_pattern_re = re.compile(cidr_pattern)
|
||||
return cidr_pattern_re.match(cird) is not None
|
||||
|
||||
|
||||
def generate_instance_identity_document(instance):
|
||||
"""
|
||||
http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/instance-identity-documents.html
|
||||
|
@ -93,3 +93,37 @@ TestAccAWSRouteTable_basic
|
||||
TestAccAWSSsmDocumentDataSource
|
||||
TestAccAwsEc2ManagedPrefixList
|
||||
TestAccAWSEgressOnlyInternetGateway
|
||||
TestAccAWSSecurityGroup_allowAll
|
||||
TestAccAWSSecurityGroup_sourceSecurityGroup
|
||||
TestAccAWSSecurityGroup_IPRangeAndSecurityGroupWithSameRules
|
||||
TestAccAWSSecurityGroup_IPRangesWithSameRules
|
||||
TestAccAWSSecurityGroup_basic
|
||||
TestAccAWSSecurityGroup_egressConfigMode
|
||||
TestAccAWSSecurityGroup_ingressConfigMode
|
||||
TestAccAWSSecurityGroup_ipv6
|
||||
TestAccAWSSecurityGroup_Name_Generated
|
||||
TestAccAWSSecurityGroup_Name_TerraformPrefix
|
||||
TestAccAWSSecurityGroup_NamePrefix
|
||||
TestAccAWSSecurityGroup_NamePrefix_TerraformPrefix
|
||||
TestAccAWSSecurityGroup_self
|
||||
TestAccAWSSecurityGroup_vpc
|
||||
TestAccAWSSecurityGroup_vpcNegOneIngress
|
||||
TestAccAWSSecurityGroup_vpcProtoNumIngress
|
||||
TestAccAWSSecurityGroup_multiIngress
|
||||
TestAccAWSSecurityGroup_ruleDescription
|
||||
TestAccAWSSecurityGroup_defaultEgressVPC
|
||||
TestAccAWSSecurityGroup_defaultEgressClassic
|
||||
TestAccAWSSecurityGroup_driftComplex
|
||||
TestAccAWSSecurityGroup_invalidCIDRBlock
|
||||
TestAccAWSSecurityGroup_tags
|
||||
TestAccAWSSecurityGroup_CIDRandGroups
|
||||
TestAccAWSSecurityGroup_ingressWithCidrAndSGsVPC
|
||||
TestAccAWSSecurityGroup_ipv4andipv6Egress
|
||||
TestAccAWSSecurityGroup_failWithDiffMismatch
|
||||
TestAccAWSSecurityGroup_ruleLimitExceededAppend
|
||||
TestAccAWSSecurityGroupRule_Ingress_VPC
|
||||
TestAccAWSSecurityGroupRule_MultipleRuleSearching_AllProtocolCrash
|
||||
TestAccAWSSecurityGroup_rulesDropOnError
|
||||
TestAccAWSSecurityGroup_ruleLimitExceededAllNew
|
||||
TestAccAWSSecurityGroup_ruleLimitExceededPrepend
|
||||
TestAccAWSSecurityGroup_ruleLimitCidrBlockExceededAppend
|
||||
|
@ -378,6 +378,8 @@ def test_authorize_other_group_egress_and_revoke():
|
||||
{"GroupId": sg02.id, "GroupName": "sg02", "UserId": sg02.owner_id}
|
||||
],
|
||||
"IpRanges": [],
|
||||
"Ipv6Ranges": [],
|
||||
"PrefixListIds": [],
|
||||
}
|
||||
|
||||
sg01.authorize_egress(IpPermissions=[ip_permission])
|
||||
@ -858,6 +860,8 @@ def test_authorize_and_revoke_in_bulk():
|
||||
{"GroupId": sg02.id, "GroupName": "sg02", "UserId": sg02.owner_id}
|
||||
],
|
||||
"IpRanges": [],
|
||||
"Ipv6Ranges": [],
|
||||
"PrefixListIds": [],
|
||||
},
|
||||
{
|
||||
"IpProtocol": "tcp",
|
||||
@ -865,6 +869,8 @@ def test_authorize_and_revoke_in_bulk():
|
||||
"ToPort": 27018,
|
||||
"UserIdGroupPairs": [{"GroupId": sg02.id, "UserId": sg02.owner_id}],
|
||||
"IpRanges": [],
|
||||
"Ipv6Ranges": [],
|
||||
"PrefixListIds": [],
|
||||
},
|
||||
{
|
||||
"IpProtocol": "tcp",
|
||||
@ -872,6 +878,8 @@ def test_authorize_and_revoke_in_bulk():
|
||||
"ToPort": 27017,
|
||||
"UserIdGroupPairs": [{"GroupName": "sg03", "UserId": sg03.owner_id}],
|
||||
"IpRanges": [],
|
||||
"Ipv6Ranges": [],
|
||||
"PrefixListIds": [],
|
||||
},
|
||||
{
|
||||
"IpProtocol": "tcp",
|
||||
@ -881,6 +889,8 @@ def test_authorize_and_revoke_in_bulk():
|
||||
"IpRanges": [
|
||||
{"CidrIp": "10.10.10.0/24", "Description": "Some Description"}
|
||||
],
|
||||
"Ipv6Ranges": [],
|
||||
"PrefixListIds": [],
|
||||
},
|
||||
{
|
||||
"IpProtocol": "tcp",
|
||||
@ -888,6 +898,8 @@ def test_authorize_and_revoke_in_bulk():
|
||||
"ToPort": 27016,
|
||||
"UserIdGroupPairs": [{"GroupId": sg04.id, "UserId": sg04.owner_id}],
|
||||
"IpRanges": [{"CidrIp": "10.10.10.0/24"}],
|
||||
"Ipv6Ranges": [],
|
||||
"PrefixListIds": [],
|
||||
},
|
||||
]
|
||||
expected_ip_permissions = copy.deepcopy(ip_permissions)
|
||||
@ -979,6 +991,8 @@ def test_revoke_security_group_egress():
|
||||
"IpProtocol": "-1",
|
||||
"IpRanges": [{"CidrIp": "0.0.0.0/0"}],
|
||||
"UserIdGroupPairs": [],
|
||||
"Ipv6Ranges": [],
|
||||
"PrefixListIds": [],
|
||||
}
|
||||
]
|
||||
)
|
||||
@ -989,6 +1003,8 @@ def test_revoke_security_group_egress():
|
||||
"IpProtocol": "-1",
|
||||
"IpRanges": [{"CidrIp": "0.0.0.0/0"}],
|
||||
"UserIdGroupPairs": [],
|
||||
"Ipv6Ranges": [],
|
||||
"PrefixListIds": [],
|
||||
}
|
||||
]
|
||||
)
|
||||
|
Loading…
Reference in New Issue
Block a user