1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223
|
from typing import Any, Optional
from moto.utilities.utils import filter_resources, get_partition
from ..utils import describe_tag_filter, random_managed_prefix_list_id
from .core import TaggedEC2Resource
class ManagedPrefixList(TaggedEC2Resource):
def __init__(
self,
backend: Any,
region: str,
address_family: Optional[str] = None,
entry: Optional[list[dict[str, str]]] = None,
max_entries: Optional[str] = None,
prefix_list_name: Optional[str] = None,
tags: Optional[dict[str, str]] = None,
owner_id: Optional[str] = None,
):
self.ec2_backend = backend
self.address_family = address_family
self.max_entries = max_entries
self.id = random_managed_prefix_list_id()
self.prefix_list_name = prefix_list_name
self.state = "create-complete"
self.state_message = None
self.add_tags(tags or {})
self.version: Optional[int] = 1
self.entries = {self.version: entry} if entry else {}
self.resource_owner_id = owner_id if owner_id else None
self.prefix_list_arn = self.arn(region, self.owner_id)
self.delete_counter = 1
def arn(self, region: str, owner_id: str) -> str:
return (
f"arn:{get_partition(region)}:ec2:{region}:{owner_id}:prefix-list/{self.id}"
)
@property
def owner_id(self) -> str:
return self.resource_owner_id or self.ec2_backend.account_id
@property
def prefix_list_id(self) -> str:
return self.id
class ManagedPrefixListBackend:
def __init__(self) -> None:
self.managed_prefix_lists: dict[str, ManagedPrefixList] = {}
self.create_default_pls()
def create_managed_prefix_list(
self,
address_family: Optional[str] = None,
entry: Optional[list[dict[str, str]]] = None,
max_entries: Optional[str] = None,
prefix_list_name: Optional[str] = None,
tags: Optional[dict[str, str]] = None,
owner_id: Optional[str] = None,
) -> ManagedPrefixList:
managed_prefix_list = ManagedPrefixList(
self,
address_family=address_family,
entry=entry,
max_entries=max_entries,
prefix_list_name=prefix_list_name,
region=self.region_name, # type: ignore[attr-defined]
tags=tags,
owner_id=owner_id,
)
self.managed_prefix_lists[managed_prefix_list.id] = managed_prefix_list
return managed_prefix_list
def describe_managed_prefix_lists(
self, prefix_list_ids: Optional[list[str]] = None, filters: Any = None
) -> list[ManagedPrefixList]:
managed_prefix_lists = list(self.managed_prefix_lists.values())
attr_pairs = (
("owner-id", "owner_id"),
("prefix-list-id", "id"),
("prefix-list-name", "prefix_list_name"),
)
if prefix_list_ids:
managed_prefix_lists = [
managed_prefix_list
for managed_prefix_list in managed_prefix_lists
if managed_prefix_list.id in prefix_list_ids
]
result = managed_prefix_lists
if filters:
result = filter_resources(result, filters, attr_pairs)
result = describe_tag_filter(filters, result)
for item in result.copy():
if not item.delete_counter:
self.managed_prefix_lists.pop(item.id, None)
result.remove(item)
if item.state == "delete-complete":
item.delete_counter -= 1
return result
def get_managed_prefix_list_entries(
self, prefix_list_id: str
) -> Optional[ManagedPrefixList]:
return self.managed_prefix_lists.get(prefix_list_id)
def delete_managed_prefix_list(self, prefix_list_id: str) -> ManagedPrefixList:
managed_prefix_list: ManagedPrefixList = self.managed_prefix_lists.get(
prefix_list_id
) # type: ignore
managed_prefix_list.state = "delete-complete"
return managed_prefix_list
def modify_managed_prefix_list(
self,
add_entry: list[dict[str, str]],
remove_entry: list[dict[str, str]],
prefix_list_id: Optional[str] = None,
current_version: Optional[str] = None,
prefix_list_name: Optional[str] = None,
) -> ManagedPrefixList:
managed_pl: ManagedPrefixList = self.managed_prefix_lists.get(prefix_list_id) # type: ignore
managed_pl.prefix_list_name = prefix_list_name
if remove_entry or add_entry:
latest_version = managed_pl.entries.get(managed_pl.version) # type: ignore[arg-type]
entries = (
managed_pl.entries.get(current_version, latest_version).copy() # type: ignore
if managed_pl.entries
else []
)
for item in entries.copy():
if item.get("Cidr", "") in [entry["Cidr"] for entry in remove_entry]:
entries.remove(item)
for item in add_entry:
if item not in entries.copy():
entries.append(item)
managed_pl.version += 1 # type: ignore[operator]
managed_pl.entries[managed_pl.version] = entries
managed_pl.state = "modify-complete"
return managed_pl
def _create_aws_managed_prefix_list(
self, name: str, address_family: str, entries: list[dict[str, str]]
) -> None:
managed_prefix_list = self.create_managed_prefix_list(
address_family=address_family,
entry=entries,
prefix_list_name=name,
owner_id="AWS",
)
managed_prefix_list.version = None
managed_prefix_list.max_entries = None
self.managed_prefix_lists[managed_prefix_list.id] = managed_prefix_list
def create_default_pls(self) -> None:
# See https://docs.aws.amazon.com/vpc/latest/userguide/working-with-aws-managed-prefix-lists.html
# S3
self._create_aws_managed_prefix_list(
name=f"com.amazonaws.{self.region_name}.s3", # type: ignore[attr-defined]
address_family="IPv4",
entries=[
{"Cidr": "52.216.0.0/15", "Description": "default"},
{"Cidr": "3.5.0.0/19", "Description": "default"},
{"Cidr": "54.231.0.0/16", "Description": "default"},
],
)
# DynamoDB
self._create_aws_managed_prefix_list(
name=f"com.amazonaws.{self.region_name}.dynamodb", # type: ignore[attr-defined]
address_family="IPv4",
entries=[
{"Cidr": "3.218.182.0/24", "Description": "default"},
{"Cidr": "3.218.180.0/23", "Description": "default"},
{"Cidr": "52.94.0.0/22", "Description": "default"},
{"Cidr": "52.119.224.0/20", "Description": "default"},
],
)
# CloudFront
self._create_aws_managed_prefix_list(
name="com.amazonaws.global.cloudfront.origin-facing",
address_family="IPv4",
entries=[
{"Cidr": "13.124.199.0/24", "Description": "default"},
{"Cidr": "130.176.0.0/18", "Description": "default"},
{"Cidr": "15.158.0.0/16", "Description": "default"},
{"Cidr": "18.68.0.0/16", "Description": "default"},
{"Cidr": "204.246.166.0/24", "Description": "default"},
{"Cidr": "205.251.218.0/24", "Description": "default"},
{"Cidr": "3.172.0.0/18", "Description": "default"},
{"Cidr": "54.239.208.0/21", "Description": "default"},
{"Cidr": "64.252.64.0/18", "Description": "default"},
{"Cidr": "70.132.0.0/18", "Description": "default"},
],
)
# Ground Station
self._create_aws_managed_prefix_list(
name="com.amazonaws.global.groundstation",
address_family="IPv4",
entries=[{"Cidr": "3.2.16.0/20", "Description": "default"}],
)
# VPC Lattice
self._create_aws_managed_prefix_list(
name=f"com.amazonaws.{self.region_name}.vpc-lattice", # type: ignore[attr-defined]
address_family="IPv4",
entries=[{"Cidr": "169.254.171.0/24", "Description": "default"}],
)
# VPC Lattice ipv6
self._create_aws_managed_prefix_list(
name=f"com.amazonaws.{self.region_name}.ipv6.vpc-lattice", # type: ignore[attr-defined]
address_family="IPv6",
entries=[{"Cidr": "fd00:ec2:80::/64", "Description": "default"}],
)
|