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,124 @@
1
+ import logging
2
+ from typing import Any
3
+ from typing import Dict
4
+ from typing import List
5
+
6
+ import neo4j
7
+ from azure.core.exceptions import ClientAuthenticationError
8
+ from azure.core.exceptions import HttpResponseError
9
+ from azure.mgmt.web import WebSiteManagementClient
10
+
11
+ from cartography.client.core.tx import load
12
+ from cartography.graph.job import GraphJob
13
+ from cartography.models.azure.function_app import AzureFunctionAppSchema
14
+ from cartography.util import timeit
15
+
16
+ from .util.credentials import Credentials
17
+
18
+ logger = logging.getLogger(__name__)
19
+
20
+
21
+ @timeit
22
+ def get_function_apps(credentials: Credentials, subscription_id: str) -> List[Dict]:
23
+ """
24
+ Get a list of Function Apps from the given Azure subscription.
25
+ """
26
+ try:
27
+ client = WebSiteManagementClient(credentials.credential, subscription_id)
28
+ # Note: Function Apps are a type of Web App, so we list all web apps
29
+ # and then filter them in the transform stage.
30
+ return [app.as_dict() for app in client.web_apps.list()]
31
+
32
+ except ClientAuthenticationError as e:
33
+ logger.warning(
34
+ (
35
+ "Failed to authenticate to get function apps for subscription '%s'. "
36
+ "Please check your credentials. Error: %s"
37
+ ),
38
+ subscription_id,
39
+ e,
40
+ )
41
+ return []
42
+
43
+ except HttpResponseError as e:
44
+ logger.warning(
45
+ (
46
+ "Failed to get function apps for subscription '%s' due to an API error. "
47
+ "Status code: %s. Message: %s"
48
+ ),
49
+ subscription_id,
50
+ e.status_code,
51
+ str(e),
52
+ )
53
+ return []
54
+
55
+
56
+ @timeit
57
+ def transform_function_apps(function_apps_response: List[Dict]) -> List[Dict]:
58
+ """
59
+ Transform the raw API response to the dictionary structure that the model expects.
60
+ """
61
+ transformed_apps: List[Dict[str, Any]] = []
62
+ for app in function_apps_response:
63
+ # We only want to ingest resources that are explicitly function apps.
64
+ if "functionapp" in app.get("kind", ""):
65
+ transformed_app = {
66
+ "id": app.get("id"),
67
+ "name": app.get("name"),
68
+ "kind": app.get("kind"),
69
+ "location": app.get("location"),
70
+ "state": app.get("state"),
71
+ "default_host_name": app.get("default_host_name"),
72
+ "https_only": app.get("https_only"),
73
+ }
74
+ transformed_apps.append(transformed_app)
75
+ return transformed_apps
76
+
77
+
78
+ @timeit
79
+ def load_function_apps(
80
+ neo4j_session: neo4j.Session,
81
+ data: List[Dict[str, Any]],
82
+ subscription_id: str,
83
+ update_tag: int,
84
+ ) -> None:
85
+ """
86
+ Load the transformed Azure Function App data to Neo4j.
87
+ """
88
+ load(
89
+ neo4j_session,
90
+ AzureFunctionAppSchema(),
91
+ data,
92
+ lastupdated=update_tag,
93
+ AZURE_SUBSCRIPTION_ID=subscription_id,
94
+ )
95
+
96
+
97
+ @timeit
98
+ def cleanup_function_apps(
99
+ neo4j_session: neo4j.Session, common_job_parameters: Dict
100
+ ) -> None:
101
+ """
102
+ Run the cleanup job for Azure Function Apps.
103
+ """
104
+ GraphJob.from_node_schema(AzureFunctionAppSchema(), common_job_parameters).run(
105
+ neo4j_session
106
+ )
107
+
108
+
109
+ @timeit
110
+ def sync(
111
+ neo4j_session: neo4j.Session,
112
+ credentials: Credentials,
113
+ subscription_id: str,
114
+ update_tag: int,
115
+ common_job_parameters: Dict,
116
+ ) -> None:
117
+ """
118
+ The main sync function for Azure Function Apps.
119
+ """
120
+ logger.info(f"Syncing Azure Function Apps for subscription {subscription_id}.")
121
+ raw_apps = get_function_apps(credentials, subscription_id)
122
+ transformed_apps = transform_function_apps(raw_apps)
123
+ load_function_apps(neo4j_session, transformed_apps, subscription_id, update_tag)
124
+ cleanup_function_apps(neo4j_session, common_job_parameters)
@@ -0,0 +1,263 @@
1
+ import logging
2
+ from typing import Any
3
+
4
+ import neo4j
5
+ from azure.mgmt.network import NetworkManagementClient
6
+
7
+ from cartography.client.core.tx import load
8
+ from cartography.graph.job import GraphJob
9
+ from cartography.models.azure.load_balancer.load_balancer import AzureLoadBalancerSchema
10
+ from cartography.models.azure.load_balancer.load_balancer_backend_pool import (
11
+ AzureLoadBalancerBackendPoolSchema,
12
+ )
13
+ from cartography.models.azure.load_balancer.load_balancer_frontend_ip import (
14
+ AzureLoadBalancerFrontendIPSchema,
15
+ )
16
+ from cartography.models.azure.load_balancer.load_balancer_inbound_nat_rule import (
17
+ AzureLoadBalancerInboundNatRuleSchema,
18
+ )
19
+ from cartography.models.azure.load_balancer.load_balancer_rule import (
20
+ AzureLoadBalancerRuleSchema,
21
+ )
22
+ from cartography.util import timeit
23
+
24
+ from .util.credentials import Credentials
25
+
26
+ logger = logging.getLogger(__name__)
27
+
28
+
29
+ def _get_resource_group_from_id(resource_id: str) -> str:
30
+ parts = resource_id.lower().split("/")
31
+ rg_index = parts.index("resourcegroups")
32
+ return parts[rg_index + 1]
33
+
34
+
35
+ @timeit
36
+ def get_load_balancers(client: NetworkManagementClient) -> list[dict]:
37
+ """
38
+ Get a list of all Load Balancers in a subscription.
39
+ """
40
+ return [lb.as_dict() for lb in client.load_balancers.list_all()]
41
+
42
+
43
+ def transform_load_balancers(load_balancers: list[dict]) -> list[dict]:
44
+ transformed: list[dict[str, Any]] = []
45
+ for lb in load_balancers:
46
+ transformed.append(
47
+ {
48
+ "id": lb.get("id"),
49
+ "name": lb.get("name"),
50
+ "location": lb.get("location"),
51
+ "sku_name": lb.get("sku", {}).get("name"),
52
+ }
53
+ )
54
+ return transformed
55
+
56
+
57
+ def transform_frontend_ips(load_balancer: dict) -> list[dict]:
58
+ transformed: list[dict[str, Any]] = []
59
+ for config in load_balancer.get("frontend_ip_configurations", []):
60
+ transformed.append(
61
+ {
62
+ "id": config.get("id"),
63
+ "name": config.get("name"),
64
+ "private_ip_address": config.get("properties", {}).get(
65
+ "private_ip_address"
66
+ ),
67
+ "public_ip_address_id": config.get("properties", {})
68
+ .get("public_ip_address", {})
69
+ .get("id"),
70
+ }
71
+ )
72
+ return transformed
73
+
74
+
75
+ def transform_backend_pools(load_balancer: dict) -> list[dict]:
76
+ transformed: list[dict[str, Any]] = []
77
+ for pool in load_balancer.get("backend_address_pools", []):
78
+ transformed.append(
79
+ {
80
+ "id": pool.get("id"),
81
+ "name": pool.get("name"),
82
+ }
83
+ )
84
+ return transformed
85
+
86
+
87
+ def transform_rules(load_balancer: dict) -> list[dict]:
88
+ transformed: list[dict[str, Any]] = []
89
+ for rule in load_balancer.get("load_balancing_rules", []):
90
+ transformed.append(
91
+ {
92
+ "id": rule.get("id"),
93
+ "name": rule.get("name"),
94
+ "protocol": rule.get("properties", {}).get("protocol"),
95
+ "frontend_port": rule.get("properties", {}).get("frontend_port"),
96
+ "backend_port": rule.get("properties", {}).get("backend_port"),
97
+ "FRONTEND_IP_ID": rule.get("frontend_ip_configuration", {}).get("id"),
98
+ "BACKEND_POOL_ID": rule.get("backend_address_pool", {}).get("id"),
99
+ }
100
+ )
101
+ return transformed
102
+
103
+
104
+ def transform_inbound_nat_rules(load_balancer: dict) -> list[dict]:
105
+ transformed: list[dict[str, Any]] = []
106
+ for rule in load_balancer.get("inbound_nat_rules", []):
107
+ transformed.append(
108
+ {
109
+ "id": rule.get("id"),
110
+ "name": rule.get("name"),
111
+ "protocol": rule.get("properties", {}).get("protocol"),
112
+ "frontend_port": rule.get("properties", {}).get("frontend_port"),
113
+ "backend_port": rule.get("properties", {}).get("backend_port"),
114
+ }
115
+ )
116
+ return transformed
117
+
118
+
119
+ @timeit
120
+ def load_load_balancers(
121
+ neo4j_session: neo4j.Session,
122
+ data: list[dict[str, Any]],
123
+ subscription_id: str,
124
+ update_tag: int,
125
+ ) -> None:
126
+ load(
127
+ neo4j_session,
128
+ AzureLoadBalancerSchema(),
129
+ data,
130
+ lastupdated=update_tag,
131
+ AZURE_SUBSCRIPTION_ID=subscription_id,
132
+ )
133
+
134
+
135
+ @timeit
136
+ def load_frontend_ips(
137
+ neo4j_session: neo4j.Session,
138
+ data: list[dict[str, Any]],
139
+ lb_id: str,
140
+ subscription_id: str,
141
+ update_tag: int,
142
+ ) -> None:
143
+ load(
144
+ neo4j_session,
145
+ AzureLoadBalancerFrontendIPSchema(),
146
+ data,
147
+ lastupdated=update_tag,
148
+ LOAD_BALANCER_ID=lb_id,
149
+ AZURE_SUBSCRIPTION_ID=subscription_id,
150
+ )
151
+
152
+
153
+ @timeit
154
+ def load_backend_pools(
155
+ neo4j_session: neo4j.Session,
156
+ data: list[dict[str, Any]],
157
+ lb_id: str,
158
+ subscription_id: str,
159
+ update_tag: int,
160
+ ) -> None:
161
+ load(
162
+ neo4j_session,
163
+ AzureLoadBalancerBackendPoolSchema(),
164
+ data,
165
+ lastupdated=update_tag,
166
+ LOAD_BALANCER_ID=lb_id,
167
+ AZURE_SUBSCRIPTION_ID=subscription_id,
168
+ )
169
+
170
+
171
+ @timeit
172
+ def load_rules(
173
+ neo4j_session: neo4j.Session,
174
+ data: list[dict[str, Any]],
175
+ lb_id: str,
176
+ subscription_id: str,
177
+ update_tag: int,
178
+ ) -> None:
179
+ load(
180
+ neo4j_session,
181
+ AzureLoadBalancerRuleSchema(),
182
+ data,
183
+ lastupdated=update_tag,
184
+ LOAD_BALANCER_ID=lb_id,
185
+ AZURE_SUBSCRIPTION_ID=subscription_id,
186
+ )
187
+
188
+
189
+ @timeit
190
+ def load_inbound_nat_rules(
191
+ neo4j_session: neo4j.Session,
192
+ data: list[dict[str, Any]],
193
+ lb_id: str,
194
+ subscription_id: str,
195
+ update_tag: int,
196
+ ) -> None:
197
+ load(
198
+ neo4j_session,
199
+ AzureLoadBalancerInboundNatRuleSchema(),
200
+ data,
201
+ lastupdated=update_tag,
202
+ LOAD_BALANCER_ID=lb_id,
203
+ AZURE_SUBSCRIPTION_ID=subscription_id,
204
+ )
205
+
206
+
207
+ @timeit
208
+ def sync(
209
+ neo4j_session: neo4j.Session,
210
+ credentials: Credentials,
211
+ subscription_id: str,
212
+ update_tag: int,
213
+ common_job_parameters: dict,
214
+ ) -> None:
215
+ logger.info(f"Syncing Azure Load Balancers for subscription {subscription_id}.")
216
+ client = NetworkManagementClient(credentials.credential, subscription_id)
217
+
218
+ load_balancers = get_load_balancers(client)
219
+ transformed_lbs = transform_load_balancers(load_balancers)
220
+ load_load_balancers(neo4j_session, transformed_lbs, subscription_id, update_tag)
221
+
222
+ for lb in load_balancers:
223
+ lb_id = lb["id"]
224
+
225
+ frontend_ips = transform_frontend_ips(lb)
226
+ load_frontend_ips(
227
+ neo4j_session, frontend_ips, lb_id, subscription_id, update_tag
228
+ )
229
+
230
+ backend_pools = transform_backend_pools(lb)
231
+ load_backend_pools(
232
+ neo4j_session, backend_pools, lb_id, subscription_id, update_tag
233
+ )
234
+
235
+ rules = transform_rules(lb)
236
+ load_rules(neo4j_session, rules, lb_id, subscription_id, update_tag)
237
+
238
+ inbound_nat_rules = transform_inbound_nat_rules(lb)
239
+ load_inbound_nat_rules(
240
+ neo4j_session, inbound_nat_rules, lb_id, subscription_id, update_tag
241
+ )
242
+
243
+ # TODO: Implement relationships from Backend Pools and Inbound NAT Rules to Network Interfaces (NICs).
244
+
245
+ # Scoped cleanup for child components
246
+ cleanup_params = common_job_parameters.copy()
247
+ cleanup_params["LOAD_BALANCER_ID"] = lb_id
248
+ GraphJob.from_node_schema(
249
+ AzureLoadBalancerFrontendIPSchema(), cleanup_params
250
+ ).run(neo4j_session)
251
+ GraphJob.from_node_schema(
252
+ AzureLoadBalancerBackendPoolSchema(), cleanup_params
253
+ ).run(neo4j_session)
254
+ GraphJob.from_node_schema(AzureLoadBalancerRuleSchema(), cleanup_params).run(
255
+ neo4j_session
256
+ )
257
+ GraphJob.from_node_schema(
258
+ AzureLoadBalancerInboundNatRuleSchema(), cleanup_params
259
+ ).run(neo4j_session)
260
+
261
+ GraphJob.from_node_schema(AzureLoadBalancerSchema(), common_job_parameters).run(
262
+ neo4j_session
263
+ )
@@ -0,0 +1,101 @@
1
+ import logging
2
+ from typing import Any
3
+
4
+ import neo4j
5
+ from azure.core.exceptions import ClientAuthenticationError
6
+ from azure.core.exceptions import HttpResponseError
7
+ from azure.mgmt.logic import LogicManagementClient
8
+
9
+ from cartography.client.core.tx import load
10
+ from cartography.graph.job import GraphJob
11
+ from cartography.models.azure.logic_apps import AzureLogicAppSchema
12
+ from cartography.util import timeit
13
+
14
+ from .util.credentials import Credentials
15
+
16
+ logger = logging.getLogger(__name__)
17
+
18
+
19
+ @timeit
20
+ def get_logic_apps(credentials: Credentials, subscription_id: str) -> list[dict]:
21
+ """
22
+ Get a list of Logic Apps from the given Azure subscription.
23
+ """
24
+ try:
25
+ client = LogicManagementClient(credentials.credential, subscription_id)
26
+ # NOTE: The resource for a Logic App is called a "Workflow" in the SDK.
27
+ return [w.as_dict() for w in client.workflows.list_by_subscription()]
28
+ except (ClientAuthenticationError, HttpResponseError) as e:
29
+ logger.warning(
30
+ f"Failed to get logic apps for subscription {subscription_id}: {str(e)}"
31
+ )
32
+ return []
33
+
34
+
35
+ def transform_logic_apps(logic_apps_response: list[dict]) -> list[dict]:
36
+ """
37
+ Transform the raw API response to the dictionary structure that the model expects.
38
+ """
39
+ transformed_apps: list[dict[str, Any]] = []
40
+ for app in logic_apps_response:
41
+ transformed_app = {
42
+ "id": app.get("id"),
43
+ "name": app.get("name"),
44
+ "location": app.get("location"),
45
+ "state": app.get("properties", {}).get("state"),
46
+ "created_time": app.get("properties", {}).get("created_time"),
47
+ "changed_time": app.get("properties", {}).get("changed_time"),
48
+ "version": app.get("properties", {}).get("version"),
49
+ "access_endpoint": app.get("properties", {}).get("access_endpoint"),
50
+ }
51
+ transformed_apps.append(transformed_app)
52
+ return transformed_apps
53
+
54
+
55
+ @timeit
56
+ def load_logic_apps(
57
+ neo4j_session: neo4j.Session,
58
+ data: list[dict[str, Any]],
59
+ subscription_id: str,
60
+ update_tag: int,
61
+ ) -> None:
62
+ """
63
+ Load the transformed Azure Logic App data to Neo4j.
64
+ """
65
+ load(
66
+ neo4j_session,
67
+ AzureLogicAppSchema(),
68
+ data,
69
+ lastupdated=update_tag,
70
+ AZURE_SUBSCRIPTION_ID=subscription_id,
71
+ )
72
+
73
+
74
+ @timeit
75
+ def cleanup_logic_apps(
76
+ neo4j_session: neo4j.Session, common_job_parameters: dict
77
+ ) -> None:
78
+ """
79
+ Run the cleanup job for Azure Logic Apps.
80
+ """
81
+ GraphJob.from_node_schema(AzureLogicAppSchema(), common_job_parameters).run(
82
+ neo4j_session
83
+ )
84
+
85
+
86
+ @timeit
87
+ def sync(
88
+ neo4j_session: neo4j.Session,
89
+ credentials: Credentials,
90
+ subscription_id: str,
91
+ update_tag: int,
92
+ common_job_parameters: dict,
93
+ ) -> None:
94
+ """
95
+ The main sync function for Azure Logic Apps.
96
+ """
97
+ logger.info(f"Syncing Azure Logic Apps for subscription {subscription_id}.")
98
+ raw_apps = get_logic_apps(credentials, subscription_id)
99
+ transformed_apps = transform_logic_apps(raw_apps)
100
+ load_logic_apps(neo4j_session, transformed_apps, subscription_id, update_tag)
101
+ cleanup_logic_apps(neo4j_session, common_job_parameters)
@@ -0,0 +1,105 @@
1
+ import logging
2
+ from typing import Any
3
+
4
+ import neo4j
5
+ from azure.core.exceptions import HttpResponseError
6
+ from azure.mgmt.monitor import MonitorManagementClient
7
+
8
+ from cartography.client.core.tx import load
9
+ from cartography.graph.job import GraphJob
10
+ from cartography.models.azure.monitor import AzureMonitorMetricAlertSchema
11
+ from cartography.util import timeit
12
+
13
+ from .util.credentials import Credentials
14
+
15
+ logger = logging.getLogger(__name__)
16
+
17
+
18
+ @timeit
19
+ def get_metric_alerts(client: MonitorManagementClient) -> list[dict]:
20
+ """
21
+ Get a list of Metric Alerts from the given Azure subscription.
22
+ """
23
+ try:
24
+ return [
25
+ alert.as_dict() for alert in client.metric_alerts.list_by_subscription()
26
+ ]
27
+ except HttpResponseError:
28
+ logger.warning(
29
+ "Failed to get Azure Monitor Metric Alerts due to a transient error.",
30
+ exc_info=True,
31
+ )
32
+ return []
33
+
34
+
35
+ def transform_metric_alerts(metric_alerts: list[dict]) -> list[dict]:
36
+ """
37
+ Transform the raw API response to the dictionary structure that the model expects.
38
+ """
39
+ transformed_alerts: list[dict[str, Any]] = []
40
+ for alert in metric_alerts:
41
+ transformed_alert = {
42
+ "id": alert.get("id"),
43
+ "name": alert.get("name"),
44
+ "location": alert.get("location"),
45
+ "description": alert.get("description"),
46
+ "severity": alert.get("severity"),
47
+ "enabled": alert.get("enabled"),
48
+ "window_size": str(alert.get("window_size")),
49
+ "evaluation_frequency": str(alert.get("evaluation_frequency")),
50
+ "last_updated_time": alert.get("properties", {}).get("last_updated_time"),
51
+ }
52
+ transformed_alerts.append(transformed_alert)
53
+ return transformed_alerts
54
+
55
+
56
+ @timeit
57
+ def load_metric_alerts(
58
+ neo4j_session: neo4j.Session,
59
+ data: list[dict[str, Any]],
60
+ subscription_id: str,
61
+ update_tag: int,
62
+ ) -> None:
63
+ """
64
+ Load the transformed Azure Monitor Metric Alert data to Neo4j.
65
+ """
66
+ load(
67
+ neo4j_session,
68
+ AzureMonitorMetricAlertSchema(),
69
+ data,
70
+ lastupdated=update_tag,
71
+ AZURE_SUBSCRIPTION_ID=subscription_id,
72
+ )
73
+
74
+
75
+ @timeit
76
+ def cleanup_metric_alerts(
77
+ neo4j_session: neo4j.Session, common_job_parameters: dict
78
+ ) -> None:
79
+ """
80
+ Run the cleanup job for Azure Monitor Metric Alerts.
81
+ """
82
+ GraphJob.from_node_schema(
83
+ AzureMonitorMetricAlertSchema(), common_job_parameters
84
+ ).run(neo4j_session)
85
+
86
+
87
+ @timeit
88
+ def sync(
89
+ neo4j_session: neo4j.Session,
90
+ credentials: Credentials,
91
+ subscription_id: str,
92
+ update_tag: int,
93
+ common_job_parameters: dict,
94
+ ) -> None:
95
+ """
96
+ The main sync function for Azure Monitor.
97
+ """
98
+ logger.info(
99
+ f"Syncing Azure Monitor Metric Alerts for subscription {subscription_id}."
100
+ )
101
+ client = MonitorManagementClient(credentials.credential, subscription_id)
102
+ raw_alerts = get_metric_alerts(client)
103
+ transformed_alerts = transform_metric_alerts(raw_alerts)
104
+ load_metric_alerts(neo4j_session, transformed_alerts, subscription_id, update_tag)
105
+ cleanup_metric_alerts(neo4j_session, common_job_parameters)