prowler-cloud 5.17.1__py3-none-any.whl → 5.18.1__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 (219) hide show
  1. dashboard/compliance/hipaa_azure.py +25 -0
  2. dashboard/pages/overview.py +20 -11
  3. prowler/AGENTS.md +1 -1
  4. prowler/CHANGELOG.md +43 -0
  5. prowler/__main__.py +5 -0
  6. prowler/compliance/azure/hipaa_azure.json +820 -0
  7. prowler/compliance/m365/cis_4.0_m365.json +6 -2
  8. prowler/compliance/m365/cis_6.0_m365.json +6 -2
  9. prowler/compliance/m365/iso27001_2022_m365.json +13 -11
  10. prowler/compliance/openstack/__init__.py +0 -0
  11. prowler/config/config.py +2 -1
  12. prowler/config/config.yaml +4 -1
  13. prowler/config/openstack_mutelist_example.yaml +60 -0
  14. prowler/lib/check/check.py +4 -0
  15. prowler/lib/check/models.py +27 -2
  16. prowler/lib/cli/parser.py +3 -2
  17. prowler/lib/outputs/finding.py +14 -0
  18. prowler/lib/outputs/html/html.py +72 -0
  19. prowler/lib/outputs/jira/jira.py +3 -3
  20. prowler/lib/outputs/outputs.py +2 -0
  21. prowler/lib/outputs/summary_table.py +7 -0
  22. prowler/lib/timeline/__init__.py +0 -0
  23. prowler/lib/timeline/models.py +27 -0
  24. prowler/lib/timeline/timeline.py +36 -0
  25. prowler/providers/aws/lib/cloudtrail_timeline/__init__.py +0 -0
  26. prowler/providers/aws/lib/cloudtrail_timeline/cloudtrail_timeline.py +218 -0
  27. prowler/providers/aws/services/codebuild/codebuild_project_webhook_filters_use_anchored_patterns/__init__.py +0 -0
  28. prowler/providers/aws/services/codebuild/codebuild_project_webhook_filters_use_anchored_patterns/codebuild_project_webhook_filters_use_anchored_patterns.metadata.json +40 -0
  29. prowler/providers/aws/services/codebuild/codebuild_project_webhook_filters_use_anchored_patterns/codebuild_project_webhook_filters_use_anchored_patterns.py +58 -0
  30. prowler/providers/aws/services/codebuild/codebuild_service.py +45 -0
  31. prowler/providers/aws/services/dynamodb/dynamodb_table_cross_account_access/dynamodb_table_cross_account_access.metadata.json +1 -1
  32. prowler/providers/aws/services/dynamodb/dynamodb_table_cross_account_access/dynamodb_table_cross_account_access.py +4 -0
  33. prowler/providers/aws/services/eventbridge/eventbridge_bus_cross_account_access/eventbridge_bus_cross_account_access.metadata.json +1 -1
  34. prowler/providers/aws/services/eventbridge/eventbridge_bus_cross_account_access/eventbridge_bus_cross_account_access.py +4 -0
  35. prowler/providers/aws/services/eventbridge/eventbridge_schema_registry_cross_account_access/eventbridge_schema_registry_cross_account_access.metadata.json +1 -1
  36. prowler/providers/aws/services/eventbridge/eventbridge_schema_registry_cross_account_access/eventbridge_schema_registry_cross_account_access.py +2 -0
  37. prowler/providers/aws/services/iam/lib/policy.py +19 -3
  38. prowler/providers/aws/services/rds/rds_instance_extended_support/__init__.py +0 -0
  39. prowler/providers/aws/services/rds/rds_instance_extended_support/rds_instance_extended_support.metadata.json +41 -0
  40. prowler/providers/aws/services/rds/rds_instance_extended_support/rds_instance_extended_support.py +37 -0
  41. prowler/providers/aws/services/rds/rds_service.py +4 -0
  42. prowler/providers/aws/services/s3/s3_bucket_cross_account_access/s3_bucket_cross_account_access.metadata.json +1 -1
  43. prowler/providers/aws/services/s3/s3_bucket_cross_account_access/s3_bucket_cross_account_access.py +5 -1
  44. prowler/providers/azure/lib/service/service.py +23 -0
  45. prowler/providers/azure/services/app/app_client_certificates_on/app_client_certificates_on.metadata.json +18 -12
  46. prowler/providers/azure/services/app/app_ensure_auth_is_set_up/app_ensure_auth_is_set_up.metadata.json +18 -11
  47. prowler/providers/azure/services/app/app_ensure_http_is_redirected_to_https/app_ensure_http_is_redirected_to_https.metadata.json +19 -12
  48. prowler/providers/azure/services/app/app_ensure_java_version_is_latest/app_ensure_java_version_is_latest.metadata.json +19 -12
  49. prowler/providers/azure/services/app/app_ensure_php_version_is_latest/app_ensure_php_version_is_latest.metadata.json +19 -12
  50. prowler/providers/azure/services/app/app_ensure_python_version_is_latest/app_ensure_python_version_is_latest.metadata.json +19 -12
  51. prowler/providers/azure/services/app/app_ensure_using_http20/app_ensure_using_http20.metadata.json +18 -11
  52. prowler/providers/azure/services/app/app_ftp_deployment_disabled/app_ftp_deployment_disabled.metadata.json +21 -13
  53. prowler/providers/azure/services/app/app_function_access_keys_configured/app_function_access_keys_configured.metadata.json +19 -11
  54. prowler/providers/azure/services/app/app_function_application_insights_enabled/app_function_application_insights_enabled.metadata.json +21 -14
  55. prowler/providers/azure/services/app/app_function_ftps_deployment_disabled/app_function_ftps_deployment_disabled.metadata.json +18 -13
  56. prowler/providers/azure/services/app/app_function_identity_is_configured/app_function_identity_is_configured.metadata.json +20 -13
  57. prowler/providers/azure/services/app/app_function_identity_without_admin_privileges/app_function_identity_without_admin_privileges.metadata.json +18 -11
  58. prowler/providers/azure/services/app/app_function_latest_runtime_version/app_function_latest_runtime_version.metadata.json +20 -13
  59. prowler/providers/azure/services/app/app_function_not_publicly_accessible/app_function_not_publicly_accessible.metadata.json +20 -13
  60. prowler/providers/azure/services/app/app_function_vnet_integration_enabled/app_function_vnet_integration_enabled.metadata.json +21 -14
  61. prowler/providers/azure/services/app/app_http_logs_enabled/app_http_logs_enabled.metadata.json +18 -12
  62. prowler/providers/azure/services/app/app_minimum_tls_version_12/app_minimum_tls_version_12.metadata.json +20 -12
  63. prowler/providers/azure/services/app/app_register_with_identity/app_register_with_identity.metadata.json +18 -11
  64. prowler/providers/azure/services/appinsights/appinsights_ensure_is_configured/appinsights_ensure_is_configured.metadata.json +18 -12
  65. prowler/providers/azure/services/containerregistry/containerregistry_admin_user_disabled/containerregistry_admin_user_disabled.metadata.json +17 -11
  66. prowler/providers/azure/services/containerregistry/containerregistry_not_publicly_accessible/containerregistry_not_publicly_accessible.metadata.json +18 -12
  67. prowler/providers/azure/services/containerregistry/containerregistry_uses_private_link/containerregistry_uses_private_link.metadata.json +21 -13
  68. prowler/providers/azure/services/cosmosdb/cosmosdb_account_firewall_use_selected_networks/cosmosdb_account_firewall_use_selected_networks.metadata.json +20 -12
  69. prowler/providers/azure/services/cosmosdb/cosmosdb_account_use_aad_and_rbac/cosmosdb_account_use_aad_and_rbac.metadata.json +19 -13
  70. prowler/providers/azure/services/cosmosdb/cosmosdb_account_use_private_endpoints/cosmosdb_account_use_private_endpoints.metadata.json +20 -13
  71. prowler/providers/azure/services/databricks/databricks_workspace_cmk_encryption_enabled/databricks_workspace_cmk_encryption_enabled.metadata.json +20 -14
  72. prowler/providers/azure/services/databricks/databricks_workspace_vnet_injection_enabled/databricks_workspace_vnet_injection_enabled.metadata.json +20 -14
  73. prowler/providers/azure/services/defender/defender_additional_email_configured_with_a_security_contact/defender_additional_email_configured_with_a_security_contact.metadata.json +20 -13
  74. prowler/providers/azure/services/defender/defender_assessments_vm_endpoint_protection_installed/defender_assessments_vm_endpoint_protection_installed.metadata.json +17 -11
  75. prowler/providers/azure/services/defender/defender_attack_path_notifications_properly_configured/defender_attack_path_notifications_properly_configured.metadata.json +19 -13
  76. prowler/providers/azure/services/defender/defender_auto_provisioning_log_analytics_agent_vms_on/defender_auto_provisioning_log_analytics_agent_vms_on.metadata.json +20 -13
  77. prowler/providers/azure/services/defender/defender_auto_provisioning_vulnerabilty_assessments_machines_on/defender_auto_provisioning_vulnerabilty_assessments_machines_on.metadata.json +19 -12
  78. prowler/providers/azure/services/defender/defender_container_images_resolved_vulnerabilities/defender_container_images_resolved_vulnerabilities.metadata.json +20 -12
  79. prowler/providers/azure/services/defender/defender_container_images_scan_enabled/defender_container_images_scan_enabled.metadata.json +22 -13
  80. prowler/providers/azure/services/defender/defender_ensure_defender_for_app_services_is_on/defender_ensure_defender_for_app_services_is_on.metadata.json +17 -11
  81. prowler/providers/azure/services/defender/defender_ensure_defender_for_arm_is_on/defender_ensure_defender_for_arm_is_on.metadata.json +17 -11
  82. prowler/providers/azure/services/defender/defender_ensure_defender_for_azure_sql_databases_is_on/defender_ensure_defender_for_azure_sql_databases_is_on.metadata.json +17 -11
  83. prowler/providers/azure/services/defender/defender_ensure_defender_for_containers_is_on/defender_ensure_defender_for_containers_is_on.metadata.json +17 -11
  84. prowler/providers/azure/services/defender/defender_ensure_defender_for_cosmosdb_is_on/defender_ensure_defender_for_cosmosdb_is_on.metadata.json +17 -11
  85. prowler/providers/azure/services/defender/defender_ensure_defender_for_databases_is_on/defender_ensure_defender_for_databases_is_on.metadata.json +17 -11
  86. prowler/providers/azure/services/defender/defender_ensure_defender_for_dns_is_on/defender_ensure_defender_for_dns_is_on.metadata.json +17 -11
  87. prowler/providers/azure/services/defender/defender_ensure_defender_for_keyvault_is_on/defender_ensure_defender_for_keyvault_is_on.metadata.json +17 -11
  88. prowler/providers/azure/services/defender/defender_ensure_defender_for_os_relational_databases_is_on/defender_ensure_defender_for_os_relational_databases_is_on.metadata.json +17 -11
  89. prowler/providers/azure/services/defender/defender_ensure_defender_for_server_is_on/defender_ensure_defender_for_server_is_on.metadata.json +19 -11
  90. prowler/providers/azure/services/defender/defender_ensure_defender_for_sql_servers_is_on/defender_ensure_defender_for_sql_servers_is_on.metadata.json +17 -11
  91. prowler/providers/azure/services/defender/defender_ensure_defender_for_storage_is_on/defender_ensure_defender_for_storage_is_on.metadata.json +17 -11
  92. prowler/providers/azure/services/defender/defender_ensure_iot_hub_defender_is_on/defender_ensure_iot_hub_defender_is_on.metadata.json +17 -11
  93. prowler/providers/azure/services/defender/defender_ensure_mcas_is_enabled/defender_ensure_mcas_is_enabled.metadata.json +20 -12
  94. prowler/providers/azure/services/defender/defender_ensure_notify_alerts_severity_is_high/defender_ensure_notify_alerts_severity_is_high.metadata.json +19 -12
  95. prowler/providers/azure/services/defender/defender_ensure_notify_emails_to_owners/defender_ensure_notify_emails_to_owners.metadata.json +19 -12
  96. prowler/providers/azure/services/defender/defender_ensure_system_updates_are_applied/defender_ensure_system_updates_are_applied.metadata.json +17 -9
  97. prowler/providers/azure/services/defender/defender_ensure_wdatp_is_enabled/defender_ensure_wdatp_is_enabled.metadata.json +21 -13
  98. prowler/providers/azure/services/entra/entra_service.py +3 -11
  99. prowler/providers/azure/services/entra/entra_user_with_vm_access_has_mfa/entra_user_with_vm_access_has_mfa.py +6 -0
  100. prowler/providers/azure/services/iam/iam_custom_role_has_permissions_to_administer_resource_locks/iam_custom_role_has_permissions_to_administer_resource_locks.metadata.json +19 -13
  101. prowler/providers/azure/services/iam/iam_role_user_access_admin_restricted/iam_role_user_access_admin_restricted.metadata.json +16 -10
  102. prowler/providers/azure/services/iam/iam_subscription_roles_owner_custom_not_created/iam_subscription_roles_owner_custom_not_created.metadata.json +18 -12
  103. prowler/providers/azure/services/keyvault/keyvault_rbac_secret_expiration_set/keyvault_rbac_secret_expiration_set.py +10 -11
  104. prowler/providers/azure/services/keyvault/keyvault_service.py +164 -81
  105. prowler/providers/azure/services/mysql/mysql_flexible_server_audit_log_connection_activated/mysql_flexible_server_audit_log_connection_activated.metadata.json +18 -12
  106. prowler/providers/azure/services/mysql/mysql_flexible_server_audit_log_enabled/mysql_flexible_server_audit_log_enabled.metadata.json +19 -12
  107. prowler/providers/azure/services/mysql/mysql_flexible_server_minimum_tls_version_12/mysql_flexible_server_minimum_tls_version_12.metadata.json +18 -12
  108. prowler/providers/azure/services/mysql/mysql_flexible_server_ssl_connection_enabled/mysql_flexible_server_ssl_connection_enabled.metadata.json +19 -12
  109. prowler/providers/azure/services/network/network_bastion_host_exists/network_bastion_host_exists.metadata.json +21 -12
  110. prowler/providers/azure/services/network/network_flow_log_captured_sent/network_flow_log_captured_sent.metadata.json +19 -12
  111. prowler/providers/azure/services/network/network_flow_log_more_than_90_days/network_flow_log_more_than_90_days.metadata.json +21 -12
  112. prowler/providers/azure/services/network/network_http_internet_access_restricted/network_http_internet_access_restricted.metadata.json +18 -12
  113. prowler/providers/azure/services/network/network_public_ip_shodan/network_public_ip_shodan.metadata.json +15 -10
  114. prowler/providers/azure/services/network/network_rdp_internet_access_restricted/network_rdp_internet_access_restricted.metadata.json +20 -12
  115. prowler/providers/azure/services/network/network_ssh_internet_access_restricted/network_ssh_internet_access_restricted.metadata.json +19 -12
  116. prowler/providers/azure/services/network/network_udp_internet_access_restricted/network_udp_internet_access_restricted.metadata.json +19 -12
  117. prowler/providers/azure/services/network/network_watcher_enabled/network_watcher_enabled.metadata.json +21 -13
  118. prowler/providers/azure/services/policy/policy_ensure_asc_enforcement_enabled/policy_ensure_asc_enforcement_enabled.metadata.json +16 -11
  119. prowler/providers/azure/services/postgresql/postgresql_flexible_server_allow_access_services_disabled/postgresql_flexible_server_allow_access_services_disabled.metadata.json +20 -13
  120. prowler/providers/azure/services/postgresql/postgresql_flexible_server_connection_throttling_on/postgresql_flexible_server_connection_throttling_on.metadata.json +18 -12
  121. prowler/providers/azure/services/postgresql/postgresql_flexible_server_enforce_ssl_enabled/postgresql_flexible_server_enforce_ssl_enabled.metadata.json +19 -13
  122. prowler/providers/azure/services/postgresql/postgresql_flexible_server_entra_id_authentication_enabled/postgresql_flexible_server_entra_id_authentication_enabled.metadata.json +4 -4
  123. prowler/providers/azure/services/postgresql/postgresql_flexible_server_log_checkpoints_on/postgresql_flexible_server_log_checkpoints_on.metadata.json +19 -13
  124. prowler/providers/azure/services/postgresql/postgresql_flexible_server_log_connections_on/postgresql_flexible_server_log_connections_on.metadata.json +18 -11
  125. prowler/providers/azure/services/postgresql/postgresql_flexible_server_log_disconnections_on/postgresql_flexible_server_log_disconnections_on.metadata.json +18 -12
  126. prowler/providers/azure/services/postgresql/postgresql_flexible_server_log_retention_days_greater_3/postgresql_flexible_server_log_retention_days_greater_3.metadata.json +18 -12
  127. prowler/providers/azure/services/sqlserver/sqlserver_auditing_enabled/sqlserver_auditing_enabled.metadata.json +20 -13
  128. prowler/providers/azure/services/sqlserver/sqlserver_auditing_retention_90_days/sqlserver_auditing_retention_90_days.metadata.json +20 -12
  129. prowler/providers/azure/services/sqlserver/sqlserver_azuread_administrator_enabled/sqlserver_azuread_administrator_enabled.metadata.json +18 -12
  130. prowler/providers/azure/services/sqlserver/sqlserver_microsoft_defender_enabled/sqlserver_microsoft_defender_enabled.metadata.json +23 -13
  131. prowler/providers/azure/services/sqlserver/sqlserver_recommended_minimal_tls_version/sqlserver_recommended_minimal_tls_version.metadata.json +19 -12
  132. prowler/providers/azure/services/sqlserver/sqlserver_tde_encrypted_with_cmk/sqlserver_tde_encrypted_with_cmk.metadata.json +20 -13
  133. prowler/providers/azure/services/sqlserver/sqlserver_tde_encryption_enabled/sqlserver_tde_encryption_enabled.metadata.json +20 -13
  134. prowler/providers/azure/services/sqlserver/sqlserver_unrestricted_inbound_access/sqlserver_unrestricted_inbound_access.metadata.json +18 -12
  135. prowler/providers/azure/services/sqlserver/sqlserver_va_emails_notifications_admins_enabled/sqlserver_va_emails_notifications_admins_enabled.metadata.json +19 -12
  136. prowler/providers/azure/services/sqlserver/sqlserver_va_periodic_recurring_scans_enabled/sqlserver_va_periodic_recurring_scans_enabled.metadata.json +19 -12
  137. prowler/providers/azure/services/sqlserver/sqlserver_va_scan_reports_configured/sqlserver_va_scan_reports_configured.metadata.json +18 -12
  138. prowler/providers/azure/services/sqlserver/sqlserver_vulnerability_assessment_enabled/sqlserver_vulnerability_assessment_enabled.metadata.json +19 -12
  139. prowler/providers/azure/services/storage/storage_account_key_access_disabled/storage_account_key_access_disabled.metadata.json +17 -12
  140. prowler/providers/azure/services/storage/storage_blob_public_access_level_is_disabled/storage_blob_public_access_level_is_disabled.metadata.json +18 -12
  141. prowler/providers/azure/services/storage/storage_blob_versioning_is_enabled/storage_blob_versioning_is_enabled.metadata.json +19 -11
  142. prowler/providers/azure/services/storage/storage_cross_tenant_replication_disabled/storage_cross_tenant_replication_disabled.metadata.json +19 -13
  143. prowler/providers/azure/services/storage/storage_default_network_access_rule_is_denied/storage_default_network_access_rule_is_denied.metadata.json +19 -12
  144. prowler/providers/azure/services/storage/storage_default_to_entra_authorization_enabled/storage_default_to_entra_authorization_enabled.metadata.json +20 -13
  145. prowler/providers/azure/services/storage/storage_ensure_azure_services_are_trusted_to_access_is_enabled/storage_ensure_azure_services_are_trusted_to_access_is_enabled.metadata.json +17 -10
  146. prowler/providers/azure/services/storage/storage_ensure_encryption_with_customer_managed_keys/storage_ensure_encryption_with_customer_managed_keys.metadata.json +15 -10
  147. prowler/providers/azure/services/storage/storage_ensure_file_shares_soft_delete_is_enabled/storage_ensure_file_shares_soft_delete_is_enabled.metadata.json +18 -12
  148. prowler/providers/azure/services/storage/storage_ensure_minimum_tls_version_12/storage_ensure_minimum_tls_version_12.metadata.json +14 -10
  149. prowler/providers/azure/services/storage/storage_ensure_private_endpoints_in_storage_accounts/storage_ensure_private_endpoints_in_storage_accounts.metadata.json +19 -11
  150. prowler/providers/azure/services/storage/storage_ensure_soft_delete_is_enabled/storage_ensure_soft_delete_is_enabled.metadata.json +17 -12
  151. prowler/providers/azure/services/storage/storage_geo_redundant_enabled/storage_geo_redundant_enabled.metadata.json +19 -12
  152. prowler/providers/azure/services/storage/storage_infrastructure_encryption_is_enabled/storage_infrastructure_encryption_is_enabled.metadata.json +13 -9
  153. prowler/providers/azure/services/storage/storage_key_rotation_90_days/storage_key_rotation_90_days.metadata.json +17 -12
  154. prowler/providers/azure/services/storage/storage_secure_transfer_required_is_enabled/storage_secure_transfer_required_is_enabled.metadata.json +15 -11
  155. prowler/providers/azure/services/storage/storage_smb_channel_encryption_with_secure_algorithm/storage_smb_channel_encryption_with_secure_algorithm.metadata.json +19 -12
  156. prowler/providers/azure/services/storage/storage_smb_protocol_version_is_latest/storage_smb_protocol_version_is_latest.metadata.json +19 -13
  157. prowler/providers/cloudflare/cloudflare_provider.py +95 -12
  158. prowler/providers/cloudflare/lib/arguments/arguments.py +7 -0
  159. prowler/providers/cloudflare/services/dns/dns_record_cname_target_valid/__init__.py +0 -0
  160. prowler/providers/cloudflare/services/dns/dns_record_cname_target_valid/dns_record_cname_target_valid.metadata.json +36 -0
  161. prowler/providers/cloudflare/services/dns/dns_record_cname_target_valid/dns_record_cname_target_valid.py +109 -0
  162. prowler/providers/cloudflare/services/dns/dns_record_no_internal_ip/__init__.py +0 -0
  163. prowler/providers/cloudflare/services/dns/dns_record_no_internal_ip/dns_record_no_internal_ip.metadata.json +36 -0
  164. prowler/providers/cloudflare/services/dns/dns_record_no_internal_ip/dns_record_no_internal_ip.py +73 -0
  165. prowler/providers/cloudflare/services/dns/dns_record_no_wildcard/__init__.py +0 -0
  166. prowler/providers/cloudflare/services/dns/dns_record_no_wildcard/dns_record_no_wildcard.metadata.json +36 -0
  167. prowler/providers/cloudflare/services/dns/dns_record_no_wildcard/dns_record_no_wildcard.py +60 -0
  168. prowler/providers/cloudflare/services/dns/dns_record_proxied/__init__.py +0 -0
  169. prowler/providers/cloudflare/services/dns/dns_record_proxied/dns_record_proxied.metadata.json +36 -0
  170. prowler/providers/cloudflare/services/dns/dns_record_proxied/dns_record_proxied.py +49 -0
  171. prowler/providers/cloudflare/services/dns/dns_service.py +52 -6
  172. prowler/providers/cloudflare/services/firewall/__init__.py +0 -0
  173. prowler/providers/cloudflare/services/firewall/firewall_client.py +4 -0
  174. prowler/providers/cloudflare/services/firewall/firewall_service.py +123 -0
  175. prowler/providers/cloudflare/services/zone/zone_firewall_blocking_rules_configured/__init__.py +0 -0
  176. prowler/providers/cloudflare/services/zone/zone_firewall_blocking_rules_configured/zone_firewall_blocking_rules_configured.metadata.json +36 -0
  177. prowler/providers/cloudflare/services/zone/zone_firewall_blocking_rules_configured/zone_firewall_blocking_rules_configured.py +53 -0
  178. prowler/providers/cloudflare/services/zone/zone_service.py +133 -1
  179. prowler/providers/cloudflare/services/zone/zone_waf_owasp_ruleset_enabled/__init__.py +0 -0
  180. prowler/providers/cloudflare/services/zone/zone_waf_owasp_ruleset_enabled/zone_waf_owasp_ruleset_enabled.metadata.json +36 -0
  181. prowler/providers/cloudflare/services/zone/zone_waf_owasp_ruleset_enabled/zone_waf_owasp_ruleset_enabled.py +58 -0
  182. prowler/providers/common/provider.py +23 -0
  183. prowler/providers/gcp/services/compute/compute_instance_suspended_without_persistent_disks/__init__.py +0 -0
  184. prowler/providers/gcp/services/compute/compute_instance_suspended_without_persistent_disks/compute_instance_suspended_without_persistent_disks.metadata.json +37 -0
  185. prowler/providers/gcp/services/compute/compute_instance_suspended_without_persistent_disks/compute_instance_suspended_without_persistent_disks.py +35 -0
  186. prowler/providers/gcp/services/compute/compute_service.py +2 -0
  187. prowler/providers/m365/lib/powershell/m365_powershell.py +47 -1
  188. prowler/providers/m365/services/defender/defender_service.py +52 -0
  189. prowler/providers/m365/services/defender/defender_zap_for_teams_enabled/__init__.py +0 -0
  190. prowler/providers/m365/services/defender/defender_zap_for_teams_enabled/defender_zap_for_teams_enabled.metadata.json +38 -0
  191. prowler/providers/m365/services/defender/defender_zap_for_teams_enabled/defender_zap_for_teams_enabled.py +53 -0
  192. prowler/providers/m365/services/exchange/exchange_service.py +78 -0
  193. prowler/providers/m365/services/exchange/exchange_shared_mailbox_sign_in_disabled/__init__.py +0 -0
  194. prowler/providers/m365/services/exchange/exchange_shared_mailbox_sign_in_disabled/exchange_shared_mailbox_sign_in_disabled.metadata.json +37 -0
  195. prowler/providers/m365/services/exchange/exchange_shared_mailbox_sign_in_disabled/exchange_shared_mailbox_sign_in_disabled.py +59 -0
  196. prowler/providers/openstack/__init__.py +0 -0
  197. prowler/providers/openstack/exceptions/__init__.py +0 -0
  198. prowler/providers/openstack/exceptions/exceptions.py +166 -0
  199. prowler/providers/openstack/lib/__init__.py +0 -0
  200. prowler/providers/openstack/lib/arguments/__init__.py +0 -0
  201. prowler/providers/openstack/lib/arguments/arguments.py +113 -0
  202. prowler/providers/openstack/lib/mutelist/__init__.py +0 -0
  203. prowler/providers/openstack/lib/mutelist/mutelist.py +31 -0
  204. prowler/providers/openstack/lib/service/__init__.py +0 -0
  205. prowler/providers/openstack/lib/service/service.py +21 -0
  206. prowler/providers/openstack/models.py +100 -0
  207. prowler/providers/openstack/openstack_provider.py +515 -0
  208. prowler/providers/openstack/services/__init__.py +0 -0
  209. prowler/providers/openstack/services/compute/__init__.py +0 -0
  210. prowler/providers/openstack/services/compute/compute_client.py +4 -0
  211. prowler/providers/openstack/services/compute/compute_instance_security_groups_attached/__init__.py +0 -0
  212. prowler/providers/openstack/services/compute/compute_instance_security_groups_attached/compute_instance_security_groups_attached.metadata.json +40 -0
  213. prowler/providers/openstack/services/compute/compute_instance_security_groups_attached/compute_instance_security_groups_attached.py +35 -0
  214. prowler/providers/openstack/services/compute/compute_service.py +63 -0
  215. {prowler_cloud-5.17.1.dist-info → prowler_cloud-5.18.1.dist-info}/METADATA +11 -9
  216. {prowler_cloud-5.17.1.dist-info → prowler_cloud-5.18.1.dist-info}/RECORD +219 -155
  217. {prowler_cloud-5.17.1.dist-info → prowler_cloud-5.18.1.dist-info}/LICENSE +0 -0
  218. {prowler_cloud-5.17.1.dist-info → prowler_cloud-5.18.1.dist-info}/WHEEL +0 -0
  219. {prowler_cloud-5.17.1.dist-info → prowler_cloud-5.18.1.dist-info}/entry_points.txt +0 -0
@@ -4,7 +4,6 @@ from pydantic import BaseModel
4
4
 
5
5
  from prowler.lib.logger import logger
6
6
  from prowler.providers.cloudflare.lib.service.service import CloudflareService
7
- from prowler.providers.cloudflare.services.zone.zone_client import zone_client
8
7
 
9
8
 
10
9
  class DNS(CloudflareService):
@@ -19,10 +18,13 @@ class DNS(CloudflareService):
19
18
  """List DNS records for all zones."""
20
19
  logger.info("DNS - Listing DNS records...")
21
20
  try:
22
- for zone in zone_client.zones.values():
21
+ # Get zones directly from API to avoid circular dependency with zone_client
22
+ zones = self._get_zones()
23
+
24
+ for zone_id, zone_name in zones.items():
23
25
  seen_record_ids: set[str] = set()
24
26
  try:
25
- for record in self.client.dns.records.list(zone_id=zone.id):
27
+ for record in self.client.dns.records.list(zone_id=zone_id):
26
28
  record_id = getattr(record, "id", None)
27
29
  # Prevent infinite loop
28
30
  if record_id in seen_record_ids:
@@ -32,8 +34,8 @@ class DNS(CloudflareService):
32
34
  self.records.append(
33
35
  CloudflareDNSRecord(
34
36
  id=record_id,
35
- zone_id=zone.id,
36
- zone_name=zone.name,
37
+ zone_id=zone_id,
38
+ zone_name=zone_name,
37
39
  name=getattr(record, "name", None),
38
40
  type=getattr(record, "type", None),
39
41
  content=getattr(record, "content", ""),
@@ -43,13 +45,57 @@ class DNS(CloudflareService):
43
45
  )
44
46
  except Exception as error:
45
47
  logger.error(
46
- f"{zone.id} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
48
+ f"{zone_id} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
47
49
  )
48
50
  except Exception as error:
49
51
  logger.error(
50
52
  f"{error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
51
53
  )
52
54
 
55
+ def _get_zones(self) -> dict[str, str]:
56
+ """Get zones directly from Cloudflare API.
57
+
58
+ Returns:
59
+ Dictionary mapping zone_id to zone_name.
60
+ """
61
+ zones = {}
62
+ audited_accounts = self.provider.identity.audited_accounts
63
+ filter_zones = self.provider.filter_zones
64
+ seen_zone_ids: set[str] = set()
65
+
66
+ try:
67
+ for zone in self.client.zones.list():
68
+ zone_id = getattr(zone, "id", None)
69
+ # Prevent infinite loop - skip if we've seen this zone
70
+ if zone_id in seen_zone_ids:
71
+ break
72
+ seen_zone_ids.add(zone_id)
73
+
74
+ zone_account = getattr(zone, "account", None)
75
+ account_id = getattr(zone_account, "id", None) if zone_account else None
76
+
77
+ # Filter by audited accounts
78
+ if audited_accounts and account_id not in audited_accounts:
79
+ continue
80
+
81
+ zone_name = getattr(zone, "name", None)
82
+
83
+ # Apply zone filter if specified via --region
84
+ if (
85
+ filter_zones
86
+ and zone_id not in filter_zones
87
+ and zone_name not in filter_zones
88
+ ):
89
+ continue
90
+
91
+ zones[zone_id] = zone_name
92
+ except Exception as error:
93
+ logger.error(
94
+ f"{error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
95
+ )
96
+
97
+ return zones
98
+
53
99
 
54
100
  class CloudflareDNSRecord(BaseModel):
55
101
  """Cloudflare DNS record representation."""
@@ -0,0 +1,4 @@
1
+ from prowler.providers.cloudflare.services.firewall.firewall_service import Firewall
2
+ from prowler.providers.common.provider import Provider
3
+
4
+ firewall_client = Firewall(Provider.get_global_provider())
@@ -0,0 +1,123 @@
1
+ from typing import Optional
2
+
3
+ from pydantic import BaseModel
4
+
5
+ from prowler.lib.logger import logger
6
+ from prowler.providers.cloudflare.lib.service.service import CloudflareService
7
+
8
+
9
+ class Firewall(CloudflareService):
10
+ """Retrieve Cloudflare firewall rules for all zones."""
11
+
12
+ def __init__(self, provider):
13
+ super().__init__(__class__.__name__, provider)
14
+ self.rules: list["CloudflareFirewallRule"] = []
15
+ self._list_rulesets()
16
+
17
+ def _list_rulesets(self) -> None:
18
+ """List firewall rulesets for all zones."""
19
+ logger.info("Firewall - Listing firewall rulesets...")
20
+ try:
21
+ # Get zones directly from API to avoid circular dependency with zone_client
22
+ zones = self._get_zones()
23
+
24
+ for zone_id, zone_name in zones.items():
25
+ try:
26
+ # Get all rulesets for the zone
27
+ rulesets = self.client.rulesets.list(zone_id=zone_id)
28
+ for ruleset in rulesets:
29
+ ruleset_id = getattr(ruleset, "id", None)
30
+ phase = getattr(ruleset, "phase", None)
31
+ if not ruleset_id:
32
+ continue
33
+
34
+ # Get rules within each ruleset
35
+ try:
36
+ ruleset_detail = self.client.rulesets.get(
37
+ ruleset_id=ruleset_id, zone_id=zone_id
38
+ )
39
+ rules = getattr(ruleset_detail, "rules", []) or []
40
+ for rule in rules:
41
+ self.rules.append(
42
+ CloudflareFirewallRule(
43
+ id=getattr(rule, "id", None),
44
+ zone_id=zone_id,
45
+ zone_name=zone_name,
46
+ ruleset_id=ruleset_id,
47
+ phase=phase,
48
+ action=getattr(rule, "action", None),
49
+ expression=getattr(rule, "expression", None),
50
+ description=getattr(rule, "description", None),
51
+ enabled=getattr(rule, "enabled", True),
52
+ )
53
+ )
54
+ except Exception as error:
55
+ logger.debug(
56
+ f"{zone_id} ruleset {ruleset_id} -- {error.__class__.__name__}: {error}"
57
+ )
58
+ except Exception as error:
59
+ logger.error(
60
+ f"{zone_id} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
61
+ )
62
+ except Exception as error:
63
+ logger.error(
64
+ f"{error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
65
+ )
66
+
67
+ def _get_zones(self) -> dict[str, str]:
68
+ """Get zones directly from Cloudflare API.
69
+
70
+ Returns:
71
+ Dictionary mapping zone_id to zone_name.
72
+ """
73
+ zones = {}
74
+ audited_accounts = self.provider.identity.audited_accounts
75
+ filter_zones = self.provider.filter_zones
76
+ seen_zone_ids: set[str] = set()
77
+
78
+ try:
79
+ for zone in self.client.zones.list():
80
+ zone_id = getattr(zone, "id", None)
81
+ # Prevent infinite loop - skip if we've seen this zone
82
+ if zone_id in seen_zone_ids:
83
+ break
84
+ seen_zone_ids.add(zone_id)
85
+
86
+ zone_account = getattr(zone, "account", None)
87
+ account_id = getattr(zone_account, "id", None) if zone_account else None
88
+
89
+ # Filter by audited accounts
90
+ if audited_accounts and account_id not in audited_accounts:
91
+ continue
92
+
93
+ zone_name = getattr(zone, "name", None)
94
+
95
+ # Apply zone filter if specified via --region
96
+ if (
97
+ filter_zones
98
+ and zone_id not in filter_zones
99
+ and zone_name not in filter_zones
100
+ ):
101
+ continue
102
+
103
+ zones[zone_id] = zone_name
104
+ except Exception as error:
105
+ logger.error(
106
+ f"{error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
107
+ )
108
+
109
+ return zones
110
+
111
+
112
+ class CloudflareFirewallRule(BaseModel):
113
+ """Cloudflare firewall rule representation."""
114
+
115
+ id: Optional[str] = None
116
+ zone_id: str
117
+ zone_name: str
118
+ ruleset_id: Optional[str] = None
119
+ phase: Optional[str] = None
120
+ action: Optional[str] = None
121
+ expression: Optional[str] = None
122
+ description: Optional[str] = None
123
+ enabled: bool = True
@@ -0,0 +1,36 @@
1
+ {
2
+ "Provider": "cloudflare",
3
+ "CheckID": "zone_firewall_blocking_rules_configured",
4
+ "CheckTitle": "Cloudflare Zone Firewall Rules Use Blocking Actions to Protect Against Threats",
5
+ "CheckType": [],
6
+ "ServiceName": "zone",
7
+ "SubServiceName": "",
8
+ "ResourceIdTemplate": "",
9
+ "Severity": "medium",
10
+ "ResourceType": "Zone",
11
+ "ResourceGroup": "network",
12
+ "Description": "**Cloudflare zones** are assessed for **firewall blocking rules** by checking if custom rules use block, challenge, js_challenge, or managed_challenge actions to actively protect against threats rather than only logging.",
13
+ "Risk": "Firewall rules configured only for **logging** provide visibility but no protection.\n- **Confidentiality**: malicious traffic can access and exfiltrate sensitive data\n- **Integrity**: application exploits can modify data without being blocked\n- **Availability**: credential stuffing and abuse attacks reach the origin unimpeded",
14
+ "RelatedUrl": "",
15
+ "AdditionalURLs": [
16
+ "https://developers.cloudflare.com/waf/custom-rules/"
17
+ ],
18
+ "Remediation": {
19
+ "Code": {
20
+ "CLI": "",
21
+ "NativeIaC": "",
22
+ "Other": "1. Log in to the Cloudflare dashboard and select your account and domain\n2. Go to Security > WAF > Custom rules\n3. Review existing rules and their actions\n4. Update rules to use blocking actions (Block, Challenge, JS Challenge, Managed Challenge)\n5. Test rules in log mode first, then enable blocking actions",
23
+ "Terraform": "```hcl\n# Configure firewall rule with blocking action\nresource \"cloudflare_ruleset\" \"blocking_rule\" {\n zone_id = \"<ZONE_ID>\"\n name = \"Block malicious requests\"\n kind = \"zone\"\n phase = \"http_request_firewall_custom\"\n rules {\n action = \"block\" # Actively blocks matching traffic\n expression = \"(ip.geoip.country eq \\\"XX\\\")\"\n description = \"Block traffic from high-risk country\"\n }\n}\n```"
24
+ },
25
+ "Recommendation": {
26
+ "Text": "Configure **firewall rules** with blocking actions to enforce security policies.\n- Use challenge actions for suspicious traffic to verify human visitors\n- Use block actions for known malicious patterns and high-risk sources\n- Test rules in log mode before enabling blocking to avoid false positives\n- Follow the principle of least privilege in rule configuration",
27
+ "Url": "https://hub.prowler.com/checks/cloudflare/zone_firewall_blocking_rules_configured"
28
+ }
29
+ },
30
+ "Categories": [
31
+ "internet-exposed"
32
+ ],
33
+ "DependsOn": [],
34
+ "RelatedTo": [],
35
+ "Notes": "Blocking actions include: block, challenge, js_challenge, managed_challenge. Log-only rules provide visibility but do not prevent attacks."
36
+ }
@@ -0,0 +1,53 @@
1
+ from prowler.lib.check.models import Check, CheckReportCloudflare
2
+ from prowler.providers.cloudflare.services.zone.zone_client import zone_client
3
+
4
+ BLOCKING_ACTIONS = {"block", "challenge", "js_challenge", "managed_challenge"}
5
+
6
+
7
+ class zone_firewall_blocking_rules_configured(Check):
8
+ """Ensure that firewall rules with blocking actions are configured for Cloudflare zones.
9
+
10
+ Firewall rules should use blocking actions (block, challenge, js_challenge,
11
+ managed_challenge) to actively protect against threats rather than only logging
12
+ traffic. Without blocking actions, malicious requests can reach the origin server
13
+ and potentially compromise the application's security.
14
+ """
15
+
16
+ def execute(self) -> list[CheckReportCloudflare]:
17
+ """Execute the firewall blocking rules configured check.
18
+
19
+ Iterates through all Cloudflare zones and verifies that at least one
20
+ firewall rule exists with a blocking action. Blocking actions include
21
+ block, challenge, js_challenge, and managed_challenge.
22
+
23
+ Returns:
24
+ A list of CheckReportCloudflare objects with PASS status if blocking
25
+ rules are configured, or FAIL status if no blocking rules exist.
26
+ """
27
+ findings = []
28
+
29
+ for zone in zone_client.zones.values():
30
+ report = CheckReportCloudflare(
31
+ metadata=self.metadata(),
32
+ resource=zone,
33
+ )
34
+
35
+ # Find blocking rules for this zone
36
+ blocking_rules = [
37
+ rule for rule in zone.firewall_rules if rule.action in BLOCKING_ACTIONS
38
+ ]
39
+
40
+ if blocking_rules:
41
+ report.status = "PASS"
42
+ report.status_extended = (
43
+ f"Zone {zone.name} has firewall rules with blocking actions "
44
+ f"({len(blocking_rules)} rule(s))."
45
+ )
46
+ else:
47
+ report.status = "FAIL"
48
+ report.status_extended = (
49
+ f"Zone {zone.name} has no firewall rules with blocking actions."
50
+ )
51
+ findings.append(report)
52
+
53
+ return findings
@@ -17,6 +17,31 @@ class CloudflareRateLimitRule(BaseModel):
17
17
  expression: Optional[str] = None
18
18
 
19
19
 
20
+ class CloudflareFirewallRule(BaseModel):
21
+ """Represents a firewall rule from custom rulesets."""
22
+
23
+ id: str
24
+ name: str = ""
25
+ description: Optional[str] = None
26
+ action: Optional[str] = None
27
+ enabled: bool = True
28
+ expression: Optional[str] = None
29
+ phase: Optional[str] = None
30
+
31
+ class Config:
32
+ arbitrary_types_allowed = True
33
+
34
+
35
+ class CloudflareWAFRuleset(BaseModel):
36
+ """Represents a WAF ruleset (managed rules) for a zone."""
37
+
38
+ id: str
39
+ name: str
40
+ kind: Optional[str] = None
41
+ phase: Optional[str] = None
42
+ enabled: bool = True
43
+
44
+
20
45
  class Zone(CloudflareService):
21
46
  """Retrieve Cloudflare zones with security-relevant settings."""
22
47
 
@@ -29,6 +54,8 @@ class Zone(CloudflareService):
29
54
  self._get_zones_universal_ssl()
30
55
  self._get_zones_rate_limit_rules()
31
56
  self._get_zones_bot_management()
57
+ self._get_zones_firewall_rules()
58
+ self._get_zones_waf_rulesets()
32
59
 
33
60
  def _list_zones(self) -> None:
34
61
  """List all Cloudflare zones with their basic information."""
@@ -122,7 +149,7 @@ class Zone(CloudflareService):
122
149
 
123
150
  def _get_zones_universal_ssl(self) -> None:
124
151
  """Get Universal SSL settings for all zones."""
125
- logger.info("Zones - Getting Universal SSL settings...")
152
+ logger.info("Zone - Getting Universal SSL settings...")
126
153
  for zone in self.zones.values():
127
154
  try:
128
155
  universal_ssl = self.client.ssl.universal.settings.get(zone_id=zone.id)
@@ -191,6 +218,109 @@ class Zone(CloudflareService):
191
218
  f"{zone.id} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
192
219
  )
193
220
 
221
+ def _get_zones_firewall_rules(self) -> None:
222
+ """Get firewall rules for all zones."""
223
+ logger.info("Zone - Getting firewall rules...")
224
+ for zone in self.zones.values():
225
+ try:
226
+ self._get_zone_firewall_rules(zone)
227
+ except Exception as error:
228
+ logger.error(
229
+ f"{zone.id} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
230
+ )
231
+
232
+ def _get_zone_firewall_rules(self, zone: "CloudflareZone") -> None:
233
+ """List firewall rules from custom rulesets for a zone."""
234
+ seen_ruleset_ids: set[str] = set()
235
+ try:
236
+ for ruleset in self.client.rulesets.list(zone_id=zone.id):
237
+ ruleset_id = getattr(ruleset, "id", "")
238
+ if ruleset_id in seen_ruleset_ids:
239
+ break
240
+ seen_ruleset_ids.add(ruleset_id)
241
+
242
+ ruleset_phase = getattr(ruleset, "phase", "")
243
+ if ruleset_phase in [
244
+ "http_request_firewall_custom",
245
+ "http_ratelimit",
246
+ "http_request_firewall_managed",
247
+ ]:
248
+ try:
249
+ ruleset_detail = self.client.rulesets.get(
250
+ ruleset_id=ruleset_id, zone_id=zone.id
251
+ )
252
+ rules = getattr(ruleset_detail, "rules", []) or []
253
+ seen_rule_ids: set[str] = set()
254
+ for rule in rules:
255
+ rule_id = getattr(rule, "id", "")
256
+ if rule_id in seen_rule_ids:
257
+ break
258
+ seen_rule_ids.add(rule_id)
259
+ try:
260
+ zone.firewall_rules.append(
261
+ CloudflareFirewallRule(
262
+ id=rule_id,
263
+ name=getattr(rule, "description", "")
264
+ or rule_id,
265
+ description=getattr(rule, "description", None),
266
+ action=getattr(rule, "action", None),
267
+ enabled=getattr(rule, "enabled", True),
268
+ expression=getattr(rule, "expression", None),
269
+ phase=ruleset_phase,
270
+ )
271
+ )
272
+ except Exception as error:
273
+ logger.error(
274
+ f"{error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
275
+ )
276
+ except Exception as error:
277
+ logger.error(
278
+ f"{error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
279
+ )
280
+ except Exception as error:
281
+ logger.error(
282
+ f"{error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
283
+ )
284
+
285
+ def _get_zones_waf_rulesets(self) -> None:
286
+ """Get WAF rulesets for all zones."""
287
+ logger.info("Zone - Getting WAF rulesets...")
288
+ for zone in self.zones.values():
289
+ try:
290
+ self._get_zone_waf_rulesets(zone)
291
+ except Exception as error:
292
+ logger.error(
293
+ f"{zone.id} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
294
+ )
295
+
296
+ def _get_zone_waf_rulesets(self, zone: "CloudflareZone") -> None:
297
+ """List WAF rulesets for a zone using the rulesets API."""
298
+ seen_ids: set[str] = set()
299
+ try:
300
+ for ruleset in self.client.rulesets.list(zone_id=zone.id):
301
+ ruleset_id = getattr(ruleset, "id", "")
302
+ if ruleset_id in seen_ids:
303
+ break
304
+ seen_ids.add(ruleset_id)
305
+ try:
306
+ zone.waf_rulesets.append(
307
+ CloudflareWAFRuleset(
308
+ id=ruleset_id,
309
+ name=getattr(ruleset, "name", ""),
310
+ kind=getattr(ruleset, "kind", None),
311
+ phase=getattr(ruleset, "phase", None),
312
+ enabled=True,
313
+ )
314
+ )
315
+ except Exception as error:
316
+ logger.error(
317
+ f"{error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
318
+ )
319
+ except Exception as error:
320
+ logger.error(
321
+ f"{error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
322
+ )
323
+
194
324
  def _get_zone_setting(self, zone_id: str, setting_id: str):
195
325
  """Get a single zone setting by ID."""
196
326
  try:
@@ -326,3 +456,5 @@ class CloudflareZone(BaseModel):
326
456
  settings: CloudflareZoneSettings = Field(default_factory=CloudflareZoneSettings)
327
457
  dnssec_status: Optional[str] = None
328
458
  rate_limit_rules: list[CloudflareRateLimitRule] = Field(default_factory=list)
459
+ firewall_rules: list[CloudflareFirewallRule] = Field(default_factory=list)
460
+ waf_rulesets: list[CloudflareWAFRuleset] = Field(default_factory=list)
@@ -0,0 +1,36 @@
1
+ {
2
+ "Provider": "cloudflare",
3
+ "CheckID": "zone_waf_owasp_ruleset_enabled",
4
+ "CheckTitle": "Cloudflare Zone OWASP Managed WAF Rulesets Are Enabled",
5
+ "CheckType": [],
6
+ "ServiceName": "zone",
7
+ "SubServiceName": "",
8
+ "ResourceIdTemplate": "",
9
+ "Severity": "high",
10
+ "ResourceType": "Zone",
11
+ "ResourceGroup": "network",
12
+ "Description": "**Cloudflare zones** are assessed for **OWASP managed rulesets** by checking if they are enabled to protect against common web application vulnerabilities including **SQL injection**, **XSS**, and other **OWASP Top 10** threats.",
13
+ "Risk": "Without **OWASP managed rulesets**, web applications are exposed to well-known attack vectors.\n- **Confidentiality**: SQL injection attacks can exfiltrate sensitive database contents\n- **Integrity**: XSS attacks can modify page content and steal session tokens\n- **Availability**: remote code execution can compromise server availability",
14
+ "RelatedUrl": "",
15
+ "AdditionalURLs": [
16
+ "https://developers.cloudflare.com/waf/managed-rules/"
17
+ ],
18
+ "Remediation": {
19
+ "Code": {
20
+ "CLI": "",
21
+ "NativeIaC": "",
22
+ "Other": "1. Log in to the Cloudflare dashboard and select your account and domain\n2. Go to Security > WAF > Managed rules\n3. Enable the Cloudflare OWASP Core Ruleset\n4. Review and configure rule sensitivity based on your application\n5. Monitor WAF analytics to tune rules and reduce false positives",
23
+ "Terraform": "```hcl\n# Enable OWASP managed WAF rulesets\nresource \"cloudflare_ruleset\" \"waf_owasp\" {\n zone_id = \"<ZONE_ID>\"\n name = \"OWASP Managed Rules\"\n kind = \"zone\"\n phase = \"http_request_firewall_managed\"\n rules {\n action = \"execute\"\n action_parameters {\n id = \"4814384a9e5d4991b9815dcfc25d2f1f\" # Cloudflare OWASP Core Ruleset\n }\n expression = \"true\"\n description = \"Execute Cloudflare OWASP Core Ruleset\"\n }\n}\n```"
24
+ },
25
+ "Recommendation": {
26
+ "Text": "Enable **OWASP Core Ruleset** managed rules as part of a defense in depth strategy.\n- Protects against OWASP Top 10 vulnerabilities including SQLi and XSS\n- Regularly review and tune rule sensitivity based on application requirements\n- Monitor WAF analytics to identify and address false positives\n- Combine with custom rules for application-specific protection",
27
+ "Url": "https://hub.prowler.com/checks/cloudflare/zone_waf_owasp_ruleset_enabled"
28
+ }
29
+ },
30
+ "Categories": [
31
+ "vulnerabilities"
32
+ ],
33
+ "DependsOn": [],
34
+ "RelatedTo": [],
35
+ "Notes": "OWASP managed rulesets are available on Pro, Business, and Enterprise plans. The Cloudflare OWASP Core Ruleset provides protection against common web application vulnerabilities."
36
+ }
@@ -0,0 +1,58 @@
1
+ from prowler.lib.check.models import Check, CheckReportCloudflare
2
+ from prowler.providers.cloudflare.services.zone.zone_client import zone_client
3
+
4
+
5
+ class zone_waf_owasp_ruleset_enabled(Check):
6
+ """Ensure that OWASP managed WAF rulesets are enabled for Cloudflare zones.
7
+
8
+ The OWASP Core Ruleset provides protection against common web application
9
+ vulnerabilities including SQL injection, cross-site scripting (XSS), and other
10
+ OWASP Top 10 threats. These managed rulesets are essential for defense in depth
11
+ and protecting applications from well-known attack vectors.
12
+ """
13
+
14
+ def execute(self) -> list[CheckReportCloudflare]:
15
+ """Execute the OWASP WAF ruleset enabled check.
16
+
17
+ Iterates through all Cloudflare zones and verifies that OWASP managed
18
+ WAF rulesets are enabled. The check identifies OWASP rulesets by name
19
+ containing "owasp" or by the http_request_firewall_managed phase.
20
+
21
+ Returns:
22
+ A list of CheckReportCloudflare objects with PASS status if OWASP
23
+ rulesets are enabled, or FAIL status if no OWASP protection exists.
24
+ """
25
+ findings = []
26
+
27
+ for zone in zone_client.zones.values():
28
+ report = CheckReportCloudflare(
29
+ metadata=self.metadata(),
30
+ resource=zone,
31
+ )
32
+
33
+ # Find OWASP managed rulesets for this zone
34
+ # Only match rulesets that explicitly contain "owasp" in the name
35
+ # The phase check was too broad as it matched any managed ruleset
36
+ owasp_rulesets = [
37
+ ruleset
38
+ for ruleset in zone.waf_rulesets
39
+ if "owasp" in (ruleset.name or "").lower()
40
+ ]
41
+
42
+ if owasp_rulesets:
43
+ report.status = "PASS"
44
+ ruleset_descriptions = ", ".join(
45
+ ruleset.name for ruleset in owasp_rulesets
46
+ )
47
+ report.status_extended = (
48
+ f"Zone {zone.name} has OWASP managed WAF ruleset enabled: "
49
+ f"{ruleset_descriptions}."
50
+ )
51
+ else:
52
+ report.status = "FAIL"
53
+ report.status_extended = (
54
+ f"Zone {zone.name} does not have OWASP managed WAF ruleset enabled."
55
+ )
56
+ findings.append(report)
57
+
58
+ return findings
@@ -251,6 +251,7 @@ class Provider(ABC):
251
251
  elif "cloudflare" in provider_class_name.lower():
252
252
  provider_class(
253
253
  filter_zones=arguments.region,
254
+ filter_accounts=arguments.account_id,
254
255
  config_path=arguments.config_file,
255
256
  mutelist_path=arguments.mutelist_file,
256
257
  fixer_config=fixer_config,
@@ -293,6 +294,28 @@ class Provider(ABC):
293
294
  fixer_config=fixer_config,
294
295
  use_instance_principal=arguments.use_instance_principal,
295
296
  )
297
+ elif "openstack" in provider_class_name.lower():
298
+ provider_class(
299
+ clouds_yaml_file=getattr(arguments, "clouds_yaml_file", None),
300
+ clouds_yaml_cloud=getattr(arguments, "clouds_yaml_cloud", None),
301
+ auth_url=getattr(arguments, "os_auth_url", None),
302
+ identity_api_version=getattr(
303
+ arguments, "os_identity_api_version", None
304
+ ),
305
+ username=getattr(arguments, "os_username", None),
306
+ password=getattr(arguments, "os_password", None),
307
+ project_id=getattr(arguments, "os_project_id", None),
308
+ region_name=getattr(arguments, "os_region_name", None),
309
+ user_domain_name=getattr(
310
+ arguments, "os_user_domain_name", None
311
+ ),
312
+ project_domain_name=getattr(
313
+ arguments, "os_project_domain_name", None
314
+ ),
315
+ config_path=arguments.config_file,
316
+ mutelist_path=arguments.mutelist_file,
317
+ fixer_config=fixer_config,
318
+ )
296
319
  elif "alibabacloud" in provider_class_name.lower():
297
320
  provider_class(
298
321
  role_arn=arguments.role_arn,
@@ -0,0 +1,37 @@
1
+ {
2
+ "Provider": "gcp",
3
+ "CheckID": "compute_instance_suspended_without_persistent_disks",
4
+ "CheckTitle": "Suspended VM instance does not have persistent disks attached",
5
+ "CheckType": [],
6
+ "ServiceName": "compute",
7
+ "SubServiceName": "",
8
+ "ResourceIdTemplate": "",
9
+ "Severity": "medium",
10
+ "ResourceType": "compute.googleapis.com/Instance",
11
+ "ResourceGroup": "compute",
12
+ "Description": "This check identifies VM instances in a **SUSPENDED** or **SUSPENDING** state with persistent disks still attached.\n\nPersistent disks on suspended VMs remain accessible through the GCP API and could contain **sensitive data** while the instance is inactive, potentially creating security blind spots in long-forgotten infrastructure.",
13
+ "Risk": "Persistent disks on suspended VM instances remain accessible through the GCP API and may contain **sensitive data**, creating potential security risks:\n\n- **Unauthorized data access** if credentials are compromised or permissions are misconfigured\n- **Data exposure** from forgotten infrastructure that is no longer actively monitored\n- **Security blind spots** where suspended resources are overlooked during security reviews and audits",
14
+ "RelatedUrl": "",
15
+ "AdditionalURLs": [
16
+ "https://cloud.google.com/icompute/docs/instances/suspend-resume-instance",
17
+ "https://www.trendmicro.com/cloudoneconformity/knowledge-base/gcp/ComputeEngine/persistent-disks-attached-to-suspended-vms.html"
18
+ ],
19
+ "Remediation": {
20
+ "Code": {
21
+ "CLI": "gcloud compute instances delete INSTANCE_NAME --zone=ZONE",
22
+ "NativeIaC": "",
23
+ "Other": "1. Open the Google Cloud Console\n2. Navigate to Compute Engine > VM instances\n3. Identify suspended instances with attached disks\n4. If the instance is no longer needed, select it and click DELETE\n5. If the instance will be resumed, take no action or resume it with: gcloud compute instances resume INSTANCE_NAME --zone=ZONE",
24
+ "Terraform": "```hcl\n# To remediate, either delete the suspended instance or resume it\n# Delete by removing the resource from your Terraform configuration\n# Or resume by changing the desired_status\nresource \"google_compute_instance\" \"example_resource\" {\n name = \"example-instance\"\n machine_type = \"e2-medium\"\n zone = \"us-central1-a\"\n\n # Set desired_status to RUNNING to resume the instance\n desired_status = \"RUNNING\"\n\n boot_disk {\n initialize_params {\n image = \"debian-cloud/debian-11\"\n }\n }\n\n network_interface {\n network = \"default\"\n }\n}\n```"
25
+ },
26
+ "Recommendation": {
27
+ "Text": "Regularly review suspended VM instances to reduce your attack surface. Either **resume** instances if still needed, or **delete** them along with their attached disks to eliminate potential data exposure. Implement automated policies to detect and alert on long-suspended instances as part of your security monitoring.",
28
+ "Url": "https://hub.prowler.com/check/compute_instance_suspended_without_persistent_disks"
29
+ }
30
+ },
31
+ "Categories": [],
32
+ "DependsOn": [],
33
+ "RelatedTo": [
34
+ "compute_instance_disk_auto_delete_disabled"
35
+ ],
36
+ "Notes": "This check is focused on security risks rather than cost optimization. Persistent disks on suspended VMs remain accessible and may contain sensitive data, creating potential unauthorized access risks."
37
+ }