mirror of
https://github.com/ghndrx/prowler.git
synced 2026-02-10 06:45:08 +00:00
feat(azure): add new check related with cmk (#3466)
Co-authored-by: Hugo Gálvez Ureña <hugogalvezu96@gmail.com>
This commit is contained in:
@@ -0,0 +1,30 @@
|
||||
{
|
||||
"Provider": "azure",
|
||||
"CheckID": "monitor_storage_account_with_activity_logs_cmk_encrypted",
|
||||
"CheckTitle": "Ensure the storage account containing the container with activity logs is encrypted with Customer Managed Key",
|
||||
"CheckType": [],
|
||||
"ServiceName": "monitor",
|
||||
"SubServiceName": "",
|
||||
"ResourceIdTemplate": "",
|
||||
"Severity": "Medium",
|
||||
"ResourceType": "Monitor",
|
||||
"Description": "Storage accounts with the activity log exports can be configured to use CustomerManaged Keys (CMK).",
|
||||
"Risk": "Configuring the storage account with the activity log export container to use CMKs provides additional confidentiality controls on log data, as a given user must have read permission on the corresponding storage account and must be granted decrypt permission by the CMK.",
|
||||
"RelatedUrl": "https://learn.microsoft.com/en-us/security/benchmark/azure/security-controls-v3-data-protection#dp-5-encrypt-sensitive-data-at-rest",
|
||||
"Remediation": {
|
||||
"Code": {
|
||||
"CLI": "az storage account update --name <name of the storage account> --resource-group <resource group for a storage account> --encryption-key-source=Microsoft.Keyvault --encryption-key-vault <Key Vault URI> --encryption-key-name <KeyName> --encryption-key-version <Key Version>",
|
||||
"NativeIaC": "",
|
||||
"Other": "https://www.trendmicro.com/cloudoneconformity-staging/knowledge-base/azure/Monitor/use-cmk-for-activity-log-storage-container-encryption.html",
|
||||
"Terraform": "https://docs.bridgecrew.io/docs/ensure-that-storage-accounts-use-customer-managed-key-for-encryption#terraform"
|
||||
},
|
||||
"Recommendation": {
|
||||
"Text": "1. Go to Activity log 2. Select Export 3. Select Subscription 4. In section Storage Account, note the name of the Storage account 5. Close the Export Audit Logs blade. Close the Monitor - Activity Log blade. 6. In right column, Click service Storage Accounts to access Storage account blade 7. Click on the storage account name noted in step 4. This will open blade specific to that storage account 8. Under Security + networking, click Encryption. 9. Ensure Customer-managed keys is selected and Key URI is set.",
|
||||
"Url": "https://learn.microsoft.com/en-us/azure/azure-monitor/essentials/activity-log?tabs=cli#managing-legacy-log-profiles"
|
||||
}
|
||||
},
|
||||
"Categories": [],
|
||||
"DependsOn": [],
|
||||
"RelatedTo": [],
|
||||
"Notes": "NOTE: You must have your key vault setup to utilize this. All Audit Logs will be encrypted with a key you provide. You will need to set up customer managed keys separately, and you will select which key to use via the instructions here. You will be responsible for the lifecycle of the keys, and will need to manually replace them at your own determined intervals to keep the data secure."
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
from prowler.lib.check.models import Check, Check_Report_Azure
|
||||
from prowler.providers.azure.services.monitor.monitor_client import monitor_client
|
||||
from prowler.providers.azure.services.storage.storage_client import storage_client
|
||||
|
||||
|
||||
class monitor_storage_account_with_activity_logs_cmk_encrypted(Check):
|
||||
def execute(self) -> Check_Report_Azure:
|
||||
findings = []
|
||||
|
||||
for (
|
||||
subscription_name,
|
||||
diagnostic_settings,
|
||||
) in monitor_client.diagnostics_settings.items():
|
||||
for diagnostic_setting in diagnostic_settings:
|
||||
for storage_account in storage_client.storage_accounts[
|
||||
subscription_name
|
||||
]:
|
||||
if storage_account.name == diagnostic_setting.storage_account_name:
|
||||
report = Check_Report_Azure(self.metadata())
|
||||
report.subscription = subscription_name
|
||||
report.resource_name = storage_account.name
|
||||
report.resource_id = storage_account.id
|
||||
if storage_account.encryption_type == "Microsoft.Storage":
|
||||
report.status = "FAIL"
|
||||
report.status_extended = f"Storage account {storage_account.name} storing activity log in subscription {subscription_name} is not encrypted with Customer Managed Key."
|
||||
else:
|
||||
report.status = "PASS"
|
||||
report.status_extended = f"Storage account {storage_account.name} storing activity log in subscription {subscription_name} is encrypted with Customer Managed Key or not necessary."
|
||||
|
||||
findings.append(report)
|
||||
|
||||
return findings
|
||||
@@ -0,0 +1,157 @@
|
||||
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_storage_account_with_activity_logs_cmk_encrypted:
|
||||
def test_monitor_storage_account_with_activity_logs_cmk_encrypted_no_subscriptions(
|
||||
self,
|
||||
):
|
||||
monitor_client = mock.MagicMock
|
||||
monitor_client.diagnostics_settings = {}
|
||||
|
||||
with mock.patch(
|
||||
"prowler.providers.azure.services.monitor.monitor_storage_account_with_activity_logs_cmk_encrypted.monitor_storage_account_with_activity_logs_cmk_encrypted.monitor_client",
|
||||
new=monitor_client,
|
||||
):
|
||||
from prowler.providers.azure.services.monitor.monitor_storage_account_with_activity_logs_cmk_encrypted.monitor_storage_account_with_activity_logs_cmk_encrypted import (
|
||||
monitor_storage_account_with_activity_logs_cmk_encrypted,
|
||||
)
|
||||
|
||||
check = monitor_storage_account_with_activity_logs_cmk_encrypted()
|
||||
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_storage_account_with_activity_logs_cmk_encrypted.monitor_storage_account_with_activity_logs_cmk_encrypted.monitor_client",
|
||||
new=monitor_client,
|
||||
):
|
||||
from prowler.providers.azure.services.monitor.monitor_storage_account_with_activity_logs_cmk_encrypted.monitor_storage_account_with_activity_logs_cmk_encrypted import (
|
||||
monitor_storage_account_with_activity_logs_cmk_encrypted,
|
||||
)
|
||||
|
||||
check = monitor_storage_account_with_activity_logs_cmk_encrypted()
|
||||
result = check.execute()
|
||||
assert len(result) == 0
|
||||
|
||||
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_storage_account_with_activity_logs_cmk_encrypted.monitor_storage_account_with_activity_logs_cmk_encrypted.monitor_client",
|
||||
new=monitor_client,
|
||||
):
|
||||
with mock.patch(
|
||||
"prowler.providers.azure.services.monitor.monitor_storage_account_with_activity_logs_cmk_encrypted.monitor_storage_account_with_activity_logs_cmk_encrypted.storage_client",
|
||||
new=storage_client,
|
||||
):
|
||||
from prowler.providers.azure.services.monitor.monitor_storage_account_with_activity_logs_cmk_encrypted.monitor_storage_account_with_activity_logs_cmk_encrypted import (
|
||||
monitor_storage_account_with_activity_logs_cmk_encrypted,
|
||||
)
|
||||
|
||||
check = monitor_storage_account_with_activity_logs_cmk_encrypted()
|
||||
result = check.execute()
|
||||
assert len(result) == 2
|
||||
assert result[0].subscription == AZURE_SUBSCRIPTION
|
||||
assert result[0].status == "PASS"
|
||||
assert result[0].resource_name == "storageaccountname1"
|
||||
assert (
|
||||
result[0].resource_id
|
||||
== "/subscriptions/1234a5-123a-123a-123a-1234567890ab/resourceGroups/rg/providers/Microsoft.Storage/storageAccounts/storageaccountname1"
|
||||
)
|
||||
assert (
|
||||
result[0].status_extended
|
||||
== f"Storage account {storage_client.storage_accounts[AZURE_SUBSCRIPTION][0].name} storing activity log in subscription {AZURE_SUBSCRIPTION} is encrypted with Customer Managed Key or not necessary."
|
||||
)
|
||||
assert result[1].status == "FAIL"
|
||||
assert result[1].resource_name == "storageaccountname2"
|
||||
assert (
|
||||
result[1].resource_id
|
||||
== "/subscriptions/1224a5-123a-123a-123a-1234567890ab/resourceGroups/rg/providers/Microsoft.Storage/storageAccounts/storageaccountname2"
|
||||
)
|
||||
assert (
|
||||
result[1].status_extended
|
||||
== f"Storage account {storage_client.storage_accounts[AZURE_SUBSCRIPTION][1].name} storing activity log in subscription {AZURE_SUBSCRIPTION} is not encrypted with Customer Managed Key."
|
||||
)
|
||||
Reference in New Issue
Block a user