mirror of
https://github.com/ghndrx/prowler.git
synced 2026-02-10 06:45:08 +00:00
feat(azure): Defender check defender_ensure_iot_hub_defender_is_on (#3367)
This commit is contained in:
committed by
GitHub
parent
f7051351ec
commit
740e829e4f
@@ -0,0 +1,30 @@
|
||||
{
|
||||
"Provider": "azure",
|
||||
"CheckID": "defender_ensure_iot_hub_defender_is_on",
|
||||
"CheckTitle": "Ensure That Microsoft Defender for IoT Hub Is Set To 'On'",
|
||||
"CheckType": [],
|
||||
"ServiceName": "defender",
|
||||
"SubServiceName": "",
|
||||
"ResourceIdTemplate": "",
|
||||
"Severity": "high",
|
||||
"ResourceType": "DefenderIoT",
|
||||
"Description": "Microsoft Defender for IoT acts as a central security hub for IoT devices within your organization.",
|
||||
"Risk": "IoT devices are very rarely patched and can be potential attack vectors for enterprise networks. Updating their network configuration to use a central security hub allows for detection of these breaches.",
|
||||
"RelatedUrl": "https://azure.microsoft.com/en-us/services/iot-defender/#overview",
|
||||
"Remediation": {
|
||||
"Code": {
|
||||
"CLI": "",
|
||||
"NativeIaC": "",
|
||||
"Other": "",
|
||||
"Terraform": ""
|
||||
},
|
||||
"Recommendation": {
|
||||
"Text": "1. Go to IoT Hub. 2. Select a IoT Hub to validate. 3. Select Overview in Defender for IoT. 4. Click on Secure your IoT solution, and complete the onboarding.",
|
||||
"Url": "https://learn.microsoft.com/en-us/azure/defender-for-iot/device-builders/quickstart-onboard-iot-hub"
|
||||
}
|
||||
},
|
||||
"Categories": [],
|
||||
"DependsOn": [],
|
||||
"RelatedTo": [],
|
||||
"Notes": "Enabling Microsoft Defender for IoT will incur additional charges dependent on the level of usage."
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
from prowler.lib.check.models import Check, Check_Report_Azure
|
||||
from prowler.providers.azure.services.defender.defender_client import defender_client
|
||||
|
||||
|
||||
class defender_ensure_iot_hub_defender_is_on(Check):
|
||||
def execute(self) -> Check_Report_Azure:
|
||||
findings = []
|
||||
|
||||
for (
|
||||
subscription_name,
|
||||
iot_security_solutions,
|
||||
) in defender_client.iot_security_solutions.items():
|
||||
|
||||
if not iot_security_solutions:
|
||||
report = Check_Report_Azure(self.metadata())
|
||||
report.status = "FAIL"
|
||||
report.subscription = subscription_name
|
||||
report.resource_name = "IoT Hub Defender"
|
||||
report.resource_id = "IoT Hub Defender"
|
||||
report.status_extended = f"No IoT Security Solutions found in the subscription {subscription_name}."
|
||||
findings.append(report)
|
||||
continue
|
||||
|
||||
for (
|
||||
iot_security_solution_name,
|
||||
iot_security_solution,
|
||||
) in iot_security_solutions.items():
|
||||
report = Check_Report_Azure(self.metadata())
|
||||
report.status = "PASS"
|
||||
report.subscription = subscription_name
|
||||
report.resource_name = iot_security_solution_name
|
||||
report.resource_id = iot_security_solution.resource_id
|
||||
report.status_extended = f"The security solution {iot_security_solution_name} is enabled in susbscription {subscription_name}."
|
||||
|
||||
if iot_security_solution.status != "Enabled":
|
||||
report.status = "FAIL"
|
||||
report.status_extended = f"The security solution {iot_security_solution_name} is disabled in susbscription {subscription_name}"
|
||||
|
||||
findings.append(report)
|
||||
|
||||
return findings
|
||||
@@ -17,6 +17,7 @@ class Defender(AzureService):
|
||||
self.assessments = self.__get_assessments__()
|
||||
self.settings = self.__get_settings__()
|
||||
self.security_contacts = self.__get_security_contacts__()
|
||||
self.iot_security_solutions = self.__get_iot_security_solutions__()
|
||||
|
||||
def __get_pricings__(self):
|
||||
logger.info("Defender - Getting pricings...")
|
||||
@@ -142,6 +143,30 @@ class Defender(AzureService):
|
||||
)
|
||||
return security_contacts
|
||||
|
||||
def __get_iot_security_solutions__(self):
|
||||
logger.info("Defender - Getting IoT Security Solutions...")
|
||||
iot_security_solutions = {}
|
||||
for subscription_name, client in self.clients.items():
|
||||
try:
|
||||
iot_security_solutions_list = (
|
||||
client.iot_security_solution.list_by_subscription()
|
||||
)
|
||||
iot_security_solutions.update({subscription_name: {}})
|
||||
for iot_security_solution in iot_security_solutions_list:
|
||||
iot_security_solutions[subscription_name].update(
|
||||
{
|
||||
iot_security_solution.name: IoTSecuritySolution(
|
||||
resource_id=iot_security_solution.id,
|
||||
status=iot_security_solution.status,
|
||||
)
|
||||
}
|
||||
)
|
||||
except Exception as error:
|
||||
logger.error(
|
||||
f"Subscription name: {subscription_name} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
|
||||
)
|
||||
return iot_security_solutions
|
||||
|
||||
|
||||
class Pricing(BaseModel):
|
||||
resource_id: str
|
||||
@@ -177,3 +202,8 @@ class SecurityContacts(BaseModel):
|
||||
alert_notifications_state: str
|
||||
notified_roles: list[str]
|
||||
notified_roles_state: str
|
||||
|
||||
|
||||
class IoTSecuritySolution(BaseModel):
|
||||
resource_id: str
|
||||
status: str
|
||||
|
||||
@@ -0,0 +1,153 @@
|
||||
from unittest import mock
|
||||
from uuid import uuid4
|
||||
|
||||
from prowler.providers.azure.services.defender.defender_service import (
|
||||
IoTSecuritySolution,
|
||||
)
|
||||
from tests.providers.azure.azure_fixtures import AZURE_SUBSCRIPTION
|
||||
|
||||
|
||||
class Test_defender_ensure_iot_hub_defender_is_on:
|
||||
def test_defender_no_subscriptions(self):
|
||||
defender_client = mock.MagicMock
|
||||
defender_client.iot_security_solutions = {}
|
||||
|
||||
with mock.patch(
|
||||
"prowler.providers.azure.services.defender.defender_ensure_iot_hub_defender_is_on.defender_ensure_iot_hub_defender_is_on.defender_client",
|
||||
new=defender_client,
|
||||
):
|
||||
from prowler.providers.azure.services.defender.defender_ensure_iot_hub_defender_is_on.defender_ensure_iot_hub_defender_is_on import (
|
||||
defender_ensure_iot_hub_defender_is_on,
|
||||
)
|
||||
|
||||
check = defender_ensure_iot_hub_defender_is_on()
|
||||
result = check.execute()
|
||||
assert len(result) == 0
|
||||
|
||||
def test_defender_no_iot_hub_solutions(self):
|
||||
defender_client = mock.MagicMock
|
||||
defender_client.iot_security_solutions = {AZURE_SUBSCRIPTION: {}}
|
||||
|
||||
with mock.patch(
|
||||
"prowler.providers.azure.services.defender.defender_ensure_iot_hub_defender_is_on.defender_ensure_iot_hub_defender_is_on.defender_client",
|
||||
new=defender_client,
|
||||
):
|
||||
from prowler.providers.azure.services.defender.defender_ensure_iot_hub_defender_is_on.defender_ensure_iot_hub_defender_is_on import (
|
||||
defender_ensure_iot_hub_defender_is_on,
|
||||
)
|
||||
|
||||
check = defender_ensure_iot_hub_defender_is_on()
|
||||
result = check.execute()
|
||||
assert len(result) == 1
|
||||
assert result[0].status == "FAIL"
|
||||
assert (
|
||||
result[0].status_extended
|
||||
== f"No IoT Security Solutions found in the subscription {AZURE_SUBSCRIPTION}."
|
||||
)
|
||||
assert result[0].resource_name == "IoT Hub Defender"
|
||||
assert result[0].resource_id == "IoT Hub Defender"
|
||||
|
||||
def test_defender_iot_hub_solution_disabled(self):
|
||||
resource_id = str(uuid4())
|
||||
defender_client = mock.MagicMock
|
||||
defender_client.iot_security_solutions = {
|
||||
AZURE_SUBSCRIPTION: {
|
||||
"iot_sec_solution": IoTSecuritySolution(
|
||||
resource_id=resource_id, status="Disabled"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
with mock.patch(
|
||||
"prowler.providers.azure.services.defender.defender_ensure_iot_hub_defender_is_on.defender_ensure_iot_hub_defender_is_on.defender_client",
|
||||
new=defender_client,
|
||||
):
|
||||
from prowler.providers.azure.services.defender.defender_ensure_iot_hub_defender_is_on.defender_ensure_iot_hub_defender_is_on import (
|
||||
defender_ensure_iot_hub_defender_is_on,
|
||||
)
|
||||
|
||||
check = defender_ensure_iot_hub_defender_is_on()
|
||||
result = check.execute()
|
||||
assert len(result) == 1
|
||||
assert result[0].status == "FAIL"
|
||||
assert (
|
||||
result[0].status_extended
|
||||
== f"The security solution iot_sec_solution is disabled in susbscription {AZURE_SUBSCRIPTION}"
|
||||
)
|
||||
assert result[0].resource_name == "iot_sec_solution"
|
||||
assert result[0].resource_id == resource_id
|
||||
|
||||
def test_defender_iot_hub_solution_enabled(self):
|
||||
resource_id = str(uuid4())
|
||||
defender_client = mock.MagicMock
|
||||
defender_client.iot_security_solutions = {
|
||||
AZURE_SUBSCRIPTION: {
|
||||
"iot_sec_solution": IoTSecuritySolution(
|
||||
resource_id=resource_id, status="Enabled"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
with mock.patch(
|
||||
"prowler.providers.azure.services.defender.defender_ensure_iot_hub_defender_is_on.defender_ensure_iot_hub_defender_is_on.defender_client",
|
||||
new=defender_client,
|
||||
):
|
||||
from prowler.providers.azure.services.defender.defender_ensure_iot_hub_defender_is_on.defender_ensure_iot_hub_defender_is_on import (
|
||||
defender_ensure_iot_hub_defender_is_on,
|
||||
)
|
||||
|
||||
check = defender_ensure_iot_hub_defender_is_on()
|
||||
result = check.execute()
|
||||
assert len(result) == 1
|
||||
assert result[0].status == "PASS"
|
||||
assert (
|
||||
result[0].status_extended
|
||||
== f"The security solution iot_sec_solution is enabled in susbscription {AZURE_SUBSCRIPTION}."
|
||||
)
|
||||
assert result[0].resource_name == "iot_sec_solution"
|
||||
assert result[0].resource_id == resource_id
|
||||
assert result[0].subscription == AZURE_SUBSCRIPTION
|
||||
|
||||
def test_defender_multiple_iot_hub_solution_enabled_and_disabled(self):
|
||||
resource_id_enabled = str(uuid4())
|
||||
resource_id_disabled = str(uuid4())
|
||||
defender_client = mock.MagicMock
|
||||
defender_client.iot_security_solutions = {
|
||||
AZURE_SUBSCRIPTION: {
|
||||
"iot_sec_solution_enabled": IoTSecuritySolution(
|
||||
resource_id=resource_id_enabled, status="Enabled"
|
||||
),
|
||||
"iot_sec_solution_disabled": IoTSecuritySolution(
|
||||
resource_id=resource_id_disabled, status="Disabled"
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
with mock.patch(
|
||||
"prowler.providers.azure.services.defender.defender_ensure_iot_hub_defender_is_on.defender_ensure_iot_hub_defender_is_on.defender_client",
|
||||
new=defender_client,
|
||||
):
|
||||
from prowler.providers.azure.services.defender.defender_ensure_iot_hub_defender_is_on.defender_ensure_iot_hub_defender_is_on import (
|
||||
defender_ensure_iot_hub_defender_is_on,
|
||||
)
|
||||
|
||||
check = defender_ensure_iot_hub_defender_is_on()
|
||||
result = check.execute()
|
||||
assert len(result) == 2
|
||||
assert result[0].status == "PASS"
|
||||
assert (
|
||||
result[0].status_extended
|
||||
== f"The security solution iot_sec_solution_enabled is enabled in susbscription {AZURE_SUBSCRIPTION}."
|
||||
)
|
||||
assert result[0].resource_name == "iot_sec_solution_enabled"
|
||||
assert result[0].resource_id == resource_id_enabled
|
||||
assert result[0].subscription == AZURE_SUBSCRIPTION
|
||||
|
||||
assert result[1].status == "FAIL"
|
||||
assert (
|
||||
result[1].status_extended
|
||||
== f"The security solution iot_sec_solution_disabled is disabled in susbscription {AZURE_SUBSCRIPTION}"
|
||||
)
|
||||
assert result[1].resource_name == "iot_sec_solution_disabled"
|
||||
assert result[1].resource_id == resource_id_disabled
|
||||
assert result[1].subscription == AZURE_SUBSCRIPTION
|
||||
@@ -5,6 +5,7 @@ from prowler.providers.azure.services.defender.defender_service import (
|
||||
Assesment,
|
||||
AutoProvisioningSetting,
|
||||
Defender,
|
||||
IoTSecuritySolution,
|
||||
Pricing,
|
||||
SecurityContacts,
|
||||
Setting,
|
||||
@@ -81,6 +82,17 @@ def mock_defender_get_settings(_):
|
||||
}
|
||||
|
||||
|
||||
def mock_defender_get_iot_security_solutions(_):
|
||||
return {
|
||||
AZURE_SUBSCRIPTION: {
|
||||
"iot_sec_solution": IoTSecuritySolution(
|
||||
resource_id="/subscriptions/resource_id",
|
||||
status="Enabled",
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@patch(
|
||||
"prowler.providers.azure.services.defender.defender_service.Defender.__get_pricings__",
|
||||
new=mock_defender_get_pricings,
|
||||
@@ -101,6 +113,10 @@ def mock_defender_get_settings(_):
|
||||
"prowler.providers.azure.services.defender.defender_service.Defender.__get_security_contacts__",
|
||||
new=mock_defender_get_security_contacts,
|
||||
)
|
||||
@patch(
|
||||
"prowler.providers.azure.services.defender.defender_service.Defender.__get_iot_security_solutions__",
|
||||
new=mock_defender_get_iot_security_solutions,
|
||||
)
|
||||
class Test_Defender_Service:
|
||||
def test__get_client__(self):
|
||||
defender = Defender(set_mocked_azure_audit_info())
|
||||
@@ -221,3 +237,19 @@ class Test_Defender_Service:
|
||||
].notified_roles_state
|
||||
== "On"
|
||||
)
|
||||
|
||||
def test__get_iot_security_solutions__(self):
|
||||
defender = Defender(set_mocked_azure_audit_info())
|
||||
assert len(defender.iot_security_solutions) == 1
|
||||
assert (
|
||||
defender.iot_security_solutions[AZURE_SUBSCRIPTION][
|
||||
"iot_sec_solution"
|
||||
].resource_id
|
||||
== "/subscriptions/resource_id"
|
||||
)
|
||||
assert (
|
||||
defender.iot_security_solutions[AZURE_SUBSCRIPTION][
|
||||
"iot_sec_solution"
|
||||
].status
|
||||
== "Enabled"
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user