cartography 0.102.0rc2__py3-none-any.whl → 0.103.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 (251) hide show
  1. cartography/__main__.py +1 -2
  2. cartography/_version.py +2 -2
  3. cartography/cli.py +302 -253
  4. cartography/client/core/tx.py +39 -18
  5. cartography/config.py +4 -0
  6. cartography/driftdetect/__main__.py +1 -2
  7. cartography/driftdetect/add_shortcut.py +10 -2
  8. cartography/driftdetect/cli.py +71 -75
  9. cartography/driftdetect/detect_deviations.py +7 -3
  10. cartography/driftdetect/get_states.py +20 -8
  11. cartography/driftdetect/model.py +5 -5
  12. cartography/driftdetect/serializers.py +8 -6
  13. cartography/driftdetect/storage.py +2 -2
  14. cartography/graph/cleanupbuilder.py +35 -15
  15. cartography/graph/job.py +46 -17
  16. cartography/graph/querybuilder.py +165 -80
  17. cartography/graph/statement.py +35 -26
  18. cartography/intel/analysis.py +4 -1
  19. cartography/intel/aws/__init__.py +114 -55
  20. cartography/intel/aws/apigateway.py +134 -63
  21. cartography/intel/aws/cloudtrail.py +127 -0
  22. cartography/intel/aws/config.py +56 -20
  23. cartography/intel/aws/dynamodb.py +108 -40
  24. cartography/intel/aws/ec2/__init__.py +2 -2
  25. cartography/intel/aws/ec2/auto_scaling_groups.py +181 -78
  26. cartography/intel/aws/ec2/elastic_ip_addresses.py +41 -13
  27. cartography/intel/aws/ec2/images.py +49 -20
  28. cartography/intel/aws/ec2/instances.py +234 -136
  29. cartography/intel/aws/ec2/internet_gateways.py +40 -11
  30. cartography/intel/aws/ec2/key_pairs.py +44 -20
  31. cartography/intel/aws/ec2/launch_templates.py +101 -59
  32. cartography/intel/aws/ec2/load_balancer_v2s.py +104 -39
  33. cartography/intel/aws/ec2/load_balancers.py +82 -42
  34. cartography/intel/aws/ec2/network_acls.py +89 -65
  35. cartography/intel/aws/ec2/network_interfaces.py +146 -87
  36. cartography/intel/aws/ec2/reserved_instances.py +45 -16
  37. cartography/intel/aws/ec2/route_tables.py +138 -98
  38. cartography/intel/aws/ec2/security_groups.py +71 -21
  39. cartography/intel/aws/ec2/snapshots.py +61 -22
  40. cartography/intel/aws/ec2/subnets.py +54 -18
  41. cartography/intel/aws/ec2/tgw.py +100 -34
  42. cartography/intel/aws/ec2/util.py +1 -1
  43. cartography/intel/aws/ec2/volumes.py +69 -41
  44. cartography/intel/aws/ec2/vpc.py +37 -12
  45. cartography/intel/aws/ec2/vpc_peerings.py +83 -24
  46. cartography/intel/aws/ecr.py +88 -32
  47. cartography/intel/aws/ecs.py +83 -47
  48. cartography/intel/aws/eks.py +55 -29
  49. cartography/intel/aws/elasticache.py +42 -18
  50. cartography/intel/aws/elasticsearch.py +57 -20
  51. cartography/intel/aws/emr.py +61 -23
  52. cartography/intel/aws/iam.py +401 -145
  53. cartography/intel/aws/iam_instance_profiles.py +22 -22
  54. cartography/intel/aws/identitycenter.py +71 -37
  55. cartography/intel/aws/inspector.py +159 -89
  56. cartography/intel/aws/kms.py +92 -38
  57. cartography/intel/aws/lambda_function.py +103 -34
  58. cartography/intel/aws/organizations.py +30 -10
  59. cartography/intel/aws/permission_relationships.py +133 -51
  60. cartography/intel/aws/rds.py +249 -85
  61. cartography/intel/aws/redshift.py +107 -46
  62. cartography/intel/aws/resourcegroupstaggingapi.py +120 -66
  63. cartography/intel/aws/resources.py +53 -46
  64. cartography/intel/aws/route53.py +108 -61
  65. cartography/intel/aws/s3.py +168 -83
  66. cartography/intel/aws/s3accountpublicaccessblock.py +157 -0
  67. cartography/intel/aws/secretsmanager.py +24 -12
  68. cartography/intel/aws/securityhub.py +20 -9
  69. cartography/intel/aws/sns.py +166 -0
  70. cartography/intel/aws/sqs.py +60 -28
  71. cartography/intel/aws/ssm.py +70 -30
  72. cartography/intel/aws/util/arns.py +7 -7
  73. cartography/intel/aws/util/common.py +31 -4
  74. cartography/intel/azure/__init__.py +78 -19
  75. cartography/intel/azure/compute.py +101 -27
  76. cartography/intel/azure/cosmosdb.py +496 -170
  77. cartography/intel/azure/sql.py +296 -105
  78. cartography/intel/azure/storage.py +322 -113
  79. cartography/intel/azure/subscription.py +39 -23
  80. cartography/intel/azure/tenant.py +13 -4
  81. cartography/intel/azure/util/credentials.py +95 -55
  82. cartography/intel/bigfix/__init__.py +2 -2
  83. cartography/intel/bigfix/computers.py +93 -65
  84. cartography/intel/create_indexes.py +3 -2
  85. cartography/intel/crowdstrike/__init__.py +11 -9
  86. cartography/intel/crowdstrike/endpoints.py +5 -1
  87. cartography/intel/crowdstrike/spotlight.py +8 -3
  88. cartography/intel/cve/__init__.py +46 -13
  89. cartography/intel/cve/feed.py +48 -12
  90. cartography/intel/digitalocean/__init__.py +22 -13
  91. cartography/intel/digitalocean/compute.py +75 -108
  92. cartography/intel/digitalocean/management.py +44 -80
  93. cartography/intel/digitalocean/platform.py +48 -43
  94. cartography/intel/dns.py +36 -10
  95. cartography/intel/duo/__init__.py +21 -16
  96. cartography/intel/duo/api_host.py +14 -9
  97. cartography/intel/duo/endpoints.py +50 -45
  98. cartography/intel/duo/groups.py +18 -14
  99. cartography/intel/duo/phones.py +37 -34
  100. cartography/intel/duo/tokens.py +26 -23
  101. cartography/intel/duo/users.py +54 -50
  102. cartography/intel/duo/web_authn_credentials.py +30 -25
  103. cartography/intel/entra/__init__.py +25 -7
  104. cartography/intel/entra/ou.py +112 -0
  105. cartography/intel/entra/users.py +69 -63
  106. cartography/intel/gcp/__init__.py +185 -49
  107. cartography/intel/gcp/compute.py +418 -231
  108. cartography/intel/gcp/crm.py +96 -43
  109. cartography/intel/gcp/dns.py +60 -19
  110. cartography/intel/gcp/gke.py +72 -38
  111. cartography/intel/gcp/iam.py +61 -41
  112. cartography/intel/gcp/storage.py +84 -55
  113. cartography/intel/github/__init__.py +13 -11
  114. cartography/intel/github/repos.py +270 -137
  115. cartography/intel/github/teams.py +170 -88
  116. cartography/intel/github/users.py +70 -39
  117. cartography/intel/github/util.py +36 -34
  118. cartography/intel/gsuite/__init__.py +47 -26
  119. cartography/intel/gsuite/api.py +73 -30
  120. cartography/intel/jamf/__init__.py +19 -1
  121. cartography/intel/jamf/computers.py +30 -7
  122. cartography/intel/jamf/util.py +7 -2
  123. cartography/intel/kandji/__init__.py +6 -3
  124. cartography/intel/kandji/devices.py +14 -8
  125. cartography/intel/kubernetes/namespaces.py +7 -4
  126. cartography/intel/kubernetes/pods.py +7 -4
  127. cartography/intel/kubernetes/services.py +8 -4
  128. cartography/intel/lastpass/__init__.py +2 -2
  129. cartography/intel/lastpass/users.py +23 -12
  130. cartography/intel/oci/__init__.py +44 -11
  131. cartography/intel/oci/iam.py +134 -38
  132. cartography/intel/oci/organizations.py +13 -6
  133. cartography/intel/oci/utils.py +43 -20
  134. cartography/intel/okta/__init__.py +66 -15
  135. cartography/intel/okta/applications.py +42 -20
  136. cartography/intel/okta/awssaml.py +93 -33
  137. cartography/intel/okta/factors.py +16 -4
  138. cartography/intel/okta/groups.py +56 -29
  139. cartography/intel/okta/organization.py +5 -1
  140. cartography/intel/okta/origins.py +6 -2
  141. cartography/intel/okta/roles.py +15 -5
  142. cartography/intel/okta/users.py +20 -8
  143. cartography/intel/okta/utils.py +6 -4
  144. cartography/intel/pagerduty/__init__.py +8 -7
  145. cartography/intel/pagerduty/escalation_policies.py +18 -6
  146. cartography/intel/pagerduty/schedules.py +12 -4
  147. cartography/intel/pagerduty/services.py +11 -4
  148. cartography/intel/pagerduty/teams.py +8 -3
  149. cartography/intel/pagerduty/users.py +3 -1
  150. cartography/intel/pagerduty/vendors.py +3 -1
  151. cartography/intel/semgrep/__init__.py +24 -6
  152. cartography/intel/semgrep/dependencies.py +50 -28
  153. cartography/intel/semgrep/deployment.py +3 -1
  154. cartography/intel/semgrep/findings.py +42 -18
  155. cartography/intel/snipeit/__init__.py +17 -3
  156. cartography/intel/snipeit/asset.py +12 -6
  157. cartography/intel/snipeit/user.py +8 -5
  158. cartography/intel/snipeit/util.py +9 -4
  159. cartography/models/aws/apigateway.py +21 -17
  160. cartography/models/aws/apigatewaycertificate.py +28 -22
  161. cartography/models/aws/apigatewayresource.py +28 -20
  162. cartography/models/aws/apigatewaystage.py +33 -25
  163. cartography/models/aws/cloudtrail/__init__.py +0 -0
  164. cartography/models/aws/cloudtrail/trail.py +61 -0
  165. cartography/models/aws/dynamodb/gsi.py +30 -22
  166. cartography/models/aws/dynamodb/tables.py +25 -17
  167. cartography/models/aws/ec2/auto_scaling_groups.py +102 -82
  168. cartography/models/aws/ec2/images.py +36 -34
  169. cartography/models/aws/ec2/instances.py +51 -45
  170. cartography/models/aws/ec2/keypair.py +21 -16
  171. cartography/models/aws/ec2/keypair_instance.py +28 -21
  172. cartography/models/aws/ec2/launch_configurations.py +30 -26
  173. cartography/models/aws/ec2/launch_template_versions.py +48 -38
  174. cartography/models/aws/ec2/launch_templates.py +21 -17
  175. cartography/models/aws/ec2/load_balancer_listeners.py +27 -23
  176. cartography/models/aws/ec2/load_balancers.py +47 -37
  177. cartography/models/aws/ec2/network_acl_rules.py +38 -30
  178. cartography/models/aws/ec2/network_acls.py +38 -29
  179. cartography/models/aws/ec2/networkinterface_instance.py +52 -39
  180. cartography/models/aws/ec2/networkinterfaces.py +53 -37
  181. cartography/models/aws/ec2/privateip_networkinterface.py +32 -22
  182. cartography/models/aws/ec2/reservations.py +18 -14
  183. cartography/models/aws/ec2/route_table_associations.py +44 -34
  184. cartography/models/aws/ec2/route_tables.py +50 -43
  185. cartography/models/aws/ec2/routes.py +45 -37
  186. cartography/models/aws/ec2/securitygroup_instance.py +29 -20
  187. cartography/models/aws/ec2/securitygroup_networkinterface.py +24 -15
  188. cartography/models/aws/ec2/subnet_instance.py +24 -19
  189. cartography/models/aws/ec2/subnet_networkinterface.py +40 -31
  190. cartography/models/aws/ec2/volumes.py +47 -40
  191. cartography/models/aws/eks/clusters.py +23 -21
  192. cartography/models/aws/emr.py +32 -30
  193. cartography/models/aws/iam/instanceprofile.py +33 -24
  194. cartography/models/aws/identitycenter/awsidentitycenter.py +18 -14
  195. cartography/models/aws/identitycenter/awspermissionset.py +37 -29
  196. cartography/models/aws/identitycenter/awsssouser.py +23 -21
  197. cartography/models/aws/inspector/findings.py +77 -65
  198. cartography/models/aws/inspector/packages.py +35 -29
  199. cartography/models/aws/s3/__init__.py +0 -0
  200. cartography/models/aws/s3/account_public_access_block.py +51 -0
  201. cartography/models/aws/sns/__init__.py +0 -0
  202. cartography/models/aws/sns/topic.py +50 -0
  203. cartography/models/aws/ssm/instance_information.py +51 -39
  204. cartography/models/aws/ssm/instance_patch.py +32 -26
  205. cartography/models/bigfix/bigfix_computer.py +42 -38
  206. cartography/models/bigfix/bigfix_root.py +3 -3
  207. cartography/models/core/common.py +12 -10
  208. cartography/models/core/nodes.py +5 -2
  209. cartography/models/core/relationships.py +14 -6
  210. cartography/models/crowdstrike/hosts.py +37 -35
  211. cartography/models/cve/cve.py +34 -32
  212. cartography/models/cve/cve_feed.py +6 -6
  213. cartography/models/digitalocean/__init__.py +0 -0
  214. cartography/models/digitalocean/account.py +21 -0
  215. cartography/models/digitalocean/droplet.py +56 -0
  216. cartography/models/digitalocean/project.py +48 -0
  217. cartography/models/duo/api_host.py +3 -3
  218. cartography/models/duo/endpoint.py +43 -41
  219. cartography/models/duo/group.py +14 -14
  220. cartography/models/duo/phone.py +27 -27
  221. cartography/models/duo/token.py +16 -16
  222. cartography/models/duo/user.py +46 -44
  223. cartography/models/duo/web_authn_credential.py +27 -19
  224. cartography/models/entra/ou.py +48 -0
  225. cartography/models/entra/tenant.py +24 -18
  226. cartography/models/entra/user.py +64 -48
  227. cartography/models/gcp/iam.py +23 -23
  228. cartography/models/github/orgs.py +5 -4
  229. cartography/models/github/teams.py +37 -31
  230. cartography/models/github/users.py +34 -23
  231. cartography/models/kandji/device.py +22 -16
  232. cartography/models/kandji/tenant.py +6 -4
  233. cartography/models/lastpass/tenant.py +3 -3
  234. cartography/models/lastpass/user.py +32 -28
  235. cartography/models/semgrep/dependencies.py +36 -24
  236. cartography/models/semgrep/deployment.py +5 -5
  237. cartography/models/semgrep/findings.py +58 -42
  238. cartography/models/semgrep/locations.py +27 -21
  239. cartography/models/snipeit/asset.py +30 -21
  240. cartography/models/snipeit/tenant.py +6 -4
  241. cartography/models/snipeit/user.py +19 -12
  242. cartography/stats.py +3 -3
  243. cartography/sync.py +107 -31
  244. cartography/util.py +84 -62
  245. {cartography-0.102.0rc2.dist-info → cartography-0.103.0rc1.dist-info}/METADATA +3 -14
  246. cartography-0.103.0rc1.dist-info/RECORD +396 -0
  247. {cartography-0.102.0rc2.dist-info → cartography-0.103.0rc1.dist-info}/WHEEL +1 -1
  248. cartography-0.102.0rc2.dist-info/RECORD +0 -381
  249. {cartography-0.102.0rc2.dist-info → cartography-0.103.0rc1.dist-info}/entry_points.txt +0 -0
  250. {cartography-0.102.0rc2.dist-info → cartography-0.103.0rc1.dist-info}/licenses/LICENSE +0 -0
  251. {cartography-0.102.0rc2.dist-info → cartography-0.103.0rc1.dist-info}/top_level.txt +0 -0
@@ -54,11 +54,18 @@ def get_sca_vulns(semgrep_app_token: str, deployment_slug: str) -> List[Dict[str
54
54
  while has_more:
55
55
 
56
56
  try:
57
- response = requests.get(sca_url, params=request_data, headers=headers, timeout=_TIMEOUT)
57
+ response = requests.get(
58
+ sca_url,
59
+ params=request_data,
60
+ headers=headers,
61
+ timeout=_TIMEOUT,
62
+ )
58
63
  response.raise_for_status()
59
64
  data = response.json()
60
65
  except (ReadTimeout, HTTPError):
61
- logger.warning(f"Failed to retrieve Semgrep SCA vulns for page {page}. Retrying...")
66
+ logger.warning(
67
+ f"Failed to retrieve Semgrep SCA vulns for page {page}. Retrying...",
68
+ )
62
69
  retries += 1
63
70
  if retries >= _MAX_RETRIES:
64
71
  raise
@@ -104,14 +111,16 @@ def _determine_exposure(vuln: Dict[str, Any]) -> str | None:
104
111
 
105
112
 
106
113
  def _build_vuln_url(vuln: str) -> str | None:
107
- if 'CVE' in vuln:
114
+ if "CVE" in vuln:
108
115
  return f"https://nvd.nist.gov/vuln/detail/{vuln}"
109
- if 'GHSA' in vuln:
116
+ if "GHSA" in vuln:
110
117
  return f"https://github.com/advisories/{vuln}"
111
118
  return None
112
119
 
113
120
 
114
- def transform_sca_vulns(raw_vulns: List[Dict[str, Any]]) -> Tuple[List[Dict[str, Any]], List[Dict[str, str]]]:
121
+ def transform_sca_vulns(
122
+ raw_vulns: List[Dict[str, Any]],
123
+ ) -> Tuple[List[Dict[str, Any]], List[Dict[str, str]]]:
115
124
  """
116
125
  Transforms the raw SCA vulns response from Semgrep API into a list of dicts
117
126
  that can be used to create the SemgrepSCAFinding nodes.
@@ -124,7 +133,7 @@ def transform_sca_vulns(raw_vulns: List[Dict[str, Any]]) -> Tuple[List[Dict[str,
124
133
  repository_name = vuln["repository"]["name"]
125
134
  rule_id = vuln["rule"]["name"]
126
135
  vulnerability_class = _get_vuln_class(vuln)
127
- package = vuln['found_dependency']['package']
136
+ package = vuln["found_dependency"]["package"]
128
137
  sca_vuln["id"] = vuln["id"]
129
138
  sca_vuln["repositoryName"] = repository_name
130
139
  sca_vuln["branch"] = vuln["ref"]
@@ -133,9 +142,15 @@ def transform_sca_vulns(raw_vulns: List[Dict[str, Any]]) -> Tuple[List[Dict[str,
133
142
  sca_vuln["description"] = vuln["rule"]["message"]
134
143
  sca_vuln["ecosystem"] = vuln["found_dependency"]["ecosystem"]
135
144
  sca_vuln["severity"] = vuln["severity"].upper()
136
- sca_vuln["reachability"] = vuln["reachability"].upper() # Check done to determine rechabilitity
137
- sca_vuln["reachableIf"] = vuln["reachable_condition"].upper() if vuln["reachable_condition"] else None
138
- sca_vuln["exposureType"] = _determine_exposure(vuln) # Determintes if reachable or unreachable
145
+ sca_vuln["reachability"] = vuln[
146
+ "reachability"
147
+ ].upper() # Check done to determine rechabilitity
148
+ sca_vuln["reachableIf"] = (
149
+ vuln["reachable_condition"].upper() if vuln["reachable_condition"] else None
150
+ )
151
+ sca_vuln["exposureType"] = _determine_exposure(
152
+ vuln,
153
+ ) # Determintes if reachable or unreachable
139
154
  dependency = f"{package}|{vuln['found_dependency']['version']}"
140
155
  sca_vuln["matchedDependency"] = dependency
141
156
  dep_url = vuln["found_dependency"]["lockfile_line_url"]
@@ -145,14 +160,16 @@ def transform_sca_vulns(raw_vulns: List[Dict[str, Any]]) -> Tuple[List[Dict[str,
145
160
  sca_vuln["dependencyFileLocation_url"] = dep_url
146
161
  else:
147
162
  if sca_vuln.get("location"):
148
- sca_vuln["dependencyFileLocation_path"] = sca_vuln["location"]["file_path"]
163
+ sca_vuln["dependencyFileLocation_path"] = sca_vuln["location"][
164
+ "file_path"
165
+ ]
149
166
  sca_vuln["transitivity"] = vuln["found_dependency"]["transitivity"].upper()
150
167
  if vuln.get("vulnerability_identifier"):
151
168
  vuln_id = vuln["vulnerability_identifier"].upper()
152
169
  sca_vuln["cveId"] = vuln_id
153
170
  sca_vuln["ref_urls"] = [_build_vuln_url(vuln_id)]
154
- if vuln.get('fix_recommendations') and len(vuln['fix_recommendations']) > 0:
155
- fix = vuln['fix_recommendations'][0]
171
+ if vuln.get("fix_recommendations") and len(vuln["fix_recommendations"]) > 0:
172
+ fix = vuln["fix_recommendations"][0]
156
173
  dep_fix = f"{fix['package']}|{fix['version']}"
157
174
  sca_vuln["closestSafeDependency"] = dep_fix
158
175
  sca_vuln["openedAt"] = vuln["created_at"]
@@ -213,16 +230,19 @@ def load_semgrep_sca_usages(
213
230
 
214
231
  @timeit
215
232
  def cleanup(
216
- neo4j_session: neo4j.Session, common_job_parameters: Dict[str, Any],
233
+ neo4j_session: neo4j.Session,
234
+ common_job_parameters: Dict[str, Any],
217
235
  ) -> None:
218
236
  logger.info("Running Semgrep SCA findings cleanup job.")
219
237
  findings_cleanup_job = GraphJob.from_node_schema(
220
- SemgrepSCAFindingSchema(), common_job_parameters,
238
+ SemgrepSCAFindingSchema(),
239
+ common_job_parameters,
221
240
  )
222
241
  findings_cleanup_job.run(neo4j_session)
223
242
  logger.info("Running Semgrep SCA Locations cleanup job.")
224
243
  locations_cleanup_job = GraphJob.from_node_schema(
225
- SemgrepSCALocationSchema(), common_job_parameters,
244
+ SemgrepSCALocationSchema(),
245
+ common_job_parameters,
226
246
  )
227
247
  locations_cleanup_job.run(neo4j_session)
228
248
 
@@ -249,14 +269,18 @@ def sync_findings(
249
269
  vulns, usages = transform_sca_vulns(raw_vulns)
250
270
  load_semgrep_sca_vulns(neo4j_session, vulns, deployment_id, update_tag)
251
271
  load_semgrep_sca_usages(neo4j_session, usages, deployment_id, update_tag)
252
- run_scoped_analysis_job('semgrep_sca_risk_analysis.json', neo4j_session, common_job_parameters)
272
+ run_scoped_analysis_job(
273
+ "semgrep_sca_risk_analysis.json",
274
+ neo4j_session,
275
+ common_job_parameters,
276
+ )
253
277
 
254
278
  cleanup(neo4j_session, common_job_parameters)
255
279
  merge_module_sync_metadata(
256
280
  neo4j_session=neo4j_session,
257
- group_type='Semgrep',
281
+ group_type="Semgrep",
258
282
  group_id=deployment_id,
259
- synced_type='SCA',
283
+ synced_type="SCA",
260
284
  update_tag=update_tag,
261
285
  stat_handler=stat_handler,
262
286
  )
@@ -14,7 +14,11 @@ stat_handler = get_stats_client(__name__)
14
14
 
15
15
  @timeit
16
16
  def start_snipeit_ingestion(neo4j_session: neo4j.Session, config: Config) -> None:
17
- if config.snipeit_base_uri is None or config.snipeit_token is None or config.snipeit_tenant_id is None:
17
+ if (
18
+ config.snipeit_base_uri is None
19
+ or config.snipeit_token is None
20
+ or config.snipeit_tenant_id is None
21
+ ):
18
22
  logger.warning(
19
23
  "Required parameter(s) missing. Skipping sync.",
20
24
  )
@@ -26,5 +30,15 @@ def start_snipeit_ingestion(neo4j_session: neo4j.Session, config: Config) -> Non
26
30
  }
27
31
 
28
32
  # Ingest SnipeIT users and assets
29
- user.sync(neo4j_session, common_job_parameters, config.snipeit_base_uri, config.snipeit_token)
30
- asset.sync(neo4j_session, common_job_parameters, config.snipeit_base_uri, config.snipeit_token)
33
+ user.sync(
34
+ neo4j_session,
35
+ common_job_parameters,
36
+ config.snipeit_base_uri,
37
+ config.snipeit_token,
38
+ )
39
+ asset.sync(
40
+ neo4j_session,
41
+ common_job_parameters,
42
+ config.snipeit_base_uri,
43
+ config.snipeit_token,
44
+ )
@@ -5,13 +5,13 @@ from typing import List
5
5
 
6
6
  import neo4j
7
7
 
8
- from .util import call_snipeit_api
9
8
  from cartography.client.core.tx import load
10
9
  from cartography.graph.job import GraphJob
11
10
  from cartography.models.snipeit.asset import SnipeitAssetSchema
12
11
  from cartography.models.snipeit.tenant import SnipeitTenantSchema
13
12
  from cartography.util import timeit
14
13
 
14
+ from .util import call_snipeit_api
15
15
 
16
16
  logger = logging.getLogger(__name__)
17
17
 
@@ -24,9 +24,9 @@ def get(base_uri: str, token: str) -> List[Dict]:
24
24
  offset = len(results)
25
25
  api_endpoint = f"{api_endpoint}?order='asc'&offset={offset}"
26
26
  response = call_snipeit_api(api_endpoint, base_uri, token)
27
- results.extend(response['rows'])
27
+ results.extend(response["rows"])
28
28
 
29
- total = response['total']
29
+ total = response["total"]
30
30
  results_count = len(results)
31
31
  if results_count >= total:
32
32
  break
@@ -44,7 +44,7 @@ def load_assets(
44
44
  load(
45
45
  neo4j_session,
46
46
  SnipeitTenantSchema(),
47
- [{'id': common_job_parameters["TENANT_ID"]}],
47
+ [{"id": common_job_parameters["TENANT_ID"]}],
48
48
  lastupdated=common_job_parameters["UPDATE_TAG"],
49
49
  )
50
50
 
@@ -59,7 +59,9 @@ def load_assets(
59
59
 
60
60
  @timeit
61
61
  def cleanup(neo4j_session: neo4j.Session, common_job_parameters: Dict) -> None:
62
- GraphJob.from_node_schema(SnipeitAssetSchema(), common_job_parameters).run(neo4j_session)
62
+ GraphJob.from_node_schema(SnipeitAssetSchema(), common_job_parameters).run(
63
+ neo4j_session,
64
+ )
63
65
 
64
66
 
65
67
  @timeit
@@ -70,5 +72,9 @@ def sync(
70
72
  token: str,
71
73
  ) -> None:
72
74
  assets = get(base_uri=base_uri, token=token)
73
- load_assets(neo4j_session=neo4j_session, common_job_parameters=common_job_parameters, data=assets)
75
+ load_assets(
76
+ neo4j_session=neo4j_session,
77
+ common_job_parameters=common_job_parameters,
78
+ data=assets,
79
+ )
74
80
  cleanup(neo4j_session, common_job_parameters)
@@ -5,13 +5,14 @@ from typing import List
5
5
 
6
6
  import neo4j
7
7
 
8
- from .util import call_snipeit_api
9
8
  from cartography.client.core.tx import load
10
9
  from cartography.graph.job import GraphJob
11
10
  from cartography.models.snipeit.tenant import SnipeitTenantSchema
12
11
  from cartography.models.snipeit.user import SnipeitUserSchema
13
12
  from cartography.util import timeit
14
13
 
14
+ from .util import call_snipeit_api
15
+
15
16
  logger = logging.getLogger(__name__)
16
17
 
17
18
 
@@ -23,9 +24,9 @@ def get(base_uri: str, token: str) -> List[Dict]:
23
24
  offset = len(results)
24
25
  api_endpoint = f"{api_endpoint}?order='asc'&offset={offset}"
25
26
  response = call_snipeit_api(api_endpoint, base_uri, token)
26
- results.extend(response['rows'])
27
+ results.extend(response["rows"])
27
28
 
28
- total = response['total']
29
+ total = response["total"]
29
30
  results_count = len(results)
30
31
  if results_count >= total:
31
32
  break
@@ -45,7 +46,7 @@ def load_users(
45
46
  load(
46
47
  neo4j_session,
47
48
  SnipeitTenantSchema(),
48
- [{'id': common_job_parameters["TENANT_ID"]}],
49
+ [{"id": common_job_parameters["TENANT_ID"]}],
49
50
  lastupdated=common_job_parameters["UPDATE_TAG"],
50
51
  )
51
52
 
@@ -60,7 +61,9 @@ def load_users(
60
61
 
61
62
  @timeit
62
63
  def cleanup(neo4j_session: neo4j.Session, common_job_parameters: Dict) -> None:
63
- GraphJob.from_node_schema(SnipeitUserSchema(), common_job_parameters).run(neo4j_session)
64
+ GraphJob.from_node_schema(SnipeitUserSchema(), common_job_parameters).run(
65
+ neo4j_session,
66
+ )
64
67
 
65
68
 
66
69
  @timeit
@@ -12,17 +12,22 @@ _TIMEOUT = (60, 60)
12
12
 
13
13
 
14
14
  @timeit
15
- def call_snipeit_api(api_and_parameters: str, base_uri: str, token: str) -> Dict[str, Any]:
15
+ def call_snipeit_api(
16
+ api_and_parameters: str,
17
+ base_uri: str,
18
+ token: str,
19
+ ) -> Dict[str, Any]:
16
20
  uri = base_uri + api_and_parameters
17
21
  try:
18
22
  logger.debug(
19
- "SnipeIT: Get %s", uri,
23
+ "SnipeIT: Get %s",
24
+ uri,
20
25
  )
21
26
  response = requests.get(
22
27
  uri,
23
28
  headers={
24
- 'Accept': 'application/json',
25
- 'Authorization': f'Bearer {token}',
29
+ "Accept": "application/json",
30
+ "Authorization": f"Bearer {token}",
26
31
  },
27
32
  timeout=_TIMEOUT,
28
33
  )
@@ -12,36 +12,40 @@ from cartography.models.core.relationships import TargetNodeMatcher
12
12
 
13
13
  @dataclass(frozen=True)
14
14
  class APIGatewayRestAPINodeProperties(CartographyNodeProperties):
15
- id: PropertyRef = PropertyRef('id', extra_index=True)
16
- createddate: PropertyRef = PropertyRef('createdDate')
17
- version: PropertyRef = PropertyRef('version')
18
- minimumcompressionsize: PropertyRef = PropertyRef('minimumCompressionSize')
19
- disableexecuteapiendpoint: PropertyRef = PropertyRef('disableExecuteApiEndpoint')
20
- region: PropertyRef = PropertyRef('region', set_in_kwargs=True)
21
- lastupdated: PropertyRef = PropertyRef('lastupdated', set_in_kwargs=True)
22
- anonymous_access: PropertyRef = PropertyRef('anonymous_access')
23
- anonymous_actions: PropertyRef = PropertyRef('anonymous_actions')
15
+ id: PropertyRef = PropertyRef("id", extra_index=True)
16
+ createddate: PropertyRef = PropertyRef("createdDate")
17
+ version: PropertyRef = PropertyRef("version")
18
+ minimumcompressionsize: PropertyRef = PropertyRef("minimumCompressionSize")
19
+ disableexecuteapiendpoint: PropertyRef = PropertyRef("disableExecuteApiEndpoint")
20
+ region: PropertyRef = PropertyRef("region", set_in_kwargs=True)
21
+ lastupdated: PropertyRef = PropertyRef("lastupdated", set_in_kwargs=True)
22
+ anonymous_access: PropertyRef = PropertyRef("anonymous_access")
23
+ anonymous_actions: PropertyRef = PropertyRef("anonymous_actions")
24
24
 
25
25
 
26
26
  @dataclass(frozen=True)
27
- class APIGatewayRestAPIToAwsAccountRelProperties(CartographyRelProperties):
28
- lastupdated: PropertyRef = PropertyRef('lastupdated', set_in_kwargs=True)
27
+ class APIGatewayRestAPIToAWSAccountRelRelProperties(CartographyRelProperties):
28
+ lastupdated: PropertyRef = PropertyRef("lastupdated", set_in_kwargs=True)
29
29
 
30
30
 
31
31
  @dataclass(frozen=True)
32
32
  # (:APIGatewayRestAPI)<-[:RESOURCE]-(:AWSAccount)
33
- class APIGatewayRestAPIToAWSAccount(CartographyRelSchema):
34
- target_node_label: str = 'AWSAccount'
33
+ class APIGatewayRestAPIToAWSAccountRel(CartographyRelSchema):
34
+ target_node_label: str = "AWSAccount"
35
35
  target_node_matcher: TargetNodeMatcher = make_target_node_matcher(
36
- {'id': PropertyRef('AWS_ID', set_in_kwargs=True)},
36
+ {"id": PropertyRef("AWS_ID", set_in_kwargs=True)},
37
37
  )
38
38
  direction: LinkDirection = LinkDirection.INWARD
39
39
  rel_label: str = "RESOURCE"
40
- properties: APIGatewayRestAPIToAwsAccountRelProperties = APIGatewayRestAPIToAwsAccountRelProperties()
40
+ properties: APIGatewayRestAPIToAWSAccountRelRelProperties = (
41
+ APIGatewayRestAPIToAWSAccountRelRelProperties()
42
+ )
41
43
 
42
44
 
43
45
  @dataclass(frozen=True)
44
46
  class APIGatewayRestAPISchema(CartographyNodeSchema):
45
- label: str = 'APIGatewayRestAPI'
47
+ label: str = "APIGatewayRestAPI"
46
48
  properties: APIGatewayRestAPINodeProperties = APIGatewayRestAPINodeProperties()
47
- sub_resource_relationship: APIGatewayRestAPIToAWSAccount = APIGatewayRestAPIToAWSAccount()
49
+ sub_resource_relationship: APIGatewayRestAPIToAWSAccountRel = (
50
+ APIGatewayRestAPIToAWSAccountRel()
51
+ )
@@ -13,54 +13,60 @@ from cartography.models.core.relationships import TargetNodeMatcher
13
13
 
14
14
  @dataclass(frozen=True)
15
15
  class APIGatewayClientCertificateNodeProperties(CartographyNodeProperties):
16
- id: PropertyRef = PropertyRef('clientCertificateId')
17
- createddate: PropertyRef = PropertyRef('createdDate')
18
- expirationdate: PropertyRef = PropertyRef('expirationDate')
19
- lastupdated: PropertyRef = PropertyRef('lastupdated', set_in_kwargs=True)
16
+ id: PropertyRef = PropertyRef("clientCertificateId")
17
+ createddate: PropertyRef = PropertyRef("createdDate")
18
+ expirationdate: PropertyRef = PropertyRef("expirationDate")
19
+ lastupdated: PropertyRef = PropertyRef("lastupdated", set_in_kwargs=True)
20
20
 
21
21
 
22
22
  @dataclass(frozen=True)
23
- class APIGatewayClientCertificateToStageRelProperties(CartographyRelProperties):
24
- lastupdated: PropertyRef = PropertyRef('lastupdated', set_in_kwargs=True)
23
+ class APIGatewayClientCertificateToStageRelRelProperties(CartographyRelProperties):
24
+ lastupdated: PropertyRef = PropertyRef("lastupdated", set_in_kwargs=True)
25
25
 
26
26
 
27
27
  @dataclass(frozen=True)
28
- class CertToStageRelProps(CartographyRelProperties):
29
- lastupdated: PropertyRef = PropertyRef('lastupdated', set_in_kwargs=True)
28
+ class CertToStageRelProperties(CartographyRelProperties):
29
+ lastupdated: PropertyRef = PropertyRef("lastupdated", set_in_kwargs=True)
30
30
 
31
31
 
32
32
  @dataclass(frozen=True)
33
33
  # (:APIGatewayStage)-[:HAS_CERTIFICATE]->(:APIGatewayClientCertificate)
34
- class APIGatewayClientCertificateToStage(CartographyRelSchema):
35
- target_node_label: str = 'APIGatewayStage'
34
+ class APIGatewayClientCertificateToStageRel(CartographyRelSchema):
35
+ target_node_label: str = "APIGatewayStage"
36
36
  target_node_matcher: TargetNodeMatcher = make_target_node_matcher(
37
- {'id': PropertyRef('stageArn')},
37
+ {"id": PropertyRef("stageArn")},
38
38
  )
39
39
  direction: LinkDirection = LinkDirection.INWARD
40
40
  rel_label: str = "HAS_CERTIFICATE"
41
- properties: CertToStageRelProps = CertToStageRelProps()
41
+ properties: CertToStageRelProperties = CertToStageRelProperties()
42
42
 
43
43
 
44
44
  @dataclass(frozen=True)
45
- class CertToAccountRelProps(CartographyRelProperties):
46
- lastupdated: PropertyRef = PropertyRef('lastupdated', set_in_kwargs=True)
45
+ class CertToAccountRelProperties(CartographyRelProperties):
46
+ lastupdated: PropertyRef = PropertyRef("lastupdated", set_in_kwargs=True)
47
47
 
48
48
 
49
49
  @dataclass(frozen=True)
50
50
  # (:APIGatewayClientCertificate)<-[:RESOURCE]-(:AWSAccount)
51
- class APIGatewayClientCertificateToAWSAccount(CartographyRelSchema):
52
- target_node_label: str = 'AWSAccount'
51
+ class APIGatewayClientCertificateToAWSAccountRel(CartographyRelSchema):
52
+ target_node_label: str = "AWSAccount"
53
53
  target_node_matcher: TargetNodeMatcher = make_target_node_matcher(
54
- {'id': PropertyRef('AWS_ID', set_in_kwargs=True)},
54
+ {"id": PropertyRef("AWS_ID", set_in_kwargs=True)},
55
55
  )
56
56
  direction: LinkDirection = LinkDirection.INWARD
57
57
  rel_label: str = "RESOURCE"
58
- properties: CertToAccountRelProps = CertToAccountRelProps()
58
+ properties: CertToAccountRelProperties = CertToAccountRelProperties()
59
59
 
60
60
 
61
61
  @dataclass(frozen=True)
62
62
  class APIGatewayClientCertificateSchema(CartographyNodeSchema):
63
- label: str = 'APIGatewayClientCertificate'
64
- properties: APIGatewayClientCertificateNodeProperties = APIGatewayClientCertificateNodeProperties()
65
- sub_resource_relationship: APIGatewayClientCertificateToAWSAccount = APIGatewayClientCertificateToAWSAccount()
66
- other_relationships: OtherRelationships = OtherRelationships([APIGatewayClientCertificateToStage()])
63
+ label: str = "APIGatewayClientCertificate"
64
+ properties: APIGatewayClientCertificateNodeProperties = (
65
+ APIGatewayClientCertificateNodeProperties()
66
+ )
67
+ sub_resource_relationship: APIGatewayClientCertificateToAWSAccountRel = (
68
+ APIGatewayClientCertificateToAWSAccountRel()
69
+ )
70
+ other_relationships: OtherRelationships = OtherRelationships(
71
+ [APIGatewayClientCertificateToStageRel()],
72
+ )
@@ -13,50 +13,58 @@ from cartography.models.core.relationships import TargetNodeMatcher
13
13
 
14
14
  @dataclass(frozen=True)
15
15
  class APIGatewayResourceNodeProperties(CartographyNodeProperties):
16
- id: PropertyRef = PropertyRef('id')
17
- path: PropertyRef = PropertyRef('path')
18
- pathpart: PropertyRef = PropertyRef('pathPart')
19
- parentid: PropertyRef = PropertyRef('parentId')
20
- lastupdated: PropertyRef = PropertyRef('lastupdated', set_in_kwargs=True)
16
+ id: PropertyRef = PropertyRef("id")
17
+ path: PropertyRef = PropertyRef("path")
18
+ pathpart: PropertyRef = PropertyRef("pathPart")
19
+ parentid: PropertyRef = PropertyRef("parentId")
20
+ lastupdated: PropertyRef = PropertyRef("lastupdated", set_in_kwargs=True)
21
21
 
22
22
 
23
23
  @dataclass(frozen=True)
24
- class APIGatewayResourceToRestAPIRelProperties(CartographyRelProperties):
25
- lastupdated: PropertyRef = PropertyRef('lastupdated', set_in_kwargs=True)
24
+ class APIGatewayResourceToRestAPIRelRelProperties(CartographyRelProperties):
25
+ lastupdated: PropertyRef = PropertyRef("lastupdated", set_in_kwargs=True)
26
26
 
27
27
 
28
28
  @dataclass(frozen=True)
29
29
  # (:APIGatewayResource)<-[:RESOURCE]-(:APIGatewayRestAPI)
30
- class APIGatewayResourceToRestAPI(CartographyRelSchema):
31
- target_node_label: str = 'APIGatewayRestAPI'
30
+ class APIGatewayResourceToRestAPIRel(CartographyRelSchema):
31
+ target_node_label: str = "APIGatewayRestAPI"
32
32
  target_node_matcher: TargetNodeMatcher = make_target_node_matcher(
33
- {'id': PropertyRef('apiId')},
33
+ {"id": PropertyRef("apiId")},
34
34
  )
35
35
  direction: LinkDirection = LinkDirection.INWARD
36
36
  rel_label: str = "RESOURCE"
37
- properties: APIGatewayResourceToRestAPIRelProperties = APIGatewayResourceToRestAPIRelProperties()
37
+ properties: APIGatewayResourceToRestAPIRelRelProperties = (
38
+ APIGatewayResourceToRestAPIRelRelProperties()
39
+ )
38
40
 
39
41
 
40
42
  @dataclass(frozen=True)
41
- class APIGatewayResourceToAwsAccountRelProperties(CartographyRelProperties):
42
- lastupdated: PropertyRef = PropertyRef('lastupdated', set_in_kwargs=True)
43
+ class APIGatewayResourceToAWSAccountRelRelProperties(CartographyRelProperties):
44
+ lastupdated: PropertyRef = PropertyRef("lastupdated", set_in_kwargs=True)
43
45
 
44
46
 
45
47
  @dataclass(frozen=True)
46
48
  # (:APIGatewayResource)<-[:RESOURCE]-(:AWSAccount)
47
- class APIGatewayResourceToAWSAccount(CartographyRelSchema):
48
- target_node_label: str = 'AWSAccount'
49
+ class APIGatewayResourceToAWSAccountRel(CartographyRelSchema):
50
+ target_node_label: str = "AWSAccount"
49
51
  target_node_matcher: TargetNodeMatcher = make_target_node_matcher(
50
- {'id': PropertyRef('AWS_ID', set_in_kwargs=True)},
52
+ {"id": PropertyRef("AWS_ID", set_in_kwargs=True)},
51
53
  )
52
54
  direction: LinkDirection = LinkDirection.INWARD
53
55
  rel_label: str = "RESOURCE"
54
- properties: APIGatewayResourceToAwsAccountRelProperties = APIGatewayResourceToAwsAccountRelProperties()
56
+ properties: APIGatewayResourceToAWSAccountRelRelProperties = (
57
+ APIGatewayResourceToAWSAccountRelRelProperties()
58
+ )
55
59
 
56
60
 
57
61
  @dataclass(frozen=True)
58
62
  class APIGatewayResourceSchema(CartographyNodeSchema):
59
- label: str = 'APIGatewayResource'
63
+ label: str = "APIGatewayResource"
60
64
  properties: APIGatewayResourceNodeProperties = APIGatewayResourceNodeProperties()
61
- sub_resource_relationship: APIGatewayResourceToAWSAccount = APIGatewayResourceToAWSAccount()
62
- other_relationships: OtherRelationships = OtherRelationships([APIGatewayResourceToRestAPI()])
65
+ sub_resource_relationship: APIGatewayResourceToAWSAccountRel = (
66
+ APIGatewayResourceToAWSAccountRel()
67
+ )
68
+ other_relationships: OtherRelationships = OtherRelationships(
69
+ [APIGatewayResourceToRestAPIRel()],
70
+ )
@@ -13,55 +13,63 @@ from cartography.models.core.relationships import TargetNodeMatcher
13
13
 
14
14
  @dataclass(frozen=True)
15
15
  class APIGatewayStageNodeProperties(CartographyNodeProperties):
16
- id: PropertyRef = PropertyRef('arn')
17
- stagename: PropertyRef = PropertyRef('stageName')
18
- createddate: PropertyRef = PropertyRef('createdDate')
19
- deploymentid: PropertyRef = PropertyRef('deploymentId')
20
- clientcertificateid: PropertyRef = PropertyRef('clientCertificateId')
21
- cacheclusterenabled: PropertyRef = PropertyRef('cacheClusterEnabled')
22
- cacheclusterstatus: PropertyRef = PropertyRef('cacheClusterStatus')
23
- tracingenabled: PropertyRef = PropertyRef('tracingEnabled')
24
- webaclarn: PropertyRef = PropertyRef('webAclArn')
25
- lastupdated: PropertyRef = PropertyRef('lastupdated', set_in_kwargs=True)
16
+ id: PropertyRef = PropertyRef("arn")
17
+ stagename: PropertyRef = PropertyRef("stageName")
18
+ createddate: PropertyRef = PropertyRef("createdDate")
19
+ deploymentid: PropertyRef = PropertyRef("deploymentId")
20
+ clientcertificateid: PropertyRef = PropertyRef("clientCertificateId")
21
+ cacheclusterenabled: PropertyRef = PropertyRef("cacheClusterEnabled")
22
+ cacheclusterstatus: PropertyRef = PropertyRef("cacheClusterStatus")
23
+ tracingenabled: PropertyRef = PropertyRef("tracingEnabled")
24
+ webaclarn: PropertyRef = PropertyRef("webAclArn")
25
+ lastupdated: PropertyRef = PropertyRef("lastupdated", set_in_kwargs=True)
26
26
 
27
27
 
28
28
  @dataclass(frozen=True)
29
- class APIGatewayStageToRestAPIRelProperties(CartographyRelProperties):
30
- lastupdated: PropertyRef = PropertyRef('lastupdated', set_in_kwargs=True)
29
+ class APIGatewayStageToRestAPIRelRelProperties(CartographyRelProperties):
30
+ lastupdated: PropertyRef = PropertyRef("lastupdated", set_in_kwargs=True)
31
31
 
32
32
 
33
33
  @dataclass(frozen=True)
34
34
  # (:APIGatewayStage)<-[:ASSOCIATED_WITH]-(:APIGatewayRestAPI)
35
- class APIGatewayStageToRestAPI(CartographyRelSchema):
36
- target_node_label: str = 'APIGatewayRestAPI'
35
+ class APIGatewayStageToRestAPIRel(CartographyRelSchema):
36
+ target_node_label: str = "APIGatewayRestAPI"
37
37
  target_node_matcher: TargetNodeMatcher = make_target_node_matcher(
38
- {'id': PropertyRef('apiId')},
38
+ {"id": PropertyRef("apiId")},
39
39
  )
40
40
  direction: LinkDirection = LinkDirection.INWARD
41
41
  rel_label: str = "ASSOCIATED_WITH"
42
- properties: APIGatewayStageToRestAPIRelProperties = APIGatewayStageToRestAPIRelProperties()
42
+ properties: APIGatewayStageToRestAPIRelRelProperties = (
43
+ APIGatewayStageToRestAPIRelRelProperties()
44
+ )
43
45
 
44
46
 
45
47
  @dataclass(frozen=True)
46
- class APIGatewayStageToAwsAccountRelProperties(CartographyRelProperties):
47
- lastupdated: PropertyRef = PropertyRef('lastupdated', set_in_kwargs=True)
48
+ class APIGatewayStageToAWSAccountRelRelProperties(CartographyRelProperties):
49
+ lastupdated: PropertyRef = PropertyRef("lastupdated", set_in_kwargs=True)
48
50
 
49
51
 
50
52
  @dataclass(frozen=True)
51
53
  # (:APIGatewayStage)<-[:RESOURCE]-(:AWSAccount)
52
- class APIGatewayStageToAWSAccount(CartographyRelSchema):
53
- target_node_label: str = 'AWSAccount'
54
+ class APIGatewayStageToAWSAccountRel(CartographyRelSchema):
55
+ target_node_label: str = "AWSAccount"
54
56
  target_node_matcher: TargetNodeMatcher = make_target_node_matcher(
55
- {'id': PropertyRef('AWS_ID', set_in_kwargs=True)},
57
+ {"id": PropertyRef("AWS_ID", set_in_kwargs=True)},
56
58
  )
57
59
  direction: LinkDirection = LinkDirection.INWARD
58
60
  rel_label: str = "RESOURCE"
59
- properties: APIGatewayStageToAwsAccountRelProperties = APIGatewayStageToAwsAccountRelProperties()
61
+ properties: APIGatewayStageToAWSAccountRelRelProperties = (
62
+ APIGatewayStageToAWSAccountRelRelProperties()
63
+ )
60
64
 
61
65
 
62
66
  @dataclass(frozen=True)
63
67
  class APIGatewayStageSchema(CartographyNodeSchema):
64
- label: str = 'APIGatewayStage'
68
+ label: str = "APIGatewayStage"
65
69
  properties: APIGatewayStageNodeProperties = APIGatewayStageNodeProperties()
66
- sub_resource_relationship: APIGatewayStageToAWSAccount = APIGatewayStageToAWSAccount()
67
- other_relationships: OtherRelationships = OtherRelationships([APIGatewayStageToRestAPI()])
70
+ sub_resource_relationship: APIGatewayStageToAWSAccountRel = (
71
+ APIGatewayStageToAWSAccountRel()
72
+ )
73
+ other_relationships: OtherRelationships = OtherRelationships(
74
+ [APIGatewayStageToRestAPIRel()],
75
+ )
File without changes