feat(azure): Add check defender_ensure_system_updates_are_applied and defender_auto_provisioning_vulnerabilty_assessments_machines_on (#3327)

This commit is contained in:
Rubén De la Torre Vico
2024-01-31 12:29:45 +01:00
committed by GitHub
parent 48587bd034
commit 622bce9c52
11 changed files with 650 additions and 8 deletions

View File

@@ -1,3 +1,41 @@
from uuid import uuid4
from azure.identity import DefaultAzureCredential
from prowler.providers.azure.lib.audit_info.models import (
Azure_Audit_Info,
Azure_Identity_Info,
Azure_Region_Config,
)
AZURE_SUSCRIPTION = str(uuid4())
# Azure Identity
IDENTITY_ID = "00000000-0000-0000-0000-000000000000"
IDENTITY_TYPE = "Service Principal"
TENANT_IDS = ["00000000-0000-0000-0000-000000000000"]
DOMAIN = "user.onmicrosoft.com"
# Mocked Azure Audit Info
def set_mocked_azure_audit_info(
credentials: DefaultAzureCredential = DefaultAzureCredential(),
identity: Azure_Identity_Info = Azure_Identity_Info(
identity_id=IDENTITY_ID,
identity_type=IDENTITY_TYPE,
tenant_ids=TENANT_IDS,
domain=DOMAIN,
subscriptions={AZURE_SUSCRIPTION: "id_subscription"},
),
audit_config: dict = None,
azure_region_config: Azure_Region_Config = Azure_Region_Config(),
):
audit_info = Azure_Audit_Info(
credentials=credentials,
identity=identity,
audit_metadata=None,
audit_resources=None,
audit_config=audit_config,
azure_region_config=azure_region_config,
)
return audit_info

View File

@@ -0,0 +1,91 @@
from unittest import mock
from uuid import uuid4
from prowler.providers.azure.services.defender.defender_service import (
Defender_Assessments,
)
from tests.providers.azure.azure_fixtures import AZURE_SUSCRIPTION
class Test_defender_auto_provisioning_vulnerabilty_assessments_machines_on:
def test_defender_no_app_services(self):
defender_client = mock.MagicMock
defender_client.assessments = {}
with mock.patch(
"prowler.providers.azure.services.defender.defender_auto_provisioning_vulnerabilty_assessments_machines_on.defender_auto_provisioning_vulnerabilty_assessments_machines_on.defender_client",
new=defender_client,
):
from prowler.providers.azure.services.defender.defender_auto_provisioning_vulnerabilty_assessments_machines_on.defender_auto_provisioning_vulnerabilty_assessments_machines_on import (
defender_auto_provisioning_vulnerabilty_assessments_machines_on,
)
check = defender_auto_provisioning_vulnerabilty_assessments_machines_on()
result = check.execute()
assert len(result) == 0
def test_defender_machines_no_vulnerability_assessment_solution(self):
resource_id = str(uuid4())
defender_client = mock.MagicMock
defender_client.assessments = {
AZURE_SUSCRIPTION: {
"Machines should have a vulnerability assessment solution": Defender_Assessments(
resource_id=resource_id,
resource_name="vm1",
status="Unhealthy",
)
}
}
with mock.patch(
"prowler.providers.azure.services.defender.defender_auto_provisioning_vulnerabilty_assessments_machines_on.defender_auto_provisioning_vulnerabilty_assessments_machines_on.defender_client",
new=defender_client,
):
from prowler.providers.azure.services.defender.defender_auto_provisioning_vulnerabilty_assessments_machines_on.defender_auto_provisioning_vulnerabilty_assessments_machines_on import (
defender_auto_provisioning_vulnerabilty_assessments_machines_on,
)
check = defender_auto_provisioning_vulnerabilty_assessments_machines_on()
result = check.execute()
assert len(result) == 1
assert result[0].status == "FAIL"
assert (
result[0].status_extended
== f"Vulnerability assessment is not set up in all VMs in subscription {AZURE_SUSCRIPTION}."
)
assert result[0].subscription == AZURE_SUSCRIPTION
assert result[0].resource_name == "vm1"
assert result[0].resource_id == resource_id
def test_defender_machines_vulnerability_assessment_solution(self):
resource_id = str(uuid4())
defender_client = mock.MagicMock
defender_client.assessments = {
AZURE_SUSCRIPTION: {
"Machines should have a vulnerability assessment solution": Defender_Assessments(
resource_id=resource_id,
resource_name="vm1",
status="Healthy",
)
}
}
with mock.patch(
"prowler.providers.azure.services.defender.defender_auto_provisioning_vulnerabilty_assessments_machines_on.defender_auto_provisioning_vulnerabilty_assessments_machines_on.defender_client",
new=defender_client,
):
from prowler.providers.azure.services.defender.defender_auto_provisioning_vulnerabilty_assessments_machines_on.defender_auto_provisioning_vulnerabilty_assessments_machines_on import (
defender_auto_provisioning_vulnerabilty_assessments_machines_on,
)
check = defender_auto_provisioning_vulnerabilty_assessments_machines_on()
result = check.execute()
assert len(result) == 1
assert result[0].status == "PASS"
assert (
result[0].status_extended
== f"Vulnerability assessment is set up in all VMs in subscription {AZURE_SUSCRIPTION}."
)
assert result[0].subscription == AZURE_SUSCRIPTION
assert result[0].resource_name == "vm1"
assert result[0].resource_id == resource_id

View File

@@ -0,0 +1,201 @@
from unittest import mock
from uuid import uuid4
from prowler.providers.azure.services.defender.defender_service import (
Defender_Assessments,
)
from tests.providers.azure.azure_fixtures import AZURE_SUSCRIPTION
class Test_defender_ensure_system_updates_are_applied:
def test_defender_no_app_services(self):
defender_client = mock.MagicMock
defender_client.assessments = {}
with mock.patch(
"prowler.providers.azure.services.defender.defender_ensure_system_updates_are_applied.defender_ensure_system_updates_are_applied.defender_client",
new=defender_client,
):
from prowler.providers.azure.services.defender.defender_ensure_system_updates_are_applied.defender_ensure_system_updates_are_applied import (
defender_ensure_system_updates_are_applied,
)
check = defender_ensure_system_updates_are_applied()
result = check.execute()
assert len(result) == 0
def test_defender_machines_no_log_analytics_installed(self):
resource_id = str(uuid4())
defender_client = mock.MagicMock
defender_client.assessments = {
AZURE_SUSCRIPTION: {
"Log Analytics agent should be installed on virtual machines": Defender_Assessments(
resource_id=resource_id,
resource_name="vm1",
status="Unhealthy",
),
"Machines should be configured to periodically check for missing system updates": Defender_Assessments(
resource_id=resource_id,
resource_name="vm1",
status="Healthy",
),
"System updates should be installed on your machines": Defender_Assessments(
resource_id=resource_id,
resource_name="vm1",
status="Healthy",
),
}
}
with mock.patch(
"prowler.providers.azure.services.defender.defender_ensure_system_updates_are_applied.defender_ensure_system_updates_are_applied.defender_client",
new=defender_client,
):
from prowler.providers.azure.services.defender.defender_ensure_system_updates_are_applied.defender_ensure_system_updates_are_applied import (
defender_ensure_system_updates_are_applied,
)
check = defender_ensure_system_updates_are_applied()
result = check.execute()
assert len(result) == 1
assert result[0].status == "FAIL"
assert (
result[0].status_extended
== f"System updates are not applied for all the VMs in the subscription {AZURE_SUSCRIPTION}."
)
assert result[0].subscription == AZURE_SUSCRIPTION
assert result[0].resource_name == "vm1"
assert result[0].resource_id == resource_id
def test_defender_machines_no_configured_to_periodically_check_for_system_updates(
self,
):
resource_id = str(uuid4())
defender_client = mock.MagicMock
defender_client.assessments = {
AZURE_SUSCRIPTION: {
"Log Analytics agent should be installed on virtual machines": Defender_Assessments(
resource_id=resource_id,
resource_name="vm1",
status="Healthy",
),
"Machines should be configured to periodically check for missing system updates": Defender_Assessments(
resource_id=resource_id,
resource_name="vm1",
status="Unhealthy",
),
"System updates should be installed on your machines": Defender_Assessments(
resource_id=resource_id,
resource_name="vm1",
status="Healthy",
),
}
}
with mock.patch(
"prowler.providers.azure.services.defender.defender_ensure_system_updates_are_applied.defender_ensure_system_updates_are_applied.defender_client",
new=defender_client,
):
from prowler.providers.azure.services.defender.defender_ensure_system_updates_are_applied.defender_ensure_system_updates_are_applied import (
defender_ensure_system_updates_are_applied,
)
check = defender_ensure_system_updates_are_applied()
result = check.execute()
assert len(result) == 1
assert result[0].status == "FAIL"
assert (
result[0].status_extended
== f"System updates are not applied for all the VMs in the subscription {AZURE_SUSCRIPTION}."
)
assert result[0].subscription == AZURE_SUSCRIPTION
assert result[0].resource_name == "vm1"
assert result[0].resource_id == resource_id
def test_defender_machines_no_system_updates_installed(self):
resource_id = str(uuid4())
defender_client = mock.MagicMock
defender_client.assessments = {
AZURE_SUSCRIPTION: {
"Log Analytics agent should be installed on virtual machines": Defender_Assessments(
resource_id=resource_id,
resource_name="vm1",
status="Healthy",
),
"Machines should be configured to periodically check for missing system updates": Defender_Assessments(
resource_id=resource_id,
resource_name="vm1",
status="Healthy",
),
"System updates should be installed on your machines": Defender_Assessments(
resource_id=resource_id,
resource_name="vm1",
status="Unhealthy",
),
}
}
with mock.patch(
"prowler.providers.azure.services.defender.defender_ensure_system_updates_are_applied.defender_ensure_system_updates_are_applied.defender_client",
new=defender_client,
):
from prowler.providers.azure.services.defender.defender_ensure_system_updates_are_applied.defender_ensure_system_updates_are_applied import (
defender_ensure_system_updates_are_applied,
)
check = defender_ensure_system_updates_are_applied()
result = check.execute()
assert len(result) == 1
assert result[0].status == "FAIL"
assert (
result[0].status_extended
== f"System updates are not applied for all the VMs in the subscription {AZURE_SUSCRIPTION}."
)
assert result[0].subscription == AZURE_SUSCRIPTION
assert result[0].resource_name == "vm1"
assert result[0].resource_id == resource_id
def test_defender_machines_configured_to_periodically_check_for_system_updates_and_system_updates_installed(
self,
):
resource_id = str(uuid4())
defender_client = mock.MagicMock
defender_client.assessments = {
AZURE_SUSCRIPTION: {
"Log Analytics agent should be installed on virtual machines": Defender_Assessments(
resource_id=resource_id,
resource_name="vm1",
status="Healthy",
),
"Machines should be configured to periodically check for missing system updates": Defender_Assessments(
resource_id=resource_id,
resource_name="vm1",
status="Healthy",
),
"System updates should be installed on your machines": Defender_Assessments(
resource_id=resource_id,
resource_name="vm1",
status="Healthy",
),
}
}
with mock.patch(
"prowler.providers.azure.services.defender.defender_ensure_system_updates_are_applied.defender_ensure_system_updates_are_applied.defender_client",
new=defender_client,
):
from prowler.providers.azure.services.defender.defender_ensure_system_updates_are_applied.defender_ensure_system_updates_are_applied import (
defender_ensure_system_updates_are_applied,
)
check = defender_ensure_system_updates_are_applied()
result = check.execute()
assert len(result) == 1
assert result[0].status == "PASS"
assert (
result[0].status_extended
== f"System updates are applied for all the VMs in the subscription {AZURE_SUSCRIPTION}."
)
assert result[0].subscription == AZURE_SUSCRIPTION
assert result[0].resource_name == "vm1"
assert result[0].resource_id == resource_id

View File

@@ -0,0 +1,131 @@
from datetime import timedelta
from unittest.mock import patch
from prowler.providers.azure.services.defender.defender_service import (
AutoProvisioningSetting,
Defender,
Defender_Assessments,
Defender_Pricing,
)
from tests.providers.azure.azure_fixtures import (
AZURE_SUSCRIPTION,
set_mocked_azure_audit_info,
)
def mock_defender_get_pricings(_):
return {
AZURE_SUSCRIPTION: {
"Standard": Defender_Pricing(
resource_id="resource_id",
pricing_tier="pricing_tier",
free_trial_remaining_time=timedelta(days=1),
)
}
}
def mock_defender_get_auto_provisioning_settings(_):
return {
AZURE_SUSCRIPTION: {
"default": AutoProvisioningSetting(
resource_id="/subscriptions/resource_id",
resource_name="default",
resource_type="Microsoft.Security/autoProvisioningSettings",
auto_provision="On",
)
}
}
def mock_defender_get_assessments(_):
return {
AZURE_SUSCRIPTION: {
"default": Defender_Assessments(
resource_id="/subscriptions/resource_id",
resource_name="default",
status="Healthy",
)
}
}
@patch(
"prowler.providers.azure.services.defender.defender_service.Defender.__get_pricings__",
new=mock_defender_get_pricings,
)
@patch(
"prowler.providers.azure.services.defender.defender_service.Defender.__get_auto_provisioning_settings__",
new=mock_defender_get_auto_provisioning_settings,
)
@patch(
"prowler.providers.azure.services.defender.defender_service.Defender.__get_assessments__",
new=mock_defender_get_assessments,
)
class Test_Defender_Service:
def test__get_client__(self):
defender = Defender(set_mocked_azure_audit_info())
assert (
defender.clients[AZURE_SUSCRIPTION].__class__.__name__ == "SecurityCenter"
)
def test__get_subscriptions__(self):
defender = Defender(set_mocked_azure_audit_info())
defender = Defender(set_mocked_azure_audit_info())
assert defender.subscriptions.__class__.__name__ == "dict"
def test__get_pricings__(self):
defender = Defender(set_mocked_azure_audit_info())
assert len(defender.pricings) == 1
assert (
defender.pricings[AZURE_SUSCRIPTION]["Standard"].resource_id
== "resource_id"
)
assert (
defender.pricings[AZURE_SUSCRIPTION]["Standard"].pricing_tier
== "pricing_tier"
)
assert defender.pricings[AZURE_SUSCRIPTION][
"Standard"
].free_trial_remaining_time == timedelta(days=1)
def test__get_auto_provisioning_settings__(self):
defender = Defender(set_mocked_azure_audit_info())
assert len(defender.auto_provisioning_settings) == 1
assert (
defender.auto_provisioning_settings[AZURE_SUSCRIPTION][
"default"
].resource_id
== "/subscriptions/resource_id"
)
assert (
defender.auto_provisioning_settings[AZURE_SUSCRIPTION][
"default"
].resource_name
== "default"
)
assert (
defender.auto_provisioning_settings[AZURE_SUSCRIPTION][
"default"
].resource_type
== "Microsoft.Security/autoProvisioningSettings"
)
assert (
defender.auto_provisioning_settings[AZURE_SUSCRIPTION][
"default"
].auto_provision
== "On"
)
def test__get_assessments__(self):
defender = Defender(set_mocked_azure_audit_info())
assert len(defender.assessments) == 1
assert (
defender.assessments[AZURE_SUSCRIPTION]["default"].resource_id
== "/subscriptions/resource_id"
)
assert (
defender.assessments[AZURE_SUSCRIPTION]["default"].resource_name
== "default"
)
assert defender.assessments[AZURE_SUSCRIPTION]["default"].status == "Healthy"