prowler 5.17.1__py3-none-any.whl → 5.18.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (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-5.17.1.dist-info → prowler-5.18.0.dist-info}/METADATA +11 -9
  216. {prowler-5.17.1.dist-info → prowler-5.18.0.dist-info}/RECORD +219 -155
  217. {prowler-5.17.1.dist-info → prowler-5.18.0.dist-info}/LICENSE +0 -0
  218. {prowler-5.17.1.dist-info → prowler-5.18.0.dist-info}/WHEEL +0 -0
  219. {prowler-5.17.1.dist-info → prowler-5.18.0.dist-info}/entry_points.txt +0 -0
@@ -121,7 +121,9 @@
121
121
  {
122
122
  "Id": "1.2.2",
123
123
  "Description": "Shared mailboxes are used when multiple people need access to the same mailbox, such as a company information or support email address, reception desk, or other function that might be shared by multiple people.Users with permissions to the group mailbox can send as or send on behalf of the mailbox email address if the administrator has given that user permissions to do that. This is particularly useful for help and support mailboxes because users can send emails from \"Contoso Support\" or \"Building A Reception Desk.\"Shared mailboxes are created with a corresponding user account using a system generated password that is unknown at the time of creation.The recommended state is `Sign in blocked` for `Shared mailboxes`.",
124
- "Checks": [],
124
+ "Checks": [
125
+ "exchange_shared_mailbox_sign_in_disabled"
126
+ ],
125
127
  "Attributes": [
126
128
  {
127
129
  "Section": "1 Microsoft 365 admin center",
@@ -691,7 +693,9 @@
691
693
  {
692
694
  "Id": "2.4.4",
693
695
  "Description": "Zero-hour auto purge (ZAP) is a protection feature that retroactively detects and neutralizes malware and high confidence phishing. When ZAP for Teams protection blocks a message, the message is blocked for everyone in the chat. The initial block happens right after delivery, but ZAP occurs up to 48 hours after delivery.",
694
- "Checks": [],
696
+ "Checks": [
697
+ "defender_zap_for_teams_enabled"
698
+ ],
695
699
  "Attributes": [
696
700
  {
697
701
  "Section": "2 Microsoft 365 Defender",
@@ -121,7 +121,9 @@
121
121
  {
122
122
  "Id": "1.2.2",
123
123
  "Description": "Shared mailboxes are used when multiple people need access to the same mailbox, such as a company information or support email address, reception desk, or other function that might be shared by multiple people. Shared mailboxes are created with a corresponding user account using a system generated password that is unknown at the time of creation. The recommended state is Sign in blocked for Shared mailboxes.",
124
- "Checks": [],
124
+ "Checks": [
125
+ "exchange_shared_mailbox_sign_in_disabled"
126
+ ],
125
127
  "Attributes": [
126
128
  {
127
129
  "Section": "1 Microsoft 365 admin center",
@@ -753,7 +755,9 @@
753
755
  {
754
756
  "Id": "2.4.4",
755
757
  "Description": "Zero-hour auto purge (ZAP) is a protection feature that retroactively detects and neutralizes malware and high confidence phishing. When ZAP for Teams protection blocks a message, the message is blocked for everyone in the chat. The initial block happens right after delivery, but ZAP occurs up to 48 hours after delivery.",
756
- "Checks": [],
758
+ "Checks": [
759
+ "defender_zap_for_teams_enabled"
760
+ ],
757
761
  "Attributes": [
758
762
  {
759
763
  "Section": "2 Microsoft 365 Defender",
@@ -112,12 +112,13 @@
112
112
  }
113
113
  ],
114
114
  "Checks": [
115
- "entra_identity_protection_sign_in_risk_enabled",
116
- "entra_identity_protection_user_risk_enabled",
115
+ "defender_antiphishing_policy_configured",
117
116
  "defender_antispam_outbound_policy_configured",
118
117
  "defender_malware_policy_notifications_internal_users_malware_enabled",
119
- "defender_antiphishing_policy_configured",
120
- "entra_admin_users_phishing_resistant_mfa_enabled"
118
+ "defender_zap_for_teams_enabled",
119
+ "entra_admin_users_phishing_resistant_mfa_enabled",
120
+ "entra_identity_protection_sign_in_risk_enabled",
121
+ "entra_identity_protection_user_risk_enabled"
121
122
  ]
122
123
  },
123
124
  {
@@ -344,15 +345,15 @@
344
345
  }
345
346
  ],
346
347
  "Checks": [
347
- "defender_antispam_outbound_policy_configured",
348
- "defender_malware_policy_notifications_internal_users_malware_enabled",
349
- "defender_malware_policy_common_attachments_filter_enabled",
350
- "defender_malware_policy_comprehensive_attachments_filter_applied",
351
348
  "defender_antispam_connection_filter_policy_empty_ip_allowlist",
352
349
  "defender_antispam_connection_filter_policy_safe_list_off",
353
350
  "defender_antispam_outbound_policy_configured",
354
351
  "defender_antispam_outbound_policy_forwarding_disabled",
355
- "defender_antispam_policy_inbound_no_allowed_domains"
352
+ "defender_antispam_policy_inbound_no_allowed_domains",
353
+ "defender_malware_policy_common_attachments_filter_enabled",
354
+ "defender_malware_policy_comprehensive_attachments_filter_applied",
355
+ "defender_malware_policy_notifications_internal_users_malware_enabled",
356
+ "defender_zap_for_teams_enabled"
356
357
  ]
357
358
  },
358
359
  {
@@ -368,11 +369,11 @@
368
369
  }
369
370
  ],
370
371
  "Checks": [
372
+ "defender_antispam_outbound_policy_configured",
371
373
  "defender_malware_policy_common_attachments_filter_enabled",
372
374
  "defender_malware_policy_comprehensive_attachments_filter_applied",
373
375
  "defender_malware_policy_notifications_internal_users_malware_enabled",
374
- "defender_antispam_outbound_policy_configured",
375
- "defender_malware_policy_notifications_internal_users_malware_enabled"
376
+ "defender_zap_for_teams_enabled"
376
377
  ]
377
378
  },
378
379
  {
@@ -691,6 +692,7 @@
691
692
  "defender_malware_policy_common_attachments_filter_enabled",
692
693
  "defender_malware_policy_comprehensive_attachments_filter_applied",
693
694
  "defender_malware_policy_notifications_internal_users_malware_enabled",
695
+ "defender_zap_for_teams_enabled",
694
696
  "teams_external_domains_restricted",
695
697
  "teams_external_users_cannot_start_conversations"
696
698
  ]
File without changes
prowler/config/config.py CHANGED
@@ -38,7 +38,7 @@ class _MutableTimestamp:
38
38
 
39
39
  timestamp = _MutableTimestamp(datetime.today())
40
40
  timestamp_utc = _MutableTimestamp(datetime.now(timezone.utc))
41
- prowler_version = "5.17.1"
41
+ prowler_version = "5.18.0"
42
42
  html_logo_url = "https://github.com/prowler-cloud/prowler/"
43
43
  square_logo_img = "https://raw.githubusercontent.com/prowler-cloud/prowler/dc7d2d5aeb92fdf12e8604f42ef6472cd3e8e889/docs/img/prowler-logo-black.png"
44
44
  aws_logo = "https://user-images.githubusercontent.com/38561120/235953920-3e3fba08-0795-41dc-b480-9bea57db9f2e.png"
@@ -62,6 +62,7 @@ class Provider(str, Enum):
62
62
  MONGODBATLAS = "mongodbatlas"
63
63
  ORACLECLOUD = "oraclecloud"
64
64
  ALIBABACLOUD = "alibabacloud"
65
+ OPENSTACK = "openstack"
65
66
 
66
67
 
67
68
  # Compliance
@@ -63,7 +63,10 @@ aws:
63
63
  fargate_windows_latest_version: "1.0.0"
64
64
 
65
65
  # AWS VPC Configuration (vpc_endpoint_connections_trust_boundaries, vpc_endpoint_services_allowed_principals_trust_boundaries)
66
- # AWS SSM Configuration (aws.ssm_documents_set_as_public)
66
+ # AWS SSM Configuration (ssm_documents_set_as_public)
67
+ # AWS S3 Configuration (s3_bucket_cross_account_access)
68
+ # AWS EventBridge Configuration (eventbridge_schema_registry_cross_account_access, eventbridge_bus_cross_account_access)
69
+ # AWS DynamoDB Configuration (dynamodb_table_cross_account_access)
67
70
  # Single account environment: No action required. The AWS account number will be automatically added by the checks.
68
71
  # Multi account environment: Any additional trusted account number should be added as a space separated list, e.g.
69
72
  # trusted_account_ids : ["123456789012", "098765432109", "678901234567"]
@@ -0,0 +1,60 @@
1
+ ### Project ID, Check and/or Region can be * to apply for all the cases.
2
+ ### Resources and tags are lists that can have either Regex or Keywords.
3
+ ### Tags is an optional list that matches on tuples of 'key=value' and are "ANDed" together.
4
+ ### Use an alternation Regex to match one of multiple tags with "ORed" logic.
5
+ ### For each check you can except Project IDs, Regions, Resources and/or Tags.
6
+ ########################### MUTELIST EXAMPLE ###########################
7
+ Mutelist:
8
+ Accounts:
9
+ "example-project-id": # Your OpenStack project ID
10
+ Checks:
11
+ "compute_instance_security_groups_attached":
12
+ Regions:
13
+ - "EU-WEST-PAR"
14
+ Resources:
15
+ - "prowler-test-fail" # Mute by instance name
16
+ - "example-instance-id" # Mute by instance ID
17
+ Description: "Mute prowler-test-fail instance in compute_instance_security_groups_attached check"
18
+ "compute_*":
19
+ Regions:
20
+ - "*"
21
+ Resources:
22
+ - "test-*" # Mute all resources starting with "test-"
23
+ Description: "Mute all test instances for all compute checks"
24
+ "*":
25
+ Regions:
26
+ - "*"
27
+ Resources:
28
+ - "dev-instance"
29
+ Tags:
30
+ - "environment=dev" # Mute resources with environment=dev tag
31
+ - "testing=true"
32
+ Description: "Mute all resources with specific tags"
33
+
34
+ "*": # Apply to all projects
35
+ Checks:
36
+ "compute_instance_security_groups_attached":
37
+ Regions:
38
+ - "EU-WEST-PAR"
39
+ Resources:
40
+ - "legacy-.*" # Regex: mute all instances starting with "legacy-"
41
+ Description: "Mute legacy instances in EU-WEST-PAR region"
42
+ "*":
43
+ Regions:
44
+ - "*"
45
+ Resources:
46
+ - "*"
47
+ Tags:
48
+ - "prowler-ignore=true" # Mute any resource with this tag across all checks
49
+ Description: "Global mute for resources tagged with prowler-ignore=true"
50
+ "identity_password_policy_enabled":
51
+ Regions:
52
+ - "*"
53
+ Resources:
54
+ - "*"
55
+ Exceptions:
56
+ Accounts:
57
+ - "production-project-id"
58
+ Regions:
59
+ - "US-EAST-1"
60
+ Description: "Mute identity_password_policy_enabled everywhere EXCEPT in production-project-id in US-EAST-1"
@@ -687,6 +687,10 @@ def execute(
687
687
  is_finding_muted_args["account_id"] = (
688
688
  global_provider.identity.account_id
689
689
  )
690
+ elif global_provider.type == "openstack":
691
+ is_finding_muted_args["project_id"] = (
692
+ global_provider.identity.project_id
693
+ )
690
694
  for finding in check_findings:
691
695
  if global_provider.type == "cloudflare":
692
696
  is_finding_muted_args["account_id"] = finding.account_id
@@ -779,7 +779,10 @@ class CheckReportCloudflare(Check_Report):
779
779
 
780
780
  @property
781
781
  def zone_name(self) -> str:
782
- """Zone name."""
782
+ """Zone name - for DNS records use zone_name attribute, for zones use name."""
783
+ zone_name = getattr(self._zone, "zone_name", None)
784
+ if zone_name:
785
+ return zone_name
783
786
  return getattr(self._zone, "name", "")
784
787
 
785
788
  @property
@@ -792,7 +795,10 @@ class CheckReportCloudflare(Check_Report):
792
795
 
793
796
  @property
794
797
  def region(self) -> str:
795
- """Cloudflare is a global service."""
798
+ """Return zone_name as region for zone-scoped resources, otherwise global."""
799
+ zone_name = getattr(self._zone, "zone_name", None)
800
+ if zone_name:
801
+ return zone_name
796
802
  return "global"
797
803
 
798
804
 
@@ -907,6 +913,25 @@ class CheckReportNHN(Check_Report):
907
913
  self.location = getattr(resource, "location", "kr1")
908
914
 
909
915
 
916
+ @dataclass
917
+ class CheckReportOpenStack(Check_Report):
918
+ """Contains the OpenStack Check's finding information."""
919
+
920
+ resource_name: str
921
+ resource_id: str
922
+ project_id: str
923
+ region: str
924
+
925
+ def __init__(self, metadata: Dict, resource: Any) -> None:
926
+ super().__init__(metadata, resource)
927
+ self.resource_name = getattr(
928
+ resource, "name", getattr(resource, "resource_name", "default")
929
+ )
930
+ self.resource_id = getattr(resource, "id", getattr(resource, "resource_id", ""))
931
+ self.project_id = getattr(resource, "project_id", "")
932
+ self.region = getattr(resource, "region", "global")
933
+
934
+
910
935
  @dataclass
911
936
  class CheckReportMongoDBAtlas(Check_Report):
912
937
  """Contains the MongoDB Atlas Check's finding information."""
prowler/lib/cli/parser.py CHANGED
@@ -27,10 +27,10 @@ class ProwlerArgumentParser:
27
27
  self.parser = argparse.ArgumentParser(
28
28
  prog="prowler",
29
29
  formatter_class=RawTextHelpFormatter,
30
- usage="prowler [-h] [--version] {aws,azure,gcp,kubernetes,m365,github,nhn,mongodbatlas,oraclecloud,alibabacloud,cloudflare,dashboard,iac} ...",
30
+ usage="prowler [-h] [--version] {aws,azure,gcp,kubernetes,m365,github,nhn,mongodbatlas,oraclecloud,alibabacloud,cloudflare,openstack,dashboard,iac} ...",
31
31
  epilog="""
32
32
  Available Cloud Providers:
33
- {aws,azure,gcp,kubernetes,m365,github,iac,llm,nhn,mongodbatlas,oraclecloud,alibabacloud,cloudflare}
33
+ {aws,azure,gcp,kubernetes,m365,github,iac,llm,nhn,mongodbatlas,oraclecloud,alibabacloud,cloudflare,openstack}
34
34
  aws AWS Provider
35
35
  azure Azure Provider
36
36
  gcp GCP Provider
@@ -39,6 +39,7 @@ Available Cloud Providers:
39
39
  github GitHub Provider
40
40
  cloudflare Cloudflare Provider
41
41
  oraclecloud Oracle Cloud Infrastructure Provider
42
+ openstack OpenStack Provider
42
43
  alibabacloud Alibaba Cloud Provider
43
44
  iac IaC Provider (Beta)
44
45
  llm LLM Provider (Beta)
@@ -366,6 +366,20 @@ class Finding(BaseModel):
366
366
  )
367
367
  output_data["region"] = check_output.region
368
368
 
369
+ elif provider.type == "openstack":
370
+ output_data["auth_method"] = (
371
+ f"Username: {get_nested_attribute(provider, 'identity.username')}"
372
+ )
373
+ output_data["account_uid"] = get_nested_attribute(
374
+ provider, "identity.project_id"
375
+ )
376
+ output_data["account_name"] = get_nested_attribute(
377
+ provider, "identity.project_name"
378
+ )
379
+ output_data["resource_name"] = check_output.resource_name
380
+ output_data["resource_uid"] = check_output.resource_id
381
+ output_data["region"] = check_output.region
382
+
369
383
  # check_output Unique ID
370
384
  # TODO: move this to a function
371
385
  # TODO: in Azure, GCP and K8s there are findings without resource_name
@@ -1160,6 +1160,78 @@ class HTML(Output):
1160
1160
  )
1161
1161
  return ""
1162
1162
 
1163
+ @staticmethod
1164
+ def get_openstack_assessment_summary(provider: Provider) -> str:
1165
+ """
1166
+ get_openstack_assessment_summary gets the HTML assessment summary for the OpenStack provider
1167
+
1168
+ Args:
1169
+ provider (Provider): the OpenStack provider object
1170
+
1171
+ Returns:
1172
+ str: HTML assessment summary for the OpenStack provider
1173
+ """
1174
+ try:
1175
+ project_id = getattr(provider.identity, "project_id", "unknown")
1176
+ project_name = getattr(provider.identity, "project_name", "")
1177
+ region_name = getattr(provider.identity, "region_name", "unknown")
1178
+ username = getattr(provider.identity, "username", "unknown")
1179
+ user_id = getattr(provider.identity, "user_id", "")
1180
+
1181
+ project_name_item = (
1182
+ f"""
1183
+ <li class="list-group-item">
1184
+ <b>Project Name:</b> {project_name}
1185
+ </li>"""
1186
+ if project_name
1187
+ else ""
1188
+ )
1189
+
1190
+ user_id_item = (
1191
+ f"""
1192
+ <li class="list-group-item">
1193
+ <b>User ID:</b> {user_id}
1194
+ </li>"""
1195
+ if user_id
1196
+ else ""
1197
+ )
1198
+
1199
+ return f"""
1200
+ <div class="col-md-2">
1201
+ <div class="card">
1202
+ <div class="card-header">
1203
+ OpenStack Assessment Summary
1204
+ </div>
1205
+ <ul class="list-group list-group-flush">
1206
+ <li class="list-group-item">
1207
+ <b>Project ID:</b> {project_id}
1208
+ </li>
1209
+ {project_name_item}
1210
+ <li class="list-group-item">
1211
+ <b>Region:</b> {region_name}
1212
+ </li>
1213
+ </ul>
1214
+ </div>
1215
+ </div>
1216
+ <div class="col-md-4">
1217
+ <div class="card">
1218
+ <div class="card-header">
1219
+ OpenStack Credentials
1220
+ </div>
1221
+ <ul class="list-group list-group-flush">
1222
+ <li class="list-group-item">
1223
+ <b>Username:</b> {username}
1224
+ </li>
1225
+ {user_id_item}
1226
+ </ul>
1227
+ </div>
1228
+ </div>"""
1229
+ except Exception as error:
1230
+ logger.error(
1231
+ f"{error.__class__.__name__}[{error.__traceback__.tb_lineno}] -- {error}"
1232
+ )
1233
+ return ""
1234
+
1163
1235
  @staticmethod
1164
1236
  def get_assessment_summary(provider: Provider) -> str:
1165
1237
  """
@@ -1875,12 +1875,12 @@ class Jira:
1875
1875
  summary_parts.append(finding.resource_uid)
1876
1876
 
1877
1877
  summary = " - ".join(summary_parts[1:])
1878
- summary = f"{summary_parts[0]} {summary}"
1878
+ summary = f"{summary_parts[0]} {summary}"[:255]
1879
1879
 
1880
1880
  payload = {
1881
1881
  "fields": {
1882
1882
  "project": {"key": project_key},
1883
- "summary": f"[Prowler] {finding.metadata.Severity.value.upper()} - {finding.metadata.CheckID} - {finding.resource_uid}",
1883
+ "summary": summary,
1884
1884
  "description": adf_description,
1885
1885
  "issuetype": {"name": issue_type},
1886
1886
  "customfield_10148": {"value": "SDK"},
@@ -2081,7 +2081,7 @@ class Jira:
2081
2081
  if resource_uid:
2082
2082
  summary_parts.append(resource_uid)
2083
2083
  summary = " - ".join(summary_parts[1:])
2084
- summary = f"{summary_parts[0]} {summary}"
2084
+ summary = f"{summary_parts[0]} {summary}"[:255]
2085
2085
 
2086
2086
  payload = {
2087
2087
  "fields": {
@@ -32,6 +32,8 @@ def stdout_report(finding, color, verbose, status, fix):
32
32
  details = finding.region
33
33
  if finding.check_metadata.Provider == "alibabacloud":
34
34
  details = finding.region
35
+ if finding.check_metadata.Provider == "openstack":
36
+ details = finding.region
35
37
  if finding.check_metadata.Provider == "cloudflare":
36
38
  details = finding.zone_name
37
39
 
@@ -86,6 +86,13 @@ def display_summary_table(
86
86
  elif provider.type == "alibabacloud":
87
87
  entity_type = "Account"
88
88
  audited_entities = provider.identity.account_id
89
+ elif provider.type == "openstack":
90
+ entity_type = "Project"
91
+ audited_entities = (
92
+ provider.identity.project_name
93
+ if provider.identity.project_name
94
+ else provider.identity.project_id
95
+ )
89
96
 
90
97
  # Check if there are findings and that they are not all MANUAL
91
98
  if findings and not all(finding.status == "MANUAL" for finding in findings):
File without changes
@@ -0,0 +1,27 @@
1
+ from datetime import datetime
2
+ from typing import Any, Dict, Optional
3
+
4
+ from pydantic.v1 import BaseModel
5
+
6
+
7
+ class TimelineEvent(BaseModel):
8
+ """A timeline event representing a resource modification.
9
+
10
+ Provider-agnostic model that can be used by any timeline implementation
11
+ (AWS CloudTrail, Azure Activity Logs, GCP Audit Logs, etc.).
12
+ """
13
+
14
+ event_id: str
15
+ event_time: datetime
16
+ event_name: str
17
+ event_source: str
18
+ actor: str
19
+ actor_uid: Optional[str] = None
20
+ actor_type: Optional[str] = None
21
+ source_ip_address: Optional[str] = None
22
+ user_agent: Optional[str] = None
23
+ request_data: Optional[Dict[str, Any]] = None
24
+ response_data: Optional[Dict[str, Any]] = None
25
+ error_code: Optional[str] = None
26
+ error_message: Optional[str] = None
27
+ metadata: Optional[Dict[str, Any]] = None
@@ -0,0 +1,36 @@
1
+ """Abstract base class for timeline services."""
2
+
3
+ from abc import ABC, abstractmethod
4
+ from typing import Any, Dict, List, Optional
5
+
6
+
7
+ class TimelineService(ABC):
8
+ """Abstract base class for provider-specific timeline implementations.
9
+
10
+ Subclasses should implement the get_resource_timeline method to query
11
+ their provider's audit/activity log service (e.g., AWS CloudTrail,
12
+ Azure Activity Logs, GCP Audit Logs).
13
+ """
14
+
15
+ @abstractmethod
16
+ def get_resource_timeline(
17
+ self,
18
+ region: Optional[str] = None,
19
+ resource_id: Optional[str] = None,
20
+ resource_uid: Optional[str] = None,
21
+ ) -> List[Dict[str, Any]]:
22
+ """Get timeline events for a resource.
23
+
24
+ Args:
25
+ region: Region/location where the resource exists. Implementations
26
+ may provide a sensible default for global/regionless resources.
27
+ resource_id: Provider-specific resource ID (e.g., bucket name, instance ID)
28
+ resource_uid: Provider-specific unique identifier (e.g., AWS ARN, Azure Resource ID)
29
+
30
+ Returns:
31
+ List of timeline event dictionaries
32
+
33
+ Raises:
34
+ ValueError: If neither resource_id nor resource_uid is provided
35
+ """
36
+ raise NotImplementedError