diff --git a/prowler/providers/azure/services/defender/defender_service.py b/prowler/providers/azure/services/defender/defender_service.py index 442a5f81..f0c97595 100644 --- a/prowler/providers/azure/services/defender/defender_service.py +++ b/prowler/providers/azure/services/defender/defender_service.py @@ -1,5 +1,6 @@ from datetime import timedelta +from azure.core.exceptions import HttpResponseError from azure.mgmt.security import SecurityCenter from pydantic import BaseModel @@ -121,9 +122,9 @@ class Defender(AzureService): security_contacts = {} for subscription_name, client in self.clients.items(): try: + security_contacts.update({subscription_name: {}}) # TODO: List all security contacts. For now, the list method is not working. security_contact_default = client.security_contacts.get("default") - security_contacts.update({subscription_name: {}}) security_contacts[subscription_name].update( { security_contact_default.name: SecurityContacts( @@ -137,6 +138,25 @@ class Defender(AzureService): ) } ) + except HttpResponseError as error: + if error.status_code == 404: + security_contacts[subscription_name].update( + { + "default": SecurityContacts( + resource_id=f"/subscriptions/{self.subscriptions[subscription_name]}/providers/Microsoft.Security/securityContacts/default", + emails="", + phone="", + alert_notifications_minimal_severity="", + alert_notifications_state="", + notified_roles=[""], + notified_roles_state="", + ) + } + ) + else: + logger.error( + f"Subscription name: {subscription_name} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}" + ) except Exception as error: logger.error( f"Subscription name: {subscription_name} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}" diff --git a/tests/providers/azure/services/defender/defender_additional_email_configured_with_a_security_contact/defender_additional_email_configured_with_a_security_contact_test.py b/tests/providers/azure/services/defender/defender_additional_email_configured_with_a_security_contact/defender_additional_email_configured_with_a_security_contact_test.py index 3acaae74..5078c909 100644 --- a/tests/providers/azure/services/defender/defender_additional_email_configured_with_a_security_contact/defender_additional_email_configured_with_a_security_contact_test.py +++ b/tests/providers/azure/services/defender/defender_additional_email_configured_with_a_security_contact/defender_additional_email_configured_with_a_security_contact_test.py @@ -6,7 +6,7 @@ from tests.providers.azure.azure_fixtures import AZURE_SUBSCRIPTION class Test_defender_additional_email_configured_with_a_security_contact: - def test_defender_no_notify_emails(self): + def test_defender_no_subscriptions(self): defender_client = mock.MagicMock defender_client.security_contacts = {} @@ -206,3 +206,42 @@ class Test_defender_additional_email_configured_with_a_security_contact: assert result[0].subscription == AZURE_SUBSCRIPTION assert result[0].resource_name == "default" assert result[0].resource_id == resource_id + + def test_defender_default_security_contact_not_found(self): + defender_client = mock.MagicMock + defender_client.security_contacts = { + AZURE_SUBSCRIPTION: { + "default": SecurityContacts( + resource_id=f"/subscriptions/{AZURE_SUBSCRIPTION}/providers/Microsoft.Security/securityContacts/default", + emails="", + phone="", + alert_notifications_minimal_severity="", + alert_notifications_state="", + notified_roles=[""], + notified_roles_state="", + ) + } + } + + with mock.patch( + "prowler.providers.azure.services.defender.defender_additional_email_configured_with_a_security_contact.defender_additional_email_configured_with_a_security_contact.defender_client", + new=defender_client, + ): + from prowler.providers.azure.services.defender.defender_additional_email_configured_with_a_security_contact.defender_additional_email_configured_with_a_security_contact import ( + defender_additional_email_configured_with_a_security_contact, + ) + + check = defender_additional_email_configured_with_a_security_contact() + result = check.execute() + assert len(result) == 1 + assert result[0].status == "FAIL" + assert ( + result[0].status_extended + == f"There is not another correct email configured for susbscription {AZURE_SUBSCRIPTION}." + ) + assert result[0].subscription == AZURE_SUBSCRIPTION + assert result[0].resource_name == "default" + assert ( + result[0].resource_id + == f"/subscriptions/{AZURE_SUBSCRIPTION}/providers/Microsoft.Security/securityContacts/default" + ) diff --git a/tests/providers/azure/services/defender/defender_ensure_notify_alerts_severity_is_high/defender_ensure_notify_alerts_severity_is_high_test.py b/tests/providers/azure/services/defender/defender_ensure_notify_alerts_severity_is_high/defender_ensure_notify_alerts_severity_is_high_test.py index a323584f..48b1f1bd 100644 --- a/tests/providers/azure/services/defender/defender_ensure_notify_alerts_severity_is_high/defender_ensure_notify_alerts_severity_is_high_test.py +++ b/tests/providers/azure/services/defender/defender_ensure_notify_alerts_severity_is_high/defender_ensure_notify_alerts_severity_is_high_test.py @@ -6,7 +6,7 @@ from tests.providers.azure.azure_fixtures import AZURE_SUBSCRIPTION class Test_defender_ensure_notify_alerts_severity_is_high: - def test_defender_no_severity_alerts(self): + def test_defender_no_subscriptions(self): defender_client = mock.MagicMock defender_client.security_contacts = {} @@ -95,3 +95,42 @@ class Test_defender_ensure_notify_alerts_severity_is_high: assert result[0].subscription == AZURE_SUBSCRIPTION assert result[0].resource_name == "default" assert result[0].resource_id == resource_id + + def test_defender_default_security_contact_not_found(self): + defender_client = mock.MagicMock + defender_client.security_contacts = { + AZURE_SUBSCRIPTION: { + "default": SecurityContacts( + resource_id=f"/subscriptions/{AZURE_SUBSCRIPTION}/providers/Microsoft.Security/securityContacts/default", + emails="", + phone="", + alert_notifications_minimal_severity="", + alert_notifications_state="", + notified_roles=[""], + notified_roles_state="", + ) + } + } + + with mock.patch( + "prowler.providers.azure.services.defender.defender_ensure_notify_alerts_severity_is_high.defender_ensure_notify_alerts_severity_is_high.defender_client", + new=defender_client, + ): + from prowler.providers.azure.services.defender.defender_ensure_notify_alerts_severity_is_high.defender_ensure_notify_alerts_severity_is_high import ( + defender_ensure_notify_alerts_severity_is_high, + ) + + check = defender_ensure_notify_alerts_severity_is_high() + result = check.execute() + assert len(result) == 1 + assert result[0].status == "FAIL" + assert ( + result[0].status_extended + == f"Notifiy alerts are not enabled for severity high in susbscription {AZURE_SUBSCRIPTION}." + ) + assert result[0].subscription == AZURE_SUBSCRIPTION + assert result[0].resource_name == "default" + assert ( + result[0].resource_id + == f"/subscriptions/{AZURE_SUBSCRIPTION}/providers/Microsoft.Security/securityContacts/default" + ) diff --git a/tests/providers/azure/services/defender/defender_ensure_notify_emails_to_owners/defender_ensure_notify_emails_to_owners_test.py b/tests/providers/azure/services/defender/defender_ensure_notify_emails_to_owners/defender_ensure_notify_emails_to_owners_test.py index 854c0bdf..4df36a11 100644 --- a/tests/providers/azure/services/defender/defender_ensure_notify_emails_to_owners/defender_ensure_notify_emails_to_owners_test.py +++ b/tests/providers/azure/services/defender/defender_ensure_notify_emails_to_owners/defender_ensure_notify_emails_to_owners_test.py @@ -6,7 +6,7 @@ from tests.providers.azure.azure_fixtures import AZURE_SUBSCRIPTION class Test_defender_ensure_notify_emails_to_owners: - def test_defender_no_notify_emails(self): + def test_defender_no_subscriptions(self): defender_client = mock.MagicMock defender_client.security_contacts = {} @@ -132,3 +132,42 @@ class Test_defender_ensure_notify_emails_to_owners: assert result[0].subscription == AZURE_SUBSCRIPTION assert result[0].resource_name == "default" assert result[0].resource_id == resource_id + + def test_defender_default_security_contact_not_found(self): + defender_client = mock.MagicMock + defender_client.security_contacts = { + AZURE_SUBSCRIPTION: { + "default": SecurityContacts( + resource_id=f"/subscriptions/{AZURE_SUBSCRIPTION}/providers/Microsoft.Security/securityContacts/default", + emails="", + phone="", + alert_notifications_minimal_severity="", + alert_notifications_state="", + notified_roles=[""], + notified_roles_state="", + ) + } + } + + with mock.patch( + "prowler.providers.azure.services.defender.defender_ensure_notify_emails_to_owners.defender_ensure_notify_emails_to_owners.defender_client", + new=defender_client, + ): + from prowler.providers.azure.services.defender.defender_ensure_notify_emails_to_owners.defender_ensure_notify_emails_to_owners import ( + defender_ensure_notify_emails_to_owners, + ) + + check = defender_ensure_notify_emails_to_owners() + result = check.execute() + assert len(result) == 1 + assert result[0].status == "FAIL" + assert ( + result[0].status_extended + == f"The Owner role is not notified for subscription {AZURE_SUBSCRIPTION}." + ) + assert result[0].subscription == AZURE_SUBSCRIPTION + assert result[0].resource_name == "default" + assert ( + result[0].resource_id + == f"/subscriptions/{AZURE_SUBSCRIPTION}/providers/Microsoft.Security/securityContacts/default" + )