From bd4366f59f89e7d67192c914270e395bae8010b7 Mon Sep 17 00:00:00 2001 From: pedrooot Date: Wed, 13 Nov 2024 12:17:09 +0100 Subject: [PATCH 01/10] feat(compliance): add ens for azure --- prowler/__main__.py | 15 + .../compliance/azure/ens_rd2022_azure.json | 1173 +++++++++++++++++ prowler/lib/outputs/compliance/ens/ens.py | 2 +- .../lib/outputs/compliance/ens/ens_azure.py | 103 ++ prowler/lib/outputs/compliance/ens/models.py | 29 + 5 files changed, 1321 insertions(+), 1 deletion(-) create mode 100644 prowler/compliance/azure/ens_rd2022_azure.json create mode 100644 prowler/lib/outputs/compliance/ens/ens_azure.py diff --git a/prowler/__main__.py b/prowler/__main__.py index 71325e1f4af..70608f1dc18 100644 --- a/prowler/__main__.py +++ b/prowler/__main__.py @@ -53,6 +53,7 @@ from prowler.lib.outputs.compliance.cis.cis_kubernetes import KubernetesCIS from prowler.lib.outputs.compliance.compliance import display_compliance_table from prowler.lib.outputs.compliance.ens.ens_aws import AWSENS +from prowler.lib.outputs.compliance.ens.ens_azure import AzureENS from prowler.lib.outputs.compliance.generic.generic import GenericCompliance from prowler.lib.outputs.compliance.iso27001.iso27001_aws import AWSISO27001 from prowler.lib.outputs.compliance.kisa_ismsp.kisa_ismsp_aws import AWSKISAISMSP @@ -511,6 +512,20 @@ def prowler(): ) generated_outputs["compliance"].append(mitre_attack) mitre_attack.batch_write_data_to_file() + elif compliance_name.startswith("ens_"): + # Generate ENS Finding Object + filename = ( + f"{output_options.output_directory}/compliance/" + f"{output_options.output_filename}_{compliance_name}.csv" + ) + ens = AzureENS( + findings=finding_outputs, + compliance=bulk_compliance_frameworks[compliance_name], + create_file_descriptor=True, + file_path=filename, + ) + generated_outputs["compliance"].append(ens) + ens.batch_write_data_to_file() else: filename = ( f"{output_options.output_directory}/compliance/" diff --git a/prowler/compliance/azure/ens_rd2022_azure.json b/prowler/compliance/azure/ens_rd2022_azure.json new file mode 100644 index 00000000000..5fff5ebdf39 --- /dev/null +++ b/prowler/compliance/azure/ens_rd2022_azure.json @@ -0,0 +1,1173 @@ +{ + "Framework": "ENS", + "Version": "RD2022", + "Provider": "Azure", + "Description": "The accreditation scheme of the ENS (National Security Scheme) has been developed by the Ministry of Finance and Public Administrations and the CCN (National Cryptological Center). This includes the basic principles and minimum requirements necessary for the adequate protection of information.", + "Requirements": [ + { + "Id": "op.acc.1.az.eid.1", + "Description": "Identificación", + "Attributes": [ + { + "IdGrupoControl": "op.acc.1", + "Marco": "operacional", + "Categoria": "control de acceso", + "DescripcionControl": "Se deberá utilizar las credenciales de acceso de la organización configurando el uso de cuentas de usuario y grupos con Microsoft Entra.", + "Nivel": "alto", + "Tipo": "requisito", + "Dimensiones": [ + "trazabilidad", + "autenticidad" + ], + "ModoEjecucion": "automático", + "Dependencias": [] + } + ], + "Checks": [ + "app_ensure_auth_is_set_up" + ] + }, + { + "Id": "op.acc.1.az.r1.eid.1", + "Description": "Identificacion Avanzada", + "Attributes": [ + { + "IdGrupoControl": "op.acc.1.r1", + "Marco": "operacional", + "Categoria": "control de acceso", + "DescripcionControl": "La asignación del usuario deberá realizarse de manera única, singularizando a la persona asociada a cada identificador en Microsoft Entra", + "Nivel": "alto", + "Tipo": "refuerzo", + "Dimensiones": [ + "trazabilidad", + "autenticidad" + ], + "ModoEjecucion": "automático", + "Dependencias": [] + } + ], + "Checks": [ + "entra_global_admin_in_less_than_five_users" + ] + }, + { + "Id": "op.acc.2.az.rbac.1", + "Description": "Requisitos de acceso", + "Attributes": [ + { + "IdGrupoControl": "op.acc.2", + "Marco": "operacional", + "Categoria": "control de acceso", + "DescripcionControl": "Se debe aplicar la restricción de acceso al portal de Azure y la habilitación de Microsoft Entra Protection para minimizar los riesgos de inicio de sesión y comportamientos inusuales.", + "Nivel": "alto", + "Tipo": "requisito", + "Dimensiones": [ + "confidencialidad", + "integridad", + "trazabilidad", + "autenticidad" + ], + "ModoEjecucion": "automático", + "Dependencias": [] + } + ], + "Checks": [ + "entra_policy_default_users_cannot_create_security_groups", + "entra_policy_ensure_default_user_cannot_create_tenants", + "iam_subscription_roles_owner_custom_not_created" + ] + }, + { + "Id": "op.acc.2.az.r1.eid.1", + "Description": "Privilegios de acceso", + "Attributes": [ + { + "IdGrupoControl": "op.acc.2.r1", + "Marco": "operacional", + "Categoria": "control de acceso", + "DescripcionControl": "Requisito de la configuración a través de la aplicación de roles RBAC", + "Nivel": "alto", + "Tipo": "refuerzo", + "Dimensiones": [ + "confidencialidad", + "integridad", + "trazabilidad", + "autenticidad" + ], + "ModoEjecucion": "automático", + "Dependencias": [] + } + ], + "Checks": [ + "aks_cluster_rbac_enabled", + "entra_policy_restricts_user_consent_for_apps", + "entra_users_cannot_create_microsoft_365_groups", + "entra_policy_user_consent_for_verified_apps", + "keyvault_rbac_enabled" + ] + }, + { + "Id": "op.acc.3.az.eid.1", + "Description": "Segregación de funciones y tareas", + "Attributes": [ + { + "IdGrupoControl": "op.acc.3", + "Marco": "operacional", + "Categoria": "control de acceso", + "DescripcionControl": "Se deberá separar las funciones según el entorno de trabajo, y según las obligaciones, asegurándo que un usuario no pueda tener funciones de desarrollo y operación. ", + "Nivel": "alto", + "Tipo": "requisito", + "Dimensiones": [ + "confidencialidad", + "integridad", + "trazabilidad", + "autenticidad" + ], + "ModoEjecucion": "automático", + "Dependencias": [] + } + ], + "Checks": [ + "iam_custom_role_has_permissions_to_administer_resource_locks" + ] + }, + { + "Id": "op.acc.5.r2.az.eid.1", + "Description": "Contraseña + OTP", + "Attributes": [ + { + "IdGrupoControl": "op.acc.5.r2", + "Marco": "operacional", + "Categoria": "control de acceso", + "DescripcionControl": "Proteger el acceso a los datos y aplicaciones a travez de la autenticación multifactor (MFA) de Microsoft Entra", + "Nivel": "alto", + "Tipo": "refuerzo", + "Dimensiones": [ + "confidencialidad", + "integridad", + "trazabilidad", + "autenticidad" + ], + "ModoEjecucion": "automático", + "Dependencias": [] + } + ], + "Checks": [ + "entra_privileged_user_has_mfa", + "entra_security_defaults_enabled" + ] + }, + { + "Id": "op.acc.5.r3.az.kv.1", + "Description": "Certificados", + "Attributes": [ + { + "IdGrupoControl": "op.acc.5.r3", + "Marco": "operacional", + "Categoria": "control de acceso", + "DescripcionControl": "Utilizar el servicio KEY Vault para la gestión de certificados asociados a Cloud Services", + "Nivel": "alto", + "Tipo": "refuerzo", + "Dimensiones": [ + "confidencialidad", + "integridad", + "trazabilidad", + "autenticidad" + ], + "ModoEjecucion": "automático", + "Dependencias": [] + } + ], + "Checks": [ + "keyvault_logging_enabled", + "keyvault_rbac_enabled", + "app_client_certificates_on" + ] + }, + { + "Id": "op.acc.5.r4.az.eid.1", + "Description": "Certificados en dispositivo físico", + "Attributes": [ + { + "IdGrupoControl": "op.acc.5.r4", + "Marco": "operacional", + "Categoria": "control de acceso", + "DescripcionControl": "Habilitación de autenticación MFA para usuarios externos", + "Nivel": "alto", + "Tipo": "refuerzo", + "Dimensiones": [ + "confidencialidad", + "integridad", + "trazabilidad", + "autenticidad" + ], + "ModoEjecucion": "automático", + "Dependencias": [] + } + ], + "Checks": [ + "entra_conditional_access_policy_require_mfa_for_management_api" + ] + }, + { + "Id": "op.acc.5.r5.az.eid.1", + "Description": "Registro", + "Attributes": [ + { + "IdGrupoControl": "op.acc.5.r5", + "Marco": "operacional", + "Categoria": "control de acceso", + "DescripcionControl": "Habilitar los valores de seguridad de Entra Id por defecto", + "Nivel": "alto", + "Tipo": "refuerzo", + "Dimensiones": [ + "confidencialidad", + "integridad", + "trazabilidad", + "autenticidad" + ], + "ModoEjecucion": "automático", + "Dependencias": [] + } + ], + "Checks": [ + "entra_security_defaults_enabled" + ] + }, + { + "Id": "op.acc.6.az.eid1", + "Description": "Mecanismo de autenticación (usuarios de la organización)", + "Attributes": [ + { + "IdGrupoControl": "op.acc.6", + "Marco": "operacional", + "Categoria": "control de acceso", + "DescripcionControl": "El acceso del usuario será gestionado desde Microsoft Entra", + "Nivel": "alto", + "Tipo": "requisito", + "Dimensiones": [ + "confidencialidad", + "integridad", + "trazabilidad", + "autenticidad" + ], + "ModoEjecucion": "automático", + "Dependencias": [] + } + ], + "Checks": [ + "entra_conditional_access_policy_require_mfa_for_management_api" + ] + }, + { + "Id": "op.acc.6.r1.az.eid1", + "Description": "Contraseñas", + "Attributes": [ + { + "IdGrupoControl": "op.acc.6.r1", + "Marco": "operacional", + "Categoria": "control de acceso", + "DescripcionControl": "Deberá habilitarse el vencimiento de las credenciales de los usuarios", + "Nivel": "alto", + "Tipo": "refuerzo", + "Dimensiones": [ + "confidencialidad", + "integridad", + "trazabilidad", + "autenticidad" + ], + "ModoEjecucion": "automático", + "Dependencias": [] + } + ], + "Checks": [ + "keyvault_key_expiration_set_in_non_rbac" + ] + }, + { + "Id": "op.acc.6.r1.az.eid2", + "Description": "Contraseñas", + "Attributes": [ + { + "IdGrupoControl": "op.acc.6.r1", + "Marco": "operacional", + "Categoria": "control de acceso", + "DescripcionControl": "Las credenciales deberan rotarse cada 90 días o menos", + "Nivel": "alto", + "Tipo": "refuerzo", + "Dimensiones": [ + "confidencialidad", + "integridad", + "trazabilidad", + "autenticidad" + ], + "ModoEjecucion": "automático", + "Dependencias": [] + } + ], + "Checks": [ + "storage_key_rotation_90_days", + "keyvault_rbac_key_expiration_set", + "keyvault_rbac_secret_expiration_set" + ] + }, + { + "Id": "op.acc.6.r1.az.eid3", + "Description": "Contraseñas", + "Attributes": [ + { + "IdGrupoControl": "op.acc.6.r1", + "Marco": "operacional", + "Categoria": "control de acceso", + "DescripcionControl": "Habilitar la protección de Defender para los KEY Vault", + "Nivel": "alto", + "Tipo": "refuerzo", + "Dimensiones": [ + "confidencialidad", + "integridad", + "trazabilidad", + "autenticidad" + ], + "ModoEjecucion": "automático", + "Dependencias": [] + } + ], + "Checks": [ + "defender_ensure_defender_for_keyvault_is_on" + ] + }, + { + "Id": "op.acc.6.r2.az.eid1", + "Description": "Contraseña + otro factor de autenticación", + "Attributes": [ + { + "IdGrupoControl": "op.acc.6.r2", + "Marco": "operacional", + "Categoria": "control de acceso", + "DescripcionControl": "Proteger el acceso a los datos y aplicaciones a travez de la autenticación multifactor (MFA) de Microsoft Entra", + "Nivel": "alto", + "Tipo": "refuerzo", + "Dimensiones": [ + "confidencialidad", + "integridad", + "trazabilidad", + "autenticidad" + ], + "ModoEjecucion": "automático", + "Dependencias": [] + } + ], + "Checks": [ + "entra_privileged_user_has_mfa", + "entra_security_defaults_enabled" + ] + }, + { + "Id": "op.acc.6.r3.az.kv1", + "Description": "Certificados", + "Attributes": [ + { + "IdGrupoControl": "op.acc.6.r3", + "Marco": "operacional", + "Categoria": "control de acceso", + "DescripcionControl": "Utilizar el servicio KEY Vault para la gestión de certificados asociados a Cloud Services", + "Nivel": "alto", + "Tipo": "refuerzo", + "Dimensiones": [ + "confidencialidad", + "integridad", + "trazabilidad", + "autenticidad" + ], + "ModoEjecucion": "automático", + "Dependencias": [] + } + ], + "Checks": [ + "keyvault_logging_enabled", + "keyvault_rbac_enabled", + "app_client_certificates_on" + ] + }, + { + "Id": "op.acc.6.r4.az.mfa1", + "Description": "Certificados en dispositivo físico", + "Attributes": [ + { + "IdGrupoControl": "op.acc.6.r4", + "Marco": "operacional", + "Categoria": "control de acceso", + "DescripcionControl": "Habilitación de autenticación MFA para usuarios de la organización", + "Nivel": "alto", + "Tipo": "refuerzo", + "Dimensiones": [ + "confidencialidad", + "integridad", + "trazabilidad", + "autenticidad" + ], + "ModoEjecucion": "automático", + "Dependencias": [] + } + ], + "Checks": [ + "entra_conditional_access_policy_require_mfa_for_management_api" + ] + }, + { + "Id": "op.acc.6.r5.az.eid1", + "Description": "Registro de la actividad", + "Attributes": [ + { + "IdGrupoControl": "op.acc.6.r5", + "Marco": "operacional", + "Categoria": "control de acceso", + "DescripcionControl": "Registro de la actividad en la sesión del usuario configurando los valores de seguridad por defecto.", + "Nivel": "alto", + "Tipo": "refuerzo", + "Dimensiones": [ + "confidencialidad", + "integridad", + "trazabilidad", + "autenticidad" + ], + "ModoEjecucion": "automático", + "Dependencias": [] + } + ], + "Checks": [ + "entra_security_defaults_enabled", + "iam_custom_role_has_permissions_to_administer_resource_locks" + ] + }, + { + "Id": "op.acc.6.r8.az.eid1", + "Description": "Doble factor para acceso desde o através de zonas no controladas", + "Attributes": [ + { + "IdGrupoControl": "op.acc.6.r8", + "Marco": "operacional", + "Categoria": "control de acceso", + "DescripcionControl": "Se utilizará como mecanismo de autenticación adicional a la contraseña, un factor de autenticación.", + "Nivel": "alto", + "Tipo": "refuerzo", + "Dimensiones": [ + "confidencialidad", + "integridad", + "trazabilidad", + "autenticidad" + ], + "ModoEjecucion": "automático", + "Dependencias": [] + } + ], + "Checks": [ + "entra_non_privileged_user_has_mfa", + "entra_user_with_vm_access_has_mfa" + ] + }, + { + "Id": "op.exp.8.az.md1", + "Description": "Registro de la actividad", + "Attributes": [ + { + "IdGrupoControl": "op.exp.8", + "Marco": "operacional", + "Categoria": "explotación", + "DescripcionControl": "Se habilitará el monitor de diagnóstico para cada categoría usada dentro de la subscripción.", + "Nivel": "alto", + "Tipo": "requisito", + "Dimensiones": [ + "trazabilidad" + ], + "ModoEjecucion": "automático", + "Dependencias": [] + } + ], + "Checks": [ + "entra_trusted_named_locations_exists", + "monitor_diagnostic_setting_with_appropriate_categories" + ] + }, + { + "Id": "op.exp.8.r4.az.sa1", + "Description": "Control de acceso", + "Attributes": [ + { + "IdGrupoControl": "op.exp.8.r4", + "Marco": "operacional", + "Categoria": "explotación", + "DescripcionControl": "Configuración de la actividad de las cuentas de almacenamiento.", + "Nivel": "alto", + "Tipo": "refuerzo", + "Dimensiones": [ + "trazabilidad" + ], + "ModoEjecucion": "automático", + "Dependencias": [] + } + ], + "Checks": [ + "monitor_storage_account_with_activity_logs_cmk_encrypted" + ] + }, + { + "Id": "op.exp.8.r4.az.sa2", + "Description": "Control de acceso", + "Attributes": [ + { + "IdGrupoControl": "op.exp.8.r4", + "Marco": "operacional", + "Categoria": "explotación", + "DescripcionControl": "Configuración del acceso por defecto a las cuentas de almacenamiento definida como denegada", + "Nivel": "alto", + "Tipo": "refuerzo", + "Dimensiones": [ + "trazabilidad" + ], + "ModoEjecucion": "automático", + "Dependencias": [] + } + ], + "Checks": [ + "storage_default_network_access_rule_is_denied" + ] + }, + { + "Id": "op.exp.10.az.kv2", + "Description": "Protección de claves criptográficas", + "Attributes": [ + { + "IdGrupoControl": "op.exp.10 ", + "Marco": "operacional", + "Categoria": "explotación", + "DescripcionControl": "Habilitación de las claves criptográficas para las cuentas de almacenamiento", + "Nivel": "alto", + "Tipo": "requisito", + "Dimensiones": [ + "confidencialidad", + "integridad", + "trazabilidad", + "autenticidad", + "disponibilidad" + ], + "ModoEjecucion": "automático", + "Dependencias": [] + } + ], + "Checks": [ + "storage_infrastructure_encryption_is_enabled", + "storage_ensure_encryption_with_customer_managed_keys" + ] + }, + { + "Id": "op.mon.1.az.nw.1", + "Description": "Detección de intrusión", + "Attributes": [ + { + "IdGrupoControl": "op.mon.1 ", + "Marco": "operacional", + "Categoria": "monitorización del sistema", + "DescripcionControl": "Activación del Network Watcher para la captura de paquetes y detección del tráfico de la red.", + "Nivel": "alto", + "Tipo": "requisito", + "Dimensiones": [ + "confidencialidad", + "integridad", + "trazabilidad", + "autenticidad", + "disponibilidad" + ], + "ModoEjecucion": "automático", + "Dependencias": [] + } + ], + "Checks": [ + "entra_security_defaults_enabled", + "network_watcher_enabled" + ] + }, + { + "Id": "op.mon.1.r1.az.nf.1", + "Description": "Detección basada en reglas", + "Attributes": [ + { + "IdGrupoControl": "op.mon.1.r1 ", + "Marco": "operacional", + "Categoria": "monitorización del sistema", + "DescripcionControl": "Activación del Network Flow Log para la identificación del tráfico de la red.", + "Nivel": "alto", + "Tipo": "refuerzo", + "Dimensiones": [ + "confidencialidad", + "integridad", + "trazabilidad", + "autenticidad", + "disponibilidad" + ], + "ModoEjecucion": "automático", + "Dependencias": [] + } + ], + "Checks": [ + "network_flow_log_captured_sent" + ] + }, + { + "Id": "op.mon.1.r2.az.de.1", + "Description": "Procedimientos de respuesta", + "Attributes": [ + { + "IdGrupoControl": "op.mon.1.r2 ", + "Marco": "operacional", + "Categoria": "monitorización del sistema", + "DescripcionControl": "Utilizar Defender para el análisis y verificación de vulnerabilidades detectadas.", + "Nivel": "alto", + "Tipo": "refuerzo", + "Dimensiones": [ + "confidencialidad", + "integridad", + "trazabilidad", + "autenticidad", + "disponibilidad" + ], + "ModoEjecucion": "automático", + "Dependencias": [] + } + ], + "Checks": [ + "defender_container_images_resolved_vulnerabilities" + ] + }, + { + "Id": "op.mon.2.az.md.1", + "Description": "Sistema de métricas", + "Attributes": [ + { + "IdGrupoControl": "op.mon.2 ", + "Marco": "operacional", + "Categoria": "monitorización del sistema", + "DescripcionControl": "Configurar el monitor de diagnóstico para los elementos habilitados de la nube.", + "Nivel": "alto", + "Tipo": "requisito", + "Dimensiones": [ + "confidencialidad", + "integridad", + "trazabilidad", + "autenticidad", + "disponibilidad" + ], + "ModoEjecucion": "automático", + "Dependencias": [] + } + ], + "Checks": [ + "monitor_diagnostic_setting_with_appropriate_categories" + ] + }, + { + "Id": "op.mon.3.r3.az.de.1", + "Description": "Ciberamenazas avanzadas", + "Attributes": [ + { + "IdGrupoControl": "op.mon.3.r3 ", + "Marco": "operacional", + "Categoria": "monitorización del sistema", + "DescripcionControl": "Se deberá utilizar la evaluación de vulnerabilidades con Defender y el aseguramiento de la notificación de alertas de severidad alta.", + "Nivel": "alto", + "Tipo": "refuerzo", + "Dimensiones": [ + "confidencialidad", + "integridad", + "trazabilidad", + "autenticidad", + "disponibilidad" + ], + "ModoEjecucion": "automático", + "Dependencias": [] + } + ], + "Checks": [ + "defender_auto_provisioning_vulnerabilty_assessments_machines_on", + "defender_ensure_notify_alerts_severity_is_high" + ] + }, + { + "Id": "op.mon.3.r3.az.de.2", + "Description": "Ciberamenazas avanzadas", + "Attributes": [ + { + "IdGrupoControl": "op.mon.3.r3 ", + "Marco": "operacional", + "Categoria": "monitorización del sistema", + "DescripcionControl": "Habilitar la protección de amenazas avanzadas para la detección de ciberamenazas en la nube.", + "Nivel": "alto", + "Tipo": "refuerzo", + "Dimensiones": [ + "confidencialidad", + "integridad", + "trazabilidad", + "autenticidad", + "disponibilidad" + ], + "ModoEjecucion": "automático", + "Dependencias": [] + } + ], + "Checks": [ + "defender_ensure_wdatp_is_enabled" + ] + }, + { + "Id": "op.mon.3.r4.az.de.1", + "Description": "Observatorios digitales", + "Attributes": [ + { + "IdGrupoControl": "op.mon.3.r4 ", + "Marco": "operacional", + "Categoria": "monitorización del sistema", + "DescripcionControl": "Se deberá asegurar las notificaciones por correo a los propietarios a través de Defender.", + "Nivel": "alto", + "Tipo": "refuerzo", + "Dimensiones": [ + "confidencialidad", + "integridad", + "trazabilidad", + "autenticidad", + "disponibilidad" + ], + "ModoEjecucion": "automático", + "Dependencias": [] + } + ], + "Checks": [ + "defender_ensure_notify_emails_to_owners" + ] + }, + { + "Id": "op.mon.3.r6.az.ma.1", + "Description": "Inspecciones de seguridad", + "Attributes": [ + { + "IdGrupoControl": "op.mon.3.r6 ", + "Marco": "operacional", + "Categoria": "monitorización del sistema", + "DescripcionControl": "Utilizar las alertas para las inspecciones de seguridad", + "Nivel": "alto", + "Tipo": "refuerzo", + "Dimensiones": [ + "confidencialidad", + "integridad", + "trazabilidad", + "autenticidad", + "disponibilidad" + ], + "ModoEjecucion": "automático", + "Dependencias": [] + } + ], + "Checks": [ + "monitor_alert_create_update_security_solution" + ] + }, + { + "Id": "mp.com.1.az.nw.1", + "Description": "Perímetro seguro", + "Attributes": [ + { + "IdGrupoControl": "mp.com.1", + "Marco": "medidas de protección", + "Categoria": "protección de las comunicaciones", + "DescripcionControl": "Habilitar la restricción de acceso para el tráfico por internet a través de RDP", + "Nivel": "alto", + "Tipo": "requisito", + "Dimensiones": [ + "confidencialidad", + "integridad", + "trazabilidad", + "autenticidad", + "disponibilidad" + ], + "ModoEjecucion": "automático", + "Dependencias": [] + } + ], + "Checks": [ + "network_watcher_enabled", + "network_rdp_internet_access_restricted" + ] + }, + { + "Id": "mp.com.1.az.nw.3", + "Description": "Perímetro seguro", + "Attributes": [ + { + "IdGrupoControl": "mp.com.1", + "Marco": "medidas de protección", + "Categoria": "protección de las comunicaciones", + "DescripcionControl": "Habilitar la restricción de acceso para el tráfico por internet a través de UDP.", + "Nivel": "alto", + "Tipo": "requisito", + "Dimensiones": [ + "confidencialidad", + "integridad", + "trazabilidad", + "autenticidad", + "disponibilidad" + ], + "ModoEjecucion": "automático", + "Dependencias": [] + } + ], + "Checks": [ + "network_watcher_enabled", + "network_udp_internet_access_restricted" + ] + }, + { + "Id": "mp.com.3.az.sa.1", + "Description": "Protección de la integridad y de la autenticidad", + "Attributes": [ + { + "IdGrupoControl": "mp.com.3 ", + "Marco": "medidas de protección", + "Categoria": "protección de las comunicaciones", + "DescripcionControl": "Asegurarse que la seguridad en transferencia de datos para las cuentas de almacenamiento esté habilitada", + "Nivel": "alto", + "Tipo": "requisito", + "Dimensiones": [ + "integridad", + "autenticidad" + ], + "ModoEjecucion": "automático", + "Dependencias": [] + } + ], + "Checks": [ + "storage_secure_transfer_required_is_enabled" + ] + }, + { + "Id": "mp.com.3.r1.az.nt.1", + "Description": "Redes privadas virtuales", + "Attributes": [ + { + "IdGrupoControl": "mp.com.3.r1 ", + "Marco": "medidas de protección", + "Categoria": "protección de las comunicaciones", + "DescripcionControl": "Habilitar la integración de las redes privadas virtuales para las funciones de aplicación", + "Nivel": "alto", + "Tipo": "refuerzo", + "Dimensiones": [ + "integridad", + "autenticidad" + ], + "ModoEjecucion": "automático", + "Dependencias": [] + } + ], + "Checks": [ + "app_function_vnet_integration_enabled" + ] + }, + { + "Id": "mp.com.3.r2.az.tls.1", + "Description": "Algoritmos y parámetros autorizados", + "Attributes": [ + { + "IdGrupoControl": "mp.com.3.r2 ", + "Marco": "medidas de protección", + "Categoria": "protección de las comunicaciones", + "DescripcionControl": "La versión de TLS para las aplicaciones debe de ser como mínimo versión 1.2", + "Nivel": "alto", + "Tipo": "refuerzo", + "Dimensiones": [ + "integridad", + "autenticidad" + ], + "ModoEjecucion": "automático", + "Dependencias": [] + } + ], + "Checks": [ + "app_minimum_tls_version_12", + "network_http_internet_access_restricted" + ] + }, + { + "Id": "mp.com.3.r2.az.tls.2", + "Description": "Algoritmos y parámetros autorizados", + "Attributes": [ + { + "IdGrupoControl": "mp.com.3.r2 ", + "Marco": "medidas de protección", + "Categoria": "protección de las comunicaciones", + "DescripcionControl": "La versión de TLS para MYSQL debe ser como mínimo versión 1.2", + "Nivel": "alto", + "Tipo": "refuerzo", + "Dimensiones": [ + "integridad", + "autenticidad" + ], + "ModoEjecucion": "automático", + "Dependencias": [] + } + ], + "Checks": [ + "mysql_flexible_server_minimum_tls_version_12" + ] + }, + { + "Id": "mp.com.4.az.nt.1", + "Description": "Separación de flujos de información en la red", + "Attributes": [ + { + "IdGrupoControl": "mp.com.4", + "Marco": "medidas de protección", + "Categoria": "protección de las comunicaciones", + "DescripcionControl": "Evitar el uso de subnets con acceso a IPs públicas.", + "Nivel": "alto", + "Tipo": "requisito", + "Dimensiones": [ + "confidencialidad", + "integridad", + "trazabilidad", + "autenticidad", + "disponibilidad" + ], + "ModoEjecucion": "automático", + "Dependencias": [] + } + ], + "Checks": [ + "app_function_vnet_integration_enabled", + "app_function_not_publicly_accessible" + ] + }, + { + "Id": "mp.com.4.az.aks.2", + "Description": "Separación de flujos de información en la red", + "Attributes": [ + { + "IdGrupoControl": "mp.com.4", + "Marco": "medidas de protección", + "Categoria": "protección de las comunicaciones", + "DescripcionControl": "Evitar el uso de subnets con acceso a IPs públicas, para AKS", + "Nivel": "alto", + "Tipo": "requisito", + "Dimensiones": [ + "confidencialidad", + "integridad", + "trazabilidad", + "autenticidad", + "disponibilidad" + ], + "ModoEjecucion": "automático", + "Dependencias": [] + } + ], + "Checks": [ + "aks_clusters_public_access_disabled" + ] + }, + { + "Id": "mp.com.4.r1.az.nt.1", + "Description": "Segmentación lógica básica", + "Attributes": [ + { + "IdGrupoControl": "mp.com.4.r1", + "Marco": "medidas de protección", + "Categoria": "protección de las comunicaciones", + "DescripcionControl": "Implementación de la segmentación de VNET en diferentes ubicaciones", + "Nivel": "alto", + "Tipo": "refuerzo", + "Dimensiones": [ + "confidencialidad", + "integridad", + "trazabilidad", + "autenticidad", + "disponibilidad" + ], + "ModoEjecucion": "automático", + "Dependencias": [] + } + ], + "Checks": [ + "app_function_vnet_integration_enabled" + ] + }, + { + "Id": "mp.com.4.r2.az.aks.1", + "Description": "Segmentación lógica avanzada", + "Attributes": [ + { + "IdGrupoControl": "mp.com.4.r2", + "Marco": "medidas de protección", + "Categoria": "protección de las comunicaciones", + "DescripcionControl": "Habilitar las políticas de red para AKS", + "Nivel": "alto", + "Tipo": "refuerzo", + "Dimensiones": [ + "confidencialidad", + "integridad", + "trazabilidad", + "autenticidad", + "disponibilidad" + ], + "ModoEjecucion": "automático", + "Dependencias": [] + } + ], + "Checks": [ + "aks_network_policy_enabled", + "aks_clusters_created_with_private_nodes", + "keyvault_private_endpoints" + ] + }, + { + "Id": "mp.com.4.r2..az.sa.1", + "Description": "Segmentación lógica avanzada", + "Attributes": [ + { + "IdGrupoControl": "mp.com.4.r2", + "Marco": "medidas de protección", + "Categoria": "protección de las comunicaciones", + "DescripcionControl": "Habilitar los endpoints privados en cuentas de almacenamiento", + "Nivel": "alto", + "Tipo": "refuerzo", + "Dimensiones": [ + "confidencialidad", + "integridad", + "trazabilidad", + "autenticidad", + "disponibilidad" + ], + "ModoEjecucion": "automático", + "Dependencias": [] + } + ], + "Checks": [ + "storage_ensure_private_endpoints_in_storage_accounts" + ] + }, + { + "Id": "mp.com.4.r3.az.1", + "Description": "Segmentación física", + "Attributes": [ + { + "IdGrupoControl": "mp.com.4.r3", + "Marco": "medidas de protección", + "Categoria": "protección de las comunicaciones", + "DescripcionControl": "Configuración de VNETs para el aislamiento de redes", + "Nivel": "alto", + "Tipo": "refuerzo", + "Dimensiones": [ + "confidencialidad", + "integridad", + "trazabilidad", + "autenticidad", + "disponibilidad" + ], + "ModoEjecucion": "automático", + "Dependencias": [] + } + ], + "Checks": [ + "network_http_internet_access_restricted" + ] + }, + { + "Id": "mp.com.4.r4.az.nt.1", + "Description": "Puntos de interconexión", + "Attributes": [ + { + "IdGrupoControl": "mp.com.4.r4", + "Marco": "medidas de protección", + "Categoria": "protección de las comunicaciones", + "DescripcionControl": "Asegurarse de que el acceso a la red de conexión con internet esté protegida.", + "Nivel": "alto", + "Tipo": "refuerzo", + "Dimensiones": [ + "confidencialidad", + "integridad", + "trazabilidad", + "autenticidad", + "disponibilidad" + ], + "ModoEjecucion": "automático", + "Dependencias": [] + } + ], + "Checks": [ + "network_http_internet_access_restricted", + "network_bastion_host_exists" + ] + }, + { + "Id": "mp.info.6.r2.az.sa.1", + "Description": "Protección de las copias de seguridad", + "Attributes": [ + { + "IdGrupoControl": "mp.info.6.r2", + "Marco": "medidas de protección", + "Categoria": "protección de la información", + "DescripcionControl": "Asegurarse que los servicios de almacenamiento tenga acceso de confianza.", + "Nivel": "alto", + "Tipo": "refuerzo", + "Dimensiones": [ + "disponibilidad" + ], + "ModoEjecucion": "automático", + "Dependencias": [] + } + ], + "Checks": [ + "storage_ensure_azure_services_are_trusted_to_access_is_enabled" + ] + }, + { + "Id": "mp.s.4.az.nt.1", + "Description": "Protección frente a denegación de servicio", + "Attributes": [ + { + "IdGrupoControl": "mp.s.4", + "Marco": "medidas de protección", + "Categoria": "protección de los servicios", + "DescripcionControl": "El acceso a la red de conexión con internet debe estar restringida.", + "Nivel": "alto", + "Tipo": "requisito", + "Dimensiones": [ + "disponibilidad" + ], + "ModoEjecucion": "automático", + "Dependencias": [] + } + ], + "Checks": [ + "network_http_internet_access_restricted" + ] + }, + { + "Id": "mp.s.4.r1.az.nt.1", + "Description": "Detección y reacción", + "Attributes": [ + { + "IdGrupoControl": "mp.s.4.r1", + "Marco": "medidas de protección", + "Categoria": "protección de los servicios", + "DescripcionControl": "Habilitar el flujo de logs de la red para la captura de los datos enviados", + "Nivel": "alto", + "Tipo": "requisito", + "Dimensiones": [ + "disponibilidad" + ], + "ModoEjecucion": "automático", + "Dependencias": [] + } + ], + "Checks": [ + "network_flow_log_captured_sent" + ] + } + ] +} diff --git a/prowler/lib/outputs/compliance/ens/ens.py b/prowler/lib/outputs/compliance/ens/ens.py index 923638350fc..64107f7ff74 100644 --- a/prowler/lib/outputs/compliance/ens/ens.py +++ b/prowler/lib/outputs/compliance/ens/ens.py @@ -30,7 +30,7 @@ def get_ens_table( check = bulk_checks_metadata[finding.check_metadata.CheckID] check_compliances = check.Compliance for compliance in check_compliances: - if compliance.Framework == "ENS" and compliance.Provider == "AWS": + if compliance.Framework == "ENS": for requirement in compliance.Requirements: for attribute in requirement.Attributes: marco_categoria = f"{attribute.Marco}/{attribute.Categoria}" diff --git a/prowler/lib/outputs/compliance/ens/ens_azure.py b/prowler/lib/outputs/compliance/ens/ens_azure.py new file mode 100644 index 00000000000..5858ee44510 --- /dev/null +++ b/prowler/lib/outputs/compliance/ens/ens_azure.py @@ -0,0 +1,103 @@ +from prowler.lib.check.compliance_models import Compliance +from prowler.lib.outputs.compliance.compliance_output import ComplianceOutput +from prowler.lib.outputs.compliance.ens.models import AzureENSModel +from prowler.lib.outputs.finding import Finding + + +class AzureENS(ComplianceOutput): + """ + This class represents the Azure ENS compliance output. + + Attributes: + - _data (list): A list to store transformed data from findings. + - _file_descriptor (TextIOWrapper): A file descriptor to write data to a file. + + Methods: + - transform: Transforms findings into AWS ENS compliance format. + """ + + def transform( + self, + findings: list[Finding], + compliance: Compliance, + compliance_name: str, + ) -> None: + """ + Transforms a list of findings into AWS ENS compliance format. + + Parameters: + - findings (list): A list of findings. + - compliance (Compliance): A compliance model. + - compliance_name (str): The name of the compliance model. + + Returns: + - None + """ + for finding in findings: + # Get the compliance requirements for the finding + finding_requirements = finding.compliance.get(compliance_name, []) + for requirement in compliance.Requirements: + if requirement.Id in finding_requirements: + for attribute in requirement.Attributes: + compliance_row = AzureENSModel( + Provider=finding.provider, + Description=compliance.Description, + Subscription=finding.account_name, + Location=finding.region, + AssessmentDate=str(finding.timestamp), + Requirements_Id=requirement.Id, + Requirements_Description=requirement.Description, + Requirements_Attributes_IdGrupoControl=attribute.IdGrupoControl, + Requirements_Attributes_Marco=attribute.Marco, + Requirements_Attributes_Categoria=attribute.Categoria, + Requirements_Attributes_DescripcionControl=attribute.DescripcionControl, + Requirements_Attributes_Nivel=attribute.Nivel, + Requirements_Attributes_Tipo=attribute.Tipo, + Requirements_Attributes_Dimensiones=",".join( + attribute.Dimensiones + ), + Requirements_Attributes_ModoEjecucion=attribute.ModoEjecucion, + Requirements_Attributes_Dependencias=",".join( + attribute.Dependencias + ), + Status=finding.status, + StatusExtended=finding.status_extended, + ResourceId=finding.resource_uid, + ResourceName=finding.resource_name, + CheckId=finding.check_id, + Muted=finding.muted, + ) + self._data.append(compliance_row) + # Add manual requirements to the compliance output + for requirement in compliance.Requirements: + if not requirement.Checks: + for attribute in requirement.Attributes: + compliance_row = AzureENSModel( + Provider=compliance.Provider.lower(), + Description=compliance.Description, + Subscription="", + Location="", + AssessmentDate=str(finding.timestamp), + Requirements_Id=requirement.Id, + Requirements_Description=requirement.Description, + Requirements_Attributes_IdGrupoControl=attribute.IdGrupoControl, + Requirements_Attributes_Marco=attribute.Marco, + Requirements_Attributes_Categoria=attribute.Categoria, + Requirements_Attributes_DescripcionControl=attribute.DescripcionControl, + Requirements_Attributes_Nivel=attribute.Nivel, + Requirements_Attributes_Tipo=attribute.Tipo, + Requirements_Attributes_Dimensiones=",".join( + attribute.Dimensiones + ), + Requirements_Attributes_ModoEjecucion=attribute.ModoEjecucion, + Requirements_Attributes_Dependencias=",".join( + attribute.Dependencias + ), + Status="MANUAL", + StatusExtended="Manual check", + ResourceId="manual_check", + ResourceName="Manual check", + CheckId="manual", + Muted=False, + ) + self._data.append(compliance_row) diff --git a/prowler/lib/outputs/compliance/ens/models.py b/prowler/lib/outputs/compliance/ens/models.py index 0e14f16a28f..9077e2ab570 100644 --- a/prowler/lib/outputs/compliance/ens/models.py +++ b/prowler/lib/outputs/compliance/ens/models.py @@ -28,3 +28,32 @@ class AWSENSModel(BaseModel): CheckId: str Muted: bool ResourceName: str + + +class AzureENSModel(BaseModel): + """ + AzureENSModel generates a finding's output in CSV ENS format for Azure. + """ + + Provider: str + Description: str + Subscription: str + Location: str + AssessmentDate: str + Requirements_Id: str + Requirements_Description: str + Requirements_Attributes_IdGrupoControl: str + Requirements_Attributes_Marco: str + Requirements_Attributes_Categoria: str + Requirements_Attributes_DescripcionControl: str + Requirements_Attributes_Nivel: str + Requirements_Attributes_Tipo: str + Requirements_Attributes_Dimensiones: str + Requirements_Attributes_ModoEjecucion: str + Requirements_Attributes_Dependencias: str + Status: str + StatusExtended: str + ResourceId: str + CheckId: str + Muted: bool + ResourceName: str From 6abf56c074f2ad6c321ac445377e62e4404c3d2b Mon Sep 17 00:00:00 2001 From: pedrooot Date: Fri, 15 Nov 2024 10:30:12 +0100 Subject: [PATCH 02/10] feat(compliance): improve ens for gcp --- .../compliance/azure/ens_rd2022_azure.json | 609 +++++++++++++++++- 1 file changed, 597 insertions(+), 12 deletions(-) diff --git a/prowler/compliance/azure/ens_rd2022_azure.json b/prowler/compliance/azure/ens_rd2022_azure.json index 5fff5ebdf39..946971ba02e 100644 --- a/prowler/compliance/azure/ens_rd2022_azure.json +++ b/prowler/compliance/azure/ens_rd2022_azure.json @@ -27,6 +27,29 @@ "app_ensure_auth_is_set_up" ] }, + { + "Id": "op.acc.1.az.eid.1", + "Description": "Identificación", + "Attributes": [ + { + "IdGrupoControl": "op.acc.1", + "Marco": "operacional", + "Categoria": "control de acceso", + "DescripcionControl": "", + "Nivel": "alto", + "Tipo": "requisito", + "Dimensiones": [ + "trazabilidad", + "autenticidad" + ], + "ModoEjecucion": "automático", + "Dependencias": [] + } + ], + "Checks": [ + "app_register_with_identity" + ] + }, { "Id": "op.acc.1.az.r1.eid.1", "Description": "Identificacion Avanzada", @@ -131,6 +154,32 @@ "iam_custom_role_has_permissions_to_administer_resource_locks" ] }, + { + "Id": "opc.acc.5.az.eid.1", + "Description": "Mecanismo de autenticación (usuarios externos)", + "Attributes": [ + { + "IdGrupoControl": "op.acc.5", + "Marco": "operacional", + "Categoria": "control de acceso", + "DescripcionControl": "El usuario externo deberá contar con un usuario de la organización creado y gestionado para sus actividades de colaboración durante el período de tiempo definido en el contrato, de igual manera que el mecanismo de autenticación (usuarios de la organización) y será gestionado en la organización con Microsoft Entra.", + "Nivel": "alto", + "Tipo": "requisito", + "Dimensiones": [ + "confidencialidad", + "integridad", + "trazabilidad", + "autenticidad" + ], + "ModoEjecucion": "automático", + "Dependencias": [] + } + ], + "Checks": [ + "entra_policy_guest_users_access_restrictions", + "entra_policy_guest_invite_only_for_admin_roles" + ] + }, { "Id": "op.acc.5.r2.az.eid.1", "Description": "Contraseña + OTP", @@ -235,7 +284,7 @@ ] }, { - "Id": "op.acc.6.az.eid1", + "Id": "op.acc.6.az.eid.1", "Description": "Mecanismo de autenticación (usuarios de la organización)", "Attributes": [ { @@ -260,7 +309,7 @@ ] }, { - "Id": "op.acc.6.r1.az.eid1", + "Id": "op.acc.6.r1.az.eid.1", "Description": "Contraseñas", "Attributes": [ { @@ -285,7 +334,7 @@ ] }, { - "Id": "op.acc.6.r1.az.eid2", + "Id": "op.acc.6.r1.az.eid.2", "Description": "Contraseñas", "Attributes": [ { @@ -312,7 +361,7 @@ ] }, { - "Id": "op.acc.6.r1.az.eid3", + "Id": "op.acc.6.r1.az.eid.3", "Description": "Contraseñas", "Attributes": [ { @@ -337,7 +386,7 @@ ] }, { - "Id": "op.acc.6.r2.az.eid1", + "Id": "op.acc.6.r2.az.eid.1", "Description": "Contraseña + otro factor de autenticación", "Attributes": [ { @@ -363,7 +412,7 @@ ] }, { - "Id": "op.acc.6.r3.az.kv1", + "Id": "op.acc.6.r3.az.kv.1", "Description": "Certificados", "Attributes": [ { @@ -390,7 +439,7 @@ ] }, { - "Id": "op.acc.6.r4.az.mfa1", + "Id": "op.acc.6.r4.az.mfa.1", "Description": "Certificados en dispositivo físico", "Attributes": [ { @@ -415,7 +464,7 @@ ] }, { - "Id": "op.acc.6.r5.az.eid1", + "Id": "op.acc.6.r5.az.eid.1", "Description": "Registro de la actividad", "Attributes": [ { @@ -441,7 +490,139 @@ ] }, { - "Id": "op.acc.6.r8.az.eid1", + "Id": "op.acc.6.r5.az.eid.2", + "Description": "Registro de la actividad", + "Attributes": [ + { + "IdGrupoControl": "op.acc.6.r5", + "Marco": "operacional", + "Categoria": "control de acceso", + "DescripcionControl": "El registro de actividad en los servicios de la nube debe de estar habilitado.", + "Nivel": "alto", + "Tipo": "refuerzo", + "Dimensiones": [ + "confidencialidad", + "integridad", + "trazabilidad", + "autenticidad" + ], + "ModoEjecucion": "automático", + "Dependencias": [] + } + ], + "Checks": [ + "monitor_alert_delete_nsg", + "monitor_alert_delete_policy_assignment", + "monitor_alert_delete_public_ip_address_rule", + "monitor_alert_delete_security_solution", + "monitor_alert_delete_sqlserver_fr" + ] + }, + { + "Id": "op.acc.6.r5.az.eid.3", + "Description": "Registro de la actividad", + "Attributes": [ + { + "IdGrupoControl": "op.acc.6.r5", + "Marco": "operacional", + "Categoria": "control de acceso", + "DescripcionControl": "El registro de actividad en los servicios de PostgreSQL debe de estar habilitado.", + "Nivel": "alto", + "Tipo": "refuerzo", + "Dimensiones": [ + "confidencialidad", + "integridad", + "trazabilidad", + "autenticidad" + ], + "ModoEjecucion": "automático", + "Dependencias": [] + } + ], + "Checks": [ + "postgresql_flexible_server_log_connections_on", + "postgresql_flexible_server_log_disconnections_on", + "postgresql_flexible_server_log_checkpoints_on" + ] + }, + { + "Id": "op.acc.6.r5.az.eid.4", + "Description": "Registro de la actividad", + "Attributes": [ + { + "IdGrupoControl": "op.acc.6.r5", + "Marco": "operacional", + "Categoria": "control de acceso", + "DescripcionControl": "El registro de actividad en los servicios de SQL Server debe de estar habilitado.", + "Nivel": "alto", + "Tipo": "refuerzo", + "Dimensiones": [ + "confidencialidad", + "integridad", + "trazabilidad", + "autenticidad" + ], + "ModoEjecucion": "automático", + "Dependencias": [] + } + ], + "Checks": [ + "sqlserver_auditing_enabled" + ] + }, + { + "Id": "op.acc.6.r5.az.eid.5", + "Description": "Registro de la actividad", + "Attributes": [ + { + "IdGrupoControl": "op.acc.6.r5", + "Marco": "operacional", + "Categoria": "control de acceso", + "DescripcionControl": "El registro de actividad en los servicios de MySQL debe de estar habilitado.", + "Nivel": "alto", + "Tipo": "refuerzo", + "Dimensiones": [ + "confidencialidad", + "integridad", + "trazabilidad", + "autenticidad" + ], + "ModoEjecucion": "automático", + "Dependencias": [] + } + ], + "Checks": [ + "mysql_flexible_server_audit_log_connection_activated", + "mysql_flexible_server_audit_log_enabled" + ] + }, + { + "Id": "op.acc.6.r5.az.eid.6", + "Description": "Registro de la actividad", + "Attributes": [ + { + "IdGrupoControl": "op.acc.6.r5", + "Marco": "operacional", + "Categoria": "control de acceso", + "DescripcionControl": "El registro de actividad en los servicios de aplicación debe de estar habilitado.", + "Nivel": "alto", + "Tipo": "refuerzo", + "Dimensiones": [ + "confidencialidad", + "integridad", + "trazabilidad", + "autenticidad" + ], + "ModoEjecucion": "automático", + "Dependencias": [] + } + ], + "Checks": [ + "app_http_logs_enabled" + ] + }, + { + "Id": "op.acc.6.r8.az.eid.1", "Description": "Doble factor para acceso desde o através de zonas no controladas", "Attributes": [ { @@ -467,7 +648,7 @@ ] }, { - "Id": "op.exp.8.az.md1", + "Id": "op.exp.8.az.md.1", "Description": "Registro de la actividad", "Attributes": [ { @@ -490,7 +671,53 @@ ] }, { - "Id": "op.exp.8.r4.az.sa1", + "Id": "op.exp.8.r1.az.sa.1", + "Description": "Revisión de los registros", + "Attributes": [ + { + "IdGrupoControl": "op.exp.8.r1", + "Marco": "operacional", + "Categoria": "explotación", + "DescripcionControl": "Registro de la actividad en las cuentas de almacenamiento", + "Nivel": "alto", + "Tipo": "refuerzo", + "Dimensiones": [ + "trazabilidad" + ], + "ModoEjecucion": "automático", + "Dependencias": [] + } + ], + "Checks": [ + "monitor_storage_account_with_activity_logs_is_private" + ] + }, + { + "Id": "op.exp.8.r3.az.nt.1", + "Description": "Retención de registros", + "Attributes": [ + { + "IdGrupoControl": "[op.exp.8.r3]", + "Marco": "operacional", + "Categoria": "explotación", + "DescripcionControl": "La configuración de los registros debe estar configurada con un período de retención.", + "Nivel": "alto", + "Tipo": "refuerzo", + "Dimensiones": [ + "trazabilidad" + ], + "ModoEjecucion": "automático", + "Dependencias": [] + } + ], + "Checks": [ + "network_flow_log_more_than_90_days", + "sqlserver_auditing_retention_90_days", + "postgresql_flexible_server_log_retention_days_greater_3" + ] + }, + { + "Id": "op.exp.8.r4.az.sa.1", "Description": "Control de acceso", "Attributes": [ { @@ -512,7 +739,7 @@ ] }, { - "Id": "op.exp.8.r4.az.sa2", + "Id": "op.exp.8.r4.az.sa.2", "Description": "Control de acceso", "Attributes": [ { @@ -533,6 +760,77 @@ "storage_default_network_access_rule_is_denied" ] }, + { + "Id": "op.exp.8.r4.az.sa.3", + "Description": "Control de acceso", + "Attributes": [ + { + "IdGrupoControl": "op.exp.8.r4", + "Marco": "operacional", + "Categoria": "explotación", + "DescripcionControl": "Configuración del acceso para servicios de bases de datos.", + "Nivel": "alto", + "Tipo": "refuerzo", + "Dimensiones": [ + "trazabilidad" + ], + "ModoEjecucion": "automático", + "Dependencias": [] + } + ], + "Checks": [ + "postgresql_flexible_server_allow_access_services_disabled" + ] + }, + { + "Id": "op.exp.8.r5.az.ds1", + "Description": "Revisión automática y correlación de eventos", + "Attributes": [ + { + "IdGrupoControl": "op.exp.8.r5", + "Marco": "operacional", + "Categoria": "explotación", + "DescripcionControl": "Activación del monitor de diagnóstico para la revisión automática de eventos.", + "Nivel": "alto", + "Tipo": "refuerzo", + "Dimensiones": [ + "trazabilidad" + ], + "ModoEjecucion": "automático", + "Dependencias": [] + } + ], + "Checks": [ + "monitor_diagnostic_settings_exists" + ] + }, + { + "Id": "op.exp.10.az.kv1", + "Description": "Protección de claves criptográficas", + "Attributes": [ + { + "IdGrupoControl": "op.exp.10 ", + "Marco": "operacional", + "Categoria": "explotación", + "DescripcionControl": "Configuración de KEY Vault, limitando el acceso a administradores.", + "Nivel": "alto", + "Tipo": "requisito", + "Dimensiones": [ + "confidencialidad", + "integridad", + "trazabilidad", + "autenticidad", + "disponibilidad" + ], + "ModoEjecucion": "automático", + "Dependencias": [] + } + ], + "Checks": [ + "keyvault_key_expiration_set_in_non_rbac", + "keyvault_recoverable" + ] + }, { "Id": "op.exp.10.az.kv2", "Description": "Protección de claves criptográficas", @@ -665,6 +963,90 @@ "monitor_diagnostic_setting_with_appropriate_categories" ] }, + { + "Id": "opmon.2.r1.az.ma.1", + "Description": "Efectividad del sistema de incidentes", + "Attributes": [ + { + "IdGrupoControl": "op.mon.2.r1 ", + "Marco": "operacional", + "Categoria": "monitorización del sistema", + "DescripcionControl": "Configurar el monitor de alerta para los cambios en los elementos de seguridad habilitados.", + "Nivel": "alto", + "Tipo": "refuerzo", + "Dimensiones": [ + "confidencialidad", + "integridad", + "trazabilidad", + "autenticidad", + "disponibilidad" + ], + "ModoEjecucion": "automático", + "Dependencias": [] + } + ], + "Checks": [ + "monitor_alert_create_policy_assignment", + "monitor_alert_create_update_nsg", + "monitor_alert_create_update_public_ip_address_rule", + "monitor_alert_create_update_security_solution", + "monitor_alert_create_update_sqlserver_fr" + ] + }, + { + "Id": "op.mon.3.az.nw.1", + "Description": "Vigilancia", + "Attributes": [ + { + "IdGrupoControl": "op.mon.3 ", + "Marco": "operacional", + "Categoria": "monitorización del sistema", + "DescripcionControl": "Habilitar Network Watcher para registrar y mantener la información de seguridad centralizada.", + "Nivel": "alto", + "Tipo": "requisito", + "Dimensiones": [ + "confidencialidad", + "integridad", + "trazabilidad", + "autenticidad", + "disponibilidad" + ], + "ModoEjecucion": "automático", + "Dependencias": [] + } + ], + "Checks": [ + "network_watcher_enabled", + "defender_ensure_notify_alerts_severity_is_high", + "network_public_ip_shodan" + ] + }, + { + "Id": "op.mon.3.r2.az.de.1", + "Description": "Análisis dinámico", + "Attributes": [ + { + "IdGrupoControl": "op.mon.3.r2 ", + "Marco": "operacional", + "Categoria": "monitorización del sistema", + "DescripcionControl": "Activar log analícs de Defender para la detección automática de eventos de seguridad.", + "Nivel": "alto", + "Tipo": "refuerzo", + "Dimensiones": [ + "confidencialidad", + "integridad", + "trazabilidad", + "autenticidad", + "disponibilidad" + ], + "ModoEjecucion": "automático", + "Dependencias": [] + } + ], + "Checks": [ + "defender_auto_provisioning_log_analytics_agent_vms_on" + ] + }, { "Id": "op.mon.3.r3.az.de.1", "Description": "Ciberamenazas avanzadas", @@ -744,6 +1126,33 @@ "defender_ensure_notify_emails_to_owners" ] }, + { + "Id": "op.mon.3.r5.az.1", + "Description": "Minería de datos", + "Attributes": [ + { + "IdGrupoControl": "[op.mon.3.r5] ", + "Marco": "operacional", + "Categoria": "monitorización del sistema", + "DescripcionControl": "Aplicación de medidas para restringir el acceso a datos sin autorización en los servicios de la nuve", + "Nivel": "alto", + "Tipo": "refuerzo", + "Dimensiones": [ + "confidencialidad", + "integridad", + "trazabilidad", + "autenticidad", + "disponibilidad" + ], + "ModoEjecucion": "automático", + "Dependencias": [] + } + ], + "Checks": [ + "sqlserver_unrestricted_inbound_access", + "storage_blob_public_access_level_is_disabled" + ] + }, { "Id": "op.mon.3.r6.az.ma.1", "Description": "Inspecciones de seguridad", @@ -797,6 +1206,33 @@ "network_rdp_internet_access_restricted" ] }, + { + "Id": "mp.com.1.az.nw.2", + "Description": "Perímetro seguro", + "Attributes": [ + { + "IdGrupoControl": "mp.com.1", + "Marco": "medidas de protección", + "Categoria": "protección de las comunicaciones", + "DescripcionControl": "Habilitar la restricción de acceso para el tráfico por internet a través de SSH", + "Nivel": "alto", + "Tipo": "requisito", + "Dimensiones": [ + "confidencialidad", + "integridad", + "trazabilidad", + "autenticidad", + "disponibilidad" + ], + "ModoEjecucion": "automático", + "Dependencias": [] + } + ], + "Checks": [ + "network_watcher_enabled", + "network_ssh_internet_access_restricted" + ] + }, { "Id": "mp.com.1.az.nw.3", "Description": "Perímetro seguro", @@ -824,6 +1260,31 @@ "network_udp_internet_access_restricted" ] }, + { + "Id": "mp.com.3.az.nw.1", + "Description": "Protección de la integridad y de la autenticidad", + "Attributes": [ + { + "IdGrupoControl": "mp.com.3 ", + "Marco": "medidas de protección", + "Categoria": "protección de las comunicaciones", + "DescripcionControl": "Asegurarse de que la comunicación del frontal sea a través de HTTPS.", + "Nivel": "alto", + "Tipo": "requisito", + "Dimensiones": [ + "integridad", + "autenticidad" + ], + "ModoEjecucion": "automático", + "Dependencias": [] + } + ], + "Checks": [ + "network_watcher_enabled", + "defender_ensure_notify_alerts_severity_is_high", + "app_ensure_http_is_redirected_to_https" + ] + }, { "Id": "mp.com.3.az.sa.1", "Description": "Protección de la integridad y de la autenticidad", @@ -917,6 +1378,29 @@ "mysql_flexible_server_minimum_tls_version_12" ] }, + { + "Id": "mp.com.3.r2.az.tls.3", + "Description": "Algoritmos y parámetros autorizados", + "Attributes": [ + { + "IdGrupoControl": "mp.com.3.r2 ", + "Marco": "medidas de protección", + "Categoria": "protección de las comunicaciones", + "DescripcionControl": "La versión de TLS para las cuentas de almacenamiento deben ser como mínimo versión 1.2", + "Nivel": "alto", + "Tipo": "refuerzo", + "Dimensiones": [ + "integridad", + "autenticidad" + ], + "ModoEjecucion": "automático", + "Dependencias": [] + } + ], + "Checks": [ + "storage_ensure_minimum_tls_version_12" + ] + }, { "Id": "mp.com.4.az.nt.1", "Description": "Separación de flujos de información en la red", @@ -1168,6 +1652,107 @@ "Checks": [ "network_flow_log_captured_sent" ] + }, + { + "Id": "mp.s.4.r1.az.nt.2", + "Description": "Detección y reacción", + "Attributes": [ + { + "IdGrupoControl": "mp.s.4.r1", + "Marco": "medidas de protección", + "Categoria": "protección de los servicios", + "DescripcionControl": "Habilitar la supervisión del rendimiento de aplicaciones para los servicios en la nube", + "Nivel": "alto", + "Tipo": "requisito", + "Dimensiones": [ + "disponibilidad" + ], + "ModoEjecucion": "automático", + "Dependencias": [] + } + ], + "Checks": [ + "appinsights_ensure_is_configured", + "app_function_application_insights_enabled" + ] + }, + { + "Id": "mp.s.4.r1.az.nt.3", + "Description": "Detección y reacción", + "Attributes": [ + { + "IdGrupoControl": "mp.s.4.r1", + "Marco": "medidas de protección", + "Categoria": "protección de los servicios", + "DescripcionControl": "Habilitar defender para los servicios de aplicaciones en la nube", + "Nivel": "alto", + "Tipo": "requisito", + "Dimensiones": [ + "disponibilidad" + ], + "ModoEjecucion": "automático", + "Dependencias": [] + } + ], + "Checks": [ + "defender_ensure_defender_for_app_services_is_on", + "defender_ensure_defender_for_arm_is_on", + "defender_ensure_defender_for_containers_is_on", + "defender_ensure_iot_hub_defender_is_on", + "defender_ensure_mcas_is_enabled", + "defender_ensure_defender_for_dns_is_on", + "defender_ensure_defender_for_server_is_on" + ] + }, + { + "Id": "mp.s.4.r1.az.nt.4", + "Description": "Detección y reacción", + "Attributes": [ + { + "IdGrupoControl": "mp.s.4.r1", + "Marco": "medidas de protección", + "Categoria": "protección de los servicios", + "DescripcionControl": "Habilitar defender para los servicios de bases de datos en la nube", + "Nivel": "alto", + "Tipo": "requisito", + "Dimensiones": [ + "disponibilidad" + ], + "ModoEjecucion": "automático", + "Dependencias": [] + } + ], + "Checks": [ + "defender_ensure_defender_for_azure_sql_databases_is_on", + "defender_ensure_defender_for_cosmosdb_is_on", + "defender_ensure_defender_for_databases_is_on", + "defender_ensure_defender_for_os_relational_databases_is_on", + "defender_ensure_defender_for_sql_servers_is_on", + "sqlserver_microsoft_defender_enabled" + ] + }, + { + "Id": "mp.s.4.r1.az.nt.5", + "Description": "Detección y reacción", + "Attributes": [ + { + "IdGrupoControl": "mp.s.4.r1", + "Marco": "medidas de protección", + "Categoria": "protección de los servicios", + "DescripcionControl": "Habilitar defender para los servicios de almacenamiento en la nube", + "Nivel": "alto", + "Tipo": "requisito", + "Dimensiones": [ + "disponibilidad" + ], + "ModoEjecucion": "automático", + "Dependencias": [] + } + ], + "Checks": [ + "defender_ensure_defender_for_storage_is_on", + "defender_auto_provisioning_log_analytics_agent_vms_on" + ] } ] } From 7807840fb9e079c907ea2f134956e348b319b037 Mon Sep 17 00:00:00 2001 From: pedrooot Date: Fri, 15 Nov 2024 10:31:48 +0100 Subject: [PATCH 03/10] feat(compliance): add ens for gcp --- prowler/compliance/gcp/ens_rd2022_gcp.json | 706 +++++++++++++++++++++ 1 file changed, 706 insertions(+) create mode 100644 prowler/compliance/gcp/ens_rd2022_gcp.json diff --git a/prowler/compliance/gcp/ens_rd2022_gcp.json b/prowler/compliance/gcp/ens_rd2022_gcp.json new file mode 100644 index 00000000000..84969cd3025 --- /dev/null +++ b/prowler/compliance/gcp/ens_rd2022_gcp.json @@ -0,0 +1,706 @@ +{ + "Framework": "ENS", + "Version": "RD2022", + "Provider": "GCP", + "Description": "The accreditation scheme of the ENS (National Security Scheme) has been developed by the Ministry of Finance and Public Administrations and the CCN (National Cryptological Center). This includes the basic principles and minimum requirements necessary for the adequate protection of information.", + "Requirements": [ + { + "Id": "op.acc.1.gcp.iam.1", + "Description": "Identificación", + "Attributes": [ + { + "IdGrupoControl": "op.acc.1", + "Marco": "operacional", + "Categoria": "control de acceso", + "DescripcionControl": "Utilizar las credenciales de acceso de la organización en lugar de las cuentas personales, como las de Gmail.", + "Nivel": "alto", + "Tipo": "requisito", + "Dimensiones": [ + "trazabilidad", + "autenticidad" + ], + "ModoEjecucion": "automático", + "Dependencias": [] + } + ], + "Checks": [ + "iam_organization_essential_contacts_configured" + ] + }, + { + "Id": "op.acc.1.r1.gcp.iam.1", + "Description": "Identificacion Avanzada", + "Attributes": [ + { + "IdGrupoControl": "op.acc.1.r1", + "Marco": "operacional", + "Categoria": "control de acceso", + "DescripcionControl": "El usuario deberá ser identificado de manera singular asociada a una persona en particular permitiendo al responsable del sistema, al responsable de la seguirdad o a los administradores determinar sus responsabilidades dentro del sistema con GCP Cloud Identity", + "Nivel": "alto", + "Tipo": "refuerzo", + "Dimensiones": [ + "trazabilidad", + "autenticidad" + ], + "ModoEjecucion": "automático", + "Dependencias": [] + } + ], + "Checks": [ + "iam_no_service_roles_at_project_level", + "apikeys_api_restrictions_configured" + ] + }, + { + "Id": "opc.acc.1.r1.gcp.iam.2", + "Description": "", + "Attributes": [ + { + "IdGrupoControl": "", + "Marco": "operacional", + "Categoria": "control de acceso", + "DescripcionControl": "El administrador del sistema será el responsable de mantener la lista de usuarios autorizados a través de los distintos tipos de cuentas que gestiona GCP.", + "Nivel": "alto", + "Tipo": "refuerzo", + "Dimensiones": [ + "trazabilidad", + "autenticidad" + ], + "ModoEjecucion": "automático", + "Dependencias": [] + } + ], + "Checks": [ + "logging_log_metric_filter_and_alert_for_custom_role_changes_enabled", + "logging_log_metric_filter_and_alert_for_project_ownership_changes_enabled", + "iam_audit_logs_enabled" + ] + }, + { + "Id": "op.acc.2.gcp.rbak.1", + "Description": "Requisitos de acceso", + "Attributes": [ + { + "IdGrupoControl": "op.acc.2", + "Marco": "operacional", + "Categoria": "control de acceso", + "DescripcionControl": "El acceso a los recursos del sistema se progerá utilizando un mecanismo que impida su utilización a través del uso de políticas administradas por el responsible del sistema o el responsible de la seguridad.", + "Nivel": "alto", + "Tipo": "requisito", + "Dimensiones": [ + "confidencialidad", + "integridad", + "trazabilidad", + "autenticidad" + ], + "ModoEjecucion": "automático", + "Dependencias": [] + } + ], + "Checks": [ + "apikeys_key_exists", + "iam_sa_no_user_managed_keys" + ] + }, + { + "Id": "opc.acc.2.gcp.iap.1", + "Description": "Privilegios de acceso", + "Attributes": [ + { + "IdGrupoControl": "op.acc.2.r1", + "Marco": "operacional", + "Categoria": "control de acceso", + "DescripcionControl": "Identity-Aware Proxy (IAP, permite definir un conjunto de atributos de seguridad que puedan ser gestionados por separado, restringiendo el tipo de acceso que cada usuario deba tener.", + "Nivel": "alto", + "Tipo": "refuerzo", + "Dimensiones": [ + "confidencialidad", + "integridad", + "trazabilidad", + "autenticidad" + ], + "ModoEjecucion": "automático", + "Dependencias": [] + } + ], + "Checks": [ + "iam_organization_essential_contacts_configured" + ] + }, + { + "Id": "op.acc.3.gcp.org.1", + "Description": "Segregación de funciones y tareas", + "Attributes": [ + { + "IdGrupoControl": "op.acc.3", + "Marco": "operacional", + "Categoria": "control de acceso", + "DescripcionControl": "Se deberá aplicar el principio de separación de obligaciones al asignar funciones relacionadas con las cuentas de servicio a los usuarios. La separación de obligaciones es el concepto de asegurar que un individuo no tenga todos los permisos necesarios para poder completar una acción maliciosa. En GCP IAM podría ser una acción como el uso de una cuenta de servicio para acceder a recursos a los que el usuario no debería tener acceso normalmente.", + "Nivel": "alto", + "Tipo": "requisito", + "Dimensiones": [ + "confidencialidad", + "integridad", + "trazabilidad", + "autenticidad" + ], + "ModoEjecucion": "automático", + "Dependencias": [] + } + ], + "Checks": [ + "iam_role_sa_enforce_separation_of_duties", + "iam_role_kms_enforce_separation_of_duties" + ] + }, + { + "Id": "op.acc.3.gcp.iam.1", + "Description": "Cuentas de servicio", + "Attributes": [ + { + "IdGrupoControl": "", + "Marco": "operacional", + "Categoria": "control de acceso", + "DescripcionControl": "Las cuentas de servicio no pueden tener privilegios de administrador. GCP IAM.", + "Nivel": "alto", + "Tipo": "requisito", + "Dimensiones": [ + "confidencialidad", + "integridad", + "trazabilidad", + "autenticidad" + ], + "ModoEjecucion": "automático", + "Dependencias": [] + } + ], + "Checks": [ + "iam_sa_no_user_managed_keys", + "iam_sa_no_administrative_privileges", + "compute_instance_default_service_account_in_use" + ] + }, + { + "Id": "op.acc.3.r1.gcp.iam.1", + "Description": "Segregación rigurosa", + "Attributes": [ + { + "IdGrupoControl": "op.acc.3.r1", + "Marco": "operacional", + "Categoria": "control de acceso", + "DescripcionControl": "Las actividades de configuración, mantenimiento, auditoría o supervisión, no debe ser realizada por la misma persona, para lo cual se deberá configurar un rol específico para cada función y gestionarlo con GCP IAM.", + "Nivel": "alto", + "Tipo": "refuerzo", + "Dimensiones": [ + "confidencialidad", + "integridad", + "trazabilidad", + "autenticidad" + ], + "ModoEjecucion": "automático", + "Dependencias": [] + } + ], + "Checks": [ + "logging_log_metric_filter_and_alert_for_project_ownership_changes_enabled" + ] + }, + { + "Id": "opc.acc.4.gcp.iam.1", + "Description": "Proceso de gestión de derechos de acceso", + "Attributes": [ + { + "IdGrupoControl": "op.acc.4", + "Marco": "operacional", + "Categoria": "control de acceso", + "DescripcionControl": "La limitación del acceso a los usuarios será aplicando los principios del mínimo privilegio, negando de forma predeterminada, el acceso al sistema para el usuario en GCP IAM.", + "Nivel": "alto", + "Tipo": "requisito", + "Dimensiones": [ + "confidencialidad", + "integridad", + "trazabilidad", + "autenticidad" + ], + "ModoEjecucion": "automático", + "Dependencias": [] + } + ], + "Checks": [ + "iam_sa_no_administrative_privileges", + "gke_cluster_no_default_service_account" + ] + }, + { + "Id": "op.acc.6.gcp.ip.1", + "Description": "Mecanismo de autenticación (usuarios de la organización)", + "Attributes": [ + { + "IdGrupoControl": "op.acc.6", + "Marco": "operacional", + "Categoria": "control de acceso", + "DescripcionControl": "El control de acceso será gestionado desde Identity Platform para administrar las identidades y acceso.", + "Nivel": "alto", + "Tipo": "requisito", + "Dimensiones": [ + "confidencialidad", + "integridad", + "trazabilidad", + "autenticidad" + ], + "ModoEjecucion": "automático", + "Dependencias": [] + } + ], + "Checks": [ + "iam_account_access_approval_enabled" + ] + }, + { + "Id": "op.acc.6.r1.gcp.ip.1", + "Description": "Contraseñas", + "Attributes": [ + { + "IdGrupoControl": "op.acc.6.r1", + "Marco": "operacional", + "Categoria": "control de acceso", + "DescripcionControl": "El uso de políticas de contraseñas debe ser aplicado según lo defina la organización.", + "Nivel": "alto", + "Tipo": "refuerzo", + "Dimensiones": [ + "confidencialidad", + "integridad", + "trazabilidad", + "autenticidad" + ], + "ModoEjecucion": "automático", + "Dependencias": [] + } + ], + "Checks": [ + "apikeys_key_rotated_in_90_days", + "kms_key_rotation_enabled", + "iam_sa_user_managed_key_rotate_90_days" + ] + }, + { + "Id": "op.acc.6.r5.gcp.cl.1", + "Description": "Registro de la actividad", + "Attributes": [ + { + "IdGrupoControl": "op.acc.6.r5", + "Marco": "operacional", + "Categoria": "control de acceso", + "DescripcionControl": "Es necesario registrar la actividad de acceso tanto exitoso como fallido de los usuarios.", + "Nivel": "alto", + "Tipo": "refuerzo", + "Dimensiones": [ + "confidencialidad", + "integridad", + "trazabilidad", + "autenticidad" + ], + "ModoEjecucion": "automático", + "Dependencias": [] + } + ], + "Checks": [ + "iam_audit_logs_enabled" + ] + }, + { + "Id": "", + "Description": "Acceso remoto", + "Attributes": [ + { + "IdGrupoControl": "op.acc.6.r9", + "Marco": "operacional", + "Categoria": "control de acceso", + "DescripcionControl": "Se debe de considerar la autorización por la autoridad correspondiente, siendo el tráfico cifrado, recogiendo los registros de auditoría.", + "Nivel": "alto", + "Tipo": "refuerzo", + "Dimensiones": [ + "confidencialidad", + "integridad", + "trazabilidad", + "autenticidad" + ], + "ModoEjecucion": "automático", + "Dependencias": [] + } + ], + "Checks": [ + "apikeys_api_restrictions_configured", + "iam_audit_logs_enabled" + ] + }, + { + "Id": "op.exp.1.gcp.cai.1", + "Description": "Inventario de activos", + "Attributes": [ + { + "IdGrupoControl": "op.exp.1", + "Marco": "operacional", + "Categoria": "explotación", + "DescripcionControl": "Se requiere mantener la identificación de recursos y servicios de todos los elementos del sistema teniendo la capacidad para evaluar el cumplimiento normativo del ENS en GCP y conociendo las propiedades del recurso.", + "Nivel": "alto", + "Tipo": "requisito", + "Dimensiones": [ + "confidencialidad", + "integridad", + "trazabilidad", + "autenticidad", + "disponibilidad" + ], + "ModoEjecucion": "automático", + "Dependencias": [] + } + ], + "Checks": [ + "iam_cloud_asset_inventory_enabled" + ] + }, + { + "Id": "op.exp.1.r2.gcp.cai.1", + "Description": "Identificación periódica de activos", + "Attributes": [ + { + "IdGrupoControl": "op.exp.1.r2", + "Marco": "operacional", + "Categoria": "explotación", + "DescripcionControl": "Permitir visualizar de forma contínua el estado de todos los activos del sistema.Cloud Asset Inventory proporciona una base de datos con un histórico de los recursos de GCP.", + "Nivel": "alto", + "Tipo": "recomendación", + "Dimensiones": [ + "confidencialidad", + "integridad", + "trazabilidad", + "autenticidad", + "disponibilidad" + ], + "ModoEjecucion": "automático", + "Dependencias": [] + } + ], + "Checks": [ + "logging_log_metric_filter_and_alert_for_audit_configuration_changes_enabled", + "logging_log_metric_filter_and_alert_for_bucket_permission_changes_enabled" + ] + }, + { + "Id": "", + "Description": "Monitorización contínua", + "Attributes": [ + { + "IdGrupoControl": "op.exp.4.r4", + "Marco": "operacional", + "Categoria": "explotación", + "DescripcionControl": "", + "Nivel": "alto", + "Tipo": "refuerzo", + "Dimensiones": [ + "confidencialidad", + "integridad", + "trazabilidad", + "autenticidad", + "disponibilidad" + ], + "ModoEjecucion": "automático", + "Dependencias": [] + } + ], + "Checks": [ + "logging_log_metric_filter_and_alert_for_audit_configuration_changes_enabled", + "artifacts_container_analysis_enabled" + ] + }, + { + "Id": "op.exp.8.gcp.nt.1", + "Description": "Registro de la actividad", + "Attributes": [ + { + "IdGrupoControl": "op.exp.8", + "Marco": "operacional", + "Categoria": "explotación", + "DescripcionControl": "Configuración de las reglas de actividad de red para registrar los cambios ", + "Nivel": "alto", + "Tipo": "requisito", + "Dimensiones": [ + "trazabilidad" + ], + "ModoEjecucion": "automático", + "Dependencias": [] + } + ], + "Checks": [ + "logging_log_metric_filter_and_alert_for_vpc_firewall_rule_changes_enabled", + "logging_log_metric_filter_and_alert_for_vpc_network_changes_enabled", + "logging_log_metric_filter_and_alert_for_vpc_network_route_changes_enabled", + "compute_network_dns_logging_enabled" + ] + }, + { + "Id": "op.exp.8.r1.gcp.nt.1", + "Description": "Revisión de los registros", + "Attributes": [ + { + "IdGrupoControl": "op.exp.8.r1", + "Marco": "operacional", + "Categoria": "explotación", + "DescripcionControl": "Configuración de las reglas de actividad de red para registrar los cambios y alertar sobre posibles situaciones extraordinarias", + "Nivel": "alto", + "Tipo": "refuerzo", + "Dimensiones": [ + "trazabilidad" + ], + "ModoEjecucion": "automático", + "Dependencias": [] + } + ], + "Checks": [ + "logging_log_metric_filter_and_alert_for_vpc_firewall_rule_changes_enabled", + "logging_log_metric_filter_and_alert_for_vpc_network_changes_enabled", + "logging_log_metric_filter_and_alert_for_vpc_network_route_changes_enabled" + ] + }, + { + "Id": "op.exp.8.r3.gcp.cs.1", + "Description": "Retención de registros", + "Attributes": [ + { + "IdGrupoControl": "op.exp.8.r3", + "Marco": "operacional", + "Categoria": "explotación", + "DescripcionControl": "La configuración de los registros debe estar configurada con un período de retención.", + "Nivel": "alto", + "Tipo": "refuerzo", + "Dimensiones": [ + "trazabilidad" + ], + "ModoEjecucion": "automático", + "Dependencias": [] + } + ], + "Checks": [ + "cloudstorage_bucket_log_retention_policy_lock" + ] + }, + { + "Id": "op.exp.8.r5.gcp.cl.1", + "Description": "Revisión automática y correlación de evnetos", + "Attributes": [ + { + "IdGrupoControl": "op.exp.8.r5", + "Marco": "operacional", + "Categoria": "explotación", + "DescripcionControl": "Habilitar log sink para el correcto registro de logging para administrarlos para cada receptor de manera automática", + "Nivel": "alto", + "Tipo": "refuerzo", + "Dimensiones": [ + "trazabilidad" + ], + "ModoEjecucion": "automático", + "Dependencias": [] + } + ], + "Checks": [ + "logging_sink_created" + ] + }, + { + "Id": "op.exp.10.gcp.kms.1", + "Description": "Protección de claves criptográficas", + "Attributes": [ + { + "IdGrupoControl": "op.exp.10 ", + "Marco": "operacional", + "Categoria": "explotación", + "DescripcionControl": "Las claves criptográficas no deben estar expuestas, deben ser protegidas por el administrador.", + "Nivel": "alto", + "Tipo": "requisito", + "Dimensiones": [ + "confidencialidad", + "integridad", + "trazabilidad", + "autenticidad", + "disponibilidad" + ], + "ModoEjecucion": "automático", + "Dependencias": [] + } + ], + "Checks": [ + "kms_key_not_publicly_accessible" + ] + }, + { + "Id": "op.mon.1.gcp.sc.1", + "Description": "Detección de intrusión", + "Attributes": [ + { + "IdGrupoControl": "op.mon.1 ", + "Marco": "operacional", + "Categoria": "monitorización del sistema", + "DescripcionControl": "Habilitación del contenedor GCR para el registro de repositorios Docker", + "Nivel": "alto", + "Tipo": "requisito", + "Dimensiones": [ + "confidencialidad", + "integridad", + "trazabilidad", + "autenticidad", + "disponibilidad" + ], + "ModoEjecucion": "automático", + "Dependencias": [] + } + ], + "Checks": [ + "gcr_container_scanning_enabled" + ] + }, + { + "Id": "op.mon.3.gcp.sc.1", + "Description": "Vigilancia", + "Attributes": [ + { + "IdGrupoControl": "op.mon.3 ", + "Marco": "operacional", + "Categoria": "monitorización del sistema", + "DescripcionControl": "Se deberá habilitar la verificación de vulnerabilidades para los servicios de GCP", + "Nivel": "alto", + "Tipo": "requisito", + "Dimensiones": [ + "confidencialidad", + "integridad", + "trazabilidad", + "autenticidad", + "disponibilidad" + ], + "ModoEjecucion": "automático", + "Dependencias": [] + } + ], + "Checks": [ + "gcr_container_scanning_enabled", + "artifacts_container_analysis_enabled" + ] + }, + { + "Id": "mp.com.2.gcp.lb.1", + "Description": "Protección de la confidencialidad", + "Attributes": [ + { + "IdGrupoControl": "mp.com.2 ", + "Marco": "medidas de protección", + "Categoria": "protección de las comunicaciones", + "DescripcionControl": "Se deberá asegurar que los balanceadores de carga HTTPS o SSL no permiten políticas poco seguras.", + "Nivel": "alto", + "Tipo": "requisito", + "Dimensiones": [ + "confidencialidad" + ], + "ModoEjecucion": "automático", + "Dependencias": [] + } + ], + "Checks": [ + "compute_loadbalancer_logging_enabled" + ] + }, + { + "Id": "mp.com.4.gcp.vpc.1", + "Description": "Separación de flujos de información en la red", + "Attributes": [ + { + "IdGrupoControl": "mp.com.4", + "Marco": "medidas de protección", + "Categoria": "protección de las comunicaciones", + "DescripcionControl": "Se deberá eliminar la red por defecto del proyecto (default).", + "Nivel": "alto", + "Tipo": "requisito", + "Dimensiones": [ + "confidencialidad", + "integridad", + "trazabilidad", + "autenticidad", + "disponibilidad" + ], + "ModoEjecucion": "automático", + "Dependencias": [] + } + ], + "Checks": [ + "compute_network_default_in_use" + ] + }, + { + "Id": "mp.info.3.r1.gcp.crt.1", + "Description": "Certificados cualificados", + "Attributes": [ + { + "IdGrupoControl": "mp.info.3.r1", + "Marco": "medidas de protección", + "Categoria": "protección de la información", + "DescripcionControl": "Habilitar el funcionamiento adecuado de los certificados para los recursos.", + "Nivel": "alto", + "Tipo": "refuerzo", + "Dimensiones": [ + "integridad", + "autenticidad" + ], + "ModoEjecucion": "automático", + "Dependencias": [] + } + ], + "Checks": [ + "dns_rsasha1_in_use_to_key_sign_in_dnssec", + "dns_rsasha1_in_use_to_zone_sign_in_dnssec" + ] + }, + { + "Id": "mp.info.6.gcp.bk.1", + "Description": "Copias de seguridad", + "Attributes": [ + { + "IdGrupoControl": "mp.info.6", + "Marco": "medidas de protección", + "Categoria": "protección de la información", + "DescripcionControl": "Se debe configurar las copias de seguridad de los recursos de almacenamiento de GCP", + "Nivel": "alto", + "Tipo": "requisito", + "Dimensiones": [ + "disponibilidad" + ], + "ModoEjecucion": "automático", + "Dependencias": [] + } + ], + "Checks": [ + "cloudsql_instance_automated_backups" + ] + }, + { + "Id": "mp.info.6.r2.gcp.bk.1", + "Description": "Protección de las copias de seguridad", + "Attributes": [ + { + "IdGrupoControl": "mp.info.6.r2", + "Marco": "medidas de protección", + "Categoria": "protección de la información", + "DescripcionControl": "Se debe configurar las copias de seguridad de los recursos de almacenamiento de GCP", + "Nivel": "alto", + "Tipo": "refuerzo", + "Dimensiones": [ + "disponibilidad" + ], + "ModoEjecucion": "automático", + "Dependencias": [] + } + ], + "Checks": [ + "cloudsql_instance_automated_backups" + ] + } + ] +} From 4001e5687d1d3a2dc83957f38310dba39cb910ce Mon Sep 17 00:00:00 2001 From: pedrooot Date: Fri, 15 Nov 2024 10:40:24 +0100 Subject: [PATCH 04/10] feat(compliance): add ensgcp model and fix typos for azure --- .../lib/outputs/compliance/cis/cis_azure.py | 4 +- prowler/lib/outputs/compliance/cis/models.py | 2 +- .../lib/outputs/compliance/ens/ens_azure.py | 6 +- prowler/lib/outputs/compliance/ens/ens_gcp.py | 103 ++++++++++++++++++ prowler/lib/outputs/compliance/ens/models.py | 31 +++++- 5 files changed, 139 insertions(+), 7 deletions(-) create mode 100644 prowler/lib/outputs/compliance/ens/ens_gcp.py diff --git a/prowler/lib/outputs/compliance/cis/cis_azure.py b/prowler/lib/outputs/compliance/cis/cis_azure.py index d101773a9d3..9ebe7fddaf9 100644 --- a/prowler/lib/outputs/compliance/cis/cis_azure.py +++ b/prowler/lib/outputs/compliance/cis/cis_azure.py @@ -42,7 +42,7 @@ def transform( compliance_row = AzureCISModel( Provider=finding.provider, Description=compliance.Description, - Subscription=finding.account_name, + SubscriptionId=finding.account_uid, Location=finding.region, AssessmentDate=str(finding.timestamp), Requirements_Id=requirement.Id, @@ -73,7 +73,7 @@ def transform( compliance_row = AzureCISModel( Provider=compliance.Provider.lower(), Description=compliance.Description, - Subscription="", + SubscriptionId="", Location="", AssessmentDate=str(finding.timestamp), Requirements_Id=requirement.Id, diff --git a/prowler/lib/outputs/compliance/cis/models.py b/prowler/lib/outputs/compliance/cis/models.py index 00862360238..d8e1889d529 100644 --- a/prowler/lib/outputs/compliance/cis/models.py +++ b/prowler/lib/outputs/compliance/cis/models.py @@ -38,7 +38,7 @@ class AzureCISModel(BaseModel): Provider: str Description: str - Subscription: str + SubscriptionId: str Location: str AssessmentDate: str Requirements_Id: str diff --git a/prowler/lib/outputs/compliance/ens/ens_azure.py b/prowler/lib/outputs/compliance/ens/ens_azure.py index 5858ee44510..53992ef03a7 100644 --- a/prowler/lib/outputs/compliance/ens/ens_azure.py +++ b/prowler/lib/outputs/compliance/ens/ens_azure.py @@ -13,7 +13,7 @@ class AzureENS(ComplianceOutput): - _file_descriptor (TextIOWrapper): A file descriptor to write data to a file. Methods: - - transform: Transforms findings into AWS ENS compliance format. + - transform: Transforms findings into Azure ENS compliance format. """ def transform( @@ -42,7 +42,7 @@ def transform( compliance_row = AzureENSModel( Provider=finding.provider, Description=compliance.Description, - Subscription=finding.account_name, + SubscriptionId=finding.account_name, Location=finding.region, AssessmentDate=str(finding.timestamp), Requirements_Id=requirement.Id, @@ -75,7 +75,7 @@ def transform( compliance_row = AzureENSModel( Provider=compliance.Provider.lower(), Description=compliance.Description, - Subscription="", + SubscriptionId="", Location="", AssessmentDate=str(finding.timestamp), Requirements_Id=requirement.Id, diff --git a/prowler/lib/outputs/compliance/ens/ens_gcp.py b/prowler/lib/outputs/compliance/ens/ens_gcp.py new file mode 100644 index 00000000000..7c719436ac3 --- /dev/null +++ b/prowler/lib/outputs/compliance/ens/ens_gcp.py @@ -0,0 +1,103 @@ +from prowler.lib.check.compliance_models import Compliance +from prowler.lib.outputs.compliance.compliance_output import ComplianceOutput +from prowler.lib.outputs.compliance.ens.models import GCPENSModel +from prowler.lib.outputs.finding import Finding + + +class GCPENS(ComplianceOutput): + """ + This class represents the GCP ENS compliance output. + + Attributes: + - _data (list): A list to store transformed data from findings. + - _file_descriptor (TextIOWrapper): A file descriptor to write data to a file. + + Methods: + - transform: Transforms findings into GCP ENS compliance format. + """ + + def transform( + self, + findings: list[Finding], + compliance: Compliance, + compliance_name: str, + ) -> None: + """ + Transforms a list of findings into AWS ENS compliance format. + + Parameters: + - findings (list): A list of findings. + - compliance (Compliance): A compliance model. + - compliance_name (str): The name of the compliance model. + + Returns: + - None + """ + for finding in findings: + # Get the compliance requirements for the finding + finding_requirements = finding.compliance.get(compliance_name, []) + for requirement in compliance.Requirements: + if requirement.Id in finding_requirements: + for attribute in requirement.Attributes: + compliance_row = GCPENSModel( + Provider=finding.provider, + Description=compliance.Description, + ProjectId=finding.account_uid, + Location=finding.region, + AssessmentDate=str(finding.timestamp), + Requirements_Id=requirement.Id, + Requirements_Description=requirement.Description, + Requirements_Attributes_IdGrupoControl=attribute.IdGrupoControl, + Requirements_Attributes_Marco=attribute.Marco, + Requirements_Attributes_Categoria=attribute.Categoria, + Requirements_Attributes_DescripcionControl=attribute.DescripcionControl, + Requirements_Attributes_Nivel=attribute.Nivel, + Requirements_Attributes_Tipo=attribute.Tipo, + Requirements_Attributes_Dimensiones=",".join( + attribute.Dimensiones + ), + Requirements_Attributes_ModoEjecucion=attribute.ModoEjecucion, + Requirements_Attributes_Dependencias=",".join( + attribute.Dependencias + ), + Status=finding.status, + StatusExtended=finding.status_extended, + ResourceId=finding.resource_uid, + ResourceName=finding.resource_name, + CheckId=finding.check_id, + Muted=finding.muted, + ) + self._data.append(compliance_row) + # Add manual requirements to the compliance output + for requirement in compliance.Requirements: + if not requirement.Checks: + for attribute in requirement.Attributes: + compliance_row = GCPENSModel( + Provider=compliance.Provider.lower(), + Description=compliance.Description, + ProjectId="", + Location="", + AssessmentDate=str(finding.timestamp), + Requirements_Id=requirement.Id, + Requirements_Description=requirement.Description, + Requirements_Attributes_IdGrupoControl=attribute.IdGrupoControl, + Requirements_Attributes_Marco=attribute.Marco, + Requirements_Attributes_Categoria=attribute.Categoria, + Requirements_Attributes_DescripcionControl=attribute.DescripcionControl, + Requirements_Attributes_Nivel=attribute.Nivel, + Requirements_Attributes_Tipo=attribute.Tipo, + Requirements_Attributes_Dimensiones=",".join( + attribute.Dimensiones + ), + Requirements_Attributes_ModoEjecucion=attribute.ModoEjecucion, + Requirements_Attributes_Dependencias=",".join( + attribute.Dependencias + ), + Status="MANUAL", + StatusExtended="Manual check", + ResourceId="manual_check", + ResourceName="Manual check", + CheckId="manual", + Muted=False, + ) + self._data.append(compliance_row) diff --git a/prowler/lib/outputs/compliance/ens/models.py b/prowler/lib/outputs/compliance/ens/models.py index 9077e2ab570..6ff2b9e52f5 100644 --- a/prowler/lib/outputs/compliance/ens/models.py +++ b/prowler/lib/outputs/compliance/ens/models.py @@ -37,7 +37,36 @@ class AzureENSModel(BaseModel): Provider: str Description: str - Subscription: str + SubscriptionId: str + Location: str + AssessmentDate: str + Requirements_Id: str + Requirements_Description: str + Requirements_Attributes_IdGrupoControl: str + Requirements_Attributes_Marco: str + Requirements_Attributes_Categoria: str + Requirements_Attributes_DescripcionControl: str + Requirements_Attributes_Nivel: str + Requirements_Attributes_Tipo: str + Requirements_Attributes_Dimensiones: str + Requirements_Attributes_ModoEjecucion: str + Requirements_Attributes_Dependencias: str + Status: str + StatusExtended: str + ResourceId: str + CheckId: str + Muted: bool + ResourceName: str + + +class GCPENSModel(BaseModel): + """ + GCPENSModel generates a finding's output in CSV ENS format for GCP. + """ + + Provider: str + Description: str + ProjectId: str Location: str AssessmentDate: str Requirements_Id: str From 8b68b55d86483ac17d7a68554166c1f34a7c5d63 Mon Sep 17 00:00:00 2001 From: pedrooot Date: Fri, 15 Nov 2024 10:52:52 +0100 Subject: [PATCH 05/10] feat(compliance): remove changes from fix --- prowler/lib/outputs/compliance/cis/cis_azure.py | 4 ++-- prowler/lib/outputs/compliance/cis/models.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/prowler/lib/outputs/compliance/cis/cis_azure.py b/prowler/lib/outputs/compliance/cis/cis_azure.py index 9ebe7fddaf9..d101773a9d3 100644 --- a/prowler/lib/outputs/compliance/cis/cis_azure.py +++ b/prowler/lib/outputs/compliance/cis/cis_azure.py @@ -42,7 +42,7 @@ def transform( compliance_row = AzureCISModel( Provider=finding.provider, Description=compliance.Description, - SubscriptionId=finding.account_uid, + Subscription=finding.account_name, Location=finding.region, AssessmentDate=str(finding.timestamp), Requirements_Id=requirement.Id, @@ -73,7 +73,7 @@ def transform( compliance_row = AzureCISModel( Provider=compliance.Provider.lower(), Description=compliance.Description, - SubscriptionId="", + Subscription="", Location="", AssessmentDate=str(finding.timestamp), Requirements_Id=requirement.Id, diff --git a/prowler/lib/outputs/compliance/cis/models.py b/prowler/lib/outputs/compliance/cis/models.py index d8e1889d529..00862360238 100644 --- a/prowler/lib/outputs/compliance/cis/models.py +++ b/prowler/lib/outputs/compliance/cis/models.py @@ -38,7 +38,7 @@ class AzureCISModel(BaseModel): Provider: str Description: str - SubscriptionId: str + Subscription: str Location: str AssessmentDate: str Requirements_Id: str From 51c37039fedd235a312b4bc19a8f30eb72e00647 Mon Sep 17 00:00:00 2001 From: pedrooot Date: Fri, 15 Nov 2024 12:28:53 +0100 Subject: [PATCH 06/10] feat(compliance): fix typos on ens json and add changes to main --- prowler/__main__.py | 15 +++++++++++++++ prowler/compliance/gcp/ens_rd2022_gcp.json | 22 +++++++++++----------- 2 files changed, 26 insertions(+), 11 deletions(-) diff --git a/prowler/__main__.py b/prowler/__main__.py index 70608f1dc18..d3ba23db6be 100644 --- a/prowler/__main__.py +++ b/prowler/__main__.py @@ -54,6 +54,7 @@ from prowler.lib.outputs.compliance.compliance import display_compliance_table from prowler.lib.outputs.compliance.ens.ens_aws import AWSENS from prowler.lib.outputs.compliance.ens.ens_azure import AzureENS +from prowler.lib.outputs.compliance.ens.ens_gcp import GCPENS from prowler.lib.outputs.compliance.generic.generic import GenericCompliance from prowler.lib.outputs.compliance.iso27001.iso27001_aws import AWSISO27001 from prowler.lib.outputs.compliance.kisa_ismsp.kisa_ismsp_aws import AWSKISAISMSP @@ -570,6 +571,20 @@ def prowler(): ) generated_outputs["compliance"].append(mitre_attack) mitre_attack.batch_write_data_to_file() + elif compliance_name.startswith("ens_"): + # Generate ENS Finding Object + filename = ( + f"{output_options.output_directory}/compliance/" + f"{output_options.output_filename}_{compliance_name}.csv" + ) + ens = GCPENS( + findings=finding_outputs, + compliance=bulk_compliance_frameworks[compliance_name], + create_file_descriptor=True, + file_path=filename, + ) + generated_outputs["compliance"].append(ens) + ens.batch_write_data_to_file() else: filename = ( f"{output_options.output_directory}/compliance/" diff --git a/prowler/compliance/gcp/ens_rd2022_gcp.json b/prowler/compliance/gcp/ens_rd2022_gcp.json index 84969cd3025..b4ab9da113c 100644 --- a/prowler/compliance/gcp/ens_rd2022_gcp.json +++ b/prowler/compliance/gcp/ens_rd2022_gcp.json @@ -56,7 +56,7 @@ "Description": "", "Attributes": [ { - "IdGrupoControl": "", + "IdGrupoControl": "opc.acc.1.r1", "Marco": "operacional", "Categoria": "control de acceso", "DescripcionControl": "El administrador del sistema será el responsable de mantener la lista de usuarios autorizados a través de los distintos tipos de cuentas que gestiona GCP.", @@ -158,7 +158,7 @@ "Description": "Cuentas de servicio", "Attributes": [ { - "IdGrupoControl": "", + "IdGrupoControl": "op.acc.3", "Marco": "operacional", "Categoria": "control de acceso", "DescripcionControl": "Las cuentas de servicio no pueden tener privilegios de administrador. GCP IAM.", @@ -309,7 +309,7 @@ ] }, { - "Id": "", + "Id": "op.acc.6.r9.gcp.ar.1", "Description": "Acceso remoto", "Attributes": [ { @@ -370,7 +370,7 @@ "Categoria": "explotación", "DescripcionControl": "Permitir visualizar de forma contínua el estado de todos los activos del sistema.Cloud Asset Inventory proporciona una base de datos con un histórico de los recursos de GCP.", "Nivel": "alto", - "Tipo": "recomendación", + "Tipo": "recomendacion", "Dimensiones": [ "confidencialidad", "integridad", @@ -388,14 +388,14 @@ ] }, { - "Id": "", + "Id": "op.exp.4.gcp.mc.1", "Description": "Monitorización contínua", "Attributes": [ { "IdGrupoControl": "op.exp.4.r4", "Marco": "operacional", "Categoria": "explotación", - "DescripcionControl": "", + "DescripcionControl": "Desplegar a nivel de sistema una estrategia de monitorización continua de amenazas y vulnerabilidades detallando: indicadores críticos de seguridad, política de aplicación de parches y criterios de revisión regular y excepcional de amenazas del sistema.", "Nivel": "alto", "Tipo": "refuerzo", "Dimensiones": [ @@ -422,7 +422,7 @@ "IdGrupoControl": "op.exp.8", "Marco": "operacional", "Categoria": "explotación", - "DescripcionControl": "Configuración de las reglas de actividad de red para registrar los cambios ", + "DescripcionControl": "Configuración de las reglas de actividad de red para registrar los cambios", "Nivel": "alto", "Tipo": "requisito", "Dimensiones": [ @@ -512,7 +512,7 @@ "Description": "Protección de claves criptográficas", "Attributes": [ { - "IdGrupoControl": "op.exp.10 ", + "IdGrupoControl": "op.exp.10", "Marco": "operacional", "Categoria": "explotación", "DescripcionControl": "Las claves criptográficas no deben estar expuestas, deben ser protegidas por el administrador.", @@ -538,7 +538,7 @@ "Description": "Detección de intrusión", "Attributes": [ { - "IdGrupoControl": "op.mon.1 ", + "IdGrupoControl": "op.mon.1", "Marco": "operacional", "Categoria": "monitorización del sistema", "DescripcionControl": "Habilitación del contenedor GCR para el registro de repositorios Docker", @@ -564,7 +564,7 @@ "Description": "Vigilancia", "Attributes": [ { - "IdGrupoControl": "op.mon.3 ", + "IdGrupoControl": "op.mon.3", "Marco": "operacional", "Categoria": "monitorización del sistema", "DescripcionControl": "Se deberá habilitar la verificación de vulnerabilidades para los servicios de GCP", @@ -591,7 +591,7 @@ "Description": "Protección de la confidencialidad", "Attributes": [ { - "IdGrupoControl": "mp.com.2 ", + "IdGrupoControl": "mp.com.2", "Marco": "medidas de protección", "Categoria": "protección de las comunicaciones", "DescripcionControl": "Se deberá asegurar que los balanceadores de carga HTTPS o SSL no permiten políticas poco seguras.", From e0c6b6b701173bf0af3885a25a1266a93c4ffc31 Mon Sep 17 00:00:00 2001 From: pedrooot Date: Fri, 15 Nov 2024 12:42:37 +0100 Subject: [PATCH 07/10] feat(compliance): add tests for azure ens --- .../outputs/compliance/ens/ens_azure_test.py | 140 ++++++++++++++++++ tests/lib/outputs/compliance/fixtures.py | 49 +++++- 2 files changed, 188 insertions(+), 1 deletion(-) create mode 100644 tests/lib/outputs/compliance/ens/ens_azure_test.py diff --git a/tests/lib/outputs/compliance/ens/ens_azure_test.py b/tests/lib/outputs/compliance/ens/ens_azure_test.py new file mode 100644 index 00000000000..1ea4e00e60d --- /dev/null +++ b/tests/lib/outputs/compliance/ens/ens_azure_test.py @@ -0,0 +1,140 @@ +from datetime import datetime +from io import StringIO + +from freezegun import freeze_time +from mock import patch + +from prowler.lib.outputs.compliance.ens.ens_azure import AzureENS +from prowler.lib.outputs.compliance.ens.models import AzureENSModel +from tests.lib.outputs.compliance.fixtures import ENS_RD2022_AZURE +from tests.lib.outputs.fixtures.fixtures import generate_finding_output + + +class TestAzureENS: + def test_output_transform(self): + findings = [ + generate_finding_output( + compliance={"ENS-RD2022": "op.exp.8.azure.ct.3"}, + provider="azure", + region="global", + ), + ] + + output = AzureENS(findings, ENS_RD2022_AZURE) + output_data = output.data[0] + assert isinstance(output_data, AzureENSModel) + assert output_data.Provider == "azure" + assert output_data.SubscriptionId == "123456789012" + assert output_data.Location == "global" + assert output_data.Description == ENS_RD2022_AZURE.Description + assert output_data.Requirements_Id == ENS_RD2022_AZURE.Requirements[0].Id + assert ( + output_data.Requirements_Description + == ENS_RD2022_AZURE.Requirements[0].Description + ) + assert ( + output_data.Requirements_Attributes_IdGrupoControl + == ENS_RD2022_AZURE.Requirements[0].Attributes[0].IdGrupoControl + ) + assert ( + output_data.Requirements_Attributes_Marco + == ENS_RD2022_AZURE.Requirements[0].Attributes[0].Marco + ) + assert ( + output_data.Requirements_Attributes_Categoria + == ENS_RD2022_AZURE.Requirements[0].Attributes[0].Categoria + ) + assert ( + output_data.Requirements_Attributes_DescripcionControl + == ENS_RD2022_AZURE.Requirements[0].Attributes[0].DescripcionControl + ) + assert ( + output_data.Requirements_Attributes_Nivel + == ENS_RD2022_AZURE.Requirements[0].Attributes[0].Nivel + ) + assert ( + output_data.Requirements_Attributes_Tipo + == ENS_RD2022_AZURE.Requirements[0].Attributes[0].Tipo + ) + assert [ + output_data.Requirements_Attributes_Dimensiones + ] == ENS_RD2022_AZURE.Requirements[0].Attributes[0].Dimensiones + assert ( + output_data.Requirements_Attributes_ModoEjecucion + == ENS_RD2022_AZURE.Requirements[0].Attributes[0].ModoEjecucion + ) + assert output_data.Requirements_Attributes_Dependencias == "" + assert output_data.Status == "PASS" + assert output_data.StatusExtended == "" + assert output_data.ResourceId == "" + assert output_data.ResourceName == "" + assert output_data.CheckId == "test-check-id" + assert output_data.Muted is False + # Test manual check + output_data_manual = output.data[1] + assert output_data_manual.Provider == "azure" + assert output_data_manual.SubscriptionId == "" + assert output_data_manual.Location == "" + assert output_data_manual.Requirements_Id == ENS_RD2022_AZURE.Requirements[1].Id + assert ( + output_data_manual.Requirements_Description + == ENS_RD2022_AZURE.Requirements[1].Description + ) + assert ( + output_data_manual.Requirements_Attributes_IdGrupoControl + == ENS_RD2022_AZURE.Requirements[1].Attributes[0].IdGrupoControl + ) + assert ( + output_data_manual.Requirements_Attributes_Marco + == ENS_RD2022_AZURE.Requirements[1].Attributes[0].Marco + ) + assert ( + output_data_manual.Requirements_Attributes_Categoria + == ENS_RD2022_AZURE.Requirements[1].Attributes[0].Categoria + ) + assert ( + output_data_manual.Requirements_Attributes_DescripcionControl + == ENS_RD2022_AZURE.Requirements[1].Attributes[0].DescripcionControl + ) + assert ( + output_data_manual.Requirements_Attributes_Nivel + == ENS_RD2022_AZURE.Requirements[1].Attributes[0].Nivel + ) + assert ( + output_data_manual.Requirements_Attributes_Tipo + == ENS_RD2022_AZURE.Requirements[1].Attributes[0].Tipo + ) + assert [ + output_data_manual.Requirements_Attributes_Dimensiones + ] == ENS_RD2022_AZURE.Requirements[1].Attributes[0].Dimensiones + assert ( + output_data_manual.Requirements_Attributes_ModoEjecucion + == ENS_RD2022_AZURE.Requirements[1].Attributes[0].ModoEjecucion + ) + assert output_data_manual.Status == "MANUAL" + assert output_data_manual.StatusExtended == "Manual check" + assert output_data_manual.ResourceId == "manual_check" + assert output_data_manual.ResourceName == "Manual check" + assert output_data_manual.CheckId == "manual" + assert output_data_manual.Muted is False + + @freeze_time(datetime.now()) + def test_batch_write_data_to_file(self): + mock_file = StringIO() + findings = [ + generate_finding_output( + compliance={"ENS-RD2022": "op.exp.8.azure.ct.3"}, + provider="azure", + region="global", + ), + ] + output = AzureENS(findings, ENS_RD2022_AZURE) + output._file_descriptor = mock_file + + with patch.object(mock_file, "close", return_value=None): + output.batch_write_data_to_file() + + mock_file.seek(0) + content = mock_file.read() + expected_csv = f"PROVIDER;DESCRIPTION;SUBSCRIPTIONID;LOCATION;ASSESSMENTDATE;REQUIREMENTS_ID;REQUIREMENTS_DESCRIPTION;REQUIREMENTS_ATTRIBUTES_IDGRUPOCONTROL;REQUIREMENTS_ATTRIBUTES_MARCO;REQUIREMENTS_ATTRIBUTES_CATEGORIA;REQUIREMENTS_ATTRIBUTES_DESCRIPCIONCONTROL;REQUIREMENTS_ATTRIBUTES_NIVEL;REQUIREMENTS_ATTRIBUTES_TIPO;REQUIREMENTS_ATTRIBUTES_DIMENSIONES;REQUIREMENTS_ATTRIBUTES_MODOEJECUCION;REQUIREMENTS_ATTRIBUTES_DEPENDENCIAS;STATUS;STATUSEXTENDED;RESOURCEID;CHECKID;MUTED;RESOURCENAME\r\nazure;The accreditation scheme of the ENS (National Security Scheme) has been developed by the Ministry of Finance and Public Administrations and the CCN (National Cryptological Center). This includes the basic principles and minimum requirements necessary for the adequate protection of information.;123456789012;global;{datetime.now()};op.exp.8.azure.ct.3;Registro de actividad;op.exp.8;operacional;explotación;Habilitar la validación de archivos en todos los trails, evitando así que estos se vean modificados o eliminados.;alto;requisito;trazabilidad;automático;;PASS;;;test-check-id;False;\r\nazure;The accreditation scheme of the ENS (National Security Scheme) has been developed by the Ministry of Finance and Public Administrations and the CCN (National Cryptological Center). This includes the basic principles and minimum requirements necessary for the adequate protection of information.;;;{datetime.now()};op.exp.8.azure.ct.4;Registro de actividad;op.exp.8;operacional;explotación;Habilitar la validación de archivos en todos los trails, evitando así que estos se vean modificados o eliminados.;alto;requisito;trazabilidad;automático;;MANUAL;Manual check;manual_check;manual;False;Manual check\r\n" + assert content == expected_csv diff --git a/tests/lib/outputs/compliance/fixtures.py b/tests/lib/outputs/compliance/fixtures.py index 7b1d069c1e7..3f93dc2d8ac 100644 --- a/tests/lib/outputs/compliance/fixtures.py +++ b/tests/lib/outputs/compliance/fixtures.py @@ -8,11 +8,11 @@ ENS_Requirement_Attribute_Tipos, Generic_Compliance_Requirement_Attribute, ISO27001_2013_Requirement_Attribute, + KISA_ISMSP_Requirement_Attribute, Mitre_Requirement, Mitre_Requirement_Attribute_AWS, Mitre_Requirement_Attribute_Azure, Mitre_Requirement_Attribute_GCP, - KISA_ISMSP_Requirement_Attribute, ) CIS_1_4_AWS_NAME = "cis_1.4_aws" @@ -469,6 +469,53 @@ ), ], ) +ENS_RD2022_AZURE_NAME = "ens_rd2022_azure" +ENS_RD2022_AZURE = Compliance( + Framework="ENS", + Provider="Azure", + Version="RD2022", + Description="The accreditation scheme of the ENS (National Security Scheme) has been developed by the Ministry of Finance and Public Administrations and the CCN (National Cryptological Center). This includes the basic principles and minimum requirements necessary for the adequate protection of information.", + Requirements=[ + Compliance_Requirement( + Id="op.exp.8.azure.ct.3", + Description="Registro de actividad", + Name=None, + Attributes=[ + ENS_Requirement_Attribute( + IdGrupoControl="op.exp.8", + Marco="operacional", + Categoria="explotación", + DescripcionControl="Habilitar la validación de archivos en todos los trails, evitando así que estos se vean modificados o eliminados.", + Tipo=ENS_Requirement_Attribute_Tipos.requisito, + Nivel=ENS_Requirement_Attribute_Nivel.alto, + Dimensiones=["trazabilidad"], + ModoEjecucion="automático", + Dependencias=[], + ) + ], + Checks=["cloudtrail_log_file_validation_enabled"], + ), + Compliance_Requirement( + Id="op.exp.8.azure.ct.4", + Description="Registro de actividad", + Name=None, + Attributes=[ + ENS_Requirement_Attribute( + IdGrupoControl="op.exp.8", + Marco="operacional", + Categoria="explotación", + DescripcionControl="Habilitar la validación de archivos en todos los trails, evitando así que estos se vean modificados o eliminados.", + Tipo=ENS_Requirement_Attribute_Tipos.requisito, + Nivel=ENS_Requirement_Attribute_Nivel.alto, + Dimensiones=["trazabilidad"], + ModoEjecucion="automático", + Dependencias=[], + ) + ], + Checks=[], + ), + ], +) NOT_PRESENT_COMPLIANCE_NAME = "not_present_compliance_name" NOT_PRESENT_COMPLIANCE = Compliance( Framework="NOT_EXISTENT", From ae666fa62bfb0b88a3bea25106c2a29c7be01f2b Mon Sep 17 00:00:00 2001 From: pedrooot Date: Fri, 15 Nov 2024 12:48:48 +0100 Subject: [PATCH 08/10] feat(compliance): add tests for gcp ens --- .../outputs/compliance/ens/ens_gcp_test.py | 140 ++++++++++++++++++ tests/lib/outputs/compliance/fixtures.py | 47 ++++++ 2 files changed, 187 insertions(+) create mode 100644 tests/lib/outputs/compliance/ens/ens_gcp_test.py diff --git a/tests/lib/outputs/compliance/ens/ens_gcp_test.py b/tests/lib/outputs/compliance/ens/ens_gcp_test.py new file mode 100644 index 00000000000..a2b92efb2c1 --- /dev/null +++ b/tests/lib/outputs/compliance/ens/ens_gcp_test.py @@ -0,0 +1,140 @@ +from datetime import datetime +from io import StringIO + +from freezegun import freeze_time +from mock import patch + +from prowler.lib.outputs.compliance.ens.ens_gcp import GCPENS +from prowler.lib.outputs.compliance.ens.models import GCPENSModel +from tests.lib.outputs.compliance.fixtures import ENS_RD2022_GCP +from tests.lib.outputs.fixtures.fixtures import generate_finding_output + + +class TestGCPENS: + def test_output_transform(self): + findings = [ + generate_finding_output( + compliance={"ENS-RD2022": "op.exp.8.gcp.ct.3"}, + provider="gcp", + region="global", + ), + ] + + output = GCPENS(findings, ENS_RD2022_GCP) + output_data = output.data[0] + assert isinstance(output_data, GCPENSModel) + assert output_data.Provider == "gcp" + assert output_data.ProjectId == "123456789012" + assert output_data.Location == "global" + assert output_data.Description == ENS_RD2022_GCP.Description + assert output_data.Requirements_Id == ENS_RD2022_GCP.Requirements[0].Id + assert ( + output_data.Requirements_Description + == ENS_RD2022_GCP.Requirements[0].Description + ) + assert ( + output_data.Requirements_Attributes_IdGrupoControl + == ENS_RD2022_GCP.Requirements[0].Attributes[0].IdGrupoControl + ) + assert ( + output_data.Requirements_Attributes_Marco + == ENS_RD2022_GCP.Requirements[0].Attributes[0].Marco + ) + assert ( + output_data.Requirements_Attributes_Categoria + == ENS_RD2022_GCP.Requirements[0].Attributes[0].Categoria + ) + assert ( + output_data.Requirements_Attributes_DescripcionControl + == ENS_RD2022_GCP.Requirements[0].Attributes[0].DescripcionControl + ) + assert ( + output_data.Requirements_Attributes_Nivel + == ENS_RD2022_GCP.Requirements[0].Attributes[0].Nivel + ) + assert ( + output_data.Requirements_Attributes_Tipo + == ENS_RD2022_GCP.Requirements[0].Attributes[0].Tipo + ) + assert [ + output_data.Requirements_Attributes_Dimensiones + ] == ENS_RD2022_GCP.Requirements[0].Attributes[0].Dimensiones + assert ( + output_data.Requirements_Attributes_ModoEjecucion + == ENS_RD2022_GCP.Requirements[0].Attributes[0].ModoEjecucion + ) + assert output_data.Requirements_Attributes_Dependencias == "" + assert output_data.Status == "PASS" + assert output_data.StatusExtended == "" + assert output_data.ResourceId == "" + assert output_data.ResourceName == "" + assert output_data.CheckId == "test-check-id" + assert output_data.Muted is False + # Test manual check + output_data_manual = output.data[1] + assert output_data_manual.Provider == "gcp" + assert output_data_manual.ProjectId == "" + assert output_data_manual.Location == "" + assert output_data_manual.Requirements_Id == ENS_RD2022_GCP.Requirements[1].Id + assert ( + output_data_manual.Requirements_Description + == ENS_RD2022_GCP.Requirements[1].Description + ) + assert ( + output_data_manual.Requirements_Attributes_IdGrupoControl + == ENS_RD2022_GCP.Requirements[1].Attributes[0].IdGrupoControl + ) + assert ( + output_data_manual.Requirements_Attributes_Marco + == ENS_RD2022_GCP.Requirements[1].Attributes[0].Marco + ) + assert ( + output_data_manual.Requirements_Attributes_Categoria + == ENS_RD2022_GCP.Requirements[1].Attributes[0].Categoria + ) + assert ( + output_data_manual.Requirements_Attributes_DescripcionControl + == ENS_RD2022_GCP.Requirements[1].Attributes[0].DescripcionControl + ) + assert ( + output_data_manual.Requirements_Attributes_Nivel + == ENS_RD2022_GCP.Requirements[1].Attributes[0].Nivel + ) + assert ( + output_data_manual.Requirements_Attributes_Tipo + == ENS_RD2022_GCP.Requirements[1].Attributes[0].Tipo + ) + assert [ + output_data_manual.Requirements_Attributes_Dimensiones + ] == ENS_RD2022_GCP.Requirements[1].Attributes[0].Dimensiones + assert ( + output_data_manual.Requirements_Attributes_ModoEjecucion + == ENS_RD2022_GCP.Requirements[1].Attributes[0].ModoEjecucion + ) + assert output_data_manual.Status == "MANUAL" + assert output_data_manual.StatusExtended == "Manual check" + assert output_data_manual.ResourceId == "manual_check" + assert output_data_manual.ResourceName == "Manual check" + assert output_data_manual.CheckId == "manual" + assert output_data_manual.Muted is False + + @freeze_time(datetime.now()) + def test_batch_write_data_to_file(self): + mock_file = StringIO() + findings = [ + generate_finding_output( + compliance={"ENS-RD2022": "op.exp.8.gcp.ct.3"}, + provider="gcp", + region="global", + ), + ] + output = GCPENS(findings, ENS_RD2022_GCP) + output._file_descriptor = mock_file + + with patch.object(mock_file, "close", return_value=None): + output.batch_write_data_to_file() + + mock_file.seek(0) + content = mock_file.read() + expected_csv = f"PROVIDER;DESCRIPTION;PROJECTID;LOCATION;ASSESSMENTDATE;REQUIREMENTS_ID;REQUIREMENTS_DESCRIPTION;REQUIREMENTS_ATTRIBUTES_IDGRUPOCONTROL;REQUIREMENTS_ATTRIBUTES_MARCO;REQUIREMENTS_ATTRIBUTES_CATEGORIA;REQUIREMENTS_ATTRIBUTES_DESCRIPCIONCONTROL;REQUIREMENTS_ATTRIBUTES_NIVEL;REQUIREMENTS_ATTRIBUTES_TIPO;REQUIREMENTS_ATTRIBUTES_DIMENSIONES;REQUIREMENTS_ATTRIBUTES_MODOEJECUCION;REQUIREMENTS_ATTRIBUTES_DEPENDENCIAS;STATUS;STATUSEXTENDED;RESOURCEID;CHECKID;MUTED;RESOURCENAME\r\ngcp;The accreditation scheme of the ENS (National Security Scheme) has been developed by the Ministry of Finance and Public Administrations and the CCN (National Cryptological Center). This includes the basic principles and minimum requirements necessary for the adequate protection of information.;123456789012;global;{datetime.now()};op.exp.8.gcp.ct.3;Registro de actividad;op.exp.8;operacional;explotación;Habilitar la validación de archivos en todos los trails, evitando así que estos se vean modificados o eliminados.;alto;requisito;trazabilidad;automático;;PASS;;;test-check-id;False;\r\ngcp;The accreditation scheme of the ENS (National Security Scheme) has been developed by the Ministry of Finance and Public Administrations and the CCN (National Cryptological Center). This includes the basic principles and minimum requirements necessary for the adequate protection of information.;;;{datetime.now()};op.exp.8.gcp.ct.4;Registro de actividad;op.exp.8;operacional;explotación;Habilitar la validación de archivos en todos los trails, evitando así que estos se vean modificados o eliminados.;alto;requisito;trazabilidad;automático;;MANUAL;Manual check;manual_check;manual;False;Manual check\r\n" + assert content == expected_csv diff --git a/tests/lib/outputs/compliance/fixtures.py b/tests/lib/outputs/compliance/fixtures.py index 3f93dc2d8ac..8b35860c334 100644 --- a/tests/lib/outputs/compliance/fixtures.py +++ b/tests/lib/outputs/compliance/fixtures.py @@ -516,6 +516,53 @@ ), ], ) +ENS_RD2022_GCP_NAME = "ens_rd2022_gcp" +ENS_RD2022_GCP = Compliance( + Framework="ENS", + Provider="GCP", + Version="RD2022", + Description="The accreditation scheme of the ENS (National Security Scheme) has been developed by the Ministry of Finance and Public Administrations and the CCN (National Cryptological Center). This includes the basic principles and minimum requirements necessary for the adequate protection of information.", + Requirements=[ + Compliance_Requirement( + Id="op.exp.8.gcp.ct.3", + Description="Registro de actividad", + Name=None, + Attributes=[ + ENS_Requirement_Attribute( + IdGrupoControl="op.exp.8", + Marco="operacional", + Categoria="explotación", + DescripcionControl="Habilitar la validación de archivos en todos los trails, evitando así que estos se vean modificados o eliminados.", + Tipo=ENS_Requirement_Attribute_Tipos.requisito, + Nivel=ENS_Requirement_Attribute_Nivel.alto, + Dimensiones=["trazabilidad"], + ModoEjecucion="automático", + Dependencias=[], + ) + ], + Checks=["cloudtrail_log_file_validation_enabled"], + ), + Compliance_Requirement( + Id="op.exp.8.gcp.ct.4", + Description="Registro de actividad", + Name=None, + Attributes=[ + ENS_Requirement_Attribute( + IdGrupoControl="op.exp.8", + Marco="operacional", + Categoria="explotación", + DescripcionControl="Habilitar la validación de archivos en todos los trails, evitando así que estos se vean modificados o eliminados.", + Tipo=ENS_Requirement_Attribute_Tipos.requisito, + Nivel=ENS_Requirement_Attribute_Nivel.alto, + Dimensiones=["trazabilidad"], + ModoEjecucion="automático", + Dependencias=[], + ) + ], + Checks=[], + ), + ], +) NOT_PRESENT_COMPLIANCE_NAME = "not_present_compliance_name" NOT_PRESENT_COMPLIANCE = Compliance( Framework="NOT_EXISTENT", From c78458c4e20fe9d1ed147e7acffa1530a28cd10c Mon Sep 17 00:00:00 2001 From: pedrooot Date: Fri, 15 Nov 2024 12:50:28 +0100 Subject: [PATCH 09/10] docs: update readme with compliance numbers --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 99396fec467..3f1ed03f660 100644 --- a/README.md +++ b/README.md @@ -64,8 +64,8 @@ It contains hundreds of controls covering CIS, NIST 800, NIST CSF, CISA, RBI, Fe | Provider | Checks | Services | [Compliance Frameworks](https://docs.prowler.com/projects/prowler-open-source/en/latest/tutorials/compliance/) | [Categories](https://docs.prowler.com/projects/prowler-open-source/en/latest/tutorials/misc/#categories) | |---|---|---|---|---| | AWS | 553 | 77 -> `prowler aws --list-services` | 30 -> `prowler aws --list-compliance` | 9 -> `prowler aws --list-categories` | -| GCP | 77 | 13 -> `prowler gcp --list-services` | 2 -> `prowler gcp --list-compliance` | 2 -> `prowler gcp --list-categories`| -| Azure | 138 | 17 -> `prowler azure --list-services` | 3 -> `prowler azure --list-compliance` | 2 -> `prowler azure --list-categories` | +| GCP | 77 | 13 -> `prowler gcp --list-services` | 3 -> `prowler gcp --list-compliance` | 2 -> `prowler gcp --list-categories`| +| Azure | 138 | 17 -> `prowler azure --list-services` | 4 -> `prowler azure --list-compliance` | 2 -> `prowler azure --list-categories` | | Kubernetes | 83 | 7 -> `prowler kubernetes --list-services` | 1 -> `prowler kubernetes --list-compliance` | 7 -> `prowler kubernetes --list-categories` | # 💻 Installation From fef6fc0dc78565d413ab311129455f6b10800ba6 Mon Sep 17 00:00:00 2001 From: pedrooot Date: Fri, 15 Nov 2024 13:30:32 +0100 Subject: [PATCH 10/10] feat(compliance): fix tests --- tests/lib/cli/parser_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/lib/cli/parser_test.py b/tests/lib/cli/parser_test.py index ce5d770e338..3f92ca2d57c 100644 --- a/tests/lib/cli/parser_test.py +++ b/tests/lib/cli/parser_test.py @@ -654,7 +654,7 @@ def test_checks_parser_wrong_severity(self, capsys): def test_checks_parser_wrong_compliance(self): argument = "--compliance" - framework = "ens_rd2022_azure" + framework = "ens_rd2022_kubernetes" command = [prowler_command, argument, framework] with pytest.raises(SystemExit) as wrapped_exit: _ = self.parser.parse(command)