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
@@ -0,0 +1,35 @@
1
+ from prowler.lib.check.models import Check, Check_Report_GCP
2
+ from prowler.providers.gcp.services.compute.compute_client import compute_client
3
+
4
+
5
+ class compute_instance_suspended_without_persistent_disks(Check):
6
+ """
7
+ Ensure that VM instances in SUSPENDED state do not have persistent disks attached.
8
+
9
+ This check identifies VM instances that are in a SUSPENDED or SUSPENDING state
10
+ and have persistent disks still attached. Suspended VMs with attached disks
11
+ represent unused infrastructure that continues to incur storage costs.
12
+
13
+ - PASS: VM instance is not in SUSPENDED/SUSPENDING state, or is suspended but has no disks attached.
14
+ - FAIL: VM instance is in SUSPENDED/SUSPENDING state with persistent disks attached.
15
+ """
16
+
17
+ def execute(self) -> list[Check_Report_GCP]:
18
+ findings = []
19
+ for instance in compute_client.instances:
20
+ report = Check_Report_GCP(metadata=self.metadata(), resource=instance)
21
+ report.status = "PASS"
22
+ report.status_extended = f"VM Instance {instance.name} is not suspended."
23
+
24
+ if instance.status in ("SUSPENDED", "SUSPENDING"):
25
+ attached_disks = [disk.name for disk in instance.disks]
26
+
27
+ if attached_disks:
28
+ report.status = "FAIL"
29
+ report.status_extended = f"VM Instance {instance.name} is {instance.status.lower()} with {len(attached_disks)} persistent disk(s) attached: {', '.join(attached_disks)}."
30
+ else:
31
+ report.status_extended = f"VM Instance {instance.name} is {instance.status.lower()} but has no persistent disks attached."
32
+
33
+ findings.append(report)
34
+
35
+ return findings
@@ -198,6 +198,7 @@ class Compute(GCPService):
198
198
  "deletionProtection", False
199
199
  ),
200
200
  network_interfaces=network_interfaces,
201
+ status=instance.get("status", "RUNNING"),
201
202
  on_host_maintenance=instance.get("scheduling", {}).get(
202
203
  "onHostMaintenance", "MIGRATE"
203
204
  ),
@@ -700,6 +701,7 @@ class Instance(BaseModel):
700
701
  provisioning_model: str = "STANDARD"
701
702
  deletion_protection: bool = False
702
703
  network_interfaces: list[NetworkInterface] = []
704
+ status: str = "RUNNING"
703
705
  on_host_maintenance: str = "MIGRATE"
704
706
 
705
707
 
@@ -823,6 +823,52 @@ class M365PowerShell(PowerShellSession):
823
823
  "Get-SharingPolicy | ConvertTo-Json -Depth 10", json_parse=True
824
824
  )
825
825
 
826
+ def get_teams_protection_policy(self) -> dict:
827
+ """
828
+ Get Teams Protection Policy.
829
+
830
+ Retrieves the Teams protection policy settings including Zero-hour auto purge (ZAP) configuration.
831
+
832
+ Returns:
833
+ dict: Teams protection policy settings in JSON format.
834
+
835
+ Example:
836
+ >>> get_teams_protection_policy()
837
+ {
838
+ "Identity": "Teams Protection Policy",
839
+ "ZapEnabled": True
840
+ }
841
+ """
842
+ return self.execute(
843
+ "Get-TeamsProtectionPolicy | ConvertTo-Json -Depth 10", json_parse=True
844
+ )
845
+
846
+ def get_shared_mailboxes(self) -> dict:
847
+ """
848
+ Get Exchange Online Shared Mailboxes.
849
+
850
+ Retrieves all shared mailboxes from Exchange Online with their external
851
+ directory object IDs for cross-referencing with Entra ID user accounts.
852
+
853
+ Returns:
854
+ dict: Shared mailbox information in JSON format.
855
+
856
+ Example:
857
+ >>> get_shared_mailboxes()
858
+ [
859
+ {
860
+ "DisplayName": "Support Mailbox",
861
+ "UserPrincipalName": "support@contoso.com",
862
+ "ExternalDirectoryObjectId": "12345678-1234-1234-1234-123456789012",
863
+ "Identity": "support@contoso.com"
864
+ }
865
+ ]
866
+ """
867
+ return self.execute(
868
+ "Get-EXOMailbox -RecipientTypeDetails SharedMailbox -ResultSize Unlimited | Select-Object DisplayName, UserPrincipalName, ExternalDirectoryObjectId, Identity | ConvertTo-Json -Depth 10",
869
+ json_parse=True,
870
+ )
871
+
826
872
  def get_user_account_status(self) -> dict:
827
873
  """
828
874
  Get User Account Status.
@@ -833,7 +879,7 @@ class M365PowerShell(PowerShellSession):
833
879
  dict: User account status settings in JSON format.
834
880
  """
835
881
  return self.execute(
836
- "$dict=@{}; Get-User -ResultSize Unlimited | ForEach-Object { $dict[$_.Id] = @{ AccountDisabled = $_.AccountDisabled } }; $dict | ConvertTo-Json -Depth 10",
882
+ "$dict=@{}; Get-User -ResultSize Unlimited | ForEach-Object { $dict[$_.ExternalDirectoryObjectId] = @{ AccountDisabled = $_.AccountDisabled } }; $dict | ConvertTo-Json -Depth 10",
837
883
  json_parse=True,
838
884
  )
839
885
 
@@ -8,7 +8,20 @@ from prowler.providers.m365.m365_provider import M365Provider
8
8
 
9
9
 
10
10
  class Defender(M365Service):
11
+ """
12
+ Microsoft 365 Defender service implementation.
13
+
14
+ Provides access to Microsoft Defender for Office 365 configurations including
15
+ malware policies, spam filtering, anti-phishing, and Teams protection settings.
16
+ """
17
+
11
18
  def __init__(self, provider: M365Provider):
19
+ """
20
+ Initialize the Defender service.
21
+
22
+ Args:
23
+ provider: The M365 provider instance.
24
+ """
12
25
  super().__init__(provider)
13
26
  self.malware_policies = []
14
27
  self.outbound_spam_policies = {}
@@ -20,6 +33,7 @@ class Defender(M365Service):
20
33
  self.inbound_spam_policies = []
21
34
  self.inbound_spam_rules = {}
22
35
  self.report_submission_policy = None
36
+ self.teams_protection_policy = None
23
37
  if self.powershell:
24
38
  if self.powershell.connect_exchange_online():
25
39
  self.malware_policies = self._get_malware_filter_policy()
@@ -33,6 +47,7 @@ class Defender(M365Service):
33
47
  self.inbound_spam_policies = self._get_inbound_spam_filter_policy()
34
48
  self.inbound_spam_rules = self._get_inbound_spam_filter_rule()
35
49
  self.report_submission_policy = self._get_report_submission_policy()
50
+ self.teams_protection_policy = self._get_teams_protection_policy()
36
51
  self.powershell.close()
37
52
 
38
53
  def _get_malware_filter_policy(self):
@@ -350,6 +365,12 @@ class Defender(M365Service):
350
365
  return inbound_spam_rules
351
366
 
352
367
  def _get_report_submission_policy(self):
368
+ """
369
+ Retrieve the Defender report submission policy.
370
+
371
+ Returns:
372
+ ReportSubmissionPolicy: The report submission policy configuration.
373
+ """
353
374
  logger.info("Microsoft365 - Getting Defender report submission policy...")
354
375
  report_submission_policy = None
355
376
  try:
@@ -387,6 +408,28 @@ class Defender(M365Service):
387
408
  )
388
409
  return report_submission_policy
389
410
 
411
+ def _get_teams_protection_policy(self):
412
+ """
413
+ Retrieve the Teams protection policy including ZAP settings.
414
+
415
+ Returns:
416
+ TeamsProtectionPolicy: The Teams protection policy configuration.
417
+ """
418
+ logger.info("Microsoft365 - Getting Teams protection policy...")
419
+ teams_protection_policy = None
420
+ try:
421
+ policy = self.powershell.get_teams_protection_policy()
422
+ if policy:
423
+ teams_protection_policy = TeamsProtectionPolicy(
424
+ identity=policy.get("Identity", ""),
425
+ zap_enabled=policy.get("ZapEnabled", True),
426
+ )
427
+ except Exception as error:
428
+ logger.error(
429
+ f"{error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
430
+ )
431
+ return teams_protection_policy
432
+
390
433
 
391
434
  class MalwarePolicy(BaseModel):
392
435
  enable_file_filter: bool
@@ -470,6 +513,8 @@ class InboundSpamRule(BaseModel):
470
513
 
471
514
 
472
515
  class ReportSubmissionPolicy(BaseModel):
516
+ """Model for Defender report submission policy settings."""
517
+
473
518
  report_junk_to_customized_address: bool
474
519
  report_not_junk_to_customized_address: bool
475
520
  report_phish_to_customized_address: bool
@@ -478,3 +523,10 @@ class ReportSubmissionPolicy(BaseModel):
478
523
  report_phish_addresses: list[str]
479
524
  report_chat_message_enabled: bool
480
525
  report_chat_message_to_customized_address_enabled: bool
526
+
527
+
528
+ class TeamsProtectionPolicy(BaseModel):
529
+ """Model for Teams protection policy settings including ZAP configuration."""
530
+
531
+ identity: str
532
+ zap_enabled: bool
@@ -0,0 +1,38 @@
1
+ {
2
+ "Provider": "m365",
3
+ "CheckID": "defender_zap_for_teams_enabled",
4
+ "CheckTitle": "Zero-hour auto purge (ZAP) protects Microsoft Teams from malware and phishing",
5
+ "CheckType": [],
6
+ "ServiceName": "defender",
7
+ "SubServiceName": "",
8
+ "ResourceIdTemplate": "",
9
+ "Severity": "medium",
10
+ "ResourceType": "Teams Protection Policy",
11
+ "ResourceGroup": "collaboration",
12
+ "Description": "Zero-hour auto purge (ZAP) is a protection feature that retroactively detects and neutralizes **malware** and **high confidence phishing** in Teams messages.\n\nWhen ZAP blocks a message, it is blocked for everyone in the chat. The initial block happens right after delivery, but ZAP can occur up to 48 hours after delivery.",
13
+ "Risk": "Without ZAP enabled, malicious content delivered to Teams chats remains accessible to users for up to 48 hours after delivery, even after being identified as harmful.\n\nThis extended exposure window could lead to:\n- **Malware infections** from weaponized attachments or links\n- **Phishing attacks** compromising user credentials and MFA tokens\n- **Lateral movement** as attackers exploit compromised accounts within the organization",
14
+ "RelatedUrl": "",
15
+ "AdditionalURLs": [
16
+ "https://learn.microsoft.com/en-us/defender-office-365/zero-hour-auto-purge?view=o365-worldwide#zero-hour-auto-purge-zap-in-microsoft-teams",
17
+ "https://learn.microsoft.com/en-us/defender-office-365/mdo-support-teams-about?view=o365-worldwide"
18
+ ],
19
+ "Remediation": {
20
+ "Code": {
21
+ "CLI": "Set-TeamsProtectionPolicy -Identity 'Teams Protection Policy' -ZapEnabled $true",
22
+ "NativeIaC": "",
23
+ "Other": "1. Navigate to Microsoft Defender https://security.microsoft.com/\n2. Click to expand System and select Settings > Email & collaboration > Microsoft Teams protection\n3. Set Zero-hour auto purge (ZAP) to On (Default)",
24
+ "Terraform": ""
25
+ },
26
+ "Recommendation": {
27
+ "Text": "Enable Zero-hour auto purge (ZAP) for Microsoft Teams to ensure malicious content is automatically removed from chats after detection, even if it was delivered before being identified as harmful.",
28
+ "Url": "https://hub.prowler.com/check/defender_zap_for_teams_enabled"
29
+ }
30
+ },
31
+ "Categories": [
32
+ "email-security",
33
+ "e5"
34
+ ],
35
+ "DependsOn": [],
36
+ "RelatedTo": [],
37
+ "Notes": ""
38
+ }
@@ -0,0 +1,53 @@
1
+ from typing import List
2
+
3
+ from prowler.lib.check.models import Check, CheckReportM365
4
+ from prowler.providers.m365.services.defender.defender_client import defender_client
5
+
6
+
7
+ class defender_zap_for_teams_enabled(Check):
8
+ """Check if Zero-hour auto purge (ZAP) is enabled for Microsoft Teams.
9
+
10
+ ZAP is a protection feature that retroactively detects and neutralizes malware
11
+ and high confidence phishing in Teams messages.
12
+
13
+ - PASS: ZAP is enabled for Teams protection.
14
+ - FAIL: ZAP is not enabled for Teams protection.
15
+
16
+ Attributes:
17
+ metadata: Metadata associated with the check (inherited from Check).
18
+ """
19
+
20
+ def execute(self) -> List[CheckReportM365]:
21
+ """Execute the check for Teams ZAP protection status.
22
+
23
+ This method checks if Zero-hour auto purge (ZAP) is enabled for Microsoft Teams
24
+ to ensure malicious content is automatically removed from chats after detection.
25
+
26
+ Returns:
27
+ List[CheckReportM365]: A list of reports containing the result of the check.
28
+ """
29
+ findings = []
30
+ teams_protection_policy = defender_client.teams_protection_policy
31
+
32
+ if teams_protection_policy:
33
+ report = CheckReportM365(
34
+ metadata=self.metadata(),
35
+ resource=teams_protection_policy,
36
+ resource_name="Teams Protection Policy",
37
+ resource_id="teamsProtectionPolicy",
38
+ )
39
+
40
+ if teams_protection_policy.zap_enabled:
41
+ report.status = "PASS"
42
+ report.status_extended = (
43
+ "Zero-hour auto purge (ZAP) is enabled for Microsoft Teams."
44
+ )
45
+ else:
46
+ report.status = "FAIL"
47
+ report.status_extended = (
48
+ "Zero-hour auto purge (ZAP) is not enabled for Microsoft Teams."
49
+ )
50
+
51
+ findings.append(report)
52
+
53
+ return findings
@@ -9,7 +9,20 @@ from prowler.providers.m365.m365_provider import M365Provider
9
9
 
10
10
 
11
11
  class Exchange(M365Service):
12
+ """
13
+ Exchange Online service for Microsoft 365.
14
+
15
+ This service provides access to Exchange Online resources and configurations
16
+ including organization settings, mailboxes, transport rules, and policies.
17
+ """
18
+
12
19
  def __init__(self, provider: M365Provider):
20
+ """
21
+ Initialize the Exchange service.
22
+
23
+ Args:
24
+ provider: The M365Provider instance for authentication and configuration.
25
+ """
13
26
  super().__init__(provider)
14
27
  self.organization_config = None
15
28
  self.mailboxes_config = []
@@ -19,6 +32,7 @@ class Exchange(M365Service):
19
32
  self.mailbox_policies = []
20
33
  self.role_assignment_policies = []
21
34
  self.mailbox_audit_properties = []
35
+ self.shared_mailboxes = []
22
36
 
23
37
  if self.powershell:
24
38
  if self.powershell.connect_exchange_online():
@@ -30,6 +44,7 @@ class Exchange(M365Service):
30
44
  self.mailbox_policies = self._get_mailbox_policy()
31
45
  self.role_assignment_policies = self._get_role_assignment_policies()
32
46
  self.mailbox_audit_properties = self._get_mailbox_audit_properties()
47
+ self.shared_mailboxes = self._get_shared_mailboxes()
33
48
  self.powershell.close()
34
49
 
35
50
  def _get_organization_config(self):
@@ -211,6 +226,12 @@ class Exchange(M365Service):
211
226
  return role_assignment_policies
212
227
 
213
228
  def _get_mailbox_audit_properties(self):
229
+ """
230
+ Get mailbox audit properties for all mailboxes.
231
+
232
+ Returns:
233
+ list[MailboxAuditProperties]: List of mailbox audit property configurations.
234
+ """
214
235
  logger.info("Microsoft365 - Getting mailbox audit properties...")
215
236
  mailbox_audit_properties = []
216
237
  try:
@@ -248,6 +269,44 @@ class Exchange(M365Service):
248
269
  )
249
270
  return mailbox_audit_properties
250
271
 
272
+ def _get_shared_mailboxes(self):
273
+ """
274
+ Get all shared mailboxes from Exchange Online.
275
+
276
+ Retrieves shared mailboxes with their external directory object IDs
277
+ for cross-referencing with Entra ID user accounts.
278
+
279
+ Returns:
280
+ list[SharedMailbox]: List of shared mailbox configurations.
281
+ """
282
+ logger.info("Microsoft365 - Getting shared mailboxes...")
283
+ shared_mailboxes = []
284
+ try:
285
+ shared_mailboxes_data = self.powershell.get_shared_mailboxes()
286
+ if not shared_mailboxes_data:
287
+ return shared_mailboxes
288
+ if isinstance(shared_mailboxes_data, dict):
289
+ shared_mailboxes_data = [shared_mailboxes_data]
290
+ for shared_mailbox in shared_mailboxes_data:
291
+ if shared_mailbox:
292
+ shared_mailboxes.append(
293
+ SharedMailbox(
294
+ name=shared_mailbox.get("DisplayName", ""),
295
+ user_principal_name=shared_mailbox.get(
296
+ "UserPrincipalName", ""
297
+ ),
298
+ external_directory_object_id=shared_mailbox.get(
299
+ "ExternalDirectoryObjectId", ""
300
+ ),
301
+ identity=shared_mailbox.get("Identity", ""),
302
+ )
303
+ )
304
+ except Exception as error:
305
+ logger.error(
306
+ f"{error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
307
+ )
308
+ return shared_mailboxes
309
+
251
310
 
252
311
  class Organization(BaseModel):
253
312
  name: str
@@ -342,6 +401,8 @@ class AuditDelegate(Enum):
342
401
 
343
402
 
344
403
  class AuditOwner(Enum):
404
+ """Audit actions for mailbox owner operations."""
405
+
345
406
  APPLY_RECORD = "ApplyRecord"
346
407
  CREATE = "Create"
347
408
  HARD_DELETE = "HardDelete"
@@ -353,3 +414,20 @@ class AuditOwner(Enum):
353
414
  UPDATE_CALENDAR_DELEGATION = "UpdateCalendarDelegation"
354
415
  UPDATE_FOLDER_PERMISSIONS = "UpdateFolderPermissions"
355
416
  UPDATE_INBOX_RULES = "UpdateInboxRules"
417
+
418
+
419
+ class SharedMailbox(BaseModel):
420
+ """
421
+ Model for Exchange Online shared mailbox.
422
+
423
+ Attributes:
424
+ name: Display name of the shared mailbox.
425
+ user_principal_name: User principal name (email) of the shared mailbox.
426
+ external_directory_object_id: The Entra ID object ID for cross-referencing.
427
+ identity: Identity of the shared mailbox in Exchange.
428
+ """
429
+
430
+ name: str
431
+ user_principal_name: str
432
+ external_directory_object_id: str
433
+ identity: str
@@ -0,0 +1,37 @@
1
+ {
2
+ "Provider": "m365",
3
+ "CheckID": "exchange_shared_mailbox_sign_in_disabled",
4
+ "CheckTitle": "Shared mailbox has sign-in blocked",
5
+ "CheckType": [],
6
+ "ServiceName": "exchange",
7
+ "SubServiceName": "",
8
+ "ResourceIdTemplate": "",
9
+ "Severity": "medium",
10
+ "ResourceType": "Shared Mailbox",
11
+ "ResourceGroup": "IAM",
12
+ "Description": "Shared mailboxes are used for collaboration and should not permit direct sign-in. This check verifies that the **AccountEnabled** property is set to `false` in Entra ID for all shared mailboxes, preventing direct authentication.",
13
+ "Risk": "When sign-in is enabled on shared mailboxes, users with the password can bypass delegation controls and access the mailbox directly. This undermines **accountability** since actions cannot be attributed to individual users, and it increases the attack surface for credential-based attacks.",
14
+ "RelatedUrl": "",
15
+ "AdditionalURLs": [
16
+ "https://learn.microsoft.com/en-us/microsoft-365/admin/email/about-shared-mailboxes",
17
+ "https://learn.microsoft.com/en-us/microsoft-365/admin/email/create-a-shared-mailbox#block-sign-in-for-the-shared-mailbox-account"
18
+ ],
19
+ "Remediation": {
20
+ "Code": {
21
+ "CLI": "Get-EXOMailbox -RecipientTypeDetails SharedMailbox | ForEach-Object { Update-MgUser -UserId $_.ExternalDirectoryObjectId -AccountEnabled:$false }",
22
+ "NativeIaC": "",
23
+ "Other": "1. Navigate to Entra admin center (https://entra.microsoft.com/)\n2. Expand Identity > Users and select All users\n3. Search for and select the shared mailbox user account\n4. In the properties pane, go to Account status\n5. Uncheck 'Account enabled' and click Save\n6. Repeat for all shared mailbox accounts",
24
+ "Terraform": ""
25
+ },
26
+ "Recommendation": {
27
+ "Text": "Block sign-in for all shared mailboxes to ensure users can only access them through delegation. This enforces accountability and reduces security risks from shared credentials.",
28
+ "Url": "https://hub.prowler.com/check/exchange_shared_mailbox_sign_in_disabled"
29
+ }
30
+ },
31
+ "Categories": [
32
+ "identity-access"
33
+ ],
34
+ "DependsOn": [],
35
+ "RelatedTo": [],
36
+ "Notes": ""
37
+ }
@@ -0,0 +1,59 @@
1
+ from typing import List
2
+
3
+ from prowler.lib.check.models import Check, CheckReportM365
4
+ from prowler.providers.m365.services.entra.entra_client import entra_client
5
+ from prowler.providers.m365.services.exchange.exchange_client import exchange_client
6
+
7
+
8
+ class exchange_shared_mailbox_sign_in_disabled(Check):
9
+ """
10
+ Verify that sign-in is blocked for all shared mailboxes.
11
+
12
+ Shared mailboxes are designed for collaboration and should not permit direct
13
+ sign-in. Users should access shared mailboxes through delegation only, which
14
+ ensures accountability and proper access controls.
15
+
16
+ - PASS: Shared mailbox has sign-in blocked (AccountEnabled = False in Entra ID).
17
+ - FAIL: Shared mailbox has sign-in enabled (AccountEnabled = True in Entra ID).
18
+ """
19
+
20
+ def execute(self) -> List[CheckReportM365]:
21
+ """
22
+ Execute the check to verify shared mailbox sign-in status.
23
+
24
+ Cross-references shared mailboxes from Exchange Online with user accounts
25
+ in Entra ID to determine if sign-in is blocked.
26
+
27
+ Returns:
28
+ List[CheckReportM365]: A list of reports with the sign-in status for
29
+ each shared mailbox.
30
+ """
31
+ findings = []
32
+
33
+ for shared_mailbox in exchange_client.shared_mailboxes:
34
+ report = CheckReportM365(
35
+ metadata=self.metadata(),
36
+ resource=shared_mailbox,
37
+ resource_name=shared_mailbox.name or shared_mailbox.user_principal_name,
38
+ resource_id=shared_mailbox.external_directory_object_id
39
+ or shared_mailbox.identity,
40
+ )
41
+
42
+ # Look up the user in Entra ID by their external directory object ID
43
+ entra_user = entra_client.users.get(
44
+ shared_mailbox.external_directory_object_id
45
+ )
46
+
47
+ if not entra_user:
48
+ report.status = "FAIL"
49
+ report.status_extended = f"Shared mailbox {shared_mailbox.user_principal_name} could not be found in Entra ID for verification."
50
+ elif entra_user.account_enabled:
51
+ report.status = "FAIL"
52
+ report.status_extended = f"Shared mailbox {shared_mailbox.user_principal_name} has sign-in enabled."
53
+ else:
54
+ report.status = "PASS"
55
+ report.status_extended = f"Shared mailbox {shared_mailbox.user_principal_name} has sign-in blocked."
56
+
57
+ findings.append(report)
58
+
59
+ return findings
File without changes
File without changes