cartography 0.102.0rc1__py3-none-any.whl → 0.102.0rc2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of cartography might be problematic. Click here for more details.
- cartography/_version.py +1 -1
- cartography/intel/aws/ec2/route_tables.py +287 -0
- cartography/intel/aws/resources.py +2 -0
- cartography/models/aws/ec2/route_table_associations.py +87 -0
- cartography/models/aws/ec2/route_tables.py +121 -0
- cartography/models/aws/ec2/routes.py +77 -0
- {cartography-0.102.0rc1.dist-info → cartography-0.102.0rc2.dist-info}/METADATA +1 -1
- {cartography-0.102.0rc1.dist-info → cartography-0.102.0rc2.dist-info}/RECORD +12 -8
- {cartography-0.102.0rc1.dist-info → cartography-0.102.0rc2.dist-info}/WHEEL +0 -0
- {cartography-0.102.0rc1.dist-info → cartography-0.102.0rc2.dist-info}/entry_points.txt +0 -0
- {cartography-0.102.0rc1.dist-info → cartography-0.102.0rc2.dist-info}/licenses/LICENSE +0 -0
- {cartography-0.102.0rc1.dist-info → cartography-0.102.0rc2.dist-info}/top_level.txt +0 -0
cartography/_version.py
CHANGED
|
@@ -0,0 +1,287 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
from typing import Any
|
|
3
|
+
|
|
4
|
+
import boto3
|
|
5
|
+
import neo4j
|
|
6
|
+
|
|
7
|
+
from cartography.client.core.tx import load
|
|
8
|
+
from cartography.graph.job import GraphJob
|
|
9
|
+
from cartography.intel.aws.ec2.util import get_botocore_config
|
|
10
|
+
from cartography.models.aws.ec2.route_table_associations import RouteTableAssociationSchema
|
|
11
|
+
from cartography.models.aws.ec2.route_tables import RouteTableSchema
|
|
12
|
+
from cartography.models.aws.ec2.routes import RouteSchema
|
|
13
|
+
from cartography.util import aws_handle_regions
|
|
14
|
+
from cartography.util import timeit
|
|
15
|
+
|
|
16
|
+
logger = logging.getLogger(__name__)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def _get_route_id_and_target(route_table_id: str, route: dict[str, Any]) -> tuple[str, str | None]:
|
|
20
|
+
"""
|
|
21
|
+
Generate a unique identifier for an AWS EC2 route and return the target of the route
|
|
22
|
+
regardless of its type.
|
|
23
|
+
|
|
24
|
+
Args:
|
|
25
|
+
route_table_id: The ID of the route table this route belongs to
|
|
26
|
+
route: The route data from AWS API
|
|
27
|
+
|
|
28
|
+
Returns:
|
|
29
|
+
A tuple containing the unique identifier for the route and the target of the route
|
|
30
|
+
"""
|
|
31
|
+
route_target_keys = [
|
|
32
|
+
'DestinationCidrBlock',
|
|
33
|
+
'DestinationIpv6CidrBlock',
|
|
34
|
+
'GatewayId',
|
|
35
|
+
'InstanceId',
|
|
36
|
+
'NatGatewayId',
|
|
37
|
+
'TransitGatewayId',
|
|
38
|
+
'LocalGatewayId',
|
|
39
|
+
'CarrierGatewayId',
|
|
40
|
+
'NetworkInterfaceId',
|
|
41
|
+
'VpcPeeringConnectionId',
|
|
42
|
+
'EgressOnlyInternetGatewayId',
|
|
43
|
+
'CoreNetworkArn',
|
|
44
|
+
]
|
|
45
|
+
|
|
46
|
+
# Start with the route table ID
|
|
47
|
+
parts = [route_table_id]
|
|
48
|
+
target = None
|
|
49
|
+
found_target = False
|
|
50
|
+
|
|
51
|
+
for key in route_target_keys:
|
|
52
|
+
# Each route is a "union"-like data structure, so only one of the keys will be present.
|
|
53
|
+
if key in route:
|
|
54
|
+
parts.append(route[key])
|
|
55
|
+
target = route[key]
|
|
56
|
+
found_target = True
|
|
57
|
+
break
|
|
58
|
+
|
|
59
|
+
if not found_target:
|
|
60
|
+
logger.warning(
|
|
61
|
+
f"No target found for route in {route_table_id}. Please review the route and file an issue to "
|
|
62
|
+
"https://github.com/cartography-cncf/cartography/issues sharing what the route table looks like "
|
|
63
|
+
"so that we can update the available keys.",
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
return '|'.join(parts), target
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
@timeit
|
|
70
|
+
@aws_handle_regions
|
|
71
|
+
def get_route_tables(boto3_session: boto3.session.Session, region: str) -> list[dict[str, Any]]:
|
|
72
|
+
client = boto3_session.client('ec2', region_name=region, config=get_botocore_config())
|
|
73
|
+
paginator = client.get_paginator('describe_route_tables')
|
|
74
|
+
route_tables: list[dict[str, Any]] = []
|
|
75
|
+
for page in paginator.paginate():
|
|
76
|
+
route_tables.extend(page['RouteTables'])
|
|
77
|
+
return route_tables
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
def _transform_route_table_associations(
|
|
81
|
+
route_table_id: str,
|
|
82
|
+
associations: list[dict[str, Any]],
|
|
83
|
+
) -> tuple[list[dict[str, Any]], bool]:
|
|
84
|
+
"""
|
|
85
|
+
Transform route table association data into a format suitable for cartography ingestion.
|
|
86
|
+
|
|
87
|
+
Args:
|
|
88
|
+
route_table_id: The ID of the route table
|
|
89
|
+
associations: List of association data from AWS API
|
|
90
|
+
|
|
91
|
+
Returns:
|
|
92
|
+
1. List of transformed association data
|
|
93
|
+
2. Boolean indicating if the association is the main association, meaning that the route table is the main
|
|
94
|
+
route table for the VPC
|
|
95
|
+
"""
|
|
96
|
+
transformed = []
|
|
97
|
+
is_main = False
|
|
98
|
+
for association in associations:
|
|
99
|
+
if association.get('SubnetId'):
|
|
100
|
+
target = association['SubnetId']
|
|
101
|
+
elif association.get('GatewayId'):
|
|
102
|
+
target = association['GatewayId']
|
|
103
|
+
else:
|
|
104
|
+
is_main = True
|
|
105
|
+
target = 'main'
|
|
106
|
+
|
|
107
|
+
transformed_association = {
|
|
108
|
+
'id': association['RouteTableAssociationId'],
|
|
109
|
+
'route_table_id': route_table_id,
|
|
110
|
+
'subnet_id': association.get('SubnetId'),
|
|
111
|
+
'gateway_id': association.get('GatewayId'),
|
|
112
|
+
'main': association.get('Main', False),
|
|
113
|
+
'association_state': association.get('AssociationState', {}).get('State'),
|
|
114
|
+
'association_state_message': association.get('AssociationState', {}).get('Message'),
|
|
115
|
+
'_target': target,
|
|
116
|
+
}
|
|
117
|
+
transformed.append(transformed_association)
|
|
118
|
+
return transformed, is_main
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
def _transform_route_table_routes(route_table_id: str, routes: list[dict[str, Any]]) -> list[dict[str, Any]]:
|
|
122
|
+
"""
|
|
123
|
+
Transform route table route data into a format suitable for cartography ingestion.
|
|
124
|
+
|
|
125
|
+
Args:
|
|
126
|
+
route_table_id: The ID of the route table
|
|
127
|
+
routes: List of route data from AWS API
|
|
128
|
+
|
|
129
|
+
Returns:
|
|
130
|
+
List of transformed route data
|
|
131
|
+
"""
|
|
132
|
+
transformed = []
|
|
133
|
+
for route in routes:
|
|
134
|
+
route_id, target = _get_route_id_and_target(route_table_id, route)
|
|
135
|
+
|
|
136
|
+
transformed_route = {
|
|
137
|
+
'id': route_id,
|
|
138
|
+
'route_table_id': route_table_id,
|
|
139
|
+
'destination_cidr_block': route.get('DestinationCidrBlock'),
|
|
140
|
+
'destination_ipv6_cidr_block': route.get('DestinationIpv6CidrBlock'),
|
|
141
|
+
'gateway_id': route.get('GatewayId'),
|
|
142
|
+
'instance_id': route.get('InstanceId'),
|
|
143
|
+
'instance_owner_id': route.get('InstanceOwnerId'),
|
|
144
|
+
'nat_gateway_id': route.get('NatGatewayId'),
|
|
145
|
+
'transit_gateway_id': route.get('TransitGatewayId'),
|
|
146
|
+
'local_gateway_id': route.get('LocalGatewayId'),
|
|
147
|
+
'carrier_gateway_id': route.get('CarrierGatewayId'),
|
|
148
|
+
'network_interface_id': route.get('NetworkInterfaceId'),
|
|
149
|
+
'vpc_peering_connection_id': route.get('VpcPeeringConnectionId'),
|
|
150
|
+
'state': route.get('State'),
|
|
151
|
+
'origin': route.get('Origin'),
|
|
152
|
+
'core_network_arn': route.get('CoreNetworkArn'),
|
|
153
|
+
'destination_prefix_list_id': route.get('DestinationPrefixListId'),
|
|
154
|
+
'egress_only_internet_gateway_id': route.get('EgressOnlyInternetGatewayId'),
|
|
155
|
+
'_target': target,
|
|
156
|
+
}
|
|
157
|
+
transformed.append(transformed_route)
|
|
158
|
+
return transformed
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
def transform_route_table_data(
|
|
162
|
+
route_tables: list[dict[str, Any]],
|
|
163
|
+
) -> tuple[list[dict[str, Any]], list[dict[str, Any]], list[dict[str, Any]]]:
|
|
164
|
+
"""
|
|
165
|
+
Transform route table data into a format suitable for cartography ingestion.
|
|
166
|
+
|
|
167
|
+
Args:
|
|
168
|
+
route_tables: List of route table data from AWS API
|
|
169
|
+
|
|
170
|
+
Returns:
|
|
171
|
+
Tuple of (transformed route table data, transformed association data, transformed route data)
|
|
172
|
+
"""
|
|
173
|
+
transformed_tables = []
|
|
174
|
+
association_data = []
|
|
175
|
+
route_data = []
|
|
176
|
+
|
|
177
|
+
for rt in route_tables:
|
|
178
|
+
route_table_id = rt['RouteTableId']
|
|
179
|
+
|
|
180
|
+
# Transform routes
|
|
181
|
+
current_routes = []
|
|
182
|
+
if rt.get('Routes'):
|
|
183
|
+
current_routes = _transform_route_table_routes(route_table_id, rt['Routes'])
|
|
184
|
+
route_data.extend(current_routes)
|
|
185
|
+
|
|
186
|
+
# If the rt has a association marked with main=True, then it is the main route table for the VPC.
|
|
187
|
+
is_main = False
|
|
188
|
+
# Transform associations
|
|
189
|
+
if rt.get('Associations'):
|
|
190
|
+
associations, is_main = _transform_route_table_associations(route_table_id, rt['Associations'])
|
|
191
|
+
association_data.extend(associations)
|
|
192
|
+
|
|
193
|
+
transformed_rt = {
|
|
194
|
+
'id': route_table_id,
|
|
195
|
+
'route_table_id': route_table_id,
|
|
196
|
+
'owner_id': rt.get('OwnerId'),
|
|
197
|
+
'vpc_id': rt.get('VpcId'),
|
|
198
|
+
'VpnGatewayIds': [vgw['GatewayId'] for vgw in rt.get('PropagatingVgws', [])],
|
|
199
|
+
'RouteTableAssociationIds': [assoc['RouteTableAssociationId'] for assoc in rt.get('Associations', [])],
|
|
200
|
+
'RouteIds': [route['id'] for route in current_routes],
|
|
201
|
+
'tags': rt.get('Tags', []),
|
|
202
|
+
'main': is_main,
|
|
203
|
+
}
|
|
204
|
+
transformed_tables.append(transformed_rt)
|
|
205
|
+
|
|
206
|
+
return transformed_tables, association_data, route_data
|
|
207
|
+
|
|
208
|
+
|
|
209
|
+
@timeit
|
|
210
|
+
def load_route_tables(
|
|
211
|
+
neo4j_session: neo4j.Session,
|
|
212
|
+
data: list[dict[str, Any]],
|
|
213
|
+
region: str,
|
|
214
|
+
current_aws_account_id: str,
|
|
215
|
+
update_tag: int,
|
|
216
|
+
) -> None:
|
|
217
|
+
load(
|
|
218
|
+
neo4j_session,
|
|
219
|
+
RouteTableSchema(),
|
|
220
|
+
data,
|
|
221
|
+
Region=region,
|
|
222
|
+
AWS_ID=current_aws_account_id,
|
|
223
|
+
lastupdated=update_tag,
|
|
224
|
+
)
|
|
225
|
+
|
|
226
|
+
|
|
227
|
+
@timeit
|
|
228
|
+
def load_route_table_associations(
|
|
229
|
+
neo4j_session: neo4j.Session,
|
|
230
|
+
data: list[dict[str, Any]],
|
|
231
|
+
region: str,
|
|
232
|
+
current_aws_account_id: str,
|
|
233
|
+
update_tag: int,
|
|
234
|
+
) -> None:
|
|
235
|
+
load(
|
|
236
|
+
neo4j_session,
|
|
237
|
+
RouteTableAssociationSchema(),
|
|
238
|
+
data,
|
|
239
|
+
Region=region,
|
|
240
|
+
AWS_ID=current_aws_account_id,
|
|
241
|
+
lastupdated=update_tag,
|
|
242
|
+
)
|
|
243
|
+
|
|
244
|
+
|
|
245
|
+
@timeit
|
|
246
|
+
def load_routes(
|
|
247
|
+
neo4j_session: neo4j.Session,
|
|
248
|
+
data: list[dict[str, Any]],
|
|
249
|
+
region: str,
|
|
250
|
+
current_aws_account_id: str,
|
|
251
|
+
update_tag: int,
|
|
252
|
+
) -> None:
|
|
253
|
+
load(
|
|
254
|
+
neo4j_session,
|
|
255
|
+
RouteSchema(),
|
|
256
|
+
data,
|
|
257
|
+
Region=region,
|
|
258
|
+
AWS_ID=current_aws_account_id,
|
|
259
|
+
lastupdated=update_tag,
|
|
260
|
+
)
|
|
261
|
+
|
|
262
|
+
|
|
263
|
+
@timeit
|
|
264
|
+
def cleanup(neo4j_session: neo4j.Session, common_job_parameters: dict[str, Any]) -> None:
|
|
265
|
+
logger.debug("Running EC2 route tables cleanup")
|
|
266
|
+
GraphJob.from_node_schema(RouteTableSchema(), common_job_parameters).run(neo4j_session)
|
|
267
|
+
GraphJob.from_node_schema(RouteSchema(), common_job_parameters).run(neo4j_session)
|
|
268
|
+
GraphJob.from_node_schema(RouteTableAssociationSchema(), common_job_parameters).run(neo4j_session)
|
|
269
|
+
|
|
270
|
+
|
|
271
|
+
@timeit
|
|
272
|
+
def sync_route_tables(
|
|
273
|
+
neo4j_session: neo4j.Session,
|
|
274
|
+
boto3_session: boto3.session.Session,
|
|
275
|
+
regions: list[str],
|
|
276
|
+
current_aws_account_id: str,
|
|
277
|
+
update_tag: int,
|
|
278
|
+
common_job_parameters: dict[str, Any],
|
|
279
|
+
) -> None:
|
|
280
|
+
for region in regions:
|
|
281
|
+
logger.info("Syncing EC2 route tables for region '%s' in account '%s'.", region, current_aws_account_id)
|
|
282
|
+
route_tables = get_route_tables(boto3_session, region)
|
|
283
|
+
transformed_tables, association_data, route_data = transform_route_table_data(route_tables)
|
|
284
|
+
load_routes(neo4j_session, route_data, region, current_aws_account_id, update_tag)
|
|
285
|
+
load_route_table_associations(neo4j_session, association_data, region, current_aws_account_id, update_tag)
|
|
286
|
+
load_route_tables(neo4j_session, transformed_tables, region, current_aws_account_id, update_tag)
|
|
287
|
+
cleanup(neo4j_session, common_job_parameters)
|
|
@@ -45,6 +45,7 @@ from .ec2.volumes import sync_ebs_volumes
|
|
|
45
45
|
from .ec2.vpc import sync_vpc
|
|
46
46
|
from .ec2.vpc_peerings import sync_vpc_peerings
|
|
47
47
|
from .iam_instance_profiles import sync_iam_instance_profiles
|
|
48
|
+
from cartography.intel.aws.ec2.route_tables import sync_route_tables
|
|
48
49
|
|
|
49
50
|
RESOURCE_FUNCTIONS: Dict[str, Callable[..., None]] = {
|
|
50
51
|
'iam': iam.sync,
|
|
@@ -62,6 +63,7 @@ RESOURCE_FUNCTIONS: Dict[str, Callable[..., None]] = {
|
|
|
62
63
|
'ec2:load_balancer_v2': sync_load_balancer_v2s,
|
|
63
64
|
'ec2:network_acls': sync_network_acls,
|
|
64
65
|
'ec2:network_interface': sync_network_interfaces,
|
|
66
|
+
'ec2:route_table': sync_route_tables,
|
|
65
67
|
'ec2:security_group': sync_ec2_security_groupinfo,
|
|
66
68
|
'ec2:subnet': sync_subnets,
|
|
67
69
|
'ec2:tgw': sync_transit_gateways,
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
from dataclasses import dataclass
|
|
2
|
+
|
|
3
|
+
from cartography.models.core.common import PropertyRef
|
|
4
|
+
from cartography.models.core.nodes import CartographyNodeProperties
|
|
5
|
+
from cartography.models.core.nodes import CartographyNodeSchema
|
|
6
|
+
from cartography.models.core.relationships import CartographyRelProperties
|
|
7
|
+
from cartography.models.core.relationships import CartographyRelSchema
|
|
8
|
+
from cartography.models.core.relationships import LinkDirection
|
|
9
|
+
from cartography.models.core.relationships import make_target_node_matcher
|
|
10
|
+
from cartography.models.core.relationships import OtherRelationships
|
|
11
|
+
from cartography.models.core.relationships import TargetNodeMatcher
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
@dataclass(frozen=True)
|
|
15
|
+
class RouteTableAssociationNodeProperties(CartographyNodeProperties):
|
|
16
|
+
id: PropertyRef = PropertyRef('id')
|
|
17
|
+
route_table_association_id: PropertyRef = PropertyRef('id', extra_index=True)
|
|
18
|
+
target: PropertyRef = PropertyRef('_target')
|
|
19
|
+
gateway_id: PropertyRef = PropertyRef('gateway_id')
|
|
20
|
+
main: PropertyRef = PropertyRef('main')
|
|
21
|
+
route_table_id: PropertyRef = PropertyRef('route_table_id')
|
|
22
|
+
subnet_id: PropertyRef = PropertyRef('subnet_id')
|
|
23
|
+
association_state: PropertyRef = PropertyRef('association_state')
|
|
24
|
+
association_state_message: PropertyRef = PropertyRef('association_state_message')
|
|
25
|
+
region: PropertyRef = PropertyRef('Region', set_in_kwargs=True)
|
|
26
|
+
lastupdated: PropertyRef = PropertyRef('lastupdated', set_in_kwargs=True)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
@dataclass(frozen=True)
|
|
30
|
+
class RouteTableAssociationToAwsAccountRelProperties(CartographyRelProperties):
|
|
31
|
+
lastupdated: PropertyRef = PropertyRef('lastupdated', set_in_kwargs=True)
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
@dataclass(frozen=True)
|
|
35
|
+
class RouteTableAssociationToAWSAccount(CartographyRelSchema):
|
|
36
|
+
target_node_label: str = 'AWSAccount'
|
|
37
|
+
target_node_matcher: TargetNodeMatcher = make_target_node_matcher(
|
|
38
|
+
{'id': PropertyRef('AWS_ID', set_in_kwargs=True)},
|
|
39
|
+
)
|
|
40
|
+
direction: LinkDirection = LinkDirection.INWARD
|
|
41
|
+
rel_label: str = "RESOURCE"
|
|
42
|
+
properties: RouteTableAssociationToAwsAccountRelProperties = RouteTableAssociationToAwsAccountRelProperties()
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
@dataclass(frozen=True)
|
|
46
|
+
class RouteTableAssociationToSubnetRelProperties(CartographyRelProperties):
|
|
47
|
+
lastupdated: PropertyRef = PropertyRef('lastupdated', set_in_kwargs=True)
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
@dataclass(frozen=True)
|
|
51
|
+
class RouteTableAssociationToSubnet(CartographyRelSchema):
|
|
52
|
+
target_node_label: str = 'EC2Subnet'
|
|
53
|
+
target_node_matcher: TargetNodeMatcher = make_target_node_matcher(
|
|
54
|
+
{'subnetid': PropertyRef('subnet_id')},
|
|
55
|
+
)
|
|
56
|
+
direction: LinkDirection = LinkDirection.OUTWARD
|
|
57
|
+
rel_label: str = "ASSOCIATED_SUBNET"
|
|
58
|
+
properties: RouteTableAssociationToSubnetRelProperties = RouteTableAssociationToSubnetRelProperties()
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
@dataclass(frozen=True)
|
|
62
|
+
class RouteTableAssociationToIgwRelProperties(CartographyRelProperties):
|
|
63
|
+
lastupdated: PropertyRef = PropertyRef('lastupdated', set_in_kwargs=True)
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
@dataclass(frozen=True)
|
|
67
|
+
class RouteTableAssociationToIgw(CartographyRelSchema):
|
|
68
|
+
target_node_label: str = 'AWSInternetGateway'
|
|
69
|
+
target_node_matcher: TargetNodeMatcher = make_target_node_matcher(
|
|
70
|
+
{'id': PropertyRef('gateway_id')},
|
|
71
|
+
)
|
|
72
|
+
direction: LinkDirection = LinkDirection.OUTWARD
|
|
73
|
+
rel_label: str = "ASSOCIATED_IGW_FOR_INGRESS"
|
|
74
|
+
properties: RouteTableAssociationToIgwRelProperties = RouteTableAssociationToIgwRelProperties()
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
@dataclass(frozen=True)
|
|
78
|
+
class RouteTableAssociationSchema(CartographyNodeSchema):
|
|
79
|
+
label: str = 'EC2RouteTableAssociation'
|
|
80
|
+
properties: RouteTableAssociationNodeProperties = RouteTableAssociationNodeProperties()
|
|
81
|
+
sub_resource_relationship: RouteTableAssociationToAWSAccount = RouteTableAssociationToAWSAccount()
|
|
82
|
+
other_relationships: OtherRelationships = OtherRelationships(
|
|
83
|
+
[
|
|
84
|
+
RouteTableAssociationToSubnet(),
|
|
85
|
+
RouteTableAssociationToIgw(),
|
|
86
|
+
],
|
|
87
|
+
)
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
from dataclasses import dataclass
|
|
2
|
+
|
|
3
|
+
from cartography.models.core.common import PropertyRef
|
|
4
|
+
from cartography.models.core.nodes import CartographyNodeProperties
|
|
5
|
+
from cartography.models.core.nodes import CartographyNodeSchema
|
|
6
|
+
from cartography.models.core.relationships import CartographyRelProperties
|
|
7
|
+
from cartography.models.core.relationships import CartographyRelSchema
|
|
8
|
+
from cartography.models.core.relationships import LinkDirection
|
|
9
|
+
from cartography.models.core.relationships import make_target_node_matcher
|
|
10
|
+
from cartography.models.core.relationships import OtherRelationships
|
|
11
|
+
from cartography.models.core.relationships import TargetNodeMatcher
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
@dataclass(frozen=True)
|
|
15
|
+
class RouteTableNodeProperties(CartographyNodeProperties):
|
|
16
|
+
"""
|
|
17
|
+
Schema describing a RouteTable.
|
|
18
|
+
"""
|
|
19
|
+
id: PropertyRef = PropertyRef('id')
|
|
20
|
+
route_table_id: PropertyRef = PropertyRef('route_table_id', extra_index=True)
|
|
21
|
+
owner_id: PropertyRef = PropertyRef('owner_id')
|
|
22
|
+
vpc_id: PropertyRef = PropertyRef('VpcId')
|
|
23
|
+
region: PropertyRef = PropertyRef('Region', set_in_kwargs=True)
|
|
24
|
+
lastupdated: PropertyRef = PropertyRef('lastupdated', set_in_kwargs=True)
|
|
25
|
+
main: PropertyRef = PropertyRef('main')
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
@dataclass(frozen=True)
|
|
29
|
+
class RouteTableToAwsAccountRelProperties(CartographyRelProperties):
|
|
30
|
+
lastupdated: PropertyRef = PropertyRef('lastupdated', set_in_kwargs=True)
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
@dataclass(frozen=True)
|
|
34
|
+
class RouteTableToAWSAccount(CartographyRelSchema):
|
|
35
|
+
target_node_label: str = 'AWSAccount'
|
|
36
|
+
target_node_matcher: TargetNodeMatcher = make_target_node_matcher(
|
|
37
|
+
{'id': PropertyRef('AWS_ID', set_in_kwargs=True)},
|
|
38
|
+
)
|
|
39
|
+
direction: LinkDirection = LinkDirection.INWARD
|
|
40
|
+
rel_label: str = "RESOURCE"
|
|
41
|
+
properties: RouteTableToAwsAccountRelProperties = RouteTableToAwsAccountRelProperties()
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
@dataclass(frozen=True)
|
|
45
|
+
class RouteTableToVpcRelProperties(CartographyRelProperties):
|
|
46
|
+
lastupdated: PropertyRef = PropertyRef('lastupdated', set_in_kwargs=True)
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
@dataclass(frozen=True)
|
|
50
|
+
class RouteTableToVpc(CartographyRelSchema):
|
|
51
|
+
target_node_label: str = 'AWSVpc'
|
|
52
|
+
target_node_matcher: TargetNodeMatcher = make_target_node_matcher(
|
|
53
|
+
{'id': PropertyRef('vpc_id')},
|
|
54
|
+
)
|
|
55
|
+
direction: LinkDirection = LinkDirection.OUTWARD
|
|
56
|
+
rel_label: str = "MEMBER_OF_AWS_VPC"
|
|
57
|
+
properties: RouteTableToVpcRelProperties = RouteTableToVpcRelProperties()
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
@dataclass(frozen=True)
|
|
61
|
+
class RouteTableToRouteRelProperties(CartographyRelProperties):
|
|
62
|
+
lastupdated: PropertyRef = PropertyRef('lastupdated', set_in_kwargs=True)
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
@dataclass(frozen=True)
|
|
66
|
+
class RouteTableToRoute(CartographyRelSchema):
|
|
67
|
+
target_node_label: str = 'EC2Route'
|
|
68
|
+
target_node_matcher: TargetNodeMatcher = make_target_node_matcher(
|
|
69
|
+
{'id': PropertyRef('RouteIds', one_to_many=True)},
|
|
70
|
+
)
|
|
71
|
+
direction: LinkDirection = LinkDirection.OUTWARD
|
|
72
|
+
rel_label: str = "ROUTE"
|
|
73
|
+
properties: RouteTableToRouteRelProperties = RouteTableToRouteRelProperties()
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
@dataclass(frozen=True)
|
|
77
|
+
class RouteTableToAssociationRelProperties(CartographyRelProperties):
|
|
78
|
+
lastupdated: PropertyRef = PropertyRef('lastupdated', set_in_kwargs=True)
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
@dataclass(frozen=True)
|
|
82
|
+
class RouteTableToAssociation(CartographyRelSchema):
|
|
83
|
+
target_node_label: str = 'EC2RouteTableAssociation'
|
|
84
|
+
target_node_matcher: TargetNodeMatcher = make_target_node_matcher(
|
|
85
|
+
{'id': PropertyRef('RouteTableAssociationIds', one_to_many=True)},
|
|
86
|
+
)
|
|
87
|
+
direction: LinkDirection = LinkDirection.OUTWARD
|
|
88
|
+
rel_label: str = "ASSOCIATION"
|
|
89
|
+
properties: RouteTableToAssociationRelProperties = RouteTableToAssociationRelProperties()
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
@dataclass(frozen=True)
|
|
93
|
+
class RouteTableToVpnGatewayRelProperties(CartographyRelProperties):
|
|
94
|
+
lastupdated: PropertyRef = PropertyRef('lastupdated', set_in_kwargs=True)
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
# TODO implement AWSVpnGateways
|
|
98
|
+
@dataclass(frozen=True)
|
|
99
|
+
class RouteTableToVpnGateway(CartographyRelSchema):
|
|
100
|
+
target_node_label: str = 'AWSVpnGateway'
|
|
101
|
+
target_node_matcher: TargetNodeMatcher = make_target_node_matcher(
|
|
102
|
+
{'id': PropertyRef('VpnGatewayIds', one_to_many=True)},
|
|
103
|
+
)
|
|
104
|
+
direction: LinkDirection = LinkDirection.OUTWARD
|
|
105
|
+
rel_label: str = "CONNECTED_TO"
|
|
106
|
+
properties: RouteTableToVpnGatewayRelProperties = RouteTableToVpnGatewayRelProperties()
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
@dataclass(frozen=True)
|
|
110
|
+
class RouteTableSchema(CartographyNodeSchema):
|
|
111
|
+
label: str = 'EC2RouteTable'
|
|
112
|
+
properties: RouteTableNodeProperties = RouteTableNodeProperties()
|
|
113
|
+
sub_resource_relationship: RouteTableToAWSAccount = RouteTableToAWSAccount()
|
|
114
|
+
other_relationships: OtherRelationships = OtherRelationships(
|
|
115
|
+
[
|
|
116
|
+
RouteTableToVpc(),
|
|
117
|
+
RouteTableToRoute(),
|
|
118
|
+
RouteTableToAssociation(),
|
|
119
|
+
RouteTableToVpnGateway(),
|
|
120
|
+
],
|
|
121
|
+
)
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
from dataclasses import dataclass
|
|
2
|
+
|
|
3
|
+
from cartography.models.core.common import PropertyRef
|
|
4
|
+
from cartography.models.core.nodes import CartographyNodeProperties
|
|
5
|
+
from cartography.models.core.nodes import CartographyNodeSchema
|
|
6
|
+
from cartography.models.core.relationships import CartographyRelProperties
|
|
7
|
+
from cartography.models.core.relationships import CartographyRelSchema
|
|
8
|
+
from cartography.models.core.relationships import LinkDirection
|
|
9
|
+
from cartography.models.core.relationships import make_target_node_matcher
|
|
10
|
+
from cartography.models.core.relationships import OtherRelationships
|
|
11
|
+
from cartography.models.core.relationships import TargetNodeMatcher
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
@dataclass(frozen=True)
|
|
15
|
+
class RouteNodeProperties(CartographyNodeProperties):
|
|
16
|
+
id: PropertyRef = PropertyRef('id')
|
|
17
|
+
carrier_gateway_id: PropertyRef = PropertyRef('carrier_gateway_id')
|
|
18
|
+
core_network_arn: PropertyRef = PropertyRef('core_network_arn')
|
|
19
|
+
destination_cidr_block: PropertyRef = PropertyRef('destination_cidr_block')
|
|
20
|
+
destination_ipv6_cidr_block: PropertyRef = PropertyRef('destination_ipv6_cidr_block')
|
|
21
|
+
destination_prefix_list_id: PropertyRef = PropertyRef('destination_prefix_list_id')
|
|
22
|
+
egress_only_internet_gateway_id: PropertyRef = PropertyRef('egress_only_internet_gateway_id')
|
|
23
|
+
gateway_id: PropertyRef = PropertyRef('gateway_id')
|
|
24
|
+
instance_id: PropertyRef = PropertyRef('instance_id')
|
|
25
|
+
instance_owner_id: PropertyRef = PropertyRef('instance_owner_id')
|
|
26
|
+
local_gateway_id: PropertyRef = PropertyRef('local_gateway_id')
|
|
27
|
+
nat_gateway_id: PropertyRef = PropertyRef('nat_gateway_id')
|
|
28
|
+
network_interface_id: PropertyRef = PropertyRef('network_interface_id')
|
|
29
|
+
origin: PropertyRef = PropertyRef('origin')
|
|
30
|
+
state: PropertyRef = PropertyRef('state')
|
|
31
|
+
transit_gateway_id: PropertyRef = PropertyRef('transit_gateway_id')
|
|
32
|
+
vpc_peering_connection_id: PropertyRef = PropertyRef('vpc_peering_connection_id')
|
|
33
|
+
region: PropertyRef = PropertyRef('Region', set_in_kwargs=True)
|
|
34
|
+
lastupdated: PropertyRef = PropertyRef('lastupdated', set_in_kwargs=True)
|
|
35
|
+
target: PropertyRef = PropertyRef('_target')
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
@dataclass(frozen=True)
|
|
39
|
+
class RouteToAwsAccountRelProperties(CartographyRelProperties):
|
|
40
|
+
lastupdated: PropertyRef = PropertyRef('lastupdated', set_in_kwargs=True)
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
@dataclass(frozen=True)
|
|
44
|
+
class RouteToAWSAccount(CartographyRelSchema):
|
|
45
|
+
target_node_label: str = 'AWSAccount'
|
|
46
|
+
target_node_matcher: TargetNodeMatcher = make_target_node_matcher(
|
|
47
|
+
{'id': PropertyRef('AWS_ID', set_in_kwargs=True)},
|
|
48
|
+
)
|
|
49
|
+
direction: LinkDirection = LinkDirection.INWARD
|
|
50
|
+
rel_label: str = "RESOURCE"
|
|
51
|
+
properties: RouteToAwsAccountRelProperties = RouteToAwsAccountRelProperties()
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
@dataclass(frozen=True)
|
|
55
|
+
class RouteToInternetGatewayRelProperties(CartographyRelProperties):
|
|
56
|
+
lastupdated: PropertyRef = PropertyRef('lastupdated', set_in_kwargs=True)
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
@dataclass(frozen=True)
|
|
60
|
+
class RouteToInternetGateway(CartographyRelSchema):
|
|
61
|
+
target_node_label: str = 'AWSInternetGateway'
|
|
62
|
+
target_node_matcher: TargetNodeMatcher = make_target_node_matcher(
|
|
63
|
+
{'id': PropertyRef('gateway_id')},
|
|
64
|
+
)
|
|
65
|
+
direction: LinkDirection = LinkDirection.OUTWARD
|
|
66
|
+
rel_label: str = "ROUTES_TO_GATEWAY"
|
|
67
|
+
properties: RouteToInternetGatewayRelProperties = RouteToInternetGatewayRelProperties()
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
@dataclass(frozen=True)
|
|
71
|
+
class RouteSchema(CartographyNodeSchema):
|
|
72
|
+
label: str = 'EC2Route'
|
|
73
|
+
properties: RouteNodeProperties = RouteNodeProperties()
|
|
74
|
+
sub_resource_relationship: RouteToAWSAccount = RouteToAWSAccount()
|
|
75
|
+
other_relationships: OtherRelationships = OtherRelationships([
|
|
76
|
+
RouteToInternetGateway(),
|
|
77
|
+
])
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
cartography/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
2
|
cartography/__main__.py,sha256=JftXT_nUPkqcEh8uxCCT4n-OyHYqbldEgrDS-4ygy0U,101
|
|
3
|
-
cartography/_version.py,sha256=
|
|
3
|
+
cartography/_version.py,sha256=OI9fh-YQyeutwYIFkGxdZOniCKb7_CUDhbEwgHnJdYI,518
|
|
4
4
|
cartography/cli.py,sha256=-fGIdBx3IwauUeYojsb-NnQPma2wtS7mFRgOETyfCg4,34796
|
|
5
5
|
cartography/config.py,sha256=xXM0OqsDl5Du55C-hr2LgjdtpU1_znPsmAgujrPGPgo,12553
|
|
6
6
|
cartography/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -160,7 +160,7 @@ cartography/intel/aws/permission_relationships.py,sha256=IarV9gt5BaplZ5TPo_mfypt
|
|
|
160
160
|
cartography/intel/aws/rds.py,sha256=vnlNYmrO2Cc0PNn31CeG2QwYhwjVosbQFE9Ol1vQyLE,25252
|
|
161
161
|
cartography/intel/aws/redshift.py,sha256=KOqiXIllHmtPTeaNGl-cX4srY5pFE6o12j8MQ5-zWpc,6694
|
|
162
162
|
cartography/intel/aws/resourcegroupstaggingapi.py,sha256=I2VrL-oplGj2Jyhbo312V6vnER_FXpJRrc6OBJ-_VmI,10375
|
|
163
|
-
cartography/intel/aws/resources.py,sha256=
|
|
163
|
+
cartography/intel/aws/resources.py,sha256=jb2U6xsrwwp2AYirqHYc09ttOpIqYEsk-CR7He-qgzQ,3652
|
|
164
164
|
cartography/intel/aws/route53.py,sha256=IYqeQud1HuHnf11A7T-Jeif5DWgjpaaU-Jfr2cLUc_o,14099
|
|
165
165
|
cartography/intel/aws/s3.py,sha256=SVxUMtMSkbdjZv5qOSYIbYb8BQa-QTojbHG85-EFWLA,27034
|
|
166
166
|
cartography/intel/aws/secretsmanager.py,sha256=YogwRPT6qZPVg5HrND71zI-nNn60oxoWaW7eUlhuTS0,3304
|
|
@@ -180,6 +180,7 @@ cartography/intel/aws/ec2/load_balancers.py,sha256=ah9-lXvipzVDjGFqfpNCrEyBfdu-B
|
|
|
180
180
|
cartography/intel/aws/ec2/network_acls.py,sha256=_UiOx79OxcqH0ecRjcVMglAzz5XJ4aVYLlv6dl_ism4,6809
|
|
181
181
|
cartography/intel/aws/ec2/network_interfaces.py,sha256=CzF8PooCYUQ2pk8DR8JDAhkWRUQSBj_27OsIfkL_-Cs,9199
|
|
182
182
|
cartography/intel/aws/ec2/reserved_instances.py,sha256=jv8-VLI5KL8jN1QRI20yim8lzZ7I7wR8a5EF8DckahA,3122
|
|
183
|
+
cartography/intel/aws/ec2/route_tables.py,sha256=h3oXZP1TCUeEbjmknIgSIDGHmmofXrqtBK45lXh06cQ,10182
|
|
183
184
|
cartography/intel/aws/ec2/security_groups.py,sha256=vxLeaCpCowkbl-YpON1UdbjtPolMfj_reOEuKujN80Y,6060
|
|
184
185
|
cartography/intel/aws/ec2/snapshots.py,sha256=R3U6ZwE4bQPy5yikLCRcUHyXN1dD7TzS-3jULQO-F0g,5432
|
|
185
186
|
cartography/intel/aws/ec2/subnets.py,sha256=42KODMXswv4OCVnkWDHZbZDLUnc_ZAD-1TDMk88rWdo,3892
|
|
@@ -307,6 +308,9 @@ cartography/models/aws/ec2/networkinterface_instance.py,sha256=t3oqcQ4GjYf7dwqPU
|
|
|
307
308
|
cartography/models/aws/ec2/networkinterfaces.py,sha256=z1-Dl6I79-TCxXKG8QBpSKga93lPCPaLR1XqKJZK3ME,4127
|
|
308
309
|
cartography/models/aws/ec2/privateip_networkinterface.py,sha256=j8MyiZsiUCuzuGUH_4PBKV3rLTk1GkE-SZb6K11oSdM,3038
|
|
309
310
|
cartography/models/aws/ec2/reservations.py,sha256=dE9uSB3Em-ca1dDbetbu79JXr4ZWHC3r5gA1S3mjhVU,1930
|
|
311
|
+
cartography/models/aws/ec2/route_table_associations.py,sha256=MfP41U64XM86G0VMz_kbmlOc4cxMG6MbVWk1mfVoTaI,3846
|
|
312
|
+
cartography/models/aws/ec2/route_tables.py,sha256=qFdfb1QExqJ8r3wCMUPaticWY_ppoLKEjyZx8Xs9etE,4725
|
|
313
|
+
cartography/models/aws/ec2/routes.py,sha256=qmWkhvNavycKv422ih0b3jUYd02tOgHNAuIpivwj6XM,3626
|
|
310
314
|
cartography/models/aws/ec2/securitygroup_instance.py,sha256=RZS9TzHHatTOESQgcs5_YHmF9sM7pRkUq2VPjk9FJlU,2876
|
|
311
315
|
cartography/models/aws/ec2/securitygroup_networkinterface.py,sha256=PiaA8J82kybZyZ1wDsa-ACIDa88vt4NoA3smGNiwl14,2399
|
|
312
316
|
cartography/models/aws/ec2/subnet_instance.py,sha256=ct_ibXiPN2C5ld06TczwSTXtsnlov5VCW6elphtbvPs,2752
|
|
@@ -369,9 +373,9 @@ cartography/models/snipeit/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJ
|
|
|
369
373
|
cartography/models/snipeit/asset.py,sha256=FyRAaeXuZjMy0eUQcSDFcgEAF5lbLMlvqp1Tv9d3Lv4,3238
|
|
370
374
|
cartography/models/snipeit/tenant.py,sha256=p4rFnpNNuF1W5ilGBbexDaETWTwavfb38RcQGoImkQI,679
|
|
371
375
|
cartography/models/snipeit/user.py,sha256=MsB4MiCVNTH6JpESime7cOkB89autZOXQpL6Z0l7L6o,2113
|
|
372
|
-
cartography-0.102.
|
|
373
|
-
cartography-0.102.
|
|
374
|
-
cartography-0.102.
|
|
375
|
-
cartography-0.102.
|
|
376
|
-
cartography-0.102.
|
|
377
|
-
cartography-0.102.
|
|
376
|
+
cartography-0.102.0rc2.dist-info/licenses/LICENSE,sha256=kvLEBRYaQ1RvUni6y7Ti9uHeooqnjPoo6n_-0JO1ETc,11351
|
|
377
|
+
cartography-0.102.0rc2.dist-info/METADATA,sha256=n51HlV7I_bq7yGnIkU9rXzv-D7mOeJHXIU7HeQl3lO8,12087
|
|
378
|
+
cartography-0.102.0rc2.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
|
|
379
|
+
cartography-0.102.0rc2.dist-info/entry_points.txt,sha256=GVIAWD0o0_K077qMA_k1oZU4v-M0a8GLKGJR8tZ-qH8,112
|
|
380
|
+
cartography-0.102.0rc2.dist-info/top_level.txt,sha256=BHqsNJQiI6Q72DeypC1IINQJE59SLhU4nllbQjgJi9g,12
|
|
381
|
+
cartography-0.102.0rc2.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|