From a8edd03e651600ade3edcb304b5aa8dcac8f5108 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20De=20la=20Torre=20Vico?= Date: Mon, 29 Jan 2024 11:02:49 +0100 Subject: [PATCH] feat(azure): Add check `defender_auto_provisioning_log_analytics_agent_vms_on` (#3322) Co-authored-by: Pepe Fagoaga --- .../__init__.py | 0 ...g_log_analytics_agent_vms_on.metadata.json | 30 ++++ ...provisioning_log_analytics_agent_vms_on.py | 29 ++++ .../services/defender/defender_service.py | 34 ++++- ...sioning_log_analytics_agent_vms_on_test.py | 142 ++++++++++++++++++ 5 files changed, 234 insertions(+), 1 deletion(-) create mode 100644 prowler/providers/azure/services/defender/defender_auto_provisioning_log_analytics_agent_vms_on/__init__.py create mode 100644 prowler/providers/azure/services/defender/defender_auto_provisioning_log_analytics_agent_vms_on/defender_auto_provisioning_log_analytics_agent_vms_on.metadata.json create mode 100644 prowler/providers/azure/services/defender/defender_auto_provisioning_log_analytics_agent_vms_on/defender_auto_provisioning_log_analytics_agent_vms_on.py create mode 100644 tests/providers/azure/services/defender/defender_auto_provisioning_log_analytics_agent_vms_on/defender_auto_provisioning_log_analytics_agent_vms_on_test.py diff --git a/prowler/providers/azure/services/defender/defender_auto_provisioning_log_analytics_agent_vms_on/__init__.py b/prowler/providers/azure/services/defender/defender_auto_provisioning_log_analytics_agent_vms_on/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/prowler/providers/azure/services/defender/defender_auto_provisioning_log_analytics_agent_vms_on/defender_auto_provisioning_log_analytics_agent_vms_on.metadata.json b/prowler/providers/azure/services/defender/defender_auto_provisioning_log_analytics_agent_vms_on/defender_auto_provisioning_log_analytics_agent_vms_on.metadata.json new file mode 100644 index 00000000..ec571bf4 --- /dev/null +++ b/prowler/providers/azure/services/defender/defender_auto_provisioning_log_analytics_agent_vms_on/defender_auto_provisioning_log_analytics_agent_vms_on.metadata.json @@ -0,0 +1,30 @@ +{ + "Provider": "azure", + "CheckID": "defender_auto_provisioning_log_analytics_agent_vms_on", + "CheckTitle": "Ensure that Auto provisioning of 'Log Analytics agent for Azure VMs' is Set to 'On'", + "CheckType": [], + "ServiceName": "defender", + "SubServiceName": "", + "ResourceIdTemplate": "", + "Severity": "medium", + "ResourceType": "AzureDefenderPlan", + "Description": "Ensure that Auto provisioning of 'Log Analytics agent for Azure VMs' is Set to 'On'. The Microsoft Monitoring Agent scans for various security-related configurations and events such as system updates, OS vulnerabilities, endpoint protection, and provides alerts.", + "Risk": "Missing critical security information about your Azure VMs, such as security alerts, security recommendations, and change tracking.", + "RelatedUrl": "https://docs.microsoft.com/en-us/azure/security-center/security-center-data-security", + "Remediation": { + "Code": { + "CLI": "", + "NativeIaC": "", + "Other": "https://www.trendmicro.com/cloudoneconformity-staging/knowledge-base/azure/SecurityCenter/automatic-provisioning-of-monitoring-agent.html", + "Terraform": "" + }, + "Recommendation": { + "Text": "Ensure comprehensive visibility into possible security vulnerabilities, including missing updates, misconfigured operating system security settings, and active threats, allowing for timely mitigation and improved overall security posture", + "Url": "https://learn.microsoft.com/en-us/azure/defender-for-cloud/monitoring-components" + } + }, + "Categories": [], + "DependsOn": [], + "RelatedTo": [], + "Notes": "" +} diff --git a/prowler/providers/azure/services/defender/defender_auto_provisioning_log_analytics_agent_vms_on/defender_auto_provisioning_log_analytics_agent_vms_on.py b/prowler/providers/azure/services/defender/defender_auto_provisioning_log_analytics_agent_vms_on/defender_auto_provisioning_log_analytics_agent_vms_on.py new file mode 100644 index 00000000..ff14bd51 --- /dev/null +++ b/prowler/providers/azure/services/defender/defender_auto_provisioning_log_analytics_agent_vms_on/defender_auto_provisioning_log_analytics_agent_vms_on.py @@ -0,0 +1,29 @@ +from prowler.lib.check.models import Check, Check_Report_Azure +from prowler.providers.azure.services.defender.defender_client import defender_client + + +class defender_auto_provisioning_log_analytics_agent_vms_on(Check): + def execute(self) -> Check_Report_Azure: + findings = [] + + for ( + subscription_name, + auto_provisioning_settings, + ) in defender_client.auto_provisioning_settings.items(): + + for auto_provisioning_setting in auto_provisioning_settings.values(): + + report = Check_Report_Azure(self.metadata()) + report.status = "PASS" + report.subscription = subscription_name + report.resource_name = auto_provisioning_setting.resource_name + report.resource_id = auto_provisioning_setting.resource_id + report.status_extended = f"Defender Auto Provisioning Log Analytics Agents from subscription {subscription_name} is set to ON." + + if auto_provisioning_setting.auto_provision != "On": + report.status = "FAIL" + report.status_extended = f"Defender Auto Provisioning Log Analytics Agents from subscription {subscription_name} is set to OFF." + + findings.append(report) + + return findings diff --git a/prowler/providers/azure/services/defender/defender_service.py b/prowler/providers/azure/services/defender/defender_service.py index d234c8c0..6f9f9bd5 100644 --- a/prowler/providers/azure/services/defender/defender_service.py +++ b/prowler/providers/azure/services/defender/defender_service.py @@ -13,6 +13,7 @@ class Defender(AzureService): super().__init__(SecurityCenter, audit_info) self.pricings = self.__get_pricings__() + self.auto_provisioning_settings = self.__get_auto_provisioning_settings__() def __get_pricings__(self): logger.info("Defender - Getting pricings...") @@ -31,15 +32,46 @@ class Defender(AzureService): ) } ) + except Exception as error: + logger.error( + f"Subscription name: {subscription} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}" + ) + return pricings + + def __get_auto_provisioning_settings__(self): + logger.info("Defender - Getting auto provisioning settings...") + auto_provisioning = {} + for subscription, client in self.clients.items(): + try: + auto_provisioning_settings = client.auto_provisioning_settings.list() + auto_provisioning.update({subscription: {}}) + for ap in auto_provisioning_settings: + auto_provisioning[subscription].update( + { + ap.name: AutoProvisioningSetting( + resource_id=ap.id, + resource_name=ap.name, + resource_type=ap.type, + auto_provision=ap.auto_provision, + ) + } + ) except Exception as error: logger.error(f"Subscription name: {subscription}") logger.error( f"{error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}" ) - return pricings + return auto_provisioning class Defender_Pricing(BaseModel): resource_id: str pricing_tier: str free_trial_remaining_time: timedelta + + +class AutoProvisioningSetting(BaseModel): + resource_id: str + resource_name: str + resource_type: str + auto_provision: str diff --git a/tests/providers/azure/services/defender/defender_auto_provisioning_log_analytics_agent_vms_on/defender_auto_provisioning_log_analytics_agent_vms_on_test.py b/tests/providers/azure/services/defender/defender_auto_provisioning_log_analytics_agent_vms_on/defender_auto_provisioning_log_analytics_agent_vms_on_test.py new file mode 100644 index 00000000..772520e5 --- /dev/null +++ b/tests/providers/azure/services/defender/defender_auto_provisioning_log_analytics_agent_vms_on/defender_auto_provisioning_log_analytics_agent_vms_on_test.py @@ -0,0 +1,142 @@ +from unittest import mock +from uuid import uuid4 + +from prowler.providers.azure.services.defender.defender_service import ( + AutoProvisioningSetting, +) +from tests.providers.azure.azure_fixtures import AZURE_SUSCRIPTION + + +class Test_defender_auto_provisioning_log_analytics_agent_vms_on: + def test_defender_no_app_services(self): + defender_client = mock.MagicMock + defender_client.auto_provisioning_settings = {} + + with mock.patch( + "prowler.providers.azure.services.defender.defender_auto_provisioning_log_analytics_agent_vms_on.defender_auto_provisioning_log_analytics_agent_vms_on.defender_client", + new=defender_client, + ): + from prowler.providers.azure.services.defender.defender_auto_provisioning_log_analytics_agent_vms_on.defender_auto_provisioning_log_analytics_agent_vms_on import ( + defender_auto_provisioning_log_analytics_agent_vms_on, + ) + + check = defender_auto_provisioning_log_analytics_agent_vms_on() + result = check.execute() + assert len(result) == 0 + + def test_defender_auto_provisioning_log_analytics_off(self): + resource_id = str(uuid4()) + defender_client = mock.MagicMock + defender_client.auto_provisioning_settings = { + AZURE_SUSCRIPTION: { + "default": AutoProvisioningSetting( + resource_id=resource_id, + resource_name="default", + auto_provision="Off", + resource_type="Defender", + ) + } + } + + with mock.patch( + "prowler.providers.azure.services.defender.defender_auto_provisioning_log_analytics_agent_vms_on.defender_auto_provisioning_log_analytics_agent_vms_on.defender_client", + new=defender_client, + ): + from prowler.providers.azure.services.defender.defender_auto_provisioning_log_analytics_agent_vms_on.defender_auto_provisioning_log_analytics_agent_vms_on import ( + defender_auto_provisioning_log_analytics_agent_vms_on, + ) + + check = defender_auto_provisioning_log_analytics_agent_vms_on() + result = check.execute() + assert len(result) == 1 + assert result[0].status == "FAIL" + assert ( + result[0].status_extended + == f"Defender Auto Provisioning Log Analytics Agents from subscription {AZURE_SUSCRIPTION} is set to OFF." + ) + assert result[0].subscription == AZURE_SUSCRIPTION + assert result[0].resource_name == "default" + assert result[0].resource_id == resource_id + + def test_defender_auto_provisioning_log_analytics_on(self): + resource_id = str(uuid4()) + defender_client = mock.MagicMock + defender_client.auto_provisioning_settings = { + AZURE_SUSCRIPTION: { + "default": AutoProvisioningSetting( + resource_id=resource_id, + resource_name="default", + auto_provision="On", + resource_type="Defender", + ) + } + } + + with mock.patch( + "prowler.providers.azure.services.defender.defender_auto_provisioning_log_analytics_agent_vms_on.defender_auto_provisioning_log_analytics_agent_vms_on.defender_client", + new=defender_client, + ): + from prowler.providers.azure.services.defender.defender_auto_provisioning_log_analytics_agent_vms_on.defender_auto_provisioning_log_analytics_agent_vms_on import ( + defender_auto_provisioning_log_analytics_agent_vms_on, + ) + + check = defender_auto_provisioning_log_analytics_agent_vms_on() + result = check.execute() + assert len(result) == 1 + assert result[0].status == "PASS" + assert ( + result[0].status_extended + == f"Defender Auto Provisioning Log Analytics Agents from subscription {AZURE_SUSCRIPTION} is set to ON." + ) + assert result[0].subscription == AZURE_SUSCRIPTION + assert result[0].resource_name == "default" + assert result[0].resource_id == resource_id + + def test_defender_auto_provisioning_log_analytics_on_and_off(self): + resource_id = str(uuid4()) + defender_client = mock.MagicMock + defender_client.auto_provisioning_settings = { + AZURE_SUSCRIPTION: { + "default": AutoProvisioningSetting( + resource_id=resource_id, + resource_name="default", + auto_provision="On", + resource_type="Defender", + ), + "default2": AutoProvisioningSetting( + resource_id=resource_id, + resource_name="default2", + auto_provision="Off", + resource_type="Defender", + ), + } + } + + with mock.patch( + "prowler.providers.azure.services.defender.defender_auto_provisioning_log_analytics_agent_vms_on.defender_auto_provisioning_log_analytics_agent_vms_on.defender_client", + new=defender_client, + ): + from prowler.providers.azure.services.defender.defender_auto_provisioning_log_analytics_agent_vms_on.defender_auto_provisioning_log_analytics_agent_vms_on import ( + defender_auto_provisioning_log_analytics_agent_vms_on, + ) + + check = defender_auto_provisioning_log_analytics_agent_vms_on() + result = check.execute() + assert len(result) == 2 + assert result[0].status == "PASS" + assert ( + result[0].status_extended + == f"Defender Auto Provisioning Log Analytics Agents from subscription {AZURE_SUSCRIPTION} is set to ON." + ) + assert result[0].subscription == AZURE_SUSCRIPTION + assert result[0].resource_name == "default" + assert result[0].resource_id == resource_id + + assert result[1].status == "FAIL" + assert ( + result[1].status_extended + == f"Defender Auto Provisioning Log Analytics Agents from subscription {AZURE_SUSCRIPTION} is set to OFF." + ) + assert result[1].subscription == AZURE_SUSCRIPTION + assert result[1].resource_name == "default2" + assert result[1].resource_id == resource_id