cartography 0.107.0rc1__py3-none-any.whl → 0.107.0rc2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of cartography might be problematic. Click here for more details.

cartography/_version.py CHANGED
@@ -17,5 +17,5 @@ __version__: str
17
17
  __version_tuple__: VERSION_TUPLE
18
18
  version_tuple: VERSION_TUPLE
19
19
 
20
- __version__ = version = '0.107.0rc1'
21
- __version_tuple__ = version_tuple = (0, 107, 0, 'rc1')
20
+ __version__ = version = '0.107.0rc2'
21
+ __version_tuple__ = version_tuple = (0, 107, 0, 'rc2')
@@ -3,14 +3,17 @@ from typing import Any
3
3
  from typing import Dict
4
4
  from typing import Iterator
5
5
  from typing import List
6
+ from typing import Set
6
7
  from typing import Tuple
7
8
 
8
9
  import boto3
9
10
  import neo4j
10
11
 
11
12
  from cartography.client.core.tx import load
13
+ from cartography.client.core.tx import load_matchlinks
12
14
  from cartography.graph.job import GraphJob
13
15
  from cartography.models.aws.inspector.findings import AWSInspectorFindingSchema
16
+ from cartography.models.aws.inspector.findings import InspectorFindingToPackageMatchLink
14
17
  from cartography.models.aws.inspector.packages import AWSInspectorPackageSchema
15
18
  from cartography.util import aws_handle_regions
16
19
  from cartography.util import aws_paginate
@@ -107,9 +110,10 @@ def get_inspector_findings(
107
110
 
108
111
  def transform_inspector_findings(
109
112
  results: List[Dict[str, Any]],
110
- ) -> Tuple[List[Dict[str, Any]], List[Dict[str, Any]]]:
113
+ ) -> Tuple[List[Dict[str, Any]], List[Dict[str, Any]], List[Dict[str, str]]]:
111
114
  findings_list: List[Dict] = []
112
- packages: Dict[str, Any] = {}
115
+ packages_set: Set[frozenset] = set()
116
+ finding_to_package_map: List[Dict[str, str]] = []
113
117
 
114
118
  for f in results:
115
119
  finding: Dict = {}
@@ -163,55 +167,45 @@ def transform_inspector_findings(
163
167
  "vendorUpdatedAt",
164
168
  )
165
169
 
166
- new_packages = _process_packages(
167
- f["packageVulnerabilityDetails"],
168
- f["awsAccountId"],
169
- f["findingArn"],
170
- )
171
- finding["vulnerablepackageids"] = list(new_packages.keys())
172
- packages = {**packages, **new_packages}
173
-
170
+ packages = transform_inspector_packages(f["packageVulnerabilityDetails"])
171
+ finding["vulnerablepackageids"] = list(packages.keys())
172
+ for package_id, package in packages.items():
173
+ finding_to_package_map.append(
174
+ {
175
+ "findingarn": finding["id"],
176
+ "packageid": package_id,
177
+ "remediation": package.get("remediation"),
178
+ "fixedInVersion": package.get("fixedInVersion"),
179
+ "filePath": package.get("filePath"),
180
+ "sourceLayerHash": package.get("sourceLayerHash"),
181
+ "sourceLambdaLayerArn": package.get("sourceLambdaLayerArn"),
182
+ }
183
+ )
184
+ packages_set.add(frozenset(package.items()))
174
185
  findings_list.append(finding)
175
- packages_list = transform_inspector_packages(packages)
176
- return findings_list, packages_list
177
-
186
+ packages_list = [dict(p) for p in packages_set]
187
+ return findings_list, packages_list, finding_to_package_map
178
188
 
179
- def transform_inspector_packages(packages: Dict[str, Any]) -> List[Dict[str, Any]]:
180
- packages_list: List[Dict] = []
181
- for package_id in packages.keys():
182
- packages_list.append(packages[package_id])
183
189
 
184
- return packages_list
185
-
186
-
187
- def _process_packages(
190
+ def transform_inspector_packages(
188
191
  package_details: Dict[str, Any],
189
- aws_account_id: str,
190
- finding_arn: str,
191
192
  ) -> Dict[str, Any]:
192
193
  packages: Dict[str, Any] = {}
193
194
  for package in package_details["vulnerablePackages"]:
194
- new_package = {}
195
- new_package["id"] = (
196
- f"{package.get('name', '')}|"
197
- f"{package.get('arch', '')}|"
198
- f"{package.get('version', '')}|"
199
- f"{package.get('release', '')}|"
200
- f"{package.get('epoch', '')}"
201
- )
202
- new_package["name"] = package.get("name")
203
- new_package["arch"] = package.get("arch")
204
- new_package["version"] = package.get("version")
205
- new_package["release"] = package.get("release")
206
- new_package["epoch"] = package.get("epoch")
207
- new_package["manager"] = package.get("packageManager")
208
- new_package["filepath"] = package.get("filePath")
209
- new_package["fixedinversion"] = package.get("fixedInVersion")
210
- new_package["sourcelayerhash"] = package.get("sourceLayerHash")
211
- new_package["awsaccount"] = aws_account_id
212
- new_package["findingarn"] = finding_arn
213
-
214
- packages[new_package["id"]] = new_package
195
+ # Following RPM package naming convention for consistency
196
+ name = package["name"] # Mandatory field
197
+ epoch = str(package.get("epoch", ""))
198
+ if epoch:
199
+ epoch = f"{epoch}:"
200
+ version = package["version"] # Mandatory field
201
+ release = package.get("release", "")
202
+ if release:
203
+ release = f"-{release}"
204
+ arch = package.get("arch", "")
205
+ if arch:
206
+ arch = f".{arch}"
207
+ id = f"{name}|{epoch}{version}{release}{arch}"
208
+ packages[id] = {**package, "id": id}
215
209
 
216
210
  return packages
217
211
 
@@ -244,7 +238,6 @@ def load_inspector_findings(
244
238
  def load_inspector_packages(
245
239
  neo4j_session: neo4j.Session,
246
240
  packages: List[Dict[str, Any]],
247
- region: str,
248
241
  aws_update_tag: int,
249
242
  current_aws_account_id: str,
250
243
  ) -> None:
@@ -252,12 +245,28 @@ def load_inspector_packages(
252
245
  neo4j_session,
253
246
  AWSInspectorPackageSchema(),
254
247
  packages,
255
- Region=region,
256
248
  AWS_ID=current_aws_account_id,
257
249
  lastupdated=aws_update_tag,
258
250
  )
259
251
 
260
252
 
253
+ @timeit
254
+ def load_inspector_finding_to_package_match_links(
255
+ neo4j_session: neo4j.Session,
256
+ finding_to_package_map: List[Dict[str, str]],
257
+ aws_update_tag: int,
258
+ current_aws_account_id: str,
259
+ ) -> None:
260
+ load_matchlinks(
261
+ neo4j_session,
262
+ InspectorFindingToPackageMatchLink(),
263
+ finding_to_package_map,
264
+ lastupdated=aws_update_tag,
265
+ _sub_resource_label="AWSAccount",
266
+ _sub_resource_id=current_aws_account_id,
267
+ )
268
+
269
+
261
270
  @timeit
262
271
  def cleanup(
263
272
  neo4j_session: neo4j.Session,
@@ -270,6 +279,14 @@ def cleanup(
270
279
  GraphJob.from_node_schema(AWSInspectorPackageSchema(), common_job_parameters).run(
271
280
  neo4j_session,
272
281
  )
282
+ GraphJob.from_matchlink(
283
+ InspectorFindingToPackageMatchLink(),
284
+ "AWSAccount",
285
+ common_job_parameters["ACCOUNT_ID"],
286
+ common_job_parameters["UPDATE_TAG"],
287
+ ).run(
288
+ neo4j_session,
289
+ )
273
290
 
274
291
 
275
292
  def _sync_findings_for_account(
@@ -288,7 +305,9 @@ def _sync_findings_for_account(
288
305
  logger.info(f"No findings to sync for account {account_id} in region {region}")
289
306
  return
290
307
  for f_batch in findings:
291
- finding_data, package_data = transform_inspector_findings(f_batch)
308
+ finding_data, package_data, finding_to_package_map = (
309
+ transform_inspector_findings(f_batch)
310
+ )
292
311
  logger.info(f"Loading {len(finding_data)} findings from account {account_id}")
293
312
  load_inspector_findings(
294
313
  neo4j_session,
@@ -301,7 +320,15 @@ def _sync_findings_for_account(
301
320
  load_inspector_packages(
302
321
  neo4j_session,
303
322
  package_data,
304
- region,
323
+ update_tag,
324
+ current_aws_account_id,
325
+ )
326
+ logger.info(
327
+ f"Loading {len(finding_to_package_map)} finding to package relationships"
328
+ )
329
+ load_inspector_finding_to_package_match_links(
330
+ neo4j_session,
331
+ finding_to_package_map,
305
332
  update_tag,
306
333
  current_aws_account_id,
307
334
  )
@@ -337,5 +364,7 @@ def sync(
337
364
  update_tag,
338
365
  current_aws_account_id,
339
366
  )
367
+ common_job_parameters["ACCOUNT_ID"] = current_aws_account_id
368
+ common_job_parameters["UPDATE_TAG"] = update_tag
340
369
 
341
370
  cleanup(neo4j_session, common_job_parameters)
@@ -7,8 +7,10 @@ from cartography.models.core.nodes import ExtraNodeLabels
7
7
  from cartography.models.core.relationships import CartographyRelProperties
8
8
  from cartography.models.core.relationships import CartographyRelSchema
9
9
  from cartography.models.core.relationships import LinkDirection
10
+ from cartography.models.core.relationships import make_source_node_matcher
10
11
  from cartography.models.core.relationships import make_target_node_matcher
11
12
  from cartography.models.core.relationships import OtherRelationships
13
+ from cartography.models.core.relationships import SourceNodeMatcher
12
14
  from cartography.models.core.relationships import TargetNodeMatcher
13
15
 
14
16
 
@@ -135,6 +137,40 @@ class InspectorFindingToECRImageRel(CartographyRelSchema):
135
137
  )
136
138
 
137
139
 
140
+ @dataclass(frozen=True)
141
+ class InspectorFindingToPackageRelRelProperties(CartographyRelProperties):
142
+ lastupdated: PropertyRef = PropertyRef("lastupdated", set_in_kwargs=True)
143
+ _sub_resource_label: PropertyRef = PropertyRef(
144
+ "_sub_resource_label", set_in_kwargs=True
145
+ )
146
+ _sub_resource_id: PropertyRef = PropertyRef("_sub_resource_id", set_in_kwargs=True)
147
+ # The following properties live in vulnerablePackages from AWS API
148
+ # Adding them here to avoid multiple repetion of packages
149
+ filepath: PropertyRef = PropertyRef("filePath")
150
+ fixedinversion: PropertyRef = PropertyRef("fixedInVersion")
151
+ remediation: PropertyRef = PropertyRef("remediation")
152
+ sourcelayerhash: PropertyRef = PropertyRef("sourceLayerHash")
153
+ sourcelambdalayerarn: PropertyRef = PropertyRef("sourceLambdaLayerArn")
154
+
155
+
156
+ @dataclass(frozen=True)
157
+ # (:AWSInspectorFinding)-[:HAS]->(:AWSInspectorPackage)
158
+ class InspectorFindingToPackageMatchLink(CartographyRelSchema):
159
+ target_node_label: str = "AWSInspectorPackage"
160
+ target_node_matcher: TargetNodeMatcher = make_target_node_matcher(
161
+ {"id": PropertyRef("packageid")},
162
+ )
163
+ source_node_label: str = "AWSInspectorFinding"
164
+ source_node_matcher: SourceNodeMatcher = make_source_node_matcher(
165
+ {"id": PropertyRef("findingarn")},
166
+ )
167
+ properties: InspectorFindingToPackageRelRelProperties = (
168
+ InspectorFindingToPackageRelRelProperties()
169
+ )
170
+ direction: LinkDirection = LinkDirection.OUTWARD
171
+ rel_label: str = "HAS"
172
+
173
+
138
174
  @dataclass(frozen=True)
139
175
  class AWSInspectorFindingSchema(CartographyNodeSchema):
140
176
  label: str = "AWSInspectorFinding"
@@ -146,6 +182,7 @@ class AWSInspectorFindingSchema(CartographyNodeSchema):
146
182
  other_relationships: OtherRelationships = OtherRelationships(
147
183
  [
148
184
  InspectorFindingToEC2InstanceRel(),
185
+ # TODO: Fix ECRRepository and ECRImage relationships
149
186
  InspectorFindingToECRRepositoryRel(),
150
187
  InspectorFindingToECRImageRel(),
151
188
  InspectorFindingToAWSAccountRelDelegateRel(),
@@ -7,25 +7,18 @@ from cartography.models.core.relationships import CartographyRelProperties
7
7
  from cartography.models.core.relationships import CartographyRelSchema
8
8
  from cartography.models.core.relationships import LinkDirection
9
9
  from cartography.models.core.relationships import make_target_node_matcher
10
- from cartography.models.core.relationships import OtherRelationships
11
10
  from cartography.models.core.relationships import TargetNodeMatcher
12
11
 
13
12
 
14
13
  @dataclass(frozen=True)
15
14
  class AWSInspectorPackageNodeProperties(CartographyNodeProperties):
16
15
  id: PropertyRef = PropertyRef("id")
17
- region: PropertyRef = PropertyRef("Region", set_in_kwargs=True)
18
- awsaccount: PropertyRef = PropertyRef("AWS_ID", set_in_kwargs=True)
19
- findingarn: PropertyRef = PropertyRef("findingarn", extra_index=True)
20
16
  name: PropertyRef = PropertyRef("name", extra_index=True)
21
- arch: PropertyRef = PropertyRef("arch")
22
17
  version: PropertyRef = PropertyRef("version", extra_index=True)
23
18
  release: PropertyRef = PropertyRef("release", extra_index=True)
19
+ arch: PropertyRef = PropertyRef("arch")
24
20
  epoch: PropertyRef = PropertyRef("epoch")
25
21
  manager: PropertyRef = PropertyRef("packageManager")
26
- filepath: PropertyRef = PropertyRef("filePath")
27
- fixedinversion: PropertyRef = PropertyRef("fixedInVersion")
28
- sourcelayerhash: PropertyRef = PropertyRef("sourceLayerHash")
29
22
  lastupdated: PropertyRef = PropertyRef("lastupdated", set_in_kwargs=True)
30
23
 
31
24
 
@@ -47,24 +40,6 @@ class InspectorPackageToAWSAccountRel(CartographyRelSchema):
47
40
  )
48
41
 
49
42
 
50
- @dataclass(frozen=True)
51
- class InspectorPackageToFindingRelRelProperties(CartographyRelProperties):
52
- lastupdated: PropertyRef = PropertyRef("lastupdated", set_in_kwargs=True)
53
-
54
-
55
- @dataclass(frozen=True)
56
- class InspectorPackageToFindingRel(CartographyRelSchema):
57
- target_node_label: str = "AWSInspectorFinding"
58
- target_node_matcher: TargetNodeMatcher = make_target_node_matcher(
59
- {"id": PropertyRef("findingarn")},
60
- )
61
- direction: LinkDirection = LinkDirection.INWARD
62
- rel_label: str = "HAS"
63
- properties: InspectorPackageToFindingRelRelProperties = (
64
- InspectorPackageToFindingRelRelProperties()
65
- )
66
-
67
-
68
43
  @dataclass(frozen=True)
69
44
  class AWSInspectorPackageSchema(CartographyNodeSchema):
70
45
  label: str = "AWSInspectorPackage"
@@ -72,8 +47,3 @@ class AWSInspectorPackageSchema(CartographyNodeSchema):
72
47
  sub_resource_relationship: InspectorPackageToAWSAccountRel = (
73
48
  InspectorPackageToAWSAccountRel()
74
49
  )
75
- other_relationships: OtherRelationships = OtherRelationships(
76
- [
77
- InspectorPackageToFindingRel(),
78
- ],
79
- )
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cartography
3
- Version: 0.107.0rc1
3
+ Version: 0.107.0rc2
4
4
  Summary: Explore assets and their relationships across your technical infrastructure.
5
5
  Maintainer: Cartography Contributors
6
6
  License: apache2
@@ -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=p-Djna7oRUSPYcKo49GYVaSUJK3PW0h7Jw79Ngeb9Mo,525
3
+ cartography/_version.py,sha256=9t4xjY9Ix9CT_vuPkt5BMT5Cw71TXl8xuRRWDmRjqAg,525
4
4
  cartography/cli.py,sha256=e5F9239v_JoLR293JMZI1toYg43li2RX_F-qOHTB-HA,46054
5
5
  cartography/config.py,sha256=mM7Frg8maGB4a0Oad2nvktM38uC7zgrwSmofO5l4Aus,16492
6
6
  cartography/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -172,7 +172,7 @@ cartography/intel/aws/emr.py,sha256=EJoKjHQP7-F_A1trUNU05Sb42yNR1i0C9VIpGcCfAXw,
172
172
  cartography/intel/aws/iam.py,sha256=bkyIzWw2OC4MHxuoCvTiZ5eEGEQhz2asiUgY_tkX2GY,34322
173
173
  cartography/intel/aws/iam_instance_profiles.py,sha256=QUyu30xid60BFaemp-q0y9FgNsHaIQyQnQ8gHUzWC4k,2211
174
174
  cartography/intel/aws/identitycenter.py,sha256=C2EOfwQO1zBjePAXtreUcJIy7RU__ior3liRT4SpGO8,9544
175
- cartography/intel/aws/inspector.py,sha256=rD_O3DUGv5-GSMNqDzb11Ps5bX1sIo_JDq3UTAGvUpE,11168
175
+ cartography/intel/aws/inspector.py,sha256=G8a60uuFCuENvR2DNJ9VmWEJwG9UDENaC1buULvuSZc,12415
176
176
  cartography/intel/aws/kms.py,sha256=RtCxNG-Den-f4Il-NO3YL_-BFUmg1qFt4lNucue9SQM,12130
177
177
  cartography/intel/aws/lambda_function.py,sha256=cutCsMnvyJB8vKUP0fHORrhijw944cXSoLKOHYdi6SM,10389
178
178
  cartography/intel/aws/organizations.py,sha256=m5qk60N6pe7iKLN-Rtfg9aYv7OozoloSkcsuePd-RGs,4680
@@ -427,8 +427,8 @@ cartography/models/aws/identitycenter/awsidentitycenter.py,sha256=-ybcEgdZjwF0RI
427
427
  cartography/models/aws/identitycenter/awspermissionset.py,sha256=12kDKzsJQOHg6d9dlX98sM9gKXGMQh7FaxzlJov7Dgo,3651
428
428
  cartography/models/aws/identitycenter/awsssouser.py,sha256=EWnyX5ev2aaK64YjKGuJSoknBF5b_kS5xc0kDf_0xfo,2886
429
429
  cartography/models/aws/inspector/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
430
- cartography/models/aws/inspector/findings.py,sha256=z6fVygv8rmlYB1huX64jDgrCEjoTdLkoeKIVeoMk9wI,6469
431
- cartography/models/aws/inspector/packages.py,sha256=4TWu9EiS8aOR-n5z0FqG7564t-GKS4zrD4THX_2NKRo,3348
430
+ cartography/models/aws/inspector/findings.py,sha256=ikm0vvjhGK_-BDt5VGyS4_0KwJsq81T6VgROq9HK2NE,8188
431
+ cartography/models/aws/inspector/packages.py,sha256=IoJT7w6n8Vx3vGGJPWKDgJLRpioqtOS5iMYZLnX7thg,2113
432
432
  cartography/models/aws/s3/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
433
433
  cartography/models/aws/s3/account_public_access_block.py,sha256=L6AS0OncfSOWHP4pOXshnJFDPwnWqywzUIeUppJcw-Q,2256
434
434
  cartography/models/aws/s3/notification.py,sha256=SF1VvCP_2WVh8K29d4ms8MUcg9AyO_MN8vCgzLFlGAs,1017
@@ -542,9 +542,9 @@ cartography/models/trivy/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZ
542
542
  cartography/models/trivy/findings.py,sha256=SgI_h1aRyR20uAHvuXIZ1T6r4IZJt6SVhxRaF2bTsm0,3085
543
543
  cartography/models/trivy/fix.py,sha256=ho9ENVl9HSXqyggyCwR6ilkOBKDxpQ7rGibo_j21NA4,2587
544
544
  cartography/models/trivy/package.py,sha256=IwO1RZZ-MFRtNbt8Cq6YFl6fdNJMFmULnJkkK8Q4rL4,2809
545
- cartography-0.107.0rc1.dist-info/licenses/LICENSE,sha256=kvLEBRYaQ1RvUni6y7Ti9uHeooqnjPoo6n_-0JO1ETc,11351
546
- cartography-0.107.0rc1.dist-info/METADATA,sha256=4iitm8S4B9hie7yMMuR5tGdbOPOvBPqucuCHqXUXVnM,12861
547
- cartography-0.107.0rc1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
548
- cartography-0.107.0rc1.dist-info/entry_points.txt,sha256=GVIAWD0o0_K077qMA_k1oZU4v-M0a8GLKGJR8tZ-qH8,112
549
- cartography-0.107.0rc1.dist-info/top_level.txt,sha256=BHqsNJQiI6Q72DeypC1IINQJE59SLhU4nllbQjgJi9g,12
550
- cartography-0.107.0rc1.dist-info/RECORD,,
545
+ cartography-0.107.0rc2.dist-info/licenses/LICENSE,sha256=kvLEBRYaQ1RvUni6y7Ti9uHeooqnjPoo6n_-0JO1ETc,11351
546
+ cartography-0.107.0rc2.dist-info/METADATA,sha256=fE9Ro2jtKzFQVmrKpCA8YSn_oUzG-ds1qs0OQ6rGzpQ,12861
547
+ cartography-0.107.0rc2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
548
+ cartography-0.107.0rc2.dist-info/entry_points.txt,sha256=GVIAWD0o0_K077qMA_k1oZU4v-M0a8GLKGJR8tZ-qH8,112
549
+ cartography-0.107.0rc2.dist-info/top_level.txt,sha256=BHqsNJQiI6Q72DeypC1IINQJE59SLhU4nllbQjgJi9g,12
550
+ cartography-0.107.0rc2.dist-info/RECORD,,