diff --git a/docs/CHANGELOG-v1.md b/docs/CHANGELOG-v1.md index 4304ba9d8be..555d649ce04 100644 --- a/docs/CHANGELOG-v1.md +++ b/docs/CHANGELOG-v1.md @@ -39,6 +39,12 @@ See [upgrade notes][1] for helpful information when upgrading from previous vers - Virtual Machine Scale Sets: - Check that automatic instance repairs are enabled by @BenjaminEngeset. [#2895](https://github.com/Azure/PSRule.Rules.Azure/issues/2895) +- Updated rules: + - Azure MySQL: + - Updated `Azure.MySQL.DefenderCloud` to support flexible servers by @BenjaminEngeset. + [#2904](https://github.com/Azure/PSRule.Rules.Azure/issues/2904) + - Added check for Microsoft Defender for Cloud for Azure Database for MySQL for the flexible deployment model. + - Bumped rule set to `2024_06`. - Engineering: - Bump xunit to v2.8.1. [#2892](https://github.com/Azure/PSRule.Rules.Azure/pull/2892) diff --git a/docs/en/rules/Azure.MySQL.DefenderCloud.md b/docs/en/rules/Azure.MySQL.DefenderCloud.md index 4b8ec498682..d9f0585e5f1 100644 --- a/docs/en/rules/Azure.MySQL.DefenderCloud.md +++ b/docs/en/rules/Azure.MySQL.DefenderCloud.md @@ -1,7 +1,8 @@ --- +reviewed: 2024-06-01 severity: Important pillar: Security -category: Security operations +category: SE:10 Monitoring and threat detection resource: Azure Database for MySQL online version: https://azure.github.io/PSRule.Rules.Azure/en/rules/Azure.MySQL.DefenderCloud/ --- @@ -14,7 +15,8 @@ Enable Microsoft Defender for Cloud for Azure Database for MySQL. ## DESCRIPTION -Defender for Cloud detects anomalous activities indicating unusual and potentially harmful attempts to access or exploit databases. +Microsoft Defender for Cloud detects anomalous activities that may indicate unusual and potentially harmful attempts to access or exploit your databases. +It provides advanced threat protection for your Azure Database for MySQL, helping to safeguard your data and maintain compliance. ## RECOMMENDATION @@ -123,12 +125,17 @@ resource mysqlDefender 'Microsoft.DBforMySQL/servers/securityAlertPolicies@2017- ## NOTES -This rule is only applicable for the Azure Database for MySQL Single Server deployment model. +For the Azure Database for MySQL Flexible Server deployment model, enabling Microsoft Defender for Cloud is handled differently as the `Microsoft.DBforMySQL/flexibleServers/advancedThreatProtectionSettings` resource is read-only. +It can be enabled through either of the following methods: -Azure Database for MySQL Flexible Server deployment model does not currently support Microsoft Defender for Cloud. +- Subscription Level Enablement: Enable the `open-source relational databases` resource type under the Microsoft Defender for Cloud Databases plan for the subscription where the server is located. +- Resource Level Enablement: Manually enable Microsoft Defender for Cloud for the specific resource via the Azure portal under the resource blade. ## LINKS -- [Security operations](https://learn.microsoft.com/azure/architecture/framework/security/security-operations) -- [Enable Microsoft Defender for open-source relational databases](https://learn.microsoft.com/azure/defender-for-cloud/defender-for-databases-usage) -- [Azure deployment reference](https://learn.microsoft.com/azure/templates/microsoft.dbformysql/servers/securityalertpolicies) +- [SE:10 Monitoring and threat detection](https://learn.microsoft.com/en-us/azure/well-architected/security/monitor-threats) +- [Azure security baseline for Azure Database for MySQL - Flexible Server](https://learn.microsoft.com/security/benchmark/azure/baselines/azure-database-for-mysql-flexible-server-security-baseline) +- [LT-1: Enable threat detection capabilities](https://learn.microsoft.com/security/benchmark/azure/baselines/azure-database-for-mysql-flexible-server-security-baseline#lt-1-enable-threat-detection-capabilities) +- [Enable Microsoft Defender for open-source relational databases](https://learn.microsoft.com/azure/defender-for-cloud/enable-defender-for-databases-azure) +- [Azure resource deployment](https://learn.microsoft.com/azure/templates/microsoft.dbformysql/flexibleservers/advancedthreatprotectionsettings) +- [Azure resource deployment](https://learn.microsoft.com/azure/templates/microsoft.dbformysql/servers/securityalertpolicies) diff --git a/src/PSRule.Rules.Azure/rules/Azure.MySQL.Rule.ps1 b/src/PSRule.Rules.Azure/rules/Azure.MySQL.Rule.ps1 index 19393a7fcb1..1089f4d826a 100644 --- a/src/PSRule.Rules.Azure/rules/Azure.MySQL.Rule.ps1 +++ b/src/PSRule.Rules.Azure/rules/Azure.MySQL.Rule.ps1 @@ -61,7 +61,8 @@ Rule 'Azure.MySQL.UseFlexible' -Ref 'AZR-000325' -Type 'Microsoft.DBforMySQL/fle } # Synopsis: Enable Microsoft Defender for Cloud for Azure Database for MySQL. -Rule 'Azure.MySQL.DefenderCloud' -Ref 'AZR-000328' -Type 'Microsoft.DBforMySQL/servers', 'Microsoft.DBforMySQL/servers/securityAlertPolicies' -Tag @{ release = 'GA'; ruleSet = '2022_12'; 'Azure.WAF/pillar' = 'Security'; } { +Rule 'Azure.MySQL.DefenderCloud' -Ref 'AZR-000328' -Type 'Microsoft.DBforMySQL/servers', 'Microsoft.DBforMySQL/servers/securityAlertPolicies', 'Microsoft.DBforMySQL/flexibleServers/advancedThreatProtectionSettings' -Tag @{ release = 'GA'; ruleSet = '2024_06'; 'Azure.WAF/pillar' = 'Security'; } -Labels @{ 'Azure.MCSB.v1/control' = 'LT-1' } { + # Single server deployment model if ($PSRule.TargetType -eq 'Microsoft.DBforMySQL/servers') { $defenderConfigs = @(GetSubResources -ResourceType 'Microsoft.DBforMySQL/servers/securityAlertPolicies') if ($defenderConfigs.Length -eq 0) { @@ -75,6 +76,12 @@ Rule 'Azure.MySQL.DefenderCloud' -Ref 'AZR-000328' -Type 'Microsoft.DBforMySQL/s elseif ($PSRule.TargetType -eq 'Microsoft.DBforMySQL/servers/securityAlertPolicies') { $Assert.HasFieldValue($TargetObject, 'properties.state', 'Enabled') } + + # Flexible server deployment model, only export as this resource type is read-only. + # The Sub-resource when exported is not under the resources property of the parent resource. + elseif ($PSRule.TargetType -eq 'Microsoft.DBforMySQL/flexibleServers/advancedThreatProtectionSettings' -and (IsExport)) { + $Assert.HasFieldValue($TargetObject, 'properties.state', 'Enabled') + } } # Synopsis: Use Azure Active Directory (AAD) authentication with Azure Database for MySQL databases. diff --git a/tests/PSRule.Rules.Azure.Tests/Azure.MySQL.Tests.ps1 b/tests/PSRule.Rules.Azure.Tests/Azure.MySQL.Tests.ps1 index 9ac16f73c32..086ac50184d 100644 --- a/tests/PSRule.Rules.Azure.Tests/Azure.MySQL.Tests.ps1 +++ b/tests/PSRule.Rules.Azure.Tests/Azure.MySQL.Tests.ps1 @@ -148,18 +148,17 @@ Describe 'Azure.MySQL' -Tag 'MySql' { # Fail $ruleResult = @($filteredResult | Where-Object { $_.Outcome -eq 'Fail' }); - $ruleResult | Should -Not -BeNullOrEmpty; - $ruleResult.Length | Should -Be 2; - $ruleResult.TargetName | Should -BeIn 'server-A', 'server-B'; + $ruleResult.Length | Should -Be 3; + $ruleResult.TargetName | Should -BeIn 'server-A', 'server-B', 'server-F/Default'; $ruleResult[0].Reason | Should -BeExactly "A sub-resource of type 'Microsoft.DBforMySQL/servers/securityAlertPolicies' has not been specified."; $ruleResult[1].Reason | Should -BeExactly "Path resources.properties.state: Is set to 'Disabled'."; + $ruleResult[2].Reason | Should -BeExactly "Path properties.state: Is set to 'Disabled'."; # Pass $ruleResult = @($filteredResult | Where-Object { $_.Outcome -eq 'Pass' }); - $ruleResult | Should -Not -BeNullOrEmpty; - $ruleResult.Length | Should -Be 1; - $ruleResult.TargetName | Should -BeIn 'server-C'; + $ruleResult.Length | Should -Be 2; + $ruleResult.TargetName | Should -BeIn 'server-C', 'server-E/Default'; } It 'Azure.MySQL.UseFlexible' { diff --git a/tests/PSRule.Rules.Azure.Tests/Resources.MySQL.json b/tests/PSRule.Rules.Azure.Tests/Resources.MySQL.json index acee20e9cfa..46c83e7c813 100644 --- a/tests/PSRule.Rules.Azure.Tests/Resources.MySQL.json +++ b/tests/PSRule.Rules.Azure.Tests/Resources.MySQL.json @@ -580,5 +580,33 @@ "value": "ON", "source": "user-override" } + }, + { + "ResourceId": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.DBforMySQL/flexibleServers/server-F/advancedThreatProtectionSettings/Default", + "ResourceName": "server-F/Default", + "Name": "server-F/Default", + "ResourceType": "Microsoft.DBforMySQL/flexibleServers/advancedThreatProtectionSettings", + "Kind": null, + "ResourceGroupName": "test-rg", + "Location": "region", + "SubscriptionId": "00000000-0000-0000-0000-000000000000", + "Tags": null, + "properties": { + "state": "Disabled" + } + }, + { + "ResourceId": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.DBforMySQL/flexibleServers/server-E/advancedThreatProtectionSettings/Default", + "Name": "server-E/Default", + "ResourceName": "server-E/Default", + "ResourceType": "Microsoft.DBforMySQL/flexibleServers/advancedThreatProtectionSettings", + "Kind": null, + "ResourceGroupName": "test-rg", + "Location": "region", + "SubscriptionId": "00000000-0000-0000-0000-000000000000", + "Tags": null, + "properties": { + "state": "Enabled" + } } ]