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
@@ -1,4 +1,5 @@
1
1
  import logging
2
+ from copy import deepcopy
2
3
  from typing import Any
3
4
  from typing import Dict
4
5
  from typing import List
@@ -6,10 +7,14 @@ from typing import Tuple
6
7
 
7
8
  import neo4j
8
9
 
10
+ from cartography.client.core.tx import load
11
+ from cartography.graph.job import GraphJob
9
12
  from cartography.intel.github.util import fetch_all
13
+ from cartography.models.github.orgs import GitHubOrganizationSchema
14
+ from cartography.models.github.users import GitHubOrganizationUserSchema
15
+ from cartography.models.github.users import GitHubUnaffiliatedUserSchema
10
16
  from cartography.stats import get_stats_client
11
17
  from cartography.util import merge_module_sync_metadata
12
- from cartography.util import run_cleanup_job
13
18
  from cartography.util import timeit
14
19
 
15
20
  logger = logging.getLogger(__name__)
@@ -32,6 +37,7 @@ GITHUB_ORG_USERS_PAGINATED_GRAPHQL = """
32
37
  isSiteAdmin
33
38
  email
34
39
  company
40
+ organizationVerifiedDomainEmails(login: $login)
35
41
  }
36
42
  role
37
43
  }
@@ -44,83 +50,242 @@ GITHUB_ORG_USERS_PAGINATED_GRAPHQL = """
44
50
  }
45
51
  """
46
52
 
53
+ GITHUB_ENTERPRISE_OWNER_USERS_PAGINATED_GRAPHQL = """
54
+ query($login: String!, $cursor: String) {
55
+ organization(login: $login)
56
+ {
57
+ url
58
+ login
59
+ enterpriseOwners(first:100, after: $cursor){
60
+ edges {
61
+ node {
62
+ url
63
+ login
64
+ name
65
+ isSiteAdmin
66
+ email
67
+ company
68
+ organizationVerifiedDomainEmails(login: $login)
69
+ }
70
+ organizationRole
71
+ }
72
+ pageInfo{
73
+ endCursor
74
+ hasNextPage
75
+ }
76
+ }
77
+ }
78
+ }
79
+ """
80
+
47
81
 
48
82
  @timeit
49
- def get(token: str, api_url: str, organization: str) -> Tuple[List[Dict], Dict]:
83
+ def get_users(token: str, api_url: str, organization: str) -> Tuple[List[Dict], Dict]:
50
84
  """
51
85
  Retrieve a list of users from the given GitHub organization as described in
52
86
  https://docs.github.com/en/graphql/reference/objects#organizationmemberedge.
53
87
  :param token: The Github API token as string.
54
88
  :param api_url: The Github v4 API endpoint as string.
55
89
  :param organization: The name of the target Github organization as string.
56
- :return: A 2-tuple containing 1. a list of dicts representing users - see tests.data.github.users.GITHUB_USER_DATA
57
- for shape, and 2. data on the owning GitHub organization - see tests.data.github.users.GITHUB_ORG_DATA for shape.
90
+ :return: A 2-tuple containing
91
+ 1. a list of dicts representing users and
92
+ 2. data on the owning GitHub organization
93
+ see tests.data.github.users.GITHUB_USER_DATA for shape of both
58
94
  """
95
+ logger.info(f"Retrieving users from GitHub organization {organization}")
59
96
  users, org = fetch_all(
60
97
  token,
61
98
  api_url,
62
99
  organization,
63
100
  GITHUB_ORG_USERS_PAGINATED_GRAPHQL,
64
- 'membersWithRole',
101
+ "membersWithRole",
65
102
  )
66
103
  return users.edges, org
67
104
 
68
105
 
106
+ def get_enterprise_owners(
107
+ token: str,
108
+ api_url: str,
109
+ organization: str,
110
+ ) -> Tuple[List[Dict], Dict]:
111
+ """
112
+ Retrieve a list of enterprise owners from the given GitHub organization as described in
113
+ https://docs.github.com/en/graphql/reference/objects#organizationenterpriseowneredge.
114
+ :param token: The Github API token as string.
115
+ :param api_url: The Github v4 API endpoint as string.
116
+ :param organization: The name of the target Github organization as string.
117
+ :return: A 2-tuple containing
118
+ 1. a list of dicts representing users who are enterprise owners
119
+ 3. data on the owning GitHub organization
120
+ see tests.data.github.users.GITHUB_ENTERPRISE_OWNER_DATA for shape
121
+ """
122
+ logger.info(f"Retrieving enterprise owners from GitHub organization {organization}")
123
+ owners, org = fetch_all(
124
+ token,
125
+ api_url,
126
+ organization,
127
+ GITHUB_ENTERPRISE_OWNER_USERS_PAGINATED_GRAPHQL,
128
+ "enterpriseOwners",
129
+ )
130
+ return owners.edges, org
131
+
132
+
133
+ @timeit
134
+ def transform_users(
135
+ user_data: List[Dict],
136
+ owners_data: List[Dict],
137
+ org_data: Dict,
138
+ ) -> Tuple[List[Dict], List[Dict]]:
139
+ """
140
+ Taking raw user and owner data, return two lists of processed user data:
141
+ * organization users aka affiliated users (users directly affiliated with an organization)
142
+ * unaffiliated users (user who, for example, are enterprise owners but not members of the target organization).
143
+
144
+ :param token: The Github API token as string.
145
+ :param api_url: The Github v4 API endpoint as string.
146
+ :param organization: The name of the target Github organization as string.
147
+ :return: A 2-tuple containing
148
+ 1. a list of dicts representing users who are affiliated with the target org
149
+ see tests.data.github.users.GITHUB_USER_DATA for shape
150
+ 2. a list of dicts representing users who are not affiliated (e.g. enterprise owners who are not also in
151
+ the target org) — see tests.data.github.users.GITHUB_ENTERPRISE_OWNER_DATA for shape
152
+ 3. data on the owning GitHub organization
153
+ """
154
+
155
+ users_dict = {}
156
+ for user in user_data:
157
+ # all members get the 'MEMBER_OF' relationship
158
+ processed_user = deepcopy(user["node"])
159
+ # GitHub returns empty strings for email addresses, so we convert them to None
160
+ if "email" in processed_user and not processed_user["email"]:
161
+ processed_user["email"] = None
162
+ processed_user["hasTwoFactorEnabled"] = user["hasTwoFactorEnabled"]
163
+ processed_user["MEMBER_OF"] = org_data["url"]
164
+ # admins get a second relationship expressing them as such
165
+ if user["role"] == "ADMIN":
166
+ processed_user["ADMIN_OF"] = org_data["url"]
167
+ users_dict[processed_user["url"]] = processed_user
168
+
169
+ owners_dict = {}
170
+ for owner in owners_data:
171
+ processed_owner = deepcopy(owner["node"])
172
+ processed_owner["isEnterpriseOwner"] = True
173
+ if owner["organizationRole"] == "UNAFFILIATED":
174
+ processed_owner["UNAFFILIATED"] = org_data["url"]
175
+ else:
176
+ processed_owner["MEMBER_OF"] = org_data["url"]
177
+ owners_dict[processed_owner["url"]] = processed_owner
178
+
179
+ affiliated_users = [] # users affiliated with the target org
180
+ for url, user in users_dict.items():
181
+ user["isEnterpriseOwner"] = url in owners_dict
182
+ affiliated_users.append(user)
183
+
184
+ unaffiliated_users = [] # users not affiliated with the target org
185
+ for url, owner in owners_dict.items():
186
+ if url not in users_dict:
187
+ unaffiliated_users.append(owner)
188
+
189
+ return affiliated_users, unaffiliated_users
190
+
191
+
69
192
  @timeit
70
- def load_organization_users(
71
- neo4j_session: neo4j.Session, user_data: List[Dict], org_data: Dict,
193
+ def load_users(
194
+ neo4j_session: neo4j.Session,
195
+ node_schema: GitHubOrganizationUserSchema | GitHubUnaffiliatedUserSchema,
196
+ user_data: List[Dict],
197
+ org_data: Dict,
72
198
  update_tag: int,
73
199
  ) -> None:
74
- query = """
75
- MERGE (org:GitHubOrganization{id: $OrgUrl})
76
- ON CREATE SET org.firstseen = timestamp()
77
- SET org.username = $OrgLogin,
78
- org.lastupdated = $UpdateTag
79
- WITH org
80
-
81
- UNWIND $UserData as user
82
-
83
- MERGE (u:GitHubUser{id: user.node.url})
84
- ON CREATE SET u.firstseen = timestamp()
85
- SET u.fullname = user.node.name,
86
- u.username = user.node.login,
87
- u.has_2fa_enabled = user.hasTwoFactorEnabled,
88
- u.role = user.role,
89
- u.is_site_admin = user.node.isSiteAdmin,
90
- u.email = user.node.email,
91
- u.company = user.node.company,
92
- u.lastupdated = $UpdateTag
93
-
94
- MERGE (u)-[r:MEMBER_OF]->(org)
95
- ON CREATE SET r.firstseen = timestamp()
96
- SET r.lastupdated = $UpdateTag
97
- """
98
- neo4j_session.run(
99
- query,
100
- OrgUrl=org_data['url'],
101
- OrgLogin=org_data['login'],
102
- UserData=user_data,
103
- UpdateTag=update_tag,
200
+ logger.info(f"Loading {len(user_data)} GitHub users to the graph")
201
+ load(
202
+ neo4j_session,
203
+ node_schema,
204
+ user_data,
205
+ lastupdated=update_tag,
206
+ org_url=org_data["url"],
207
+ )
208
+
209
+
210
+ @timeit
211
+ def load_organization(
212
+ neo4j_session: neo4j.Session,
213
+ node_schema: GitHubOrganizationSchema,
214
+ org_data: List[Dict[str, Any]],
215
+ update_tag: int,
216
+ ) -> None:
217
+ logger.info(f"Loading {len(org_data)} GitHub organization to the graph")
218
+ load(
219
+ neo4j_session,
220
+ node_schema,
221
+ org_data,
222
+ lastupdated=update_tag,
104
223
  )
105
224
 
106
225
 
226
+ @timeit
227
+ def cleanup(
228
+ neo4j_session: neo4j.Session,
229
+ common_job_parameters: dict[str, Any],
230
+ ) -> None:
231
+ logger.info("Cleaning up GitHub users")
232
+ GraphJob.from_node_schema(
233
+ GitHubOrganizationUserSchema(),
234
+ common_job_parameters,
235
+ ).run(neo4j_session)
236
+ GraphJob.from_node_schema(
237
+ GitHubUnaffiliatedUserSchema(),
238
+ common_job_parameters,
239
+ ).run(neo4j_session)
240
+
241
+
107
242
  @timeit
108
243
  def sync(
109
- neo4j_session: neo4j.Session,
110
- common_job_parameters: Dict[str, Any],
111
- github_api_key: str,
112
- github_url: str,
113
- organization: str,
244
+ neo4j_session: neo4j.Session,
245
+ common_job_parameters: Dict,
246
+ github_api_key: str,
247
+ github_url: str,
248
+ organization: str,
114
249
  ) -> None:
115
250
  logger.info("Syncing GitHub users")
116
- user_data, org_data = get(github_api_key, github_url, organization)
117
- load_organization_users(neo4j_session, user_data, org_data, common_job_parameters['UPDATE_TAG'])
118
- run_cleanup_job('github_users_cleanup.json', neo4j_session, common_job_parameters)
251
+ user_data, org_data = get_users(github_api_key, github_url, organization)
252
+ owners_data, org_data = get_enterprise_owners(
253
+ github_api_key,
254
+ github_url,
255
+ organization,
256
+ )
257
+ processed_affiliated_user_data, processed_unaffiliated_user_data = transform_users(
258
+ user_data,
259
+ owners_data,
260
+ org_data,
261
+ )
262
+ load_organization(
263
+ neo4j_session,
264
+ GitHubOrganizationSchema(),
265
+ [org_data],
266
+ common_job_parameters["UPDATE_TAG"],
267
+ )
268
+ load_users(
269
+ neo4j_session,
270
+ GitHubOrganizationUserSchema(),
271
+ processed_affiliated_user_data,
272
+ org_data,
273
+ common_job_parameters["UPDATE_TAG"],
274
+ )
275
+ load_users(
276
+ neo4j_session,
277
+ GitHubUnaffiliatedUserSchema(),
278
+ processed_unaffiliated_user_data,
279
+ org_data,
280
+ common_job_parameters["UPDATE_TAG"],
281
+ )
282
+ cleanup(neo4j_session, common_job_parameters)
283
+
119
284
  merge_module_sync_metadata(
120
285
  neo4j_session,
121
- group_type='GitHubOrganization',
122
- group_id=org_data['url'],
123
- synced_type='GitHubOrganization',
124
- update_tag=common_job_parameters['UPDATE_TAG'],
286
+ group_type="GitHubOrganization",
287
+ group_id=org_data["url"],
288
+ synced_type="GitHubOrganization",
289
+ update_tag=common_job_parameters["UPDATE_TAG"],
125
290
  stat_handler=stat_handler,
126
291
  )
@@ -13,7 +13,6 @@ from typing import Tuple
13
13
 
14
14
  import requests
15
15
 
16
-
17
16
  logger = logging.getLogger(__name__)
18
17
  # Connect and read timeouts of 60 seconds each; see https://requests.readthedocs.io/en/master/user/advanced/#timeouts
19
18
  _TIMEOUT = (60, 60)
@@ -26,25 +25,28 @@ class PaginatedGraphqlData(NamedTuple):
26
25
 
27
26
 
28
27
  def handle_rate_limit_sleep(token: str) -> None:
29
- '''
28
+ """
30
29
  Check the remaining rate limit and sleep if remaining is below threshold
31
30
  :param token: The Github API token as string.
32
- '''
33
- response = requests.get('https://api.github.com/rate_limit', headers={'Authorization': f"token {token}"})
31
+ """
32
+ response = requests.get(
33
+ "https://api.github.com/rate_limit",
34
+ headers={"Authorization": f"token {token}"},
35
+ )
34
36
  response.raise_for_status()
35
37
  response_json = response.json()
36
- rate_limit_obj = response_json['resources']['graphql']
37
- remaining = rate_limit_obj['remaining']
38
+ rate_limit_obj = response_json["resources"]["graphql"]
39
+ remaining = rate_limit_obj["remaining"]
38
40
  threshold = _GRAPHQL_RATE_LIMIT_REMAINING_THRESHOLD
39
41
  if remaining > threshold:
40
42
  return
41
- reset_at = datetime.fromtimestamp(rate_limit_obj['reset'], tz=tz.utc)
43
+ reset_at = datetime.fromtimestamp(rate_limit_obj["reset"], tz=tz.utc)
42
44
  now = datetime.now(tz.utc)
43
45
  # add an extra minute for safety
44
46
  sleep_duration = reset_at - now + timedelta(minutes=1)
45
47
  logger.warning(
46
- f'Github graphql ratelimit has {remaining} remaining and is under threshold {threshold},'
47
- f' sleeping until reset at {reset_at} for {sleep_duration}',
48
+ f"Github graphql ratelimit has {remaining} remaining and is under threshold {threshold},"
49
+ f" sleeping until reset at {reset_at} for {sleep_duration}",
48
50
  )
49
51
  time.sleep(sleep_duration.seconds)
50
52
 
@@ -58,11 +60,11 @@ def call_github_api(query: str, variables: str, token: str, api_url: str) -> Dic
58
60
  :param api_url: the URL to call for the API
59
61
  :return: query results json
60
62
  """
61
- headers = {'Authorization': f"token {token}"}
63
+ headers = {"Authorization": f"token {token}"}
62
64
  try:
63
65
  response = requests.post(
64
66
  api_url,
65
- json={'query': query, 'variables': variables},
67
+ json={"query": query, "variables": variables},
66
68
  headers=headers,
67
69
  timeout=_TIMEOUT,
68
70
  )
@@ -75,7 +77,7 @@ def call_github_api(query: str, variables: str, token: str, api_url: str) -> Dic
75
77
  if "errors" in response_json:
76
78
  logger.warning(
77
79
  f'call_github_api() response has errors, please investigate. Raw response: {response_json["errors"]}; '
78
- f'continuing sync.',
80
+ f"continuing sync.",
79
81
  )
80
82
  return response_json # type: ignore
81
83
 
@@ -101,8 +103,8 @@ def fetch_page(
101
103
  """
102
104
  gql_vars = {
103
105
  **kwargs,
104
- 'login': organization,
105
- 'cursor': cursor,
106
+ "login": organization,
107
+ "cursor": cursor,
106
108
  }
107
109
  gql_vars_json = json.dumps(gql_vars)
108
110
  response = call_github_api(query, gql_vars_json, token, api_url)
@@ -110,14 +112,14 @@ def fetch_page(
110
112
 
111
113
 
112
114
  def fetch_all(
113
- token: str,
114
- api_url: str,
115
- organization: str,
116
- query: str,
117
- resource_type: str,
118
- retries: int = 5,
119
- resource_inner_type: Optional[str] = None,
120
- **kwargs: Any,
115
+ token: str,
116
+ api_url: str,
117
+ organization: str,
118
+ query: str,
119
+ resource_type: str,
120
+ retries: int = 5,
121
+ resource_inner_type: Optional[str] = None,
122
+ **kwargs: Any,
121
123
  ) -> Tuple[PaginatedGraphqlData, Dict[str, Any]]:
122
124
  """
123
125
  Fetch and return all data items of the given `resource_type` and `field_name` from Github's paginated GraphQL API as
@@ -155,6 +157,18 @@ def fetch_all(
155
157
  retry += 1
156
158
  exc = err
157
159
  except requests.exceptions.HTTPError as err:
160
+ if (
161
+ err.response is not None
162
+ and err.response.status_code == 502
163
+ and kwargs.get("count")
164
+ and kwargs["count"] > 1
165
+ ):
166
+ kwargs["count"] = max(1, kwargs["count"] // 2)
167
+ logger.warning(
168
+ "GitHub: Received 502 response. Reducing page size to %s and retrying.",
169
+ kwargs["count"],
170
+ )
171
+ continue
158
172
  retry += 1
159
173
  exc = err
160
174
  except requests.exceptions.ChunkedEncodingError as err:
@@ -163,37 +177,38 @@ def fetch_all(
163
177
 
164
178
  if retry >= retries:
165
179
  logger.error(
166
- f"GitHub: Could not retrieve page of resource `{resource_type}` due to HTTP error.",
180
+ f"GitHub: Could not retrieve page of resource `{resource_type}` due to HTTP error "
181
+ f"after {retry} retries. Raising exception.",
167
182
  exc_info=True,
168
183
  )
169
184
  raise exc
170
185
  elif retry > 0:
171
- time.sleep(2 ** retry)
186
+ time.sleep(2**retry)
172
187
  continue
173
188
 
174
- if 'data' not in resp:
189
+ if "data" not in resp:
175
190
  logger.warning(
176
191
  f'Got no "data" attribute in response: {resp}. '
177
- f'Stopping requests for organization: {organization} and '
178
- f'resource_type: {resource_type}',
192
+ f"Stopping requests for organization: {organization} and "
193
+ f"resource_type: {resource_type}",
179
194
  )
180
195
  has_next_page = False
181
196
  continue
182
197
 
183
- resource = resp['data']['organization'][resource_type]
198
+ resource = resp["data"]["organization"][resource_type]
184
199
  if resource_inner_type:
185
- resource = resp['data']['organization'][resource_type][resource_inner_type]
200
+ resource = resp["data"]["organization"][resource_type][resource_inner_type]
186
201
 
187
202
  # Allow for paginating both nodes and edges fields of the GitHub GQL structure.
188
- data.nodes.extend(resource.get('nodes', []))
189
- data.edges.extend(resource.get('edges', []))
203
+ data.nodes.extend(resource.get("nodes", []))
204
+ data.edges.extend(resource.get("edges", []))
190
205
 
191
- cursor = resource['pageInfo']['endCursor']
192
- has_next_page = resource['pageInfo']['hasNextPage']
206
+ cursor = resource["pageInfo"]["endCursor"]
207
+ has_next_page = resource["pageInfo"]["hasNextPage"]
193
208
  if not org_data:
194
209
  org_data = {
195
- 'url': resp['data']['organization']['url'],
196
- 'login': resp['data']['organization']['login'],
210
+ "url": resp["data"]["organization"]["url"],
211
+ "login": resp["data"]["organization"]["login"],
197
212
  }
198
213
 
199
214
  if not org_data:
@@ -0,0 +1,193 @@
1
+ import base64
2
+ import json
3
+ import logging
4
+ import os
5
+ from collections import namedtuple
6
+
7
+ import googleapiclient.discovery
8
+ import neo4j
9
+ from google.auth import default
10
+ from google.auth.exceptions import DefaultCredentialsError
11
+ from google.auth.transport.requests import Request
12
+ from google.oauth2 import credentials
13
+ from google.oauth2 import service_account
14
+ from google.oauth2.credentials import Credentials as OAuth2Credentials
15
+ from google.oauth2.service_account import Credentials as ServiceAccountCredentials
16
+
17
+ from cartography.config import Config
18
+ from cartography.intel.googleworkspace import devices
19
+ from cartography.intel.googleworkspace import groups
20
+ from cartography.intel.googleworkspace import oauth_apps
21
+ from cartography.intel.googleworkspace import tenant
22
+ from cartography.intel.googleworkspace import users
23
+ from cartography.util import timeit
24
+
25
+ OAUTH_SCOPES = [
26
+ "https://www.googleapis.com/auth/admin.directory.customer.readonly",
27
+ "https://www.googleapis.com/auth/admin.directory.user.readonly",
28
+ "https://www.googleapis.com/auth/admin.directory.user.security",
29
+ "https://www.googleapis.com/auth/cloud-identity.devices.readonly",
30
+ "https://www.googleapis.com/auth/cloud-identity.groups.readonly",
31
+ ]
32
+
33
+ logger = logging.getLogger(__name__)
34
+
35
+ Resources = namedtuple("Resources", ["admin", "cloudidentity"])
36
+
37
+
38
+ def _initialize_resources(
39
+ creds: OAuth2Credentials | ServiceAccountCredentials,
40
+ ) -> Resources:
41
+ """
42
+ Create namedtuple of all resource objects necessary for Google API data gathering.
43
+ :param credentials: The credentials object
44
+ :return: namedtuple of all resource objects
45
+ """
46
+
47
+ return Resources(
48
+ googleapiclient.discovery.build(
49
+ "admin",
50
+ "directory_v1",
51
+ credentials=creds,
52
+ cache_discovery=False,
53
+ ),
54
+ googleapiclient.discovery.build(
55
+ "cloudidentity",
56
+ "v1",
57
+ credentials=creds,
58
+ cache_discovery=False,
59
+ ),
60
+ )
61
+
62
+
63
+ @timeit
64
+ def start_googleworkspace_ingestion(
65
+ neo4j_session: neo4j.Session, config: Config
66
+ ) -> None:
67
+ """
68
+ Starts the Google Workspace ingestion process by initializing
69
+
70
+ :param neo4j_session: The Neo4j session
71
+ :param config: A `cartography.config` object
72
+ :return: Nothing
73
+ """
74
+ common_job_parameters = {
75
+ "UPDATE_TAG": config.update_tag,
76
+ }
77
+
78
+ creds: OAuth2Credentials | ServiceAccountCredentials
79
+ if config.googleworkspace_auth_method == "delegated": # Legacy delegated method
80
+ if config.googleworkspace_config is None or not os.path.isfile(
81
+ config.googleworkspace_config
82
+ ):
83
+ logger.warning(
84
+ (
85
+ "The Google Workspace config file is not set or is not a valid file."
86
+ "Skipping Google Workspace ingestion."
87
+ ),
88
+ )
89
+ return
90
+ logger.info(
91
+ "Attempting to authenticate to Google Workspace using legacy delegated method"
92
+ )
93
+ try:
94
+ creds = service_account.Credentials.from_service_account_file(
95
+ config.googleworkspace_config,
96
+ scopes=OAUTH_SCOPES,
97
+ )
98
+ creds = creds.with_subject(os.environ.get("GOOGLE_DELEGATED_ADMIN"))
99
+
100
+ except DefaultCredentialsError as e:
101
+ logger.error(
102
+ (
103
+ "Unable to initialize Google Workspace creds. If you don't have Google Workspace data or don't want to load "
104
+ "Google Workspace data then you can ignore this message. Otherwise, the error code is: %s "
105
+ "Make sure your Google Workspace credentials file (if any) is valid. "
106
+ "For more details see documentation."
107
+ ),
108
+ e,
109
+ )
110
+ return
111
+ elif config.googleworkspace_auth_method == "oauth":
112
+ auth_tokens = json.loads(
113
+ str(base64.b64decode(config.googleworkspace_config).decode())
114
+ )
115
+ logger.info("Attempting to authenticate to Google Workspace using OAuth")
116
+ try:
117
+ creds = credentials.Credentials(
118
+ token=None,
119
+ client_id=auth_tokens["client_id"],
120
+ client_secret=auth_tokens["client_secret"],
121
+ refresh_token=auth_tokens["refresh_token"],
122
+ expiry=None,
123
+ token_uri=auth_tokens["token_uri"],
124
+ scopes=OAUTH_SCOPES,
125
+ )
126
+ creds.refresh(Request())
127
+ except DefaultCredentialsError as e:
128
+ logger.error(
129
+ (
130
+ "Unable to initialize Google Workspace creds. If you don't have Google Workspace data or don't want to load "
131
+ "Google Workspace data then you can ignore this message. Otherwise, the error code is: %s "
132
+ "Make sure your Google Workspace credentials are configured correctly, your credentials are valid. "
133
+ "For more details see documentation."
134
+ ),
135
+ e,
136
+ )
137
+ return
138
+ elif config.googleworkspace_auth_method == "default":
139
+ logger.info(
140
+ "Attempting to authenticate to Google Workspace using default credentials"
141
+ )
142
+ try:
143
+ creds, _ = default(scopes=OAUTH_SCOPES)
144
+ except DefaultCredentialsError as e:
145
+ logger.error(
146
+ (
147
+ "Unable to initialize Google Workspace creds using default credentials. If you don't have Google Workspace data or "
148
+ "don't want to load Google Workspace data then you can ignore this message. Otherwise, the error code is: %s "
149
+ "Make sure you have valid application default credentials configured. "
150
+ "For more details see documentation."
151
+ ),
152
+ e,
153
+ )
154
+ return
155
+
156
+ resources = _initialize_resources(creds)
157
+ customer_id = tenant.sync_googleworkspace_tenant(
158
+ neo4j_session,
159
+ resources.admin,
160
+ config.update_tag,
161
+ common_job_parameters,
162
+ )
163
+ common_job_parameters["CUSTOMER_ID"] = customer_id
164
+
165
+ # Sync users and get the list of transformed users for OAuth token sync
166
+ user_ids = users.sync_googleworkspace_users(
167
+ neo4j_session,
168
+ resources.admin,
169
+ config.update_tag,
170
+ common_job_parameters,
171
+ )
172
+
173
+ # Sync OAuth apps for all users
174
+ oauth_apps.sync_googleworkspace_oauth_apps(
175
+ neo4j_session,
176
+ resources.admin,
177
+ user_ids,
178
+ config.update_tag,
179
+ common_job_parameters,
180
+ )
181
+
182
+ groups.sync_googleworkspace_groups(
183
+ neo4j_session,
184
+ resources.cloudidentity,
185
+ config.update_tag,
186
+ common_job_parameters,
187
+ )
188
+ devices.sync_googleworkspace_devices(
189
+ neo4j_session,
190
+ resources.cloudidentity,
191
+ config.update_tag,
192
+ common_job_parameters,
193
+ )