cartography 0.112.0__py3-none-any.whl → 0.113.0__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.

@@ -1,13 +1,17 @@
1
1
  import logging
2
2
  from typing import Dict
3
3
  from typing import List
4
+ from typing import Tuple
4
5
 
5
6
  import neo4j
6
7
  from googleapiclient.discovery import HttpError
7
8
  from googleapiclient.discovery import Resource
8
9
 
10
+ from cartography.client.core.tx import load
11
+ from cartography.graph.job import GraphJob
9
12
  from cartography.intel.gcp import compute
10
- from cartography.util import run_cleanup_job
13
+ from cartography.models.gcp.storage.bucket import GCPBucketLabelSchema
14
+ from cartography.models.gcp.storage.bucket import GCPBucketSchema
11
15
  from cartography.util import timeit
12
16
 
13
17
  logger = logging.getLogger(__name__)
@@ -58,165 +62,85 @@ def get_gcp_buckets(storage: Resource, project_id: str) -> Dict:
58
62
 
59
63
 
60
64
  @timeit
61
- def transform_gcp_buckets(bucket_res: Dict) -> List[Dict]:
65
+ def transform_gcp_buckets_and_labels(bucket_res: Dict) -> Tuple[List[Dict], List[Dict]]:
62
66
  """
63
- Transform the GCP Storage Bucket response object for Neo4j ingestion
67
+ Transform the GCP Storage Bucket response object for Neo4j ingestion.
64
68
 
65
- :type bucket_res: The GCP storage resource object (https://cloud.google.com/storage/docs/json_api/v1/buckets)
66
- :param bucket_res: The return data
67
-
68
- :rtype: list
69
- :return: List of buckets ready for ingestion to Neo4j
69
+ :param bucket_res: The raw GCP bucket response.
70
+ :return: A tuple of (buckets, bucket_labels) ready for ingestion to Neo4j.
70
71
  """
71
72
 
72
- bucket_list = []
73
+ buckets: List[Dict] = []
74
+ labels: List[Dict] = []
73
75
  for b in bucket_res.get("items", []):
74
- bucket = {}
75
- bucket["etag"] = b.get("etag")
76
- bucket["iam_config_bucket_policy_only"] = (
77
- b.get("iamConfiguration", {})
78
- .get("bucketPolicyOnly", {})
79
- .get("enabled", None)
80
- )
81
- bucket["id"] = b["id"]
82
- bucket["labels"] = [(key, val) for (key, val) in b.get("labels", {}).items()]
83
- bucket["owner_entity"] = b.get("owner", {}).get("entity")
84
- bucket["owner_entity_id"] = b.get("owner", {}).get("entityId")
85
- bucket["kind"] = b.get("kind")
86
- bucket["location"] = b.get("location")
87
- bucket["location_type"] = b.get("locationType")
88
- bucket["meta_generation"] = b.get("metageneration", None)
89
- bucket["project_number"] = b["projectNumber"]
90
- bucket["self_link"] = b.get("selfLink")
91
- bucket["storage_class"] = b.get("storageClass")
92
- bucket["time_created"] = b.get("timeCreated")
93
- bucket["updated"] = b.get("updated")
94
- bucket["versioning_enabled"] = b.get("versioning", {}).get("enabled", None)
95
- bucket["default_event_based_hold"] = b.get("defaultEventBasedHold", None)
96
- bucket["retention_period"] = b.get("retentionPolicy", {}).get(
97
- "retentionPeriod",
98
- None,
99
- )
100
- bucket["default_kms_key_name"] = b.get("encryption", {}).get(
101
- "defaultKmsKeyName",
102
- )
103
- bucket["log_bucket"] = b.get("logging", {}).get("logBucket")
104
- bucket["requester_pays"] = b.get("billing", {}).get("requesterPays", None)
105
- bucket_list.append(bucket)
106
- return bucket_list
76
+ bucket = {
77
+ "iam_config_bucket_policy_only": (
78
+ b.get("iamConfiguration", {}).get("bucketPolicyOnly", {}).get("enabled")
79
+ ),
80
+ "id": b["id"],
81
+ # Preserve legacy bucket_id field for compatibility
82
+ "bucket_id": b["id"],
83
+ "owner_entity": b.get("owner", {}).get("entity"),
84
+ "owner_entity_id": b.get("owner", {}).get("entityId"),
85
+ "kind": b.get("kind"),
86
+ "location": b.get("location"),
87
+ "location_type": b.get("locationType"),
88
+ "meta_generation": b.get("metageneration"),
89
+ "project_number": b.get("projectNumber"),
90
+ "self_link": b.get("selfLink"),
91
+ "storage_class": b.get("storageClass"),
92
+ "time_created": b.get("timeCreated"),
93
+ "versioning_enabled": b.get("versioning", {}).get("enabled"),
94
+ "retention_period": b.get("retentionPolicy", {}).get("retentionPeriod"),
95
+ "default_kms_key_name": b.get("encryption", {}).get("defaultKmsKeyName"),
96
+ "log_bucket": b.get("logging", {}).get("logBucket"),
97
+ "requester_pays": b.get("billing", {}).get("requesterPays"),
98
+ }
99
+ buckets.append(bucket)
100
+ for key, val in b.get("labels", {}).items():
101
+ labels.append(
102
+ {
103
+ "id": f"GCPBucket_{key}",
104
+ "key": key,
105
+ "value": val,
106
+ "bucket_id": b["id"],
107
+ }
108
+ )
109
+ return buckets, labels
107
110
 
108
111
 
109
112
  @timeit
110
113
  def load_gcp_buckets(
111
114
  neo4j_session: neo4j.Session,
112
115
  buckets: List[Dict],
116
+ project_id: str,
113
117
  gcp_update_tag: int,
114
118
  ) -> None:
115
- """
116
- Ingest GCP Storage Buckets to Neo4j
117
-
118
- :type neo4j_session: Neo4j session object
119
- :param neo4j session: The Neo4j session object
120
-
121
- :type buckets: list
122
- :param buckets: List of GCP Storage Buckets to injest
123
-
124
- :type gcp_update_tag: timestamp
125
- :param gcp_update_tag: The timestamp value to set our new Neo4j nodes with
126
-
127
- :rtype: NoneType
128
- :return: Nothing
129
- """
130
-
131
- query = """
132
- MERGE(p:GCPProject{projectnumber:$ProjectNumber})
133
- ON CREATE SET p.firstseen = timestamp()
134
- SET p.lastupdated = $gcp_update_tag
135
-
136
- MERGE(bucket:GCPBucket{id:$BucketId})
137
- ON CREATE SET bucket.firstseen = timestamp(),
138
- bucket.bucket_id = $BucketId
139
- SET bucket.self_link = $SelfLink,
140
- bucket.project_number = $ProjectNumber,
141
- bucket.kind = $Kind,
142
- bucket.location = $Location,
143
- bucket.location_type = $LocationType,
144
- bucket.meta_generation = $MetaGeneration,
145
- bucket.storage_class = $StorageClass,
146
- bucket.time_created = $TimeCreated,
147
- bucket.retention_period = $RetentionPeriod,
148
- bucket.iam_config_bucket_policy_only = $IamConfigBucketPolicyOnly,
149
- bucket.owner_entity = $OwnerEntity,
150
- bucket.owner_entity_id = $OwnerEntityId,
151
- bucket.lastupdated = $gcp_update_tag,
152
- bucket.versioning_enabled = $VersioningEnabled,
153
- bucket.log_bucket = $LogBucket,
154
- bucket.requester_pays = $RequesterPays,
155
- bucket.default_kms_key_name = $DefaultKmsKeyName
156
-
157
- MERGE (p)-[r:RESOURCE]->(bucket)
158
- ON CREATE SET r.firstseen = timestamp()
159
- SET r.lastupdated = $gcp_update_tag
160
- """
161
- for bucket in buckets:
162
- neo4j_session.run(
163
- query,
164
- ProjectNumber=bucket["project_number"],
165
- BucketId=bucket["id"],
166
- SelfLink=bucket["self_link"],
167
- Kind=bucket["kind"],
168
- Location=bucket["location"],
169
- LocationType=bucket["location_type"],
170
- MetaGeneration=bucket["meta_generation"],
171
- StorageClass=bucket["storage_class"],
172
- TimeCreated=bucket["time_created"],
173
- RetentionPeriod=bucket["retention_period"],
174
- IamConfigBucketPolicyOnly=bucket["iam_config_bucket_policy_only"],
175
- OwnerEntity=bucket["owner_entity"],
176
- OwnerEntityId=bucket["owner_entity_id"],
177
- VersioningEnabled=bucket["versioning_enabled"],
178
- LogBucket=bucket["log_bucket"],
179
- RequesterPays=bucket["requester_pays"],
180
- DefaultKmsKeyName=bucket["default_kms_key_name"],
181
- gcp_update_tag=gcp_update_tag,
182
- )
183
- _attach_gcp_bucket_labels(neo4j_session, bucket, gcp_update_tag)
119
+ """Ingest GCP Storage Buckets to Neo4j."""
120
+ load(
121
+ neo4j_session,
122
+ GCPBucketSchema(),
123
+ buckets,
124
+ lastupdated=gcp_update_tag,
125
+ PROJECT_ID=project_id,
126
+ )
184
127
 
185
128
 
186
129
  @timeit
187
- def _attach_gcp_bucket_labels(
130
+ def load_gcp_bucket_labels(
188
131
  neo4j_session: neo4j.Session,
189
- bucket: Resource,
132
+ bucket_labels: List[Dict],
133
+ project_id: str,
190
134
  gcp_update_tag: int,
191
135
  ) -> None:
192
- """
193
- Attach GCP bucket labels to the bucket.
194
- :param neo4j_session: The neo4j session
195
- :param bucket: The GCP bucket object
196
- :param gcp_update_tag: The update tag for this sync
197
- :return: Nothing
198
- """
199
- query = """
200
- MERGE (l:Label:GCPBucketLabel{id: $BucketLabelId})
201
- ON CREATE SET l.firstseen = timestamp(),
202
- l.key = $Key
203
- SET l.value = $Value,
204
- l.lastupdated = $gcp_update_tag
205
- WITH l
206
- MATCH (bucket:GCPBucket{id:$BucketId})
207
- MERGE (l)<-[r:LABELED]-(bucket)
208
- ON CREATE SET r.firstseen = timestamp()
209
- SET r.lastupdated = $gcp_update_tag
210
- """
211
- for key, val in bucket.get("labels", []):
212
- neo4j_session.run(
213
- query,
214
- BucketLabelId=f"GCPBucket_{key}",
215
- Key=key,
216
- Value=val,
217
- BucketId=bucket["id"],
218
- gcp_update_tag=gcp_update_tag,
219
- )
136
+ """Ingest GCP Storage Bucket labels and attach them to buckets."""
137
+ load(
138
+ neo4j_session,
139
+ GCPBucketLabelSchema(),
140
+ bucket_labels,
141
+ lastupdated=gcp_update_tag,
142
+ PROJECT_ID=project_id,
143
+ )
220
144
 
221
145
 
222
146
  @timeit
@@ -224,22 +148,14 @@ def cleanup_gcp_buckets(
224
148
  neo4j_session: neo4j.Session,
225
149
  common_job_parameters: Dict,
226
150
  ) -> None:
227
- """
228
- Delete out-of-date GCP Storage Bucket nodes and relationships
229
-
230
- :type neo4j_session: The Neo4j session object
231
- :param neo4j_session: The Neo4j session
232
-
233
- :type common_job_parameters: dict
234
- :param common_job_parameters: Dictionary of other job parameters to pass to Neo4j
235
-
236
- :rtype: NoneType
237
- :return: Nothing
238
- """
239
- run_cleanup_job(
240
- "gcp_storage_bucket_cleanup.json",
151
+ """Delete out-of-date GCP Storage Bucket nodes and relationships."""
152
+ # Bucket labels depend on buckets, so we must remove labels first to avoid
153
+ # dangling references before deleting the buckets themselves.
154
+ GraphJob.from_node_schema(GCPBucketLabelSchema(), common_job_parameters).run(
155
+ neo4j_session,
156
+ )
157
+ GraphJob.from_node_schema(GCPBucketSchema(), common_job_parameters).run(
241
158
  neo4j_session,
242
- common_job_parameters,
243
159
  )
244
160
 
245
161
 
@@ -274,7 +190,7 @@ def sync_gcp_buckets(
274
190
  """
275
191
  logger.info("Syncing Storage objects for project %s.", project_id)
276
192
  storage_res = get_gcp_buckets(storage, project_id)
277
- bucket_list = transform_gcp_buckets(storage_res)
278
- load_gcp_buckets(neo4j_session, bucket_list, gcp_update_tag)
279
- # TODO scope the cleanup to the current project - https://github.com/cartography-cncf/cartography/issues/381
193
+ buckets, bucket_labels = transform_gcp_buckets_and_labels(storage_res)
194
+ load_gcp_buckets(neo4j_session, buckets, project_id, gcp_update_tag)
195
+ load_gcp_bucket_labels(neo4j_session, bucket_labels, project_id, gcp_update_tag)
280
196
  cleanup_gcp_buckets(neo4j_session, common_job_parameters)
File without changes
@@ -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 APIGatewayV2APINodeProperties(CartographyNodeProperties):
15
+ id: PropertyRef = PropertyRef("id", extra_index=True)
16
+ name: PropertyRef = PropertyRef("name")
17
+ protocoltype: PropertyRef = PropertyRef("protocolType")
18
+ routeselectionexpression: PropertyRef = PropertyRef("routeSelectionExpression")
19
+ apikeyselectionexpression: PropertyRef = PropertyRef("apiKeySelectionExpression")
20
+ apiendpoint: PropertyRef = PropertyRef("apiEndpoint")
21
+ version: PropertyRef = PropertyRef("version")
22
+ createddate: PropertyRef = PropertyRef("createdDate")
23
+ description: PropertyRef = PropertyRef("description")
24
+ region: PropertyRef = PropertyRef("region", set_in_kwargs=True)
25
+ lastupdated: PropertyRef = PropertyRef("lastupdated", set_in_kwargs=True)
26
+
27
+
28
+ @dataclass(frozen=True)
29
+ class APIGatewayV2APIToAWSAccountRelProperties(CartographyRelProperties):
30
+ lastupdated: PropertyRef = PropertyRef("lastupdated", set_in_kwargs=True)
31
+
32
+
33
+ @dataclass(frozen=True)
34
+ # (:APIGatewayV2API)<-[:RESOURCE]-(:AWSAccount)
35
+ class APIGatewayV2APIToAWSAccountRel(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: APIGatewayV2APIToAWSAccountRelProperties = (
43
+ APIGatewayV2APIToAWSAccountRelProperties()
44
+ )
45
+
46
+
47
+ @dataclass(frozen=True)
48
+ class APIGatewayV2APISchema(CartographyNodeSchema):
49
+ label: str = "APIGatewayV2API"
50
+ properties: APIGatewayV2APINodeProperties = APIGatewayV2APINodeProperties()
51
+ sub_resource_relationship: APIGatewayV2APIToAWSAccountRel = (
52
+ APIGatewayV2APIToAWSAccountRel()
53
+ )
@@ -0,0 +1,109 @@
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 GCPDNSZoneNodeProperties(CartographyNodeProperties):
17
+ id: PropertyRef = PropertyRef("id", extra_index=True)
18
+ name: PropertyRef = PropertyRef("name", extra_index=True)
19
+ dns_name: PropertyRef = PropertyRef("dns_name")
20
+ description: PropertyRef = PropertyRef("description")
21
+ visibility: PropertyRef = PropertyRef("visibility")
22
+ kind: PropertyRef = PropertyRef("kind")
23
+ nameservers: PropertyRef = PropertyRef("nameservers")
24
+ created_at: PropertyRef = PropertyRef("created_at")
25
+ lastupdated: PropertyRef = PropertyRef("lastupdated", set_in_kwargs=True)
26
+
27
+
28
+ @dataclass(frozen=True)
29
+ class GCPDNSZoneToProjectRelProperties(CartographyRelProperties):
30
+ lastupdated: PropertyRef = PropertyRef("lastupdated", set_in_kwargs=True)
31
+
32
+
33
+ @dataclass(frozen=True)
34
+ # (:GCPProject)-[:RESOURCE]->(:GCPDNSZone)
35
+ class GCPDNSZoneToProjectRel(CartographyRelSchema):
36
+ target_node_label: str = "GCPProject"
37
+ target_node_matcher: TargetNodeMatcher = make_target_node_matcher(
38
+ {"id": PropertyRef("PROJECT_ID", set_in_kwargs=True)}
39
+ )
40
+ direction: LinkDirection = LinkDirection.INWARD
41
+ rel_label: str = "RESOURCE"
42
+ properties: GCPDNSZoneToProjectRelProperties = GCPDNSZoneToProjectRelProperties()
43
+
44
+
45
+ @dataclass(frozen=True)
46
+ class GCPDNSZoneSchema(CartographyNodeSchema):
47
+ label: str = "GCPDNSZone"
48
+ properties: GCPDNSZoneNodeProperties = GCPDNSZoneNodeProperties()
49
+ extra_node_labels: ExtraNodeLabels = ExtraNodeLabels(["DNSZone"])
50
+ sub_resource_relationship: GCPDNSZoneToProjectRel = GCPDNSZoneToProjectRel()
51
+
52
+
53
+ @dataclass(frozen=True)
54
+ class GCPRecordSetNodeProperties(CartographyNodeProperties):
55
+ id: PropertyRef = PropertyRef("id", extra_index=True)
56
+ name: PropertyRef = PropertyRef("name", extra_index=True)
57
+ type: PropertyRef = PropertyRef("type")
58
+ ttl: PropertyRef = PropertyRef("ttl")
59
+ data: PropertyRef = PropertyRef("data")
60
+ lastupdated: PropertyRef = PropertyRef("lastupdated", set_in_kwargs=True)
61
+
62
+
63
+ @dataclass(frozen=True)
64
+ class GCPRecordSetToProjectRelProperties(CartographyRelProperties):
65
+ lastupdated: PropertyRef = PropertyRef("lastupdated", set_in_kwargs=True)
66
+
67
+
68
+ @dataclass(frozen=True)
69
+ # (:GCPProject)-[:RESOURCE]->(:GCPRecordSet)
70
+ class GCPRecordSetToProjectRel(CartographyRelSchema):
71
+ target_node_label: str = "GCPProject"
72
+ target_node_matcher: TargetNodeMatcher = make_target_node_matcher(
73
+ {"id": PropertyRef("PROJECT_ID", set_in_kwargs=True)}
74
+ )
75
+ direction: LinkDirection = LinkDirection.INWARD
76
+ rel_label: str = "RESOURCE"
77
+ properties: GCPRecordSetToProjectRelProperties = (
78
+ GCPRecordSetToProjectRelProperties()
79
+ )
80
+
81
+
82
+ @dataclass(frozen=True)
83
+ class GCPRecordSetToZoneRelProperties(CartographyRelProperties):
84
+ lastupdated: PropertyRef = PropertyRef("lastupdated", set_in_kwargs=True)
85
+
86
+
87
+ @dataclass(frozen=True)
88
+ # (:GCPDNSZone)-[:HAS_RECORD]->(:GCPRecordSet)
89
+ class GCPRecordSetToZoneRel(CartographyRelSchema):
90
+ target_node_label: str = "GCPDNSZone"
91
+ target_node_matcher: TargetNodeMatcher = make_target_node_matcher(
92
+ {"id": PropertyRef("zone_id")}
93
+ )
94
+ direction: LinkDirection = LinkDirection.INWARD
95
+ rel_label: str = "HAS_RECORD"
96
+ properties: GCPRecordSetToZoneRelProperties = GCPRecordSetToZoneRelProperties()
97
+
98
+
99
+ @dataclass(frozen=True)
100
+ class GCPRecordSetSchema(CartographyNodeSchema):
101
+ label: str = "GCPRecordSet"
102
+ properties: GCPRecordSetNodeProperties = GCPRecordSetNodeProperties()
103
+ extra_node_labels: ExtraNodeLabels = ExtraNodeLabels(["DNSRecord"])
104
+ sub_resource_relationship: GCPRecordSetToProjectRel = GCPRecordSetToProjectRel()
105
+ other_relationships: OtherRelationships = OtherRelationships(
106
+ [
107
+ GCPRecordSetToZoneRel(),
108
+ ]
109
+ )
@@ -4,6 +4,7 @@ from dataclasses import dataclass
4
4
  from cartography.models.core.common import PropertyRef
5
5
  from cartography.models.core.nodes import CartographyNodeProperties
6
6
  from cartography.models.core.nodes import CartographyNodeSchema
7
+ from cartography.models.core.nodes import ExtraNodeLabels
7
8
  from cartography.models.core.relationships import CartographyRelProperties
8
9
  from cartography.models.core.relationships import CartographyRelSchema
9
10
  from cartography.models.core.relationships import LinkDirection
@@ -61,6 +62,8 @@ class GCPServiceAccountSchema(CartographyNodeSchema):
61
62
  label: str = "GCPServiceAccount"
62
63
  properties: GCPServiceAccountNodeProperties = GCPServiceAccountNodeProperties()
63
64
  sub_resource_relationship: GCPPrincipalToProject = GCPPrincipalToProject()
65
+ # Service accounts are principals; add shared label for cross-module queries
66
+ extra_node_labels: ExtraNodeLabels = ExtraNodeLabels(["GCPPrincipal"])
64
67
 
65
68
 
66
69
  @dataclass(frozen=True)
File without changes
@@ -0,0 +1,119 @@
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 GCPBucketNodeProperties(CartographyNodeProperties):
16
+ id: PropertyRef = PropertyRef("id", extra_index=True)
17
+ # Preserve legacy field for compatibility with existing queries
18
+ bucket_id: PropertyRef = PropertyRef("bucket_id")
19
+ project_number: PropertyRef = PropertyRef("project_number")
20
+ self_link: PropertyRef = PropertyRef("self_link")
21
+ kind: PropertyRef = PropertyRef("kind")
22
+ location: PropertyRef = PropertyRef("location")
23
+ location_type: PropertyRef = PropertyRef("location_type")
24
+ meta_generation: PropertyRef = PropertyRef("meta_generation")
25
+ storage_class: PropertyRef = PropertyRef("storage_class")
26
+ time_created: PropertyRef = PropertyRef("time_created")
27
+ retention_period: PropertyRef = PropertyRef("retention_period")
28
+ iam_config_bucket_policy_only: PropertyRef = PropertyRef(
29
+ "iam_config_bucket_policy_only"
30
+ )
31
+ owner_entity: PropertyRef = PropertyRef("owner_entity")
32
+ owner_entity_id: PropertyRef = PropertyRef("owner_entity_id")
33
+ versioning_enabled: PropertyRef = PropertyRef("versioning_enabled")
34
+ log_bucket: PropertyRef = PropertyRef("log_bucket")
35
+ requester_pays: PropertyRef = PropertyRef("requester_pays")
36
+ default_kms_key_name: PropertyRef = PropertyRef("default_kms_key_name")
37
+ lastupdated: PropertyRef = PropertyRef("lastupdated", set_in_kwargs=True)
38
+
39
+
40
+ @dataclass(frozen=True)
41
+ class GCPBucketToProjectRelProperties(CartographyRelProperties):
42
+ lastupdated: PropertyRef = PropertyRef("lastupdated", set_in_kwargs=True)
43
+
44
+
45
+ @dataclass(frozen=True)
46
+ # (:GCPProject)-[:RESOURCE]->(:GCPBucket)
47
+ class GCPBucketToProjectRel(CartographyRelSchema):
48
+ target_node_label: str = "GCPProject"
49
+ target_node_matcher: TargetNodeMatcher = make_target_node_matcher(
50
+ {"id": PropertyRef("PROJECT_ID", set_in_kwargs=True)}
51
+ )
52
+ direction: LinkDirection = LinkDirection.INWARD
53
+ rel_label: str = "RESOURCE"
54
+ properties: GCPBucketToProjectRelProperties = GCPBucketToProjectRelProperties()
55
+
56
+
57
+ @dataclass(frozen=True)
58
+ class GCPBucketSchema(CartographyNodeSchema):
59
+ label: str = "GCPBucket"
60
+ properties: GCPBucketNodeProperties = GCPBucketNodeProperties()
61
+ sub_resource_relationship: GCPBucketToProjectRel = GCPBucketToProjectRel()
62
+
63
+
64
+ @dataclass(frozen=True)
65
+ class GCPBucketLabelNodeProperties(CartographyNodeProperties):
66
+ id: PropertyRef = PropertyRef("id", extra_index=True)
67
+ key: PropertyRef = PropertyRef("key", extra_index=True)
68
+ value: PropertyRef = PropertyRef("value")
69
+ lastupdated: PropertyRef = PropertyRef("lastupdated", set_in_kwargs=True)
70
+
71
+
72
+ @dataclass(frozen=True)
73
+ class GCPBucketLabelToProjectRelProperties(CartographyRelProperties):
74
+ lastupdated: PropertyRef = PropertyRef("lastupdated", set_in_kwargs=True)
75
+
76
+
77
+ @dataclass(frozen=True)
78
+ # (:GCPProject)-[:RESOURCE]->(:GCPBucketLabel)
79
+ class GCPBucketLabelToProjectRel(CartographyRelSchema):
80
+ target_node_label: str = "GCPProject"
81
+ target_node_matcher: TargetNodeMatcher = make_target_node_matcher(
82
+ {"id": PropertyRef("PROJECT_ID", set_in_kwargs=True)}
83
+ )
84
+ direction: LinkDirection = LinkDirection.INWARD
85
+ rel_label: str = "RESOURCE"
86
+ properties: GCPBucketLabelToProjectRelProperties = (
87
+ GCPBucketLabelToProjectRelProperties()
88
+ )
89
+
90
+
91
+ @dataclass(frozen=True)
92
+ class GCPBucketLabelToBucketRelProperties(CartographyRelProperties):
93
+ lastupdated: PropertyRef = PropertyRef("lastupdated", set_in_kwargs=True)
94
+
95
+
96
+ @dataclass(frozen=True)
97
+ # (:GCPBucket)-[:LABELED]->(:GCPBucketLabel)
98
+ class GCPBucketLabelToBucketRel(CartographyRelSchema):
99
+ target_node_label: str = "GCPBucket"
100
+ target_node_matcher: TargetNodeMatcher = make_target_node_matcher(
101
+ {"id": PropertyRef("bucket_id")}
102
+ )
103
+ direction: LinkDirection = LinkDirection.INWARD
104
+ rel_label: str = "LABELED"
105
+ properties: GCPBucketLabelToBucketRelProperties = (
106
+ GCPBucketLabelToBucketRelProperties()
107
+ )
108
+
109
+
110
+ @dataclass(frozen=True)
111
+ class GCPBucketLabelSchema(CartographyNodeSchema):
112
+ label: str = "GCPBucketLabel"
113
+ properties: GCPBucketLabelNodeProperties = GCPBucketLabelNodeProperties()
114
+ sub_resource_relationship: GCPBucketLabelToProjectRel = GCPBucketLabelToProjectRel()
115
+ other_relationships: OtherRelationships = OtherRelationships(
116
+ [
117
+ GCPBucketLabelToBucketRel(),
118
+ ]
119
+ )
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cartography
3
- Version: 0.112.0
3
+ Version: 0.113.0
4
4
  Summary: Explore assets and their relationships across your technical infrastructure.
5
5
  Maintainer: Cartography Contributors
6
6
  License-Expression: Apache-2.0