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
@@ -7,7 +7,9 @@ import neo4j
7
7
  from azure.core.exceptions import HttpResponseError
8
8
  from azure.mgmt.resource import SubscriptionClient
9
9
 
10
- from cartography.util import run_cleanup_job
10
+ from cartography.client.core.tx import load
11
+ from cartography.graph.job import GraphJob
12
+ from cartography.models.azure.subscription import AzureSubscriptionSchema
11
13
  from cartography.util import timeit
12
14
 
13
15
  from .util.credentials import Credentials
@@ -18,19 +20,16 @@ logger = logging.getLogger(__name__)
18
20
  def get_all_azure_subscriptions(credentials: Credentials) -> List[Dict]:
19
21
  try:
20
22
  # Create the client
21
- client = SubscriptionClient(credentials.arm_credentials)
23
+ client = SubscriptionClient(credentials.credential)
22
24
 
23
25
  # Get all the accessible subscriptions
24
26
  subs = list(client.subscriptions.list())
25
27
 
26
28
  except HttpResponseError as e:
27
- logger.error(
28
- f"failed to fetch subscriptions for the credentials \
29
- The provided credentials do not have access to any subscriptions - \
30
- {e}",
31
- )
32
-
33
- return []
29
+ raise RuntimeError(
30
+ f"Failed to fetch subscriptions for the credentials. "
31
+ f"The provided credentials do not have access to any subscriptions: {e}",
32
+ ) from e
34
33
 
35
34
  subscriptions = []
36
35
  for sub in subs:
@@ -52,19 +51,16 @@ def get_current_azure_subscription(
52
51
  ) -> List[Dict]:
53
52
  try:
54
53
  # Create the client
55
- client = SubscriptionClient(credentials.arm_credentials)
54
+ client = SubscriptionClient(credentials.credential)
56
55
 
57
56
  # Get all the accessible subscriptions
58
57
  sub = client.subscriptions.get(subscription_id)
59
58
 
60
59
  except HttpResponseError as e:
61
- logger.error(
62
- f"failed to fetch subscription for the credentials \
63
- The provided credentials do not have access to this subscription: {subscription_id} - \
64
- {e}",
65
- )
66
-
67
- return []
60
+ raise RuntimeError(
61
+ f"Failed to fetch subscription for the credentials. "
62
+ f"The provided credentials do not have access to this subscription: {subscription_id}: {e}",
63
+ ) from e
68
64
 
69
65
  return [
70
66
  {
@@ -82,36 +78,18 @@ def load_azure_subscriptions(
82
78
  subscriptions: List[Dict],
83
79
  update_tag: int,
84
80
  ) -> None:
85
- query = """
86
- MERGE (at:AzureTenant{id: $TENANT_ID})
87
- ON CREATE SET at.firstseen = timestamp()
88
- SET at.lastupdated = $update_tag
89
- WITH at
90
- MERGE (as:AzureSubscription{id: $SUBSCRIPTION_ID})
91
- ON CREATE SET as.firstseen = timestamp(), as.path = $SUBSCRIPTION_PATH
92
- SET as.lastupdated = $update_tag, as.name = $SUBSCRIPTION_NAME, as.state = $SUBSCRIPTION_STATE
93
- WITH as, at
94
- MERGE (at)-[r:RESOURCE]->(as)
95
- ON CREATE SET r.firstseen = timestamp()
96
- SET r.lastupdated = $update_tag;
97
- """
98
- for sub in subscriptions:
99
- neo4j_session.run(
100
- query,
101
- TENANT_ID=tenant_id,
102
- SUBSCRIPTION_ID=sub["subscriptionId"],
103
- SUBSCRIPTION_PATH=sub["id"],
104
- SUBSCRIPTION_NAME=sub["displayName"],
105
- SUBSCRIPTION_STATE=sub["state"],
106
- update_tag=update_tag,
107
- )
81
+ load(
82
+ neo4j_session,
83
+ AzureSubscriptionSchema(),
84
+ subscriptions,
85
+ lastupdated=update_tag,
86
+ TENANT_ID=tenant_id,
87
+ )
108
88
 
109
89
 
110
90
  def cleanup(neo4j_session: neo4j.Session, common_job_parameters: Dict) -> None:
111
- run_cleanup_job(
112
- "azure_subscriptions_cleanup.json",
91
+ GraphJob.from_node_schema(AzureSubscriptionSchema(), common_job_parameters).run(
113
92
  neo4j_session,
114
- common_job_parameters,
115
93
  )
116
94
 
117
95
 
@@ -1,58 +1,67 @@
1
1
  import logging
2
2
  from typing import Dict
3
+ from typing import Optional
3
4
 
4
5
  import neo4j
5
6
 
6
- from cartography.util import run_cleanup_job
7
- from cartography.util import timeit
7
+ from cartography.client.core.tx import load
8
+ from cartography.graph.job import GraphJob
9
+ from cartography.models.azure.principal import AzurePrincipalSchema
8
10
 
9
- from .util.credentials import Credentials
11
+ # Import the new, separated schemas
12
+ from cartography.models.azure.tenant import AzureTenantSchema
13
+ from cartography.util import timeit
10
14
 
11
15
  logger = logging.getLogger(__name__)
12
16
 
13
17
 
14
- def get_tenant_id(credentials: Credentials) -> str:
15
- return credentials.get_tenant_id()
16
-
17
-
18
+ @timeit
18
19
  def load_azure_tenant(
19
20
  neo4j_session: neo4j.Session,
20
21
  tenant_id: str,
21
- current_user: str,
22
+ current_user: Optional[str],
22
23
  update_tag: int,
23
24
  ) -> None:
24
- query = """
25
- MERGE (at:AzureTenant{id: $TENANT_ID})
26
- ON CREATE SET at.firstseen = timestamp()
27
- SET at.lastupdated = $update_tag
28
- WITH at
29
- MERGE (ap:AzurePrincipal{id: $CURRENT_USER})
30
- ON CREATE SET ap.email = $CURRENT_USER, ap.firstseen = timestamp()
31
- SET ap.lastupdated = $update_tag
32
- WITH at, ap
33
- MERGE (at)-[r:RESOURCE]->(ap)
34
- ON CREATE SET r.firstseen = timestamp()
35
- SET r.lastupdated = $update_tag;
36
25
  """
37
- neo4j_session.run(
38
- query,
39
- TENANT_ID=tenant_id,
40
- CURRENT_USER=current_user,
41
- update_tag=update_tag,
42
- )
26
+ Ingest the Azure Tenant and, if available, the Azure Principal into Neo4j.
27
+ """
28
+ tenant_data = {"id": tenant_id}
29
+ load(neo4j_session, AzureTenantSchema(), [tenant_data], lastupdated=update_tag)
43
30
 
31
+ if current_user:
32
+ principal_data = {"id": current_user}
33
+ load(
34
+ neo4j_session,
35
+ AzurePrincipalSchema(),
36
+ [principal_data],
37
+ lastupdated=update_tag,
38
+ TENANT_ID=tenant_id,
39
+ )
44
40
 
45
- def cleanup(neo4j_session: neo4j.Session, common_job_parameters: Dict) -> None:
46
- run_cleanup_job("azure_tenant_cleanup.json", neo4j_session, common_job_parameters)
41
+
42
+ @timeit
43
+ def cleanup_azure_tenant(
44
+ neo4j_session: neo4j.Session, common_job_parameters: Dict
45
+ ) -> None:
46
+ """
47
+ Delete stale Azure Tenants and Principals.
48
+ """
49
+ GraphJob.from_node_schema(AzureTenantSchema(), common_job_parameters).run(
50
+ neo4j_session
51
+ )
52
+ GraphJob.from_node_schema(AzurePrincipalSchema(), common_job_parameters).run(
53
+ neo4j_session
54
+ )
47
55
 
48
56
 
49
57
  @timeit
50
58
  def sync(
51
59
  neo4j_session: neo4j.Session,
52
60
  tenant_id: str,
53
- current_user: str,
61
+ current_user: Optional[str],
54
62
  update_tag: int,
55
63
  common_job_parameters: Dict,
56
64
  ) -> None:
65
+ logger.info("Syncing Azure tenant '%s'.", tenant_id)
57
66
  load_azure_tenant(neo4j_session, tenant_id, current_user, update_tag)
58
- cleanup(neo4j_session, common_job_parameters)
67
+ cleanup_azure_tenant(neo4j_session, common_job_parameters)
@@ -0,0 +1,13 @@
1
+ import logging
2
+
3
+ logger = logging.getLogger(__name__)
4
+
5
+
6
+ def get_resource_group_from_id(resource_id: str) -> str:
7
+ """
8
+ Helper function to parse the resource group name from a full resource ID string.
9
+ e.g. /subscriptions/sub_id/resourceGroups/rg_name/providers/...
10
+ """
11
+ parts = resource_id.lower().split("/")
12
+ rg_index = parts.index("resourcegroups")
13
+ return parts[rg_index + 1]
@@ -1,222 +1,97 @@
1
1
  import logging
2
- from datetime import datetime
3
- from datetime import timedelta
4
2
  from typing import Any
5
3
  from typing import Optional
6
4
 
7
- import adal
8
- import requests
9
- from azure.common.credentials import get_azure_cli_credentials
10
- from azure.common.credentials import get_cli_profile
11
- from azure.core.exceptions import HttpResponseError
5
+ import jwt
6
+ from azure.identity import AzureCliCredential
12
7
  from azure.identity import ClientSecretCredential
13
- from msrestazure.azure_active_directory import AADTokenCredentials
8
+ from azure.mgmt.resource import SubscriptionClient
14
9
 
15
10
  logger = logging.getLogger(__name__)
16
- AUTHORITY_HOST_URI = "https://login.microsoftonline.com"
11
+
12
+
13
+ def _get_tenant_id_from_token(credential: Any) -> str:
14
+ """
15
+ A helper function to get the tenant ID from the claims in an access token.
16
+ """
17
+ token = credential.get_token("https://management.azure.com/.default")
18
+ decoded_token = jwt.decode(token.token, options={"verify_signature": False})
19
+ return decoded_token.get("tid", "")
17
20
 
18
21
 
19
22
  class Credentials:
23
+ """
24
+ A simple data container for the credential object and its associated IDs.
25
+ """
20
26
 
21
27
  def __init__(
22
28
  self,
23
- arm_credentials: Any,
24
- aad_graph_credentials: Any,
29
+ credential: Any,
25
30
  tenant_id: Optional[str] = None,
26
31
  subscription_id: Optional[str] = None,
27
- context: Optional[adal.AuthenticationContext] = None,
28
- current_user: Optional[str] = None,
29
32
  ) -> None:
30
- self.arm_credentials = arm_credentials # Azure Resource Manager API credentials
31
- self.aad_graph_credentials = (
32
- aad_graph_credentials # Azure AD Graph API credentials
33
- )
33
+ self.credential = credential
34
34
  self.tenant_id = tenant_id
35
35
  self.subscription_id = subscription_id
36
- self.context = context
37
- self.current_user = current_user
38
-
39
- def get_current_user(self) -> Optional[str]:
40
- return self.current_user
41
-
42
- def get_tenant_id(self) -> Any:
43
- if self.tenant_id:
44
- return self.tenant_id
45
- elif "tenant_id" in self.aad_graph_credentials.token:
46
- return self.aad_graph_credentials.token["tenant_id"]
47
- else:
48
- # This is a last resort, e.g. for MSI authentication
49
- try:
50
- h = {
51
- "Authorization": "Bearer {}".format(
52
- self.arm_credentials.token["access_token"],
53
- ),
54
- }
55
- r = requests.get(
56
- "https://management.azure.com/tenants?api-version=2020-01-01",
57
- headers=h,
58
- )
59
- r2 = r.json()
60
- return r2.get("value")[0].get("tenantId")
61
- except requests.ConnectionError as e:
62
- logger.error(f"Unable to infer tenant ID: {e}")
63
- return None
64
-
65
- def get_credentials(self, resource: str) -> Any:
66
- if resource == "arm":
67
- self.arm_credentials = self.get_fresh_credentials(self.arm_credentials)
68
- return self.arm_credentials
69
- elif resource == "aad_graph":
70
- self.aad_graph_credentials = self.get_fresh_credentials(
71
- self.aad_graph_credentials,
72
- )
73
- return self.aad_graph_credentials
74
- else:
75
- raise Exception("Invalid credentials resource type")
76
-
77
- def get_fresh_credentials(self, credentials: Any) -> Any:
78
- """
79
- Check if credentials are outdated and if so refresh them.
80
- """
81
- if self.context and hasattr(credentials, "token"):
82
- expiration_datetime = datetime.fromtimestamp(
83
- credentials.token["expires_on"],
84
- )
85
- current_datetime = datetime.now()
86
- expiration_delta = expiration_datetime - current_datetime
87
- if expiration_delta < timedelta(minutes=5):
88
- return self.refresh_credential(credentials)
89
- return credentials
90
-
91
- def refresh_credential(self, credentials: Any) -> Any:
92
- """
93
- Refresh credentials
94
- """
95
- logger.debug("Refreshing credentials")
96
- authority_uri = AUTHORITY_HOST_URI + "/" + self.get_tenant_id()
97
- if self.context:
98
- existing_cache = self.context.cache
99
- context = adal.AuthenticationContext(authority_uri, cache=existing_cache)
100
-
101
- else:
102
- context = adal.AuthenticationContext(authority_uri)
103
-
104
- new_token = context.acquire_token(
105
- credentials.token["resource"],
106
- credentials.token["user_id"],
107
- credentials.token["_client_id"],
108
- )
109
-
110
- new_credentials = AADTokenCredentials(
111
- new_token,
112
- credentials.token.get("_client_id"),
113
- )
114
- return new_credentials
115
36
 
116
37
 
117
38
  class Authenticator:
118
39
 
119
- def authenticate_cli(self) -> Credentials:
40
+ def authenticate_cli(self) -> Optional[Credentials]:
120
41
  """
121
- Implements authentication for the Azure provider
42
+ Implements authentication using the Azure CLI with the modern library.
122
43
  """
44
+ logging.getLogger("urllib3").setLevel(logging.ERROR)
45
+ logging.getLogger(
46
+ "azure.core.pipeline.policies.http_logging_policy",
47
+ ).setLevel(logging.ERROR)
123
48
  try:
49
+ credential = AzureCliCredential()
124
50
 
125
- # Set logging level to error for libraries as otherwise generates a lot of warnings
126
- logging.getLogger("adal-python").setLevel(logging.ERROR)
127
- logging.getLogger("msrest").setLevel(logging.ERROR)
128
- logging.getLogger("msrestazure.azure_active_directory").setLevel(
129
- logging.ERROR,
130
- )
131
- logging.getLogger("urllib3").setLevel(logging.ERROR)
132
- logging.getLogger(
133
- "azure.core.pipeline.policies.http_logging_policy",
134
- ).setLevel(logging.ERROR)
51
+ subscription_client = SubscriptionClient(credential)
52
+ subscription = next(subscription_client.subscriptions.list())
53
+ subscription_id = subscription.subscription_id
135
54
 
136
- arm_credentials, subscription_id, tenant_id = get_azure_cli_credentials(
137
- with_tenant=True,
138
- )
139
- aad_graph_credentials, placeholder_1, placeholder_2 = (
140
- get_azure_cli_credentials(
141
- with_tenant=True,
142
- resource="https://graph.windows.net",
143
- )
144
- )
145
-
146
- profile = get_cli_profile()
55
+ tenant_id = _get_tenant_id_from_token(credential)
147
56
 
148
57
  return Credentials(
149
- arm_credentials,
150
- aad_graph_credentials,
58
+ credential=credential,
151
59
  tenant_id=tenant_id,
152
- current_user=profile.get_current_account_user(),
153
60
  subscription_id=subscription_id,
154
61
  )
155
-
156
- except HttpResponseError as e:
157
- if (
158
- ", AdalError: Unsupported wstrust endpoint version. "
159
- "Current supported version is wstrust2005 or wstrust13." in e.args
160
- ):
161
- logger.error(
162
- f"You are likely authenticating with a Microsoft Account. \
163
- This authentication mode only supports Azure Active Directory principal authentication.\
164
- {e}",
165
- )
166
-
167
- raise e
62
+ except Exception as e:
63
+ logger.error(
64
+ f"Failed to authenticate with Azure CLI. Have you run 'az login'? Details: {e}"
65
+ )
66
+ return None
168
67
 
169
68
  def authenticate_sp(
170
69
  self,
171
70
  tenant_id: Optional[str] = None,
172
71
  client_id: Optional[str] = None,
173
72
  client_secret: Optional[str] = None,
174
- ) -> Credentials:
73
+ subscription_id: Optional[str] = None,
74
+ ) -> Optional[Credentials]:
175
75
  """
176
- Implements authentication for the Azure provider
76
+ Implements authentication using a Service Principal with the modern library.
177
77
  """
178
78
  try:
179
-
180
- # Set logging level to error for libraries as otherwise generates a lot of warnings
181
- logging.getLogger("adal-python").setLevel(logging.ERROR)
182
- logging.getLogger("msrest").setLevel(logging.ERROR)
183
- logging.getLogger("msrestazure.azure_active_directory").setLevel(
184
- logging.ERROR,
185
- )
186
- logging.getLogger("urllib3").setLevel(logging.ERROR)
187
- logging.getLogger(
188
- "azure.core.pipeline.policies.http_logging_policy",
189
- ).setLevel(logging.ERROR)
190
-
191
- arm_credentials = ClientSecretCredential(
192
- client_id=client_id,
193
- client_secret=client_secret,
194
- tenant_id=tenant_id,
195
- )
196
-
197
- aad_graph_credentials = ClientSecretCredential(
79
+ credential = ClientSecretCredential(
198
80
  client_id=client_id,
199
81
  client_secret=client_secret,
200
82
  tenant_id=tenant_id,
201
- resource="https://graph.windows.net",
202
83
  )
203
-
204
84
  return Credentials(
205
- arm_credentials,
206
- aad_graph_credentials,
85
+ credential=credential,
207
86
  tenant_id=tenant_id,
208
- current_user=client_id,
87
+ subscription_id=subscription_id,
209
88
  )
210
-
211
- except HttpResponseError as e:
212
- if (
213
- ", AdalError: Unsupported wstrust endpoint version. "
214
- "Current supported version is wstrust2005 or wstrust13." in e.args
215
- ):
216
- logger.error(
217
- f"You are likely authenticating with a Microsoft Account. \
218
- This authentication mode only supports Azure Active Directory principal authentication.\
219
- {e}",
220
- )
221
-
222
- raise e
89
+ except Exception as e:
90
+ logger.error(
91
+ (
92
+ "Failed to authenticate with Service Principal. "
93
+ "Please ensure the tenant ID, client ID, and client secret are correct. Details: %s"
94
+ ),
95
+ e,
96
+ )
97
+ return None
@@ -0,0 +1,41 @@
1
+ import logging
2
+
3
+ logger = logging.getLogger(__name__)
4
+
5
+
6
+ def transform_tags(
7
+ resource_list: list[dict], subscription_id: str, resource_id_field: str = "id"
8
+ ) -> list[dict]:
9
+ """
10
+ Transforms tags from a list of Azure resources into a standardized list of tag dictionaries.
11
+
12
+ Args:
13
+ resource_list: List of Azure resources with tags
14
+ subscription_id: The Azure subscription ID to scope the tags
15
+ resource_id_field: Field name containing the resource ID (default: "id")
16
+
17
+ Returns:
18
+ List of tag dictionaries with subscription-scoped IDs
19
+ """
20
+ tags_list = []
21
+ for resource in resource_list:
22
+ resource_id = resource.get(resource_id_field)
23
+ tags = resource.get("tags")
24
+
25
+ if not resource_id or not tags:
26
+ continue
27
+
28
+ for key, value in tags.items():
29
+ # Generate the deterministic ID scoped to subscription: "{subscription_id}|{key}:{value}"
30
+ tag_id = f"{subscription_id}|{key}:{value}"
31
+ tags_list.append(
32
+ {
33
+ "id": tag_id,
34
+ "key": key,
35
+ "value": value,
36
+ "subscription_id": subscription_id,
37
+ "resource_id": resource_id,
38
+ }
39
+ )
40
+
41
+ return tags_list
@@ -3,6 +3,7 @@ from typing import List
3
3
 
4
4
  import neo4j
5
5
 
6
+ from cartography.client.core.tx import run_write_query
6
7
  from cartography.config import Config
7
8
  from cartography.util import load_resource_binary
8
9
 
@@ -23,4 +24,4 @@ def run(neo4j_session: neo4j.Session, config: Config) -> None:
23
24
  logger.info("Creating indexes for cartography node types.")
24
25
  for statement in get_index_statements():
25
26
  logger.debug("Executing statement: %s", statement)
26
- neo4j_session.run(statement)
27
+ run_write_query(neo4j_session, statement)
@@ -6,6 +6,7 @@ import neo4j
6
6
  from falconpy.oauth2 import OAuth2
7
7
  from falconpy.spotlight_vulnerabilities import Spotlight_Vulnerabilities
8
8
 
9
+ from cartography.client.core.tx import run_write_query
9
10
  from cartography.util import timeit
10
11
 
11
12
  logger = logging.getLogger(__name__)
@@ -79,7 +80,8 @@ def load_vulnerability_data(
79
80
  cves.append(cve)
80
81
  vuln["host_info_local_ip"] = item.get("host_info", {}).get("local_ip")
81
82
  vulns.append(vuln)
82
- neo4j_session.run(
83
+ run_write_query(
84
+ neo4j_session,
83
85
  ingestion_cypher_query,
84
86
  Vulnerabilities=vulns,
85
87
  update_tag=update_tag,
@@ -106,7 +108,8 @@ def _load_cves(neo4j_session: neo4j.Session, data: List[Dict], update_tag: int)
106
108
  ON CREATE SET hc.firstseen = timestamp()
107
109
  SET hc.lastupdated = $update_tag
108
110
  """
109
- neo4j_session.run(
111
+ run_write_query(
112
+ neo4j_session,
110
113
  ingestion_cypher_query,
111
114
  cves=data,
112
115
  update_tag=update_tag,
cartography/intel/dns.py CHANGED
@@ -8,6 +8,7 @@ import dns.rdatatype
8
8
  import dns.resolver
9
9
  import neo4j
10
10
 
11
+ from cartography.client.core.tx import run_write_query
11
12
  from cartography.util import timeit
12
13
 
13
14
  logger = logging.getLogger(__name__)
@@ -104,7 +105,8 @@ def _link_ip_to_A_record(
104
105
  SET r.lastupdated = $update_tag
105
106
  """
106
107
 
107
- neo4j_session.run(
108
+ run_write_query(
109
+ neo4j_session,
108
110
  ingest,
109
111
  ParentId=parent_record,
110
112
  IP_LIST=ip_list,
@@ -151,7 +153,8 @@ def ingest_dns_record(
151
153
 
152
154
  record_id = f"{name}+{type}"
153
155
 
154
- neo4j_session.run(
156
+ run_write_query(
157
+ neo4j_session,
155
158
  template.safe_substitute(
156
159
  record_label=record_label,
157
160
  dns_node_additional_label=dns_node_additional_label,