cartography 0.110.0rc2__py3-none-any.whl → 0.111.0rc1__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 +16 -3
- cartography/data/indexes.cypher +0 -2
- cartography/graph/querybuilder.py +70 -0
- cartography/intel/aws/apigateway.py +111 -4
- cartography/intel/aws/ec2/vpc.py +140 -124
- cartography/intel/aws/eventbridge.py +73 -0
- cartography/intel/github/repos.py +9 -2
- cartography/models/aws/apigateway/apigatewaydeployment.py +74 -0
- cartography/models/aws/ec2/vpc.py +46 -0
- cartography/models/aws/ec2/vpc_cidr.py +102 -0
- cartography/models/aws/eventbridge/target.py +71 -0
- cartography/models/tailscale/device.py +1 -0
- {cartography-0.110.0rc2.dist-info → cartography-0.111.0rc1.dist-info}/METADATA +1 -1
- {cartography-0.110.0rc2.dist-info → cartography-0.111.0rc1.dist-info}/RECORD +23 -20
- cartography/data/jobs/cleanup/aws_import_vpc_cleanup.json +0 -23
- /cartography/models/aws/{__init__.py → apigateway/__init__.py} +0 -0
- /cartography/models/aws/{apigateway.py → apigateway/apigateway.py} +0 -0
- /cartography/models/aws/{apigatewaycertificate.py → apigateway/apigatewaycertificate.py} +0 -0
- /cartography/models/aws/{apigatewayresource.py → apigateway/apigatewayresource.py} +0 -0
- /cartography/models/aws/{apigatewaystage.py → apigateway/apigatewaystage.py} +0 -0
- {cartography-0.110.0rc2.dist-info → cartography-0.111.0rc1.dist-info}/WHEEL +0 -0
- {cartography-0.110.0rc2.dist-info → cartography-0.111.0rc1.dist-info}/entry_points.txt +0 -0
- {cartography-0.110.0rc2.dist-info → cartography-0.111.0rc1.dist-info}/licenses/LICENSE +0 -0
- {cartography-0.110.0rc2.dist-info → cartography-0.111.0rc1.dist-info}/top_level.txt +0 -0
cartography/_version.py
CHANGED
|
@@ -1,7 +1,14 @@
|
|
|
1
1
|
# file generated by setuptools-scm
|
|
2
2
|
# don't change, don't track in version control
|
|
3
3
|
|
|
4
|
-
__all__ = [
|
|
4
|
+
__all__ = [
|
|
5
|
+
"__version__",
|
|
6
|
+
"__version_tuple__",
|
|
7
|
+
"version",
|
|
8
|
+
"version_tuple",
|
|
9
|
+
"__commit_id__",
|
|
10
|
+
"commit_id",
|
|
11
|
+
]
|
|
5
12
|
|
|
6
13
|
TYPE_CHECKING = False
|
|
7
14
|
if TYPE_CHECKING:
|
|
@@ -9,13 +16,19 @@ if TYPE_CHECKING:
|
|
|
9
16
|
from typing import Union
|
|
10
17
|
|
|
11
18
|
VERSION_TUPLE = Tuple[Union[int, str], ...]
|
|
19
|
+
COMMIT_ID = Union[str, None]
|
|
12
20
|
else:
|
|
13
21
|
VERSION_TUPLE = object
|
|
22
|
+
COMMIT_ID = object
|
|
14
23
|
|
|
15
24
|
version: str
|
|
16
25
|
__version__: str
|
|
17
26
|
__version_tuple__: VERSION_TUPLE
|
|
18
27
|
version_tuple: VERSION_TUPLE
|
|
28
|
+
commit_id: COMMIT_ID
|
|
29
|
+
__commit_id__: COMMIT_ID
|
|
19
30
|
|
|
20
|
-
__version__ = version = '0.
|
|
21
|
-
__version_tuple__ = version_tuple = (0,
|
|
31
|
+
__version__ = version = '0.111.0rc1'
|
|
32
|
+
__version_tuple__ = version_tuple = (0, 111, 0, 'rc1')
|
|
33
|
+
|
|
34
|
+
__commit_id__ = commit_id = None
|
cartography/data/indexes.cypher
CHANGED
|
@@ -51,8 +51,6 @@ CREATE INDEX IF NOT EXISTS FOR (n:AWSTransitGatewayAttachment) ON (n.lastupdated
|
|
|
51
51
|
CREATE INDEX IF NOT EXISTS FOR (n:AWSUser) ON (n.arn);
|
|
52
52
|
CREATE INDEX IF NOT EXISTS FOR (n:AWSUser) ON (n.name);
|
|
53
53
|
CREATE INDEX IF NOT EXISTS FOR (n:AWSUser) ON (n.lastupdated);
|
|
54
|
-
CREATE INDEX IF NOT EXISTS FOR (n:AWSVpc) ON (n.id);
|
|
55
|
-
CREATE INDEX IF NOT EXISTS FOR (n:AWSVpc) ON (n.lastupdated);
|
|
56
54
|
CREATE INDEX IF NOT EXISTS FOR (n:AccountAccessKey) ON (n.accesskeyid);
|
|
57
55
|
CREATE INDEX IF NOT EXISTS FOR (n:AccountAccessKey) ON (n.lastupdated);
|
|
58
56
|
CREATE INDEX IF NOT EXISTS FOR (n:AutoScalingGroup) ON (n.arn);
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import logging
|
|
2
2
|
from dataclasses import asdict
|
|
3
|
+
from importlib.metadata import PackageNotFoundError
|
|
4
|
+
from importlib.metadata import version
|
|
3
5
|
from string import Template
|
|
4
6
|
from typing import Dict
|
|
5
7
|
from typing import List
|
|
@@ -223,6 +225,8 @@ def _build_attach_sub_resource_statement(
|
|
|
223
225
|
$RelMergeClause
|
|
224
226
|
ON CREATE SET r.firstseen = timestamp()
|
|
225
227
|
SET
|
|
228
|
+
r._module_name = "$module_name",
|
|
229
|
+
r._module_version = "$module_version",
|
|
226
230
|
$set_rel_properties_statement
|
|
227
231
|
""",
|
|
228
232
|
)
|
|
@@ -244,6 +248,8 @@ def _build_attach_sub_resource_statement(
|
|
|
244
248
|
SubResourceLabel=sub_resource_link.target_node_label,
|
|
245
249
|
MatchClause=_build_match_clause(sub_resource_link.target_node_matcher),
|
|
246
250
|
RelMergeClause=rel_merge_clause,
|
|
251
|
+
module_name=_get_module_from_schema(sub_resource_link),
|
|
252
|
+
module_version=_get_cartography_version(),
|
|
247
253
|
SubResourceRelLabel=sub_resource_link.rel_label,
|
|
248
254
|
set_rel_properties_statement=_build_rel_properties_statement(
|
|
249
255
|
"r",
|
|
@@ -278,6 +284,8 @@ def _build_attach_additional_links_statement(
|
|
|
278
284
|
$RelMerge
|
|
279
285
|
ON CREATE SET $rel_var.firstseen = timestamp()
|
|
280
286
|
SET
|
|
287
|
+
$rel_var._module_name = "$module_name",
|
|
288
|
+
$rel_var._module_version = "$module_version",
|
|
281
289
|
$set_rel_properties_statement
|
|
282
290
|
""",
|
|
283
291
|
)
|
|
@@ -312,6 +320,8 @@ def _build_attach_additional_links_statement(
|
|
|
312
320
|
node_var=node_var,
|
|
313
321
|
rel_var=rel_var,
|
|
314
322
|
RelMerge=rel_merge,
|
|
323
|
+
module_name=_get_module_from_schema(link),
|
|
324
|
+
module_version=_get_cartography_version(),
|
|
315
325
|
set_rel_properties_statement=_build_rel_properties_statement(
|
|
316
326
|
rel_var,
|
|
317
327
|
rel_props_as_dict,
|
|
@@ -453,6 +463,8 @@ def build_ingestion_query(
|
|
|
453
463
|
MERGE (i:$node_label{id: $dict_id_field})
|
|
454
464
|
ON CREATE SET i.firstseen = timestamp()
|
|
455
465
|
SET
|
|
466
|
+
i._module_name = "$module_name",
|
|
467
|
+
i._module_version = "$module_version",
|
|
456
468
|
$set_node_properties_statement
|
|
457
469
|
$attach_relationships_statement
|
|
458
470
|
""",
|
|
@@ -475,6 +487,8 @@ def build_ingestion_query(
|
|
|
475
487
|
ingest_query = query_template.safe_substitute(
|
|
476
488
|
node_label=node_schema.label,
|
|
477
489
|
dict_id_field=node_props.id,
|
|
490
|
+
module_name=_get_module_from_schema(node_schema),
|
|
491
|
+
module_version=_get_cartography_version(),
|
|
478
492
|
set_node_properties_statement=_build_node_properties_statement(
|
|
479
493
|
node_props_as_dict,
|
|
480
494
|
node_schema.extra_node_labels,
|
|
@@ -650,6 +664,8 @@ def build_matchlink_query(rel_schema: CartographyRelSchema) -> str:
|
|
|
650
664
|
MERGE $rel
|
|
651
665
|
ON CREATE SET r.firstseen = timestamp()
|
|
652
666
|
SET
|
|
667
|
+
r._module_name = "$module_name",
|
|
668
|
+
r._module_version = "$module_version",
|
|
653
669
|
$set_rel_properties_statement;
|
|
654
670
|
"""
|
|
655
671
|
)
|
|
@@ -677,8 +693,62 @@ def build_matchlink_query(rel_schema: CartographyRelSchema) -> str:
|
|
|
677
693
|
source_match=source_match,
|
|
678
694
|
target_match=target_match,
|
|
679
695
|
rel=rel,
|
|
696
|
+
module_name=_get_module_from_schema(rel_schema),
|
|
697
|
+
module_version=_get_cartography_version(),
|
|
680
698
|
set_rel_properties_statement=_build_rel_properties_statement(
|
|
681
699
|
"r",
|
|
682
700
|
rel_props_as_dict,
|
|
683
701
|
),
|
|
684
702
|
)
|
|
703
|
+
|
|
704
|
+
|
|
705
|
+
def _get_cartography_version() -> str:
|
|
706
|
+
"""
|
|
707
|
+
Get the current version of the cartography package.
|
|
708
|
+
|
|
709
|
+
This function attempts to retrieve the version of the installed cartography package
|
|
710
|
+
using importlib.metadata. If the package is not found (typically in development
|
|
711
|
+
or testing environments), it returns 'dev' as a fallback.
|
|
712
|
+
|
|
713
|
+
Returns:
|
|
714
|
+
The version string of the cartography package, or 'dev' if not found
|
|
715
|
+
"""
|
|
716
|
+
try:
|
|
717
|
+
return version("cartography")
|
|
718
|
+
except PackageNotFoundError:
|
|
719
|
+
# This can occured if the cartography package is not installed in the environment, typically in development or testing environments.
|
|
720
|
+
logger.warning("cartography package not found. Returning 'dev' version.")
|
|
721
|
+
# Fallback to reading the VERSION file if the package is not found
|
|
722
|
+
return "dev"
|
|
723
|
+
|
|
724
|
+
|
|
725
|
+
def _get_module_from_schema(
|
|
726
|
+
schema, #: "CartographyNodeSchema" | "CartographyRelSchema",
|
|
727
|
+
) -> str:
|
|
728
|
+
"""
|
|
729
|
+
Extract the module name from a Cartography schema object.
|
|
730
|
+
|
|
731
|
+
This function extracts and formats the module name from a CartographyNodeSchema
|
|
732
|
+
or CartographyRelSchema object. It expects schemas to be part of the official
|
|
733
|
+
cartography.models package hierarchy and returns a formatted string indicating
|
|
734
|
+
the specific cartography module.
|
|
735
|
+
|
|
736
|
+
Args:
|
|
737
|
+
schema: A CartographyNodeSchema or CartographyRelSchema object
|
|
738
|
+
|
|
739
|
+
Returns:
|
|
740
|
+
A formatted module name string in the format 'cartography:<module_name>'
|
|
741
|
+
or 'unknown:<full_module_path>' if the schema is not from cartography.models
|
|
742
|
+
"""
|
|
743
|
+
# If the entity schema does not belong to the cartography.models package,
|
|
744
|
+
# we log a warning and return the full module path.
|
|
745
|
+
if not schema.__module__.startswith("cartography.models."):
|
|
746
|
+
logger.warning(
|
|
747
|
+
"The schema %s does not start with 'cartography.models.'. "
|
|
748
|
+
"This may indicate that the schema is not part of the official cartography models.",
|
|
749
|
+
schema.__module__,
|
|
750
|
+
)
|
|
751
|
+
return f"unknown:{schema.__module__}"
|
|
752
|
+
# Otherwise, we return the module path as a string.
|
|
753
|
+
parts = schema.__module__.split(".")
|
|
754
|
+
return f"cartography:{parts[2]}"
|
|
@@ -14,12 +14,18 @@ from policyuniverse.policy import Policy
|
|
|
14
14
|
|
|
15
15
|
from cartography.client.core.tx import load
|
|
16
16
|
from cartography.graph.job import GraphJob
|
|
17
|
-
from cartography.
|
|
18
|
-
from cartography.models.aws.
|
|
17
|
+
from cartography.intel.aws.ec2.util import get_botocore_config
|
|
18
|
+
from cartography.models.aws.apigateway.apigateway import APIGatewayRestAPISchema
|
|
19
|
+
from cartography.models.aws.apigateway.apigatewaycertificate import (
|
|
19
20
|
APIGatewayClientCertificateSchema,
|
|
20
21
|
)
|
|
21
|
-
from cartography.models.aws.
|
|
22
|
-
|
|
22
|
+
from cartography.models.aws.apigateway.apigatewaydeployment import (
|
|
23
|
+
APIGatewayDeploymentSchema,
|
|
24
|
+
)
|
|
25
|
+
from cartography.models.aws.apigateway.apigatewayresource import (
|
|
26
|
+
APIGatewayResourceSchema,
|
|
27
|
+
)
|
|
28
|
+
from cartography.models.aws.apigateway.apigatewaystage import APIGatewayStageSchema
|
|
23
29
|
from cartography.util import aws_handle_regions
|
|
24
30
|
from cartography.util import timeit
|
|
25
31
|
|
|
@@ -40,6 +46,38 @@ def get_apigateway_rest_apis(
|
|
|
40
46
|
return apis
|
|
41
47
|
|
|
42
48
|
|
|
49
|
+
def get_rest_api_ids(
|
|
50
|
+
rest_apis: List[Dict],
|
|
51
|
+
) -> List[str]:
|
|
52
|
+
"""
|
|
53
|
+
Extracts the IDs of the REST APIs from the provided list.
|
|
54
|
+
"""
|
|
55
|
+
return [api["id"] for api in rest_apis if "id" in api]
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
@timeit
|
|
59
|
+
@aws_handle_regions
|
|
60
|
+
def get_rest_api_deployments(
|
|
61
|
+
boto3_session: boto3.session.Session,
|
|
62
|
+
rest_api_ids: List[str],
|
|
63
|
+
region: str,
|
|
64
|
+
) -> List[Dict[str, Any]]:
|
|
65
|
+
"""
|
|
66
|
+
Retrieves the deployments for each REST API in the provided list.
|
|
67
|
+
"""
|
|
68
|
+
client = boto3_session.client(
|
|
69
|
+
"apigateway", region_name=region, config=get_botocore_config()
|
|
70
|
+
)
|
|
71
|
+
deployments: List[Dict[str, Any]] = []
|
|
72
|
+
for api_id in rest_api_ids:
|
|
73
|
+
paginator = client.get_paginator("get_deployments")
|
|
74
|
+
for page in paginator.paginate(restApiId=api_id):
|
|
75
|
+
for deployment in page.get("items", []):
|
|
76
|
+
deployment["api_id"] = api_id
|
|
77
|
+
deployments.append(deployment)
|
|
78
|
+
return deployments
|
|
79
|
+
|
|
80
|
+
|
|
43
81
|
@timeit
|
|
44
82
|
@aws_handle_regions
|
|
45
83
|
def get_rest_api_details(
|
|
@@ -244,6 +282,25 @@ def transform_rest_api_details(
|
|
|
244
282
|
return stages, certificates, resources
|
|
245
283
|
|
|
246
284
|
|
|
285
|
+
def transform_apigateway_deployments(
|
|
286
|
+
deployments: List[Dict[str, Any]],
|
|
287
|
+
region: str,
|
|
288
|
+
) -> List[Dict[str, Any]]:
|
|
289
|
+
"""
|
|
290
|
+
Transform API Gateway Deployment data for ingestion
|
|
291
|
+
"""
|
|
292
|
+
transformed_deployments = []
|
|
293
|
+
for deployment in deployments:
|
|
294
|
+
transformed_deployment = {
|
|
295
|
+
"id": f"{deployment['api_id']}/{deployment['id']}",
|
|
296
|
+
"api_id": deployment["api_id"],
|
|
297
|
+
"description": deployment.get("description"),
|
|
298
|
+
"region": region,
|
|
299
|
+
}
|
|
300
|
+
transformed_deployments.append(transformed_deployment)
|
|
301
|
+
return transformed_deployments
|
|
302
|
+
|
|
303
|
+
|
|
247
304
|
@timeit
|
|
248
305
|
def load_rest_api_details(
|
|
249
306
|
neo4j_session: neo4j.Session,
|
|
@@ -283,6 +340,30 @@ def load_rest_api_details(
|
|
|
283
340
|
)
|
|
284
341
|
|
|
285
342
|
|
|
343
|
+
@timeit
|
|
344
|
+
def load_apigateway_deployments(
|
|
345
|
+
neo4j_session: neo4j.Session,
|
|
346
|
+
data: List[Dict[str, Any]],
|
|
347
|
+
region: str,
|
|
348
|
+
current_aws_account_id: str,
|
|
349
|
+
aws_update_tag: int,
|
|
350
|
+
) -> None:
|
|
351
|
+
"""
|
|
352
|
+
Load API Gateway Deployment data into neo4j.
|
|
353
|
+
"""
|
|
354
|
+
logger.info(
|
|
355
|
+
f"Loading API Gateway {len(data)} deployments for region '{region}' into graph.",
|
|
356
|
+
)
|
|
357
|
+
load(
|
|
358
|
+
neo4j_session,
|
|
359
|
+
APIGatewayDeploymentSchema(),
|
|
360
|
+
data,
|
|
361
|
+
region=region,
|
|
362
|
+
lastupdated=aws_update_tag,
|
|
363
|
+
AWS_ID=current_aws_account_id,
|
|
364
|
+
)
|
|
365
|
+
|
|
366
|
+
|
|
286
367
|
@timeit
|
|
287
368
|
def parse_policy(api_id: str, policy: Policy) -> Optional[Dict[Any, Any]]:
|
|
288
369
|
"""
|
|
@@ -345,6 +426,12 @@ def cleanup(neo4j_session: neo4j.Session, common_job_parameters: Dict) -> None:
|
|
|
345
426
|
)
|
|
346
427
|
cleanup_job.run(neo4j_session)
|
|
347
428
|
|
|
429
|
+
cleanup_job = GraphJob.from_node_schema(
|
|
430
|
+
APIGatewayDeploymentSchema(),
|
|
431
|
+
common_job_parameters,
|
|
432
|
+
)
|
|
433
|
+
cleanup_job.run(neo4j_session)
|
|
434
|
+
|
|
348
435
|
|
|
349
436
|
@timeit
|
|
350
437
|
def sync_apigateway_rest_apis(
|
|
@@ -375,6 +462,19 @@ def sync_apigateway_rest_apis(
|
|
|
375
462
|
current_aws_account_id,
|
|
376
463
|
aws_update_tag,
|
|
377
464
|
)
|
|
465
|
+
|
|
466
|
+
api_ids = get_rest_api_ids(rest_apis)
|
|
467
|
+
deployments = get_rest_api_deployments(
|
|
468
|
+
boto3_session,
|
|
469
|
+
api_ids,
|
|
470
|
+
region,
|
|
471
|
+
)
|
|
472
|
+
|
|
473
|
+
transformed_deployments = transform_apigateway_deployments(
|
|
474
|
+
deployments,
|
|
475
|
+
region,
|
|
476
|
+
)
|
|
477
|
+
|
|
378
478
|
load_apigateway_rest_apis(
|
|
379
479
|
neo4j_session,
|
|
380
480
|
transformed_apis,
|
|
@@ -388,6 +488,13 @@ def sync_apigateway_rest_apis(
|
|
|
388
488
|
current_aws_account_id,
|
|
389
489
|
aws_update_tag,
|
|
390
490
|
)
|
|
491
|
+
load_apigateway_deployments(
|
|
492
|
+
neo4j_session,
|
|
493
|
+
transformed_deployments,
|
|
494
|
+
region,
|
|
495
|
+
current_aws_account_id,
|
|
496
|
+
aws_update_tag,
|
|
497
|
+
)
|
|
391
498
|
|
|
392
499
|
|
|
393
500
|
@timeit
|
cartography/intel/aws/ec2/vpc.py
CHANGED
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
import logging
|
|
2
|
-
from
|
|
3
|
-
from typing import Dict
|
|
4
|
-
from typing import List
|
|
2
|
+
from typing import Any
|
|
5
3
|
|
|
6
4
|
import boto3
|
|
7
5
|
import neo4j
|
|
8
6
|
|
|
7
|
+
from cartography.client.core.tx import load
|
|
8
|
+
from cartography.graph.job import GraphJob
|
|
9
|
+
from cartography.models.aws.ec2.vpc import AWSVpcSchema
|
|
10
|
+
from cartography.models.aws.ec2.vpc_cidr import AWSIPv4CidrBlockSchema
|
|
11
|
+
from cartography.models.aws.ec2.vpc_cidr import AWSIPv6CidrBlockSchema
|
|
9
12
|
from cartography.util import aws_handle_regions
|
|
10
|
-
from cartography.util import run_cleanup_job
|
|
11
13
|
from cartography.util import timeit
|
|
12
14
|
|
|
13
15
|
from .util import get_botocore_config
|
|
@@ -17,87 +19,78 @@ logger = logging.getLogger(__name__)
|
|
|
17
19
|
|
|
18
20
|
@timeit
|
|
19
21
|
@aws_handle_regions
|
|
20
|
-
def get_ec2_vpcs(
|
|
22
|
+
def get_ec2_vpcs(
|
|
23
|
+
boto3_session: boto3.session.Session,
|
|
24
|
+
region: str,
|
|
25
|
+
) -> list[dict[str, Any]]:
|
|
21
26
|
client = boto3_session.client(
|
|
22
27
|
"ec2",
|
|
23
28
|
region_name=region,
|
|
24
29
|
config=get_botocore_config(),
|
|
25
30
|
)
|
|
26
|
-
return client.describe_vpcs()
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
def
|
|
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
|
-
ingest_statement = _get_cidr_association_statement(block_type)
|
|
79
|
-
|
|
80
|
-
if block_type == "ipv6":
|
|
81
|
-
data = vpc_data.get("Ipv6CidrBlockAssociationSet", [])
|
|
82
|
-
else:
|
|
83
|
-
data = vpc_data.get("CidrBlockAssociationSet", [])
|
|
84
|
-
|
|
85
|
-
neo4j_session.run(
|
|
86
|
-
ingest_statement,
|
|
87
|
-
VpcId=vpc_id,
|
|
88
|
-
CidrBlock=data,
|
|
89
|
-
update_tag=update_tag,
|
|
90
|
-
)
|
|
31
|
+
return client.describe_vpcs().get("Vpcs", [])
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def transform_vpc_data(
|
|
35
|
+
vpc_list: list[dict[str, Any]], region: str
|
|
36
|
+
) -> tuple[list[dict[str, Any]], list[dict[str, Any]], list[dict[str, Any]]]:
|
|
37
|
+
|
|
38
|
+
vpc_data: list[dict[str, Any]] = []
|
|
39
|
+
ipv4_cidr_blocks: list[dict[str, Any]] = []
|
|
40
|
+
ipv6_cidr_blocks: list[dict[str, Any]] = []
|
|
41
|
+
|
|
42
|
+
for vpc in vpc_list:
|
|
43
|
+
vpc_record = {
|
|
44
|
+
"VpcId": vpc.get("VpcId"),
|
|
45
|
+
"InstanceTenancy": vpc.get("InstanceTenancy"),
|
|
46
|
+
"State": vpc.get("State"),
|
|
47
|
+
"IsDefault": vpc.get("IsDefault"),
|
|
48
|
+
"PrimaryCIDRBlock": vpc.get("CidrBlock"),
|
|
49
|
+
"DhcpOptionsId": vpc.get("DhcpOptionsId"),
|
|
50
|
+
"lastupdated": vpc.get("lastupdated"),
|
|
51
|
+
}
|
|
52
|
+
vpc_data.append(vpc_record)
|
|
53
|
+
|
|
54
|
+
ipv4_associations = vpc.get("CidrBlockAssociationSet", [])
|
|
55
|
+
for association in ipv4_associations:
|
|
56
|
+
ipv4_block = {
|
|
57
|
+
"Id": vpc["VpcId"] + "|" + association.get("CidrBlock"),
|
|
58
|
+
"VpcId": vpc["VpcId"],
|
|
59
|
+
"AssociationId": association.get("AssociationId"),
|
|
60
|
+
"CidrBlock": association.get("CidrBlock"),
|
|
61
|
+
"BlockState": association.get("CidrBlockState", {}).get("State"),
|
|
62
|
+
"BlockStateMessage": association.get("CidrBlockState", {}).get(
|
|
63
|
+
"StatusMessage"
|
|
64
|
+
),
|
|
65
|
+
}
|
|
66
|
+
ipv4_cidr_blocks.append(ipv4_block)
|
|
67
|
+
|
|
68
|
+
ipv6_associations = vpc.get("Ipv6CidrBlockAssociationSet", [])
|
|
69
|
+
for association in ipv6_associations:
|
|
70
|
+
ipv6_block = {
|
|
71
|
+
"Id": vpc["VpcId"] + "|" + association.get("Ipv6CidrBlock"),
|
|
72
|
+
"VpcId": vpc["VpcId"],
|
|
73
|
+
"AssociationId": association.get("AssociationId"),
|
|
74
|
+
"CidrBlock": association.get("Ipv6CidrBlock"),
|
|
75
|
+
"BlockState": association.get("Ipv6CidrBlockState", {}).get("State"),
|
|
76
|
+
"BlockStateMessage": association.get("Ipv6CidrBlockState", {}).get(
|
|
77
|
+
"StatusMessage"
|
|
78
|
+
),
|
|
79
|
+
}
|
|
80
|
+
ipv6_cidr_blocks.append(ipv6_block)
|
|
81
|
+
|
|
82
|
+
return vpc_data, ipv4_cidr_blocks, ipv6_cidr_blocks
|
|
91
83
|
|
|
92
84
|
|
|
93
85
|
@timeit
|
|
94
86
|
def load_ec2_vpcs(
|
|
95
87
|
neo4j_session: neo4j.Session,
|
|
96
|
-
|
|
88
|
+
vpcs: list[dict[str, Any]],
|
|
97
89
|
region: str,
|
|
98
|
-
|
|
90
|
+
aws_account_id: str,
|
|
99
91
|
update_tag: int,
|
|
100
92
|
) -> None:
|
|
93
|
+
logger.info(f"Loading {len(vpcs)} EC2 VPCs for region '{region}' into graph.")
|
|
101
94
|
# https://docs.aws.amazon.com/cli/latest/reference/ec2/describe-vpcs.html
|
|
102
95
|
# {
|
|
103
96
|
# "Vpcs": [
|
|
@@ -126,69 +119,69 @@ def load_ec2_vpcs(
|
|
|
126
119
|
# }
|
|
127
120
|
# ]
|
|
128
121
|
# }
|
|
122
|
+
load(
|
|
123
|
+
neo4j_session,
|
|
124
|
+
AWSVpcSchema(),
|
|
125
|
+
vpcs,
|
|
126
|
+
lastupdated=update_tag,
|
|
127
|
+
Region=region,
|
|
128
|
+
AWS_ID=aws_account_id,
|
|
129
|
+
)
|
|
129
130
|
|
|
130
|
-
ingest_vpc = """
|
|
131
|
-
MERGE (new_vpc:AWSVpc{id: $VpcId})
|
|
132
|
-
ON CREATE SET new_vpc.firstseen = timestamp(), new_vpc.vpcid =$VpcId
|
|
133
|
-
SET new_vpc.instance_tenancy = $InstanceTenancy,
|
|
134
|
-
new_vpc.state = $State,
|
|
135
|
-
new_vpc.is_default = $IsDefault,
|
|
136
|
-
new_vpc.primary_cidr_block = $PrimaryCIDRBlock,
|
|
137
|
-
new_vpc.dhcp_options_id = $DhcpOptionsId,
|
|
138
|
-
new_vpc.region = $Region,
|
|
139
|
-
new_vpc.lastupdated = $update_tag
|
|
140
|
-
WITH new_vpc
|
|
141
|
-
MATCH (awsAccount:AWSAccount{id: $AWS_ACCOUNT_ID})
|
|
142
|
-
MERGE (awsAccount)-[r:RESOURCE]->(new_vpc)
|
|
143
|
-
ON CREATE SET r.firstseen = timestamp()
|
|
144
|
-
SET r.lastupdated = $update_tag"""
|
|
145
|
-
|
|
146
|
-
for vpc in data:
|
|
147
|
-
vpc_id = vpc["VpcId"] # fail if not present
|
|
148
|
-
|
|
149
|
-
neo4j_session.run(
|
|
150
|
-
ingest_vpc,
|
|
151
|
-
VpcId=vpc_id,
|
|
152
|
-
InstanceTenancy=vpc.get("InstanceTenancy", None),
|
|
153
|
-
State=vpc.get("State", None),
|
|
154
|
-
IsDefault=vpc.get("IsDefault", None),
|
|
155
|
-
PrimaryCIDRBlock=vpc.get("CidrBlock", None),
|
|
156
|
-
DhcpOptionsId=vpc.get("DhcpOptionsId", None),
|
|
157
|
-
Region=region,
|
|
158
|
-
AWS_ACCOUNT_ID=current_aws_account_id,
|
|
159
|
-
update_tag=update_tag,
|
|
160
|
-
)
|
|
161
131
|
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
132
|
+
@timeit
|
|
133
|
+
def load_ipv4_cidr_blocks(
|
|
134
|
+
neo4j_session: neo4j.Session,
|
|
135
|
+
ipv4_cidr_blocks: list[dict[str, Any]],
|
|
136
|
+
region: str,
|
|
137
|
+
aws_account_id: str,
|
|
138
|
+
update_tag: int,
|
|
139
|
+
) -> None:
|
|
140
|
+
load(
|
|
141
|
+
neo4j_session,
|
|
142
|
+
AWSIPv4CidrBlockSchema(),
|
|
143
|
+
ipv4_cidr_blocks,
|
|
144
|
+
lastupdated=update_tag,
|
|
145
|
+
)
|
|
169
146
|
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
147
|
+
|
|
148
|
+
@timeit
|
|
149
|
+
def load_ipv6_cidr_blocks(
|
|
150
|
+
neo4j_session: neo4j.Session,
|
|
151
|
+
ipv6_cidr_blocks: list[dict[str, Any]],
|
|
152
|
+
region: str,
|
|
153
|
+
aws_account_id: str,
|
|
154
|
+
update_tag: int,
|
|
155
|
+
) -> None:
|
|
156
|
+
load(
|
|
157
|
+
neo4j_session,
|
|
158
|
+
AWSIPv6CidrBlockSchema(),
|
|
159
|
+
ipv6_cidr_blocks,
|
|
160
|
+
lastupdated=update_tag,
|
|
161
|
+
)
|
|
177
162
|
|
|
178
163
|
|
|
179
164
|
@timeit
|
|
180
|
-
def
|
|
181
|
-
|
|
165
|
+
def cleanup(
|
|
166
|
+
neo4j_session: neo4j.Session, common_job_parameters: dict[str, Any]
|
|
167
|
+
) -> None:
|
|
168
|
+
GraphJob.from_node_schema(AWSIPv6CidrBlockSchema(), common_job_parameters).run(
|
|
169
|
+
neo4j_session
|
|
170
|
+
)
|
|
171
|
+
GraphJob.from_node_schema(AWSIPv4CidrBlockSchema(), common_job_parameters).run(
|
|
172
|
+
neo4j_session
|
|
173
|
+
)
|
|
174
|
+
GraphJob.from_node_schema(AWSVpcSchema(), common_job_parameters).run(neo4j_session)
|
|
182
175
|
|
|
183
176
|
|
|
184
177
|
@timeit
|
|
185
178
|
def sync_vpc(
|
|
186
179
|
neo4j_session: neo4j.Session,
|
|
187
180
|
boto3_session: boto3.session.Session,
|
|
188
|
-
regions:
|
|
181
|
+
regions: list[str],
|
|
189
182
|
current_aws_account_id: str,
|
|
190
183
|
update_tag: int,
|
|
191
|
-
common_job_parameters:
|
|
184
|
+
common_job_parameters: dict[str, Any],
|
|
192
185
|
) -> None:
|
|
193
186
|
for region in regions:
|
|
194
187
|
logger.info(
|
|
@@ -196,6 +189,29 @@ def sync_vpc(
|
|
|
196
189
|
region,
|
|
197
190
|
current_aws_account_id,
|
|
198
191
|
)
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
192
|
+
raw_vpc_data = get_ec2_vpcs(boto3_session, region)
|
|
193
|
+
vpc_data, ipv4_cidr_blocks, ipv6_cidr_blocks = transform_vpc_data(
|
|
194
|
+
raw_vpc_data, region
|
|
195
|
+
)
|
|
196
|
+
load_ec2_vpcs(
|
|
197
|
+
neo4j_session,
|
|
198
|
+
vpc_data,
|
|
199
|
+
region,
|
|
200
|
+
current_aws_account_id,
|
|
201
|
+
update_tag,
|
|
202
|
+
)
|
|
203
|
+
load_ipv4_cidr_blocks(
|
|
204
|
+
neo4j_session,
|
|
205
|
+
ipv4_cidr_blocks,
|
|
206
|
+
region,
|
|
207
|
+
current_aws_account_id,
|
|
208
|
+
update_tag,
|
|
209
|
+
)
|
|
210
|
+
load_ipv6_cidr_blocks(
|
|
211
|
+
neo4j_session,
|
|
212
|
+
ipv6_cidr_blocks,
|
|
213
|
+
region,
|
|
214
|
+
current_aws_account_id,
|
|
215
|
+
update_tag,
|
|
216
|
+
)
|
|
217
|
+
cleanup(neo4j_session, common_job_parameters)
|
|
@@ -10,6 +10,7 @@ from cartography.client.core.tx import load
|
|
|
10
10
|
from cartography.graph.job import GraphJob
|
|
11
11
|
from cartography.intel.aws.ec2.util import get_botocore_config
|
|
12
12
|
from cartography.models.aws.eventbridge.rule import EventBridgeRuleSchema
|
|
13
|
+
from cartography.models.aws.eventbridge.target import EventBridgeTargetSchema
|
|
13
14
|
from cartography.util import aws_handle_regions
|
|
14
15
|
from cartography.util import timeit
|
|
15
16
|
|
|
@@ -33,6 +34,44 @@ def get_eventbridge_rules(
|
|
|
33
34
|
return rules
|
|
34
35
|
|
|
35
36
|
|
|
37
|
+
@timeit
|
|
38
|
+
@aws_handle_regions
|
|
39
|
+
def get_eventbridge_targets(
|
|
40
|
+
boto3_session: boto3.Session, region: str, rules: List[Dict[str, Any]]
|
|
41
|
+
) -> List[Dict[str, Any]]:
|
|
42
|
+
client = boto3_session.client(
|
|
43
|
+
"events", region_name=region, config=get_botocore_config()
|
|
44
|
+
)
|
|
45
|
+
targets = []
|
|
46
|
+
for rule in rules:
|
|
47
|
+
paginator = client.get_paginator("list_targets_by_rule")
|
|
48
|
+
for page in paginator.paginate(Rule=rule["Name"]):
|
|
49
|
+
for target in page.get("Targets", []):
|
|
50
|
+
target["RuleArn"] = rule["Arn"]
|
|
51
|
+
targets.append(target)
|
|
52
|
+
return targets
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def transform_eventbridge_targets(
|
|
56
|
+
targets: List[Dict[str, Any]],
|
|
57
|
+
region: str,
|
|
58
|
+
) -> List[Dict[str, Any]]:
|
|
59
|
+
"""
|
|
60
|
+
Transform EventBridge target data for ingestion into Neo4j.
|
|
61
|
+
"""
|
|
62
|
+
transformed_data = []
|
|
63
|
+
for target in targets:
|
|
64
|
+
transformed_target = {
|
|
65
|
+
"Id": target["Arn"],
|
|
66
|
+
"Arn": target["Arn"],
|
|
67
|
+
"RuleArn": target["RuleArn"],
|
|
68
|
+
"RoleArn": target.get("RoleArn"),
|
|
69
|
+
"Region": region,
|
|
70
|
+
}
|
|
71
|
+
transformed_data.append(transformed_target)
|
|
72
|
+
return transformed_data
|
|
73
|
+
|
|
74
|
+
|
|
36
75
|
@timeit
|
|
37
76
|
def load_eventbridge_rules(
|
|
38
77
|
neo4j_session: neo4j.Session,
|
|
@@ -54,6 +93,27 @@ def load_eventbridge_rules(
|
|
|
54
93
|
)
|
|
55
94
|
|
|
56
95
|
|
|
96
|
+
@timeit
|
|
97
|
+
def load_eventbridge_targets(
|
|
98
|
+
neo4j_session: neo4j.Session,
|
|
99
|
+
data: List[Dict[str, Any]],
|
|
100
|
+
region: str,
|
|
101
|
+
current_aws_account_id: str,
|
|
102
|
+
aws_update_tag: int,
|
|
103
|
+
) -> None:
|
|
104
|
+
logger.info(
|
|
105
|
+
f"Loading EventBridge {len(data)} targets for region '{region}' into graph.",
|
|
106
|
+
)
|
|
107
|
+
load(
|
|
108
|
+
neo4j_session,
|
|
109
|
+
EventBridgeTargetSchema(),
|
|
110
|
+
data,
|
|
111
|
+
lastupdated=aws_update_tag,
|
|
112
|
+
Region=region,
|
|
113
|
+
AWS_ID=current_aws_account_id,
|
|
114
|
+
)
|
|
115
|
+
|
|
116
|
+
|
|
57
117
|
@timeit
|
|
58
118
|
def cleanup(
|
|
59
119
|
neo4j_session: neo4j.Session,
|
|
@@ -63,6 +123,9 @@ def cleanup(
|
|
|
63
123
|
GraphJob.from_node_schema(EventBridgeRuleSchema(), common_job_parameters).run(
|
|
64
124
|
neo4j_session
|
|
65
125
|
)
|
|
126
|
+
GraphJob.from_node_schema(EventBridgeTargetSchema(), common_job_parameters).run(
|
|
127
|
+
neo4j_session
|
|
128
|
+
)
|
|
66
129
|
|
|
67
130
|
|
|
68
131
|
@timeit
|
|
@@ -88,4 +151,14 @@ def sync(
|
|
|
88
151
|
update_tag,
|
|
89
152
|
)
|
|
90
153
|
|
|
154
|
+
targets = get_eventbridge_targets(boto3_session, region, rules)
|
|
155
|
+
transformed_targets = transform_eventbridge_targets(targets, region)
|
|
156
|
+
load_eventbridge_targets(
|
|
157
|
+
neo4j_session,
|
|
158
|
+
transformed_targets,
|
|
159
|
+
region,
|
|
160
|
+
current_aws_account_id,
|
|
161
|
+
update_tag,
|
|
162
|
+
)
|
|
163
|
+
|
|
91
164
|
cleanup(neo4j_session, common_job_parameters)
|
|
@@ -405,9 +405,16 @@ def _create_default_branch_id(repo_url: str, default_branch_ref_id: str) -> str:
|
|
|
405
405
|
|
|
406
406
|
def _create_git_url_from_ssh_url(ssh_url: str) -> str:
|
|
407
407
|
"""
|
|
408
|
-
|
|
408
|
+
Convert SSH URL to git:// URL.
|
|
409
|
+
Example:
|
|
410
|
+
git@github.com:cartography-cncf/cartography.git
|
|
411
|
+
-> git://github.com/cartography-cncf/cartography.git
|
|
409
412
|
"""
|
|
410
|
-
|
|
413
|
+
# Remove the user part (e.g., "git@")
|
|
414
|
+
_, host_and_path = ssh_url.split("@", 1)
|
|
415
|
+
# Replace first ':' (separating host and repo) with '/'
|
|
416
|
+
host, path = host_and_path.split(":", 1)
|
|
417
|
+
return f"git://{host}/{path}"
|
|
411
418
|
|
|
412
419
|
|
|
413
420
|
def _transform_repo_objects(input_repo_object: Dict, out_repo_list: List[Dict]) -> None:
|
|
@@ -0,0 +1,74 @@
|
|
|
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 APIGatewayDeploymentNodeProperties(CartographyNodeProperties):
|
|
16
|
+
id: PropertyRef = PropertyRef("id")
|
|
17
|
+
arn: PropertyRef = PropertyRef("id", extra_index=True)
|
|
18
|
+
description: PropertyRef = PropertyRef("description")
|
|
19
|
+
region: PropertyRef = PropertyRef("region", set_in_kwargs=True)
|
|
20
|
+
lastupdated: PropertyRef = PropertyRef("lastupdated", set_in_kwargs=True)
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
@dataclass(frozen=True)
|
|
24
|
+
class APIGatewayDeploymentToAWSAccountRelRelProperties(CartographyRelProperties):
|
|
25
|
+
lastupdated: PropertyRef = PropertyRef("lastupdated", set_in_kwargs=True)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
@dataclass(frozen=True)
|
|
29
|
+
# (:APIGatewayDeployment)<-[:RESOURCE]-(:AWSAccount)
|
|
30
|
+
class APIGatewayDeploymentToAWSAccountRel(CartographyRelSchema):
|
|
31
|
+
target_node_label: str = "AWSAccount"
|
|
32
|
+
target_node_matcher: TargetNodeMatcher = make_target_node_matcher(
|
|
33
|
+
{"id": PropertyRef("AWS_ID", set_in_kwargs=True)},
|
|
34
|
+
)
|
|
35
|
+
direction: LinkDirection = LinkDirection.INWARD
|
|
36
|
+
rel_label: str = "RESOURCE"
|
|
37
|
+
properties: APIGatewayDeploymentToAWSAccountRelRelProperties = (
|
|
38
|
+
APIGatewayDeploymentToAWSAccountRelRelProperties()
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
@dataclass(frozen=True)
|
|
43
|
+
class APIGatewayDeploymentToRestAPIRelRelProperties(CartographyRelProperties):
|
|
44
|
+
lastupdated: PropertyRef = PropertyRef("lastupdated", set_in_kwargs=True)
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
@dataclass(frozen=True)
|
|
48
|
+
# (:APIGatewayDeployment)<-[:HAS_DEPLOYMENT]-(:APIGatewayRestAPI)
|
|
49
|
+
class APIGatewayDeploymentToRestAPIRel(CartographyRelSchema):
|
|
50
|
+
target_node_label: str = "APIGatewayRestAPI"
|
|
51
|
+
target_node_matcher: TargetNodeMatcher = make_target_node_matcher(
|
|
52
|
+
{"id": PropertyRef("api_id")},
|
|
53
|
+
)
|
|
54
|
+
direction: LinkDirection = LinkDirection.INWARD
|
|
55
|
+
rel_label: str = "HAS_DEPLOYMENT"
|
|
56
|
+
properties: APIGatewayDeploymentToRestAPIRelRelProperties = (
|
|
57
|
+
APIGatewayDeploymentToRestAPIRelRelProperties()
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
@dataclass(frozen=True)
|
|
62
|
+
class APIGatewayDeploymentSchema(CartographyNodeSchema):
|
|
63
|
+
label: str = "APIGatewayDeployment"
|
|
64
|
+
properties: APIGatewayDeploymentNodeProperties = (
|
|
65
|
+
APIGatewayDeploymentNodeProperties()
|
|
66
|
+
)
|
|
67
|
+
sub_resource_relationship: APIGatewayDeploymentToAWSAccountRel = (
|
|
68
|
+
APIGatewayDeploymentToAWSAccountRel()
|
|
69
|
+
)
|
|
70
|
+
other_relationships: OtherRelationships = OtherRelationships(
|
|
71
|
+
[
|
|
72
|
+
APIGatewayDeploymentToRestAPIRel(),
|
|
73
|
+
]
|
|
74
|
+
)
|
|
@@ -0,0 +1,46 @@
|
|
|
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 TargetNodeMatcher
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@dataclass(frozen=True)
|
|
14
|
+
class VPCNodeProperties(CartographyNodeProperties):
|
|
15
|
+
id: PropertyRef = PropertyRef("VpcId")
|
|
16
|
+
vpcid: PropertyRef = PropertyRef("VpcId", extra_index=True)
|
|
17
|
+
primary_cidr_block: PropertyRef = PropertyRef("PrimaryCIDRBlock")
|
|
18
|
+
instance_tenancy: PropertyRef = PropertyRef("InstanceTenancy")
|
|
19
|
+
state: PropertyRef = PropertyRef("State")
|
|
20
|
+
is_default: PropertyRef = PropertyRef("IsDefault")
|
|
21
|
+
dhcp_options_id: PropertyRef = PropertyRef("DhcpOptionsId")
|
|
22
|
+
region: PropertyRef = PropertyRef("Region", set_in_kwargs=True)
|
|
23
|
+
lastupdated: PropertyRef = PropertyRef("lastupdated", set_in_kwargs=True)
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
@dataclass(frozen=True)
|
|
27
|
+
class VPCToAWSAccountRelProperties(CartographyRelProperties):
|
|
28
|
+
lastupdated: PropertyRef = PropertyRef("lastupdated", set_in_kwargs=True)
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
@dataclass(frozen=True)
|
|
32
|
+
class VPCToAWSAccountRel(CartographyRelSchema):
|
|
33
|
+
target_node_label: str = "AWSAccount"
|
|
34
|
+
target_node_matcher: TargetNodeMatcher = make_target_node_matcher(
|
|
35
|
+
{"id": PropertyRef("AWS_ID", set_in_kwargs=True)}
|
|
36
|
+
)
|
|
37
|
+
direction: LinkDirection = LinkDirection.INWARD
|
|
38
|
+
rel_label: str = "RESOURCE"
|
|
39
|
+
properties: VPCToAWSAccountRelProperties = VPCToAWSAccountRelProperties()
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
@dataclass(frozen=True)
|
|
43
|
+
class AWSVpcSchema(CartographyNodeSchema):
|
|
44
|
+
label: str = "AWSVpc"
|
|
45
|
+
properties: VPCNodeProperties = VPCNodeProperties()
|
|
46
|
+
sub_resource_relationship: VPCToAWSAccountRel = VPCToAWSAccountRel()
|
|
@@ -0,0 +1,102 @@
|
|
|
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.nodes import ExtraNodeLabels
|
|
7
|
+
from cartography.models.core.relationships import CartographyRelProperties
|
|
8
|
+
from cartography.models.core.relationships import CartographyRelSchema
|
|
9
|
+
from cartography.models.core.relationships import LinkDirection
|
|
10
|
+
from cartography.models.core.relationships import make_target_node_matcher
|
|
11
|
+
from cartography.models.core.relationships import OtherRelationships
|
|
12
|
+
from cartography.models.core.relationships import TargetNodeMatcher
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
@dataclass(frozen=True)
|
|
16
|
+
class AWSIPv4CidrBlockNodeProperties(CartographyNodeProperties):
|
|
17
|
+
id: PropertyRef = PropertyRef("Id")
|
|
18
|
+
vpcid: PropertyRef = PropertyRef("VpcId")
|
|
19
|
+
association_id: PropertyRef = PropertyRef("AssociationId")
|
|
20
|
+
cidr_block: PropertyRef = PropertyRef("CidrBlock")
|
|
21
|
+
block_state: PropertyRef = PropertyRef("BlockState")
|
|
22
|
+
block_state_message: PropertyRef = PropertyRef("BlockStateMessage")
|
|
23
|
+
lastupdated: PropertyRef = PropertyRef("lastupdated", set_in_kwargs=True)
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
@dataclass(frozen=True)
|
|
27
|
+
class AWSIPv4CidrBlockToAWSVpcRelProperties(CartographyRelProperties):
|
|
28
|
+
lastupdated: PropertyRef = PropertyRef("lastupdated", set_in_kwargs=True)
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
@dataclass(frozen=True)
|
|
32
|
+
class AWSIPv4CidrBlockToAWSVpcRel(CartographyRelSchema):
|
|
33
|
+
target_node_label: str = "AWSVpc"
|
|
34
|
+
target_node_matcher: TargetNodeMatcher = make_target_node_matcher(
|
|
35
|
+
{"id": PropertyRef("VpcId")}
|
|
36
|
+
)
|
|
37
|
+
direction: LinkDirection = LinkDirection.INWARD
|
|
38
|
+
rel_label: str = "BLOCK_ASSOCIATION"
|
|
39
|
+
properties: AWSIPv4CidrBlockToAWSVpcRelProperties = (
|
|
40
|
+
AWSIPv4CidrBlockToAWSVpcRelProperties()
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
@dataclass(frozen=True)
|
|
45
|
+
class AWSIPv4CidrBlockSchema(CartographyNodeSchema):
|
|
46
|
+
"""
|
|
47
|
+
There is no sub-resource relationship here because a
|
|
48
|
+
CIDR block can be associated with more than one account
|
|
49
|
+
and it doesn't make sense to scope it to one.
|
|
50
|
+
"""
|
|
51
|
+
|
|
52
|
+
label: str = "AWSCidrBlock"
|
|
53
|
+
properties: AWSIPv4CidrBlockNodeProperties = AWSIPv4CidrBlockNodeProperties()
|
|
54
|
+
other_relationships: OtherRelationships = OtherRelationships(
|
|
55
|
+
[AWSIPv4CidrBlockToAWSVpcRel()]
|
|
56
|
+
)
|
|
57
|
+
extra_node_labels: ExtraNodeLabels = ExtraNodeLabels(["AWSIpv4CidrBlock"])
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
@dataclass(frozen=True)
|
|
61
|
+
class AWSIPv6CidrBlockNodeProperties(CartographyNodeProperties):
|
|
62
|
+
id: PropertyRef = PropertyRef("Id")
|
|
63
|
+
vpcid: PropertyRef = PropertyRef("VpcId")
|
|
64
|
+
association_id: PropertyRef = PropertyRef("AssociationId")
|
|
65
|
+
cidr_block: PropertyRef = PropertyRef("CidrBlock")
|
|
66
|
+
block_state: PropertyRef = PropertyRef("BlockState")
|
|
67
|
+
block_state_message: PropertyRef = PropertyRef("BlockStateMessage")
|
|
68
|
+
lastupdated: PropertyRef = PropertyRef("lastupdated", set_in_kwargs=True)
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
@dataclass(frozen=True)
|
|
72
|
+
class AWSIPv6CidrBlockToAWSVpcRelProperties(CartographyRelProperties):
|
|
73
|
+
lastupdated: PropertyRef = PropertyRef("lastupdated", set_in_kwargs=True)
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
@dataclass(frozen=True)
|
|
77
|
+
class AWSIPv6CidrBlockToAWSVpcRel(CartographyRelSchema):
|
|
78
|
+
target_node_label: str = "AWSVpc"
|
|
79
|
+
target_node_matcher: TargetNodeMatcher = make_target_node_matcher(
|
|
80
|
+
{"id": PropertyRef("VpcId")}
|
|
81
|
+
)
|
|
82
|
+
direction: LinkDirection = LinkDirection.INWARD
|
|
83
|
+
rel_label: str = "BLOCK_ASSOCIATION"
|
|
84
|
+
properties: AWSIPv6CidrBlockToAWSVpcRelProperties = (
|
|
85
|
+
AWSIPv6CidrBlockToAWSVpcRelProperties()
|
|
86
|
+
)
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
@dataclass(frozen=True)
|
|
90
|
+
class AWSIPv6CidrBlockSchema(CartographyNodeSchema):
|
|
91
|
+
"""
|
|
92
|
+
There is no sub-resource relationship here because a
|
|
93
|
+
CIDR block can be associated with more than one account
|
|
94
|
+
and it doesn't make sense to scope it to one.
|
|
95
|
+
"""
|
|
96
|
+
|
|
97
|
+
label: str = "AWSCidrBlock"
|
|
98
|
+
properties: AWSIPv6CidrBlockNodeProperties = AWSIPv6CidrBlockNodeProperties()
|
|
99
|
+
other_relationships: OtherRelationships = OtherRelationships(
|
|
100
|
+
[AWSIPv6CidrBlockToAWSVpcRel()]
|
|
101
|
+
)
|
|
102
|
+
extra_node_labels: ExtraNodeLabels = ExtraNodeLabels(["AWSIpv6CidrBlock"])
|
|
@@ -0,0 +1,71 @@
|
|
|
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 EventBridgeTargetNodeProperties(CartographyNodeProperties):
|
|
16
|
+
id: PropertyRef = PropertyRef("Id")
|
|
17
|
+
arn: PropertyRef = PropertyRef("Arn", extra_index=True)
|
|
18
|
+
rule_arn: PropertyRef = PropertyRef("RuleArn")
|
|
19
|
+
role_arn: PropertyRef = PropertyRef("RoleArn")
|
|
20
|
+
region: PropertyRef = PropertyRef("Region", set_in_kwargs=True)
|
|
21
|
+
lastupdated: PropertyRef = PropertyRef("lastupdated", set_in_kwargs=True)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
@dataclass(frozen=True)
|
|
25
|
+
class EventBridgeTargetToAwsAccountRelProperties(CartographyRelProperties):
|
|
26
|
+
lastupdated: PropertyRef = PropertyRef("lastupdated", set_in_kwargs=True)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
@dataclass(frozen=True)
|
|
30
|
+
class EventBridgeTargetToAWSAccountRel(CartographyRelSchema):
|
|
31
|
+
target_node_label: str = "AWSAccount"
|
|
32
|
+
target_node_matcher: TargetNodeMatcher = make_target_node_matcher(
|
|
33
|
+
{"id": PropertyRef("AWS_ID", set_in_kwargs=True)},
|
|
34
|
+
)
|
|
35
|
+
direction: LinkDirection = LinkDirection.INWARD
|
|
36
|
+
rel_label: str = "RESOURCE"
|
|
37
|
+
properties: EventBridgeTargetToAwsAccountRelProperties = (
|
|
38
|
+
EventBridgeTargetToAwsAccountRelProperties()
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
@dataclass(frozen=True)
|
|
43
|
+
class EventBridgeTargetToEventBridgeRuleRelProperties(CartographyRelProperties):
|
|
44
|
+
lastupdated: PropertyRef = PropertyRef("lastupdated", set_in_kwargs=True)
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
@dataclass(frozen=True)
|
|
48
|
+
class EventBridgeTargetToEventBridgeRuleRel(CartographyRelSchema):
|
|
49
|
+
target_node_label: str = "EventBridgeRule"
|
|
50
|
+
target_node_matcher: TargetNodeMatcher = make_target_node_matcher(
|
|
51
|
+
{"arn": PropertyRef("RuleArn")},
|
|
52
|
+
)
|
|
53
|
+
direction: LinkDirection = LinkDirection.OUTWARD
|
|
54
|
+
rel_label: str = "LINKED_TO_RULE"
|
|
55
|
+
properties: EventBridgeTargetToEventBridgeRuleRelProperties = (
|
|
56
|
+
EventBridgeTargetToEventBridgeRuleRelProperties()
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
@dataclass(frozen=True)
|
|
61
|
+
class EventBridgeTargetSchema(CartographyNodeSchema):
|
|
62
|
+
label: str = "EventBridgeTarget"
|
|
63
|
+
properties: EventBridgeTargetNodeProperties = EventBridgeTargetNodeProperties()
|
|
64
|
+
sub_resource_relationship: EventBridgeTargetToAWSAccountRel = (
|
|
65
|
+
EventBridgeTargetToAWSAccountRel()
|
|
66
|
+
)
|
|
67
|
+
other_relationships: OtherRelationships = OtherRelationships(
|
|
68
|
+
[
|
|
69
|
+
EventBridgeTargetToEventBridgeRuleRel(),
|
|
70
|
+
]
|
|
71
|
+
)
|
|
@@ -28,6 +28,7 @@ class TailscaleDeviceNodeProperties(CartographyNodeProperties):
|
|
|
28
28
|
authorized: PropertyRef = PropertyRef("authorized")
|
|
29
29
|
is_external: PropertyRef = PropertyRef("isExternal")
|
|
30
30
|
node_key: PropertyRef = PropertyRef("nodeKey")
|
|
31
|
+
addresses: PropertyRef = PropertyRef("addresses")
|
|
31
32
|
blocks_incoming_connections: PropertyRef = PropertyRef("blocksIncomingConnections")
|
|
32
33
|
client_connectivity_endpoints: PropertyRef = PropertyRef(
|
|
33
34
|
"clientConnectivity.endpoints"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
cartography/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
2
|
cartography/__main__.py,sha256=y5iqUrj4BmqZfjeDT-9balzpXeMARgHeIedRMRI1gr8,100
|
|
3
|
-
cartography/_version.py,sha256=
|
|
3
|
+
cartography/_version.py,sha256=mjqbwY_wN8Z8qqEs-Mud3vkMN1NHb8-3V1jv-jutGAM,718
|
|
4
4
|
cartography/cli.py,sha256=iw_Rhs4ztquxD_BaneRNOZDuwBzANq9zImBteB3shXI,47085
|
|
5
5
|
cartography/config.py,sha256=CUp5Klxr8enNLFttqlo67le6Z4mXTzzEb5nYiE-pGs0,17076
|
|
6
6
|
cartography/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -14,7 +14,7 @@ cartography/client/aws/iam.py,sha256=dYsGikc36DEsSeR2XVOVFFUDwuU9yWj_EVkpgVYCFgM
|
|
|
14
14
|
cartography/client/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
15
15
|
cartography/client/core/tx.py,sha256=Xx6_a5u7PE5pyREuBL_J39ORcafqieFf4KdosaEv1c4,13530
|
|
16
16
|
cartography/data/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
17
|
-
cartography/data/indexes.cypher,sha256=
|
|
17
|
+
cartography/data/indexes.cypher,sha256=Ci4Vp8UI5qqFTvIht7TIGORRY2p6seQAQlUaKJ8WxEI,22357
|
|
18
18
|
cartography/data/permission_relationships.yaml,sha256=RuKGGc_3ZUQ7ag0MssB8k_zaonCkVM5E8I_svBWTmGc,969
|
|
19
19
|
cartography/data/jobs/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
20
20
|
cartography/data/jobs/analysis/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -54,7 +54,6 @@ cartography/data/jobs/cleanup/aws_import_sqs_queues_cleanup.json,sha256=Mla8y-CW
|
|
|
54
54
|
cartography/data/jobs/cleanup/aws_import_tags_cleanup.json,sha256=mVOmhpoeHYItYQFATlTTeBhUt2GipAliRhh69zQcHok,7360
|
|
55
55
|
cartography/data/jobs/cleanup/aws_import_tgw_cleanup.json,sha256=jHlKj2jcI3avvDMOCbFd89hTS0HcNVrZinJ4AYgykQs,2097
|
|
56
56
|
cartography/data/jobs/cleanup/aws_import_users_cleanup.json,sha256=TY0VFJlbgd3ClmuHSzNuNAu-tDWFbAeEGWIZz-rmlGg,257
|
|
57
|
-
cartography/data/jobs/cleanup/aws_import_vpc_cleanup.json,sha256=2_2mVflLBg1i33WBEJiiQoVKP3RSD3MRPe-yfxzyKh0,948
|
|
58
57
|
cartography/data/jobs/cleanup/aws_import_vpc_peering_cleanup.json,sha256=jpIy2W2T9A9tB5EZQeVU2p2Z0LY52NYHS8W51NQTKaA,2040
|
|
59
58
|
cartography/data/jobs/cleanup/aws_ingest_ec2_auto_scaling_groups_cleanup.json,sha256=6EXQO_xH3kXkgxN_H3j45LKEN_TZucLg__g-lD3gyfI,1802
|
|
60
59
|
cartography/data/jobs/cleanup/aws_ingest_load_balancers_cleanup.json,sha256=1vidNCrITt-_bxw5lsSzyqGsuyWiNhI6-bnuv5lMvRI,1729
|
|
@@ -123,7 +122,7 @@ cartography/graph/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU
|
|
|
123
122
|
cartography/graph/cleanupbuilder.py,sha256=uMSjMOnfkfTDrgMJwflNK8HAd4oioG8NIU0JeMN7ets,16552
|
|
124
123
|
cartography/graph/context.py,sha256=RGxGb8EnxowcqjR0nFF86baNhgRHeUF9wjIoFUoG8LU,1230
|
|
125
124
|
cartography/graph/job.py,sha256=5h4FsOV2tHeO5O2Gv-vglI5QUNE7V6p-RNmf9Fz5gvU,9396
|
|
126
|
-
cartography/graph/querybuilder.py,sha256
|
|
125
|
+
cartography/graph/querybuilder.py,sha256=-5Vpaf_HBgZpwGnzrgtUVuy_lnBXSYr8nvcYodbUMYQ,30337
|
|
127
126
|
cartography/graph/statement.py,sha256=VtvZFMqzzZk-gDeOnBx6oDj90XYOCM1EWw4d55bm7SU,5383
|
|
128
127
|
cartography/intel/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
129
128
|
cartography/intel/analysis.py,sha256=uWIpmrk2hezkqjfepqz1VV2BopT7VZ-alBj2YekfE_c,1546
|
|
@@ -145,7 +144,7 @@ cartography/intel/anthropic/util.py,sha256=m2OopxCC6chCwOxUXmc9nWW--nOlYyBL_Nc3K
|
|
|
145
144
|
cartography/intel/anthropic/workspaces.py,sha256=_t2kdGIFceDziC_BqIJa9-nLWIoWJbPoFNX1JYqbQ-w,2544
|
|
146
145
|
cartography/intel/aws/__init__.py,sha256=lgu0kxERg_dJGuktEDU0ImpHuNGHJharoLEpirKWPZM,12330
|
|
147
146
|
cartography/intel/aws/acm.py,sha256=a_i2pYPpocjlL8itwlcrmg8KrSLfjcmrkhcrPP-Omj8,3827
|
|
148
|
-
cartography/intel/aws/apigateway.py,sha256=
|
|
147
|
+
cartography/intel/aws/apigateway.py,sha256=0aXt4IRdXYNRtTaAy-JBf-7yMoqeNHukLOwOY_mGpoQ,15101
|
|
149
148
|
cartography/intel/aws/cloudtrail.py,sha256=LCqf3pQMiMY4h1Wehb_OjwXst2fMIEnNOD8HbXsK4X4,2753
|
|
150
149
|
cartography/intel/aws/cloudtrail_management_events.py,sha256=z5VZH1wQvl_ROG1sB9ZPdH4uexp-BKrI-WdEkhQKbkQ,35751
|
|
151
150
|
cartography/intel/aws/cloudwatch.py,sha256=bBPlx5W15nun-jhYs-UAZQpo9Qm7FcBs4gBQevTqmi4,7246
|
|
@@ -160,7 +159,7 @@ cartography/intel/aws/eks.py,sha256=bPItyEj5q0nSDltJrr0S5MIrTPV0fK3xkqF6EV8fcqA,
|
|
|
160
159
|
cartography/intel/aws/elasticache.py,sha256=ePTi-49Lbw94L6m7id5dUk1cG6FZRizFxojxKZBk8XY,5552
|
|
161
160
|
cartography/intel/aws/elasticsearch.py,sha256=8X_Rp1zejkvXho0Zz_Cr4g-w9IpompdYRc-YS595Aso,8645
|
|
162
161
|
cartography/intel/aws/emr.py,sha256=EJoKjHQP7-F_A1trUNU05Sb42yNR1i0C9VIpGcCfAXw,3662
|
|
163
|
-
cartography/intel/aws/eventbridge.py,sha256=
|
|
162
|
+
cartography/intel/aws/eventbridge.py,sha256=PUq0UBxKro5oiTyq8U3gLcxomh5UaeBxoO7BhIKea6k,4442
|
|
164
163
|
cartography/intel/aws/glue.py,sha256=y3RQRNQutdMugSKOVnbJfA1CFfu12g8sqSuhp_AF4aI,5211
|
|
165
164
|
cartography/intel/aws/guardduty.py,sha256=QpwWisz3TzbOxkRKNjByk4WWDCCMXr8jgNOgOdjQM5g,8532
|
|
166
165
|
cartography/intel/aws/iam.py,sha256=bkyIzWw2OC4MHxuoCvTiZ5eEGEQhz2asiUgY_tkX2GY,34322
|
|
@@ -203,7 +202,7 @@ cartography/intel/aws/ec2/subnets.py,sha256=uzZ_YyRY2zycKXsGS05qmT6cHHi4SNbN2v1y
|
|
|
203
202
|
cartography/intel/aws/ec2/tgw.py,sha256=FcXWgLkr4EcD9DRXJMeyWQIgIHidaq40UrZneKhvnuE,9621
|
|
204
203
|
cartography/intel/aws/ec2/util.py,sha256=t6oJX9nCTejvp0D9ihxfhmCoD1aoOXQB0cuvz0pMCe0,226
|
|
205
204
|
cartography/intel/aws/ec2/volumes.py,sha256=C5V9LRE41REU4siHMAaE9yAjtbpLi8yTkaqLEw1uXMg,3726
|
|
206
|
-
cartography/intel/aws/ec2/vpc.py,sha256=
|
|
205
|
+
cartography/intel/aws/ec2/vpc.py,sha256=JXRy0G33PQmMx2UM788InHEq7UW45MdH_wasH22t_uE,6536
|
|
207
206
|
cartography/intel/aws/ec2/vpc_peerings.py,sha256=_a2Bs5tf-Qfj8SYcmPlDiUWhyzZKhKbweVAG4WEsplY,6844
|
|
208
207
|
cartography/intel/aws/util/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
209
208
|
cartography/intel/aws/util/arns.py,sha256=Hwg_Lnf9ZNRTI-oEXU182S9ejOTy2-ggm2RKIxV5lGc,549
|
|
@@ -256,7 +255,7 @@ cartography/intel/gcp/gke.py,sha256=2-lhTzFEh-gAQ756Sr0kZZJY5_zcFWPS7_p0EVNzuR8,
|
|
|
256
255
|
cartography/intel/gcp/iam.py,sha256=0aSVXeSuPLE5g0Ckl8mC0vM9d2dIi-W_8tcp1xLUhoE,7694
|
|
257
256
|
cartography/intel/gcp/storage.py,sha256=ARDDySshRza90Biw33z_oNxLGJqvxLYBDyuRJ270muc,9307
|
|
258
257
|
cartography/intel/github/__init__.py,sha256=qDMmYd-3DAVDhkPwCTVtkwP_0x5wuhWVp9jc0ghWtx4,1679
|
|
259
|
-
cartography/intel/github/repos.py,sha256=
|
|
258
|
+
cartography/intel/github/repos.py,sha256=tuxiF3M8g7XXSbWptRAUGETQsYKTdxCe2xfnZtFUdL8,42317
|
|
260
259
|
cartography/intel/github/teams.py,sha256=JICUXVScYbowtbOtIe-D4bibPmSBbQnL5z8IjzqSJ3s,14657
|
|
261
260
|
cartography/intel/github/users.py,sha256=meAkOpymGGdXXqZDCqv0hPIqCP4FHJvHkVug7L8jA10,9125
|
|
262
261
|
cartography/intel/github/util.py,sha256=00MihS14j95xjwEdoSHlC8BYXQYJzDHCMc43DkCH55o,8098
|
|
@@ -358,14 +357,15 @@ cartography/models/anthropic/apikey.py,sha256=eDaaXBHkZtRrKCDgeBD5BYR4jVUH-5QTi7
|
|
|
358
357
|
cartography/models/anthropic/organization.py,sha256=3Jr9dplEF57Jn50YKn_Jy7LMpDfSydudtiy3_Pismgc,669
|
|
359
358
|
cartography/models/anthropic/user.py,sha256=SJWrQoL-RGiC7uBuJ72vstnCXbOj2umcgypHKT-F3AA,1995
|
|
360
359
|
cartography/models/anthropic/workspace.py,sha256=I7-UkDhXr75b9KFA_WeuIhbTUikOP22RSEsuEQh8ppM,3684
|
|
361
|
-
cartography/models/aws/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
362
|
-
cartography/models/aws/apigateway.py,sha256=qwb-NQzw47qu3zH6SdGicrDfClYn19wZFYASaF_6GWo,2312
|
|
363
|
-
cartography/models/aws/apigatewaycertificate.py,sha256=vFKip_EeOws3Ke-77xI6eyUMDJK2ZgB0XWHytIuesKA,3019
|
|
364
|
-
cartography/models/aws/apigatewayresource.py,sha256=iyri4znJo1pgAAe4xBs-eoE5dHK8fEsg6-5OusdvwE0,2856
|
|
365
|
-
cartography/models/aws/apigatewaystage.py,sha256=d3m82TH4ggC--0HdE3SG7n-Uwm5Gu9eZMRT23h7a2as,3179
|
|
366
360
|
cartography/models/aws/emr.py,sha256=iZPzyqFrDsyRSRZqjCHlyDkO91H__6iszJq5hkNpOLU,3071
|
|
367
361
|
cartography/models/aws/acm/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
368
362
|
cartography/models/aws/acm/certificate.py,sha256=GvB7xKBCoPmLsV9LnqAUg8x8sGTsDDsr7WIaqh4Sc-M,3141
|
|
363
|
+
cartography/models/aws/apigateway/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
364
|
+
cartography/models/aws/apigateway/apigateway.py,sha256=qwb-NQzw47qu3zH6SdGicrDfClYn19wZFYASaF_6GWo,2312
|
|
365
|
+
cartography/models/aws/apigateway/apigatewaycertificate.py,sha256=vFKip_EeOws3Ke-77xI6eyUMDJK2ZgB0XWHytIuesKA,3019
|
|
366
|
+
cartography/models/aws/apigateway/apigatewaydeployment.py,sha256=msxbdHbTb6Upp14f6JjuP6RHe2-TFgA-Ru5wVLnxyFY,2980
|
|
367
|
+
cartography/models/aws/apigateway/apigatewayresource.py,sha256=iyri4znJo1pgAAe4xBs-eoE5dHK8fEsg6-5OusdvwE0,2856
|
|
368
|
+
cartography/models/aws/apigateway/apigatewaystage.py,sha256=d3m82TH4ggC--0HdE3SG7n-Uwm5Gu9eZMRT23h7a2as,3179
|
|
369
369
|
cartography/models/aws/cloudtrail/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
370
370
|
cartography/models/aws/cloudtrail/management_events.py,sha256=b-p_SoZsumJggaD3CfmSHRfIfW1G_29uFwgFIJdW0lw,6634
|
|
371
371
|
cartography/models/aws/cloudtrail/trail.py,sha256=dQi5txRQBnpdoHLFSl8VaWVI2Bx5tPDevGCbT7RIr0o,4452
|
|
@@ -411,6 +411,8 @@ cartography/models/aws/ec2/subnet_instance.py,sha256=6bgrWbFcCjBIjqd_6lcKv6rWyll
|
|
|
411
411
|
cartography/models/aws/ec2/subnet_networkinterface.py,sha256=B60S1YvEopVWNlRL5W-hMby3-P06uaNcC_8oOLoRGik,3872
|
|
412
412
|
cartography/models/aws/ec2/subnets.py,sha256=BtlFgf03IaD9XFesv5uzHBCm6xr71LT435m9t4MHkY8,2915
|
|
413
413
|
cartography/models/aws/ec2/volumes.py,sha256=spAi4QjoYjp5G-qNuFJdW4b-oZg7by5g5FEaqJv1mZo,5242
|
|
414
|
+
cartography/models/aws/ec2/vpc.py,sha256=7pJ-FzkoPKxUcdFlBSHbvGr2bQoujeACUS1BRsJD8Kc,2011
|
|
415
|
+
cartography/models/aws/ec2/vpc_cidr.py,sha256=8DMZZKjIbgrUpet-ojQEM-5Nlo81EPUbrdOkYerUPv4,4072
|
|
414
416
|
cartography/models/aws/ecr/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
415
417
|
cartography/models/aws/ecr/image.py,sha256=8atk1Z13BgUOcAq3uIK-sJ9gDxwcmeCIk7x1PW9B4BE,1753
|
|
416
418
|
cartography/models/aws/ecr/repository.py,sha256=goItMJ3XnLSSk8FCMvgCpWCSsleTqdNzUT_Asvw8Yhk,2908
|
|
@@ -434,6 +436,7 @@ cartography/models/aws/elasticache/cluster.py,sha256=3tx3fL3FPSp4QX3pd42sV71t6kY
|
|
|
434
436
|
cartography/models/aws/elasticache/topic.py,sha256=Rq-Hj6xo9xouRLw2NRNU1cmmVUlOP0ieRA8fT5GlZ2w,2757
|
|
435
437
|
cartography/models/aws/eventbridge/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
436
438
|
cartography/models/aws/eventbridge/rule.py,sha256=VH7oTferIyykITCJhVPWZKVx2-7H9Dxi4fm9GwDitJw,3135
|
|
439
|
+
cartography/models/aws/eventbridge/target.py,sha256=gncb5bEdZTfy2OI_Frcn1tY_a_W5HYEDOpjahsPskwE,2865
|
|
437
440
|
cartography/models/aws/glue/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
438
441
|
cartography/models/aws/glue/connection.py,sha256=wG7mDMoYnmAHXrLfi52_1wPHF6VcrLOKfDmZaJJti1Q,2213
|
|
439
442
|
cartography/models/aws/glue/job.py,sha256=Y4RUgfpXKf-4z4vxGEa4eEka7oJOATGks0hy_Aezevk,2805
|
|
@@ -583,7 +586,7 @@ cartography/models/snipeit/asset.py,sha256=hFvGPH6-6kGgG1yjztkf9wrrAmxNL2p38nc08
|
|
|
583
586
|
cartography/models/snipeit/tenant.py,sha256=E6uaY3d2W3MmfuUqF2TLpRP3T1QZkoIXRtp9BGxxSxk,695
|
|
584
587
|
cartography/models/snipeit/user.py,sha256=c-XWAnPTFrFnZLzR_sQB8pKNelwrLjHu-oWQLnQFnxg,2162
|
|
585
588
|
cartography/models/tailscale/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
586
|
-
cartography/models/tailscale/device.py,sha256=
|
|
589
|
+
cartography/models/tailscale/device.py,sha256=aKk2tYUYekU9Nma1qSDoRpUa29h8Pt4sld7x5Q9KtLw,4043
|
|
587
590
|
cartography/models/tailscale/group.py,sha256=hOtzt7TYq606EszefbW0KuBWraHJ71kl-ebjUT3Gn5I,3349
|
|
588
591
|
cartography/models/tailscale/postureintegration.py,sha256=nwyzYoCZn9PPaChVxCL7ibyfEc7x2mYXmpuVW2q3by4,2598
|
|
589
592
|
cartography/models/tailscale/tag.py,sha256=7a8SidgsBI8f_ZzoHo3NPAA83JSXgS785VxlDeU2cBs,3955
|
|
@@ -593,9 +596,9 @@ cartography/models/trivy/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZ
|
|
|
593
596
|
cartography/models/trivy/findings.py,sha256=SgI_h1aRyR20uAHvuXIZ1T6r4IZJt6SVhxRaF2bTsm0,3085
|
|
594
597
|
cartography/models/trivy/fix.py,sha256=ho9ENVl9HSXqyggyCwR6ilkOBKDxpQ7rGibo_j21NA4,2587
|
|
595
598
|
cartography/models/trivy/package.py,sha256=IwO1RZZ-MFRtNbt8Cq6YFl6fdNJMFmULnJkkK8Q4rL4,2809
|
|
596
|
-
cartography-0.
|
|
597
|
-
cartography-0.
|
|
598
|
-
cartography-0.
|
|
599
|
-
cartography-0.
|
|
600
|
-
cartography-0.
|
|
601
|
-
cartography-0.
|
|
599
|
+
cartography-0.111.0rc1.dist-info/licenses/LICENSE,sha256=kvLEBRYaQ1RvUni6y7Ti9uHeooqnjPoo6n_-0JO1ETc,11351
|
|
600
|
+
cartography-0.111.0rc1.dist-info/METADATA,sha256=fVzU8tAWysJtWlHvzRl34b9_lVSm7ZrTRrOmDYoGKm0,13008
|
|
601
|
+
cartography-0.111.0rc1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
602
|
+
cartography-0.111.0rc1.dist-info/entry_points.txt,sha256=GVIAWD0o0_K077qMA_k1oZU4v-M0a8GLKGJR8tZ-qH8,112
|
|
603
|
+
cartography-0.111.0rc1.dist-info/top_level.txt,sha256=BHqsNJQiI6Q72DeypC1IINQJE59SLhU4nllbQjgJi9g,12
|
|
604
|
+
cartography-0.111.0rc1.dist-info/RECORD,,
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"statements": [{
|
|
3
|
-
"query": "MATCH (n:CidrBlock)<-[:BLOCK_ASSOCIATION]-(:AWSVpc)<-[:RESOURCE]-(:AWSAccount{id: $AWS_ID}) WHERE n.lastupdated <> $UPDATE_TAG WITH n LIMIT $LIMIT_SIZE DETACH DELETE (n)",
|
|
4
|
-
"iterative": true,
|
|
5
|
-
"iterationsize": 100
|
|
6
|
-
},
|
|
7
|
-
{
|
|
8
|
-
"query": "MATCH (:CidrBlock)<-[r:BLOCK_ASSOCIATION]-(:AWSVpc)<-[:RESOURCE]-(:AWSAccount{id: $AWS_ID}) WHERE r.lastupdated <> $UPDATE_TAG WITH r LIMIT $LIMIT_SIZE DELETE (r)",
|
|
9
|
-
"iterative": true,
|
|
10
|
-
"iterationsize": 100
|
|
11
|
-
},
|
|
12
|
-
{
|
|
13
|
-
"query": "MATCH (n:AWSVpc)<-[:RESOURCE]-(:AWSAccount{id: $AWS_ID}) WHERE n.lastupdated <> $UPDATE_TAG WITH n LIMIT $LIMIT_SIZE DETACH DELETE (n)",
|
|
14
|
-
"iterative": true,
|
|
15
|
-
"iterationsize": 100
|
|
16
|
-
},
|
|
17
|
-
{
|
|
18
|
-
"query": "MATCH (:AWSVpc)<-[r:RESOURCE]-(:AWSAccount{id: $AWS_ID}) WHERE r.lastupdated <> $UPDATE_TAG WITH r LIMIT $LIMIT_SIZE DELETE (r)",
|
|
19
|
-
"iterative": true,
|
|
20
|
-
"iterationsize": 100
|
|
21
|
-
}],
|
|
22
|
-
"name": "cleanup AWS VPC information"
|
|
23
|
-
}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|