cartography 0.108.0rc2__py3-none-any.whl → 0.109.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 +2 -2
- cartography/data/indexes.cypher +0 -2
- cartography/data/jobs/cleanup/gcp_compute_vpc_cleanup.json +0 -12
- cartography/intel/aws/cloudtrail_management_events.py +36 -3
- cartography/intel/aws/ecr.py +55 -80
- cartography/intel/aws/resourcegroupstaggingapi.py +77 -18
- cartography/intel/aws/secretsmanager.py +62 -44
- cartography/intel/entra/groups.py +29 -1
- cartography/intel/gcp/__init__.py +10 -0
- cartography/intel/gcp/compute.py +19 -42
- cartography/models/aws/ecr/__init__.py +0 -0
- cartography/models/aws/ecr/image.py +41 -0
- cartography/models/aws/ecr/repository.py +72 -0
- cartography/models/aws/ecr/repository_image.py +95 -0
- cartography/models/aws/secretsmanager/secret.py +106 -0
- cartography/models/entra/group.py +26 -0
- cartography/models/entra/user.py +6 -0
- cartography/models/gcp/compute/__init__.py +0 -0
- cartography/models/gcp/compute/vpc.py +50 -0
- {cartography-0.108.0rc2.dist-info → cartography-0.109.0rc1.dist-info}/METADATA +1 -1
- {cartography-0.108.0rc2.dist-info → cartography-0.109.0rc1.dist-info}/RECORD +25 -19
- cartography/data/jobs/cleanup/aws_import_secrets_cleanup.json +0 -8
- {cartography-0.108.0rc2.dist-info → cartography-0.109.0rc1.dist-info}/WHEEL +0 -0
- {cartography-0.108.0rc2.dist-info → cartography-0.109.0rc1.dist-info}/entry_points.txt +0 -0
- {cartography-0.108.0rc2.dist-info → cartography-0.109.0rc1.dist-info}/licenses/LICENSE +0 -0
- {cartography-0.108.0rc2.dist-info → cartography-0.109.0rc1.dist-info}/top_level.txt +0 -0
|
@@ -391,6 +391,7 @@ def _sync_multiple_projects(
|
|
|
391
391
|
# Compute data sync
|
|
392
392
|
for project in projects:
|
|
393
393
|
project_id = project["projectId"]
|
|
394
|
+
common_job_parameters["PROJECT_ID"] = project_id
|
|
394
395
|
logger.info("Syncing GCP project %s for Compute.", project_id)
|
|
395
396
|
_sync_single_project_compute(
|
|
396
397
|
neo4j_session,
|
|
@@ -399,10 +400,12 @@ def _sync_multiple_projects(
|
|
|
399
400
|
gcp_update_tag,
|
|
400
401
|
common_job_parameters,
|
|
401
402
|
)
|
|
403
|
+
del common_job_parameters["PROJECT_ID"]
|
|
402
404
|
|
|
403
405
|
# Storage data sync
|
|
404
406
|
for project in projects:
|
|
405
407
|
project_id = project["projectId"]
|
|
408
|
+
common_job_parameters["PROJECT_ID"] = project_id
|
|
406
409
|
logger.info("Syncing GCP project %s for Storage", project_id)
|
|
407
410
|
_sync_single_project_storage(
|
|
408
411
|
neo4j_session,
|
|
@@ -411,10 +414,12 @@ def _sync_multiple_projects(
|
|
|
411
414
|
gcp_update_tag,
|
|
412
415
|
common_job_parameters,
|
|
413
416
|
)
|
|
417
|
+
del common_job_parameters["PROJECT_ID"]
|
|
414
418
|
|
|
415
419
|
# GKE data sync
|
|
416
420
|
for project in projects:
|
|
417
421
|
project_id = project["projectId"]
|
|
422
|
+
common_job_parameters["PROJECT_ID"] = project_id
|
|
418
423
|
logger.info("Syncing GCP project %s for GKE", project_id)
|
|
419
424
|
_sync_single_project_gke(
|
|
420
425
|
neo4j_session,
|
|
@@ -423,10 +428,12 @@ def _sync_multiple_projects(
|
|
|
423
428
|
gcp_update_tag,
|
|
424
429
|
common_job_parameters,
|
|
425
430
|
)
|
|
431
|
+
del common_job_parameters["PROJECT_ID"]
|
|
426
432
|
|
|
427
433
|
# DNS data sync
|
|
428
434
|
for project in projects:
|
|
429
435
|
project_id = project["projectId"]
|
|
436
|
+
common_job_parameters["PROJECT_ID"] = project_id
|
|
430
437
|
logger.info("Syncing GCP project %s for DNS", project_id)
|
|
431
438
|
_sync_single_project_dns(
|
|
432
439
|
neo4j_session,
|
|
@@ -435,14 +442,17 @@ def _sync_multiple_projects(
|
|
|
435
442
|
gcp_update_tag,
|
|
436
443
|
common_job_parameters,
|
|
437
444
|
)
|
|
445
|
+
del common_job_parameters["PROJECT_ID"]
|
|
438
446
|
|
|
439
447
|
# IAM data sync
|
|
440
448
|
for project in projects:
|
|
441
449
|
project_id = project["projectId"]
|
|
450
|
+
common_job_parameters["PROJECT_ID"] = project_id
|
|
442
451
|
logger.info("Syncing GCP project %s for IAM", project_id)
|
|
443
452
|
_sync_single_project_iam(
|
|
444
453
|
neo4j_session, resources, project_id, gcp_update_tag, common_job_parameters
|
|
445
454
|
)
|
|
455
|
+
del common_job_parameters["PROJECT_ID"]
|
|
446
456
|
|
|
447
457
|
|
|
448
458
|
@timeit
|
cartography/intel/gcp/compute.py
CHANGED
|
@@ -14,6 +14,9 @@ import neo4j
|
|
|
14
14
|
from googleapiclient.discovery import HttpError
|
|
15
15
|
from googleapiclient.discovery import Resource
|
|
16
16
|
|
|
17
|
+
from cartography.client.core.tx import load
|
|
18
|
+
from cartography.graph.job import GraphJob
|
|
19
|
+
from cartography.models.gcp.compute.vpc import GCPVpcSchema
|
|
17
20
|
from cartography.util import run_cleanup_job
|
|
18
21
|
from cartography.util import timeit
|
|
19
22
|
|
|
@@ -600,48 +603,17 @@ def load_gcp_instances(
|
|
|
600
603
|
@timeit
|
|
601
604
|
def load_gcp_vpcs(
|
|
602
605
|
neo4j_session: neo4j.Session,
|
|
603
|
-
vpcs:
|
|
606
|
+
vpcs: list[dict[str, Any]],
|
|
604
607
|
gcp_update_tag: int,
|
|
608
|
+
project_id: str,
|
|
605
609
|
) -> None:
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
query = """
|
|
614
|
-
MERGE(p:GCPProject{id:$ProjectId})
|
|
615
|
-
ON CREATE SET p.firstseen = timestamp()
|
|
616
|
-
SET p.lastupdated = $gcp_update_tag
|
|
617
|
-
|
|
618
|
-
MERGE(vpc:GCPVpc{id:$PartialUri})
|
|
619
|
-
ON CREATE SET vpc.firstseen = timestamp(),
|
|
620
|
-
vpc.partial_uri = $PartialUri
|
|
621
|
-
SET vpc.self_link = $SelfLink,
|
|
622
|
-
vpc.name = $VpcName,
|
|
623
|
-
vpc.project_id = $ProjectId,
|
|
624
|
-
vpc.auto_create_subnetworks = $AutoCreateSubnetworks,
|
|
625
|
-
vpc.routing_config_routing_mode = $RoutingMode,
|
|
626
|
-
vpc.description = $Description,
|
|
627
|
-
vpc.lastupdated = $gcp_update_tag
|
|
628
|
-
|
|
629
|
-
MERGE (p)-[r:RESOURCE]->(vpc)
|
|
630
|
-
ON CREATE SET r.firstseen = timestamp()
|
|
631
|
-
SET r.lastupdated = $gcp_update_tag
|
|
632
|
-
"""
|
|
633
|
-
for vpc in vpcs:
|
|
634
|
-
neo4j_session.run(
|
|
635
|
-
query,
|
|
636
|
-
ProjectId=vpc["project_id"],
|
|
637
|
-
PartialUri=vpc["partial_uri"],
|
|
638
|
-
SelfLink=vpc["self_link"],
|
|
639
|
-
VpcName=vpc["name"],
|
|
640
|
-
AutoCreateSubnetworks=vpc["auto_create_subnetworks"],
|
|
641
|
-
RoutingMode=vpc["routing_config_routing_mode"],
|
|
642
|
-
Description=vpc["description"],
|
|
643
|
-
gcp_update_tag=gcp_update_tag,
|
|
644
|
-
)
|
|
610
|
+
load(
|
|
611
|
+
neo4j_session,
|
|
612
|
+
GCPVpcSchema(),
|
|
613
|
+
vpcs,
|
|
614
|
+
PROJECT_ID=project_id,
|
|
615
|
+
LASTUPDATED=gcp_update_tag,
|
|
616
|
+
)
|
|
645
617
|
|
|
646
618
|
|
|
647
619
|
@timeit
|
|
@@ -1159,6 +1131,12 @@ def cleanup_gcp_vpcs(neo4j_session: neo4j.Session, common_job_parameters: Dict)
|
|
|
1159
1131
|
:param common_job_parameters: dict of other job parameters to pass to Neo4j
|
|
1160
1132
|
:return: Nothing
|
|
1161
1133
|
"""
|
|
1134
|
+
GraphJob.from_node_schema(
|
|
1135
|
+
GCPVpcSchema(),
|
|
1136
|
+
common_job_parameters,
|
|
1137
|
+
).run(neo4j_session)
|
|
1138
|
+
|
|
1139
|
+
# TODO: remove this once we refactor GCP instances and add the instance to vpc rel as an object
|
|
1162
1140
|
run_cleanup_job(
|
|
1163
1141
|
"gcp_compute_vpc_cleanup.json",
|
|
1164
1142
|
neo4j_session,
|
|
@@ -1267,8 +1245,7 @@ def sync_gcp_vpcs(
|
|
|
1267
1245
|
"""
|
|
1268
1246
|
vpc_res = get_gcp_vpcs(project_id, compute)
|
|
1269
1247
|
vpcs = transform_gcp_vpcs(vpc_res)
|
|
1270
|
-
load_gcp_vpcs(neo4j_session, vpcs, gcp_update_tag)
|
|
1271
|
-
# TODO scope the cleanup to the current project - https://github.com/cartography-cncf/cartography/issues/381
|
|
1248
|
+
load_gcp_vpcs(neo4j_session, vpcs, gcp_update_tag, project_id)
|
|
1272
1249
|
cleanup_gcp_vpcs(neo4j_session, common_job_parameters)
|
|
1273
1250
|
|
|
1274
1251
|
|
|
File without changes
|
|
@@ -0,0 +1,41 @@
|
|
|
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 ECRImageNodeProperties(CartographyNodeProperties):
|
|
15
|
+
id: PropertyRef = PropertyRef("imageDigest")
|
|
16
|
+
digest: PropertyRef = PropertyRef("imageDigest")
|
|
17
|
+
region: PropertyRef = PropertyRef("Region", set_in_kwargs=True)
|
|
18
|
+
lastupdated: PropertyRef = PropertyRef("lastupdated", set_in_kwargs=True)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
@dataclass(frozen=True)
|
|
22
|
+
class ECRImageToAWSAccountRelProperties(CartographyRelProperties):
|
|
23
|
+
lastupdated: PropertyRef = PropertyRef("lastupdated", set_in_kwargs=True)
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
@dataclass(frozen=True)
|
|
27
|
+
class ECRImageToAWSAccountRel(CartographyRelSchema):
|
|
28
|
+
target_node_label: str = "AWSAccount"
|
|
29
|
+
target_node_matcher: TargetNodeMatcher = make_target_node_matcher(
|
|
30
|
+
{"id": PropertyRef("AWS_ID", set_in_kwargs=True)}
|
|
31
|
+
)
|
|
32
|
+
direction: LinkDirection = LinkDirection.INWARD
|
|
33
|
+
rel_label: str = "RESOURCE"
|
|
34
|
+
properties: ECRImageToAWSAccountRelProperties = ECRImageToAWSAccountRelProperties()
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
@dataclass(frozen=True)
|
|
38
|
+
class ECRImageSchema(CartographyNodeSchema):
|
|
39
|
+
label: str = "ECRImage"
|
|
40
|
+
properties: ECRImageNodeProperties = ECRImageNodeProperties()
|
|
41
|
+
sub_resource_relationship: ECRImageToAWSAccountRel = ECRImageToAWSAccountRel()
|
|
@@ -0,0 +1,72 @@
|
|
|
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 ECRRepositoryNodeProperties(CartographyNodeProperties):
|
|
16
|
+
id: PropertyRef = PropertyRef("repositoryArn")
|
|
17
|
+
arn: PropertyRef = PropertyRef("repositoryArn", extra_index=True)
|
|
18
|
+
name: PropertyRef = PropertyRef("repositoryName", extra_index=True)
|
|
19
|
+
uri: PropertyRef = PropertyRef("repositoryUri", extra_index=True)
|
|
20
|
+
created_at: PropertyRef = PropertyRef("createdAt")
|
|
21
|
+
region: PropertyRef = PropertyRef("Region", set_in_kwargs=True)
|
|
22
|
+
lastupdated: PropertyRef = PropertyRef("lastupdated", set_in_kwargs=True)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
@dataclass(frozen=True)
|
|
26
|
+
class ECRRepositoryToAWSAccountRelProperties(CartographyRelProperties):
|
|
27
|
+
lastupdated: PropertyRef = PropertyRef("lastupdated", set_in_kwargs=True)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
@dataclass(frozen=True)
|
|
31
|
+
class ECRRepositoryToAWSAccountRel(CartographyRelSchema):
|
|
32
|
+
target_node_label: str = "AWSAccount"
|
|
33
|
+
target_node_matcher: TargetNodeMatcher = make_target_node_matcher(
|
|
34
|
+
{"id": PropertyRef("AWS_ID", set_in_kwargs=True)}
|
|
35
|
+
)
|
|
36
|
+
direction: LinkDirection = LinkDirection.INWARD
|
|
37
|
+
rel_label: str = "RESOURCE"
|
|
38
|
+
properties: ECRRepositoryToAWSAccountRelProperties = (
|
|
39
|
+
ECRRepositoryToAWSAccountRelProperties()
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
@dataclass(frozen=True)
|
|
44
|
+
class ECRRepositoryToRepositoryImageRelProperties(CartographyRelProperties):
|
|
45
|
+
lastupdated: PropertyRef = PropertyRef("lastupdated", set_in_kwargs=True)
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
@dataclass(frozen=True)
|
|
49
|
+
class ECRRepositoryToRepositoryImageRel(CartographyRelSchema):
|
|
50
|
+
target_node_label: str = "ECRRepositoryImage"
|
|
51
|
+
target_node_matcher: TargetNodeMatcher = make_target_node_matcher(
|
|
52
|
+
{"id": PropertyRef("id")}
|
|
53
|
+
)
|
|
54
|
+
direction: LinkDirection = LinkDirection.OUTWARD
|
|
55
|
+
rel_label: str = "REPO_IMAGE"
|
|
56
|
+
properties: ECRRepositoryToRepositoryImageRelProperties = (
|
|
57
|
+
ECRRepositoryToRepositoryImageRelProperties()
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
@dataclass(frozen=True)
|
|
62
|
+
class ECRRepositorySchema(CartographyNodeSchema):
|
|
63
|
+
label: str = "ECRRepository"
|
|
64
|
+
properties: ECRRepositoryNodeProperties = ECRRepositoryNodeProperties()
|
|
65
|
+
sub_resource_relationship: ECRRepositoryToAWSAccountRel = (
|
|
66
|
+
ECRRepositoryToAWSAccountRel()
|
|
67
|
+
)
|
|
68
|
+
other_relationships: OtherRelationships = OtherRelationships(
|
|
69
|
+
[
|
|
70
|
+
ECRRepositoryToRepositoryImageRel(),
|
|
71
|
+
]
|
|
72
|
+
)
|
|
@@ -0,0 +1,95 @@
|
|
|
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 ECRRepositoryImageNodeProperties(CartographyNodeProperties):
|
|
16
|
+
id: PropertyRef = PropertyRef("id")
|
|
17
|
+
tag: PropertyRef = PropertyRef("imageTag")
|
|
18
|
+
uri: PropertyRef = PropertyRef("uri")
|
|
19
|
+
repo_uri: PropertyRef = PropertyRef("repo_uri")
|
|
20
|
+
image_size_bytes: PropertyRef = PropertyRef("imageSizeInBytes")
|
|
21
|
+
image_pushed_at: PropertyRef = PropertyRef("imagePushedAt")
|
|
22
|
+
image_manifest_media_type: PropertyRef = PropertyRef("imageManifestMediaType")
|
|
23
|
+
artifact_media_type: PropertyRef = PropertyRef("artifactMediaType")
|
|
24
|
+
last_recorded_pull_time: PropertyRef = PropertyRef("lastRecordedPullTime")
|
|
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 ECRRepositoryImageToAWSAccountRelProperties(CartographyRelProperties):
|
|
31
|
+
lastupdated: PropertyRef = PropertyRef("lastupdated", set_in_kwargs=True)
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
@dataclass(frozen=True)
|
|
35
|
+
class ECRRepositoryImageToAWSAccountRel(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: ECRRepositoryImageToAWSAccountRelProperties = (
|
|
43
|
+
ECRRepositoryImageToAWSAccountRelProperties()
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
@dataclass(frozen=True)
|
|
48
|
+
class ECRRepositoryImageToECRRepositoryRelProperties(CartographyRelProperties):
|
|
49
|
+
lastupdated: PropertyRef = PropertyRef("lastupdated", set_in_kwargs=True)
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
@dataclass(frozen=True)
|
|
53
|
+
class ECRRepositoryImageToECRRepositoryRel(CartographyRelSchema):
|
|
54
|
+
target_node_label: str = "ECRRepository"
|
|
55
|
+
target_node_matcher: TargetNodeMatcher = make_target_node_matcher(
|
|
56
|
+
{"uri": PropertyRef("repo_uri")}
|
|
57
|
+
)
|
|
58
|
+
direction: LinkDirection = LinkDirection.INWARD
|
|
59
|
+
rel_label: str = "REPO_IMAGE"
|
|
60
|
+
properties: ECRRepositoryImageToECRRepositoryRelProperties = (
|
|
61
|
+
ECRRepositoryImageToECRRepositoryRelProperties()
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
@dataclass(frozen=True)
|
|
66
|
+
class ECRRepositoryImageToECRImageRelProperties(CartographyRelProperties):
|
|
67
|
+
lastupdated: PropertyRef = PropertyRef("lastupdated", set_in_kwargs=True)
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
@dataclass(frozen=True)
|
|
71
|
+
class ECRRepositoryImageToECRImageRel(CartographyRelSchema):
|
|
72
|
+
target_node_label: str = "ECRImage"
|
|
73
|
+
target_node_matcher: TargetNodeMatcher = make_target_node_matcher(
|
|
74
|
+
{"id": PropertyRef("imageDigest")}
|
|
75
|
+
)
|
|
76
|
+
direction: LinkDirection = LinkDirection.OUTWARD
|
|
77
|
+
rel_label: str = "IMAGE"
|
|
78
|
+
properties: ECRRepositoryImageToECRImageRelProperties = (
|
|
79
|
+
ECRRepositoryImageToECRImageRelProperties()
|
|
80
|
+
)
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
@dataclass(frozen=True)
|
|
84
|
+
class ECRRepositoryImageSchema(CartographyNodeSchema):
|
|
85
|
+
label: str = "ECRRepositoryImage"
|
|
86
|
+
properties: ECRRepositoryImageNodeProperties = ECRRepositoryImageNodeProperties()
|
|
87
|
+
sub_resource_relationship: ECRRepositoryImageToAWSAccountRel = (
|
|
88
|
+
ECRRepositoryImageToAWSAccountRel()
|
|
89
|
+
)
|
|
90
|
+
other_relationships: OtherRelationships = OtherRelationships(
|
|
91
|
+
[
|
|
92
|
+
ECRRepositoryImageToECRRepositoryRel(),
|
|
93
|
+
ECRRepositoryImageToECRImageRel(),
|
|
94
|
+
]
|
|
95
|
+
)
|
|
@@ -0,0 +1,106 @@
|
|
|
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 SecretsManagerSecretNodeProperties(CartographyNodeProperties):
|
|
16
|
+
"""
|
|
17
|
+
Properties for AWS Secrets Manager Secret
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
id: PropertyRef = PropertyRef("ARN")
|
|
21
|
+
arn: PropertyRef = PropertyRef("ARN", extra_index=True)
|
|
22
|
+
name: PropertyRef = PropertyRef("Name", extra_index=True)
|
|
23
|
+
description: PropertyRef = PropertyRef("Description")
|
|
24
|
+
|
|
25
|
+
# Rotation properties
|
|
26
|
+
rotation_enabled: PropertyRef = PropertyRef("RotationEnabled")
|
|
27
|
+
rotation_lambda_arn: PropertyRef = PropertyRef("RotationLambdaARN")
|
|
28
|
+
rotation_rules_automatically_after_days: PropertyRef = PropertyRef(
|
|
29
|
+
"RotationRulesAutomaticallyAfterDays"
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
# Date properties (will be converted to epoch timestamps)
|
|
33
|
+
created_date: PropertyRef = PropertyRef("CreatedDate")
|
|
34
|
+
last_rotated_date: PropertyRef = PropertyRef("LastRotatedDate")
|
|
35
|
+
last_changed_date: PropertyRef = PropertyRef("LastChangedDate")
|
|
36
|
+
last_accessed_date: PropertyRef = PropertyRef("LastAccessedDate")
|
|
37
|
+
deleted_date: PropertyRef = PropertyRef("DeletedDate")
|
|
38
|
+
|
|
39
|
+
# Other properties
|
|
40
|
+
kms_key_id: PropertyRef = PropertyRef("KmsKeyId")
|
|
41
|
+
owning_service: PropertyRef = PropertyRef("OwningService")
|
|
42
|
+
primary_region: PropertyRef = PropertyRef("PrimaryRegion")
|
|
43
|
+
|
|
44
|
+
# Standard cartography properties
|
|
45
|
+
region: PropertyRef = PropertyRef("Region", set_in_kwargs=True)
|
|
46
|
+
lastupdated: PropertyRef = PropertyRef("lastupdated", set_in_kwargs=True)
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
@dataclass(frozen=True)
|
|
50
|
+
class SecretsManagerSecretRelProperties(CartographyRelProperties):
|
|
51
|
+
"""
|
|
52
|
+
Properties for relationships between Secret and other nodes
|
|
53
|
+
"""
|
|
54
|
+
|
|
55
|
+
lastupdated: PropertyRef = PropertyRef("lastupdated", set_in_kwargs=True)
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
@dataclass(frozen=True)
|
|
59
|
+
class SecretsManagerSecretToAWSAccountRel(CartographyRelSchema):
|
|
60
|
+
"""
|
|
61
|
+
Relationship between Secret and AWS Account
|
|
62
|
+
"""
|
|
63
|
+
|
|
64
|
+
target_node_label: str = "AWSAccount"
|
|
65
|
+
target_node_matcher: TargetNodeMatcher = make_target_node_matcher(
|
|
66
|
+
{"id": PropertyRef("AWS_ID", set_in_kwargs=True)},
|
|
67
|
+
)
|
|
68
|
+
direction: LinkDirection = LinkDirection.INWARD
|
|
69
|
+
rel_label: str = "RESOURCE"
|
|
70
|
+
properties: SecretsManagerSecretRelProperties = SecretsManagerSecretRelProperties()
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
@dataclass(frozen=True)
|
|
74
|
+
class SecretsManagerSecretToKMSKeyRel(CartographyRelSchema):
|
|
75
|
+
"""
|
|
76
|
+
Relationship between Secret and its KMS key
|
|
77
|
+
Only created when KmsKeyId is present
|
|
78
|
+
"""
|
|
79
|
+
|
|
80
|
+
target_node_label: str = "AWSKMSKey"
|
|
81
|
+
target_node_matcher: TargetNodeMatcher = make_target_node_matcher(
|
|
82
|
+
{"id": PropertyRef("KmsKeyId")},
|
|
83
|
+
)
|
|
84
|
+
direction: LinkDirection = LinkDirection.OUTWARD
|
|
85
|
+
rel_label: str = "ENCRYPTED_BY"
|
|
86
|
+
properties: SecretsManagerSecretRelProperties = SecretsManagerSecretRelProperties()
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
@dataclass(frozen=True)
|
|
90
|
+
class SecretsManagerSecretSchema(CartographyNodeSchema):
|
|
91
|
+
"""
|
|
92
|
+
Schema for AWS Secrets Manager Secret
|
|
93
|
+
"""
|
|
94
|
+
|
|
95
|
+
label: str = "SecretsManagerSecret"
|
|
96
|
+
properties: SecretsManagerSecretNodeProperties = (
|
|
97
|
+
SecretsManagerSecretNodeProperties()
|
|
98
|
+
)
|
|
99
|
+
sub_resource_relationship: SecretsManagerSecretToAWSAccountRel = (
|
|
100
|
+
SecretsManagerSecretToAWSAccountRel()
|
|
101
|
+
)
|
|
102
|
+
other_relationships: OtherRelationships = OtherRelationships(
|
|
103
|
+
[
|
|
104
|
+
SecretsManagerSecretToKMSKeyRel(),
|
|
105
|
+
],
|
|
106
|
+
)
|
|
@@ -3,6 +3,7 @@ from dataclasses import dataclass
|
|
|
3
3
|
from cartography.models.core.common import PropertyRef
|
|
4
4
|
from cartography.models.core.nodes import CartographyNodeProperties
|
|
5
5
|
from cartography.models.core.nodes import CartographyNodeSchema
|
|
6
|
+
from cartography.models.core.nodes import ExtraNodeLabels
|
|
6
7
|
from cartography.models.core.relationships import CartographyRelProperties
|
|
7
8
|
from cartography.models.core.relationships import CartographyRelSchema
|
|
8
9
|
from cartography.models.core.relationships import LinkDirection
|
|
@@ -78,6 +79,25 @@ class EntraGroupToGroupRel(CartographyRelSchema):
|
|
|
78
79
|
properties: EntraGroupToGroupRelProperties = EntraGroupToGroupRelProperties()
|
|
79
80
|
|
|
80
81
|
|
|
82
|
+
@dataclass(frozen=True)
|
|
83
|
+
class EntraGroupToOwnerRelProperties(CartographyRelProperties):
|
|
84
|
+
lastupdated: PropertyRef = PropertyRef("lastupdated", set_in_kwargs=True)
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
@dataclass(frozen=True)
|
|
88
|
+
# (:EntraGroup)<-[:OWNER_OF]-(:EntraUser)
|
|
89
|
+
class EntraGroupToOwnerRel(CartographyRelSchema):
|
|
90
|
+
# EntraUsers and Entra service principals can be owners of a group, so we match on the general label
|
|
91
|
+
# Because id is indexed, this should be fast even though EntraIdentity will also include EntraGroups
|
|
92
|
+
target_node_label: str = "EntraIdentity"
|
|
93
|
+
target_node_matcher: TargetNodeMatcher = make_target_node_matcher(
|
|
94
|
+
{"id": PropertyRef("owner_ids", one_to_many=True)}
|
|
95
|
+
)
|
|
96
|
+
direction: LinkDirection = LinkDirection.INWARD
|
|
97
|
+
rel_label: str = "OWNER_OF"
|
|
98
|
+
properties: EntraGroupToOwnerRelProperties = EntraGroupToOwnerRelProperties()
|
|
99
|
+
|
|
100
|
+
|
|
81
101
|
@dataclass(frozen=True)
|
|
82
102
|
class EntraGroupSchema(CartographyNodeSchema):
|
|
83
103
|
label: str = "EntraGroup"
|
|
@@ -87,5 +107,11 @@ class EntraGroupSchema(CartographyNodeSchema):
|
|
|
87
107
|
[
|
|
88
108
|
EntraGroupToGroupRel(),
|
|
89
109
|
EntraGroupToUserRel(),
|
|
110
|
+
EntraGroupToOwnerRel(),
|
|
111
|
+
]
|
|
112
|
+
)
|
|
113
|
+
extra_node_labels: ExtraNodeLabels = ExtraNodeLabels(
|
|
114
|
+
[
|
|
115
|
+
"EntraIdentity",
|
|
90
116
|
]
|
|
91
117
|
)
|
cartography/models/entra/user.py
CHANGED
|
@@ -3,6 +3,7 @@ from dataclasses import dataclass
|
|
|
3
3
|
from cartography.models.core.common import PropertyRef
|
|
4
4
|
from cartography.models.core.nodes import CartographyNodeProperties
|
|
5
5
|
from cartography.models.core.nodes import CartographyNodeSchema
|
|
6
|
+
from cartography.models.core.nodes import ExtraNodeLabels
|
|
6
7
|
from cartography.models.core.relationships import CartographyRelProperties
|
|
7
8
|
from cartography.models.core.relationships import CartographyRelSchema
|
|
8
9
|
from cartography.models.core.relationships import LinkDirection
|
|
@@ -63,3 +64,8 @@ class EntraUserSchema(CartographyNodeSchema):
|
|
|
63
64
|
label: str = "EntraUser"
|
|
64
65
|
properties: EntraUserNodeProperties = EntraUserNodeProperties()
|
|
65
66
|
sub_resource_relationship: EntraUserToTenantRel = EntraUserToTenantRel()
|
|
67
|
+
extra_node_labels: ExtraNodeLabels = ExtraNodeLabels(
|
|
68
|
+
[
|
|
69
|
+
"EntraIdentity",
|
|
70
|
+
]
|
|
71
|
+
)
|
|
File without changes
|
|
@@ -0,0 +1,50 @@
|
|
|
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 GCPVpcNodeProperties(CartographyNodeProperties):
|
|
15
|
+
id: PropertyRef = PropertyRef("partial_uri", extra_index=True)
|
|
16
|
+
lastupdated: PropertyRef = PropertyRef("LASTUPDATED", set_in_kwargs=True)
|
|
17
|
+
partial_uri: PropertyRef = PropertyRef("partial_uri")
|
|
18
|
+
self_link: PropertyRef = PropertyRef("self_link")
|
|
19
|
+
name: PropertyRef = PropertyRef("name", extra_index=True)
|
|
20
|
+
project_id: PropertyRef = PropertyRef("PROJECT_ID", set_in_kwargs=True)
|
|
21
|
+
auto_create_subnetworks: PropertyRef = PropertyRef("auto_create_subnetworks")
|
|
22
|
+
routing_config_routing_mode: PropertyRef = PropertyRef(
|
|
23
|
+
"routing_config_routing_mode"
|
|
24
|
+
)
|
|
25
|
+
description: PropertyRef = PropertyRef("description")
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
@dataclass(frozen=True)
|
|
29
|
+
class GCPVpcToProjectRelProperties(CartographyRelProperties):
|
|
30
|
+
lastupdated: PropertyRef = PropertyRef("LASTUPDATED", set_in_kwargs=True)
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
@dataclass(frozen=True)
|
|
34
|
+
class GCPVpcToProjectRel(CartographyRelSchema):
|
|
35
|
+
target_node_label: str = "GCPProject"
|
|
36
|
+
target_node_matcher: TargetNodeMatcher = make_target_node_matcher(
|
|
37
|
+
{
|
|
38
|
+
"id": PropertyRef("PROJECT_ID", set_in_kwargs=True),
|
|
39
|
+
}
|
|
40
|
+
)
|
|
41
|
+
direction: LinkDirection = LinkDirection.INWARD
|
|
42
|
+
rel_label: str = "RESOURCE"
|
|
43
|
+
properties: GCPVpcToProjectRelProperties = GCPVpcToProjectRelProperties()
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
@dataclass(frozen=True)
|
|
47
|
+
class GCPVpcSchema(CartographyNodeSchema):
|
|
48
|
+
label: str = "GCPVpc"
|
|
49
|
+
properties: GCPVpcNodeProperties = GCPVpcNodeProperties()
|
|
50
|
+
sub_resource_relationship: GCPVpcToProjectRel = GCPVpcToProjectRel()
|