From d522234a03481db3dc5c650d0cb899468c6100d4 Mon Sep 17 00:00:00 2001 From: Bernie White Date: Fri, 7 Mar 2025 03:19:36 +1000 Subject: [PATCH] Updated minimum TLS for App Service #3269 (#3275) --- data/policy-ignore.json | 10 ++ docs/CHANGELOG-v1.md | 6 ++ docs/en/rules/Azure.ACR.AnonymousAccess.md | 2 +- docs/en/rules/Azure.AppService.MinTLS.md | 93 +++++++++++-------- .../rules/Azure.ImageBuilder.CustomizeHash.md | 2 +- .../rules/Azure.ImageBuilder.ValidateHash.md | 2 +- docs/examples/resources/appservice.bicep | 12 +-- docs/examples/resources/appservice.json | 16 ++-- .../rules/Azure.AppService.Rule.ps1 | 12 +-- .../PolicyAssignmentVisitorTests.cs | 2 +- .../Resources.AppService.json | 2 +- 11 files changed, 94 insertions(+), 65 deletions(-) diff --git a/data/policy-ignore.json b/data/policy-ignore.json index 6a6d26c8ba1..69e7220283a 100644 --- a/data/policy-ignore.json +++ b/data/policy-ignore.json @@ -304,5 +304,15 @@ ], "reason": "Duplicate", "value": "Azure.ACR.AnonymousAccess" + }, + { + "policyDefinitionIds": [ + "/providers/Microsoft.Authorization/policyDefinitions/f0e6e85b-9b9f-4a4b-b67b-f730d42f1b0b", + "/providers/Microsoft.Authorization/policyDefinitions/4ee5b817-627a-435a-8932-116193268172", + "/providers/Microsoft.Authorization/policyDefinitions/ae44c1d1-0df2-4ca9-98fa-a3d3ae5b409d", + "/providers/Microsoft.Authorization/policyDefinitions/014664e7-e348-41a3-aeb9-566e4ff6a9df" + ], + "reason": "Duplicate", + "value": "Azure.AppService.MinTLS" } ] diff --git a/docs/CHANGELOG-v1.md b/docs/CHANGELOG-v1.md index de5c2f2ed78..dc184850260 100644 --- a/docs/CHANGELOG-v1.md +++ b/docs/CHANGELOG-v1.md @@ -35,9 +35,15 @@ What's changed since v1.41.4: - Image Builder: - Check that image builder build and validation scripts are pinned by @BernieWhite. [#2903](https://github.com/Azure/PSRule.Rules.Azure/issues/2903) +- Updated rules: + - App Service: + - Updated `Azure.AppService.MinTLS` to include TLS 1.3 as a valid minimum version by @BernieWhite. + [#3269](https://github.com/Azure/PSRule.Rules.Azure/issues/3269) - General improvements: - Added a new quickstart guide for using Azure Pipelines with PSRule by @that-ar-guy. [#3220](https://github.com/Azure/PSRule.Rules.Azure/pull/3220) + - Added additional exclusions to policies for `Azure.AppService.MinTLS` by @BernieWhite. + [#1731](https://github.com/Azure/PSRule.Rules.Azure/issues/1731) - Engineering: - Updates to WAF documentation by @BernieWhite. [#2570](https://github.com/Azure/PSRule.Rules.Azure/issues/2570) diff --git a/docs/en/rules/Azure.ACR.AnonymousAccess.md b/docs/en/rules/Azure.ACR.AnonymousAccess.md index 2b7ed33451a..72429a1d33a 100644 --- a/docs/en/rules/Azure.ACR.AnonymousAccess.md +++ b/docs/en/rules/Azure.ACR.AnonymousAccess.md @@ -7,7 +7,7 @@ resource: Container Registry online version: https://azure.github.io/PSRule.Rules.Azure/en/rules/Azure.ACR.AnonymousAccess/ --- -# Container registry anonymous pull access is enabled +# Container Registry anonymous pull access is enabled ## SYNOPSIS diff --git a/docs/en/rules/Azure.AppService.MinTLS.md b/docs/en/rules/Azure.AppService.MinTLS.md index 47dc9cc7940..f19b5bcecc3 100644 --- a/docs/en/rules/Azure.AppService.MinTLS.md +++ b/docs/en/rules/Azure.AppService.MinTLS.md @@ -1,4 +1,5 @@ --- +reviewed: 2025-03-07 severity: Critical pillar: Security category: SE:07 Encryption @@ -7,7 +8,7 @@ online version: https://azure.github.io/PSRule.Rules.Azure/en/rules/Azure.AppSer ms-content-id: e19fbe7e-da05-47d4-8de1-2fdf52ada662 --- -# Use secure protocols for App Service +# App Service site allows insecure TLS versions ## SYNOPSIS @@ -28,11 +29,52 @@ Also consider using Azure Policy to audit or enforce this configuration. ## EXAMPLES +### Configure with Bicep + +To deploy App Services that pass this rule: + +- Set the `properties.siteConfig.minTlsVersion` property to `1.2` or `1.3`. + +For example: + +```bicep +resource web 'Microsoft.Web/sites@2024-04-01' = { + name: name + location: location + identity: { + type: 'SystemAssigned' + } + kind: 'web' + properties: { + serverFarmId: plan.id + httpsOnly: true + clientAffinityEnabled: false + siteConfig: { + alwaysOn: true + minTlsVersion: '1.2' + ftpsState: 'Disabled' + remoteDebuggingEnabled: false + http20Enabled: true + netFrameworkVersion: 'v8.0' + healthCheckPath: '/healthz' + metadata: [ + { + name: 'CURRENT_STACK' + value: 'dotnet' + } + ] + } + } +} +``` + + + ### Configure with Azure template To deploy App Services that pass this rule: -- Set the `properties.siteConfig.minTlsVersion` property to `1.2`. +- Set the `properties.siteConfig.minTlsVersion` property to `1.2` or `1.3`. For example: @@ -71,45 +113,18 @@ For example: } ``` -### Configure with Bicep - -To deploy App Services that pass this rule: - -- Set the `properties.siteConfig.minTlsVersion` property to `1.2`. +### Configure with Azure Policy -For example: - -```bicep -resource web 'Microsoft.Web/sites@2023-01-01' = { - name: name - location: location - identity: { - type: 'SystemAssigned' - } - kind: 'web' - properties: { - serverFarmId: plan.id - httpsOnly: true - siteConfig: { - alwaysOn: true - minTlsVersion: '1.2' - ftpsState: 'Disabled' - remoteDebuggingEnabled: false - http20Enabled: true - netFrameworkVersion: 'v8.0' - healthCheckPath: '/healthz' - metadata: [ - { - name: 'CURRENT_STACK' - value: 'dotnet' - } - ] - } - } -} -``` +To address this issue at runtime use the following policies: - +- [App Service apps should use the latest TLS version](https://github.com/Azure/azure-policy/blob/master/built-in-policies/policyDefinitions/App%20Service/RequireLatestTls_WebApp_Audit.json) + `/providers/Microsoft.Authorization/policyDefinitions/f0e6e85b-9b9f-4a4b-b67b-f730d42f1b0b`. +- [App Service app slots should use the latest TLS version](https://github.com/Azure/azure-policy/blob/master/built-in-policies/policyDefinitions/App%20Service/RequireLatestTls_WebApp_Slot_Audit.json) + `/providers/Microsoft.Authorization/policyDefinitions/4ee5b817-627a-435a-8932-116193268172`. +- [Configure App Service apps to use the latest TLS version](https://github.com/Azure/azure-policy/blob/master/built-in-policies/policyDefinitions/App%20Service/RequireLatestTls_WebApp_DINE.json) + `/providers/Microsoft.Authorization/policyDefinitions/ae44c1d1-0df2-4ca9-98fa-a3d3ae5b409d`. +- [Configure App Service app slots to use the latest TLS version](https://github.com/Azure/azure-policy/blob/master/built-in-policies/policyDefinitions/App%20Service/RequireLatestTls_WebApp_Slot_DINE.json) + `/providers/Microsoft.Authorization/policyDefinitions/014664e7-e348-41a3-aeb9-566e4ff6a9df`. ## LINKS diff --git a/docs/en/rules/Azure.ImageBuilder.CustomizeHash.md b/docs/en/rules/Azure.ImageBuilder.CustomizeHash.md index 43e305c9357..ea9f428f003 100644 --- a/docs/en/rules/Azure.ImageBuilder.CustomizeHash.md +++ b/docs/en/rules/Azure.ImageBuilder.CustomizeHash.md @@ -3,7 +3,7 @@ reviewed: 2025-03-06 severity: Important pillar: Security category: SE:02 Secured development lifecycle -resource: Image Builder +resource: VM Image Builder online version: https://azure.github.io/PSRule.Rules.Azure/en/rules/Azure.ImageBuilder.CustomizeHash/ --- diff --git a/docs/en/rules/Azure.ImageBuilder.ValidateHash.md b/docs/en/rules/Azure.ImageBuilder.ValidateHash.md index df76a8096ac..1999677edb4 100644 --- a/docs/en/rules/Azure.ImageBuilder.ValidateHash.md +++ b/docs/en/rules/Azure.ImageBuilder.ValidateHash.md @@ -3,7 +3,7 @@ reviewed: 2025-03-06 severity: Important pillar: Security category: SE:02 Secured development lifecycle -resource: Image Builder +resource: VM Image Builder online version: https://azure.github.io/PSRule.Rules.Azure/en/rules/Azure.ImageBuilder.ValidateHash/ --- diff --git a/docs/examples/resources/appservice.bicep b/docs/examples/resources/appservice.bicep index 1579a9aa989..70b0e71401c 100644 --- a/docs/examples/resources/appservice.bicep +++ b/docs/examples/resources/appservice.bicep @@ -13,7 +13,7 @@ param planName string param location string = resourceGroup().location // An example App Services Plan. -resource plan 'Microsoft.Web/serverfarms@2023-01-01' = { +resource plan 'Microsoft.Web/serverfarms@2024-04-01' = { name: planName location: location sku: { @@ -26,7 +26,7 @@ resource plan 'Microsoft.Web/serverfarms@2023-01-01' = { } // An example .NET Framework Web App running on a Windows App Services Plan. -resource web 'Microsoft.Web/sites@2023-01-01' = { +resource web 'Microsoft.Web/sites@2024-04-01' = { name: name location: location identity: { @@ -56,7 +56,7 @@ resource web 'Microsoft.Web/sites@2023-01-01' = { } // An example PHP Web App running on a Linux App Services Plan. -resource php 'Microsoft.Web/sites@2023-01-01' = { +resource php 'Microsoft.Web/sites@2024-04-01' = { name: name location: location identity: { @@ -79,7 +79,7 @@ resource php 'Microsoft.Web/sites@2023-01-01' = { } // Disable basic publishing credentials for FTP. -resource ftp 'Microsoft.Web/sites/basicPublishingCredentialsPolicies@2023-01-01' = { +resource ftp 'Microsoft.Web/sites/basicPublishingCredentialsPolicies@2024-04-01' = { parent: web name: 'ftp' properties: { @@ -88,7 +88,7 @@ resource ftp 'Microsoft.Web/sites/basicPublishingCredentialsPolicies@2023-01-01' } // Disable basic publishing credentials over SCM. -resource scm 'Microsoft.Web/sites/basicPublishingCredentialsPolicies@2023-01-01' = { +resource scm 'Microsoft.Web/sites/basicPublishingCredentialsPolicies@2024-04-01' = { parent: web name: 'scm' properties: { @@ -97,7 +97,7 @@ resource scm 'Microsoft.Web/sites/basicPublishingCredentialsPolicies@2023-01-01' } // An example PHP Web App -resource webAppPHP 'Microsoft.Web/sites@2023-01-01' = { +resource webAppPHP 'Microsoft.Web/sites@2024-04-01' = { name: name location: location identity: { diff --git a/docs/examples/resources/appservice.json b/docs/examples/resources/appservice.json index 811e0f7bc57..2c5f2f8258d 100644 --- a/docs/examples/resources/appservice.json +++ b/docs/examples/resources/appservice.json @@ -4,8 +4,8 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.26.54.24096", - "templateHash": "10435733640424545318" + "version": "0.33.93.31351", + "templateHash": "12567330257424459921" } }, "parameters": { @@ -32,7 +32,7 @@ "resources": [ { "type": "Microsoft.Web/serverfarms", - "apiVersion": "2023-01-01", + "apiVersion": "2024-04-01", "name": "[parameters('planName')]", "location": "[parameters('location')]", "sku": { @@ -45,7 +45,7 @@ }, { "type": "Microsoft.Web/sites", - "apiVersion": "2023-01-01", + "apiVersion": "2024-04-01", "name": "[parameters('name')]", "location": "[parameters('location')]", "identity": { @@ -78,7 +78,7 @@ }, { "type": "Microsoft.Web/sites", - "apiVersion": "2023-01-01", + "apiVersion": "2024-04-01", "name": "[parameters('name')]", "location": "[parameters('location')]", "identity": { @@ -104,7 +104,7 @@ }, { "type": "Microsoft.Web/sites/basicPublishingCredentialsPolicies", - "apiVersion": "2023-01-01", + "apiVersion": "2024-04-01", "name": "[format('{0}/{1}', parameters('name'), 'ftp')]", "properties": { "allow": false @@ -115,7 +115,7 @@ }, { "type": "Microsoft.Web/sites/basicPublishingCredentialsPolicies", - "apiVersion": "2023-01-01", + "apiVersion": "2024-04-01", "name": "[format('{0}/{1}', parameters('name'), 'scm')]", "properties": { "allow": false @@ -126,7 +126,7 @@ }, { "type": "Microsoft.Web/sites", - "apiVersion": "2023-01-01", + "apiVersion": "2024-04-01", "name": "[parameters('name')]", "location": "[parameters('location')]", "identity": { diff --git a/src/PSRule.Rules.Azure/rules/Azure.AppService.Rule.ps1 b/src/PSRule.Rules.Azure/rules/Azure.AppService.Rule.ps1 index c9ac13fdc8c..1807b4dda5b 100644 --- a/src/PSRule.Rules.Azure/rules/Azure.AppService.Rule.ps1 +++ b/src/PSRule.Rules.Azure/rules/Azure.AppService.Rule.ps1 @@ -10,19 +10,17 @@ Rule 'Azure.AppService.PlanInstanceCount' -Ref 'AZR-000071' -Type 'Microsoft.Web $Assert.GreaterOrEqual($TargetObject, 'sku.capacity', 2); } -# Synopsis: App Service should reject TLS versions older than 1.2. +# Synopsis: App Service should not accept weak or deprecated transport protocols for client-server communication. Rule 'Azure.AppService.MinTLS' -Ref 'AZR-000073' -Type 'Microsoft.Web/sites', 'Microsoft.Web/sites/slots' -Tag @{ release = 'GA'; ruleSet = '2020_06'; 'Azure.WAF/pillar' = 'Security'; } -Labels @{ 'Azure.MCSB.v1/control' = 'DP-3' } { $siteConfigs = @(GetWebSiteConfig); if ($siteConfigs.Length -eq 0) { - return $Assert. - HasFieldValue($TargetObject, 'properties.siteConfig.minTlsVersion', '1.2'). - ReasonFrom('properties.siteConfig.minTlsVersion', $LocalizedData.MinTLSVersion, $TargetObject.properties.siteConfig.minTlsVersion); + return $Assert.Version($TargetObject, 'properties.siteConfig.minTlsVersion', '>=1.2'). + ReasonFrom('properties.siteConfig.minTlsVersion', $LocalizedData.MinTLSVersion, $TargetObject.properties.siteConfig.minTlsVersion); } foreach ($siteConfig in $siteConfigs) { $path = $siteConfig._PSRule.path; - $Assert. - HasFieldValue($siteConfig, 'properties.minTlsVersion', '1.2'). - ReasonFrom('properties.minTlsVersion', $LocalizedData.MinTLSVersion, $siteConfig.properties.minTlsVersion).PathPrefix($path); + $Assert.Version($siteConfig, 'properties.minTlsVersion', '>=1.2'). + ReasonFrom('properties.minTlsVersion', $LocalizedData.MinTLSVersion, $siteConfig.properties.minTlsVersion).PathPrefix($path); } } diff --git a/tests/PSRule.Rules.Azure.Tests/PolicyAssignmentVisitorTests.cs b/tests/PSRule.Rules.Azure.Tests/PolicyAssignmentVisitorTests.cs index add0d5f28b7..9e9d8656c04 100644 --- a/tests/PSRule.Rules.Azure.Tests/PolicyAssignmentVisitorTests.cs +++ b/tests/PSRule.Rules.Azure.Tests/PolicyAssignmentVisitorTests.cs @@ -94,7 +94,7 @@ public void GetPolicyDefinitionWithIgnore() var definitions = context.GetDefinitions(); Assert.NotNull(definitions); - Assert.Equal(111, definitions.Length); + Assert.Equal(110, definitions.Length); // Check category and version var actual = definitions.FirstOrDefault(definition => definition.DefinitionId == "/providers/Microsoft.Authorization/policyDefinitions/34c877ad-507e-4c82-993e-3452a6e0ad3c"); diff --git a/tests/PSRule.Rules.Azure.Tests/Resources.AppService.json b/tests/PSRule.Rules.Azure.Tests/Resources.AppService.json index 740d8ba432c..d74616ed6fb 100644 --- a/tests/PSRule.Rules.Azure.Tests/Resources.AppService.json +++ b/tests/PSRule.Rules.Azure.Tests/Resources.AppService.json @@ -536,7 +536,7 @@ ], "scmIpSecurityRestrictionsUseMain": false, "http20Enabled": true, - "minTlsVersion": "1.2", + "minTlsVersion": "1.3", "ftpsState": "FtpsOnly", "reservedInstanceCount": 0, "preWarmedInstanceCount": null,