feat(storage): add new check storage_default_to_entra_authorization_enabled (#7981)

This commit is contained in:
Hugo Pereira Brito
2025-06-18 15:16:07 +02:00
committed by GitHub
parent c5b37887ef
commit 22343faa1e
7 changed files with 213 additions and 0 deletions
+1
View File
@@ -36,6 +36,7 @@ All notable changes to the **Prowler SDK** are documented in this file.
- IaC provider [(#7852)](https://github.com/prowler-cloud/prowler/pull/7852)
- Azure Databricks service integration for Azure provider, including the `databricks_workspace_vnet_injection_enabled` check [(#8008)](https://github.com/prowler-cloud/prowler/pull/8008)
- Azure Databricks check `databricks_workspace_cmk_encryption_enabled` to ensure workspaces use customer-managed keys (CMK) for encryption at rest [(#8017)](https://github.com/prowler-cloud/prowler/pull/8017)
- Add `storage_account_default_to_entra_authorization_enabled` check for Azure provider. [(#7981)](https://github.com/prowler-cloud/prowler/pull/7981)
---
@@ -0,0 +1,30 @@
{
"Provider": "azure",
"CheckID": "storage_default_to_entra_authorization_enabled",
"CheckTitle": "Ensure Microsoft Entra authorization is enabled by default for Azure Storage Accounts",
"CheckType": [],
"ServiceName": "storage",
"SubServiceName": "",
"ResourceIdTemplate": "",
"Severity": "high",
"ResourceType": "AzureStorageAccount",
"Description": "Ensure that the Azure Storage Account setting 'Default to Microsoft Entra authorization in the Azure portal' is enabled to enforce the use of Microsoft Entra ID for accessing blobs, files, queues, and tables.",
"Risk": "If this setting is not enabled, the Azure portal may authorize access using less secure methods such as Shared Key, increasing the risk of unauthorized data access.",
"RelatedUrl": "https://learn.microsoft.com/en-us/azure/storage/blobs/authorize-access-azure-active-directory",
"Remediation": {
"Code": {
"CLI": "az storage account update --name <storage-account-name> --resource-group <resource-group-name> --default-to-AzAd-auth true",
"NativeIaC": "",
"Other": "https://www.trendmicro.com/cloudoneconformity-staging/knowledge-base/azure/StorageAccounts/enable-microsoft-entra-authorization-by-default.html",
"Terraform": ""
},
"Recommendation": {
"Text": "Enable Microsoft Entra authorization by default in the Azure portal to enhance security and avoid reliance on Shared Key authentication.",
"Url": "https://learn.microsoft.com/en-us/azure/storage/blobs/authorize-access-azure-active-directory"
}
},
"Categories": [],
"DependsOn": [],
"RelatedTo": [],
"Notes": ""
}
@@ -0,0 +1,38 @@
from prowler.lib.check.models import Check, Check_Report_Azure
from prowler.providers.azure.services.storage.storage_client import storage_client
class storage_default_to_entra_authorization_enabled(Check):
"""Check if the default to Microsoft Entra authorization is enabled for the storage account.
Attributes:
metadata: Metadata associated with the check (inherited from Check).
"""
def execute(self) -> Check_Report_Azure:
"""Execute the check for the default to Microsoft Entra authorization.
This method checks if the default to Microsoft Entra authorization is enabled for the storage account.
Returns:
Check_Report_Azure: A report containing the result of the check.
"""
findings = []
for subscription, storage_accounts in storage_client.storage_accounts.items():
for storage_account in storage_accounts:
report = Check_Report_Azure(
metadata=self.metadata(), resource=storage_account
)
report.subscription = subscription
report.resource_name = storage_account.name
report.resource_id = storage_account.id
report.status = "FAIL"
report.status_extended = f"Default to Microsoft Entra authorization is not enabled for storage account {storage_account.name}."
if storage_account.default_to_entra_authorization:
report.status = "PASS"
report.status_extended = f"Default to Microsoft Entra authorization is enabled for storage account {storage_account.name}."
findings.append(report)
return findings
@@ -70,6 +70,11 @@ class Storage(AzureService):
],
key_expiration_period_in_days=key_expiration_period_in_days,
location=storage_account.location,
default_to_entra_authorization=getattr(
storage_account,
"default_to_o_auth_authentication",
False,
),
replication_settings=replication_settings,
allow_cross_tenant_replication=getattr(
storage_account, "allow_cross_tenant_replication", True
@@ -243,6 +248,7 @@ class Account:
allow_cross_tenant_replication: bool = True
allow_shared_key_access: bool = True
blob_properties: Optional[BlobProperties] = None
default_to_entra_authorization: bool = False
file_shares: list = None
@@ -0,0 +1,134 @@
from unittest import mock
from uuid import uuid4
from prowler.providers.azure.services.storage.storage_service import Account
from tests.providers.azure.azure_fixtures import (
AZURE_SUBSCRIPTION_ID,
set_mocked_azure_provider,
)
class Test_storage_default_to_entra_authorization_enabled:
def test_no_storage_accounts(self):
storage_client = mock.MagicMock()
storage_client.storage_accounts = {}
with (
mock.patch(
"prowler.providers.common.provider.Provider.get_global_provider",
return_value=set_mocked_azure_provider(),
),
mock.patch(
"prowler.providers.azure.services.storage.storage_default_to_entra_authorization_enabled.storage_default_to_entra_authorization_enabled.storage_client",
new=storage_client,
),
):
from prowler.providers.azure.services.storage.storage_default_to_entra_authorization_enabled.storage_default_to_entra_authorization_enabled import (
storage_default_to_entra_authorization_enabled,
)
check = storage_default_to_entra_authorization_enabled()
result = check.execute()
assert len(result) == 0
def test_storage_default_to_entra_authorization_enabled(self):
storage_account_id = str(uuid4())
storage_account_name = "Test Storage Account Entra Auth Enabled"
storage_client = mock.MagicMock()
storage_client.storage_accounts = {
AZURE_SUBSCRIPTION_ID: [
Account(
id=storage_account_id,
name=storage_account_name,
resouce_group_name=None,
enable_https_traffic_only=False,
infrastructure_encryption=False,
allow_blob_public_access=False,
network_rule_set=None,
encryption_type=None,
minimum_tls_version=None,
key_expiration_period_in_days=None,
location="westeurope",
private_endpoint_connections=None,
default_to_entra_authorization=True,
)
]
}
with (
mock.patch(
"prowler.providers.common.provider.Provider.get_global_provider",
return_value=set_mocked_azure_provider(),
),
mock.patch(
"prowler.providers.azure.services.storage.storage_default_to_entra_authorization_enabled.storage_default_to_entra_authorization_enabled.storage_client",
new=storage_client,
),
):
from prowler.providers.azure.services.storage.storage_default_to_entra_authorization_enabled.storage_default_to_entra_authorization_enabled import (
storage_default_to_entra_authorization_enabled,
)
check = storage_default_to_entra_authorization_enabled()
result = check.execute()
assert len(result) == 1
assert result[0].status == "PASS"
assert (
result[0].status_extended
== f"Default to Microsoft Entra authorization is enabled for storage account {storage_account_name}."
)
assert result[0].subscription == AZURE_SUBSCRIPTION_ID
assert result[0].resource_name == storage_account_name
assert result[0].resource_id == storage_account_id
assert result[0].location == "westeurope"
def test_storage_account_default_to_entra_authorization_disabled(self):
storage_account_id = str(uuid4())
storage_account_name = "Test Storage Account Entra Auth Disabled"
storage_client = mock.MagicMock()
storage_client.storage_accounts = {
AZURE_SUBSCRIPTION_ID: [
Account(
id=storage_account_id,
name=storage_account_name,
resouce_group_name=None,
enable_https_traffic_only=False,
infrastructure_encryption=False,
allow_blob_public_access=False,
network_rule_set=None,
encryption_type=None,
minimum_tls_version=None,
key_expiration_period_in_days=None,
location="westeurope",
private_endpoint_connections=None,
default_to_entra_authorization=False,
)
]
}
with (
mock.patch(
"prowler.providers.common.provider.Provider.get_global_provider",
return_value=set_mocked_azure_provider(),
),
mock.patch(
"prowler.providers.azure.services.storage.storage_default_to_entra_authorization_enabled.storage_default_to_entra_authorization_enabled.storage_client",
new=storage_client,
),
):
from prowler.providers.azure.services.storage.storage_default_to_entra_authorization_enabled.storage_default_to_entra_authorization_enabled import (
storage_default_to_entra_authorization_enabled,
)
check = storage_default_to_entra_authorization_enabled()
result = check.execute()
assert len(result) == 1
assert result[0].status == "FAIL"
assert (
result[0].status_extended
== f"Default to Microsoft Entra authorization is not enabled for storage account {storage_account_name}."
)
assert result[0].subscription == AZURE_SUBSCRIPTION_ID
assert result[0].resource_name == storage_account_name
assert result[0].resource_id == storage_account_id
assert result[0].location == "westeurope"
@@ -41,6 +41,7 @@ def mock_storage_get_storage_accounts(_):
private_endpoint_connections=None,
location="westeurope",
blob_properties=blob_properties,
default_to_entra_authorization=True,
replication_settings=ReplicationSettings.STANDARD_LRS,
allow_cross_tenant_replication=True,
allow_shared_key_access=True,
@@ -120,6 +121,9 @@ class Test_Storage_Service:
default_service_version=None,
container_delete_retention_policy=None,
)
assert storage.storage_accounts[AZURE_SUBSCRIPTION_ID][
0
].default_to_entra_authorization
assert (
storage.storage_accounts[AZURE_SUBSCRIPTION_ID][0].replication_settings
== ReplicationSettings.STANDARD_LRS