cartography 0.108.0rc1__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.

Files changed (37) hide show
  1. cartography/_version.py +2 -2
  2. cartography/data/indexes.cypher +0 -2
  3. cartography/data/jobs/cleanup/gcp_compute_vpc_cleanup.json +0 -12
  4. cartography/intel/aws/cloudtrail.py +17 -4
  5. cartography/intel/aws/cloudtrail_management_events.py +593 -16
  6. cartography/intel/aws/cloudwatch.py +73 -4
  7. cartography/intel/aws/ec2/subnets.py +37 -63
  8. cartography/intel/aws/ecr.py +55 -80
  9. cartography/intel/aws/elasticache.py +102 -79
  10. cartography/intel/aws/resourcegroupstaggingapi.py +77 -18
  11. cartography/intel/aws/secretsmanager.py +62 -44
  12. cartography/intel/entra/groups.py +29 -1
  13. cartography/intel/gcp/__init__.py +10 -0
  14. cartography/intel/gcp/compute.py +19 -42
  15. cartography/models/aws/cloudtrail/management_events.py +95 -6
  16. cartography/models/aws/cloudtrail/trail.py +21 -0
  17. cartography/models/aws/cloudwatch/metric_alarm.py +53 -0
  18. cartography/models/aws/ec2/subnets.py +65 -0
  19. cartography/models/aws/ecr/__init__.py +0 -0
  20. cartography/models/aws/ecr/image.py +41 -0
  21. cartography/models/aws/ecr/repository.py +72 -0
  22. cartography/models/aws/ecr/repository_image.py +95 -0
  23. cartography/models/aws/elasticache/__init__.py +0 -0
  24. cartography/models/aws/elasticache/cluster.py +65 -0
  25. cartography/models/aws/elasticache/topic.py +67 -0
  26. cartography/models/aws/secretsmanager/secret.py +106 -0
  27. cartography/models/entra/group.py +26 -0
  28. cartography/models/entra/user.py +6 -0
  29. cartography/models/gcp/compute/__init__.py +0 -0
  30. cartography/models/gcp/compute/vpc.py +50 -0
  31. {cartography-0.108.0rc1.dist-info → cartography-0.109.0rc1.dist-info}/METADATA +1 -1
  32. {cartography-0.108.0rc1.dist-info → cartography-0.109.0rc1.dist-info}/RECORD +36 -25
  33. cartography/data/jobs/cleanup/aws_import_secrets_cleanup.json +0 -8
  34. {cartography-0.108.0rc1.dist-info → cartography-0.109.0rc1.dist-info}/WHEEL +0 -0
  35. {cartography-0.108.0rc1.dist-info → cartography-0.109.0rc1.dist-info}/entry_points.txt +0 -0
  36. {cartography-0.108.0rc1.dist-info → cartography-0.109.0rc1.dist-info}/licenses/LICENSE +0 -0
  37. {cartography-0.108.0rc1.dist-info → cartography-0.109.0rc1.dist-info}/top_level.txt +0 -0
@@ -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: List[Dict],
606
+ vpcs: list[dict[str, Any]],
604
607
  gcp_update_tag: int,
608
+ project_id: str,
605
609
  ) -> None:
606
- """
607
- Ingest VPCs to Neo4j
608
- :param neo4j_session: The Neo4j session object
609
- :param vpcs: List of VPCs to ingest
610
- :param gcp_update_tag: The timestamp value to set our new Neo4j nodes with
611
- :return: Nothing
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
 
@@ -29,12 +29,6 @@ class AssumedRoleRelProperties(CartographyRelProperties):
29
29
  times_used: PropertyRef = PropertyRef("times_used")
30
30
  first_seen_in_time_window: PropertyRef = PropertyRef("first_seen_in_time_window")
31
31
 
32
- # Event type tracking properties
33
- event_types: PropertyRef = PropertyRef("event_types")
34
- assume_role_count: PropertyRef = PropertyRef("assume_role_count")
35
- saml_count: PropertyRef = PropertyRef("saml_count")
36
- web_identity_count: PropertyRef = PropertyRef("web_identity_count")
37
-
38
32
 
39
33
  @dataclass(frozen=True)
40
34
  class AssumedRoleMatchLink(CartographyRelSchema):
@@ -62,3 +56,98 @@ class AssumedRoleMatchLink(CartographyRelSchema):
62
56
  direction: LinkDirection = LinkDirection.OUTWARD
63
57
  rel_label: str = "ASSUMED_ROLE"
64
58
  properties: AssumedRoleRelProperties = AssumedRoleRelProperties()
59
+
60
+
61
+ @dataclass(frozen=True)
62
+ class AssumedRoleWithSAMLRelProperties(CartographyRelProperties):
63
+ """
64
+ Properties for the ASSUMED_ROLE_WITH_SAML relationship representing SAML-based role assumption events.
65
+ Focuses specifically on SAML federated identity role assumptions.
66
+ """
67
+
68
+ # Mandatory fields for MatchLinks
69
+ lastupdated: PropertyRef = PropertyRef("lastupdated", set_in_kwargs=True)
70
+ _sub_resource_label: PropertyRef = PropertyRef(
71
+ "_sub_resource_label", set_in_kwargs=True
72
+ )
73
+ _sub_resource_id: PropertyRef = PropertyRef("_sub_resource_id", set_in_kwargs=True)
74
+
75
+ # CloudTrail-specific relationship properties
76
+ last_used: PropertyRef = PropertyRef("last_used")
77
+ times_used: PropertyRef = PropertyRef("times_used")
78
+ first_seen_in_time_window: PropertyRef = PropertyRef("first_seen_in_time_window")
79
+
80
+
81
+ @dataclass(frozen=True)
82
+ class AssumedRoleWithSAMLMatchLink(CartographyRelSchema):
83
+ """
84
+ MatchLink schema for ASSUMED_ROLE_WITH_SAML relationships from CloudTrail SAML events.
85
+ Creates relationships like: (AWSRole)-[:ASSUMED_ROLE_WITH_SAML]->(AWSRole)
86
+
87
+ This MatchLink handles SAML-based role assumption relationships discovered via CloudTrail
88
+ AssumeRoleWithSAML events. It creates separate relationships from regular AssumeRole events
89
+ to preserve visibility into authentication methods used.
90
+ """
91
+
92
+ # MatchLink-specific fields
93
+ source_node_label: str = "AWSSSOUser" # Match against AWS SSO User nodes
94
+ source_node_matcher: SourceNodeMatcher = make_source_node_matcher(
95
+ {"user_name": PropertyRef("source_principal_arn")},
96
+ )
97
+
98
+ # Standard CartographyRelSchema fields
99
+ target_node_label: str = "AWSRole"
100
+ target_node_matcher: TargetNodeMatcher = make_target_node_matcher(
101
+ {"arn": PropertyRef("destination_principal_arn")},
102
+ )
103
+ direction: LinkDirection = LinkDirection.OUTWARD
104
+ rel_label: str = "ASSUMED_ROLE_WITH_SAML"
105
+ properties: AssumedRoleWithSAMLRelProperties = AssumedRoleWithSAMLRelProperties()
106
+
107
+
108
+ @dataclass(frozen=True)
109
+ class AssumeRoleWithWebIdentityRelProperties(CartographyRelProperties):
110
+ """
111
+ Properties for the ASSUMED_ROLE_WITH_WEB_IDENTITY relationship representing web identity-based role assumption events.
112
+ Focuses specifically on web identity federation role assumptions (Google, Amazon, Facebook, etc.).
113
+ """
114
+
115
+ # Mandatory fields for MatchLinks
116
+ lastupdated: PropertyRef = PropertyRef("lastupdated", set_in_kwargs=True)
117
+ _sub_resource_label: PropertyRef = PropertyRef(
118
+ "_sub_resource_label", set_in_kwargs=True
119
+ )
120
+ _sub_resource_id: PropertyRef = PropertyRef("_sub_resource_id", set_in_kwargs=True)
121
+
122
+ # CloudTrail-specific relationship properties
123
+ last_used: PropertyRef = PropertyRef("last_used")
124
+ times_used: PropertyRef = PropertyRef("times_used")
125
+ first_seen_in_time_window: PropertyRef = PropertyRef("first_seen_in_time_window")
126
+
127
+
128
+ @dataclass(frozen=True)
129
+ class GitHubRepoAssumeRoleWithWebIdentityMatchLink(CartographyRelSchema):
130
+ """
131
+ MatchLink schema for ASSUMED_ROLE_WITH_WEB_IDENTITY relationships from GitHub Actions to AWS roles.
132
+ Creates relationships like: (GitHubRepository)-[:ASSUMED_ROLE_WITH_WEB_IDENTITY]->(AWSRole)
133
+
134
+ This MatchLink provides granular visibility into which specific GitHub repositories are assuming
135
+ AWS roles via GitHub Actions OIDC, rather than just showing provider-level relationships.
136
+ """
137
+
138
+ # MatchLink-specific fields for GitHub repositories
139
+ source_node_label: str = "GitHubRepository"
140
+ source_node_matcher: SourceNodeMatcher = make_source_node_matcher(
141
+ {"fullname": PropertyRef("source_repo_fullname")},
142
+ )
143
+
144
+ # Standard CartographyRelSchema fields
145
+ target_node_label: str = "AWSRole"
146
+ target_node_matcher: TargetNodeMatcher = make_target_node_matcher(
147
+ {"arn": PropertyRef("destination_principal_arn")},
148
+ )
149
+ direction: LinkDirection = LinkDirection.OUTWARD
150
+ rel_label: str = "ASSUMED_ROLE_WITH_WEB_IDENTITY"
151
+ properties: AssumeRoleWithWebIdentityRelProperties = (
152
+ AssumeRoleWithWebIdentityRelProperties()
153
+ )
@@ -73,6 +73,26 @@ class CloudTrailTrailToS3BucketRel(CartographyRelSchema):
73
73
  )
74
74
 
75
75
 
76
+ @dataclass(frozen=True)
77
+ class CloudTrailTrailToCloudWatchLogGroupRelProperties(CartographyRelProperties):
78
+ lastupdated: PropertyRef = PropertyRef("lastupdated", set_in_kwargs=True)
79
+
80
+
81
+ @dataclass(frozen=True)
82
+ class CloudTrailTrailToCloudWatchLogGroupRel(CartographyRelSchema):
83
+ target_node_label: str = "CloudWatchLogGroup"
84
+ target_node_matcher: TargetNodeMatcher = make_target_node_matcher(
85
+ {
86
+ "id": PropertyRef("CloudWatchLogsLogGroupArn"),
87
+ }
88
+ )
89
+ direction: LinkDirection = LinkDirection.OUTWARD
90
+ rel_label: str = "SENDS_LOGS_TO_CLOUDWATCH"
91
+ properties: CloudTrailTrailToCloudWatchLogGroupRelProperties = (
92
+ CloudTrailTrailToCloudWatchLogGroupRelProperties()
93
+ )
94
+
95
+
76
96
  @dataclass(frozen=True)
77
97
  class CloudTrailTrailSchema(CartographyNodeSchema):
78
98
  label: str = "CloudTrailTrail"
@@ -81,5 +101,6 @@ class CloudTrailTrailSchema(CartographyNodeSchema):
81
101
  other_relationships: OtherRelationships = OtherRelationships(
82
102
  [
83
103
  CloudTrailTrailToS3BucketRel(),
104
+ CloudTrailTrailToCloudWatchLogGroupRel(),
84
105
  ]
85
106
  )
@@ -0,0 +1,53 @@
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 CloudWatchMetricAlarmNodeProperties(CartographyNodeProperties):
15
+ id: PropertyRef = PropertyRef("AlarmArn")
16
+ arn: PropertyRef = PropertyRef("AlarmArn", extra_index=True)
17
+ alarm_name: PropertyRef = PropertyRef("AlarmName")
18
+ alarm_description: PropertyRef = PropertyRef("AlarmDescription")
19
+ state_value: PropertyRef = PropertyRef("StateValue")
20
+ state_reason: PropertyRef = PropertyRef("StateReason")
21
+ actions_enabled: PropertyRef = PropertyRef("ActionsEnabled")
22
+ comparison_operator: PropertyRef = PropertyRef("ComparisonOperator")
23
+ region: PropertyRef = PropertyRef("Region", set_in_kwargs=True)
24
+ lastupdated: PropertyRef = PropertyRef("lastupdated", set_in_kwargs=True)
25
+
26
+
27
+ @dataclass(frozen=True)
28
+ class CloudWatchMetricAlarmToAwsAccountRelProperties(CartographyRelProperties):
29
+ lastupdated: PropertyRef = PropertyRef("lastupdated", set_in_kwargs=True)
30
+
31
+
32
+ @dataclass(frozen=True)
33
+ class CloudWatchMetricAlarmToAWSAccountRel(CartographyRelSchema):
34
+ target_node_label: str = "AWSAccount"
35
+ target_node_matcher: TargetNodeMatcher = make_target_node_matcher(
36
+ {"id": PropertyRef("AWS_ID", set_in_kwargs=True)},
37
+ )
38
+ direction: LinkDirection = LinkDirection.INWARD
39
+ rel_label: str = "RESOURCE"
40
+ properties: CloudWatchMetricAlarmToAwsAccountRelProperties = (
41
+ CloudWatchMetricAlarmToAwsAccountRelProperties()
42
+ )
43
+
44
+
45
+ @dataclass(frozen=True)
46
+ class CloudWatchMetricAlarmSchema(CartographyNodeSchema):
47
+ label: str = "CloudWatchMetricAlarm"
48
+ properties: CloudWatchMetricAlarmNodeProperties = (
49
+ CloudWatchMetricAlarmNodeProperties()
50
+ )
51
+ sub_resource_relationship: CloudWatchMetricAlarmToAWSAccountRel = (
52
+ CloudWatchMetricAlarmToAWSAccountRel()
53
+ )
@@ -0,0 +1,65 @@
1
+ from dataclasses import dataclass
2
+
3
+ from cartography.models.aws.ec2.auto_scaling_groups import EC2SubnetToAWSAccountRel
4
+ from cartography.models.core.common import PropertyRef
5
+ from cartography.models.core.nodes import CartographyNodeProperties
6
+ from cartography.models.core.nodes import CartographyNodeSchema
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 EC2SubnetNodeProperties(CartographyNodeProperties):
17
+ id: PropertyRef = PropertyRef("SubnetId")
18
+ subnetid: PropertyRef = PropertyRef("SubnetId", extra_index=True)
19
+ subnet_id: PropertyRef = PropertyRef("SubnetId", extra_index=True)
20
+ subnet_arn: PropertyRef = PropertyRef("SubnetArn")
21
+ name: PropertyRef = PropertyRef("CidrBlock")
22
+ cidr_block: PropertyRef = PropertyRef("CidrBlock")
23
+ available_ip_address_count: PropertyRef = PropertyRef("AvailableIpAddressCount")
24
+ default_for_az: PropertyRef = PropertyRef("DefaultForAz")
25
+ map_customer_owned_ip_on_launch: PropertyRef = PropertyRef(
26
+ "MapCustomerOwnedIpOnLaunch"
27
+ )
28
+ state: PropertyRef = PropertyRef("State")
29
+ assignipv6addressoncreation: PropertyRef = PropertyRef(
30
+ "AssignIpv6AddressOnCreation"
31
+ )
32
+ map_public_ip_on_launch: PropertyRef = PropertyRef("MapPublicIpOnLaunch")
33
+ availability_zone: PropertyRef = PropertyRef("AvailabilityZone")
34
+ availability_zone_id: PropertyRef = PropertyRef("AvailabilityZoneId")
35
+ vpc_id: PropertyRef = PropertyRef("VpcId")
36
+ region: PropertyRef = PropertyRef("Region", set_in_kwargs=True)
37
+ lastupdated: PropertyRef = PropertyRef("lastupdated", set_in_kwargs=True)
38
+
39
+
40
+ @dataclass(frozen=True)
41
+ class EC2SubnetToVpcRelProperties(CartographyRelProperties):
42
+ lastupdated: PropertyRef = PropertyRef("lastupdated", set_in_kwargs=True)
43
+
44
+
45
+ @dataclass(frozen=True)
46
+ class EC2SubnetToVpcRel(CartographyRelSchema):
47
+ target_node_label: str = "AWSVpc"
48
+ target_node_matcher: TargetNodeMatcher = make_target_node_matcher(
49
+ {"id": PropertyRef("VpcId")}
50
+ )
51
+ direction: LinkDirection = LinkDirection.OUTWARD
52
+ rel_label: str = "MEMBER_OF_AWS_VPC"
53
+ properties: EC2SubnetToVpcRelProperties = EC2SubnetToVpcRelProperties()
54
+
55
+
56
+ @dataclass(frozen=True)
57
+ class EC2SubnetSchema(CartographyNodeSchema):
58
+ label: str = "EC2Subnet"
59
+ properties: EC2SubnetNodeProperties = EC2SubnetNodeProperties()
60
+ sub_resource_relationship: EC2SubnetToAWSAccountRel = EC2SubnetToAWSAccountRel()
61
+ other_relationships: OtherRelationships = OtherRelationships(
62
+ [
63
+ EC2SubnetToVpcRel(),
64
+ ]
65
+ )
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
+ )
File without changes
@@ -0,0 +1,65 @@
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 ElasticacheClusterNodeProperties(CartographyNodeProperties):
15
+ id: PropertyRef = PropertyRef("ARN")
16
+ arn: PropertyRef = PropertyRef("ARN", extra_index=True)
17
+ cache_cluster_id: PropertyRef = PropertyRef("CacheClusterId")
18
+ cache_node_type: PropertyRef = PropertyRef("CacheNodeType")
19
+ engine: PropertyRef = PropertyRef("Engine")
20
+ engine_version: PropertyRef = PropertyRef("EngineVersion")
21
+ cache_cluster_status: PropertyRef = PropertyRef("CacheClusterStatus")
22
+ num_cache_nodes: PropertyRef = PropertyRef("NumCacheNodes")
23
+ preferred_availability_zone: PropertyRef = PropertyRef("PreferredAvailabilityZone")
24
+ preferred_maintenance_window: PropertyRef = PropertyRef(
25
+ "PreferredMaintenanceWindow"
26
+ )
27
+ cache_cluster_create_time: PropertyRef = PropertyRef("CacheClusterCreateTime")
28
+ cache_subnet_group_name: PropertyRef = PropertyRef("CacheSubnetGroupName")
29
+ auto_minor_version_upgrade: PropertyRef = PropertyRef("AutoMinorVersionUpgrade")
30
+ replication_group_id: PropertyRef = PropertyRef("ReplicationGroupId")
31
+ snapshot_retention_limit: PropertyRef = PropertyRef("SnapshotRetentionLimit")
32
+ snapshot_window: PropertyRef = PropertyRef("SnapshotWindow")
33
+ auth_token_enabled: PropertyRef = PropertyRef("AuthTokenEnabled")
34
+ transit_encryption_enabled: PropertyRef = PropertyRef("TransitEncryptionEnabled")
35
+ at_rest_encryption_enabled: PropertyRef = PropertyRef("AtRestEncryptionEnabled")
36
+ topic_arn: PropertyRef = PropertyRef("TopicArn")
37
+ region: PropertyRef = PropertyRef("Region", set_in_kwargs=True)
38
+ lastupdated: PropertyRef = PropertyRef("lastupdated", set_in_kwargs=True)
39
+
40
+
41
+ @dataclass(frozen=True)
42
+ class ElasticacheClusterToAWSAccountRelProperties(CartographyRelProperties):
43
+ lastupdated: PropertyRef = PropertyRef("lastupdated", set_in_kwargs=True)
44
+
45
+
46
+ @dataclass(frozen=True)
47
+ class ElasticacheClusterToAWSAccountRel(CartographyRelSchema):
48
+ target_node_label: str = "AWSAccount"
49
+ target_node_matcher: TargetNodeMatcher = make_target_node_matcher(
50
+ {"id": PropertyRef("AWS_ID", set_in_kwargs=True)}
51
+ )
52
+ direction: LinkDirection = LinkDirection.INWARD
53
+ rel_label: str = "RESOURCE"
54
+ properties: ElasticacheClusterToAWSAccountRelProperties = (
55
+ ElasticacheClusterToAWSAccountRelProperties()
56
+ )
57
+
58
+
59
+ @dataclass(frozen=True)
60
+ class ElasticacheClusterSchema(CartographyNodeSchema):
61
+ label: str = "ElasticacheCluster"
62
+ properties: ElasticacheClusterNodeProperties = ElasticacheClusterNodeProperties()
63
+ sub_resource_relationship: ElasticacheClusterToAWSAccountRel = (
64
+ ElasticacheClusterToAWSAccountRel()
65
+ )