cartography 0.102.0rc2__py3-none-any.whl → 0.103.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.

Files changed (297) hide show
  1. cartography/__main__.py +1 -2
  2. cartography/_version.py +2 -2
  3. cartography/cli.py +376 -249
  4. cartography/client/core/tx.py +39 -18
  5. cartography/config.py +28 -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/cloudwatch.py +93 -0
  23. cartography/intel/aws/config.py +56 -20
  24. cartography/intel/aws/dynamodb.py +108 -40
  25. cartography/intel/aws/ec2/__init__.py +2 -2
  26. cartography/intel/aws/ec2/auto_scaling_groups.py +181 -78
  27. cartography/intel/aws/ec2/elastic_ip_addresses.py +41 -13
  28. cartography/intel/aws/ec2/images.py +49 -20
  29. cartography/intel/aws/ec2/instances.py +234 -136
  30. cartography/intel/aws/ec2/internet_gateways.py +40 -11
  31. cartography/intel/aws/ec2/key_pairs.py +44 -20
  32. cartography/intel/aws/ec2/launch_templates.py +101 -59
  33. cartography/intel/aws/ec2/load_balancer_v2s.py +104 -39
  34. cartography/intel/aws/ec2/load_balancers.py +82 -42
  35. cartography/intel/aws/ec2/network_acls.py +89 -65
  36. cartography/intel/aws/ec2/network_interfaces.py +146 -87
  37. cartography/intel/aws/ec2/reserved_instances.py +45 -16
  38. cartography/intel/aws/ec2/route_tables.py +138 -98
  39. cartography/intel/aws/ec2/security_groups.py +71 -21
  40. cartography/intel/aws/ec2/snapshots.py +61 -22
  41. cartography/intel/aws/ec2/subnets.py +54 -18
  42. cartography/intel/aws/ec2/tgw.py +100 -34
  43. cartography/intel/aws/ec2/util.py +1 -1
  44. cartography/intel/aws/ec2/volumes.py +69 -41
  45. cartography/intel/aws/ec2/vpc.py +37 -12
  46. cartography/intel/aws/ec2/vpc_peerings.py +83 -24
  47. cartography/intel/aws/ecr.py +88 -32
  48. cartography/intel/aws/ecs.py +83 -47
  49. cartography/intel/aws/efs.py +93 -0
  50. cartography/intel/aws/eks.py +55 -29
  51. cartography/intel/aws/elasticache.py +42 -18
  52. cartography/intel/aws/elasticsearch.py +57 -20
  53. cartography/intel/aws/emr.py +61 -23
  54. cartography/intel/aws/iam.py +401 -145
  55. cartography/intel/aws/iam_instance_profiles.py +22 -22
  56. cartography/intel/aws/identitycenter.py +71 -37
  57. cartography/intel/aws/inspector.py +159 -89
  58. cartography/intel/aws/kms.py +92 -38
  59. cartography/intel/aws/lambda_function.py +103 -34
  60. cartography/intel/aws/organizations.py +30 -10
  61. cartography/intel/aws/permission_relationships.py +133 -51
  62. cartography/intel/aws/rds.py +249 -85
  63. cartography/intel/aws/redshift.py +107 -46
  64. cartography/intel/aws/resourcegroupstaggingapi.py +120 -66
  65. cartography/intel/aws/resources.py +57 -46
  66. cartography/intel/aws/route53.py +108 -61
  67. cartography/intel/aws/s3.py +168 -83
  68. cartography/intel/aws/s3accountpublicaccessblock.py +157 -0
  69. cartography/intel/aws/secretsmanager.py +24 -12
  70. cartography/intel/aws/securityhub.py +20 -9
  71. cartography/intel/aws/sns.py +166 -0
  72. cartography/intel/aws/sqs.py +60 -28
  73. cartography/intel/aws/ssm.py +70 -30
  74. cartography/intel/aws/util/arns.py +7 -7
  75. cartography/intel/aws/util/common.py +31 -4
  76. cartography/intel/azure/__init__.py +78 -19
  77. cartography/intel/azure/compute.py +101 -27
  78. cartography/intel/azure/cosmosdb.py +496 -170
  79. cartography/intel/azure/sql.py +296 -105
  80. cartography/intel/azure/storage.py +322 -113
  81. cartography/intel/azure/subscription.py +39 -23
  82. cartography/intel/azure/tenant.py +13 -4
  83. cartography/intel/azure/util/credentials.py +95 -55
  84. cartography/intel/bigfix/__init__.py +2 -2
  85. cartography/intel/bigfix/computers.py +93 -65
  86. cartography/intel/cloudflare/__init__.py +74 -0
  87. cartography/intel/cloudflare/accounts.py +57 -0
  88. cartography/intel/cloudflare/dnsrecords.py +64 -0
  89. cartography/intel/cloudflare/members.py +75 -0
  90. cartography/intel/cloudflare/roles.py +65 -0
  91. cartography/intel/cloudflare/zones.py +64 -0
  92. cartography/intel/create_indexes.py +3 -2
  93. cartography/intel/crowdstrike/__init__.py +11 -9
  94. cartography/intel/crowdstrike/endpoints.py +5 -1
  95. cartography/intel/crowdstrike/spotlight.py +8 -3
  96. cartography/intel/cve/__init__.py +46 -13
  97. cartography/intel/cve/feed.py +48 -12
  98. cartography/intel/digitalocean/__init__.py +22 -13
  99. cartography/intel/digitalocean/compute.py +75 -108
  100. cartography/intel/digitalocean/management.py +44 -80
  101. cartography/intel/digitalocean/platform.py +48 -43
  102. cartography/intel/dns.py +36 -10
  103. cartography/intel/duo/__init__.py +21 -16
  104. cartography/intel/duo/api_host.py +14 -9
  105. cartography/intel/duo/endpoints.py +50 -45
  106. cartography/intel/duo/groups.py +18 -14
  107. cartography/intel/duo/phones.py +37 -34
  108. cartography/intel/duo/tokens.py +26 -23
  109. cartography/intel/duo/users.py +54 -50
  110. cartography/intel/duo/web_authn_credentials.py +30 -25
  111. cartography/intel/entra/__init__.py +25 -7
  112. cartography/intel/entra/ou.py +112 -0
  113. cartography/intel/entra/users.py +69 -63
  114. cartography/intel/gcp/__init__.py +185 -49
  115. cartography/intel/gcp/compute.py +418 -231
  116. cartography/intel/gcp/crm.py +96 -43
  117. cartography/intel/gcp/dns.py +60 -19
  118. cartography/intel/gcp/gke.py +72 -38
  119. cartography/intel/gcp/iam.py +61 -41
  120. cartography/intel/gcp/storage.py +84 -55
  121. cartography/intel/github/__init__.py +13 -11
  122. cartography/intel/github/repos.py +270 -137
  123. cartography/intel/github/teams.py +170 -88
  124. cartography/intel/github/users.py +70 -39
  125. cartography/intel/github/util.py +36 -34
  126. cartography/intel/gsuite/__init__.py +47 -26
  127. cartography/intel/gsuite/api.py +73 -30
  128. cartography/intel/jamf/__init__.py +19 -1
  129. cartography/intel/jamf/computers.py +30 -7
  130. cartography/intel/jamf/util.py +7 -2
  131. cartography/intel/kandji/__init__.py +6 -3
  132. cartography/intel/kandji/devices.py +14 -8
  133. cartography/intel/kubernetes/namespaces.py +7 -4
  134. cartography/intel/kubernetes/pods.py +7 -4
  135. cartography/intel/kubernetes/services.py +8 -4
  136. cartography/intel/lastpass/__init__.py +2 -2
  137. cartography/intel/lastpass/users.py +23 -12
  138. cartography/intel/oci/__init__.py +44 -11
  139. cartography/intel/oci/iam.py +134 -38
  140. cartography/intel/oci/organizations.py +13 -6
  141. cartography/intel/oci/utils.py +43 -20
  142. cartography/intel/okta/__init__.py +66 -15
  143. cartography/intel/okta/applications.py +42 -20
  144. cartography/intel/okta/awssaml.py +93 -33
  145. cartography/intel/okta/factors.py +16 -4
  146. cartography/intel/okta/groups.py +56 -29
  147. cartography/intel/okta/organization.py +5 -1
  148. cartography/intel/okta/origins.py +6 -2
  149. cartography/intel/okta/roles.py +15 -5
  150. cartography/intel/okta/users.py +20 -8
  151. cartography/intel/okta/utils.py +6 -4
  152. cartography/intel/openai/__init__.py +86 -0
  153. cartography/intel/openai/adminapikeys.py +90 -0
  154. cartography/intel/openai/apikeys.py +96 -0
  155. cartography/intel/openai/projects.py +94 -0
  156. cartography/intel/openai/serviceaccounts.py +82 -0
  157. cartography/intel/openai/users.py +78 -0
  158. cartography/intel/openai/util.py +29 -0
  159. cartography/intel/pagerduty/__init__.py +8 -7
  160. cartography/intel/pagerduty/escalation_policies.py +18 -6
  161. cartography/intel/pagerduty/schedules.py +12 -4
  162. cartography/intel/pagerduty/services.py +11 -4
  163. cartography/intel/pagerduty/teams.py +8 -3
  164. cartography/intel/pagerduty/users.py +3 -1
  165. cartography/intel/pagerduty/vendors.py +3 -1
  166. cartography/intel/semgrep/__init__.py +24 -6
  167. cartography/intel/semgrep/dependencies.py +50 -28
  168. cartography/intel/semgrep/deployment.py +3 -1
  169. cartography/intel/semgrep/findings.py +42 -18
  170. cartography/intel/snipeit/__init__.py +17 -3
  171. cartography/intel/snipeit/asset.py +12 -6
  172. cartography/intel/snipeit/user.py +8 -5
  173. cartography/intel/snipeit/util.py +9 -4
  174. cartography/intel/tailscale/__init__.py +77 -0
  175. cartography/intel/tailscale/acls.py +146 -0
  176. cartography/intel/tailscale/devices.py +127 -0
  177. cartography/intel/tailscale/postureintegrations.py +81 -0
  178. cartography/intel/tailscale/tailnets.py +76 -0
  179. cartography/intel/tailscale/users.py +80 -0
  180. cartography/intel/tailscale/utils.py +132 -0
  181. cartography/models/aws/apigateway.py +21 -17
  182. cartography/models/aws/apigatewaycertificate.py +28 -22
  183. cartography/models/aws/apigatewayresource.py +28 -20
  184. cartography/models/aws/apigatewaystage.py +33 -25
  185. cartography/models/aws/cloudtrail/__init__.py +0 -0
  186. cartography/models/aws/cloudtrail/trail.py +61 -0
  187. cartography/models/aws/cloudwatch/__init__.py +0 -0
  188. cartography/models/aws/cloudwatch/loggroup.py +52 -0
  189. cartography/models/aws/dynamodb/gsi.py +30 -22
  190. cartography/models/aws/dynamodb/tables.py +25 -17
  191. cartography/models/aws/ec2/auto_scaling_groups.py +102 -82
  192. cartography/models/aws/ec2/images.py +36 -34
  193. cartography/models/aws/ec2/instances.py +51 -45
  194. cartography/models/aws/ec2/keypair.py +21 -16
  195. cartography/models/aws/ec2/keypair_instance.py +28 -21
  196. cartography/models/aws/ec2/launch_configurations.py +30 -26
  197. cartography/models/aws/ec2/launch_template_versions.py +48 -38
  198. cartography/models/aws/ec2/launch_templates.py +21 -17
  199. cartography/models/aws/ec2/load_balancer_listeners.py +27 -23
  200. cartography/models/aws/ec2/load_balancers.py +47 -37
  201. cartography/models/aws/ec2/network_acl_rules.py +38 -30
  202. cartography/models/aws/ec2/network_acls.py +38 -29
  203. cartography/models/aws/ec2/networkinterface_instance.py +52 -39
  204. cartography/models/aws/ec2/networkinterfaces.py +53 -37
  205. cartography/models/aws/ec2/privateip_networkinterface.py +32 -22
  206. cartography/models/aws/ec2/reservations.py +18 -14
  207. cartography/models/aws/ec2/route_table_associations.py +44 -34
  208. cartography/models/aws/ec2/route_tables.py +50 -43
  209. cartography/models/aws/ec2/routes.py +45 -37
  210. cartography/models/aws/ec2/securitygroup_instance.py +29 -20
  211. cartography/models/aws/ec2/securitygroup_networkinterface.py +24 -15
  212. cartography/models/aws/ec2/subnet_instance.py +24 -19
  213. cartography/models/aws/ec2/subnet_networkinterface.py +40 -31
  214. cartography/models/aws/ec2/volumes.py +47 -40
  215. cartography/models/aws/efs/__init__.py +0 -0
  216. cartography/models/aws/efs/mount_target.py +52 -0
  217. cartography/models/aws/eks/clusters.py +23 -21
  218. cartography/models/aws/emr.py +32 -30
  219. cartography/models/aws/iam/instanceprofile.py +33 -24
  220. cartography/models/aws/identitycenter/awsidentitycenter.py +18 -14
  221. cartography/models/aws/identitycenter/awspermissionset.py +37 -29
  222. cartography/models/aws/identitycenter/awsssouser.py +23 -21
  223. cartography/models/aws/inspector/findings.py +77 -65
  224. cartography/models/aws/inspector/packages.py +35 -29
  225. cartography/models/aws/s3/__init__.py +0 -0
  226. cartography/models/aws/s3/account_public_access_block.py +51 -0
  227. cartography/models/aws/sns/__init__.py +0 -0
  228. cartography/models/aws/sns/topic.py +50 -0
  229. cartography/models/aws/ssm/instance_information.py +51 -39
  230. cartography/models/aws/ssm/instance_patch.py +32 -26
  231. cartography/models/bigfix/bigfix_computer.py +42 -38
  232. cartography/models/bigfix/bigfix_root.py +3 -3
  233. cartography/models/cloudflare/__init__.py +0 -0
  234. cartography/models/cloudflare/account.py +25 -0
  235. cartography/models/cloudflare/dnsrecord.py +55 -0
  236. cartography/models/cloudflare/member.py +82 -0
  237. cartography/models/cloudflare/role.py +44 -0
  238. cartography/models/cloudflare/zone.py +59 -0
  239. cartography/models/core/common.py +12 -10
  240. cartography/models/core/nodes.py +5 -2
  241. cartography/models/core/relationships.py +14 -6
  242. cartography/models/crowdstrike/hosts.py +37 -35
  243. cartography/models/cve/cve.py +34 -32
  244. cartography/models/cve/cve_feed.py +6 -6
  245. cartography/models/digitalocean/__init__.py +0 -0
  246. cartography/models/digitalocean/account.py +21 -0
  247. cartography/models/digitalocean/droplet.py +56 -0
  248. cartography/models/digitalocean/project.py +48 -0
  249. cartography/models/duo/api_host.py +3 -3
  250. cartography/models/duo/endpoint.py +43 -41
  251. cartography/models/duo/group.py +14 -14
  252. cartography/models/duo/phone.py +27 -27
  253. cartography/models/duo/token.py +16 -16
  254. cartography/models/duo/user.py +46 -44
  255. cartography/models/duo/web_authn_credential.py +27 -19
  256. cartography/models/entra/ou.py +48 -0
  257. cartography/models/entra/tenant.py +24 -18
  258. cartography/models/entra/user.py +64 -48
  259. cartography/models/gcp/iam.py +23 -23
  260. cartography/models/github/orgs.py +5 -4
  261. cartography/models/github/teams.py +37 -31
  262. cartography/models/github/users.py +34 -23
  263. cartography/models/kandji/device.py +22 -16
  264. cartography/models/kandji/tenant.py +6 -4
  265. cartography/models/lastpass/tenant.py +3 -3
  266. cartography/models/lastpass/user.py +32 -28
  267. cartography/models/openai/__init__.py +0 -0
  268. cartography/models/openai/adminapikey.py +90 -0
  269. cartography/models/openai/apikey.py +84 -0
  270. cartography/models/openai/organization.py +17 -0
  271. cartography/models/openai/project.py +70 -0
  272. cartography/models/openai/serviceaccount.py +50 -0
  273. cartography/models/openai/user.py +49 -0
  274. cartography/models/semgrep/dependencies.py +36 -24
  275. cartography/models/semgrep/deployment.py +5 -5
  276. cartography/models/semgrep/findings.py +58 -42
  277. cartography/models/semgrep/locations.py +27 -21
  278. cartography/models/snipeit/asset.py +30 -21
  279. cartography/models/snipeit/tenant.py +6 -4
  280. cartography/models/snipeit/user.py +19 -12
  281. cartography/models/tailscale/__init__.py +0 -0
  282. cartography/models/tailscale/device.py +95 -0
  283. cartography/models/tailscale/group.py +86 -0
  284. cartography/models/tailscale/postureintegration.py +58 -0
  285. cartography/models/tailscale/tag.py +102 -0
  286. cartography/models/tailscale/tailnet.py +29 -0
  287. cartography/models/tailscale/user.py +52 -0
  288. cartography/stats.py +3 -3
  289. cartography/sync.py +113 -31
  290. cartography/util.py +84 -62
  291. {cartography-0.102.0rc2.dist-info → cartography-0.103.0.dist-info}/METADATA +8 -15
  292. cartography-0.103.0.dist-info/RECORD +442 -0
  293. {cartography-0.102.0rc2.dist-info → cartography-0.103.0.dist-info}/WHEEL +1 -1
  294. cartography-0.102.0rc2.dist-info/RECORD +0 -381
  295. {cartography-0.102.0rc2.dist-info → cartography-0.103.0.dist-info}/entry_points.txt +0 -0
  296. {cartography-0.102.0rc2.dist-info → cartography-0.103.0.dist-info}/licenses/LICENSE +0 -0
  297. {cartography-0.102.0rc2.dist-info → cartography-0.103.0.dist-info}/top_level.txt +0 -0
@@ -35,18 +35,28 @@ def build_cleanup_queries(node_schema: CartographyNodeSchema) -> List[str]:
35
35
  :param node_schema: The given CartographyNodeSchema
36
36
  :return: A list of Neo4j queries to clean up nodes and relationships.
37
37
  """
38
- if not node_schema.sub_resource_relationship and not node_schema.other_relationships:
38
+ if (
39
+ not node_schema.sub_resource_relationship
40
+ and not node_schema.other_relationships
41
+ ):
39
42
  return []
40
43
 
41
44
  if not node_schema.sub_resource_relationship:
42
45
  queries = []
43
- other_rels = node_schema.other_relationships.rels if node_schema.other_relationships else []
46
+ other_rels = (
47
+ node_schema.other_relationships.rels
48
+ if node_schema.other_relationships
49
+ else []
50
+ )
44
51
  for rel in other_rels:
45
52
  query = _build_cleanup_rel_query_no_sub_resource(node_schema, rel)
46
53
  queries.append(query)
47
54
  return queries
48
55
 
49
- result = _build_cleanup_node_and_rel_queries(node_schema, node_schema.sub_resource_relationship)
56
+ result = _build_cleanup_node_and_rel_queries(
57
+ node_schema,
58
+ node_schema.sub_resource_relationship,
59
+ )
50
60
  if node_schema.other_relationships:
51
61
  for rel in node_schema.other_relationships.rels:
52
62
  # [0] is the delete node query, [1] is the delete relationship query. We only want the latter.
@@ -57,16 +67,16 @@ def build_cleanup_queries(node_schema: CartographyNodeSchema) -> List[str]:
57
67
 
58
68
 
59
69
  def _build_cleanup_rel_query_no_sub_resource(
60
- node_schema: CartographyNodeSchema,
61
- selected_relationship: CartographyRelSchema,
70
+ node_schema: CartographyNodeSchema,
71
+ selected_relationship: CartographyRelSchema,
62
72
  ) -> str:
63
73
  """
64
74
  Helper function to delete stale relationships for node_schemas that have no sub resource relationship defined.
65
75
  """
66
76
  if node_schema.sub_resource_relationship:
67
77
  raise ValueError(
68
- f'Expected {node_schema.label} to not exist. '
69
- 'This function is intended for node_schemas without sub_resource_relationships.',
78
+ f"Expected {node_schema.label} to not exist. "
79
+ "This function is intended for node_schemas without sub_resource_relationships.",
70
80
  )
71
81
  # Ensure the node is attached to the sub resource and delete the node
72
82
  query_template = Template(
@@ -85,8 +95,8 @@ def _build_cleanup_rel_query_no_sub_resource(
85
95
 
86
96
 
87
97
  def _build_cleanup_node_and_rel_queries(
88
- node_schema: CartographyNodeSchema,
89
- selected_relationship: CartographyRelSchema,
98
+ node_schema: CartographyNodeSchema,
99
+ selected_relationship: CartographyRelSchema,
90
100
  ) -> List[str]:
91
101
  """
92
102
  Private function that performs the main string template logic for generating cleanup node and relationship queries.
@@ -129,7 +139,9 @@ def _build_cleanup_node_and_rel_queries(
129
139
  ]
130
140
  # Now clean up the relationships
131
141
  if selected_relationship == node_schema.sub_resource_relationship:
132
- _validate_target_node_matcher_for_cleanup_job(node_schema.sub_resource_relationship.target_node_matcher)
142
+ _validate_target_node_matcher_for_cleanup_job(
143
+ node_schema.sub_resource_relationship.target_node_matcher,
144
+ )
133
145
  delete_action_clauses.append(
134
146
  """
135
147
  WHERE s.lastupdated <> $UPDATE_TAG
@@ -159,13 +171,17 @@ def _build_cleanup_node_and_rel_queries(
159
171
  node_label=node_schema.label,
160
172
  sub_resource_link=sub_resource_link,
161
173
  sub_resource_label=node_schema.sub_resource_relationship.target_node_label,
162
- match_sub_res_clause=_build_match_clause(node_schema.sub_resource_relationship.target_node_matcher),
174
+ match_sub_res_clause=_build_match_clause(
175
+ node_schema.sub_resource_relationship.target_node_matcher,
176
+ ),
163
177
  selected_rel_clause=(
164
- "" if selected_relationship == node_schema.sub_resource_relationship
178
+ ""
179
+ if selected_relationship == node_schema.sub_resource_relationship
165
180
  else _build_selected_rel_clause(selected_relationship)
166
181
  ),
167
182
  delete_action_clause=delete_action_clause,
168
- ) for delete_action_clause in delete_action_clauses
183
+ )
184
+ for delete_action_clause in delete_action_clauses
169
185
  ]
170
186
 
171
187
 
@@ -179,8 +195,12 @@ def _build_selected_rel_clause(selected_relationship: CartographyRelSchema) -> s
179
195
  selected_rel_template = Template("<-[r:$SelectedRelLabel]-")
180
196
  else:
181
197
  selected_rel_template = Template("-[r:$SelectedRelLabel]->")
182
- selected_rel = selected_rel_template.safe_substitute(SelectedRelLabel=selected_relationship.rel_label)
183
- selected_rel_clause_template = Template("""MATCH (n)$selected_rel(:$other_node_label)""")
198
+ selected_rel = selected_rel_template.safe_substitute(
199
+ SelectedRelLabel=selected_relationship.rel_label,
200
+ )
201
+ selected_rel_clause_template = Template(
202
+ """MATCH (n)$selected_rel(:$other_node_label)""",
203
+ )
184
204
  selected_rel_clause = selected_rel_clause_template.safe_substitute(
185
205
  selected_rel=selected_rel,
186
206
  other_node_label=selected_relationship.target_node_label,
cartography/graph/job.py CHANGED
@@ -32,7 +32,7 @@ def _get_identifiers(template: string.Template) -> List[str]:
32
32
  filter(
33
33
  lambda v: v is not None,
34
34
  (
35
- mo.group('named') or mo.group('braced')
35
+ mo.group("named") or mo.group("braced")
36
36
  for mo in template.pattern.finditer(template.template)
37
37
  ),
38
38
  ),
@@ -71,7 +71,12 @@ class GraphJob:
71
71
  A job that will run against the cartography graph. A job is a sequence of statements which execute sequentially.
72
72
  """
73
73
 
74
- def __init__(self, name: str, statements: List[GraphStatement], short_name: Optional[str] = None):
74
+ def __init__(
75
+ self,
76
+ name: str,
77
+ statements: List[GraphStatement],
78
+ short_name: Optional[str] = None,
79
+ ):
75
80
  # E.g. "Okta intel module cleanup"
76
81
  self.name = name
77
82
  self.statements: List[GraphStatement] = statements
@@ -100,7 +105,11 @@ class GraphJob:
100
105
  e,
101
106
  )
102
107
  raise
103
- log_msg = f"Finished job {self.short_name}" if self.short_name else f"Finished job {self.name}"
108
+ log_msg = (
109
+ f"Finished job {self.short_name}"
110
+ if self.short_name
111
+ else f"Finished job {self.name}"
112
+ )
104
113
  logger.info(log_msg)
105
114
 
106
115
  def as_dict(self) -> Dict:
@@ -114,7 +123,7 @@ class GraphJob:
114
123
  }
115
124
 
116
125
  @classmethod
117
- def from_json(cls, blob: str, short_name: Optional[str] = None) -> 'GraphJob':
126
+ def from_json(cls, blob: str, short_name: Optional[str] = None) -> "GraphJob":
118
127
  """
119
128
  Create a job from a JSON blob.
120
129
  """
@@ -125,10 +134,10 @@ class GraphJob:
125
134
 
126
135
  @classmethod
127
136
  def from_node_schema(
128
- cls,
129
- node_schema: CartographyNodeSchema,
130
- parameters: Dict[str, Any],
131
- ) -> 'GraphJob':
137
+ cls,
138
+ node_schema: CartographyNodeSchema,
139
+ parameters: Dict[str, Any],
140
+ ) -> "GraphJob":
132
141
  """
133
142
  Create a cleanup job from a CartographyNodeSchema object.
134
143
  For a given node, the fields used in the node_schema.sub_resource_relationship.target_node_node_matcher.keys()
@@ -139,14 +148,14 @@ class GraphJob:
139
148
  expected_param_keys: Set[str] = get_parameters(queries)
140
149
  actual_param_keys: Set[str] = set(parameters.keys())
141
150
  # Hacky, but LIMIT_SIZE is specified by default in cartography.graph.statement, so we exclude it from validation
142
- actual_param_keys.add('LIMIT_SIZE')
151
+ actual_param_keys.add("LIMIT_SIZE")
143
152
 
144
153
  missing_params: Set[str] = expected_param_keys - actual_param_keys
145
154
 
146
155
  if missing_params:
147
156
  raise ValueError(
148
157
  f'GraphJob is missing the following expected query parameters: "{missing_params}". Please check the '
149
- f'value passed to `parameters`.',
158
+ f"value passed to `parameters`.",
150
159
  )
151
160
 
152
161
  statements: List[GraphStatement] = [
@@ -157,7 +166,8 @@ class GraphJob:
157
166
  iterationsize=100,
158
167
  parent_job_name=node_schema.label,
159
168
  parent_job_sequence_num=idx,
160
- ) for idx, query in enumerate(queries, start=1)
169
+ )
170
+ for idx, query in enumerate(queries, start=1)
161
171
  ]
162
172
 
163
173
  return cls(
@@ -167,7 +177,7 @@ class GraphJob:
167
177
  )
168
178
 
169
179
  @classmethod
170
- def from_json_file(cls, file_path: Union[str, Path]) -> 'GraphJob':
180
+ def from_json_file(cls, file_path: Union[str, Path]) -> "GraphJob":
171
181
  """
172
182
  Create a job from a JSON file.
173
183
  """
@@ -175,13 +185,20 @@ class GraphJob:
175
185
  data: Dict = json.load(j_file)
176
186
 
177
187
  job_shortname: str = get_job_shortname(file_path)
178
- statements: List[GraphStatement] = _get_statements_from_json(data, job_shortname)
188
+ statements: List[GraphStatement] = _get_statements_from_json(
189
+ data,
190
+ job_shortname,
191
+ )
179
192
  name: str = data["name"]
180
193
  return cls(name, statements, job_shortname)
181
194
 
182
195
  @classmethod
183
196
  def run_from_json(
184
- cls, neo4j_session: neo4j.Session, blob: str, parameters: Dict, short_name: Optional[str] = None,
197
+ cls,
198
+ neo4j_session: neo4j.Session,
199
+ blob: str,
200
+ parameters: Dict,
201
+ short_name: Optional[str] = None,
185
202
  ) -> None:
186
203
  """
187
204
  Run a job from a JSON blob. This will deserialize the job and execute all statements sequentially.
@@ -194,7 +211,12 @@ class GraphJob:
194
211
  job.run(neo4j_session)
195
212
 
196
213
  @classmethod
197
- def run_from_json_file(cls, file_path: Union[str, Path], neo4j_session: neo4j.Session, parameters: Dict) -> None:
214
+ def run_from_json_file(
215
+ cls,
216
+ file_path: Union[str, Path],
217
+ neo4j_session: neo4j.Session,
218
+ parameters: Dict,
219
+ ) -> None:
198
220
  """
199
221
  Run a job from a JSON file. This will deserialize the job and execute all statements sequentially.
200
222
  """
@@ -207,14 +229,21 @@ class GraphJob:
207
229
  job.run(neo4j_session)
208
230
 
209
231
 
210
- def _get_statements_from_json(blob: Dict, short_job_name: Optional[str] = None) -> List[GraphStatement]:
232
+ def _get_statements_from_json(
233
+ blob: Dict,
234
+ short_job_name: Optional[str] = None,
235
+ ) -> List[GraphStatement]:
211
236
  """
212
237
  Deserialize all statements from the JSON blob.
213
238
  """
214
239
  statements: List[GraphStatement] = []
215
240
  for i, statement_data in enumerate(blob["statements"]):
216
241
  # i+1 to make it 1-based and not 0-based to help with log readability
217
- statement: GraphStatement = GraphStatement.create_from_json(statement_data, short_job_name, i + 1)
242
+ statement: GraphStatement = GraphStatement.create_from_json(
243
+ statement_data,
244
+ short_job_name,
245
+ i + 1,
246
+ )
218
247
  statements.append(statement)
219
248
 
220
249
  return statements