From 14aa7a3f6701430dd6c53f592fc8b3cba7249108 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pedro=20Mart=C3=ADn?= Date: Fri, 2 Feb 2024 11:35:18 +0100 Subject: [PATCH] feat(azure): SQLServer checks related to TDE encryption (#3343) --- .../services/sqlserver/sqlserver_service.py | 74 +++++- .../__init__.py | 0 ...erver_tde_encrypted_with_cmk.metadata.json | 30 +++ .../sqlserver_tde_encrypted_with_cmk.py | 38 ++++ .../__init__.py | 0 ...erver_tde_encryption_enabled.metadata.json | 30 +++ .../sqlserver_tde_encryption_enabled.py | 27 +++ tests/lib/check/check_test.py | 64 ++++++ .../sqlserver_auditing_enabled_test.py | 2 +- ...rver_azuread_administrator_enabled_test.py | 2 +- .../sqlserver/sqlserver_service_test.py | 148 ++++++++++++ .../sqlserver_tde_encrypted_with_cmk_test.py | 210 ++++++++++++++++++ .../sqlserver_tde_encryption_enabled_test.py | 160 +++++++++++++ ...server_unrestricted_inbound_access_test.py | 2 +- 14 files changed, 782 insertions(+), 5 deletions(-) create mode 100644 prowler/providers/azure/services/sqlserver/sqlserver_tde_encrypted_with_cmk/__init__.py create mode 100644 prowler/providers/azure/services/sqlserver/sqlserver_tde_encrypted_with_cmk/sqlserver_tde_encrypted_with_cmk.metadata.json create mode 100644 prowler/providers/azure/services/sqlserver/sqlserver_tde_encrypted_with_cmk/sqlserver_tde_encrypted_with_cmk.py create mode 100644 prowler/providers/azure/services/sqlserver/sqlserver_tde_encryption_enabled/__init__.py create mode 100644 prowler/providers/azure/services/sqlserver/sqlserver_tde_encryption_enabled/sqlserver_tde_encryption_enabled.metadata.json create mode 100644 prowler/providers/azure/services/sqlserver/sqlserver_tde_encryption_enabled/sqlserver_tde_encryption_enabled.py create mode 100644 tests/providers/azure/services/sqlserver/sqlserver_service_test.py create mode 100644 tests/providers/azure/services/sqlserver/sqlserver_tde_encrypted_with_cmk/sqlserver_tde_encrypted_with_cmk_test.py create mode 100644 tests/providers/azure/services/sqlserver/sqlserver_tde_encryption_enabled/sqlserver_tde_encryption_enabled_test.py diff --git a/prowler/providers/azure/services/sqlserver/sqlserver_service.py b/prowler/providers/azure/services/sqlserver/sqlserver_service.py index 21e2b36d..0516e04a 100644 --- a/prowler/providers/azure/services/sqlserver/sqlserver_service.py +++ b/prowler/providers/azure/services/sqlserver/sqlserver_service.py @@ -2,9 +2,11 @@ from dataclasses import dataclass from azure.mgmt.sql import SqlManagementClient from azure.mgmt.sql.models import ( + EncryptionProtector, FirewallRule, ServerBlobAuditingPolicy, ServerExternalAdministrator, + TransparentDataEncryption, ) from prowler.lib.logger import logger @@ -35,6 +37,9 @@ class SQLServer(AzureService): firewall_rules = client.firewall_rules.list_by_server( resource_group_name=resource_group, server_name=sql_server.name ) + encryption_protector = self.__get_enctyption_protectors__( + subscription, resource_group, sql_server.name + ) sql_servers[subscription].append( SQL_Server( id=sql_server.id, @@ -44,12 +49,15 @@ class SQLServer(AzureService): administrators=sql_server.administrators, auditing_policies=auditing_policies, firewall_rules=firewall_rules, + encryption_protector=encryption_protector, + databases=self.__get_databases__( + subscription, resource_group, sql_server.name + ), ) ) except Exception as error: - logger.error(f"Subscription name: {subscription}") logger.error( - f"{error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}" + f"Subscription name: {subscription} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}" ) return sql_servers @@ -57,6 +65,66 @@ class SQLServer(AzureService): resource_group = id.split("/")[4] return resource_group + def __get_transparent_data_encryption__( + self, subscription, resource_group, server_name, database_name + ): + client = self.clients[subscription] + tde_encrypted = client.transparent_data_encryptions.get( + resource_group_name=resource_group, + server_name=server_name, + database_name=database_name, + transparent_data_encryption_name="current", + ) + return tde_encrypted + + def __get_enctyption_protectors__(self, subscription, resource_group, server_name): + client = self.clients[subscription] + encryption_protectors = client.encryption_protectors.get( + resource_group_name=resource_group, + server_name=server_name, + encryption_protector_name="current", + ) + return encryption_protectors + + def __get_databases__(self, subscription, resource_group, server_name): + logger.info("SQL Server - Getting server databases...") + databases = [] + try: + client = self.clients[subscription] + databases_server = client.databases.list_by_server( + resource_group_name=resource_group, + server_name=server_name, + ) + for database in databases_server: + tde_encrypted = self.__get_transparent_data_encryption__( + subscription, resource_group, server_name, database.name + ) + databases.append( + DatabaseServer( + id=database.id, + name=database.name, + type=database.type, + location=database.location, + managed_by=database.managed_by, + tde_encryption=tde_encrypted, + ) + ) + except Exception as error: + logger.error( + f"Subscription name: {subscription} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}" + ) + return databases + + +@dataclass +class DatabaseServer: + id: str + name: str + type: str + location: str + managed_by: str + tde_encryption: TransparentDataEncryption + @dataclass class SQL_Server: @@ -67,3 +135,5 @@ class SQL_Server: administrators: ServerExternalAdministrator auditing_policies: ServerBlobAuditingPolicy firewall_rules: FirewallRule + encryption_protector: EncryptionProtector = None + databases: list[DatabaseServer] = None diff --git a/prowler/providers/azure/services/sqlserver/sqlserver_tde_encrypted_with_cmk/__init__.py b/prowler/providers/azure/services/sqlserver/sqlserver_tde_encrypted_with_cmk/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/prowler/providers/azure/services/sqlserver/sqlserver_tde_encrypted_with_cmk/sqlserver_tde_encrypted_with_cmk.metadata.json b/prowler/providers/azure/services/sqlserver/sqlserver_tde_encrypted_with_cmk/sqlserver_tde_encrypted_with_cmk.metadata.json new file mode 100644 index 00000000..ff01eedb --- /dev/null +++ b/prowler/providers/azure/services/sqlserver/sqlserver_tde_encrypted_with_cmk/sqlserver_tde_encrypted_with_cmk.metadata.json @@ -0,0 +1,30 @@ +{ + "Provider": "azure", + "CheckID": "sqlserver_tde_encrypted_with_cmk", + "CheckTitle": "Ensure SQL server's Transparent Data Encryption (TDE) protector is encrypted with Customer-managed key", + "CheckType": [], + "ServiceName": "sqlserver", + "SubServiceName": "", + "ResourceIdTemplate": "", + "Severity": "medium", + "ResourceType": "SQLServer", + "Description": "Transparent Data Encryption (TDE) with Customer-managed key support provides increased transparency and control over the TDE Protector, increased security with an HSM-backed external service, and promotion of separation of duties.", + "Risk": "Customer-managed key support for Transparent Data Encryption (TDE) allows user control of TDE encryption keys and restricts who can access them and when. Azure Key Vault, Azure cloud-based external key management system, is the first key management service where TDE has integrated support for Customer-managed keys. With Customer-managed key support, the database encryption key is protected by an asymmetric key stored in the Key Vault. The asymmetric key is set at the server level and inherited by all databases under that server", + "RelatedUrl": "https://docs.microsoft.com/en-us/sql/relational-databases/security/encryption/transparent-data-encryption-byok-azure-sql", + "Remediation": { + "Code": { + "CLI": "az sql server tde-key set --resource-group resourceName --server dbServerName --server-key-type {AzureKeyVault} --kid keyIdentifier", + "NativeIaC": "", + "Other": "https://www.trendmicro.com/cloudoneconformity-staging/knowledge-base/azure/Sql/use-byok-for-transparent-data-encryption.html#", + "Terraform": "" + }, + "Recommendation": { + "Text": "1. Go to SQL servers For the desired server instance 2. Click On Transparent data encryption 3. Set Transparent data encryption to Customer-managed key 4. Browse through your key vaults to Select an existing key or create a new key in the Azure Key Vault. 5. Check Make selected key the default TDE protector", + "Url": "https://learn.microsoft.com/en-us/azure/azure-sql/database/transparent-data-encryption-byok-overview?view=azuresql" + } + }, + "Categories": [], + "DependsOn": [], + "RelatedTo": [], + "Notes": "Once TDE protector is encrypted with a Customer-managed key, it transfers entire responsibility of respective key management on to you, and hence you should be more careful about doing any operations on the particular key in order to keep data from corresponding SQL server and Databases hosted accessible. When deploying Customer Managed Keys, it is prudent to ensure that you also deploy an automated toolset for managing these keys (this should include discovery and key rotation), and Keys should be stored in an HSM or hardware backed keystore, such as Azure Key Vault. As far as toolsets go, check with your cryptographic key provider, as they may well provide one as an add-on to their service." +} diff --git a/prowler/providers/azure/services/sqlserver/sqlserver_tde_encrypted_with_cmk/sqlserver_tde_encrypted_with_cmk.py b/prowler/providers/azure/services/sqlserver/sqlserver_tde_encrypted_with_cmk/sqlserver_tde_encrypted_with_cmk.py new file mode 100644 index 00000000..c7b7fc76 --- /dev/null +++ b/prowler/providers/azure/services/sqlserver/sqlserver_tde_encrypted_with_cmk/sqlserver_tde_encrypted_with_cmk.py @@ -0,0 +1,38 @@ +from prowler.lib.check.models import Check, Check_Report_Azure +from prowler.providers.azure.services.sqlserver.sqlserver_client import sqlserver_client + + +class sqlserver_tde_encrypted_with_cmk(Check): + def execute(self) -> Check_Report_Azure: + findings = [] + for subscription, sql_servers in sqlserver_client.sql_servers.items(): + for sql_server in sql_servers: + databases = ( + sql_server.databases if sql_server.databases is not None else [] + ) + if len(databases) > 0: + report = Check_Report_Azure(self.metadata()) + report.subscription = subscription + report.resource_name = sql_server.name + report.resource_id = sql_server.id + found_disabled = False + if ( + sql_server.encryption_protector.server_key_type + == "AzureKeyVault" + ): + for database in databases: + if found_disabled: + break + if database.tde_encryption.status == "Enabled": + report.status = "PASS" + report.status_extended = f"SQL Server {sql_server.name} from subscription {subscription} has TDE enabled with CMK." + else: + report.status = "FAIL" + report.status_extended = f"SQL Server {sql_server.name} from subscription {subscription} has TDE disabled with CMK." + found_disabled = True + else: + report.status = "FAIL" + report.status_extended = f"SQL Server {sql_server.name} from subscription {subscription} has TDE disabled without CMK." + findings.append(report) + + return findings diff --git a/prowler/providers/azure/services/sqlserver/sqlserver_tde_encryption_enabled/__init__.py b/prowler/providers/azure/services/sqlserver/sqlserver_tde_encryption_enabled/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/prowler/providers/azure/services/sqlserver/sqlserver_tde_encryption_enabled/sqlserver_tde_encryption_enabled.metadata.json b/prowler/providers/azure/services/sqlserver/sqlserver_tde_encryption_enabled/sqlserver_tde_encryption_enabled.metadata.json new file mode 100644 index 00000000..4b3b71ec --- /dev/null +++ b/prowler/providers/azure/services/sqlserver/sqlserver_tde_encryption_enabled/sqlserver_tde_encryption_enabled.metadata.json @@ -0,0 +1,30 @@ +{ + "Provider": "azure", + "CheckID": "sqlserver_tde_encrypted", + "CheckTitle": "Ensure SQL server's Transparent Data Encryption (TDE) protector is encrypted", + "CheckType": [], + "ServiceName": "sqlserver", + "SubServiceName": "", + "ResourceIdTemplate": "", + "Severity": "medium", + "ResourceType": "SQLServer", + "Description": "Enable Transparent Data Encryption on every SQL server.", + "Risk": "Azure SQL Database transparent data encryption helps protect against the threat of malicious activity by performing real-time encryption and decryption of the database, associated backups, and transaction log files at rest without requiring changes to the application.", + "RelatedUrl": "https://docs.microsoft.com/en-us/sql/relational-databases/security/encryption/transparent-data-encryption-with-azure-sql-database", + "Remediation": { + "Code": { + "CLI": "az sql db tde set --resource-group resourceGroup --server dbServerName --database dbName --status Enabled", + "NativeIaC": "", + "Other": "https://www.trendmicro.com/cloudoneconformity-staging/knowledge-base/azure/Sql/data-encryption.html#", + "Terraform": "" + }, + "Recommendation": { + "Text": "1. Go to SQL databases 2. For each DB instance 3. Click on Transparent data encryption 4. Set Data encryption to On", + "Url": "https://learn.microsoft.com/en-us/azure/azure-sql/database/transparent-data-encryption-byok-overview?view=azuresql" + } + }, + "Categories": [], + "DependsOn": [], + "RelatedTo": [], + "Notes": "" +} diff --git a/prowler/providers/azure/services/sqlserver/sqlserver_tde_encryption_enabled/sqlserver_tde_encryption_enabled.py b/prowler/providers/azure/services/sqlserver/sqlserver_tde_encryption_enabled/sqlserver_tde_encryption_enabled.py new file mode 100644 index 00000000..f65e3292 --- /dev/null +++ b/prowler/providers/azure/services/sqlserver/sqlserver_tde_encryption_enabled/sqlserver_tde_encryption_enabled.py @@ -0,0 +1,27 @@ +from prowler.lib.check.models import Check, Check_Report_Azure +from prowler.providers.azure.services.sqlserver.sqlserver_client import sqlserver_client + + +class sqlserver_tde_encryption_enabled(Check): + def execute(self) -> Check_Report_Azure: + findings = [] + for subscription, sql_servers in sqlserver_client.sql_servers.items(): + for sql_server in sql_servers: + databases = ( + sql_server.databases if sql_server.databases is not None else [] + ) + if len(databases) > 0: + for database in databases: + report = Check_Report_Azure(self.metadata()) + report.subscription = subscription + report.resource_name = database.name + report.resource_id = database.id + if database.tde_encryption.status == "Enabled": + report.status = "PASS" + report.status_extended = f"Database {database.name} from SQL Server {sql_server.name} from subscription {subscription} has TDE enabled" + else: + report.status = "FAIL" + report.status_extended = f"Database {database.name} from SQL Server {sql_server.name} from subscription {subscription} has TDE disabled" + findings.append(report) + + return findings diff --git a/tests/lib/check/check_test.py b/tests/lib/check/check_test.py index 81d11b3b..72a517be 100644 --- a/tests/lib/check/check_test.py +++ b/tests/lib/check/check_test.py @@ -73,6 +73,34 @@ expected_packages = [ name="prowler.providers.azure.services.storage.storage_ensure_encryption_with_customer_managed_keys.storage_ensure_encryption_with_customer_managed_keys", ispkg=False, ), + ModuleInfo( + module_finder=FileFinder( + "/root_dir/prowler/providers/azure/services/sqlserver" + ), + name="prowler.providers.azure.services.sqlserver.sqlserver_tde_encrypted_with_cmk", + ispkg=True, + ), + ModuleInfo( + module_finder=FileFinder( + "/root_dir/prowler/providers/azure/services/sqlserver/sqlserver_tde_encrypted_with_cmk" + ), + name="prowler.providers.azure.services.sqlserver.sqlserver_tde_encrypted_with_cmk.sqlserver_tde_encrypted_with_cmk", + ispkg=False, + ), + ModuleInfo( + module_finder=FileFinder( + "/root_dir/prowler/providers/azure/services/sqlserver" + ), + name="prowler.providers.azure.services.sqlserver.sqlserver_tde_encryption_enabled", + ispkg=True, + ), + ModuleInfo( + module_finder=FileFinder( + "/root_dir/prowler/providers/azure/services/sqlserver/sqlserver_tde_encryption_enabled" + ), + name="prowler.providers.azure.services.sqlserver.sqlserver_tde_encryption_enabled.sqlserver_tde_encryption_enabled", + ispkg=False, + ), ] @@ -124,6 +152,34 @@ def mock_list_modules(*_): name="prowler.providers.azure.services.storage.storage_ensure_encryption_with_customer_managed_keys.storage_ensure_encryption_with_customer_managed_keys", ispkg=False, ), + ModuleInfo( + module_finder=FileFinder( + "/root_dir/prowler/providers/azure/services/sqlserver" + ), + name="prowler.providers.azure.services.sqlserver.sqlserver_tde_encrypted_with_cmk", + ispkg=True, + ), + ModuleInfo( + module_finder=FileFinder( + "/root_dir/prowler/providers/azure/services/sqlserver/sqlserver_tde_encrypted_with_cmk" + ), + name="prowler.providers.azure.services.sqlserver.sqlserver_tde_encrypted_with_cmk.sqlserver_tde_encrypted_with_cmk", + ispkg=False, + ), + ModuleInfo( + module_finder=FileFinder( + "/root_dir/prowler/providers/azure/services/sqlserver" + ), + name="prowler.providers.azure.services.sqlserver.sqlserver_tde_encryption_enabled", + ispkg=True, + ), + ModuleInfo( + module_finder=FileFinder( + "/root_dir/prowler/providers/azure/services/sqlserver/sqlserver_tde_encryption_enabled" + ), + name="prowler.providers.azure.services.sqlserver.sqlserver_tde_encryption_enabled.sqlserver_tde_encryption_enabled", + ispkg=False, + ), ] return modules @@ -505,6 +561,14 @@ class Test_Check: "storage_ensure_encryption_with_customer_managed_keys", "/root_dir/prowler/providers/azure/services/storage/storage_ensure_encryption_with_customer_managed_keys", ), + ( + "sqlserver_tde_encrypted_with_cmk", + "/root_dir/prowler/providers/azure/services/sqlserver/sqlserver_tde_encrypted_with_cmk", + ), + ( + "sqlserver_tde_encryption_enabled", + "/root_dir/prowler/providers/azure/services/sqlserver/sqlserver_tde_encryption_enabled", + ), ] returned_checks = recover_checks_from_provider(provider, service) assert returned_checks == expected_checks diff --git a/tests/providers/azure/services/sqlserver/sqlserver_auditing_enabled/sqlserver_auditing_enabled_test.py b/tests/providers/azure/services/sqlserver/sqlserver_auditing_enabled/sqlserver_auditing_enabled_test.py index ce8c5bf6..a202d645 100644 --- a/tests/providers/azure/services/sqlserver/sqlserver_auditing_enabled/sqlserver_auditing_enabled_test.py +++ b/tests/providers/azure/services/sqlserver/sqlserver_auditing_enabled/sqlserver_auditing_enabled_test.py @@ -12,7 +12,7 @@ from prowler.providers.azure.services.sqlserver.sqlserver_service import SQL_Ser AZURE_SUSCRIPTION = str(uuid4()) -class Test_defender_ensure_defender_for_storage_is_on: +class Test_sqlserver_auditing_enabled: def test_no_sql_servers(self): sqlserver_client = mock.MagicMock sqlserver_client.sql_servers = {} diff --git a/tests/providers/azure/services/sqlserver/sqlserver_azuread_administrator_enabled/sqlserver_azuread_administrator_enabled_test.py b/tests/providers/azure/services/sqlserver/sqlserver_azuread_administrator_enabled/sqlserver_azuread_administrator_enabled_test.py index 44b3ef82..dd8c39ba 100644 --- a/tests/providers/azure/services/sqlserver/sqlserver_azuread_administrator_enabled/sqlserver_azuread_administrator_enabled_test.py +++ b/tests/providers/azure/services/sqlserver/sqlserver_azuread_administrator_enabled/sqlserver_azuread_administrator_enabled_test.py @@ -8,7 +8,7 @@ from prowler.providers.azure.services.sqlserver.sqlserver_service import SQL_Ser AZURE_SUSCRIPTION = str(uuid4()) -class Test_defender_ensure_defender_for_storage_is_on: +class Test_sqlserver_azuread_administrator_enabled: def test_no_sql_servers(self): sqlserver_client = mock.MagicMock sqlserver_client.sql_servers = {} diff --git a/tests/providers/azure/services/sqlserver/sqlserver_service_test.py b/tests/providers/azure/services/sqlserver/sqlserver_service_test.py new file mode 100644 index 00000000..8813b307 --- /dev/null +++ b/tests/providers/azure/services/sqlserver/sqlserver_service_test.py @@ -0,0 +1,148 @@ +from unittest.mock import patch + +from azure.mgmt.sql.models import EncryptionProtector, TransparentDataEncryption + +from prowler.providers.azure.services.sqlserver.sqlserver_service import ( + DatabaseServer, + SQL_Server, + SQLServer, +) +from tests.providers.azure.azure_fixtures import ( + AZURE_SUSCRIPTION, + set_mocked_azure_audit_info, +) + + +def mock_sqlserver_get_sql_servers(_): + database = DatabaseServer( + id="id", + name="name", + type="type", + location="location", + managed_by="managed_by", + tde_encryption=TransparentDataEncryption(status="Disabled"), + ) + return { + AZURE_SUSCRIPTION: [ + SQL_Server( + id="id", + name="name", + public_network_access="public_network_access", + minimal_tls_version="minimal_tls_version", + administrators=None, + auditing_policies=None, + firewall_rules=None, + encryption_protector=EncryptionProtector( + server_key_type="AzureKeyVault" + ), + databases=[database], + ) + ] + } + + +@patch( + "prowler.providers.azure.services.sqlserver.sqlserver_service.SQLServer.__get_sql_servers__", + new=mock_sqlserver_get_sql_servers, +) +class Test_SqlServer_Service: + def test__get_client__(self): + sql_server = SQLServer(set_mocked_azure_audit_info()) + assert ( + sql_server.clients[AZURE_SUSCRIPTION].__class__.__name__ + == "SqlManagementClient" + ) + + def test__get_sql_servers__(self): + database = DatabaseServer( + id="id", + name="name", + type="type", + location="location", + managed_by="managed_by", + tde_encryption=TransparentDataEncryption(status="Disabled"), + ) + sql_server = SQLServer(set_mocked_azure_audit_info()) + assert ( + sql_server.sql_servers[AZURE_SUSCRIPTION][0].__class__.__name__ + == "SQL_Server" + ) + assert sql_server.sql_servers[AZURE_SUSCRIPTION][0].id == "id" + assert sql_server.sql_servers[AZURE_SUSCRIPTION][0].name == "name" + assert ( + sql_server.sql_servers[AZURE_SUSCRIPTION][0].public_network_access + == "public_network_access" + ) + assert ( + sql_server.sql_servers[AZURE_SUSCRIPTION][0].minimal_tls_version + == "minimal_tls_version" + ) + assert sql_server.sql_servers[AZURE_SUSCRIPTION][0].administrators is None + assert sql_server.sql_servers[AZURE_SUSCRIPTION][0].auditing_policies is None + assert sql_server.sql_servers[AZURE_SUSCRIPTION][0].firewall_rules is None + assert ( + sql_server.sql_servers[AZURE_SUSCRIPTION][ + 0 + ].encryption_protector.__class__.__name__ + == "EncryptionProtector" + ) + assert sql_server.sql_servers[AZURE_SUSCRIPTION][0].databases == [database] + + def test__get_databases__(self): + sql_server = SQLServer(set_mocked_azure_audit_info()) + assert ( + sql_server.sql_servers[AZURE_SUSCRIPTION][0].databases[0].__class__.__name__ + == "DatabaseServer" + ) + assert sql_server.sql_servers[AZURE_SUSCRIPTION][0].databases[0].id == "id" + assert sql_server.sql_servers[AZURE_SUSCRIPTION][0].databases[0].name == "name" + assert sql_server.sql_servers[AZURE_SUSCRIPTION][0].databases[0].type == "type" + assert ( + sql_server.sql_servers[AZURE_SUSCRIPTION][0].databases[0].location + == "location" + ) + assert ( + sql_server.sql_servers[AZURE_SUSCRIPTION][0].databases[0].managed_by + == "managed_by" + ) + assert ( + sql_server.sql_servers[AZURE_SUSCRIPTION][0] + .databases[0] + .tde_encryption.__class__.__name__ + == "TransparentDataEncryption" + ) + + def test__get_transparent_data_encryption__(self): + sql_server = SQLServer(set_mocked_azure_audit_info()) + assert ( + sql_server.sql_servers[AZURE_SUSCRIPTION][0] + .databases[0] + .tde_encryption.__class__.__name__ + == "TransparentDataEncryption" + ) + assert ( + sql_server.sql_servers[AZURE_SUSCRIPTION][0] + .databases[0] + .tde_encryption.status + == "Disabled" + ) + + def test__get_encryption_protectors__(self): + sql_server = SQLServer(set_mocked_azure_audit_info()) + assert ( + sql_server.sql_servers[AZURE_SUSCRIPTION][ + 0 + ].encryption_protector.__class__.__name__ + == "EncryptionProtector" + ) + assert ( + sql_server.sql_servers[AZURE_SUSCRIPTION][ + 0 + ].encryption_protector.server_key_type + == "AzureKeyVault" + ) + + def test__get_resource_group__(self): + id = "/subscriptions/subscription_id/resourceGroups/resource_group/providers/Microsoft.Sql/servers/sql_server" + sql_server = SQLServer(set_mocked_azure_audit_info()) + assert sql_server.__get_resource_group__(id) == "resource_group" diff --git a/tests/providers/azure/services/sqlserver/sqlserver_tde_encrypted_with_cmk/sqlserver_tde_encrypted_with_cmk_test.py b/tests/providers/azure/services/sqlserver/sqlserver_tde_encrypted_with_cmk/sqlserver_tde_encrypted_with_cmk_test.py new file mode 100644 index 00000000..55744519 --- /dev/null +++ b/tests/providers/azure/services/sqlserver/sqlserver_tde_encrypted_with_cmk/sqlserver_tde_encrypted_with_cmk_test.py @@ -0,0 +1,210 @@ +from unittest import mock +from uuid import uuid4 + +from azure.mgmt.sql.models import EncryptionProtector, TransparentDataEncryption + +from prowler.providers.azure.services.sqlserver.sqlserver_service import ( + DatabaseServer, + SQL_Server, +) + +AZURE_SUSCRIPTION = str(uuid4()) + + +class Test_sqlserver_tde_encrypted_with_cmk: + def test_no_sql_servers(self): + sqlserver_client = mock.MagicMock + sqlserver_client.sql_servers = {} + + with mock.patch( + "prowler.providers.azure.services.sqlserver.sqlserver_tde_encrypted_with_cmk.sqlserver_tde_encrypted_with_cmk.sqlserver_client", + new=sqlserver_client, + ): + from prowler.providers.azure.services.sqlserver.sqlserver_tde_encrypted_with_cmk.sqlserver_tde_encrypted_with_cmk import ( + sqlserver_tde_encrypted_with_cmk, + ) + + check = sqlserver_tde_encrypted_with_cmk() + result = check.execute() + assert len(result) == 0 + + def test_no_sql_servers_databases(self): + sqlserver_client = mock.MagicMock + sql_server_name = "SQL Server Name" + sql_server_id = str(uuid4()) + sqlserver_client.sql_servers = { + AZURE_SUSCRIPTION: [ + SQL_Server( + id=sql_server_id, + name=sql_server_name, + public_network_access="", + minimal_tls_version="", + administrators=None, + auditing_policies=None, + firewall_rules=None, + databases=None, + ) + ] + } + + with mock.patch( + "prowler.providers.azure.services.sqlserver.sqlserver_tde_encrypted_with_cmk.sqlserver_tde_encrypted_with_cmk.sqlserver_client", + new=sqlserver_client, + ): + from prowler.providers.azure.services.sqlserver.sqlserver_tde_encrypted_with_cmk.sqlserver_tde_encrypted_with_cmk import ( + sqlserver_tde_encrypted_with_cmk, + ) + + check = sqlserver_tde_encrypted_with_cmk() + result = check.execute() + assert len(result) == 0 + + def test_sql_servers_encryption_protector_service_managed(self): + sqlserver_client = mock.MagicMock + sql_server_name = "SQL Server Name" + sql_server_id = str(uuid4()) + database = DatabaseServer( + id="id", + name="name", + type="type", + location="location", + managed_by="managed_by", + tde_encryption=None, + ) + sqlserver_client.sql_servers = { + AZURE_SUSCRIPTION: [ + SQL_Server( + id=sql_server_id, + name=sql_server_name, + public_network_access="", + minimal_tls_version="", + administrators=None, + auditing_policies=None, + firewall_rules=None, + databases=[database], + encryption_protector=EncryptionProtector( + server_key_type="ServiceManaged" + ), + ) + ] + } + + with mock.patch( + "prowler.providers.azure.services.sqlserver.sqlserver_tde_encrypted_with_cmk.sqlserver_tde_encrypted_with_cmk.sqlserver_client", + new=sqlserver_client, + ): + from prowler.providers.azure.services.sqlserver.sqlserver_tde_encrypted_with_cmk.sqlserver_tde_encrypted_with_cmk import ( + sqlserver_tde_encrypted_with_cmk, + ) + + check = sqlserver_tde_encrypted_with_cmk() + result = check.execute() + assert len(result) == 1 + assert result[0].status == "FAIL" + assert ( + result[0].status_extended + == f"SQL Server {sql_server_name} from subscription {AZURE_SUSCRIPTION} has TDE disabled without CMK." + ) + assert result[0].subscription == AZURE_SUSCRIPTION + assert result[0].resource_name == sql_server_name + assert result[0].resource_id == sql_server_id + + def test_sql_servers_database_encryption_disabled(self): + sqlserver_client = mock.MagicMock + sql_server_name = "SQL Server Name" + sql_server_id = str(uuid4()) + database = DatabaseServer( + id="id", + name="name", + type="type", + location="location", + managed_by="managed_by", + tde_encryption=TransparentDataEncryption(status="Disabled"), + ) + sqlserver_client.sql_servers = { + AZURE_SUSCRIPTION: [ + SQL_Server( + id=sql_server_id, + name=sql_server_name, + public_network_access="", + minimal_tls_version="", + administrators=None, + auditing_policies=None, + firewall_rules=None, + databases=[database], + encryption_protector=EncryptionProtector( + server_key_type="AzureKeyVault" + ), + ) + ] + } + + with mock.patch( + "prowler.providers.azure.services.sqlserver.sqlserver_tde_encrypted_with_cmk.sqlserver_tde_encrypted_with_cmk.sqlserver_client", + new=sqlserver_client, + ): + from prowler.providers.azure.services.sqlserver.sqlserver_tde_encrypted_with_cmk.sqlserver_tde_encrypted_with_cmk import ( + sqlserver_tde_encrypted_with_cmk, + ) + + check = sqlserver_tde_encrypted_with_cmk() + result = check.execute() + assert len(result) == 1 + assert result[0].status == "FAIL" + assert ( + result[0].status_extended + == f"SQL Server {sql_server_name} from subscription {AZURE_SUSCRIPTION} has TDE disabled with CMK." + ) + assert result[0].subscription == AZURE_SUSCRIPTION + assert result[0].resource_name == sql_server_name + assert result[0].resource_id == sql_server_id + + def test_sql_servers_database_encryption_enabled(self): + sqlserver_client = mock.MagicMock + sql_server_name = "SQL Server Name" + sql_server_id = str(uuid4()) + database = DatabaseServer( + id="id", + name="name", + type="type", + location="location", + managed_by="managed_by", + tde_encryption=TransparentDataEncryption(status="Enabled"), + ) + sqlserver_client.sql_servers = { + AZURE_SUSCRIPTION: [ + SQL_Server( + id=sql_server_id, + name=sql_server_name, + public_network_access="", + minimal_tls_version="", + administrators=None, + auditing_policies=None, + firewall_rules=None, + databases=[database], + encryption_protector=EncryptionProtector( + server_key_type="AzureKeyVault" + ), + ) + ] + } + + with mock.patch( + "prowler.providers.azure.services.sqlserver.sqlserver_tde_encrypted_with_cmk.sqlserver_tde_encrypted_with_cmk.sqlserver_client", + new=sqlserver_client, + ): + from prowler.providers.azure.services.sqlserver.sqlserver_tde_encrypted_with_cmk.sqlserver_tde_encrypted_with_cmk import ( + sqlserver_tde_encrypted_with_cmk, + ) + + check = sqlserver_tde_encrypted_with_cmk() + result = check.execute() + assert len(result) == 1 + assert result[0].status == "PASS" + assert ( + result[0].status_extended + == f"SQL Server {sql_server_name} from subscription {AZURE_SUSCRIPTION} has TDE enabled with CMK." + ) + assert result[0].subscription == AZURE_SUSCRIPTION + assert result[0].resource_name == sql_server_name + assert result[0].resource_id == sql_server_id diff --git a/tests/providers/azure/services/sqlserver/sqlserver_tde_encryption_enabled/sqlserver_tde_encryption_enabled_test.py b/tests/providers/azure/services/sqlserver/sqlserver_tde_encryption_enabled/sqlserver_tde_encryption_enabled_test.py new file mode 100644 index 00000000..28c14f52 --- /dev/null +++ b/tests/providers/azure/services/sqlserver/sqlserver_tde_encryption_enabled/sqlserver_tde_encryption_enabled_test.py @@ -0,0 +1,160 @@ +from unittest import mock +from uuid import uuid4 + +from azure.mgmt.sql.models import TransparentDataEncryption + +from prowler.providers.azure.services.sqlserver.sqlserver_service import ( + DatabaseServer, + SQL_Server, +) + +AZURE_SUSCRIPTION = str(uuid4()) + + +class Test_sqlserver_tde_encryption_enabled: + def test_no_sql_servers(self): + sqlserver_client = mock.MagicMock + sqlserver_client.sql_servers = {} + + with mock.patch( + "prowler.providers.azure.services.sqlserver.sqlserver_tde_encryption_enabled.sqlserver_tde_encryption_enabled.sqlserver_client", + new=sqlserver_client, + ): + from prowler.providers.azure.services.sqlserver.sqlserver_tde_encryption_enabled.sqlserver_tde_encryption_enabled import ( + sqlserver_tde_encryption_enabled, + ) + + check = sqlserver_tde_encryption_enabled() + result = check.execute() + assert len(result) == 0 + + def test_no_sql_servers_databases(self): + sqlserver_client = mock.MagicMock + sql_server_name = "SQL Server Name" + sql_server_id = str(uuid4()) + sqlserver_client.sql_servers = { + AZURE_SUSCRIPTION: [ + SQL_Server( + id=sql_server_id, + name=sql_server_name, + public_network_access="", + minimal_tls_version="", + administrators=None, + auditing_policies=None, + firewall_rules=None, + databases=None, + ) + ] + } + + with mock.patch( + "prowler.providers.azure.services.sqlserver.sqlserver_tde_encryption_enabled.sqlserver_tde_encryption_enabled.sqlserver_client", + new=sqlserver_client, + ): + from prowler.providers.azure.services.sqlserver.sqlserver_tde_encryption_enabled.sqlserver_tde_encryption_enabled import ( + sqlserver_tde_encryption_enabled, + ) + + check = sqlserver_tde_encryption_enabled() + result = check.execute() + assert len(result) == 0 + + def test_sql_servers_database_encryption_disabled(self): + sqlserver_client = mock.MagicMock + sql_server_name = "SQL Server Name" + sql_server_id = str(uuid4()) + database_name = "Database Name" + database_id = str(uuid4()) + database = DatabaseServer( + id=database_id, + name=database_name, + type="type", + location="location", + managed_by="managed_by", + tde_encryption=TransparentDataEncryption(status="Disabled"), + ) + sqlserver_client.sql_servers = { + AZURE_SUSCRIPTION: [ + SQL_Server( + id=sql_server_id, + name=sql_server_name, + public_network_access="", + minimal_tls_version="", + administrators=None, + auditing_policies=None, + firewall_rules=None, + databases=[database], + encryption_protector=None, + ) + ] + } + + with mock.patch( + "prowler.providers.azure.services.sqlserver.sqlserver_tde_encryption_enabled.sqlserver_tde_encryption_enabled.sqlserver_client", + new=sqlserver_client, + ): + from prowler.providers.azure.services.sqlserver.sqlserver_tde_encryption_enabled.sqlserver_tde_encryption_enabled import ( + sqlserver_tde_encryption_enabled, + ) + + check = sqlserver_tde_encryption_enabled() + result = check.execute() + assert len(result) == 1 + assert result[0].status == "FAIL" + assert ( + result[0].status_extended + == f"Database {database_name} from SQL Server {sql_server_name} from subscription {AZURE_SUSCRIPTION} has TDE disabled" + ) + assert result[0].subscription == AZURE_SUSCRIPTION + assert result[0].resource_name == database_name + assert result[0].resource_id == database_id + + def test_sql_servers_database_encryption_enabled(self): + sqlserver_client = mock.MagicMock + sql_server_name = "SQL Server Name" + sql_server_id = str(uuid4()) + database_name = "Database Name" + database_id = str(uuid4()) + database = DatabaseServer( + id=database_id, + name=database_name, + type="type", + location="location", + managed_by="managed_by", + tde_encryption=TransparentDataEncryption(status="Enabled"), + ) + sqlserver_client.sql_servers = { + AZURE_SUSCRIPTION: [ + SQL_Server( + id=sql_server_id, + name=sql_server_name, + public_network_access="", + minimal_tls_version="", + administrators=None, + auditing_policies=None, + firewall_rules=None, + databases=[database], + encryption_protector=None, + ) + ] + } + + with mock.patch( + "prowler.providers.azure.services.sqlserver.sqlserver_tde_encryption_enabled.sqlserver_tde_encryption_enabled.sqlserver_client", + new=sqlserver_client, + ): + from prowler.providers.azure.services.sqlserver.sqlserver_tde_encryption_enabled.sqlserver_tde_encryption_enabled import ( + sqlserver_tde_encryption_enabled, + ) + + check = sqlserver_tde_encryption_enabled() + result = check.execute() + assert len(result) == 1 + assert result[0].status == "PASS" + assert ( + result[0].status_extended + == f"Database {database_name} from SQL Server {sql_server_name} from subscription {AZURE_SUSCRIPTION} has TDE enabled" + ) + assert result[0].subscription == AZURE_SUSCRIPTION + assert result[0].resource_name == database_name + assert result[0].resource_id == database_id diff --git a/tests/providers/azure/services/sqlserver/sqlserver_unrestricted_inbound_access/sqlserver_unrestricted_inbound_access_test.py b/tests/providers/azure/services/sqlserver/sqlserver_unrestricted_inbound_access/sqlserver_unrestricted_inbound_access_test.py index 5a50e3f3..16ee9a83 100644 --- a/tests/providers/azure/services/sqlserver/sqlserver_unrestricted_inbound_access/sqlserver_unrestricted_inbound_access_test.py +++ b/tests/providers/azure/services/sqlserver/sqlserver_unrestricted_inbound_access/sqlserver_unrestricted_inbound_access_test.py @@ -8,7 +8,7 @@ from prowler.providers.azure.services.sqlserver.sqlserver_service import SQL_Ser AZURE_SUSCRIPTION = str(uuid4()) -class Test_defender_ensure_defender_for_storage_is_on: +class Test_sqlserver_unrestricted_inbound_access: def test_no_sql_servers(self): sqlserver_client = mock.MagicMock sqlserver_client.sql_servers = {}