mirror of
https://github.com/prowler-cloud/prowler.git
synced 2026-07-23 12:31:54 +00:00
feat(storage): add new check storage_smb_protocol_version_is_latest (#8128)
Co-authored-by: Sergio Garcia <hello@mistercloudsec.com>
This commit is contained in:
committed by
GitHub
parent
15a8671f0d
commit
a319f80701
@@ -6,6 +6,7 @@ All notable changes to the **Prowler SDK** are documented in this file.
|
||||
|
||||
### Added
|
||||
- `storage_smb_channel_encryption_with_secure_algorithm` check for Azure provider [(#8123)](https://github.com/prowler-cloud/prowler/pull/8123)
|
||||
- `storage_smb_protocol_version_is_latest` check for Azure provider [(#8128)](https://github.com/prowler-cloud/prowler/pull/8128)
|
||||
- `vm_backup_enabled` check for Azure provider [(#8182)](https://github.com/prowler-cloud/prowler/pull/8182)
|
||||
- `vm_linux_enforce_ssh_authentication` check for Azure provider [(#8149)](https://github.com/prowler-cloud/prowler/pull/8149)
|
||||
- `vm_ensure_using_approved_images` check for Azure provider [(#8168)](https://github.com/prowler-cloud/prowler/pull/8168)
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
"""Constants for the storage service."""
|
||||
|
||||
LATEST_SMB_VERSION = "SMB3.1.1"
|
||||
@@ -172,6 +172,20 @@ class Storage(AzureService):
|
||||
None,
|
||||
)
|
||||
|
||||
smb_supported_versions_raw = getattr(
|
||||
getattr(
|
||||
getattr(
|
||||
file_service_properties,
|
||||
"protocol_settings",
|
||||
None,
|
||||
),
|
||||
"smb",
|
||||
None,
|
||||
),
|
||||
"versions",
|
||||
None,
|
||||
)
|
||||
|
||||
account.file_service_properties = FileServiceProperties(
|
||||
id=file_service_properties.id,
|
||||
name=file_service_properties.name,
|
||||
@@ -193,7 +207,12 @@ class Storage(AzureService):
|
||||
smb_channel_encryption_raw.rstrip(";").split(";")
|
||||
if smb_channel_encryption_raw
|
||||
else []
|
||||
)
|
||||
),
|
||||
supported_versions=(
|
||||
smb_supported_versions_raw.rstrip(";").split(";")
|
||||
if smb_supported_versions_raw
|
||||
else []
|
||||
),
|
||||
),
|
||||
)
|
||||
except Exception as error:
|
||||
@@ -240,6 +259,7 @@ class ReplicationSettings(Enum):
|
||||
|
||||
class SMBProtocolSettings(BaseModel):
|
||||
channel_encryption: list[str]
|
||||
supported_versions: list[str]
|
||||
|
||||
|
||||
class FileServiceProperties(BaseModel):
|
||||
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
{
|
||||
"Provider": "azure",
|
||||
"CheckID": "storage_smb_protocol_version_is_latest",
|
||||
"CheckTitle": "Ensure SMB protocol version for file shares is set to the latest version.",
|
||||
"CheckType": [],
|
||||
"ServiceName": "storage",
|
||||
"SubServiceName": "",
|
||||
"ResourceIdTemplate": "/subscriptions/{subscription_id}/resourceGroups/{resource_group}/providers/Microsoft.Storage/storageAccounts/{storageAccountName}/fileServices/default",
|
||||
"Severity": "medium",
|
||||
"ResourceType": "AzureStorageAccount",
|
||||
"Description": "Ensure that SMB file shares are configured to use only the latest SMB protocol version.",
|
||||
"Risk": "Allowing older SMB protocol versions may expose file shares to known vulnerabilities and security risks.",
|
||||
"RelatedUrl": "https://learn.microsoft.com/en-us/azure/storage/files/files-smb-protocol#smb-security-settings",
|
||||
"Remediation": {
|
||||
"Code": {
|
||||
"CLI": "az storage account file-service-properties update --resource-group <resource-group> --account-name <storage-account> --versions <latest-version>",
|
||||
"NativeIaC": "",
|
||||
"Other": "",
|
||||
"Terraform": ""
|
||||
},
|
||||
"Recommendation": {
|
||||
"Text": "Configure your Azure Storage Account file shares to allow only the latest SMB protocol version.",
|
||||
"Url": "https://www.trendmicro.com/cloudoneconformity/knowledge-base/azure/StorageAccounts/latest-smb-protocol-version.html"
|
||||
}
|
||||
},
|
||||
"Categories": [],
|
||||
"DependsOn": [],
|
||||
"RelatedTo": [],
|
||||
"Notes": ""
|
||||
}
|
||||
+48
@@ -0,0 +1,48 @@
|
||||
from prowler.lib.check.models import Check, Check_Report_Azure
|
||||
from prowler.providers.azure.services.storage.lib.constants import LATEST_SMB_VERSION
|
||||
from prowler.providers.azure.services.storage.storage_client import storage_client
|
||||
|
||||
|
||||
class storage_smb_protocol_version_is_latest(Check):
|
||||
"""
|
||||
Ensure SMB protocol version for file shares is set to the latest version.
|
||||
|
||||
This check evaluates whether SMB file shares are configured to use only the latest SMB protocol version.
|
||||
- PASS: Storage account allows only the latest SMB protocol version for file shares.
|
||||
- FAIL: Storage account allows other SMB protocol versions for file shares.
|
||||
"""
|
||||
|
||||
def execute(self) -> list[Check_Report_Azure]:
|
||||
findings = []
|
||||
|
||||
for subscription, storage_accounts in storage_client.storage_accounts.items():
|
||||
for account in storage_accounts:
|
||||
if getattr(account, "file_service_properties", None) and getattr(
|
||||
account.file_service_properties.smb_protocol_settings,
|
||||
"supported_versions",
|
||||
None,
|
||||
):
|
||||
report = Check_Report_Azure(
|
||||
metadata=self.metadata(),
|
||||
resource=account.file_service_properties,
|
||||
)
|
||||
report.subscription = subscription
|
||||
report.resource_name = account.name
|
||||
report.location = account.location
|
||||
if (
|
||||
len(
|
||||
account.file_service_properties.smb_protocol_settings.supported_versions
|
||||
)
|
||||
== 1
|
||||
and account.file_service_properties.smb_protocol_settings.supported_versions[
|
||||
0
|
||||
]
|
||||
== LATEST_SMB_VERSION
|
||||
):
|
||||
report.status = "PASS"
|
||||
report.status_extended = f"Storage account {account.name} from subscription {subscription} allows only the latest SMB protocol version ({LATEST_SMB_VERSION}) for file shares."
|
||||
else:
|
||||
report.status = "FAIL"
|
||||
report.status_extended = f"Storage account {account.name} from subscription {subscription} allows SMB protocol versions: {', '.join(account.file_service_properties.smb_protocol_settings.supported_versions) if account.file_service_properties.smb_protocol_settings.supported_versions else 'None'}. Only the latest SMB protocol version ({LATEST_SMB_VERSION}) should be allowed."
|
||||
findings.append(report)
|
||||
return findings
|
||||
+6
-2
@@ -91,7 +91,9 @@ class Test_storage_ensure_file_shares_soft_delete_is_enabled:
|
||||
name="default",
|
||||
type="Microsoft.Storage/storageAccounts/fileServices",
|
||||
share_delete_retention_policy=retention_policy,
|
||||
smb_protocol_settings=SMBProtocolSettings(channel_encryption=[]),
|
||||
smb_protocol_settings=SMBProtocolSettings(
|
||||
channel_encryption=[], supported_versions=[]
|
||||
),
|
||||
)
|
||||
storage_client.storage_accounts = {
|
||||
AZURE_SUBSCRIPTION_ID: [
|
||||
@@ -152,7 +154,9 @@ class Test_storage_ensure_file_shares_soft_delete_is_enabled:
|
||||
name="default",
|
||||
type="Microsoft.Storage/storageAccounts/fileServices",
|
||||
share_delete_retention_policy=retention_policy,
|
||||
smb_protocol_settings=SMBProtocolSettings(channel_encryption=[]),
|
||||
smb_protocol_settings=SMBProtocolSettings(
|
||||
channel_encryption=[], supported_versions=[]
|
||||
),
|
||||
)
|
||||
storage_client.storage_accounts = {
|
||||
AZURE_SUBSCRIPTION_ID: [
|
||||
|
||||
@@ -30,7 +30,9 @@ def mock_storage_get_storage_accounts(_):
|
||||
name="name",
|
||||
type="type",
|
||||
share_delete_retention_policy=retention_policy,
|
||||
smb_protocol_settings=SMBProtocolSettings(channel_encryption=[]),
|
||||
smb_protocol_settings=SMBProtocolSettings(
|
||||
channel_encryption=[], supported_versions=[]
|
||||
),
|
||||
)
|
||||
return {
|
||||
AZURE_SUBSCRIPTION_ID: [
|
||||
@@ -215,3 +217,11 @@ class Test_Storage_Service:
|
||||
is True
|
||||
)
|
||||
assert account.file_service_properties.share_delete_retention_policy.days == 7
|
||||
assert (
|
||||
account.file_service_properties.smb_protocol_settings.channel_encryption
|
||||
== []
|
||||
)
|
||||
assert (
|
||||
account.file_service_properties.smb_protocol_settings.supported_versions
|
||||
== []
|
||||
)
|
||||
|
||||
+5
-3
@@ -87,7 +87,9 @@ class Test_storage_smb_channel_encryption_with_secure_algorithm:
|
||||
name="fs1",
|
||||
type="type1",
|
||||
share_delete_retention_policy=DeleteRetentionPolicy(enabled=True, days=7),
|
||||
smb_protocol_settings=SMBProtocolSettings(channel_encryption=[]),
|
||||
smb_protocol_settings=SMBProtocolSettings(
|
||||
channel_encryption=[], supported_versions=[]
|
||||
),
|
||||
)
|
||||
storage_client = mock.MagicMock()
|
||||
storage_client.storage_accounts = {
|
||||
@@ -142,7 +144,7 @@ class Test_storage_smb_channel_encryption_with_secure_algorithm:
|
||||
type="type1",
|
||||
share_delete_retention_policy=DeleteRetentionPolicy(enabled=True, days=7),
|
||||
smb_protocol_settings=SMBProtocolSettings(
|
||||
channel_encryption=["AES-128-GCM"]
|
||||
channel_encryption=["AES-128-GCM"], supported_versions=[]
|
||||
),
|
||||
)
|
||||
storage_client = mock.MagicMock()
|
||||
@@ -198,7 +200,7 @@ class Test_storage_smb_channel_encryption_with_secure_algorithm:
|
||||
type="type1",
|
||||
share_delete_retention_policy=DeleteRetentionPolicy(enabled=True, days=7),
|
||||
smb_protocol_settings=SMBProtocolSettings(
|
||||
channel_encryption=["AES-256-GCM"]
|
||||
channel_encryption=["AES-256-GCM"], supported_versions=[]
|
||||
),
|
||||
)
|
||||
storage_client = mock.MagicMock()
|
||||
|
||||
+303
@@ -0,0 +1,303 @@
|
||||
from unittest import mock
|
||||
from uuid import uuid4
|
||||
|
||||
from prowler.providers.azure.services.storage.storage_service import (
|
||||
Account,
|
||||
DeleteRetentionPolicy,
|
||||
FileServiceProperties,
|
||||
NetworkRuleSet,
|
||||
SMBProtocolSettings,
|
||||
)
|
||||
from tests.providers.azure.azure_fixtures import (
|
||||
AZURE_SUBSCRIPTION_ID,
|
||||
set_mocked_azure_provider,
|
||||
)
|
||||
|
||||
|
||||
class Test_storage_smb_protocol_version_is_latest:
|
||||
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_smb_protocol_version_is_latest.storage_smb_protocol_version_is_latest.storage_client",
|
||||
new=storage_client,
|
||||
),
|
||||
):
|
||||
from prowler.providers.azure.services.storage.storage_smb_protocol_version_is_latest.storage_smb_protocol_version_is_latest import (
|
||||
storage_smb_protocol_version_is_latest,
|
||||
)
|
||||
|
||||
check = storage_smb_protocol_version_is_latest()
|
||||
result = check.execute()
|
||||
assert len(result) == 0
|
||||
|
||||
def test_no_file_service_properties(self):
|
||||
storage_account_id = str(uuid4())
|
||||
storage_account_name = "Test Storage Account"
|
||||
storage_client = mock.MagicMock()
|
||||
storage_client.storage_accounts = {
|
||||
AZURE_SUBSCRIPTION_ID: [
|
||||
Account(
|
||||
id=storage_account_id,
|
||||
name=storage_account_name,
|
||||
resouce_group_name="rg",
|
||||
enable_https_traffic_only=True,
|
||||
infrastructure_encryption=True,
|
||||
allow_blob_public_access=False,
|
||||
network_rule_set=NetworkRuleSet(
|
||||
bypass="AzureServices", default_action="Allow"
|
||||
),
|
||||
encryption_type="type",
|
||||
minimum_tls_version="TLS1_2",
|
||||
private_endpoint_connections=[],
|
||||
key_expiration_period_in_days=None,
|
||||
location="eastus",
|
||||
file_service_properties=None,
|
||||
)
|
||||
]
|
||||
}
|
||||
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_smb_protocol_version_is_latest.storage_smb_protocol_version_is_latest.storage_client",
|
||||
new=storage_client,
|
||||
),
|
||||
):
|
||||
from prowler.providers.azure.services.storage.storage_smb_protocol_version_is_latest.storage_smb_protocol_version_is_latest import (
|
||||
storage_smb_protocol_version_is_latest,
|
||||
)
|
||||
|
||||
check = storage_smb_protocol_version_is_latest()
|
||||
result = check.execute()
|
||||
assert len(result) == 0
|
||||
|
||||
def test_only_latest_smb_protocol_version(self):
|
||||
storage_account_id = str(uuid4())
|
||||
storage_account_name = "Test Storage Account"
|
||||
file_service_properties = FileServiceProperties(
|
||||
id=storage_account_id,
|
||||
name="default",
|
||||
type="type",
|
||||
share_delete_retention_policy=DeleteRetentionPolicy(enabled=True, days=7),
|
||||
smb_protocol_settings=SMBProtocolSettings(
|
||||
channel_encryption=[], supported_versions=["SMB3.1.1"]
|
||||
),
|
||||
)
|
||||
storage_client = mock.MagicMock()
|
||||
storage_client.storage_accounts = {
|
||||
AZURE_SUBSCRIPTION_ID: [
|
||||
Account(
|
||||
id=storage_account_id,
|
||||
name=storage_account_name,
|
||||
resouce_group_name="rg",
|
||||
enable_https_traffic_only=True,
|
||||
infrastructure_encryption=True,
|
||||
allow_blob_public_access=False,
|
||||
network_rule_set=NetworkRuleSet(
|
||||
bypass="AzureServices", default_action="Allow"
|
||||
),
|
||||
encryption_type="type",
|
||||
minimum_tls_version="TLS1_2",
|
||||
private_endpoint_connections=[],
|
||||
key_expiration_period_in_days=None,
|
||||
location="eastus",
|
||||
file_service_properties=file_service_properties,
|
||||
)
|
||||
]
|
||||
}
|
||||
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_smb_protocol_version_is_latest.storage_smb_protocol_version_is_latest.storage_client",
|
||||
new=storage_client,
|
||||
),
|
||||
):
|
||||
from prowler.providers.azure.services.storage.storage_smb_protocol_version_is_latest.storage_smb_protocol_version_is_latest import (
|
||||
storage_smb_protocol_version_is_latest,
|
||||
)
|
||||
|
||||
check = storage_smb_protocol_version_is_latest()
|
||||
result = check.execute()
|
||||
assert len(result) == 1
|
||||
assert result[0].status == "PASS"
|
||||
assert (
|
||||
f"Storage account {storage_account_name} from subscription {AZURE_SUBSCRIPTION_ID} allows only the latest SMB protocol version (SMB3.1.1) for file shares."
|
||||
in result[0].status_extended
|
||||
)
|
||||
|
||||
def test_multiple_smb_protocol_versions(self):
|
||||
storage_account_id = str(uuid4())
|
||||
storage_account_name = "Test Storage Account"
|
||||
file_service_properties = FileServiceProperties(
|
||||
id=storage_account_id,
|
||||
name="default",
|
||||
type="type",
|
||||
share_delete_retention_policy=DeleteRetentionPolicy(enabled=True, days=7),
|
||||
smb_protocol_settings=SMBProtocolSettings(
|
||||
channel_encryption=[], supported_versions=["SMB2.1", "SMB3.1.1"]
|
||||
),
|
||||
)
|
||||
storage_client = mock.MagicMock()
|
||||
storage_client.storage_accounts = {
|
||||
AZURE_SUBSCRIPTION_ID: [
|
||||
Account(
|
||||
id=storage_account_id,
|
||||
name=storage_account_name,
|
||||
resouce_group_name="rg",
|
||||
enable_https_traffic_only=True,
|
||||
infrastructure_encryption=True,
|
||||
allow_blob_public_access=False,
|
||||
network_rule_set=NetworkRuleSet(
|
||||
bypass="AzureServices", default_action="Allow"
|
||||
),
|
||||
encryption_type="type",
|
||||
minimum_tls_version="TLS1_2",
|
||||
private_endpoint_connections=[],
|
||||
key_expiration_period_in_days=None,
|
||||
location="eastus",
|
||||
file_service_properties=file_service_properties,
|
||||
)
|
||||
]
|
||||
}
|
||||
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_smb_protocol_version_is_latest.storage_smb_protocol_version_is_latest.storage_client",
|
||||
new=storage_client,
|
||||
),
|
||||
):
|
||||
from prowler.providers.azure.services.storage.storage_smb_protocol_version_is_latest.storage_smb_protocol_version_is_latest import (
|
||||
storage_smb_protocol_version_is_latest,
|
||||
)
|
||||
|
||||
check = storage_smb_protocol_version_is_latest()
|
||||
result = check.execute()
|
||||
assert len(result) == 1
|
||||
assert result[0].status == "FAIL"
|
||||
assert (
|
||||
f"Storage account {storage_account_name} from subscription {AZURE_SUBSCRIPTION_ID} allows SMB protocol versions: SMB2.1, SMB3.1.1. Only the latest SMB protocol version (SMB3.1.1) should be allowed."
|
||||
in result[0].status_extended
|
||||
)
|
||||
|
||||
def test_no_smb_protocol_versions(self):
|
||||
storage_account_id = str(uuid4())
|
||||
storage_account_name = "Test Storage Account"
|
||||
file_service_properties = FileServiceProperties(
|
||||
id=storage_account_id,
|
||||
name="default",
|
||||
type="type",
|
||||
share_delete_retention_policy=DeleteRetentionPolicy(enabled=True, days=7),
|
||||
smb_protocol_settings=SMBProtocolSettings(
|
||||
channel_encryption=[], supported_versions=[]
|
||||
),
|
||||
)
|
||||
storage_client = mock.MagicMock()
|
||||
storage_client.storage_accounts = {
|
||||
AZURE_SUBSCRIPTION_ID: [
|
||||
Account(
|
||||
id=storage_account_id,
|
||||
name=storage_account_name,
|
||||
resouce_group_name="rg",
|
||||
enable_https_traffic_only=True,
|
||||
infrastructure_encryption=True,
|
||||
allow_blob_public_access=False,
|
||||
network_rule_set=NetworkRuleSet(
|
||||
bypass="AzureServices", default_action="Allow"
|
||||
),
|
||||
encryption_type="type",
|
||||
minimum_tls_version="TLS1_2",
|
||||
private_endpoint_connections=[],
|
||||
key_expiration_period_in_days=None,
|
||||
location="eastus",
|
||||
file_service_properties=file_service_properties,
|
||||
)
|
||||
]
|
||||
}
|
||||
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_smb_protocol_version_is_latest.storage_smb_protocol_version_is_latest.storage_client",
|
||||
new=storage_client,
|
||||
),
|
||||
):
|
||||
from prowler.providers.azure.services.storage.storage_smb_protocol_version_is_latest.storage_smb_protocol_version_is_latest import (
|
||||
storage_smb_protocol_version_is_latest,
|
||||
)
|
||||
|
||||
check = storage_smb_protocol_version_is_latest()
|
||||
result = check.execute()
|
||||
assert len(result) == 0
|
||||
|
||||
def test_multiple_required_versions_custom_config(self):
|
||||
storage_account_id = str(uuid4())
|
||||
storage_account_name = "Test Storage Account"
|
||||
file_service_properties = FileServiceProperties(
|
||||
id=storage_account_id,
|
||||
name="default",
|
||||
type="type",
|
||||
share_delete_retention_policy=DeleteRetentionPolicy(enabled=True, days=7),
|
||||
smb_protocol_settings=SMBProtocolSettings(
|
||||
channel_encryption=[], supported_versions=["SMB3.1.1", "SMB3.0"]
|
||||
),
|
||||
)
|
||||
storage_client = mock.MagicMock()
|
||||
storage_client.storage_accounts = {
|
||||
AZURE_SUBSCRIPTION_ID: [
|
||||
Account(
|
||||
id=storage_account_id,
|
||||
name=storage_account_name,
|
||||
resouce_group_name="rg",
|
||||
enable_https_traffic_only=True,
|
||||
infrastructure_encryption=True,
|
||||
allow_blob_public_access=False,
|
||||
network_rule_set=NetworkRuleSet(
|
||||
bypass="AzureServices", default_action="Allow"
|
||||
),
|
||||
encryption_type="type",
|
||||
minimum_tls_version="TLS1_2",
|
||||
private_endpoint_connections=[],
|
||||
key_expiration_period_in_days=None,
|
||||
location="eastus",
|
||||
file_service_properties=file_service_properties,
|
||||
)
|
||||
]
|
||||
}
|
||||
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_smb_protocol_version_is_latest.storage_smb_protocol_version_is_latest.storage_client",
|
||||
new=storage_client,
|
||||
),
|
||||
):
|
||||
from prowler.providers.azure.services.storage.storage_smb_protocol_version_is_latest.storage_smb_protocol_version_is_latest import (
|
||||
storage_smb_protocol_version_is_latest,
|
||||
)
|
||||
|
||||
check = storage_smb_protocol_version_is_latest()
|
||||
result = check.execute()
|
||||
assert len(result) == 1
|
||||
assert result[0].status == "FAIL"
|
||||
assert (
|
||||
f"Storage account {storage_account_name} from subscription {AZURE_SUBSCRIPTION_ID} allows SMB protocol versions: SMB3.1.1, SMB3.0. Only the latest SMB protocol version (SMB3.1.1) should be allowed."
|
||||
in result[0].status_extended
|
||||
)
|
||||
Reference in New Issue
Block a user