feat(azure): New check related with diagnostics settings in subscriptions (#3539)

Co-authored-by: Hugo Gálvez Ureña <hugogalvezu96@gmail.com>
This commit is contained in:
Hugo966
2024-03-15 14:09:32 +01:00
committed by GitHub
parent d1602a0655
commit d7fbcce48c
4 changed files with 206 additions and 0 deletions
@@ -0,0 +1,30 @@
{
"Provider": "azure",
"CheckID": "monitor_diagnostic_settings_exists",
"CheckTitle": "Ensure that a 'Diagnostic Setting' exists for Subscription Activity Logs ",
"CheckType": [],
"ServiceName": "monitor",
"SubServiceName": "",
"ResourceIdTemplate": "",
"Severity": "medium",
"ResourceType": "Monitor",
"Description": "Enable Diagnostic settings for exporting activity logs. Diagnostic settings are available for each individual resource within a subscription. Settings should be configured for all appropriate resources for your environment.",
"Risk": "A diagnostic setting controls how a diagnostic log is exported. By default, logs are retained only for 90 days. Diagnostic settings should be defined so that logs can be exported and stored for a longer duration in order to analyze security activities within an Azure subscription.",
"RelatedUrl": "https://learn.microsoft.com/en-us/cli/azure/monitor/diagnostic-settings?view=azure-cli-latest",
"Remediation": {
"Code": {
"CLI": "az monitor diagnostic-settings subscription create --subscription <subscription id> --name <diagnostic settings name> --location <location> <[- -event-hub <event hub ID> --event-hub-auth-rule <event hub auth rule ID>] [-- storage-account <storage account ID>] [--workspace <log analytics workspace ID>] --logs '<JSON encoded categories>' (e.g. [{category:Security,enabled:true},{category:Administrative,enabled:true},{cat egory:Alert,enabled:true},{category:Policy,enabled:true}])",
"NativeIaC": "",
"Other": "https://www.trendmicro.com/cloudoneconformity-staging/knowledge-base/azure/Monitor/subscription-activity-log-diagnostic-settings.html#trendmicro",
"Terraform": ""
},
"Recommendation": {
"Text": "To enable Diagnostic Settings on a Subscription: 1. Go to Monitor 2. Click on Activity Log 3. Click on Export Activity Logs 4. Click + Add diagnostic setting 5. Enter a Diagnostic setting name 6. Select Categories for the diagnostic settings 7. Select the appropriate Destination details (this may be Log Analytics, Storage Account, Event Hub, or Partner solution) 8. Click Save To enable Diagnostic Settings on a specific resource: 1. Go to Monitor 2. Click Diagnostic settings 3. Click on the resource that has a diagnostics status of disabled 4. Select Add Diagnostic Setting 5. Enter a Diagnostic setting name 6. Select the appropriate log, metric, and destination. (this may be Log Analytics, Storage Account, Event Hub, or Partner solution) 7. Click save Repeat these step for all resources as needed.",
"Url": "https://docs.microsoft.com/en-us/azure/monitoring-and-diagnostics/monitoring-overview-activity-logs#export-the-activity-log-with-a-log-profile"
}
},
"Categories": [],
"DependsOn": [],
"RelatedTo": [],
"Notes": "By default, diagnostic setting is not set."
}
@@ -0,0 +1,27 @@
from prowler.lib.check.models import Check, Check_Report_Azure
from prowler.providers.azure.services.monitor.monitor_client import monitor_client
class monitor_diagnostic_settings_exists(Check):
def execute(self) -> Check_Report_Azure:
findings = []
for (
subscription_name,
diagnostic_settings,
) in monitor_client.diagnostics_settings.items():
report = Check_Report_Azure(self.metadata())
report.subscription = subscription_name
report.status = "FAIL"
report.status_extended = (
f"No diagnostic settings found in subscription {subscription_name}."
)
if diagnostic_settings:
report.status = "PASS"
report.status_extended = (
f"Diagnostic settings found in subscription {subscription_name}."
)
findings.append(report)
return findings
@@ -0,0 +1,149 @@
from unittest import mock
from prowler.providers.azure.services.monitor.monitor_service import DiagnosticSetting
from prowler.providers.azure.services.storage.storage_service import Account
from tests.providers.azure.azure_fixtures import AZURE_SUBSCRIPTION
class Test_monitor_diagnostic_settings_exists:
def test_monitor_diagnostic_settings_exists_no_subscriptions(
self,
):
monitor_client = mock.MagicMock
monitor_client.diagnostics_settings = {}
with mock.patch(
"prowler.providers.azure.services.monitor.monitor_diagnostic_settings_exists.monitor_diagnostic_settings_exists.monitor_client",
new=monitor_client,
):
from prowler.providers.azure.services.monitor.monitor_diagnostic_settings_exists.monitor_diagnostic_settings_exists import (
monitor_diagnostic_settings_exists,
)
check = monitor_diagnostic_settings_exists()
result = check.execute()
assert len(result) == 0
def test_no_diagnostic_settings(self):
monitor_client = mock.MagicMock
monitor_client.diagnostics_settings = {AZURE_SUBSCRIPTION: []}
with mock.patch(
"prowler.providers.azure.services.monitor.monitor_diagnostic_settings_exists.monitor_diagnostic_settings_exists.monitor_client",
new=monitor_client,
):
from prowler.providers.azure.services.monitor.monitor_diagnostic_settings_exists.monitor_diagnostic_settings_exists import (
monitor_diagnostic_settings_exists,
)
check = monitor_diagnostic_settings_exists()
result = check.execute()
assert len(result) == 1
assert result[0].subscription == AZURE_SUBSCRIPTION
assert result[0].status == "FAIL"
assert (
result[0].status_extended
== f"No diagnostic settings found in subscription {AZURE_SUBSCRIPTION}."
)
def test_diagnostic_settings_configured(self):
monitor_client = mock.MagicMock
storage_client = mock.MagicMock
monitor_client.diagnostics_settings = {
AZURE_SUBSCRIPTION: [
DiagnosticSetting(
id="id",
logs=[
mock.MagicMock(category="Administrative", enabled=True),
mock.MagicMock(category="Security", enabled=True),
mock.MagicMock(category="ServiceHealth", enabled=False),
mock.MagicMock(category="Alert", enabled=True),
mock.MagicMock(category="Recommendation", enabled=False),
mock.MagicMock(category="Policy", enabled=True),
mock.MagicMock(category="Autoscale", enabled=False),
],
storage_account_id="/subscriptions/1234a5-123a-123a-123a-1234567890ab/resourceGroups/rg/providers/Microsoft.Storage/storageAccounts/storageaccountname1",
storage_account_name="storageaccountname1",
),
DiagnosticSetting(
id="id2",
logs=[
mock.MagicMock(category="Administrative", enabled=True),
mock.MagicMock(category="Security", enabled=True),
mock.MagicMock(category="ServiceHealth", enabled=False),
mock.MagicMock(category="Alert", enabled=True),
mock.MagicMock(category="Recommendation", enabled=False),
mock.MagicMock(category="Policy", enabled=True),
mock.MagicMock(category="Autoscale", enabled=False),
],
storage_account_id="/subscriptions/1224a5-123a-123a-123a-1234567890ab/resourceGroups/rg/providers/Microsoft.Storage/storageAccounts/storageaccountname2",
storage_account_name="storageaccountname2",
),
]
}
storage_client.storage_accounts = {
AZURE_SUBSCRIPTION: [
Account(
id="/subscriptions/1234a5-123a-123a-123a-1234567890ab/resourceGroups/rg/providers/Microsoft.Storage/storageAccounts/storageaccountname1",
name="storageaccountname1",
resouce_group_name="rg",
enable_https_traffic_only=True,
infrastructure_encryption="Enabled",
allow_blob_public_access=True,
network_rule_set="AllowAll",
encryption_type="Microsoft.CustomerManagedKeyVault",
minimum_tls_version="TLS1_2",
private_endpoint_connections=[],
key_expiration_period_in_days=365,
blob_properties=mock.MagicMock(
id="id",
name="name",
type="type",
default_service_version="default_service_version",
container_delete_retention_policy="container_delete_retention_policy",
),
),
Account(
id="/subscriptions/1224a5-123a-123a-123a-1234567890ab/resourceGroups/rg/providers/Microsoft.Storage/storageAccounts/storageaccountname2",
name="storageaccountname2",
resouce_group_name="rg",
enable_https_traffic_only=False,
infrastructure_encryption="Enabled",
allow_blob_public_access=False,
network_rule_set="AllowAll",
encryption_type="Microsoft.Storage",
minimum_tls_version="TLS1_2",
private_endpoint_connections=[],
key_expiration_period_in_days=365,
blob_properties=mock.MagicMock(
id="id",
name="name",
type="type",
default_service_version="default_service_version",
container_delete_retention_policy="container_delete_retention_policy",
),
),
]
}
with mock.patch(
"prowler.providers.azure.services.monitor.monitor_diagnostic_settings_exists.monitor_diagnostic_settings_exists.monitor_client",
new=monitor_client,
):
with mock.patch(
"prowler.providers.azure.services.monitor.monitor_diagnostic_settings_exists.monitor_diagnostic_settings_exists.monitor_client",
new=monitor_client,
):
from prowler.providers.azure.services.monitor.monitor_diagnostic_settings_exists.monitor_diagnostic_settings_exists import (
monitor_diagnostic_settings_exists,
)
check = monitor_diagnostic_settings_exists()
result = check.execute()
assert len(result) == 1
assert result[0].subscription == AZURE_SUBSCRIPTION
assert result[0].status == "PASS"
assert (
result[0].status_extended
== f"Diagnostic settings found in subscription {AZURE_SUBSCRIPTION}."
)