cartography 0.104.0rc2__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 (642) hide show
  1. cartography/_version.py +16 -3
  2. cartography/cli.py +466 -5
  3. cartography/client/aws/__init__.py +19 -0
  4. cartography/client/aws/ecr.py +51 -0
  5. cartography/client/core/tx.py +357 -8
  6. cartography/config.py +153 -0
  7. cartography/data/azure_permission_relationships.yaml +20 -0
  8. cartography/data/gcp_permission_relationships.yaml +21 -0
  9. cartography/data/indexes.cypher +0 -186
  10. cartography/data/jobs/analysis/aws_ec2_keypair_analysis.json +2 -2
  11. cartography/data/jobs/analysis/keycloak_inheritance.json +30 -0
  12. cartography/data/jobs/cleanup/gcp_compute_vpc_cleanup.json +0 -12
  13. cartography/data/jobs/cleanup/github_repos_cleanup.json +2 -0
  14. cartography/driftdetect/cli.py +3 -2
  15. cartography/graph/cleanupbuilder.py +198 -41
  16. cartography/graph/job.py +54 -6
  17. cartography/graph/querybuilder.py +528 -27
  18. cartography/graph/statement.py +5 -1
  19. cartography/intel/airbyte/__init__.py +105 -0
  20. cartography/intel/airbyte/connections.py +120 -0
  21. cartography/intel/airbyte/destinations.py +81 -0
  22. cartography/intel/airbyte/organizations.py +59 -0
  23. cartography/intel/airbyte/sources.py +78 -0
  24. cartography/intel/airbyte/tags.py +64 -0
  25. cartography/intel/airbyte/users.py +106 -0
  26. cartography/intel/airbyte/util.py +122 -0
  27. cartography/intel/airbyte/workspaces.py +63 -0
  28. cartography/intel/aws/__init__.py +24 -9
  29. cartography/intel/aws/acm.py +124 -0
  30. cartography/intel/aws/apigateway.py +253 -22
  31. cartography/intel/aws/apigatewayv2.py +116 -0
  32. cartography/intel/aws/cloudtrail.py +17 -39
  33. cartography/intel/aws/cloudtrail_management_events.py +962 -0
  34. cartography/intel/aws/cloudwatch.py +150 -4
  35. cartography/intel/aws/codebuild.py +132 -0
  36. cartography/intel/aws/cognito.py +201 -0
  37. cartography/intel/aws/config.py +7 -3
  38. cartography/intel/aws/ec2/elastic_ip_addresses.py +3 -1
  39. cartography/intel/aws/ec2/instances.py +25 -1
  40. cartography/intel/aws/ec2/internet_gateways.py +4 -2
  41. cartography/intel/aws/ec2/load_balancer_v2s.py +11 -5
  42. cartography/intel/aws/ec2/network_interfaces.py +5 -1
  43. cartography/intel/aws/ec2/reserved_instances.py +3 -1
  44. cartography/intel/aws/ec2/security_groups.py +140 -122
  45. cartography/intel/aws/ec2/snapshots.py +47 -84
  46. cartography/intel/aws/ec2/subnets.py +37 -63
  47. cartography/intel/aws/ec2/tgw.py +11 -5
  48. cartography/intel/aws/ec2/volumes.py +1 -1
  49. cartography/intel/aws/ec2/vpc.py +140 -124
  50. cartography/intel/aws/ec2/vpc_peerings.py +262 -125
  51. cartography/intel/aws/ecr.py +269 -98
  52. cartography/intel/aws/ecr_image_layers.py +923 -0
  53. cartography/intel/aws/ecs.py +251 -380
  54. cartography/intel/aws/efs.py +179 -11
  55. cartography/intel/aws/elasticache.py +102 -79
  56. cartography/intel/aws/elasticsearch.py +13 -4
  57. cartography/intel/aws/eventbridge.py +164 -0
  58. cartography/intel/aws/glue.py +181 -0
  59. cartography/intel/aws/guardduty.py +443 -0
  60. cartography/intel/aws/iam.py +750 -493
  61. cartography/intel/aws/identitycenter.py +605 -83
  62. cartography/intel/aws/inspector.py +221 -105
  63. cartography/intel/aws/kms.py +173 -201
  64. cartography/intel/aws/lambda_function.py +272 -189
  65. cartography/intel/aws/organizations.py +10 -9
  66. cartography/intel/aws/permission_relationships.py +10 -20
  67. cartography/intel/aws/rds.py +337 -446
  68. cartography/intel/aws/redshift.py +9 -4
  69. cartography/intel/aws/resourcegroupstaggingapi.py +78 -19
  70. cartography/intel/aws/resources.py +18 -0
  71. cartography/intel/aws/route53.py +386 -332
  72. cartography/intel/aws/s3.py +322 -14
  73. cartography/intel/aws/secretsmanager.py +81 -49
  74. cartography/intel/aws/securityhub.py +3 -1
  75. cartography/intel/aws/sns.py +62 -2
  76. cartography/intel/aws/sqs.py +36 -90
  77. cartography/intel/aws/ssm.py +3 -5
  78. cartography/intel/azure/__init__.py +202 -48
  79. cartography/intel/azure/aks.py +175 -0
  80. cartography/intel/azure/app_service.py +105 -0
  81. cartography/intel/azure/compute.py +59 -112
  82. cartography/intel/azure/container_instances.py +95 -0
  83. cartography/intel/azure/cosmosdb.py +222 -361
  84. cartography/intel/azure/data_factory.py +85 -0
  85. cartography/intel/azure/data_factory_dataset.py +128 -0
  86. cartography/intel/azure/data_factory_linked_service.py +119 -0
  87. cartography/intel/azure/data_factory_pipeline.py +142 -0
  88. cartography/intel/azure/data_lake.py +124 -0
  89. cartography/intel/azure/event_grid.py +94 -0
  90. cartography/intel/azure/functions.py +124 -0
  91. cartography/intel/azure/load_balancers.py +263 -0
  92. cartography/intel/azure/logic_apps.py +101 -0
  93. cartography/intel/azure/monitor.py +105 -0
  94. cartography/intel/azure/network.py +467 -0
  95. cartography/intel/azure/permission_relationships.py +466 -0
  96. cartography/intel/azure/rbac.py +309 -0
  97. cartography/intel/azure/resource_groups.py +82 -0
  98. cartography/intel/azure/security_center.py +106 -0
  99. cartography/intel/azure/sql.py +145 -292
  100. cartography/intel/azure/storage.py +185 -262
  101. cartography/intel/azure/subscription.py +21 -43
  102. cartography/intel/azure/tenant.py +39 -30
  103. cartography/intel/azure/util/common.py +13 -0
  104. cartography/intel/azure/util/credentials.py +49 -174
  105. cartography/intel/azure/util/tag.py +41 -0
  106. cartography/intel/create_indexes.py +2 -1
  107. cartography/intel/crowdstrike/spotlight.py +5 -2
  108. cartography/intel/dns.py +5 -2
  109. cartography/intel/entra/__init__.py +100 -1
  110. cartography/intel/entra/app_role_assignments.py +284 -0
  111. cartography/intel/entra/applications.py +182 -0
  112. cartography/intel/entra/federation/__init__.py +0 -0
  113. cartography/intel/entra/federation/aws_identity_center.py +77 -0
  114. cartography/intel/entra/groups.py +198 -0
  115. cartography/intel/entra/ou.py +48 -24
  116. cartography/intel/entra/service_principals.py +217 -0
  117. cartography/intel/entra/users.py +105 -57
  118. cartography/intel/gcp/__init__.py +334 -396
  119. cartography/intel/gcp/bigtable_app_profile.py +101 -0
  120. cartography/intel/gcp/bigtable_backup.py +91 -0
  121. cartography/intel/gcp/bigtable_cluster.py +93 -0
  122. cartography/intel/gcp/bigtable_instance.py +86 -0
  123. cartography/intel/gcp/bigtable_table.py +87 -0
  124. cartography/intel/gcp/cai.py +292 -0
  125. cartography/intel/gcp/clients.py +112 -0
  126. cartography/intel/gcp/compute.py +128 -119
  127. cartography/intel/gcp/crm/__init__.py +0 -0
  128. cartography/intel/gcp/crm/folders.py +114 -0
  129. cartography/intel/gcp/crm/orgs.py +70 -0
  130. cartography/intel/gcp/crm/projects.py +120 -0
  131. cartography/intel/gcp/dns.py +83 -169
  132. cartography/intel/gcp/gke.py +72 -113
  133. cartography/intel/gcp/iam.py +111 -91
  134. cartography/intel/gcp/permission_relationships.py +394 -0
  135. cartography/intel/gcp/policy_bindings.py +225 -0
  136. cartography/intel/gcp/storage.py +75 -159
  137. cartography/intel/github/__init__.py +62 -25
  138. cartography/intel/github/commits.py +423 -0
  139. cartography/intel/github/repos.py +463 -85
  140. cartography/intel/github/teams.py +3 -3
  141. cartography/intel/github/users.py +5 -0
  142. cartography/intel/github/util.py +12 -0
  143. cartography/intel/googleworkspace/__init__.py +193 -0
  144. cartography/intel/googleworkspace/devices.py +254 -0
  145. cartography/intel/googleworkspace/groups.py +568 -0
  146. cartography/intel/googleworkspace/oauth_apps.py +259 -0
  147. cartography/intel/googleworkspace/tenant.py +85 -0
  148. cartography/intel/googleworkspace/users.py +138 -0
  149. cartography/intel/gsuite/__init__.py +17 -9
  150. cartography/intel/gsuite/groups.py +291 -0
  151. cartography/intel/gsuite/users.py +142 -0
  152. cartography/intel/jamf/computers.py +7 -1
  153. cartography/intel/keycloak/__init__.py +153 -0
  154. cartography/intel/keycloak/authenticationexecutions.py +322 -0
  155. cartography/intel/keycloak/authenticationflows.py +77 -0
  156. cartography/intel/keycloak/clients.py +187 -0
  157. cartography/intel/keycloak/groups.py +126 -0
  158. cartography/intel/keycloak/identityproviders.py +94 -0
  159. cartography/intel/keycloak/organizations.py +163 -0
  160. cartography/intel/keycloak/realms.py +61 -0
  161. cartography/intel/keycloak/roles.py +202 -0
  162. cartography/intel/keycloak/scopes.py +73 -0
  163. cartography/intel/keycloak/users.py +70 -0
  164. cartography/intel/keycloak/util.py +47 -0
  165. cartography/intel/kubernetes/__init__.py +60 -14
  166. cartography/intel/kubernetes/clusters.py +86 -0
  167. cartography/intel/kubernetes/eks.py +402 -0
  168. cartography/intel/kubernetes/namespaces.py +59 -57
  169. cartography/intel/kubernetes/pods.py +168 -75
  170. cartography/intel/kubernetes/rbac.py +597 -0
  171. cartography/intel/kubernetes/secrets.py +95 -45
  172. cartography/intel/kubernetes/services.py +131 -67
  173. cartography/intel/kubernetes/util.py +142 -14
  174. cartography/intel/oci/iam.py +23 -9
  175. cartography/intel/oci/organizations.py +3 -1
  176. cartography/intel/oci/utils.py +28 -5
  177. cartography/intel/okta/applications.py +15 -5
  178. cartography/intel/okta/awssaml.py +14 -10
  179. cartography/intel/okta/factors.py +3 -1
  180. cartography/intel/okta/groups.py +5 -2
  181. cartography/intel/okta/organization.py +3 -1
  182. cartography/intel/okta/origins.py +3 -1
  183. cartography/intel/okta/roles.py +5 -2
  184. cartography/intel/okta/users.py +10 -2
  185. cartography/intel/ontology/__init__.py +44 -0
  186. cartography/intel/ontology/devices.py +54 -0
  187. cartography/intel/ontology/users.py +54 -0
  188. cartography/intel/ontology/utils.py +176 -0
  189. cartography/intel/pagerduty/escalation_policies.py +13 -6
  190. cartography/intel/pagerduty/schedules.py +9 -4
  191. cartography/intel/pagerduty/services.py +7 -3
  192. cartography/intel/pagerduty/teams.py +5 -2
  193. cartography/intel/pagerduty/users.py +3 -1
  194. cartography/intel/pagerduty/vendors.py +3 -1
  195. cartography/intel/scaleway/__init__.py +127 -0
  196. cartography/intel/scaleway/iam/__init__.py +0 -0
  197. cartography/intel/scaleway/iam/apikeys.py +71 -0
  198. cartography/intel/scaleway/iam/applications.py +71 -0
  199. cartography/intel/scaleway/iam/groups.py +71 -0
  200. cartography/intel/scaleway/iam/users.py +71 -0
  201. cartography/intel/scaleway/instances/__init__.py +0 -0
  202. cartography/intel/scaleway/instances/flexibleips.py +86 -0
  203. cartography/intel/scaleway/instances/instances.py +92 -0
  204. cartography/intel/scaleway/projects.py +79 -0
  205. cartography/intel/scaleway/storage/__init__.py +0 -0
  206. cartography/intel/scaleway/storage/snapshots.py +86 -0
  207. cartography/intel/scaleway/storage/volumes.py +84 -0
  208. cartography/intel/scaleway/utils.py +37 -0
  209. cartography/intel/sentinelone/__init__.py +75 -0
  210. cartography/intel/sentinelone/account.py +140 -0
  211. cartography/intel/sentinelone/agent.py +139 -0
  212. cartography/intel/sentinelone/api.py +124 -0
  213. cartography/intel/sentinelone/application.py +248 -0
  214. cartography/intel/sentinelone/cve.py +119 -0
  215. cartography/intel/sentinelone/utils.py +28 -0
  216. cartography/intel/slack/__init__.py +78 -0
  217. cartography/intel/slack/channels.py +80 -0
  218. cartography/intel/slack/groups.py +90 -0
  219. cartography/intel/slack/teams.py +65 -0
  220. cartography/intel/slack/users.py +57 -0
  221. cartography/intel/slack/utils.py +29 -0
  222. cartography/intel/spacelift/__init__.py +161 -0
  223. cartography/intel/spacelift/account.py +73 -0
  224. cartography/intel/spacelift/ec2_ownership.py +280 -0
  225. cartography/intel/spacelift/runs.py +463 -0
  226. cartography/intel/spacelift/spaces.py +112 -0
  227. cartography/intel/spacelift/stacks.py +119 -0
  228. cartography/intel/spacelift/util.py +122 -0
  229. cartography/intel/spacelift/workerpools.py +131 -0
  230. cartography/intel/spacelift/workers.py +128 -0
  231. cartography/intel/trivy/__init__.py +272 -0
  232. cartography/intel/trivy/scanner.py +386 -0
  233. cartography/models/airbyte/__init__.py +0 -0
  234. cartography/models/airbyte/connection.py +138 -0
  235. cartography/models/airbyte/destination.py +75 -0
  236. cartography/models/airbyte/organization.py +19 -0
  237. cartography/models/airbyte/source.py +75 -0
  238. cartography/models/airbyte/stream.py +74 -0
  239. cartography/models/airbyte/tag.py +69 -0
  240. cartography/models/airbyte/user.py +115 -0
  241. cartography/models/airbyte/workspace.py +46 -0
  242. cartography/models/anthropic/apikey.py +4 -0
  243. cartography/models/anthropic/user.py +4 -0
  244. cartography/models/aws/acm/__init__.py +0 -0
  245. cartography/models/aws/acm/certificate.py +75 -0
  246. cartography/models/aws/apigateway/__init__.py +0 -0
  247. cartography/models/aws/apigateway/apigatewaydeployment.py +74 -0
  248. cartography/models/aws/apigateway/apigatewayintegration.py +79 -0
  249. cartography/models/aws/apigateway/apigatewaymethod.py +74 -0
  250. cartography/models/aws/apigatewayv2/__init__.py +0 -0
  251. cartography/models/aws/apigatewayv2/apigatewayv2.py +53 -0
  252. cartography/models/aws/cloudtrail/management_events.py +153 -0
  253. cartography/models/aws/cloudtrail/trail.py +45 -0
  254. cartography/models/aws/cloudwatch/log_metric_filter.py +79 -0
  255. cartography/models/aws/cloudwatch/metric_alarm.py +53 -0
  256. cartography/models/aws/codebuild/__init__.py +0 -0
  257. cartography/models/aws/codebuild/project.py +49 -0
  258. cartography/models/aws/cognito/__init__.py +0 -0
  259. cartography/models/aws/cognito/identity_pool.py +70 -0
  260. cartography/models/aws/cognito/user_pool.py +47 -0
  261. cartography/models/aws/dynamodb/tables.py +2 -0
  262. cartography/models/aws/ec2/instances.py +25 -1
  263. cartography/models/aws/ec2/networkinterfaces.py +4 -0
  264. cartography/models/aws/ec2/security_group_rules.py +109 -0
  265. cartography/models/aws/ec2/security_groups.py +90 -0
  266. cartography/models/aws/ec2/snapshots.py +58 -0
  267. cartography/models/aws/ec2/subnet_instance.py +2 -0
  268. cartography/models/aws/ec2/subnet_networkinterface.py +2 -0
  269. cartography/models/aws/ec2/subnets.py +65 -0
  270. cartography/models/aws/ec2/volumes.py +20 -0
  271. cartography/models/aws/ec2/vpc.py +46 -0
  272. cartography/models/aws/ec2/vpc_cidr.py +102 -0
  273. cartography/models/aws/ec2/vpc_peering.py +157 -0
  274. cartography/models/aws/ecr/__init__.py +0 -0
  275. cartography/models/aws/ecr/image.py +146 -0
  276. cartography/models/aws/ecr/image_layer.py +107 -0
  277. cartography/models/aws/ecr/repository.py +72 -0
  278. cartography/models/aws/ecr/repository_image.py +95 -0
  279. cartography/models/aws/ecs/__init__.py +0 -0
  280. cartography/models/aws/ecs/clusters.py +64 -0
  281. cartography/models/aws/ecs/container_definitions.py +93 -0
  282. cartography/models/aws/ecs/container_instances.py +84 -0
  283. cartography/models/aws/ecs/containers.py +101 -0
  284. cartography/models/aws/ecs/services.py +134 -0
  285. cartography/models/aws/ecs/task_definitions.py +135 -0
  286. cartography/models/aws/ecs/tasks.py +134 -0
  287. cartography/models/aws/efs/access_point.py +77 -0
  288. cartography/models/aws/efs/file_system.py +60 -0
  289. cartography/models/aws/efs/mount_target.py +29 -2
  290. cartography/models/aws/elasticache/__init__.py +0 -0
  291. cartography/models/aws/elasticache/cluster.py +65 -0
  292. cartography/models/aws/elasticache/topic.py +67 -0
  293. cartography/models/aws/eventbridge/__init__.py +0 -0
  294. cartography/models/aws/eventbridge/rule.py +77 -0
  295. cartography/models/aws/eventbridge/target.py +71 -0
  296. cartography/models/aws/glue/__init__.py +0 -0
  297. cartography/models/aws/glue/connection.py +51 -0
  298. cartography/models/aws/glue/job.py +69 -0
  299. cartography/models/aws/guardduty/__init__.py +1 -0
  300. cartography/models/aws/guardduty/detectors.py +50 -0
  301. cartography/models/aws/guardduty/findings.py +121 -0
  302. cartography/models/aws/iam/access_key.py +103 -0
  303. cartography/models/aws/iam/account_role.py +24 -0
  304. cartography/models/aws/iam/federated_principal.py +60 -0
  305. cartography/models/aws/iam/group.py +60 -0
  306. cartography/models/aws/iam/group_membership.py +27 -0
  307. cartography/models/aws/iam/inline_policy.py +78 -0
  308. cartography/models/aws/iam/managed_policy.py +51 -0
  309. cartography/models/aws/iam/policy_statement.py +57 -0
  310. cartography/models/aws/iam/role.py +83 -0
  311. cartography/models/aws/iam/root_principal.py +52 -0
  312. cartography/models/aws/iam/service_principal.py +30 -0
  313. cartography/models/aws/iam/sts_assumerole_allow.py +38 -0
  314. cartography/models/aws/iam/user.py +59 -0
  315. cartography/models/aws/identitycenter/awsidentitycenter.py +1 -0
  316. cartography/models/aws/identitycenter/awspermissionset.py +70 -0
  317. cartography/models/aws/identitycenter/awssogroup.py +70 -0
  318. cartography/models/aws/identitycenter/awsssouser.py +49 -9
  319. cartography/models/aws/inspector/findings.py +37 -0
  320. cartography/models/aws/inspector/packages.py +1 -31
  321. cartography/models/aws/kms/__init__.py +0 -0
  322. cartography/models/aws/kms/aliases.py +86 -0
  323. cartography/models/aws/kms/grants.py +65 -0
  324. cartography/models/aws/kms/keys.py +88 -0
  325. cartography/models/aws/lambda_function/__init__.py +0 -0
  326. cartography/models/aws/lambda_function/alias.py +74 -0
  327. cartography/models/aws/lambda_function/event_source_mapping.py +88 -0
  328. cartography/models/aws/lambda_function/lambda_function.py +91 -0
  329. cartography/models/aws/lambda_function/layer.py +72 -0
  330. cartography/models/aws/rds/__init__.py +0 -0
  331. cartography/models/aws/rds/cluster.py +91 -0
  332. cartography/models/aws/rds/event_subscription.py +146 -0
  333. cartography/models/aws/rds/instance.py +156 -0
  334. cartography/models/aws/rds/snapshot.py +108 -0
  335. cartography/models/aws/rds/subnet_group.py +101 -0
  336. cartography/models/aws/route53/__init__.py +0 -0
  337. cartography/models/aws/route53/dnsrecord.py +235 -0
  338. cartography/models/aws/route53/nameserver.py +63 -0
  339. cartography/models/aws/route53/subzone.py +40 -0
  340. cartography/models/aws/route53/zone.py +47 -0
  341. cartography/models/aws/s3/notification.py +24 -0
  342. cartography/models/aws/secretsmanager/secret.py +106 -0
  343. cartography/models/aws/secretsmanager/secret_version.py +0 -2
  344. cartography/models/aws/sns/topic_subscription.py +74 -0
  345. cartography/models/aws/sqs/__init__.py +0 -0
  346. cartography/models/aws/sqs/queue.py +89 -0
  347. cartography/models/azure/__init__.py +0 -0
  348. cartography/models/azure/aks_cluster.py +54 -0
  349. cartography/models/azure/aks_nodepool.py +54 -0
  350. cartography/models/azure/app_service.py +59 -0
  351. cartography/models/azure/container_instance.py +57 -0
  352. cartography/models/azure/cosmosdb/__init__.py +0 -0
  353. cartography/models/azure/cosmosdb/account.py +77 -0
  354. cartography/models/azure/cosmosdb/accountfailoverpolicy.py +77 -0
  355. cartography/models/azure/cosmosdb/cassandrakeyspace.py +82 -0
  356. cartography/models/azure/cosmosdb/cassandratable.py +81 -0
  357. cartography/models/azure/cosmosdb/corspolicy.py +74 -0
  358. cartography/models/azure/cosmosdb/dblocation.py +120 -0
  359. cartography/models/azure/cosmosdb/mongodbcollection.py +82 -0
  360. cartography/models/azure/cosmosdb/mongodbdatabase.py +78 -0
  361. cartography/models/azure/cosmosdb/privateendpointconnection.py +81 -0
  362. cartography/models/azure/cosmosdb/sqlcontainer.py +88 -0
  363. cartography/models/azure/cosmosdb/sqldatabase.py +78 -0
  364. cartography/models/azure/cosmosdb/tableresource.py +76 -0
  365. cartography/models/azure/cosmosdb/virtualnetworkrule.py +78 -0
  366. cartography/models/azure/data_factory/__init__.py +0 -0
  367. cartography/models/azure/data_factory/data_factory.py +51 -0
  368. cartography/models/azure/data_factory/data_factory_dataset.py +94 -0
  369. cartography/models/azure/data_factory/data_factory_linked_service.py +78 -0
  370. cartography/models/azure/data_factory/data_factory_pipeline.py +93 -0
  371. cartography/models/azure/data_lake_filesystem.py +51 -0
  372. cartography/models/azure/event_grid_topic.py +57 -0
  373. cartography/models/azure/function_app.py +59 -0
  374. cartography/models/azure/load_balancer/__init__.py +0 -0
  375. cartography/models/azure/load_balancer/load_balancer.py +49 -0
  376. cartography/models/azure/load_balancer/load_balancer_backend_pool.py +73 -0
  377. cartography/models/azure/load_balancer/load_balancer_frontend_ip.py +75 -0
  378. cartography/models/azure/load_balancer/load_balancer_inbound_nat_rule.py +78 -0
  379. cartography/models/azure/load_balancer/load_balancer_rule.py +108 -0
  380. cartography/models/azure/logic_apps.py +56 -0
  381. cartography/models/azure/monitor.py +54 -0
  382. cartography/models/azure/network_interface.py +112 -0
  383. cartography/models/azure/network_security_group.py +50 -0
  384. cartography/models/azure/permission_relationships.py +60 -0
  385. cartography/models/azure/principal.py +41 -0
  386. cartography/models/azure/public_ip_address.py +50 -0
  387. cartography/models/azure/rbac.py +268 -0
  388. cartography/models/azure/resource_groups.py +52 -0
  389. cartography/models/azure/security_center.py +50 -0
  390. cartography/models/azure/sql/__init__.py +0 -0
  391. cartography/models/azure/sql/databasethreatdetectionpolicy.py +85 -0
  392. cartography/models/azure/sql/elasticpool.py +77 -0
  393. cartography/models/azure/sql/failovergroup.py +73 -0
  394. cartography/models/azure/sql/recoverabledatabase.py +75 -0
  395. cartography/models/azure/sql/replicationlink.py +81 -0
  396. cartography/models/azure/sql/restorabledroppeddatabase.py +82 -0
  397. cartography/models/azure/sql/restorepoint.py +74 -0
  398. cartography/models/azure/sql/serveradadministrator.py +74 -0
  399. cartography/models/azure/sql/serverdnsalias.py +71 -0
  400. cartography/models/azure/sql/sqldatabase.py +85 -0
  401. cartography/models/azure/sql/sqlserver.py +50 -0
  402. cartography/models/azure/sql/transparentdataencryption.py +76 -0
  403. cartography/models/azure/storage/__init__.py +0 -0
  404. cartography/models/azure/storage/account.py +59 -0
  405. cartography/models/azure/storage/blobcontainer.py +85 -0
  406. cartography/models/azure/storage/blobservice.py +71 -0
  407. cartography/models/azure/storage/fileservice.py +71 -0
  408. cartography/models/azure/storage/fileshare.py +82 -0
  409. cartography/models/azure/storage/queue.py +71 -0
  410. cartography/models/azure/storage/queueservice.py +73 -0
  411. cartography/models/azure/storage/table.py +72 -0
  412. cartography/models/azure/storage/tableservice.py +73 -0
  413. cartography/models/azure/subnet.py +101 -0
  414. cartography/models/azure/subscription.py +47 -0
  415. cartography/models/azure/tags/__init__.py +0 -0
  416. cartography/models/azure/tags/storage_tag.py +40 -0
  417. cartography/models/azure/tags/tag.py +37 -0
  418. cartography/models/azure/tenant.py +17 -0
  419. cartography/models/azure/virtual_network.py +49 -0
  420. cartography/models/azure/vm/__init__.py +0 -0
  421. cartography/models/azure/vm/datadisk.py +80 -0
  422. cartography/models/azure/vm/disk.py +55 -0
  423. cartography/models/azure/vm/snapshot.py +56 -0
  424. cartography/models/azure/vm/virtualmachine.py +59 -0
  425. cartography/models/bigfix/bigfix_computer.py +1 -1
  426. cartography/models/cloudflare/member.py +4 -0
  427. cartography/models/core/common.py +1 -0
  428. cartography/models/core/nodes.py +15 -2
  429. cartography/models/core/relationships.py +44 -0
  430. cartography/models/crowdstrike/hosts.py +1 -1
  431. cartography/models/digitalocean/droplet.py +2 -0
  432. cartography/models/duo/endpoint.py +1 -1
  433. cartography/models/duo/phone.py +2 -2
  434. cartography/models/duo/user.py +4 -0
  435. cartography/models/entra/app_role_assignment.py +115 -0
  436. cartography/models/entra/application.py +49 -0
  437. cartography/models/entra/entra_user_to_aws_sso.py +41 -0
  438. cartography/models/entra/group.py +117 -0
  439. cartography/models/entra/service_principal.py +104 -0
  440. cartography/models/entra/user.py +42 -51
  441. cartography/models/gcp/__init__.py +0 -0
  442. cartography/models/gcp/bigtable/__init__.py +0 -0
  443. cartography/models/gcp/bigtable/app_profile.py +94 -0
  444. cartography/models/gcp/bigtable/backup.py +91 -0
  445. cartography/models/gcp/bigtable/cluster.py +73 -0
  446. cartography/models/gcp/bigtable/instance.py +52 -0
  447. cartography/models/gcp/bigtable/table.py +69 -0
  448. cartography/models/gcp/compute/__init__.py +0 -0
  449. cartography/models/gcp/compute/subnet.py +74 -0
  450. cartography/models/gcp/compute/vpc.py +50 -0
  451. cartography/models/gcp/crm/__init__.py +0 -0
  452. cartography/models/gcp/crm/folders.py +98 -0
  453. cartography/models/gcp/crm/organizations.py +21 -0
  454. cartography/models/gcp/crm/projects.py +100 -0
  455. cartography/models/gcp/dns.py +109 -0
  456. cartography/models/gcp/gke.py +69 -0
  457. cartography/models/gcp/iam.py +3 -0
  458. cartography/models/gcp/permission_relationships.py +61 -0
  459. cartography/models/gcp/policy_bindings.py +93 -0
  460. cartography/models/gcp/storage/__init__.py +0 -0
  461. cartography/models/gcp/storage/bucket.py +119 -0
  462. cartography/models/github/commits.py +63 -0
  463. cartography/models/github/dependencies.py +73 -0
  464. cartography/models/github/manifests.py +49 -0
  465. cartography/models/github/users.py +10 -0
  466. cartography/models/googleworkspace/__init__.py +0 -0
  467. cartography/models/googleworkspace/device.py +132 -0
  468. cartography/models/googleworkspace/group.py +382 -0
  469. cartography/models/googleworkspace/oauth_app.py +124 -0
  470. cartography/models/googleworkspace/tenant.py +30 -0
  471. cartography/models/googleworkspace/user.py +113 -0
  472. cartography/models/gsuite/__init__.py +0 -0
  473. cartography/models/gsuite/group.py +218 -0
  474. cartography/models/gsuite/tenant.py +29 -0
  475. cartography/models/gsuite/user.py +107 -0
  476. cartography/models/kandji/device.py +1 -2
  477. cartography/models/keycloak/__init__.py +0 -0
  478. cartography/models/keycloak/authenticationexecution.py +160 -0
  479. cartography/models/keycloak/authenticationflow.py +54 -0
  480. cartography/models/keycloak/client.py +179 -0
  481. cartography/models/keycloak/group.py +101 -0
  482. cartography/models/keycloak/identityprovider.py +89 -0
  483. cartography/models/keycloak/organization.py +116 -0
  484. cartography/models/keycloak/organizationdomain.py +73 -0
  485. cartography/models/keycloak/realm.py +173 -0
  486. cartography/models/keycloak/role.py +126 -0
  487. cartography/models/keycloak/scope.py +73 -0
  488. cartography/models/keycloak/user.py +55 -0
  489. cartography/models/kubernetes/__init__.py +0 -0
  490. cartography/models/kubernetes/clusterrolebindings.py +138 -0
  491. cartography/models/kubernetes/clusterroles.py +52 -0
  492. cartography/models/kubernetes/clusters.py +26 -0
  493. cartography/models/kubernetes/containers.py +133 -0
  494. cartography/models/kubernetes/groups.py +107 -0
  495. cartography/models/kubernetes/namespaces.py +51 -0
  496. cartography/models/kubernetes/oidc.py +51 -0
  497. cartography/models/kubernetes/pods.py +80 -0
  498. cartography/models/kubernetes/rolebindings.py +159 -0
  499. cartography/models/kubernetes/roles.py +76 -0
  500. cartography/models/kubernetes/secrets.py +79 -0
  501. cartography/models/kubernetes/serviceaccounts.py +77 -0
  502. cartography/models/kubernetes/services.py +108 -0
  503. cartography/models/kubernetes/users.py +105 -0
  504. cartography/models/lastpass/user.py +4 -0
  505. cartography/models/ontology/__init__.py +0 -0
  506. cartography/models/ontology/device.py +137 -0
  507. cartography/models/ontology/mapping/__init__.py +76 -0
  508. cartography/models/ontology/mapping/data/__init__.py +0 -0
  509. cartography/models/ontology/mapping/data/apikeys.py +93 -0
  510. cartography/models/ontology/mapping/data/computeinstance.py +95 -0
  511. cartography/models/ontology/mapping/data/containers.py +88 -0
  512. cartography/models/ontology/mapping/data/databases.py +182 -0
  513. cartography/models/ontology/mapping/data/devices.py +194 -0
  514. cartography/models/ontology/mapping/data/thirdpartyapps.py +140 -0
  515. cartography/models/ontology/mapping/data/useraccounts.py +416 -0
  516. cartography/models/ontology/mapping/data/users.py +63 -0
  517. cartography/models/ontology/mapping/specs.py +85 -0
  518. cartography/models/ontology/user.py +51 -0
  519. cartography/models/openai/adminapikey.py +4 -0
  520. cartography/models/openai/apikey.py +4 -0
  521. cartography/models/openai/user.py +4 -0
  522. cartography/models/scaleway/__init__.py +0 -0
  523. cartography/models/scaleway/iam/__init__.py +0 -0
  524. cartography/models/scaleway/iam/apikey.py +100 -0
  525. cartography/models/scaleway/iam/application.py +52 -0
  526. cartography/models/scaleway/iam/group.py +95 -0
  527. cartography/models/scaleway/iam/user.py +64 -0
  528. cartography/models/scaleway/instance/__init__.py +0 -0
  529. cartography/models/scaleway/instance/flexibleip.py +52 -0
  530. cartography/models/scaleway/instance/instance.py +120 -0
  531. cartography/models/scaleway/organization.py +19 -0
  532. cartography/models/scaleway/project.py +48 -0
  533. cartography/models/scaleway/storage/__init__.py +0 -0
  534. cartography/models/scaleway/storage/snapshot.py +78 -0
  535. cartography/models/scaleway/storage/volume.py +51 -0
  536. cartography/models/sentinelone/__init__.py +1 -0
  537. cartography/models/sentinelone/account.py +40 -0
  538. cartography/models/sentinelone/agent.py +50 -0
  539. cartography/models/sentinelone/application.py +44 -0
  540. cartography/models/sentinelone/application_version.py +96 -0
  541. cartography/models/sentinelone/cve.py +73 -0
  542. cartography/models/slack/__init__.py +0 -0
  543. cartography/models/slack/channels.py +92 -0
  544. cartography/models/slack/group.py +129 -0
  545. cartography/models/slack/team.py +22 -0
  546. cartography/models/slack/user.py +62 -0
  547. cartography/models/snipeit/asset.py +2 -0
  548. cartography/models/snipeit/user.py +4 -0
  549. cartography/models/spacelift/__init__.py +0 -0
  550. cartography/models/spacelift/cloudtrailevent.py +120 -0
  551. cartography/models/spacelift/run.py +162 -0
  552. cartography/models/spacelift/space.py +131 -0
  553. cartography/models/spacelift/spaceliftaccount.py +31 -0
  554. cartography/models/spacelift/spaceliftgitcommit.py +157 -0
  555. cartography/models/spacelift/stack.py +96 -0
  556. cartography/models/spacelift/user.py +63 -0
  557. cartography/models/spacelift/worker.py +97 -0
  558. cartography/models/spacelift/workerpool.py +90 -0
  559. cartography/models/tailscale/device.py +2 -1
  560. cartography/models/tailscale/user.py +6 -1
  561. cartography/models/trivy/__init__.py +0 -0
  562. cartography/models/trivy/findings.py +66 -0
  563. cartography/models/trivy/fix.py +66 -0
  564. cartography/models/trivy/package.py +71 -0
  565. cartography/rules/README.md +1 -0
  566. cartography/rules/__init__.py +0 -0
  567. cartography/rules/cli.py +261 -0
  568. cartography/rules/data/__init__.py +0 -0
  569. cartography/rules/data/rules/__init__.py +46 -0
  570. cartography/rules/data/rules/cloud_security_product_deactivated.py +49 -0
  571. cartography/rules/data/rules/compute_instance_exposed.py +51 -0
  572. cartography/rules/data/rules/database_instance_exposed.py +53 -0
  573. cartography/rules/data/rules/delegation_boundary_modifiable.py +90 -0
  574. cartography/rules/data/rules/identity_administration_privileges.py +100 -0
  575. cartography/rules/data/rules/inactive_user_active_accounts.py +48 -0
  576. cartography/rules/data/rules/malicious_npm_dependencies_shai_hulud.py +2222 -0
  577. cartography/rules/data/rules/mfa_missing.py +46 -0
  578. cartography/rules/data/rules/object_storage_public.py +100 -0
  579. cartography/rules/data/rules/policy_administration_privileges.py +104 -0
  580. cartography/rules/data/rules/unmanaged_accounts.py +43 -0
  581. cartography/rules/data/rules/workload_identity_admin_capabilities.py +193 -0
  582. cartography/rules/formatters.py +108 -0
  583. cartography/rules/runners.py +216 -0
  584. cartography/rules/spec/__init__.py +0 -0
  585. cartography/rules/spec/model.py +267 -0
  586. cartography/rules/spec/result.py +38 -0
  587. cartography/sync.py +25 -5
  588. cartography/util.py +101 -31
  589. {cartography-0.104.0rc2.dist-info → cartography-0.123.0.dist-info}/METADATA +61 -22
  590. cartography-0.123.0.dist-info/RECORD +856 -0
  591. {cartography-0.104.0rc2.dist-info → cartography-0.123.0.dist-info}/entry_points.txt +1 -0
  592. cartography/data/jobs/cleanup/aws_dns_cleanup.json +0 -65
  593. cartography/data/jobs/cleanup/aws_import_account_access_key_cleanup.json +0 -17
  594. cartography/data/jobs/cleanup/aws_import_ec2_security_groupinfo_cleanup.json +0 -24
  595. cartography/data/jobs/cleanup/aws_import_groups_cleanup.json +0 -13
  596. cartography/data/jobs/cleanup/aws_import_identity_center_cleanup.json +0 -16
  597. cartography/data/jobs/cleanup/aws_import_lambda_cleanup.json +0 -50
  598. cartography/data/jobs/cleanup/aws_import_principals_cleanup.json +0 -30
  599. cartography/data/jobs/cleanup/aws_import_rds_clusters_cleanup.json +0 -23
  600. cartography/data/jobs/cleanup/aws_import_rds_instances_cleanup.json +0 -47
  601. cartography/data/jobs/cleanup/aws_import_rds_snapshots_cleanup.json +0 -23
  602. cartography/data/jobs/cleanup/aws_import_roles_cleanup.json +0 -13
  603. cartography/data/jobs/cleanup/aws_import_secrets_cleanup.json +0 -8
  604. cartography/data/jobs/cleanup/aws_import_snapshots_cleanup.json +0 -30
  605. cartography/data/jobs/cleanup/aws_import_users_cleanup.json +0 -8
  606. cartography/data/jobs/cleanup/aws_import_vpc_cleanup.json +0 -23
  607. cartography/data/jobs/cleanup/aws_import_vpc_peering_cleanup.json +0 -45
  608. cartography/data/jobs/cleanup/aws_kms_details.json +0 -10
  609. cartography/data/jobs/cleanup/azure_cosmosdb_cassandra_keyspace_cleanup.json +0 -25
  610. cartography/data/jobs/cleanup/azure_cosmosdb_cors_details.json +0 -15
  611. cartography/data/jobs/cleanup/azure_cosmosdb_mongodb_database_cleanup.json +0 -25
  612. cartography/data/jobs/cleanup/azure_cosmosdb_sql_database_cleanup.json +0 -25
  613. cartography/data/jobs/cleanup/azure_cosmosdb_table_resources_cleanup.json +0 -15
  614. cartography/data/jobs/cleanup/azure_database_account_cleanup.json +0 -85
  615. cartography/data/jobs/cleanup/azure_import_disks_cleanup.json +0 -15
  616. cartography/data/jobs/cleanup/azure_import_snapshots_cleanup.json +0 -15
  617. cartography/data/jobs/cleanup/azure_import_virtual_machines_cleanup.json +0 -25
  618. cartography/data/jobs/cleanup/azure_sql_server_cleanup.json +0 -125
  619. cartography/data/jobs/cleanup/azure_storage_account_cleanup.json +0 -95
  620. cartography/data/jobs/cleanup/azure_subscriptions_cleanup.json +0 -14
  621. cartography/data/jobs/cleanup/azure_tenant_cleanup.json +0 -9
  622. cartography/data/jobs/cleanup/gcp_compute_vpc_subnet_cleanup.json +0 -35
  623. cartography/data/jobs/cleanup/gcp_crm_folder_cleanup.json +0 -23
  624. cartography/data/jobs/cleanup/gcp_crm_organization_cleanup.json +0 -17
  625. cartography/data/jobs/cleanup/gcp_crm_project_cleanup.json +0 -23
  626. cartography/data/jobs/cleanup/gcp_dns_cleanup.json +0 -29
  627. cartography/data/jobs/cleanup/gcp_gke_cluster_cleanup.json +0 -17
  628. cartography/data/jobs/cleanup/gcp_storage_bucket_cleanup.json +0 -29
  629. cartography/data/jobs/cleanup/gsuite_ingest_groups_cleanup.json +0 -23
  630. cartography/data/jobs/cleanup/gsuite_ingest_users_cleanup.json +0 -11
  631. cartography/data/jobs/cleanup/kubernetes_import_cleanup.json +0 -70
  632. cartography/intel/gcp/crm.py +0 -355
  633. cartography/intel/gsuite/api.py +0 -342
  634. cartography-0.104.0rc2.dist-info/RECORD +0 -455
  635. /cartography/data/jobs/{analysis → scoped_analysis}/aws_s3acl_analysis.json +0 -0
  636. /cartography/models/aws/{apigateway.py → apigateway/apigateway.py} +0 -0
  637. /cartography/models/aws/{apigatewaycertificate.py → apigateway/apigatewaycertificate.py} +0 -0
  638. /cartography/models/aws/{apigatewayresource.py → apigateway/apigatewayresource.py} +0 -0
  639. /cartography/models/aws/{apigatewaystage.py → apigateway/apigatewaystage.py} +0 -0
  640. {cartography-0.104.0rc2.dist-info → cartography-0.123.0.dist-info}/WHEEL +0 -0
  641. {cartography-0.104.0rc2.dist-info → cartography-0.123.0.dist-info}/licenses/LICENSE +0 -0
  642. {cartography-0.104.0rc2.dist-info → cartography-0.123.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,259 @@
1
+ import logging
2
+ from typing import Any
3
+
4
+ import neo4j
5
+ from googleapiclient.discovery import Resource
6
+ from googleapiclient.errors import HttpError
7
+
8
+ from cartography.client.core.tx import load
9
+ from cartography.client.core.tx import load_matchlinks
10
+ from cartography.graph.job import GraphJob
11
+ from cartography.models.googleworkspace.oauth_app import GoogleWorkspaceOAuthAppSchema
12
+ from cartography.models.googleworkspace.oauth_app import (
13
+ GoogleWorkspaceUserToOAuthAppRel,
14
+ )
15
+ from cartography.util import timeit
16
+
17
+ logger = logging.getLogger(__name__)
18
+
19
+ GOOGLE_API_NUM_RETRIES = 5
20
+
21
+
22
+ @timeit
23
+ def get_oauth_tokens_for_user(admin: Resource, user_id: str) -> list[dict]:
24
+ """
25
+ Get OAuth tokens for a specific user
26
+ https://developers.google.com/workspace/admin/directory/reference/rest/v1/tokens/list
27
+
28
+ :param admin: apiclient discovery resource object
29
+ :param user_id: User's ID
30
+ :return: list of OAuth tokens for the user
31
+ """
32
+ try:
33
+ request = admin.tokens().list(userKey=user_id)
34
+ resp = request.execute(num_retries=GOOGLE_API_NUM_RETRIES)
35
+ tokens = resp.get("items", [])
36
+
37
+ # Add user_id to each token for relationship mapping
38
+ for token in tokens:
39
+ token["user_id"] = user_id
40
+
41
+ return tokens
42
+ except HttpError as e:
43
+ if (
44
+ e.resp.status == 403
45
+ and "Request had insufficient authentication scopes" in str(e)
46
+ ):
47
+ logger.error(
48
+ "Missing required Google Workspace scopes. If using the gcloud CLI, "
49
+ "run: gcloud auth application-default login --scopes="
50
+ "https://www.googleapis.com/auth/admin.directory.customer.readonly,"
51
+ "https://www.googleapis.com/auth/admin.directory.user.readonly,"
52
+ "https://www.googleapis.com/auth/admin.directory.user.security,"
53
+ "https://www.googleapis.com/auth/cloud-identity.devices.readonly,"
54
+ "https://www.googleapis.com/auth/cloud-identity.groups.readonly,"
55
+ "https://www.googleapis.com/auth/cloud-platform"
56
+ )
57
+ elif e.resp.status == 404:
58
+ # User has no OAuth tokens, this is normal
59
+ return []
60
+ else:
61
+ logger.warning(f"Error fetching OAuth tokens for user: {e}")
62
+ return []
63
+
64
+
65
+ @timeit
66
+ def get_all_oauth_tokens(admin: Resource, user_ids: list[str]) -> list[dict]:
67
+ """
68
+ Get OAuth tokens for all users in the organization
69
+
70
+ :param admin: apiclient discovery resource object
71
+ :param user_ids: List of user IDs
72
+ :return: list of all OAuth tokens across all users
73
+ """
74
+ all_tokens = []
75
+
76
+ for user_id in user_ids:
77
+ tokens = get_oauth_tokens_for_user(admin, user_id)
78
+ all_tokens.extend(tokens)
79
+
80
+ logger.debug(f"Retrieved {len(all_tokens)} OAuth tokens for {len(user_ids)} users")
81
+ return all_tokens
82
+
83
+
84
+ @timeit
85
+ def transform_oauth_apps_and_authorizations(
86
+ tokens: list[dict],
87
+ ) -> tuple[list[dict[str, Any]], list[dict[str, Any]]]:
88
+ """
89
+ Transform OAuth token objects to create app nodes and user authorization relationships
90
+
91
+ :param tokens: Raw API response token objects
92
+ :return: tuple of (apps, authorizations)
93
+ - apps: list of unique OAuth app dictionaries
94
+ - authorizations: list of user->app authorization relationships with scopes
95
+ """
96
+ # Group tokens by client_id to create unique apps
97
+ apps_map: dict[str, dict[str, Any]] = {}
98
+ authorizations: list[dict[str, Any]] = []
99
+
100
+ for token in tokens:
101
+ client_id = token.get("clientId")
102
+ user_id = token.get("user_id")
103
+ scopes = token.get("scopes", [])
104
+
105
+ if not client_id or not user_id:
106
+ logger.warning("Skipping token due to missing client_id or user_id")
107
+ continue
108
+
109
+ # Create or update app entry
110
+ if client_id not in apps_map:
111
+ apps_map[client_id] = {
112
+ "client_id": client_id,
113
+ "display_text": token.get("displayText"),
114
+ "anonymous": token.get("anonymous", False),
115
+ "native_app": token.get("nativeApp", False),
116
+ }
117
+
118
+ # Create authorization relationship
119
+ authorizations.append(
120
+ {
121
+ "user_id": user_id,
122
+ "client_id": client_id,
123
+ "scopes": scopes,
124
+ }
125
+ )
126
+
127
+ apps = list(apps_map.values())
128
+ logger.info(
129
+ f"Transformed {len(apps)} unique OAuth apps with {len(authorizations)} authorizations"
130
+ )
131
+ return apps, authorizations
132
+
133
+
134
+ @timeit
135
+ def load_googleworkspace_oauth_apps(
136
+ neo4j_session: neo4j.Session,
137
+ data: list[dict[str, Any]],
138
+ googleworkspace_update_tag: int,
139
+ customer_id: str,
140
+ ) -> None:
141
+ """
142
+ Load Google Workspace OAuth apps
143
+ """
144
+ logger.info(
145
+ "Ingesting %s Google Workspace OAuth apps for customer %s",
146
+ len(data),
147
+ customer_id,
148
+ )
149
+ load(
150
+ neo4j_session,
151
+ GoogleWorkspaceOAuthAppSchema(),
152
+ data,
153
+ lastupdated=googleworkspace_update_tag,
154
+ CUSTOMER_ID=customer_id,
155
+ )
156
+
157
+
158
+ @timeit
159
+ def load_user_to_app_authorizations(
160
+ neo4j_session: neo4j.Session,
161
+ authorizations: list[dict[str, Any]],
162
+ googleworkspace_update_tag: int,
163
+ customer_id: str,
164
+ ) -> None:
165
+ """
166
+ Load user to OAuth app authorization relationships using MatchLinks
167
+ """
168
+ logger.info(
169
+ "Creating %s user to OAuth app authorization relationships",
170
+ len(authorizations),
171
+ )
172
+
173
+ load_matchlinks(
174
+ neo4j_session,
175
+ GoogleWorkspaceUserToOAuthAppRel(),
176
+ authorizations,
177
+ lastupdated=googleworkspace_update_tag,
178
+ _sub_resource_label="GoogleWorkspaceTenant",
179
+ _sub_resource_id=customer_id,
180
+ )
181
+
182
+
183
+ @timeit
184
+ def cleanup_googleworkspace_oauth_apps(
185
+ neo4j_session: neo4j.Session,
186
+ common_job_parameters: dict[str, Any],
187
+ ) -> None:
188
+ """
189
+ Clean up Google Workspace OAuth apps
190
+ """
191
+ logger.debug("Running Google Workspace OAuth apps cleanup job")
192
+ GraphJob.from_node_schema(
193
+ GoogleWorkspaceOAuthAppSchema(), common_job_parameters
194
+ ).run(neo4j_session)
195
+
196
+
197
+ @timeit
198
+ def cleanup_user_to_app_authorizations(
199
+ neo4j_session: neo4j.Session,
200
+ common_job_parameters: dict[str, Any],
201
+ ) -> None:
202
+ """
203
+ Clean up stale user to OAuth app authorization relationships using MatchLink cleanup
204
+ """
205
+ logger.debug("Running user to OAuth app authorization relationships cleanup")
206
+
207
+ GraphJob.from_matchlink(
208
+ GoogleWorkspaceUserToOAuthAppRel(),
209
+ "GoogleWorkspaceTenant",
210
+ common_job_parameters["CUSTOMER_ID"],
211
+ common_job_parameters["UPDATE_TAG"],
212
+ ).run(neo4j_session)
213
+
214
+
215
+ @timeit
216
+ def sync_googleworkspace_oauth_apps(
217
+ neo4j_session: neo4j.Session,
218
+ admin: Resource,
219
+ user_ids: list[str],
220
+ googleworkspace_update_tag: int,
221
+ common_job_parameters: dict[str, Any],
222
+ ) -> None:
223
+ """
224
+ GET Google Workspace OAuth app objects using the google admin api resource, load the data into Neo4j and clean up stale nodes.
225
+
226
+ :param neo4j_session: The Neo4j session
227
+ :param admin: Google admin resource object created by `googleapiclient.discovery.build()`.
228
+ :param user_ids: List of user IDs to fetch tokens for
229
+ :param googleworkspace_update_tag: The timestamp value to set our new Neo4j nodes with
230
+ :param common_job_parameters: Parameters to carry to the Neo4j jobs
231
+ :return: Nothing
232
+ """
233
+ logger.debug("Syncing Google Workspace OAuth Apps")
234
+
235
+ # 1. GET - Fetch data from API
236
+ tokens = get_all_oauth_tokens(admin, user_ids)
237
+
238
+ # 2. TRANSFORM - Shape data for ingestion
239
+ apps, authorizations = transform_oauth_apps_and_authorizations(tokens)
240
+
241
+ # 3. LOAD - Ingest apps to Neo4j using data model
242
+ load_googleworkspace_oauth_apps(
243
+ neo4j_session,
244
+ apps,
245
+ googleworkspace_update_tag,
246
+ common_job_parameters["CUSTOMER_ID"],
247
+ )
248
+
249
+ # 4. LOAD - Create user to app authorization relationships
250
+ load_user_to_app_authorizations(
251
+ neo4j_session,
252
+ authorizations,
253
+ googleworkspace_update_tag,
254
+ common_job_parameters["CUSTOMER_ID"],
255
+ )
256
+
257
+ # 5. CLEANUP - Remove stale data
258
+ cleanup_googleworkspace_oauth_apps(neo4j_session, common_job_parameters)
259
+ cleanup_user_to_app_authorizations(neo4j_session, common_job_parameters)
@@ -0,0 +1,85 @@
1
+ import logging
2
+ from typing import Any
3
+
4
+ import neo4j
5
+ from googleapiclient.discovery import Resource
6
+ from googleapiclient.errors import HttpError
7
+
8
+ from cartography.client.core.tx import load
9
+ from cartography.models.googleworkspace.tenant import GoogleWorkspaceTenantSchema
10
+ from cartography.util import timeit
11
+
12
+ logger = logging.getLogger(__name__)
13
+
14
+ GOOGLE_API_NUM_RETRIES = 5
15
+
16
+
17
+ @timeit
18
+ def get_tenant(admin: Resource) -> dict[str, Any]:
19
+ """
20
+ Return the Google Workspace tenant information
21
+ https://developers.google.com/workspace/admin/directory/reference/rest/v1/customers/get
22
+
23
+ :param admin: apiclient discovery resource object
24
+ :return: Google Workspace tenant information
25
+ """
26
+ try:
27
+ req = admin.customers().get(
28
+ customerKey="my_customer",
29
+ )
30
+ resp = req.execute(num_retries=GOOGLE_API_NUM_RETRIES)
31
+ return resp
32
+ except HttpError as e:
33
+ if (
34
+ e.resp.status == 403
35
+ and "Request had insufficient authentication scopes" in str(e)
36
+ ):
37
+ logger.error(
38
+ "Missing required Google Workspace scopes. If using the gcloud CLI, "
39
+ "run: gcloud auth application-default login --scopes="
40
+ "https://www.googleapis.com/auth/admin.directory.customer.readonly,"
41
+ "https://www.googleapis.com/auth/admin.directory.user.readonly,"
42
+ "https://www.googleapis.com/auth/admin.directory.user.security,"
43
+ "https://www.googleapis.com/auth/cloud-identity.devices.readonly,"
44
+ "https://www.googleapis.com/auth/cloud-identity.groups.readonly,"
45
+ "https://www.googleapis.com/auth/cloud-platform"
46
+ )
47
+ raise
48
+
49
+
50
+ @timeit
51
+ def load_googleworkspace_tenant(
52
+ neo4j_session: neo4j.Session,
53
+ tenant_data: dict[str, Any],
54
+ googleworkspace_update_tag: int,
55
+ ) -> None:
56
+ """
57
+ Load Google Workspace tenant
58
+ """
59
+ logger.info("Ingesting %s Google Workspace tenant", tenant_data["id"])
60
+ load(
61
+ neo4j_session,
62
+ GoogleWorkspaceTenantSchema(),
63
+ [tenant_data],
64
+ lastupdated=googleworkspace_update_tag,
65
+ )
66
+
67
+
68
+ @timeit
69
+ def sync_googleworkspace_tenant(
70
+ neo4j_session: neo4j.Session,
71
+ admin: Resource,
72
+ googleworkspace_update_tag: int,
73
+ common_job_parameters: dict[str, Any],
74
+ ) -> list[str]:
75
+ """Sync Google Workspace tenant data."""
76
+ logger.debug("Syncing Google Workspace Tenant data")
77
+
78
+ # GET - Fetch data from API
79
+ resp_obj = get_tenant(admin)
80
+
81
+ # LOAD - Ingest to Neo4j using data model
82
+ load_googleworkspace_tenant(neo4j_session, resp_obj, googleworkspace_update_tag)
83
+
84
+ # Return the customer ID
85
+ return resp_obj["id"]
@@ -0,0 +1,138 @@
1
+ import logging
2
+ from typing import Any
3
+
4
+ import neo4j
5
+ from googleapiclient.discovery import Resource
6
+
7
+ from cartography.client.core.tx import load
8
+ from cartography.graph.job import GraphJob
9
+ from cartography.models.googleworkspace.user import GoogleWorkspaceUserSchema
10
+ from cartography.util import timeit
11
+
12
+ logger = logging.getLogger(__name__)
13
+
14
+ GOOGLE_API_NUM_RETRIES = 5
15
+
16
+
17
+ @timeit
18
+ def get_all_users(admin: Resource) -> list[dict]:
19
+ """
20
+ Return list of Google Users in your organization
21
+ Returns empty list if we are unable to enumerate the users for any reasons
22
+ https://developers.google.com/admin-sdk/directory/v1/guides/manage-users
23
+
24
+ :param admin: apiclient discovery resource object
25
+ :return: list of Google users in domain
26
+ see https://developers.google.com/admin-sdk/directory/v1/guides/manage-users#get_all_domain_users
27
+ """
28
+ request = admin.users().list(
29
+ customer="my_customer",
30
+ maxResults=500,
31
+ orderBy="email",
32
+ )
33
+ response_objects = []
34
+ while request is not None:
35
+ resp = request.execute(num_retries=GOOGLE_API_NUM_RETRIES)
36
+ response_objects.append(resp)
37
+ request = admin.users().list_next(request, resp)
38
+ return response_objects
39
+
40
+
41
+ @timeit
42
+ def transform_users(response_objects: list[dict]) -> list[dict[str, Any]]:
43
+ """Transform list of API response objects to return list of user objects with flattened structure grouped by customerId
44
+ :param response_objects: Raw API response objects
45
+ :return: list of dictionary objects for data model consumption
46
+ """
47
+ results = []
48
+ for response_object in response_objects:
49
+ for user in response_object["users"]:
50
+ # Flatten the nested name structure
51
+ transformed_user = user.copy()
52
+ if "name" in user and isinstance(user["name"], dict):
53
+ transformed_user["name"] = user["name"].get("fullName")
54
+ transformed_user["family_name"] = user["name"].get("familyName")
55
+ transformed_user["given_name"] = user["name"].get("givenName")
56
+ for org in user.get("organizations", []):
57
+ if org.get("primary"):
58
+ transformed_user["organization_name"] = org.get("name")
59
+ transformed_user["organization_title"] = org.get("title")
60
+ transformed_user["organization_department"] = org.get("department")
61
+ results.append(transformed_user)
62
+ return results
63
+
64
+
65
+ @timeit
66
+ def load_googleworkspace_users(
67
+ neo4j_session: neo4j.Session,
68
+ data: list[dict[str, Any]],
69
+ googleworkspace_update_tag: int,
70
+ customer_id: str,
71
+ ) -> None:
72
+ """
73
+ Load Google Workspace users
74
+ """
75
+ logger.info(
76
+ "Ingesting %s Google Workspace users for customer %s", len(data), customer_id
77
+ )
78
+ # Load users with relationship to tenant
79
+ load(
80
+ neo4j_session,
81
+ GoogleWorkspaceUserSchema(),
82
+ data,
83
+ lastupdated=googleworkspace_update_tag,
84
+ CUSTOMER_ID=customer_id,
85
+ )
86
+
87
+
88
+ @timeit
89
+ def cleanup_googleworkspace_users(
90
+ neo4j_session: neo4j.Session,
91
+ common_job_parameters: dict[str, Any],
92
+ ) -> None:
93
+ """
94
+ Clean up Google Workspace users
95
+ """
96
+ logger.debug("Running Google Workspace users cleanup job")
97
+ GraphJob.from_node_schema(GoogleWorkspaceUserSchema(), common_job_parameters).run(
98
+ neo4j_session
99
+ )
100
+
101
+
102
+ @timeit
103
+ def sync_googleworkspace_users(
104
+ neo4j_session: neo4j.Session,
105
+ admin: Resource,
106
+ googleworkspace_update_tag: int,
107
+ common_job_parameters: dict[str, Any],
108
+ ) -> list[str]:
109
+ """
110
+ GET Google Workspace user objects using the google admin api resource, load the data into Neo4j and clean up stale nodes.
111
+
112
+ :param neo4j_session: The Neo4j session
113
+ :param admin: Google admin resource object created by `googleapiclient.discovery.build()`.
114
+ See https://googleapis.github.io/google-api-python-client/docs/epy/googleapiclient.discovery-module.html#build.
115
+ :param googleworkspace_update_tag: The timestamp value to set our new Neo4j nodes with
116
+ :param common_job_parameters: Parameters to carry to the Neo4j jobs
117
+ :return: List of user IDs
118
+ """
119
+ logger.debug("Syncing Google Workspace Users")
120
+
121
+ # 1. GET - Fetch data from API
122
+ resp_objs = get_all_users(admin)
123
+
124
+ # 2. TRANSFORM - Shape data for ingestion
125
+ raw_users = transform_users(resp_objs)
126
+
127
+ # 3. LOAD - Ingest to Neo4j using data model
128
+ load_googleworkspace_users(
129
+ neo4j_session,
130
+ raw_users,
131
+ googleworkspace_update_tag,
132
+ common_job_parameters["CUSTOMER_ID"],
133
+ )
134
+
135
+ # 4. CLEANUP - Remove stale data
136
+ cleanup_googleworkspace_users(neo4j_session, common_job_parameters)
137
+
138
+ return [user["id"] for user in raw_users]
@@ -16,7 +16,8 @@ from google.oauth2.service_account import Credentials as ServiceAccountCredentia
16
16
  from googleapiclient.discovery import Resource
17
17
 
18
18
  from cartography.config import Config
19
- from cartography.intel.gsuite import api
19
+ from cartography.intel.gsuite import groups
20
+ from cartography.intel.gsuite import users
20
21
  from cartography.util import timeit
21
22
 
22
23
  OAUTH_SCOPES = [
@@ -119,7 +120,6 @@ def start_gsuite_ingestion(neo4j_session: neo4j.Session, config: Config) -> None
119
120
  scopes=OAUTH_SCOPES,
120
121
  )
121
122
  creds.refresh(Request())
122
- creds = creds.create_scoped(OAUTH_SCOPES)
123
123
  except DefaultCredentialsError as e:
124
124
  logger.error(
125
125
  (
@@ -147,16 +147,24 @@ def start_gsuite_ingestion(neo4j_session: neo4j.Session, config: Config) -> None
147
147
  )
148
148
  return
149
149
 
150
- resources = _initialize_resources(creds)
151
- api.sync_gsuite_users(
152
- neo4j_session,
153
- resources.admin,
154
- config.update_tag,
155
- common_job_parameters,
150
+ logger.warning(
151
+ "The GSuite module is deprecated and will no longer receive updates. It will be completely removed in the 1.0.0 release. "
152
+ "For migration, please refer to the Google Workspace module configuration."
156
153
  )
157
- api.sync_gsuite_groups(
154
+
155
+ resources = _initialize_resources(creds)
156
+ customer_ids = users.sync_gsuite_users(
158
157
  neo4j_session,
159
158
  resources.admin,
160
159
  config.update_tag,
161
160
  common_job_parameters,
162
161
  )
162
+ for customer_id in customer_ids:
163
+ scoped_job_parameters = common_job_parameters.copy()
164
+ scoped_job_parameters["CUSTOMER_ID"] = customer_id
165
+ groups.sync_gsuite_groups(
166
+ neo4j_session,
167
+ resources.admin,
168
+ config.update_tag,
169
+ scoped_job_parameters,
170
+ )