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,216 @@
1
+ """
2
+ Framework and Fact execution logic for Cartography rules.
3
+ """
4
+
5
+ from neo4j import Driver
6
+ from neo4j import GraphDatabase
7
+
8
+ from cartography.client.core.tx import read_list_of_dicts_tx
9
+ from cartography.rules.data.rules import RULES
10
+ from cartography.rules.formatters import _format_and_output_results
11
+ from cartography.rules.formatters import _generate_neo4j_browser_url
12
+ from cartography.rules.spec.model import Fact
13
+ from cartography.rules.spec.model import Maturity
14
+ from cartography.rules.spec.model import Rule
15
+ from cartography.rules.spec.result import CounterResult
16
+ from cartography.rules.spec.result import FactResult
17
+ from cartography.rules.spec.result import RuleResult
18
+
19
+
20
+ def _run_fact(
21
+ fact: Fact,
22
+ rule: Rule,
23
+ driver: Driver,
24
+ database: str,
25
+ counter: CounterResult,
26
+ output_format: str,
27
+ neo4j_uri: str,
28
+ ) -> FactResult:
29
+ """Execute a single fact and return the result."""
30
+ if output_format == "text":
31
+ print(
32
+ f"\n\033[1mFact {counter.current_fact}/{counter.total_facts}: {fact.name}\033[0m"
33
+ )
34
+ # Display rule
35
+ print(f" \033[36m{'Rule:':<12}\033[0m {rule.id} - {rule.name}")
36
+ # Display fact details
37
+ print(f" \033[36m{'Fact ID:':<12}\033[0m {fact.id}")
38
+ print(f" \033[36m{'Description:':<12}\033[0m {fact.description}")
39
+ print(f" \033[36m{'Provider:':<12}\033[0m {fact.module.value}")
40
+
41
+ # Generate and display clickable Neo4j Browser URL
42
+ browser_url = _generate_neo4j_browser_url(neo4j_uri, fact.cypher_visual_query)
43
+ print(
44
+ f" \033[36m{'Neo4j Query:':<12}\033[0m \033]8;;{browser_url}\033\\Click to run visual query\033]8;;\033\\"
45
+ )
46
+
47
+ with driver.session(database=database) as session:
48
+ raw_findings = session.execute_read(read_list_of_dicts_tx, fact.cypher_query)
49
+ findings = rule.parse_results(fact, raw_findings)
50
+ findings_count = len(findings)
51
+
52
+ if output_format == "text":
53
+ if findings_count > 0:
54
+ print(f" \033[36m{'Results:':<12}\033[0m {findings_count} item(s) found")
55
+
56
+ # Show sample findings
57
+ print(" Sample results:")
58
+ for idx, finding in enumerate(findings[:3]): # Show first 3
59
+ # Format rule output nicely
60
+ formatted_items = []
61
+ for key, value in finding.__class__.model_fields.items():
62
+ if value is not None:
63
+ # Truncate long values
64
+ actual_value = getattr(finding, key)
65
+ str_value = str(actual_value)
66
+ if len(str_value) > 50:
67
+ str_value = str_value[:47] + "..."
68
+ formatted_items.append(f"{key}={str_value}")
69
+ if formatted_items:
70
+ print(f" {idx + 1}. {', '.join(formatted_items)}")
71
+
72
+ if findings_count > 3:
73
+ print(
74
+ f" ... and {findings_count - 3} more (use --output json to see all)"
75
+ )
76
+ else:
77
+ print(f" \033[36m{'Results:':<12}\033[0m No items found")
78
+
79
+ # Create and return fact result
80
+ counter.total_findings += findings_count
81
+
82
+ return FactResult(
83
+ fact_id=fact.id,
84
+ fact_name=fact.name,
85
+ fact_description=fact.description,
86
+ fact_provider=fact.module.value,
87
+ findings=findings,
88
+ )
89
+
90
+
91
+ def _run_single_rule(
92
+ rule_name: str,
93
+ driver: GraphDatabase.driver,
94
+ database: str,
95
+ output_format: str,
96
+ neo4j_uri: str,
97
+ fact_filter: str | None = None,
98
+ exclude_experimental: bool = False,
99
+ ) -> RuleResult:
100
+ """Execute a single rule and return results."""
101
+ rule = RULES[rule_name]
102
+ counter = CounterResult()
103
+
104
+ filtered_facts: list[Fact] = []
105
+ for fact in rule.facts:
106
+ if exclude_experimental and fact.maturity != Maturity.STABLE:
107
+ continue
108
+ if fact_filter:
109
+ if fact.id.lower() != fact_filter.lower():
110
+ continue
111
+ counter.total_facts += 1
112
+ filtered_facts.append(fact)
113
+
114
+ if output_format == "text":
115
+ print(f"Executing {rule.name} rule")
116
+ if fact_filter:
117
+ print(f"Filtered to fact: {fact_filter}")
118
+ print(f"Total facts: {counter.total_facts}")
119
+
120
+ # Execute requirements and collect results
121
+ rule_results = []
122
+
123
+ for fact in filtered_facts:
124
+ counter.current_fact += 1
125
+ fact_result = _run_fact(
126
+ fact,
127
+ rule,
128
+ driver,
129
+ database,
130
+ counter,
131
+ output_format,
132
+ neo4j_uri,
133
+ )
134
+ rule_results.append(fact_result)
135
+
136
+ # Create and return rule result
137
+ return RuleResult(
138
+ rule_id=rule.id,
139
+ rule_name=rule.name,
140
+ rule_description=rule.description,
141
+ facts=rule_results,
142
+ counter=counter,
143
+ )
144
+
145
+
146
+ def run_rules(
147
+ rule_names: list[str],
148
+ uri: str,
149
+ neo4j_user: str,
150
+ neo4j_password: str,
151
+ neo4j_database: str,
152
+ output_format: str = "text",
153
+ fact_filter: str | None = None,
154
+ exclude_experimental: bool = False,
155
+ ):
156
+ """
157
+ Execute the specified rules and present results.
158
+
159
+ :param rule_names: The names of the rules to execute.
160
+ :param uri: The URI of the Neo4j database. E.g. "bolt://localhost:7687" or "neo4j+s://tenant123.databases.neo4j.io:7687"
161
+ :param neo4j_user: The username for the Neo4j database.
162
+ :param neo4j_password: The password for the Neo4j database.
163
+ :param neo4j_database: The name of the Neo4j database.
164
+ :param output_format: Either "text" or "json". Defaults to "text".
165
+ :param fact_filter: Optional fact ID to filter execution (case-insensitive).
166
+ :param exclude_experimental: Whether to exclude experimental facts from execution.
167
+ :return: The exit code.
168
+ """
169
+ # Validate all rules exist
170
+ for rule_name in rule_names:
171
+ if rule_name not in RULES:
172
+ if output_format == "text":
173
+ print(f"Unknown rule: {rule_name}")
174
+ print(f"Available rules: {', '.join(RULES.keys())}")
175
+ return 1
176
+
177
+ # Connect to Neo4j
178
+ if output_format == "text":
179
+ print(f"Connecting to Neo4j at {uri}...")
180
+ driver = GraphDatabase.driver(uri, auth=(neo4j_user, neo4j_password))
181
+
182
+ try:
183
+ driver.verify_connectivity()
184
+
185
+ # Execute rules
186
+ all_results = []
187
+ total_facts = 0
188
+ total_findings = 0
189
+
190
+ for i, rule_name in enumerate(rule_names):
191
+ if output_format == "text" and len(rule_names) > 1:
192
+ if i > 0:
193
+ print("\n" + "=" * 60)
194
+ print(f"Executing rule {i + 1}/{len(rule_names)}: {rule_name}")
195
+
196
+ rule_result = _run_single_rule(
197
+ rule_name,
198
+ driver,
199
+ neo4j_database,
200
+ output_format,
201
+ uri,
202
+ fact_filter,
203
+ exclude_experimental,
204
+ )
205
+ all_results.append(rule_result)
206
+ total_facts += rule_result.counter.total_facts
207
+ total_findings += rule_result.counter.total_findings
208
+
209
+ # Output results
210
+ _format_and_output_results(
211
+ all_results, rule_names, output_format, total_facts, total_findings
212
+ )
213
+
214
+ return 0
215
+ finally:
216
+ driver.close()
File without changes
@@ -0,0 +1,267 @@
1
+ import json
2
+ import logging
3
+ from dataclasses import dataclass
4
+ from dataclasses import field
5
+ from enum import Enum
6
+ from typing import Any
7
+ from typing import no_type_check
8
+
9
+ from pydantic import BaseModel
10
+ from pydantic import ConfigDict
11
+ from pydantic import model_validator
12
+
13
+ logger = logging.getLogger(__name__)
14
+
15
+
16
+ class Module(str, Enum):
17
+ """Services that can be monitored"""
18
+
19
+ AIRBYTE = "Airbyte"
20
+ """Airbyte data integration"""
21
+
22
+ ANTHROPIC = "Anthropic"
23
+ """Anthropic AI"""
24
+
25
+ AWS = "AWS"
26
+ """Amazon Web Services"""
27
+
28
+ AZURE = "Azure"
29
+ """Microsoft Azure"""
30
+
31
+ BIGFIX = "BigFix"
32
+ """BigFix patch management"""
33
+
34
+ CLOUDFLARE = "Cloudflare"
35
+ """Cloudflare services"""
36
+
37
+ CROWDSTRIKE = "CrowdStrike"
38
+ """CrowdStrike endpoint security"""
39
+
40
+ DIGITALOCEAN = "DigitalOcean"
41
+ """DigitalOcean cloud services"""
42
+
43
+ DUO = "Duo"
44
+ """Duo authentication"""
45
+
46
+ ENTRA = "Entra"
47
+ """Entra identity and access management"""
48
+
49
+ GCP = "GCP"
50
+ """Google Cloud Platform"""
51
+
52
+ GITHUB = "GitHub"
53
+ """GitHub source code management"""
54
+
55
+ GOOGLEWORKSPACE = "GoogleWorkspace"
56
+ """Google Workspace identity and access management"""
57
+
58
+ JAMF = "Jamf"
59
+ """Jamf endpoint security"""
60
+
61
+ KANDJI = "Kandji"
62
+ """Kandji endpoint security"""
63
+
64
+ KEYCLOAK = "Keycloak"
65
+ """Keycloak identity and access management"""
66
+
67
+ KUBERNETES = "Kubernetes"
68
+ """Kubernetes cluster security"""
69
+
70
+ LASTPASS = "LastPass"
71
+ """LastPass password manager"""
72
+
73
+ OCI = "OCI"
74
+ """Oracle Cloud Infrastructure"""
75
+
76
+ OKTA = "Okta"
77
+ """Okta identity and access management"""
78
+
79
+ OPENAI = "OpenAI"
80
+ """OpenAI"""
81
+
82
+ PAGERDUTY = "PagerDuty"
83
+ """PagerDuty incident response"""
84
+
85
+ SCALEWAY = "Scaleway"
86
+ """Scaleway cloud services"""
87
+
88
+ SEMGREP = "Semgrep"
89
+ """Semgrep code security"""
90
+
91
+ SENTINELONE = "SentinelOne"
92
+ """SentinelOne endpoint security"""
93
+
94
+ SNIPEIT = "Snipe-IT"
95
+ """Snipe-IT asset management"""
96
+
97
+ SPACELIFT = "SpaceLift"
98
+ """SpaceLift infrastructure as code"""
99
+
100
+ TAILSCALE = "TailScale"
101
+ """TailScale VPN"""
102
+
103
+ TRIVY = "Trivy"
104
+ """Trivy vulnerability scanner"""
105
+
106
+ CROSS_CLOUD = "Cross-Cloud"
107
+ """Multi-cloud or provider-agnostic rules"""
108
+
109
+
110
+ class Maturity(str, Enum):
111
+ """Maturity levels for Facts."""
112
+
113
+ EXPERIMENTAL = "EXPERIMENTAL"
114
+ """Experimental: Initial version, may be unstable or incomplete."""
115
+
116
+ STABLE = "STABLE"
117
+ """Stable: Well-tested and reliable for production use."""
118
+
119
+
120
+ MODULE_TO_CARTOGRAPHY_INTEL = {
121
+ Module.AIRBYTE: "airbyte",
122
+ Module.ANTHROPIC: "anthropic",
123
+ Module.AWS: "aws",
124
+ Module.AZURE: "azure",
125
+ Module.BIGFIX: "bigfix",
126
+ Module.CLOUDFLARE: "cloudflare",
127
+ Module.CROWDSTRIKE: "crowdstrike",
128
+ Module.DIGITALOCEAN: "digitalocean",
129
+ Module.DUO: "duo",
130
+ Module.ENTRA: "entra",
131
+ Module.GCP: "gcp",
132
+ Module.GITHUB: "github",
133
+ Module.GOOGLEWORKSPACE: "googleworkspace",
134
+ Module.JAMF: "jamf",
135
+ Module.KANDJI: "kandji",
136
+ Module.KEYCLOAK: "keycloak",
137
+ Module.KUBERNETES: "kubernetes",
138
+ Module.LASTPASS: "lastpass",
139
+ Module.OCI: "oci",
140
+ Module.OKTA: "okta",
141
+ Module.OPENAI: "openai",
142
+ Module.PAGERDUTY: "pagerduty",
143
+ Module.SCALEWAY: "scaleway",
144
+ Module.SEMGREP: "semgrep",
145
+ Module.SENTINELONE: "sentinelone",
146
+ Module.SNIPEIT: "snipeit",
147
+ Module.SPACELIFT: "spacelift",
148
+ Module.TAILSCALE: "tailscale",
149
+ Module.TRIVY: "trivy",
150
+ }
151
+
152
+
153
+ @dataclass(frozen=True)
154
+ class RuleReference:
155
+ """A reference document for a Rule."""
156
+
157
+ text: str
158
+ url: str
159
+
160
+
161
+ @dataclass(frozen=True)
162
+ class Fact:
163
+ """A Fact gathers information about the environment using a Cypher query."""
164
+
165
+ id: str
166
+ """A descriptive identifier for the Fact. By convention, should be lowercase and use underscores like `rule-name-module`."""
167
+ name: str
168
+ """A descriptive name for the Fact."""
169
+ description: str
170
+ """More details about the Fact. Information on details that we're querying for."""
171
+ module: Module
172
+ """The Module that the Fact is associated with e.g. AWS, Azure, GCP, etc."""
173
+ maturity: Maturity
174
+ """The maturity level of the Fact query."""
175
+ # TODO can we lint the queries. full-on integ tests here are overkill though.
176
+ cypher_query: str
177
+ """The Cypher query to gather information about the environment. Returns data field by field e.g. `RETURN node.prop1, node.prop2`."""
178
+ cypher_visual_query: str
179
+ """
180
+ Same as `cypher_query`, returns it in a visual format for the web interface with `.. RETURN *`.
181
+ Often includes additional relationships to help give context.
182
+ """
183
+
184
+
185
+ class Finding(BaseModel):
186
+ """Base class for Rule finding models."""
187
+
188
+ # TODO: make this property mandatory one all modules have been updated to new datamodel
189
+ source: str | None = None
190
+ """The source of the Fact data, e.g. the specific Cartography module that ingested the data. This field is useful especially for CROSS_CLOUD facts."""
191
+ extra: dict[str, Any] = {}
192
+ """A dictionary to hold any extra fields returned by the Fact query that are not explicitly defined in the output model."""
193
+
194
+ # Config to coerce numbers to strings during instantiation
195
+ model_config = ConfigDict(coerce_numbers_to_str=True)
196
+
197
+ # Coerce o strings
198
+ @no_type_check
199
+ @model_validator(mode="before")
200
+ @classmethod
201
+ def coerce_to_string(cls, data: Any) -> Any:
202
+ if not isinstance(data, dict):
203
+ return data
204
+
205
+ for name, f in cls.model_fields.items():
206
+ if f.annotation is not str:
207
+ continue
208
+ if name not in data:
209
+ continue
210
+ v = data[name]
211
+ if isinstance(v, (list, tuple, set)):
212
+ data[name] = ", ".join(v)
213
+ if isinstance(v, dict):
214
+ data[name] = json.dumps(v)
215
+
216
+ return data
217
+
218
+
219
+ @dataclass(frozen=True)
220
+ class Rule:
221
+ """A Rule represents a security issue or misconfiguration detected in the environment."""
222
+
223
+ id: str
224
+ """A unique identifier for the Rule. Should be globally unique within Cartography."""
225
+ name: str
226
+ """A brief name for the Rule."""
227
+ tags: tuple[str, ...]
228
+ """Tags associated with the Rule for categorization and filtering."""
229
+ description: str
230
+ """A brief description of the Rule. Can include details about the security issue or misconfiguration."""
231
+ version: str
232
+ """The version of the Rule definition."""
233
+ facts: tuple[Fact, ...]
234
+ """The Facts that contribute to this Rule."""
235
+ output_model: type[Finding]
236
+ """The output model class for the Rule."""
237
+ references: list[RuleReference] = field(default_factory=list)
238
+ """References or links to external resources related to the Rule."""
239
+
240
+ @property
241
+ def modules(self) -> set[Module]:
242
+ """Returns the set of modules associated with this rule."""
243
+ return {fact.module for fact in self.facts}
244
+
245
+ def get_fact_by_id(self, fact_id: str) -> Fact | None:
246
+ """Returns a fact by its ID, or None if not found."""
247
+ for fact in self.facts:
248
+ if fact.id.lower() == fact_id.lower():
249
+ return fact
250
+ return None
251
+
252
+ def parse_results(
253
+ self, fact: Fact, fact_results: list[dict[str, Any]]
254
+ ) -> list[Finding]:
255
+ # DOC
256
+ result: list[Finding] = []
257
+ for result_item in fact_results:
258
+ parsed_output: dict[str, Any] = {"extra": {}, "source": fact.module.value}
259
+ for key, value in result_item.items():
260
+ if value is None:
261
+ continue
262
+ if key not in self.output_model.model_fields:
263
+ parsed_output["extra"][key] = value
264
+ else:
265
+ parsed_output[key] = value
266
+ result.append(self.output_model(**parsed_output))
267
+ return result
@@ -0,0 +1,38 @@
1
+ # Execution result classes
2
+ from dataclasses import dataclass
3
+ from dataclasses import field
4
+
5
+ from cartography.rules.spec.model import Finding
6
+
7
+
8
+ @dataclass
9
+ class CounterResult:
10
+ current_fact: int = 0
11
+ total_facts: int = 0
12
+ total_findings: int = 0
13
+
14
+
15
+ @dataclass
16
+ class FactResult:
17
+ """
18
+ Results for a single Fact.
19
+ """
20
+
21
+ fact_id: str
22
+ fact_name: str
23
+ fact_description: str
24
+ fact_provider: str
25
+ findings: list[Finding] = field(default_factory=list)
26
+
27
+
28
+ @dataclass
29
+ class RuleResult:
30
+ """
31
+ Results for a single Rule.
32
+ """
33
+
34
+ rule_id: str
35
+ rule_name: str
36
+ rule_description: str
37
+ counter: CounterResult
38
+ facts: list[FactResult] = field(default_factory=list)
cartography/sync.py CHANGED
@@ -13,6 +13,7 @@ import neo4j.exceptions
13
13
  from neo4j import GraphDatabase
14
14
  from statsd import StatsClient
15
15
 
16
+ import cartography.intel.airbyte
16
17
  import cartography.intel.analysis
17
18
  import cartography.intel.anthropic
18
19
  import cartography.intel.aws
@@ -27,16 +28,26 @@ import cartography.intel.duo
27
28
  import cartography.intel.entra
28
29
  import cartography.intel.gcp
29
30
  import cartography.intel.github
31
+ import cartography.intel.googleworkspace
30
32
  import cartography.intel.gsuite
33
+ import cartography.intel.jamf
31
34
  import cartography.intel.kandji
35
+ import cartography.intel.keycloak
32
36
  import cartography.intel.kubernetes
33
37
  import cartography.intel.lastpass
34
38
  import cartography.intel.oci
35
39
  import cartography.intel.okta
40
+ import cartography.intel.ontology
36
41
  import cartography.intel.openai
42
+ import cartography.intel.pagerduty
43
+ import cartography.intel.scaleway
37
44
  import cartography.intel.semgrep
45
+ import cartography.intel.sentinelone
46
+ import cartography.intel.slack
38
47
  import cartography.intel.snipeit
48
+ import cartography.intel.spacelift
39
49
  import cartography.intel.tailscale
50
+ import cartography.intel.trivy
40
51
  from cartography.config import Config
41
52
  from cartography.stats import set_stats_client
42
53
  from cartography.util import STATUS_FAILURE
@@ -45,9 +56,10 @@ from cartography.util import STATUS_SUCCESS
45
56
  logger = logging.getLogger(__name__)
46
57
 
47
58
 
48
- TOP_LEVEL_MODULES = OrderedDict(
59
+ TOP_LEVEL_MODULES: OrderedDict[str, Callable[..., None]] = OrderedDict(
49
60
  { # preserve order so that the default sync always runs `analysis` at the very end
50
61
  "create-indexes": cartography.intel.create_indexes.run,
62
+ "airbyte": cartography.intel.airbyte.start_airbyte_ingestion,
51
63
  "anthropic": cartography.intel.anthropic.start_anthropic_ingestion,
52
64
  "aws": cartography.intel.aws.start_aws_ingestion,
53
65
  "azure": cartography.intel.azure.start_azure_ingestion,
@@ -55,6 +67,7 @@ TOP_LEVEL_MODULES = OrderedDict(
55
67
  "cloudflare": cartography.intel.cloudflare.start_cloudflare_ingestion,
56
68
  "crowdstrike": cartography.intel.crowdstrike.start_crowdstrike_ingestion,
57
69
  "gcp": cartography.intel.gcp.start_gcp_ingestion,
70
+ "googleworkspace": cartography.intel.googleworkspace.start_googleworkspace_ingestion,
58
71
  "gsuite": cartography.intel.gsuite.start_gsuite_ingestion,
59
72
  "cve": cartography.intel.cve.start_cve_ingestion,
60
73
  "oci": cartography.intel.oci.start_oci_ingestion,
@@ -63,13 +76,23 @@ TOP_LEVEL_MODULES = OrderedDict(
63
76
  "github": cartography.intel.github.start_github_ingestion,
64
77
  "digitalocean": cartography.intel.digitalocean.start_digitalocean_ingestion,
65
78
  "kandji": cartography.intel.kandji.start_kandji_ingestion,
79
+ "keycloak": cartography.intel.keycloak.start_keycloak_ingestion,
66
80
  "kubernetes": cartography.intel.kubernetes.start_k8s_ingestion,
67
81
  "lastpass": cartography.intel.lastpass.start_lastpass_ingestion,
68
82
  "bigfix": cartography.intel.bigfix.start_bigfix_ingestion,
69
83
  "duo": cartography.intel.duo.start_duo_ingestion,
84
+ "scaleway": cartography.intel.scaleway.start_scaleway_ingestion,
70
85
  "semgrep": cartography.intel.semgrep.start_semgrep_ingestion,
71
86
  "snipeit": cartography.intel.snipeit.start_snipeit_ingestion,
72
87
  "tailscale": cartography.intel.tailscale.start_tailscale_ingestion,
88
+ "jamf": cartography.intel.jamf.start_jamf_ingestion,
89
+ "pagerduty": cartography.intel.pagerduty.start_pagerduty_ingestion,
90
+ "trivy": cartography.intel.trivy.start_trivy_ingestion,
91
+ "sentinelone": cartography.intel.sentinelone.start_sentinelone_ingestion,
92
+ "slack": cartography.intel.slack.start_slack_ingestion,
93
+ "spacelift": cartography.intel.spacelift.start_spacelift_ingestion,
94
+ "ontology": cartography.intel.ontology.run,
95
+ # Analysis should be the last stage
73
96
  "analysis": cartography.intel.analysis.run,
74
97
  }
75
98
  )
@@ -197,14 +220,11 @@ class Sync:
197
220
  intel_module_info.name,
198
221
  )
199
222
  available_modules[intel_module_info.name] = v
223
+ available_modules["ontology"] = cartography.intel.ontology.run
200
224
  available_modules["analysis"] = cartography.intel.analysis.run
201
225
  return available_modules
202
226
 
203
227
 
204
- # Used to avoid repeatedly calling Sync.list_intel_modules()
205
- TOP_LEVEL_MODULES = Sync.list_intel_modules()
206
-
207
-
208
228
  def run_with_config(sync: Sync, config: Union[Config, argparse.Namespace]) -> int:
209
229
  """
210
230
  Execute the cartography.sync.Sync.run method with parameters built from the given configuration object.