cartography 0.93.0rc1__py3-none-any.whl → 0.123.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.
Files changed (822) hide show
  1. cartography/__main__.py +1 -2
  2. cartography/_version.py +34 -0
  3. cartography/cli.py +903 -225
  4. cartography/client/aws/__init__.py +19 -0
  5. cartography/client/aws/ecr.py +51 -0
  6. cartography/client/core/tx.py +400 -27
  7. cartography/config.py +215 -10
  8. cartography/data/azure_permission_relationships.yaml +20 -0
  9. cartography/data/gcp_permission_relationships.yaml +21 -0
  10. cartography/data/indexes.cypher +1 -200
  11. cartography/data/jobs/analysis/aws_ec2_asset_exposure.json +17 -2
  12. cartography/data/jobs/analysis/aws_ec2_keypair_analysis.json +2 -2
  13. cartography/data/jobs/analysis/gcp_compute_asset_inet_exposure.json +1 -1
  14. cartography/data/jobs/analysis/keycloak_inheritance.json +30 -0
  15. cartography/data/jobs/cleanup/crowdstrike_import_cleanup.json +0 -5
  16. cartography/data/jobs/cleanup/gcp_compute_vpc_cleanup.json +0 -12
  17. cartography/data/jobs/cleanup/github_repos_cleanup.json +27 -0
  18. cartography/data/jobs/scoped_analysis/aws_ec2_iaminstanceprofile.json +15 -0
  19. cartography/data/jobs/scoped_analysis/semgrep_sca_risk_analysis.json +13 -13
  20. cartography/driftdetect/__main__.py +1 -2
  21. cartography/driftdetect/add_shortcut.py +10 -2
  22. cartography/driftdetect/cli.py +72 -75
  23. cartography/driftdetect/detect_deviations.py +7 -3
  24. cartography/driftdetect/get_states.py +20 -8
  25. cartography/driftdetect/model.py +5 -5
  26. cartography/driftdetect/serializers.py +8 -6
  27. cartography/driftdetect/storage.py +2 -2
  28. cartography/graph/cleanupbuilder.py +255 -35
  29. cartography/graph/job.py +104 -20
  30. cartography/graph/querybuilder.py +689 -91
  31. cartography/graph/statement.py +49 -36
  32. cartography/intel/airbyte/__init__.py +105 -0
  33. cartography/intel/airbyte/connections.py +120 -0
  34. cartography/intel/airbyte/destinations.py +81 -0
  35. cartography/intel/airbyte/organizations.py +59 -0
  36. cartography/intel/airbyte/sources.py +78 -0
  37. cartography/intel/airbyte/tags.py +64 -0
  38. cartography/intel/airbyte/users.py +106 -0
  39. cartography/intel/airbyte/util.py +122 -0
  40. cartography/intel/airbyte/workspaces.py +63 -0
  41. cartography/intel/analysis.py +4 -1
  42. cartography/intel/anthropic/__init__.py +62 -0
  43. cartography/intel/anthropic/apikeys.py +72 -0
  44. cartography/intel/anthropic/users.py +75 -0
  45. cartography/intel/anthropic/util.py +51 -0
  46. cartography/intel/anthropic/workspaces.py +95 -0
  47. cartography/intel/aws/__init__.py +137 -59
  48. cartography/intel/aws/acm.py +124 -0
  49. cartography/intel/aws/apigateway.py +482 -217
  50. cartography/intel/aws/apigatewayv2.py +116 -0
  51. cartography/intel/aws/cloudtrail.py +105 -0
  52. cartography/intel/aws/cloudtrail_management_events.py +962 -0
  53. cartography/intel/aws/cloudwatch.py +239 -0
  54. cartography/intel/aws/codebuild.py +132 -0
  55. cartography/intel/aws/cognito.py +201 -0
  56. cartography/intel/aws/config.py +63 -23
  57. cartography/intel/aws/dynamodb.py +108 -40
  58. cartography/intel/aws/ec2/__init__.py +2 -2
  59. cartography/intel/aws/ec2/auto_scaling_groups.py +254 -189
  60. cartography/intel/aws/ec2/elastic_ip_addresses.py +44 -14
  61. cartography/intel/aws/ec2/images.py +74 -39
  62. cartography/intel/aws/ec2/instances.py +262 -137
  63. cartography/intel/aws/ec2/internet_gateways.py +44 -13
  64. cartography/intel/aws/ec2/key_pairs.py +72 -39
  65. cartography/intel/aws/ec2/launch_templates.py +143 -66
  66. cartography/intel/aws/ec2/load_balancer_v2s.py +119 -45
  67. cartography/intel/aws/ec2/load_balancers.py +165 -147
  68. cartography/intel/aws/ec2/network_acls.py +233 -0
  69. cartography/intel/aws/ec2/network_interfaces.py +150 -87
  70. cartography/intel/aws/ec2/reserved_instances.py +48 -17
  71. cartography/intel/aws/ec2/route_tables.py +327 -0
  72. cartography/intel/aws/ec2/security_groups.py +189 -121
  73. cartography/intel/aws/ec2/snapshots.py +93 -91
  74. cartography/intel/aws/ec2/subnets.py +70 -58
  75. cartography/intel/aws/ec2/tgw.py +111 -39
  76. cartography/intel/aws/ec2/util.py +1 -1
  77. cartography/intel/aws/ec2/volumes.py +69 -41
  78. cartography/intel/aws/ec2/vpc.py +157 -116
  79. cartography/intel/aws/ec2/vpc_peerings.py +317 -121
  80. cartography/intel/aws/ecr.py +336 -93
  81. cartography/intel/aws/ecr_image_layers.py +923 -0
  82. cartography/intel/aws/ecs.py +310 -403
  83. cartography/intel/aws/efs.py +261 -0
  84. cartography/intel/aws/eks.py +55 -29
  85. cartography/intel/aws/elasticache.py +130 -83
  86. cartography/intel/aws/elasticsearch.py +70 -24
  87. cartography/intel/aws/emr.py +61 -23
  88. cartography/intel/aws/eventbridge.py +164 -0
  89. cartography/intel/aws/glue.py +181 -0
  90. cartography/intel/aws/guardduty.py +443 -0
  91. cartography/intel/aws/iam.py +978 -464
  92. cartography/intel/aws/iam_instance_profiles.py +73 -0
  93. cartography/intel/aws/identitycenter.py +847 -0
  94. cartography/intel/aws/inspector.py +330 -133
  95. cartography/intel/aws/kms.py +235 -209
  96. cartography/intel/aws/lambda_function.py +328 -176
  97. cartography/intel/aws/organizations.py +40 -19
  98. cartography/intel/aws/permission_relationships.py +144 -68
  99. cartography/intel/aws/rds.py +467 -412
  100. cartography/intel/aws/redshift.py +116 -50
  101. cartography/intel/aws/resourcegroupstaggingapi.py +198 -82
  102. cartography/intel/aws/resources.py +80 -42
  103. cartography/intel/aws/route53.py +419 -318
  104. cartography/intel/aws/s3.py +489 -96
  105. cartography/intel/aws/s3accountpublicaccessblock.py +157 -0
  106. cartography/intel/aws/secretsmanager.py +217 -40
  107. cartography/intel/aws/securityhub.py +23 -10
  108. cartography/intel/aws/sns.py +226 -0
  109. cartography/intel/aws/sqs.py +74 -96
  110. cartography/intel/aws/ssm.py +142 -33
  111. cartography/intel/aws/util/arns.py +7 -7
  112. cartography/intel/aws/util/common.py +31 -4
  113. cartography/intel/azure/__init__.py +259 -46
  114. cartography/intel/azure/aks.py +175 -0
  115. cartography/intel/azure/app_service.py +105 -0
  116. cartography/intel/azure/compute.py +141 -120
  117. cartography/intel/azure/container_instances.py +95 -0
  118. cartography/intel/azure/cosmosdb.py +706 -519
  119. cartography/intel/azure/data_factory.py +85 -0
  120. cartography/intel/azure/data_factory_dataset.py +128 -0
  121. cartography/intel/azure/data_factory_linked_service.py +119 -0
  122. cartography/intel/azure/data_factory_pipeline.py +142 -0
  123. cartography/intel/azure/data_lake.py +124 -0
  124. cartography/intel/azure/event_grid.py +94 -0
  125. cartography/intel/azure/functions.py +124 -0
  126. cartography/intel/azure/load_balancers.py +263 -0
  127. cartography/intel/azure/logic_apps.py +101 -0
  128. cartography/intel/azure/monitor.py +105 -0
  129. cartography/intel/azure/network.py +467 -0
  130. cartography/intel/azure/permission_relationships.py +466 -0
  131. cartography/intel/azure/rbac.py +309 -0
  132. cartography/intel/azure/resource_groups.py +82 -0
  133. cartography/intel/azure/security_center.py +106 -0
  134. cartography/intel/azure/sql.py +436 -392
  135. cartography/intel/azure/storage.py +467 -335
  136. cartography/intel/azure/subscription.py +49 -55
  137. cartography/intel/azure/tenant.py +46 -28
  138. cartography/intel/azure/util/common.py +13 -0
  139. cartography/intel/azure/util/credentials.py +58 -143
  140. cartography/intel/azure/util/tag.py +41 -0
  141. cartography/intel/bigfix/__init__.py +2 -2
  142. cartography/intel/bigfix/computers.py +93 -65
  143. cartography/intel/cloudflare/__init__.py +74 -0
  144. cartography/intel/cloudflare/accounts.py +57 -0
  145. cartography/intel/cloudflare/dnsrecords.py +64 -0
  146. cartography/intel/cloudflare/members.py +75 -0
  147. cartography/intel/cloudflare/roles.py +65 -0
  148. cartography/intel/cloudflare/zones.py +64 -0
  149. cartography/intel/create_indexes.py +5 -3
  150. cartography/intel/crowdstrike/__init__.py +26 -12
  151. cartography/intel/crowdstrike/endpoints.py +17 -45
  152. cartography/intel/crowdstrike/spotlight.py +13 -5
  153. cartography/intel/cve/__init__.py +91 -26
  154. cartography/intel/cve/feed.py +77 -56
  155. cartography/intel/digitalocean/__init__.py +22 -13
  156. cartography/intel/digitalocean/compute.py +75 -108
  157. cartography/intel/digitalocean/management.py +44 -80
  158. cartography/intel/digitalocean/platform.py +48 -43
  159. cartography/intel/dns.py +41 -12
  160. cartography/intel/duo/__init__.py +21 -16
  161. cartography/intel/duo/api_host.py +14 -9
  162. cartography/intel/duo/endpoints.py +50 -45
  163. cartography/intel/duo/groups.py +18 -14
  164. cartography/intel/duo/phones.py +37 -34
  165. cartography/intel/duo/tokens.py +26 -23
  166. cartography/intel/duo/users.py +54 -50
  167. cartography/intel/duo/web_authn_credentials.py +30 -25
  168. cartography/intel/entra/__init__.py +160 -0
  169. cartography/intel/entra/app_role_assignments.py +284 -0
  170. cartography/intel/entra/applications.py +182 -0
  171. cartography/intel/entra/federation/__init__.py +0 -0
  172. cartography/intel/entra/federation/aws_identity_center.py +77 -0
  173. cartography/intel/entra/groups.py +198 -0
  174. cartography/intel/entra/ou.py +136 -0
  175. cartography/intel/entra/service_principals.py +217 -0
  176. cartography/intel/entra/users.py +259 -0
  177. cartography/intel/gcp/__init__.py +381 -175
  178. cartography/intel/gcp/bigtable_app_profile.py +101 -0
  179. cartography/intel/gcp/bigtable_backup.py +91 -0
  180. cartography/intel/gcp/bigtable_cluster.py +93 -0
  181. cartography/intel/gcp/bigtable_instance.py +86 -0
  182. cartography/intel/gcp/bigtable_table.py +87 -0
  183. cartography/intel/gcp/cai.py +292 -0
  184. cartography/intel/gcp/clients.py +112 -0
  185. cartography/intel/gcp/compute.py +521 -325
  186. cartography/intel/gcp/crm/__init__.py +0 -0
  187. cartography/intel/gcp/crm/folders.py +114 -0
  188. cartography/intel/gcp/crm/orgs.py +70 -0
  189. cartography/intel/gcp/crm/projects.py +120 -0
  190. cartography/intel/gcp/dns.py +134 -179
  191. cartography/intel/gcp/gke.py +100 -107
  192. cartography/intel/gcp/iam.py +262 -0
  193. cartography/intel/gcp/permission_relationships.py +394 -0
  194. cartography/intel/gcp/policy_bindings.py +225 -0
  195. cartography/intel/gcp/storage.py +103 -158
  196. cartography/intel/github/__init__.py +66 -27
  197. cartography/intel/github/commits.py +423 -0
  198. cartography/intel/github/repos.py +871 -160
  199. cartography/intel/github/teams.py +386 -53
  200. cartography/intel/github/users.py +214 -49
  201. cartography/intel/github/util.py +50 -35
  202. cartography/intel/googleworkspace/__init__.py +193 -0
  203. cartography/intel/googleworkspace/devices.py +254 -0
  204. cartography/intel/googleworkspace/groups.py +568 -0
  205. cartography/intel/googleworkspace/oauth_apps.py +259 -0
  206. cartography/intel/googleworkspace/tenant.py +85 -0
  207. cartography/intel/googleworkspace/users.py +138 -0
  208. cartography/intel/gsuite/__init__.py +101 -42
  209. cartography/intel/gsuite/groups.py +291 -0
  210. cartography/intel/gsuite/users.py +142 -0
  211. cartography/intel/jamf/__init__.py +19 -1
  212. cartography/intel/jamf/computers.py +37 -8
  213. cartography/intel/jamf/util.py +7 -2
  214. cartography/intel/kandji/__init__.py +6 -3
  215. cartography/intel/kandji/devices.py +40 -10
  216. cartography/intel/keycloak/__init__.py +153 -0
  217. cartography/intel/keycloak/authenticationexecutions.py +322 -0
  218. cartography/intel/keycloak/authenticationflows.py +77 -0
  219. cartography/intel/keycloak/clients.py +187 -0
  220. cartography/intel/keycloak/groups.py +126 -0
  221. cartography/intel/keycloak/identityproviders.py +94 -0
  222. cartography/intel/keycloak/organizations.py +163 -0
  223. cartography/intel/keycloak/realms.py +61 -0
  224. cartography/intel/keycloak/roles.py +202 -0
  225. cartography/intel/keycloak/scopes.py +73 -0
  226. cartography/intel/keycloak/users.py +70 -0
  227. cartography/intel/keycloak/util.py +47 -0
  228. cartography/intel/kubernetes/__init__.py +60 -14
  229. cartography/intel/kubernetes/clusters.py +86 -0
  230. cartography/intel/kubernetes/eks.py +402 -0
  231. cartography/intel/kubernetes/namespaces.py +60 -55
  232. cartography/intel/kubernetes/pods.py +171 -75
  233. cartography/intel/kubernetes/rbac.py +597 -0
  234. cartography/intel/kubernetes/secrets.py +95 -45
  235. cartography/intel/kubernetes/services.py +131 -63
  236. cartography/intel/kubernetes/util.py +142 -14
  237. cartography/intel/lastpass/__init__.py +2 -2
  238. cartography/intel/lastpass/users.py +23 -12
  239. cartography/intel/oci/__init__.py +44 -11
  240. cartography/intel/oci/iam.py +157 -47
  241. cartography/intel/oci/organizations.py +16 -7
  242. cartography/intel/oci/utils.py +71 -25
  243. cartography/intel/okta/__init__.py +66 -15
  244. cartography/intel/okta/applications.py +57 -25
  245. cartography/intel/okta/awssaml.py +105 -41
  246. cartography/intel/okta/factors.py +19 -5
  247. cartography/intel/okta/groups.py +61 -31
  248. cartography/intel/okta/organization.py +8 -2
  249. cartography/intel/okta/origins.py +9 -3
  250. cartography/intel/okta/roles.py +20 -7
  251. cartography/intel/okta/users.py +31 -10
  252. cartography/intel/okta/utils.py +6 -4
  253. cartography/intel/ontology/__init__.py +44 -0
  254. cartography/intel/ontology/devices.py +54 -0
  255. cartography/intel/ontology/users.py +54 -0
  256. cartography/intel/ontology/utils.py +176 -0
  257. cartography/intel/openai/__init__.py +86 -0
  258. cartography/intel/openai/adminapikeys.py +89 -0
  259. cartography/intel/openai/apikeys.py +96 -0
  260. cartography/intel/openai/projects.py +97 -0
  261. cartography/intel/openai/serviceaccounts.py +82 -0
  262. cartography/intel/openai/users.py +75 -0
  263. cartography/intel/openai/util.py +45 -0
  264. cartography/intel/pagerduty/__init__.py +8 -7
  265. cartography/intel/pagerduty/escalation_policies.py +31 -12
  266. cartography/intel/pagerduty/schedules.py +21 -8
  267. cartography/intel/pagerduty/services.py +18 -7
  268. cartography/intel/pagerduty/teams.py +13 -5
  269. cartography/intel/pagerduty/users.py +6 -2
  270. cartography/intel/pagerduty/vendors.py +6 -2
  271. cartography/intel/scaleway/__init__.py +127 -0
  272. cartography/intel/scaleway/iam/__init__.py +0 -0
  273. cartography/intel/scaleway/iam/apikeys.py +71 -0
  274. cartography/intel/scaleway/iam/applications.py +71 -0
  275. cartography/intel/scaleway/iam/groups.py +71 -0
  276. cartography/intel/scaleway/iam/users.py +71 -0
  277. cartography/intel/scaleway/instances/__init__.py +0 -0
  278. cartography/intel/scaleway/instances/flexibleips.py +86 -0
  279. cartography/intel/scaleway/instances/instances.py +92 -0
  280. cartography/intel/scaleway/projects.py +79 -0
  281. cartography/intel/scaleway/storage/__init__.py +0 -0
  282. cartography/intel/scaleway/storage/snapshots.py +86 -0
  283. cartography/intel/scaleway/storage/volumes.py +84 -0
  284. cartography/intel/scaleway/utils.py +37 -0
  285. cartography/intel/semgrep/__init__.py +30 -5
  286. cartography/intel/semgrep/dependencies.py +255 -0
  287. cartography/intel/semgrep/deployment.py +69 -0
  288. cartography/intel/semgrep/findings.py +157 -117
  289. cartography/intel/sentinelone/__init__.py +75 -0
  290. cartography/intel/sentinelone/account.py +140 -0
  291. cartography/intel/sentinelone/agent.py +139 -0
  292. cartography/intel/sentinelone/api.py +124 -0
  293. cartography/intel/sentinelone/application.py +248 -0
  294. cartography/intel/sentinelone/cve.py +119 -0
  295. cartography/intel/sentinelone/utils.py +28 -0
  296. cartography/intel/slack/__init__.py +78 -0
  297. cartography/intel/slack/channels.py +80 -0
  298. cartography/intel/slack/groups.py +90 -0
  299. cartography/intel/slack/teams.py +65 -0
  300. cartography/intel/slack/users.py +57 -0
  301. cartography/intel/slack/utils.py +29 -0
  302. cartography/intel/snipeit/__init__.py +44 -0
  303. cartography/intel/snipeit/asset.py +80 -0
  304. cartography/intel/snipeit/user.py +78 -0
  305. cartography/intel/snipeit/util.py +40 -0
  306. cartography/intel/spacelift/__init__.py +161 -0
  307. cartography/intel/spacelift/account.py +73 -0
  308. cartography/intel/spacelift/ec2_ownership.py +280 -0
  309. cartography/intel/spacelift/runs.py +463 -0
  310. cartography/intel/spacelift/spaces.py +112 -0
  311. cartography/intel/spacelift/stacks.py +119 -0
  312. cartography/intel/spacelift/util.py +122 -0
  313. cartography/intel/spacelift/workerpools.py +131 -0
  314. cartography/intel/spacelift/workers.py +128 -0
  315. cartography/intel/tailscale/__init__.py +77 -0
  316. cartography/intel/tailscale/acls.py +146 -0
  317. cartography/intel/tailscale/devices.py +127 -0
  318. cartography/intel/tailscale/postureintegrations.py +81 -0
  319. cartography/intel/tailscale/tailnets.py +76 -0
  320. cartography/intel/tailscale/users.py +80 -0
  321. cartography/intel/tailscale/utils.py +132 -0
  322. cartography/intel/trivy/__init__.py +272 -0
  323. cartography/intel/trivy/scanner.py +386 -0
  324. cartography/models/airbyte/__init__.py +0 -0
  325. cartography/models/airbyte/connection.py +138 -0
  326. cartography/models/airbyte/destination.py +75 -0
  327. cartography/models/airbyte/organization.py +19 -0
  328. cartography/models/airbyte/source.py +75 -0
  329. cartography/models/airbyte/stream.py +74 -0
  330. cartography/models/airbyte/tag.py +69 -0
  331. cartography/models/airbyte/user.py +115 -0
  332. cartography/models/airbyte/workspace.py +46 -0
  333. cartography/models/anthropic/__init__.py +0 -0
  334. cartography/models/anthropic/apikey.py +94 -0
  335. cartography/models/anthropic/organization.py +19 -0
  336. cartography/models/anthropic/user.py +52 -0
  337. cartography/models/anthropic/workspace.py +90 -0
  338. cartography/models/aws/acm/__init__.py +0 -0
  339. cartography/models/aws/acm/certificate.py +75 -0
  340. cartography/models/aws/apigateway/__init__.py +0 -0
  341. cartography/models/aws/apigateway/apigateway.py +51 -0
  342. cartography/models/aws/apigateway/apigatewaycertificate.py +72 -0
  343. cartography/models/aws/apigateway/apigatewaydeployment.py +74 -0
  344. cartography/models/aws/apigateway/apigatewayintegration.py +79 -0
  345. cartography/models/aws/apigateway/apigatewaymethod.py +74 -0
  346. cartography/models/aws/apigateway/apigatewayresource.py +70 -0
  347. cartography/models/aws/apigateway/apigatewaystage.py +75 -0
  348. cartography/models/aws/apigatewayv2/__init__.py +0 -0
  349. cartography/models/aws/apigatewayv2/apigatewayv2.py +53 -0
  350. cartography/models/aws/cloudtrail/__init__.py +0 -0
  351. cartography/models/aws/cloudtrail/management_events.py +153 -0
  352. cartography/models/aws/cloudtrail/trail.py +106 -0
  353. cartography/models/aws/cloudwatch/__init__.py +0 -0
  354. cartography/models/aws/cloudwatch/log_metric_filter.py +79 -0
  355. cartography/models/aws/cloudwatch/loggroup.py +52 -0
  356. cartography/models/aws/cloudwatch/metric_alarm.py +53 -0
  357. cartography/models/aws/codebuild/__init__.py +0 -0
  358. cartography/models/aws/codebuild/project.py +49 -0
  359. cartography/models/aws/cognito/__init__.py +0 -0
  360. cartography/models/aws/cognito/identity_pool.py +70 -0
  361. cartography/models/aws/cognito/user_pool.py +47 -0
  362. cartography/models/aws/dynamodb/gsi.py +30 -22
  363. cartography/models/aws/dynamodb/tables.py +27 -17
  364. cartography/models/aws/ec2/auto_scaling_groups.py +224 -0
  365. cartography/models/aws/ec2/images.py +36 -34
  366. cartography/models/aws/ec2/instances.py +85 -38
  367. cartography/models/aws/ec2/keypair.py +59 -0
  368. cartography/models/aws/ec2/keypair_instance.py +76 -0
  369. cartography/models/aws/ec2/launch_configurations.py +59 -0
  370. cartography/models/aws/ec2/launch_template_versions.py +48 -38
  371. cartography/models/aws/ec2/launch_templates.py +21 -17
  372. cartography/models/aws/ec2/load_balancer_listeners.py +72 -0
  373. cartography/models/aws/ec2/load_balancers.py +112 -0
  374. cartography/models/aws/ec2/network_acl_rules.py +106 -0
  375. cartography/models/aws/ec2/network_acls.py +95 -0
  376. cartography/models/aws/ec2/networkinterface_instance.py +52 -39
  377. cartography/models/aws/ec2/networkinterfaces.py +57 -37
  378. cartography/models/aws/ec2/privateip_networkinterface.py +32 -22
  379. cartography/models/aws/ec2/reservations.py +18 -14
  380. cartography/models/aws/ec2/route_table_associations.py +97 -0
  381. cartography/models/aws/ec2/route_tables.py +128 -0
  382. cartography/models/aws/ec2/routes.py +85 -0
  383. cartography/models/aws/ec2/security_group_rules.py +109 -0
  384. cartography/models/aws/ec2/security_groups.py +90 -0
  385. cartography/models/aws/ec2/securitygroup_instance.py +29 -20
  386. cartography/models/aws/ec2/securitygroup_networkinterface.py +24 -15
  387. cartography/models/aws/ec2/snapshots.py +58 -0
  388. cartography/models/aws/ec2/subnet_instance.py +26 -19
  389. cartography/models/aws/ec2/subnet_networkinterface.py +42 -31
  390. cartography/models/aws/ec2/subnets.py +65 -0
  391. cartography/models/aws/ec2/volumes.py +67 -40
  392. cartography/models/aws/ec2/vpc.py +46 -0
  393. cartography/models/aws/ec2/vpc_cidr.py +102 -0
  394. cartography/models/aws/ec2/vpc_peering.py +157 -0
  395. cartography/models/aws/ecr/__init__.py +0 -0
  396. cartography/models/aws/ecr/image.py +146 -0
  397. cartography/models/aws/ecr/image_layer.py +107 -0
  398. cartography/models/aws/ecr/repository.py +72 -0
  399. cartography/models/aws/ecr/repository_image.py +95 -0
  400. cartography/models/aws/ecs/__init__.py +0 -0
  401. cartography/models/aws/ecs/clusters.py +64 -0
  402. cartography/models/aws/ecs/container_definitions.py +93 -0
  403. cartography/models/aws/ecs/container_instances.py +84 -0
  404. cartography/models/aws/ecs/containers.py +101 -0
  405. cartography/models/aws/ecs/services.py +134 -0
  406. cartography/models/aws/ecs/task_definitions.py +135 -0
  407. cartography/models/aws/ecs/tasks.py +134 -0
  408. cartography/models/aws/efs/__init__.py +0 -0
  409. cartography/models/aws/efs/access_point.py +77 -0
  410. cartography/models/aws/efs/file_system.py +60 -0
  411. cartography/models/aws/efs/mount_target.py +79 -0
  412. cartography/models/aws/eks/clusters.py +23 -21
  413. cartography/models/aws/elasticache/__init__.py +0 -0
  414. cartography/models/aws/elasticache/cluster.py +65 -0
  415. cartography/models/aws/elasticache/topic.py +67 -0
  416. cartography/models/aws/emr.py +32 -30
  417. cartography/models/aws/eventbridge/__init__.py +0 -0
  418. cartography/models/aws/eventbridge/rule.py +77 -0
  419. cartography/models/aws/eventbridge/target.py +71 -0
  420. cartography/models/aws/glue/__init__.py +0 -0
  421. cartography/models/aws/glue/connection.py +51 -0
  422. cartography/models/aws/glue/job.py +69 -0
  423. cartography/models/aws/guardduty/__init__.py +1 -0
  424. cartography/models/aws/guardduty/detectors.py +50 -0
  425. cartography/models/aws/guardduty/findings.py +121 -0
  426. cartography/models/aws/iam/__init__.py +0 -0
  427. cartography/models/aws/iam/access_key.py +103 -0
  428. cartography/models/aws/iam/account_role.py +24 -0
  429. cartography/models/aws/iam/federated_principal.py +60 -0
  430. cartography/models/aws/iam/group.py +60 -0
  431. cartography/models/aws/iam/group_membership.py +27 -0
  432. cartography/models/aws/iam/inline_policy.py +78 -0
  433. cartography/models/aws/iam/instanceprofile.py +76 -0
  434. cartography/models/aws/iam/managed_policy.py +51 -0
  435. cartography/models/aws/iam/policy_statement.py +57 -0
  436. cartography/models/aws/iam/role.py +83 -0
  437. cartography/models/aws/iam/root_principal.py +52 -0
  438. cartography/models/aws/iam/service_principal.py +30 -0
  439. cartography/models/aws/iam/sts_assumerole_allow.py +38 -0
  440. cartography/models/aws/iam/user.py +59 -0
  441. cartography/models/aws/identitycenter/__init__.py +0 -0
  442. cartography/models/aws/identitycenter/awsidentitycenter.py +49 -0
  443. cartography/models/aws/identitycenter/awspermissionset.py +162 -0
  444. cartography/models/aws/identitycenter/awssogroup.py +70 -0
  445. cartography/models/aws/identitycenter/awsssouser.py +110 -0
  446. cartography/models/aws/inspector/findings.py +124 -58
  447. cartography/models/aws/inspector/packages.py +18 -42
  448. cartography/models/aws/kms/__init__.py +0 -0
  449. cartography/models/aws/kms/aliases.py +86 -0
  450. cartography/models/aws/kms/grants.py +65 -0
  451. cartography/models/aws/kms/keys.py +88 -0
  452. cartography/models/aws/lambda_function/__init__.py +0 -0
  453. cartography/models/aws/lambda_function/alias.py +74 -0
  454. cartography/models/aws/lambda_function/event_source_mapping.py +88 -0
  455. cartography/models/aws/lambda_function/lambda_function.py +91 -0
  456. cartography/models/aws/lambda_function/layer.py +72 -0
  457. cartography/models/aws/rds/__init__.py +0 -0
  458. cartography/models/aws/rds/cluster.py +91 -0
  459. cartography/models/aws/rds/event_subscription.py +146 -0
  460. cartography/models/aws/rds/instance.py +156 -0
  461. cartography/models/aws/rds/snapshot.py +108 -0
  462. cartography/models/aws/rds/subnet_group.py +101 -0
  463. cartography/models/aws/route53/__init__.py +0 -0
  464. cartography/models/aws/route53/dnsrecord.py +235 -0
  465. cartography/models/aws/route53/nameserver.py +63 -0
  466. cartography/models/aws/route53/subzone.py +40 -0
  467. cartography/models/aws/route53/zone.py +47 -0
  468. cartography/models/aws/s3/__init__.py +0 -0
  469. cartography/models/aws/s3/account_public_access_block.py +51 -0
  470. cartography/models/aws/s3/notification.py +24 -0
  471. cartography/models/aws/secretsmanager/__init__.py +0 -0
  472. cartography/models/aws/secretsmanager/secret.py +106 -0
  473. cartography/models/aws/secretsmanager/secret_version.py +114 -0
  474. cartography/models/aws/sns/__init__.py +0 -0
  475. cartography/models/aws/sns/topic.py +50 -0
  476. cartography/models/aws/sns/topic_subscription.py +74 -0
  477. cartography/models/aws/sqs/__init__.py +0 -0
  478. cartography/models/aws/sqs/queue.py +89 -0
  479. cartography/models/aws/ssm/instance_information.py +51 -39
  480. cartography/models/aws/ssm/instance_patch.py +32 -26
  481. cartography/models/aws/ssm/parameters.py +84 -0
  482. cartography/models/azure/__init__.py +0 -0
  483. cartography/models/azure/aks_cluster.py +54 -0
  484. cartography/models/azure/aks_nodepool.py +54 -0
  485. cartography/models/azure/app_service.py +59 -0
  486. cartography/models/azure/container_instance.py +57 -0
  487. cartography/models/azure/cosmosdb/__init__.py +0 -0
  488. cartography/models/azure/cosmosdb/account.py +77 -0
  489. cartography/models/azure/cosmosdb/accountfailoverpolicy.py +77 -0
  490. cartography/models/azure/cosmosdb/cassandrakeyspace.py +82 -0
  491. cartography/models/azure/cosmosdb/cassandratable.py +81 -0
  492. cartography/models/azure/cosmosdb/corspolicy.py +74 -0
  493. cartography/models/azure/cosmosdb/dblocation.py +120 -0
  494. cartography/models/azure/cosmosdb/mongodbcollection.py +82 -0
  495. cartography/models/azure/cosmosdb/mongodbdatabase.py +78 -0
  496. cartography/models/azure/cosmosdb/privateendpointconnection.py +81 -0
  497. cartography/models/azure/cosmosdb/sqlcontainer.py +88 -0
  498. cartography/models/azure/cosmosdb/sqldatabase.py +78 -0
  499. cartography/models/azure/cosmosdb/tableresource.py +76 -0
  500. cartography/models/azure/cosmosdb/virtualnetworkrule.py +78 -0
  501. cartography/models/azure/data_factory/__init__.py +0 -0
  502. cartography/models/azure/data_factory/data_factory.py +51 -0
  503. cartography/models/azure/data_factory/data_factory_dataset.py +94 -0
  504. cartography/models/azure/data_factory/data_factory_linked_service.py +78 -0
  505. cartography/models/azure/data_factory/data_factory_pipeline.py +93 -0
  506. cartography/models/azure/data_lake_filesystem.py +51 -0
  507. cartography/models/azure/event_grid_topic.py +57 -0
  508. cartography/models/azure/function_app.py +59 -0
  509. cartography/models/azure/load_balancer/__init__.py +0 -0
  510. cartography/models/azure/load_balancer/load_balancer.py +49 -0
  511. cartography/models/azure/load_balancer/load_balancer_backend_pool.py +73 -0
  512. cartography/models/azure/load_balancer/load_balancer_frontend_ip.py +75 -0
  513. cartography/models/azure/load_balancer/load_balancer_inbound_nat_rule.py +78 -0
  514. cartography/models/azure/load_balancer/load_balancer_rule.py +108 -0
  515. cartography/models/azure/logic_apps.py +56 -0
  516. cartography/models/azure/monitor.py +54 -0
  517. cartography/models/azure/network_interface.py +112 -0
  518. cartography/models/azure/network_security_group.py +50 -0
  519. cartography/models/azure/permission_relationships.py +60 -0
  520. cartography/models/azure/principal.py +41 -0
  521. cartography/models/azure/public_ip_address.py +50 -0
  522. cartography/models/azure/rbac.py +268 -0
  523. cartography/models/azure/resource_groups.py +52 -0
  524. cartography/models/azure/security_center.py +50 -0
  525. cartography/models/azure/sql/__init__.py +0 -0
  526. cartography/models/azure/sql/databasethreatdetectionpolicy.py +85 -0
  527. cartography/models/azure/sql/elasticpool.py +77 -0
  528. cartography/models/azure/sql/failovergroup.py +73 -0
  529. cartography/models/azure/sql/recoverabledatabase.py +75 -0
  530. cartography/models/azure/sql/replicationlink.py +81 -0
  531. cartography/models/azure/sql/restorabledroppeddatabase.py +82 -0
  532. cartography/models/azure/sql/restorepoint.py +74 -0
  533. cartography/models/azure/sql/serveradadministrator.py +74 -0
  534. cartography/models/azure/sql/serverdnsalias.py +71 -0
  535. cartography/models/azure/sql/sqldatabase.py +85 -0
  536. cartography/models/azure/sql/sqlserver.py +50 -0
  537. cartography/models/azure/sql/transparentdataencryption.py +76 -0
  538. cartography/models/azure/storage/__init__.py +0 -0
  539. cartography/models/azure/storage/account.py +59 -0
  540. cartography/models/azure/storage/blobcontainer.py +85 -0
  541. cartography/models/azure/storage/blobservice.py +71 -0
  542. cartography/models/azure/storage/fileservice.py +71 -0
  543. cartography/models/azure/storage/fileshare.py +82 -0
  544. cartography/models/azure/storage/queue.py +71 -0
  545. cartography/models/azure/storage/queueservice.py +73 -0
  546. cartography/models/azure/storage/table.py +72 -0
  547. cartography/models/azure/storage/tableservice.py +73 -0
  548. cartography/models/azure/subnet.py +101 -0
  549. cartography/models/azure/subscription.py +47 -0
  550. cartography/models/azure/tags/__init__.py +0 -0
  551. cartography/models/azure/tags/storage_tag.py +40 -0
  552. cartography/models/azure/tags/tag.py +37 -0
  553. cartography/models/azure/tenant.py +17 -0
  554. cartography/models/azure/virtual_network.py +49 -0
  555. cartography/models/azure/vm/__init__.py +0 -0
  556. cartography/models/azure/vm/datadisk.py +80 -0
  557. cartography/models/azure/vm/disk.py +55 -0
  558. cartography/models/azure/vm/snapshot.py +56 -0
  559. cartography/models/azure/vm/virtualmachine.py +59 -0
  560. cartography/models/bigfix/bigfix_computer.py +42 -38
  561. cartography/models/bigfix/bigfix_root.py +3 -3
  562. cartography/models/cloudflare/__init__.py +0 -0
  563. cartography/models/cloudflare/account.py +25 -0
  564. cartography/models/cloudflare/dnsrecord.py +55 -0
  565. cartography/models/cloudflare/member.py +86 -0
  566. cartography/models/cloudflare/role.py +44 -0
  567. cartography/models/cloudflare/zone.py +59 -0
  568. cartography/models/core/common.py +53 -2
  569. cartography/models/core/nodes.py +20 -4
  570. cartography/models/core/relationships.py +58 -6
  571. cartography/models/crowdstrike/__init__.py +0 -0
  572. cartography/models/crowdstrike/hosts.py +51 -0
  573. cartography/models/cve/cve.py +34 -32
  574. cartography/models/cve/cve_feed.py +6 -6
  575. cartography/models/digitalocean/__init__.py +0 -0
  576. cartography/models/digitalocean/account.py +21 -0
  577. cartography/models/digitalocean/droplet.py +58 -0
  578. cartography/models/digitalocean/project.py +48 -0
  579. cartography/models/duo/api_host.py +3 -3
  580. cartography/models/duo/endpoint.py +43 -41
  581. cartography/models/duo/group.py +14 -14
  582. cartography/models/duo/phone.py +27 -27
  583. cartography/models/duo/token.py +16 -16
  584. cartography/models/duo/user.py +50 -44
  585. cartography/models/duo/web_authn_credential.py +27 -19
  586. cartography/models/entra/__init__.py +0 -0
  587. cartography/models/entra/app_role_assignment.py +115 -0
  588. cartography/models/entra/application.py +49 -0
  589. cartography/models/entra/entra_user_to_aws_sso.py +41 -0
  590. cartography/models/entra/group.py +117 -0
  591. cartography/models/entra/ou.py +48 -0
  592. cartography/models/entra/service_principal.py +104 -0
  593. cartography/models/entra/tenant.py +39 -0
  594. cartography/models/entra/user.py +90 -0
  595. cartography/models/gcp/__init__.py +0 -0
  596. cartography/models/gcp/bigtable/__init__.py +0 -0
  597. cartography/models/gcp/bigtable/app_profile.py +94 -0
  598. cartography/models/gcp/bigtable/backup.py +91 -0
  599. cartography/models/gcp/bigtable/cluster.py +73 -0
  600. cartography/models/gcp/bigtable/instance.py +52 -0
  601. cartography/models/gcp/bigtable/table.py +69 -0
  602. cartography/models/gcp/compute/__init__.py +0 -0
  603. cartography/models/gcp/compute/subnet.py +74 -0
  604. cartography/models/gcp/compute/vpc.py +50 -0
  605. cartography/models/gcp/crm/__init__.py +0 -0
  606. cartography/models/gcp/crm/folders.py +98 -0
  607. cartography/models/gcp/crm/organizations.py +21 -0
  608. cartography/models/gcp/crm/projects.py +100 -0
  609. cartography/models/gcp/dns.py +109 -0
  610. cartography/models/gcp/gke.py +69 -0
  611. cartography/models/gcp/iam.py +73 -0
  612. cartography/models/gcp/permission_relationships.py +61 -0
  613. cartography/models/gcp/policy_bindings.py +93 -0
  614. cartography/models/gcp/storage/__init__.py +0 -0
  615. cartography/models/gcp/storage/bucket.py +119 -0
  616. cartography/models/github/commits.py +63 -0
  617. cartography/models/github/dependencies.py +73 -0
  618. cartography/models/github/manifests.py +49 -0
  619. cartography/models/github/orgs.py +27 -0
  620. cartography/models/github/teams.py +74 -22
  621. cartography/models/github/users.py +149 -0
  622. cartography/models/googleworkspace/__init__.py +0 -0
  623. cartography/models/googleworkspace/device.py +132 -0
  624. cartography/models/googleworkspace/group.py +382 -0
  625. cartography/models/googleworkspace/oauth_app.py +124 -0
  626. cartography/models/googleworkspace/tenant.py +30 -0
  627. cartography/models/googleworkspace/user.py +113 -0
  628. cartography/models/gsuite/__init__.py +0 -0
  629. cartography/models/gsuite/group.py +218 -0
  630. cartography/models/gsuite/tenant.py +29 -0
  631. cartography/models/gsuite/user.py +107 -0
  632. cartography/models/kandji/device.py +22 -17
  633. cartography/models/kandji/tenant.py +6 -4
  634. cartography/models/keycloak/__init__.py +0 -0
  635. cartography/models/keycloak/authenticationexecution.py +160 -0
  636. cartography/models/keycloak/authenticationflow.py +54 -0
  637. cartography/models/keycloak/client.py +179 -0
  638. cartography/models/keycloak/group.py +101 -0
  639. cartography/models/keycloak/identityprovider.py +89 -0
  640. cartography/models/keycloak/organization.py +116 -0
  641. cartography/models/keycloak/organizationdomain.py +73 -0
  642. cartography/models/keycloak/realm.py +173 -0
  643. cartography/models/keycloak/role.py +126 -0
  644. cartography/models/keycloak/scope.py +73 -0
  645. cartography/models/keycloak/user.py +55 -0
  646. cartography/models/kubernetes/__init__.py +0 -0
  647. cartography/models/kubernetes/clusterrolebindings.py +138 -0
  648. cartography/models/kubernetes/clusterroles.py +52 -0
  649. cartography/models/kubernetes/clusters.py +26 -0
  650. cartography/models/kubernetes/containers.py +133 -0
  651. cartography/models/kubernetes/groups.py +107 -0
  652. cartography/models/kubernetes/namespaces.py +51 -0
  653. cartography/models/kubernetes/oidc.py +51 -0
  654. cartography/models/kubernetes/pods.py +80 -0
  655. cartography/models/kubernetes/rolebindings.py +159 -0
  656. cartography/models/kubernetes/roles.py +76 -0
  657. cartography/models/kubernetes/secrets.py +79 -0
  658. cartography/models/kubernetes/serviceaccounts.py +77 -0
  659. cartography/models/kubernetes/services.py +108 -0
  660. cartography/models/kubernetes/users.py +105 -0
  661. cartography/models/lastpass/tenant.py +3 -3
  662. cartography/models/lastpass/user.py +36 -28
  663. cartography/models/ontology/__init__.py +0 -0
  664. cartography/models/ontology/device.py +137 -0
  665. cartography/models/ontology/mapping/__init__.py +76 -0
  666. cartography/models/ontology/mapping/data/__init__.py +0 -0
  667. cartography/models/ontology/mapping/data/apikeys.py +93 -0
  668. cartography/models/ontology/mapping/data/computeinstance.py +95 -0
  669. cartography/models/ontology/mapping/data/containers.py +88 -0
  670. cartography/models/ontology/mapping/data/databases.py +182 -0
  671. cartography/models/ontology/mapping/data/devices.py +194 -0
  672. cartography/models/ontology/mapping/data/thirdpartyapps.py +140 -0
  673. cartography/models/ontology/mapping/data/useraccounts.py +416 -0
  674. cartography/models/ontology/mapping/data/users.py +63 -0
  675. cartography/models/ontology/mapping/specs.py +85 -0
  676. cartography/models/ontology/user.py +51 -0
  677. cartography/models/openai/__init__.py +0 -0
  678. cartography/models/openai/adminapikey.py +94 -0
  679. cartography/models/openai/apikey.py +88 -0
  680. cartography/models/openai/organization.py +17 -0
  681. cartography/models/openai/project.py +89 -0
  682. cartography/models/openai/serviceaccount.py +50 -0
  683. cartography/models/openai/user.py +53 -0
  684. cartography/models/scaleway/__init__.py +0 -0
  685. cartography/models/scaleway/iam/__init__.py +0 -0
  686. cartography/models/scaleway/iam/apikey.py +100 -0
  687. cartography/models/scaleway/iam/application.py +52 -0
  688. cartography/models/scaleway/iam/group.py +95 -0
  689. cartography/models/scaleway/iam/user.py +64 -0
  690. cartography/models/scaleway/instance/__init__.py +0 -0
  691. cartography/models/scaleway/instance/flexibleip.py +52 -0
  692. cartography/models/scaleway/instance/instance.py +120 -0
  693. cartography/models/scaleway/organization.py +19 -0
  694. cartography/models/scaleway/project.py +48 -0
  695. cartography/models/scaleway/storage/__init__.py +0 -0
  696. cartography/models/scaleway/storage/snapshot.py +78 -0
  697. cartography/models/scaleway/storage/volume.py +51 -0
  698. cartography/models/semgrep/dependencies.py +102 -0
  699. cartography/models/semgrep/deployment.py +5 -5
  700. cartography/models/semgrep/findings.py +58 -40
  701. cartography/models/semgrep/locations.py +27 -21
  702. cartography/models/sentinelone/__init__.py +1 -0
  703. cartography/models/sentinelone/account.py +40 -0
  704. cartography/models/sentinelone/agent.py +50 -0
  705. cartography/models/sentinelone/application.py +44 -0
  706. cartography/models/sentinelone/application_version.py +96 -0
  707. cartography/models/sentinelone/cve.py +73 -0
  708. cartography/models/slack/__init__.py +0 -0
  709. cartography/models/slack/channels.py +92 -0
  710. cartography/models/slack/group.py +129 -0
  711. cartography/models/slack/team.py +22 -0
  712. cartography/models/slack/user.py +62 -0
  713. cartography/models/snipeit/__init__.py +0 -0
  714. cartography/models/snipeit/asset.py +92 -0
  715. cartography/models/snipeit/tenant.py +19 -0
  716. cartography/models/snipeit/user.py +60 -0
  717. cartography/models/spacelift/__init__.py +0 -0
  718. cartography/models/spacelift/cloudtrailevent.py +120 -0
  719. cartography/models/spacelift/run.py +162 -0
  720. cartography/models/spacelift/space.py +131 -0
  721. cartography/models/spacelift/spaceliftaccount.py +31 -0
  722. cartography/models/spacelift/spaceliftgitcommit.py +157 -0
  723. cartography/models/spacelift/stack.py +96 -0
  724. cartography/models/spacelift/user.py +63 -0
  725. cartography/models/spacelift/worker.py +97 -0
  726. cartography/models/spacelift/workerpool.py +90 -0
  727. cartography/models/tailscale/__init__.py +0 -0
  728. cartography/models/tailscale/device.py +96 -0
  729. cartography/models/tailscale/group.py +86 -0
  730. cartography/models/tailscale/postureintegration.py +58 -0
  731. cartography/models/tailscale/tag.py +102 -0
  732. cartography/models/tailscale/tailnet.py +29 -0
  733. cartography/models/tailscale/user.py +57 -0
  734. cartography/models/trivy/__init__.py +0 -0
  735. cartography/models/trivy/findings.py +66 -0
  736. cartography/models/trivy/fix.py +66 -0
  737. cartography/models/trivy/package.py +71 -0
  738. cartography/rules/README.md +1 -0
  739. cartography/rules/__init__.py +0 -0
  740. cartography/rules/cli.py +261 -0
  741. cartography/rules/data/__init__.py +0 -0
  742. cartography/rules/data/rules/__init__.py +46 -0
  743. cartography/rules/data/rules/cloud_security_product_deactivated.py +49 -0
  744. cartography/rules/data/rules/compute_instance_exposed.py +51 -0
  745. cartography/rules/data/rules/database_instance_exposed.py +53 -0
  746. cartography/rules/data/rules/delegation_boundary_modifiable.py +90 -0
  747. cartography/rules/data/rules/identity_administration_privileges.py +100 -0
  748. cartography/rules/data/rules/inactive_user_active_accounts.py +48 -0
  749. cartography/rules/data/rules/malicious_npm_dependencies_shai_hulud.py +2222 -0
  750. cartography/rules/data/rules/mfa_missing.py +46 -0
  751. cartography/rules/data/rules/object_storage_public.py +100 -0
  752. cartography/rules/data/rules/policy_administration_privileges.py +104 -0
  753. cartography/rules/data/rules/unmanaged_accounts.py +43 -0
  754. cartography/rules/data/rules/workload_identity_admin_capabilities.py +193 -0
  755. cartography/rules/formatters.py +108 -0
  756. cartography/rules/runners.py +216 -0
  757. cartography/rules/spec/__init__.py +0 -0
  758. cartography/rules/spec/model.py +267 -0
  759. cartography/rules/spec/result.py +38 -0
  760. cartography/stats.py +4 -4
  761. cartography/sync.py +137 -31
  762. cartography/util.py +187 -77
  763. cartography-0.123.0.dist-info/METADATA +230 -0
  764. cartography-0.123.0.dist-info/RECORD +856 -0
  765. {cartography-0.93.0rc1.dist-info → cartography-0.123.0.dist-info}/WHEEL +1 -1
  766. {cartography-0.93.0rc1.dist-info → cartography-0.123.0.dist-info}/entry_points.txt +1 -0
  767. {cartography-0.93.0rc1.dist-info → cartography-0.123.0.dist-info/licenses}/LICENSE +1 -1
  768. cartography/data/jobs/analysis/aws_ec2_iaminstance.json +0 -10
  769. cartography/data/jobs/analysis/aws_ec2_iaminstanceprofile.json +0 -10
  770. cartography/data/jobs/cleanup/aws_apigateway_details.json +0 -10
  771. cartography/data/jobs/cleanup/aws_dns_cleanup.json +0 -65
  772. cartography/data/jobs/cleanup/aws_import_account_access_key_cleanup.json +0 -17
  773. cartography/data/jobs/cleanup/aws_import_apigateway_cleanup.json +0 -45
  774. cartography/data/jobs/cleanup/aws_import_ec2_security_groupinfo_cleanup.json +0 -24
  775. cartography/data/jobs/cleanup/aws_import_groups_cleanup.json +0 -13
  776. cartography/data/jobs/cleanup/aws_import_lambda_cleanup.json +0 -50
  777. cartography/data/jobs/cleanup/aws_import_principals_cleanup.json +0 -30
  778. cartography/data/jobs/cleanup/aws_import_rds_clusters_cleanup.json +0 -23
  779. cartography/data/jobs/cleanup/aws_import_rds_instances_cleanup.json +0 -47
  780. cartography/data/jobs/cleanup/aws_import_rds_snapshots_cleanup.json +0 -23
  781. cartography/data/jobs/cleanup/aws_import_roles_cleanup.json +0 -13
  782. cartography/data/jobs/cleanup/aws_import_secrets_cleanup.json +0 -8
  783. cartography/data/jobs/cleanup/aws_import_snapshots_cleanup.json +0 -30
  784. cartography/data/jobs/cleanup/aws_import_users_cleanup.json +0 -8
  785. cartography/data/jobs/cleanup/aws_import_vpc_cleanup.json +0 -23
  786. cartography/data/jobs/cleanup/aws_import_vpc_peering_cleanup.json +0 -45
  787. cartography/data/jobs/cleanup/aws_kms_details.json +0 -10
  788. cartography/data/jobs/cleanup/azure_cosmosdb_cassandra_keyspace_cleanup.json +0 -25
  789. cartography/data/jobs/cleanup/azure_cosmosdb_cors_details.json +0 -15
  790. cartography/data/jobs/cleanup/azure_cosmosdb_mongodb_database_cleanup.json +0 -25
  791. cartography/data/jobs/cleanup/azure_cosmosdb_sql_database_cleanup.json +0 -25
  792. cartography/data/jobs/cleanup/azure_cosmosdb_table_resources_cleanup.json +0 -15
  793. cartography/data/jobs/cleanup/azure_database_account_cleanup.json +0 -85
  794. cartography/data/jobs/cleanup/azure_import_disks_cleanup.json +0 -15
  795. cartography/data/jobs/cleanup/azure_import_snapshots_cleanup.json +0 -15
  796. cartography/data/jobs/cleanup/azure_import_virtual_machines_cleanup.json +0 -25
  797. cartography/data/jobs/cleanup/azure_sql_server_cleanup.json +0 -125
  798. cartography/data/jobs/cleanup/azure_storage_account_cleanup.json +0 -95
  799. cartography/data/jobs/cleanup/azure_subscriptions_cleanup.json +0 -14
  800. cartography/data/jobs/cleanup/azure_tenant_cleanup.json +0 -9
  801. cartography/data/jobs/cleanup/crxcavator_import_cleanup.json +0 -18
  802. cartography/data/jobs/cleanup/gcp_compute_vpc_subnet_cleanup.json +0 -35
  803. cartography/data/jobs/cleanup/gcp_crm_folder_cleanup.json +0 -23
  804. cartography/data/jobs/cleanup/gcp_crm_organization_cleanup.json +0 -17
  805. cartography/data/jobs/cleanup/gcp_crm_project_cleanup.json +0 -23
  806. cartography/data/jobs/cleanup/gcp_dns_cleanup.json +0 -29
  807. cartography/data/jobs/cleanup/gcp_gke_cluster_cleanup.json +0 -17
  808. cartography/data/jobs/cleanup/gcp_storage_bucket_cleanup.json +0 -29
  809. cartography/data/jobs/cleanup/github_users_cleanup.json +0 -23
  810. cartography/data/jobs/cleanup/gsuite_ingest_groups_cleanup.json +0 -23
  811. cartography/data/jobs/cleanup/gsuite_ingest_users_cleanup.json +0 -11
  812. cartography/data/jobs/cleanup/kubernetes_import_cleanup.json +0 -70
  813. cartography/intel/crxcavator/__init__.py +0 -44
  814. cartography/intel/crxcavator/crxcavator.py +0 -329
  815. cartography/intel/gcp/crm.py +0 -302
  816. cartography/intel/gsuite/api.py +0 -284
  817. cartography/models/aws/ec2/keypairs.py +0 -64
  818. cartography-0.93.0rc1.dist-info/METADATA +0 -55
  819. cartography-0.93.0rc1.dist-info/NOTICE +0 -4
  820. cartography-0.93.0rc1.dist-info/RECORD +0 -341
  821. /cartography/data/jobs/{analysis → scoped_analysis}/aws_s3acl_analysis.json +0 -0
  822. {cartography-0.93.0rc1.dist-info → cartography-0.123.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,19 @@
1
+ from typing import List
2
+
3
+ import neo4j
4
+
5
+ from cartography.client.core.tx import read_list_of_values_tx
6
+ from cartography.util import timeit
7
+
8
+
9
+ @timeit
10
+ def list_accounts(neo4j_session: neo4j.Session) -> List[str]:
11
+ """
12
+ :param neo4j_session: The neo4j session object.
13
+ :return: A list of all AWS account IDs in the graph
14
+ """
15
+ # See https://community.neo4j.com/t/extract-list-of-nodes-and-labels-from-path/13665/4
16
+ query = """
17
+ MATCH (a:AWSAccount) RETURN a.id
18
+ """
19
+ return neo4j_session.read_transaction(read_list_of_values_tx, query)
@@ -0,0 +1,51 @@
1
+ from typing import Set
2
+ from typing import Tuple
3
+
4
+ import neo4j
5
+
6
+ from cartography.client.core.tx import read_list_of_tuples_tx
7
+ from cartography.util import timeit
8
+
9
+
10
+ @timeit
11
+ def get_ecr_images(
12
+ neo4j_session: neo4j.Session, aws_account_id: str
13
+ ) -> Set[Tuple[str, str, str, str, str]]:
14
+ """
15
+ Queries the graph for all ECR images and their parent images.
16
+ Returns 5-tuples of ECR repository regions, tags, URIs, names, and binary digests. This is used to identify which
17
+ images to scan.
18
+ :param neo4j_session: The neo4j session object.
19
+ :param aws_account_id: The AWS account ID to get ECR repo data for.
20
+ :return: 5-tuples of repo region, image tag, image URI, repo_name, and image_digest.
21
+ """
22
+ # See https://community.neo4j.com/t/extract-list-of-nodes-and-labels-from-path/13665/4
23
+ query = """
24
+ MATCH (e1:ECRRepositoryImage)<-[:REPO_IMAGE]-(repo:ECRRepository)
25
+ MATCH (repo)<-[:RESOURCE]-(:AWSAccount {id: $AWS_ID})
26
+
27
+ // OPTIONAL traversal of parent hierarchy
28
+ OPTIONAL MATCH path = (e1)-[:PARENT*1..]->(ancestor:ECRRepositoryImage)
29
+ WITH e1,
30
+ CASE
31
+ WHEN path IS NULL THEN [e1]
32
+ ELSE [n IN nodes(path) | n] + [e1]
33
+ END AS repo_img_collection_unflattened
34
+
35
+ // Flatten and dedupe
36
+ UNWIND repo_img_collection_unflattened AS repo_img
37
+ WITH DISTINCT repo_img
38
+
39
+ // Match image metadata
40
+ MATCH (er:ECRRepository)-[:REPO_IMAGE]->(repo_img)-[:IMAGE]->(img:ECRImage)
41
+
42
+ RETURN DISTINCT
43
+ er.region AS region,
44
+ repo_img.tag AS tag,
45
+ repo_img.id AS uri,
46
+ er.name AS repo_name,
47
+ img.digest AS digest
48
+ """
49
+ return neo4j_session.read_transaction(
50
+ read_list_of_tuples_tx, query, AWS_ID=aws_account_id
51
+ )
@@ -1,19 +1,287 @@
1
+ import logging
2
+ import time
3
+ from functools import partial
1
4
  from typing import Any
5
+ from typing import Callable
2
6
  from typing import Dict
3
7
  from typing import List
4
8
  from typing import Optional
5
9
  from typing import Tuple
10
+ from typing import TypeVar
6
11
  from typing import Union
7
12
 
13
+ import backoff
8
14
  import neo4j
15
+ import neo4j.exceptions
9
16
 
10
17
  from cartography.graph.querybuilder import build_create_index_queries
18
+ from cartography.graph.querybuilder import build_create_index_queries_for_matchlink
11
19
  from cartography.graph.querybuilder import build_ingestion_query
20
+ from cartography.graph.querybuilder import build_matchlink_query
12
21
  from cartography.models.core.nodes import CartographyNodeSchema
22
+ from cartography.models.core.relationships import CartographyRelSchema
23
+ from cartography.util import backoff_handler
13
24
  from cartography.util import batch
14
25
 
26
+ logger = logging.getLogger(__name__)
15
27
 
16
- def read_list_of_values_tx(tx: neo4j.Transaction, query: str, **kwargs) -> List[Union[str, int]]:
28
+ T = TypeVar("T")
29
+
30
+ _MAX_NETWORK_RETRIES = 5
31
+ _MAX_ENTITY_NOT_FOUND_RETRIES = 5
32
+ _NETWORK_EXCEPTIONS: tuple[type[BaseException], ...] = (
33
+ ConnectionResetError,
34
+ neo4j.exceptions.ServiceUnavailable,
35
+ neo4j.exceptions.SessionExpired,
36
+ neo4j.exceptions.TransientError,
37
+ )
38
+
39
+
40
+ def _is_retryable_client_error(exc: Exception) -> bool:
41
+ """
42
+ Determine if a ClientError should be retried.
43
+
44
+ EntityNotFound during concurrent write operations is a known transient error in Neo4j
45
+ that occurs due to the database's query execution pipeline design. When multiple threads
46
+ run concurrent MERGE/DELETE operations, one thread can delete an entity that another
47
+ thread has already referenced but hasn't locked yet.
48
+
49
+ Neo4j maintainers explicitly recommend retrying EntityNotFound errors during
50
+ multi-threaded operations, even though the driver classifies it as a non-retryable
51
+ ClientError. See: https://github.com/neo4j/neo4j/issues/6823
52
+
53
+ This is particularly common in Cartography when:
54
+ - Multiple providers sync concurrently (e.g., AWS + GCP + Okta)
55
+ - Large batch sizes (10,000 nodes per transaction) are used
56
+ - Page cache evictions occur under memory pressure (especially in Aura)
57
+ - Concurrent MERGE and DETACH DELETE operations overlap
58
+
59
+ :param exc: The exception to check
60
+ :return: True if this is a retryable ClientError (EntityNotFound), False otherwise
61
+ """
62
+ if not isinstance(exc, neo4j.exceptions.ClientError):
63
+ return False
64
+
65
+ # Only retry EntityNotFound errors - all other ClientErrors are permanent failures
66
+ # Note: exc.code can be None for locally-created errors (per neo4j driver docs)
67
+ code = exc.code
68
+ if code is None:
69
+ return False
70
+ return code == "Neo.ClientError.Statement.EntityNotFound"
71
+
72
+
73
+ def _entity_not_found_backoff_handler(details: Dict) -> None:
74
+ """
75
+ Custom backoff handler that provides enhanced logging for EntityNotFound retries.
76
+
77
+ This handler logs additional context when retrying EntityNotFound errors to help
78
+ diagnose concurrent write issues and page cache pressure in Neo4j.
79
+
80
+ :param details: Backoff details dict containing 'exception', 'wait', 'tries', 'target'
81
+ """
82
+ exc = details.get("exception")
83
+ if isinstance(exc, Exception) and _is_retryable_client_error(exc):
84
+ wait = details.get("wait")
85
+ wait_str = f"{wait:0.1f}" if wait is not None else "unknown"
86
+ tries = details.get("tries", 0)
87
+
88
+ if tries == 1:
89
+ log_msg = (
90
+ f"Encountered EntityNotFound error (attempt 1/{_MAX_ENTITY_NOT_FOUND_RETRIES}). "
91
+ f"This is expected during concurrent write operations. "
92
+ f"Retrying after {wait_str} seconds backoff. "
93
+ f"Function: {details.get('target')}. Error: {details.get('exception')}"
94
+ )
95
+ else:
96
+ log_msg = (
97
+ f"EntityNotFound retry {tries}/{_MAX_ENTITY_NOT_FOUND_RETRIES}. "
98
+ f"Backing off {wait_str} seconds before next attempt. "
99
+ f"Function: {details.get('target')}. Error: {details.get('exception')}"
100
+ )
101
+
102
+ logger.warning(log_msg)
103
+ else:
104
+ # Fall back to standard backoff handler for other errors
105
+ backoff_handler(details)
106
+
107
+
108
+ def _run_with_retry(operation: Callable[[], T], target: str) -> T:
109
+ """
110
+ Execute the supplied callable with retry logic for transient network errors and
111
+ EntityNotFound ClientErrors.
112
+ """
113
+ network_attempts = 0
114
+ entity_attempts = 0
115
+ network_wait = backoff.expo()
116
+ entity_wait = backoff.expo()
117
+
118
+ while True:
119
+ try:
120
+ result = operation()
121
+ # Log success if we recovered from errors
122
+ if network_attempts > 0:
123
+ logger.info(
124
+ f"Successfully recovered from network error after {network_attempts} "
125
+ f"{'retry' if network_attempts == 1 else 'retries'}. Function: {target}"
126
+ )
127
+ if entity_attempts > 0:
128
+ logger.info(
129
+ f"Successfully recovered from EntityNotFound error after {entity_attempts} "
130
+ f"{'retry' if entity_attempts == 1 else 'retries'}. Function: {target}"
131
+ )
132
+ return result
133
+ except _NETWORK_EXCEPTIONS as exc:
134
+ if network_attempts >= _MAX_NETWORK_RETRIES - 1:
135
+ raise
136
+ network_attempts += 1
137
+ wait = next(network_wait)
138
+ if wait is None:
139
+ logger.error(
140
+ f"Unexpected: backoff generator returned None for wait time. "
141
+ f"target={target}, attempts={network_attempts}, exc={exc}"
142
+ )
143
+ wait = 1.0 # Fallback to 1 second wait
144
+ backoff_handler(
145
+ {
146
+ "exception": exc,
147
+ "target": target,
148
+ "tries": network_attempts,
149
+ "wait": wait,
150
+ }
151
+ )
152
+ time.sleep(wait)
153
+ continue
154
+ except neo4j.exceptions.ClientError as exc:
155
+ if not _is_retryable_client_error(exc):
156
+ raise
157
+ if entity_attempts >= _MAX_ENTITY_NOT_FOUND_RETRIES - 1:
158
+ raise
159
+ entity_attempts += 1
160
+ wait = next(entity_wait)
161
+ if wait is None:
162
+ logger.error(
163
+ f"Unexpected: backoff generator returned None for wait time. "
164
+ f"target={target}, attempts={entity_attempts}, exc={exc}"
165
+ )
166
+ wait = 1.0 # Fallback to 1 second wait
167
+ _entity_not_found_backoff_handler(
168
+ {
169
+ "exception": exc,
170
+ "target": target,
171
+ "tries": entity_attempts,
172
+ "wait": wait,
173
+ }
174
+ )
175
+ time.sleep(wait)
176
+ continue
177
+
178
+
179
+ @backoff.on_exception( # type: ignore
180
+ backoff.expo,
181
+ (
182
+ ConnectionResetError,
183
+ neo4j.exceptions.ServiceUnavailable,
184
+ neo4j.exceptions.SessionExpired,
185
+ neo4j.exceptions.TransientError,
186
+ ),
187
+ max_tries=5,
188
+ on_backoff=backoff_handler,
189
+ )
190
+ def _run_index_query_with_retry(neo4j_session: neo4j.Session, query: str) -> None:
191
+ """
192
+ Execute an index creation query with retry logic.
193
+ Index creation requires autocommit transactions and can experience transient errors.
194
+
195
+ Handles the EquivalentSchemaRuleAlreadyExists error that can occur when multiple
196
+ parallel sync operations attempt to create the same index simultaneously. Even though
197
+ we use CREATE INDEX IF NOT EXISTS, Neo4j has a race condition where concurrent
198
+ index creation can fail if another session creates the index between the existence
199
+ check and the actual creation.
200
+ """
201
+ try:
202
+ neo4j_session.run(query)
203
+ except neo4j.exceptions.ClientError as e:
204
+ # EquivalentSchemaRuleAlreadyExists means another parallel sync already created
205
+ # this index, which is the desired end state. Safe to ignore.
206
+ if e.code == "Neo.ClientError.Schema.EquivalentSchemaRuleAlreadyExists":
207
+ logger.debug(
208
+ f"Index already exists (likely created by parallel sync): {query}"
209
+ )
210
+ return
211
+ raise
212
+
213
+
214
+ def execute_write_with_retry(
215
+ neo4j_session: neo4j.Session,
216
+ tx_func: Any,
217
+ *args: Any,
218
+ **kwargs: Any,
219
+ ) -> Any:
220
+ """
221
+ Execute a custom transaction function with retry logic for transient errors.
222
+
223
+ This is a generic wrapper for any custom transaction function that needs retry logic
224
+ for EntityNotFound and other transient errors. Use this when you have complex
225
+ transaction logic that doesn't fit the standard load_graph_data pattern.
226
+
227
+ Example usage:
228
+ def my_custom_tx(tx, data_list, update_tag):
229
+ for item in data_list:
230
+ tx.run(query, **item).consume()
231
+
232
+ execute_write_with_retry(
233
+ neo4j_session,
234
+ my_custom_tx,
235
+ data_list,
236
+ update_tag
237
+ )
238
+
239
+ :param neo4j_session: The Neo4j session
240
+ :param tx_func: The transaction function to execute (takes neo4j.Transaction as first arg)
241
+ :param args: Positional arguments to pass to tx_func
242
+ :param kwargs: Keyword arguments to pass to tx_func
243
+ :return: The return value of tx_func
244
+ """
245
+
246
+ target = getattr(tx_func, "__qualname__", repr(tx_func))
247
+ operation = partial(neo4j_session.execute_write, tx_func, *args, **kwargs)
248
+ return _run_with_retry(operation, target)
249
+
250
+
251
+ def run_write_query(
252
+ neo4j_session: neo4j.Session, query: str, **parameters: Any
253
+ ) -> None:
254
+ """
255
+ Execute a write query inside a managed transaction with retry logic.
256
+
257
+ This function now includes retry logic for:
258
+ - Network errors (ConnectionResetError)
259
+ - Service unavailability (ServiceUnavailable, SessionExpired)
260
+ - Transient database errors (TransientError)
261
+ - EntityNotFound errors during concurrent operations (specific ClientError)
262
+
263
+ Used by intel modules that run manual transactions (e.g., GCP firewalls, AWS resources).
264
+
265
+ :param neo4j_session: The Neo4j session
266
+ :param query: The Cypher query to execute
267
+ :param parameters: Parameters to pass to the query
268
+ :return: None
269
+ """
270
+
271
+ def _run_query_tx(tx: neo4j.Transaction) -> None:
272
+ tx.run(query, **parameters).consume()
273
+
274
+ def _operation() -> None:
275
+ neo4j_session.execute_write(_run_query_tx)
276
+
277
+ _run_with_retry(_operation, _run_query_tx.__qualname__)
278
+
279
+
280
+ def read_list_of_values_tx(
281
+ tx: neo4j.Transaction,
282
+ query: str,
283
+ **kwargs,
284
+ ) -> List[Union[str, int]]:
17
285
  """
18
286
  Runs the given Neo4j query in the given transaction object and returns a list of either str or int. This is intended
19
287
  to be run only with queries that return a list of a single field.
@@ -21,7 +289,7 @@ def read_list_of_values_tx(tx: neo4j.Transaction, query: str, **kwargs) -> List[
21
289
  Example usage:
22
290
  query = "MATCH (a:TestNode) RETURN a.name ORDER BY a.name"
23
291
 
24
- values = neo4j_session.read_transaction(read_list_of_values_tx, query)
292
+ values = neo4j_session.execute_read(read_list_of_values_tx, query)
25
293
 
26
294
  :param tx: A neo4j read transaction object
27
295
  :param query: A neo4j query string that returns a list of single values. For example,
@@ -39,7 +307,11 @@ def read_list_of_values_tx(tx: neo4j.Transaction, query: str, **kwargs) -> List[
39
307
  return values
40
308
 
41
309
 
42
- def read_single_value_tx(tx: neo4j.Transaction, query: str, **kwargs) -> Optional[Union[str, int]]:
310
+ def read_single_value_tx(
311
+ tx: neo4j.Transaction,
312
+ query: str,
313
+ **kwargs,
314
+ ) -> Optional[Union[str, int]]:
43
315
  """
44
316
  Runs the given Neo4j query in the given transaction object and returns a str, int, or None. This is intended to be
45
317
  run only with queries that return a single str, int, or None value.
@@ -70,7 +342,11 @@ def read_single_value_tx(tx: neo4j.Transaction, query: str, **kwargs) -> Optiona
70
342
  return value
71
343
 
72
344
 
73
- def read_list_of_dicts_tx(tx: neo4j.Transaction, query: str, **kwargs) -> List[Dict[str, Any]]:
345
+ def read_list_of_dicts_tx(
346
+ tx: neo4j.Transaction,
347
+ query: str,
348
+ **kwargs,
349
+ ) -> List[Dict[str, Any]]:
74
350
  """
75
351
  Runs the given Neo4j query in the given transaction object and returns the results as a list of dicts.
76
352
 
@@ -92,7 +368,11 @@ def read_list_of_dicts_tx(tx: neo4j.Transaction, query: str, **kwargs) -> List[D
92
368
  return values
93
369
 
94
370
 
95
- def read_list_of_tuples_tx(tx: neo4j.Transaction, query: str, **kwargs) -> List[Tuple[Any, ...]]:
371
+ def read_list_of_tuples_tx(
372
+ tx: neo4j.Transaction,
373
+ query: str,
374
+ **kwargs,
375
+ ) -> List[Tuple[Any, ...]]:
96
376
  """
97
377
  Runs the given Neo4j query in the given transaction object and returns the results as a list of tuples.
98
378
 
@@ -122,7 +402,7 @@ def read_list_of_tuples_tx(tx: neo4j.Transaction, query: str, **kwargs) -> List[
122
402
  return [tuple(val) for val in values]
123
403
 
124
404
 
125
- def read_single_dict_tx(tx: neo4j.Transaction, query: str, **kwargs) -> Dict[str, Any]:
405
+ def read_single_dict_tx(tx: neo4j.Transaction, query: str, **kwargs) -> Any:
126
406
  """
127
407
  Runs the given Neo4j query in the given transaction object and returns the single dict result. This is intended to
128
408
  be run only with queries that return a single dict.
@@ -154,9 +434,9 @@ def read_single_dict_tx(tx: neo4j.Transaction, query: str, **kwargs) -> Dict[str
154
434
 
155
435
 
156
436
  def write_list_of_dicts_tx(
157
- tx: neo4j.Transaction,
158
- query: str,
159
- **kwargs,
437
+ tx: neo4j.Transaction,
438
+ query: str,
439
+ **kwargs,
160
440
  ) -> None:
161
441
  """
162
442
  Writes a list of dicts to Neo4j.
@@ -168,7 +448,7 @@ def write_list_of_dicts_tx(
168
448
  neo4j_driver = neo4j.driver(... args ...)
169
449
  neo4j_session = neo4j_driver.Session(... args ...)
170
450
 
171
- neo4j_session.write_transaction(
451
+ neo4j_session.execute_write(
172
452
  write_list_of_dicts_tx,
173
453
  '''
174
454
  UNWIND $DictList as data
@@ -188,26 +468,43 @@ def write_list_of_dicts_tx(
188
468
  :param kwargs: Keyword args to be supplied to the Neo4j query.
189
469
  :return: None
190
470
  """
191
- tx.run(query, kwargs)
471
+ tx.run(query, kwargs).consume()
192
472
 
193
473
 
194
474
  def load_graph_data(
195
- neo4j_session: neo4j.Session,
196
- query: str,
197
- dict_list: List[Dict[str, Any]],
198
- **kwargs,
475
+ neo4j_session: neo4j.Session,
476
+ query: str,
477
+ dict_list: List[Dict[str, Any]],
478
+ batch_size: int = 10000,
479
+ **kwargs,
199
480
  ) -> None:
200
481
  """
201
- Writes data to the graph.
482
+ Writes data to the graph with retry logic for transient errors.
483
+
484
+ This function handles retries for:
485
+ - Network errors (ConnectionResetError)
486
+ - Service unavailability (ServiceUnavailable, SessionExpired)
487
+ - Transient database errors (TransientError)
488
+ - EntityNotFound errors during concurrent operations (ClientError with specific code)
489
+
490
+ EntityNotFound errors are retried because they commonly occur during concurrent
491
+ write operations when multiple threads access the same node space. This is expected
492
+ behavior in Neo4j's query execution pipeline, not a permanent failure.
493
+
202
494
  :param neo4j_session: The Neo4j session
203
495
  :param query: The Neo4j write query to run. This query is not meant to be handwritten, rather it should be generated
204
496
  with cartography.graph.querybuilder.build_ingestion_query().
205
497
  :param dict_list: The data to load to the graph represented as a list of dicts.
498
+ :param batch_size: The number of items to process per transaction. Defaults to 10000.
206
499
  :param kwargs: Allows additional keyword args to be supplied to the Neo4j query.
207
500
  :return: None
208
501
  """
209
- for data_batch in batch(dict_list, size=10000):
210
- neo4j_session.write_transaction(
502
+ if batch_size <= 0:
503
+ raise ValueError(f"batch_size must be greater than 0, got {batch_size}")
504
+
505
+ for data_batch in batch(dict_list, size=batch_size):
506
+ execute_write_with_retry(
507
+ neo4j_session,
211
508
  write_list_of_dicts_tx,
212
509
  query,
213
510
  DictList=data_batch,
@@ -215,7 +512,10 @@ def load_graph_data(
215
512
  )
216
513
 
217
514
 
218
- def ensure_indexes(neo4j_session: neo4j.Session, node_schema: CartographyNodeSchema) -> None:
515
+ def ensure_indexes(
516
+ neo4j_session: neo4j.Session,
517
+ node_schema: CartographyNodeSchema,
518
+ ) -> None:
219
519
  """
220
520
  Creates indexes if they don't exist for the given CartographyNodeSchema object, as well as for all of the
221
521
  relationships defined on its `other_relationships` and `sub_resource_relationship` fields. This operation is
@@ -229,16 +529,38 @@ def ensure_indexes(neo4j_session: neo4j.Session, node_schema: CartographyNodeSch
229
529
  queries = build_create_index_queries(node_schema)
230
530
 
231
531
  for query in queries:
232
- if not query.startswith('CREATE INDEX IF NOT EXISTS'):
233
- raise ValueError('Query provided to `ensure_indexes()` does not start with "CREATE INDEX IF NOT EXISTS".')
234
- neo4j_session.run(query)
532
+ if not query.startswith("CREATE INDEX IF NOT EXISTS"):
533
+ raise ValueError(
534
+ 'Query provided to `ensure_indexes()` does not start with "CREATE INDEX IF NOT EXISTS".',
535
+ )
536
+ _run_index_query_with_retry(neo4j_session, query)
537
+
538
+
539
+ def ensure_indexes_for_matchlinks(
540
+ neo4j_session: neo4j.Session,
541
+ rel_schema: CartographyRelSchema,
542
+ ) -> None:
543
+ """
544
+ Creates indexes for node fields if they don't exist for the given CartographyRelSchema object.
545
+ This is only used for load_rels() where we match on and connect existing nodes.
546
+ This is not used for CartographyNodeSchema objects.
547
+ """
548
+ queries = build_create_index_queries_for_matchlink(rel_schema)
549
+ logger.debug(f"CREATE INDEX queries for {rel_schema.rel_label}: {queries}")
550
+ for query in queries:
551
+ if not query.startswith("CREATE INDEX IF NOT EXISTS"):
552
+ raise ValueError(
553
+ 'Query provided to `ensure_indexes_for_matchlinks()` does not start with "CREATE INDEX IF NOT EXISTS".',
554
+ )
555
+ _run_index_query_with_retry(neo4j_session, query)
235
556
 
236
557
 
237
558
  def load(
238
- neo4j_session: neo4j.Session,
239
- node_schema: CartographyNodeSchema,
240
- dict_list: List[Dict[str, Any]],
241
- **kwargs,
559
+ neo4j_session: neo4j.Session,
560
+ node_schema: CartographyNodeSchema,
561
+ dict_list: List[Dict[str, Any]],
562
+ batch_size: int = 10000,
563
+ **kwargs,
242
564
  ) -> None:
243
565
  """
244
566
  Main entrypoint for intel modules to write data to the graph. Ensures that indexes exist for the datatypes loaded
@@ -246,9 +568,60 @@ def load(
246
568
  :param neo4j_session: The Neo4j session
247
569
  :param node_schema: The CartographyNodeSchema object to create indexes for and generate a query.
248
570
  :param dict_list: The data to load to the graph represented as a list of dicts.
571
+ :param batch_size: The number of items to process per transaction. Defaults to 10000.
249
572
  :param kwargs: Allows additional keyword args to be supplied to the Neo4j query.
250
573
  :return: None
251
574
  """
575
+ if batch_size <= 0:
576
+ raise ValueError(f"batch_size must be greater than 0, got {batch_size}")
577
+ if len(dict_list) == 0:
578
+ # If there is no data to load, save some time.
579
+ return
252
580
  ensure_indexes(neo4j_session, node_schema)
253
581
  ingestion_query = build_ingestion_query(node_schema)
254
- load_graph_data(neo4j_session, ingestion_query, dict_list, **kwargs)
582
+ load_graph_data(
583
+ neo4j_session, ingestion_query, dict_list, batch_size=batch_size, **kwargs
584
+ )
585
+
586
+
587
+ def load_matchlinks(
588
+ neo4j_session: neo4j.Session,
589
+ rel_schema: CartographyRelSchema,
590
+ dict_list: list[dict[str, Any]],
591
+ batch_size: int = 10000,
592
+ **kwargs,
593
+ ) -> None:
594
+ """
595
+ Main entrypoint for intel modules to write relationships to the graph between two existing nodes.
596
+ :param neo4j_session: The Neo4j session
597
+ :param rel_schema: The CartographyRelSchema object to generate a query.
598
+ :param dict_list: The data to load to the graph represented as a list of dicts. The dicts must contain the source and
599
+ target node ids.
600
+ :param batch_size: The number of items to process per transaction. Defaults to 10000.
601
+ :param kwargs: Allows additional keyword args to be supplied to the Neo4j query.
602
+ :return: None
603
+ """
604
+ if batch_size <= 0:
605
+ raise ValueError(f"batch_size must be greater than 0, got {batch_size}")
606
+ if len(dict_list) == 0:
607
+ # If there is no data to load, save some time.
608
+ return
609
+
610
+ # Validate that required kwargs are provided for cleanup queries
611
+ if "_sub_resource_label" not in kwargs:
612
+ raise ValueError(
613
+ f"Required kwarg '_sub_resource_label' not provided for {rel_schema.rel_label}. "
614
+ "This is needed for cleanup queries."
615
+ )
616
+ if "_sub_resource_id" not in kwargs:
617
+ raise ValueError(
618
+ f"Required kwarg '_sub_resource_id' not provided for {rel_schema.rel_label}. "
619
+ "This is needed for cleanup queries."
620
+ )
621
+
622
+ ensure_indexes_for_matchlinks(neo4j_session, rel_schema)
623
+ matchlink_query = build_matchlink_query(rel_schema)
624
+ logger.debug(f"Matchlink query: {matchlink_query}")
625
+ load_graph_data(
626
+ neo4j_session, matchlink_query, dict_list, batch_size=batch_size, **kwargs
627
+ )