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:
Hugo966
2024-03-01 14:01:44 +01:00
committed by GitHub
parent b4a05f4be0
commit f91ccedc83
4 changed files with 219 additions and 0 deletions

View File

@@ -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."
}

View File

@@ -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

View File

@@ -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."
)