diff --git a/CHANGELOG.md b/CHANGELOG.md index 980701e781d..9fd96a9d972 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,9 @@ ## Unreleased - Excluded global services from Azure.Resource.AllowedRegions. [#96](https://github.com/BernieWhite/PSRule.Rules.Azure/issues/96) +- Enforce minimum TLS version for App Service. [#99](https://github.com/BernieWhite/PSRule.Rules.Azure/issues/99) +- Updated App Service site rules to include slots. [#100](https://github.com/BernieWhite/PSRule.Rules.Azure/issues/100) + - `Azure.AppService.ARRAffinity` and `Azure.AppService.UseHTTPS` now run against slots. ## v0.3.0-B190710 (pre-release) diff --git a/docs/rules/en-US/Azure.AppService.MinTLS.md b/docs/rules/en-US/Azure.AppService.MinTLS.md new file mode 100644 index 00000000000..eef2ed8d3cc --- /dev/null +++ b/docs/rules/en-US/Azure.AppService.MinTLS.md @@ -0,0 +1,23 @@ +--- +severity: Important +category: Security configuration +online version: https://github.com/BernieWhite/PSRule.Rules.Azure/blob/master/docs/rules/en-US/Azure.AppService.MinTLS.md +--- + +# Use minimum TLS version + +## SYNOPSIS + +App Service should reject TLS versions older then 1.2. + +## DESCRIPTION + +The minimum version of TLS that Azure App Service accepts is configurable. Older TLS versions are no longer considered secure by industry standards, such as PCI DSS. + +App Service lets you disable outdated protocols and enforce TLS 1.2. By default use of a minimum of TLS 1.2 is enforced. + +## RECOMMENDATION + +Consider configuring the minimum supported TLS version to be 1.2. + +For more information see [Enforce TLS versions](https://docs.microsoft.com/en-us/Azure/app-service/app-service-web-tutorial-custom-ssl#enforce-tls-versions) and [insecure protocols](https://docs.microsoft.com/en-us/Azure/app-service/overview-security#insecure-protocols-http-tls-10-ftp). diff --git a/docs/scenarios/install-instructions.md b/docs/scenarios/install-instructions.md index a831a8b4163..7f31476beb5 100644 --- a/docs/scenarios/install-instructions.md +++ b/docs/scenarios/install-instructions.md @@ -14,7 +14,6 @@ The following modules are required for `PSRule.Rules.Azure` to work: - Az.Resources - Az.Security - Az.Storage -- Az.Websites The required version of each module will automatically be installed along-side `PSRule.Rules.Azure` when using `Install-Module` or `Update-Module` cmdlets. @@ -38,7 +37,7 @@ Save for offline use from PowerShell Gallery: ```powershell # Save module, in the .\modules directory -Save-Module -Name 'PSRule', 'PSRule.Rules.Azure', 'Az.Accounts', 'Az.Resources', 'Az.Security', 'Az.Storage', 'Az.Websites' -Path '.\modules'; +Save-Module -Name 'PSRule', 'PSRule.Rules.Azure', 'Az.Accounts', 'Az.Resources', 'Az.Security', 'Az.Storage' -Path '.\modules'; ``` > For pre-release versions the `-AllowPrerelease` switch must be added when calling `Install-Module` or `Save-Module`. diff --git a/pipeline.build.ps1 b/pipeline.build.ps1 index 4c4027f0316..374ddaf3f8f 100644 --- a/pipeline.build.ps1 +++ b/pipeline.build.ps1 @@ -144,8 +144,8 @@ task PSScriptAnalyzer NuGet, { # Synopsis: Install PSRule task PSRule NuGet, { - if ($Null -eq (Get-InstalledModule -Name PSRule -MinimumVersion 0.7.0 -ErrorAction Ignore)) { - Install-Module -Name PSRule -MinimumVersion 0.7.0 -AllowPrerelease -Scope CurrentUser -Force; + if ($Null -eq (Get-InstalledModule -Name PSRule -MinimumVersion 0.8.0-B190716 -AllowPrerelease -ErrorAction Ignore)) { + Install-Module -Name PSRule -MinimumVersion 0.8.0-B190716 -AllowPrerelease -Scope CurrentUser -Force; } Import-Module -Name PSRule -Verbose:$False; } @@ -180,9 +180,6 @@ task ModuleDependencies NuGet, PSRule, { if ($Null -eq (Get-InstalledModule -Name Az.Storage -MinimumVersion 1.3.0 -ErrorAction Ignore)) { Install-Module -Name Az.Storage -Scope CurrentUser -MinimumVersion 1.3.0 -Force -AllowClobber; } - if ($Null -eq (Get-InstalledModule -Name Az.Websites -MinimumVersion 1.2.1 -ErrorAction Ignore)) { - Install-Module -Name Az.Websites -Scope CurrentUser -MinimumVersion 1.2.1 -Force; - } } task CopyModule { diff --git a/src/PSRule.Rules.Azure/PSRule.Rules.Azure.psd1 b/src/PSRule.Rules.Azure/PSRule.Rules.Azure.psd1 index ed348f8ee52..6e74d79863f 100644 --- a/src/PSRule.Rules.Azure/PSRule.Rules.Azure.psd1 +++ b/src/PSRule.Rules.Azure/PSRule.Rules.Azure.psd1 @@ -54,7 +54,6 @@ RequiredModules = @( @{ ModuleName = 'Az.Resources'; ModuleVersion = '1.4.0' } @{ ModuleName = 'Az.Security'; ModuleVersion = '0.7.4' } @{ ModuleName = 'Az.Storage'; ModuleVersion = '1.3.0' } - @{ ModuleName = 'Az.Websites'; ModuleVersion = '1.2.1' } ) # Assemblies that must be loaded prior to importing this module @@ -97,9 +96,7 @@ AliasesToExport = @() # Private data to pass to the module specified in RootModule/ModuleToProcess. This may also contain a PSData hashtable with additional module metadata used by PowerShell. PrivateData = @{ - PSData = @{ - # Tags applied to this module. These help with module discovery in online galleries. Tags = @('Rule', 'PSRule', 'Azure') @@ -114,7 +111,6 @@ PrivateData = @{ # ReleaseNotes of this module ReleaseNotes = 'https://github.com/BernieWhite/PSRule.Rules.Azure/blob/master/CHANGELOG.md' - } # End of PSData hashtable } # End of PrivateData hashtable diff --git a/src/PSRule.Rules.Azure/PSRule.Rules.Azure.psm1 b/src/PSRule.Rules.Azure/PSRule.Rules.Azure.psm1 index 91a0df7f5f4..43d29cf4685 100644 --- a/src/PSRule.Rules.Azure/PSRule.Rules.Azure.psm1 +++ b/src/PSRule.Rules.Azure/PSRule.Rules.Azure.psm1 @@ -364,9 +364,15 @@ function VisitWebApp { process { $resources = @(); + $configResourceType = 'Microsoft.Web/sites/config'; - $resources += Get-AzWebApp -ResourceGroupName $Resource.ResourceGroupName -Name $Resource.Name -DefaultProfile $Context; - $resource | Add-Member -MemberType NoteProperty -Name resources -Value $resources -PassThru; + # Handle slots + if ($Resource.ResourceType -eq 'Microsoft.Web/sites/slots') { + $configResourceType = 'Microsoft.Web/sites/slots/config'; + } + + $resources += Get-AzResource -Name $Resource.Name -ResourceType $configResourceType -ResourceGroupName $Resource.ResourceGroupName -DefaultProfile $Context -ApiVersion '2018-11-01' -ExpandProperties; + $Resource | Add-Member -MemberType NoteProperty -Name resources -Value $resources -PassThru; } } @@ -445,7 +451,8 @@ function ExpandResource { "Microsoft.DataFactory/factories" { VisitDataFactoryV2 @PSBoundParameters; } # "Microsoft.Storage/storageAccounts" { VisitStorageAccount @PSBoundParameters; } # "Microsoft.StorageSync/storageSyncServices" { VisitStorageSyncService @PSBoundParameters; } - # "Microsoft.Web/sites" { VisitWebApp @PSBoundParameters; } + "Microsoft.Web/sites" { VisitWebApp @PSBoundParameters; } + "Microsoft.Web/sites/slots" { VisitWebApp @PSBoundParameters; } "Microsoft.RecoveryServices/vaults" { VisitRecoveryServices @PSBoundParameters; } "Microsoft.Compute/virtualMachines" { VisitVirtualMachine @PSBoundParameters; } "Microsoft.Subscription" { VisitSubscription @PSBoundParameters; } diff --git a/src/PSRule.Rules.Azure/en-AU/PSRule-rules.psd1 b/src/PSRule.Rules.Azure/en-AU/PSRule-rules.psd1 new file mode 100644 index 00000000000..ea3195f88a1 --- /dev/null +++ b/src/PSRule.Rules.Azure/en-AU/PSRule-rules.psd1 @@ -0,0 +1,5 @@ +@{ + MinTLSVersion = "Minimum TLS version is set to {0}." + ResourceNotTagged = "The resource is not tagged." + AllowedRegionsNotConfigured = "The azureAllowedRegions option is not configured." +} diff --git a/src/PSRule.Rules.Azure/en-GB/PSRule-rules.psd1 b/src/PSRule.Rules.Azure/en-GB/PSRule-rules.psd1 new file mode 100644 index 00000000000..ea3195f88a1 --- /dev/null +++ b/src/PSRule.Rules.Azure/en-GB/PSRule-rules.psd1 @@ -0,0 +1,5 @@ +@{ + MinTLSVersion = "Minimum TLS version is set to {0}." + ResourceNotTagged = "The resource is not tagged." + AllowedRegionsNotConfigured = "The azureAllowedRegions option is not configured." +} diff --git a/src/PSRule.Rules.Azure/en-US/PSRule-rules.psd1 b/src/PSRule.Rules.Azure/en-US/PSRule-rules.psd1 new file mode 100644 index 00000000000..ea3195f88a1 --- /dev/null +++ b/src/PSRule.Rules.Azure/en-US/PSRule-rules.psd1 @@ -0,0 +1,5 @@ +@{ + MinTLSVersion = "Minimum TLS version is set to {0}." + ResourceNotTagged = "The resource is not tagged." + AllowedRegionsNotConfigured = "The azureAllowedRegions option is not configured." +} diff --git a/src/PSRule.Rules.Azure/rules/Azure.AppService.Rule.ps1 b/src/PSRule.Rules.Azure/rules/Azure.AppService.Rule.ps1 index 8b58319355c..e101c5ac900 100644 --- a/src/PSRule.Rules.Azure/rules/Azure.AppService.Rule.ps1 +++ b/src/PSRule.Rules.Azure/rules/Azure.AppService.Rule.ps1 @@ -17,15 +17,24 @@ Rule 'Azure.AppService.MinPlan' -If { ResourceType 'Microsoft.Web/serverfarms' } } # Synopsis: Disable client affinity for stateless services -Rule 'Azure.AppService.ARRAffinity' -If { ResourceType 'Microsoft.Web/sites' } -Tag @{ severity = 'Awareness'; category = 'Performance' } { +Rule 'Azure.AppService.ARRAffinity' -If { (ResourceType 'Microsoft.Web/sites') -or (ResourceType 'Microsoft.Web/sites/slots') } -Tag @{ severity = 'Awareness'; category = 'Performance' } { Recommend 'Disable ARR affinity when not required' $TargetObject.Properties.clientAffinityEnabled -eq $False } # Synopsis: Use HTTPS only -Rule 'Azure.AppService.UseHTTPS' -If { ResourceType 'Microsoft.Web/sites' } -Tag @{ severity = 'Important'; category = 'Security configuration' } { +Rule 'Azure.AppService.UseHTTPS' -If { (ResourceType 'Microsoft.Web/sites') -or (ResourceType 'Microsoft.Web/sites/slots') } -Tag @{ severity = 'Important'; category = 'Security configuration' } { Recommend 'Disable HTTP when not required' $TargetObject.Properties.httpsOnly -eq $True } + +# Synopsis: Use at least TLS 1.2 +Rule 'Azure.AppService.MinTLS' -If { (ResourceType 'Microsoft.Web/sites') -or (ResourceType 'Microsoft.Web/sites/slots') } { + $siteConfig = @($TargetObject.resources | Where-Object -FilterScript { + ($_.Type -eq 'Microsoft.Web/sites/config') -or + ($_.Type -eq 'Microsoft.Web/sites/slots/config') + }) + $siteConfig.Properties | Within 'minTlsVersion' '1.2' -Reason ($LocalizedData.MinTLSVersion -f $siteConfig.Properties.minTlsVersion) +} diff --git a/src/PSRule.Rules.Azure/rules/Azure.Resource.Rule.ps1 b/src/PSRule.Rules.Azure/rules/Azure.Resource.Rule.ps1 index 5f65f1db304..5c911b95d54 100644 --- a/src/PSRule.Rules.Azure/rules/Azure.Resource.Rule.ps1 +++ b/src/PSRule.Rules.Azure/rules/Azure.Resource.Rule.ps1 @@ -8,6 +8,7 @@ if ($Null -eq $Configuration.azureAllowedRegions) { # Synopsis: Resources should be tagged Rule 'Azure.Resource.UseTags' -If { (SupportsTags) } -Tag @{ severity = 'Awareness'; category = 'Operations management' } { + Reason $LocalizedData.ResourceNotTagged # List of resource that support tags can be found here: https://docs.microsoft.com/en-us/azure/azure-resource-manager/tag-support (Exists 'Tags') -and (($TargetObject.Tags.PSObject.Members | Where-Object { $_.MemberType -eq 'NoteProperty' }) -ne $Null) diff --git a/tests/PSRule.Rules.Azure.Tests/Azure.AppService.Tests.ps1 b/tests/PSRule.Rules.Azure.Tests/Azure.AppService.Tests.ps1 index de7f81655d7..11c4212e8f9 100644 --- a/tests/PSRule.Rules.Azure.Tests/Azure.AppService.Tests.ps1 +++ b/tests/PSRule.Rules.Azure.Tests/Azure.AppService.Tests.ps1 @@ -64,14 +64,14 @@ Describe 'Azure.AppService' { # Fail $ruleResult = @($filteredResult | Where-Object { $_.Outcome -eq 'Fail' }); $ruleResult | Should -Not -BeNullOrEmpty; - $ruleResult.Length | Should -Be 1; - $ruleResult.TargetName | Should -Be 'site-B'; + $ruleResult.Length | Should -Be 2; + $ruleResult.TargetName | Should -Be 'site-B', 'site-B/staging'; # Pass $ruleResult = @($filteredResult | Where-Object { $_.Outcome -eq 'Pass' }); $ruleResult | Should -Not -BeNullOrEmpty; - $ruleResult.Length | Should -Be 1; - $ruleResult.TargetName | Should -Be 'site-A'; + $ruleResult.Length | Should -Be 2; + $ruleResult.TargetName | Should -Be 'site-A', 'site-A/staging'; } It 'Azure.AppService.UseHTTPS' { @@ -80,14 +80,30 @@ Describe 'Azure.AppService' { # Fail $ruleResult = @($filteredResult | Where-Object { $_.Outcome -eq 'Fail' }); $ruleResult | Should -Not -BeNullOrEmpty; - $ruleResult.Length | Should -Be 1; - $ruleResult.TargetName | Should -Be 'site-B'; + $ruleResult.Length | Should -Be 2; + $ruleResult.TargetName | Should -Be 'site-B', 'site-B/staging'; # Pass $ruleResult = @($filteredResult | Where-Object { $_.Outcome -eq 'Pass' }); $ruleResult | Should -Not -BeNullOrEmpty; - $ruleResult.Length | Should -Be 1; - $ruleResult.TargetName | Should -Be 'site-A'; + $ruleResult.Length | Should -Be 2; + $ruleResult.TargetName | Should -Be 'site-A', 'site-A/staging'; + } + + It 'Azure.AppService.MinTLS' { + $filteredResult = $result | Where-Object { $_.RuleName -eq 'Azure.AppService.MinTLS' }; + + # Fail + $ruleResult = @($filteredResult | Where-Object { $_.Outcome -eq 'Fail' }); + $ruleResult | Should -Not -BeNullOrEmpty; + $ruleResult.Length | Should -Be 2; + $ruleResult.TargetName | Should -Be 'site-B', 'site-B/staging'; + + # Pass + $ruleResult = @($filteredResult | Where-Object { $_.Outcome -eq 'Pass' }); + $ruleResult | Should -Not -BeNullOrEmpty; + $ruleResult.Length | Should -Be 2; + $ruleResult.TargetName | Should -Be 'site-A', 'site-A/staging'; } } } diff --git a/tests/PSRule.Rules.Azure.Tests/Resources.AppService.json b/tests/PSRule.Rules.Azure.Tests/Resources.AppService.json index dc833343dc2..b10c2bd35ff 100644 --- a/tests/PSRule.Rules.Azure.Tests/Resources.AppService.json +++ b/tests/PSRule.Rules.Azure.Tests/Resources.AppService.json @@ -156,7 +156,136 @@ "destinationSlotName": "Production" }, "httpsOnly": true - } + }, + "resources": [ + { + "ResourceId": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.Web/sites/site-A/config/web", + "Id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.Web/sites/site-A/config/web", + "Location": "region", + "ResourceName": "site-A", + "Name": "site-A", + "Properties": { + "numberOfWorkers": 1, + "defaultDocuments": [ + "Default.htm", + "Default.html", + "Default.asp", + "index.htm", + "index.html", + "iisstart.htm", + "default.aspx", + "index.php", + "hostingstart.html" + ], + "netFrameworkVersion": "v4.0", + "phpVersion": "", + "pythonVersion": "", + "nodeVersion": "", + "linuxFxVersion": "", + "windowsFxVersion": null, + "requestTracingEnabled": false, + "remoteDebuggingEnabled": false, + "remoteDebuggingVersion": null, + "httpLoggingEnabled": false, + "logsDirectorySizeLimit": 35, + "detailedErrorLoggingEnabled": false, + "publishingUsername": "$site-A", + "publishingPassword": null, + "appSettings": null, + "metadata": null, + "connectionStrings": null, + "machineKey": null, + "handlerMappings": null, + "documentRoot": null, + "scmType": "VSTSRM", + "use32BitWorkerProcess": true, + "webSocketsEnabled": false, + "alwaysOn": true, + "javaVersion": null, + "javaContainer": null, + "javaContainerVersion": null, + "appCommandLine": "", + "managedPipelineMode": "Integrated", + "virtualApplications": [ + { + "virtualPath": "/", + "physicalPath": "site\\wwwroot", + "preloadEnabled": true, + "virtualDirectories": null + } + ], + "winAuthAdminState": 0, + "winAuthTenantState": 0, + "customAppPoolIdentityAdminState": false, + "customAppPoolIdentityTenantState": false, + "runtimeADUser": null, + "runtimeADUserPassword": null, + "loadBalancing": "LeastRequests", + "routingRules": [], + "experiments": { + "rampUpRules": [] + }, + "limits": null, + "autoHealEnabled": false, + "autoHealRules": null, + "tracingOptions": null, + "vnetName": "", + "siteAuthEnabled": true, + "siteAuthSettings": { + "enabled": null, + "unauthenticatedClientAction": null, + "tokenStoreEnabled": null, + "allowedExternalRedirectUrls": null, + "defaultProvider": null, + "clientId": "00000000-0000-0000-0000-000000000000", + "clientSecret": null, + "clientSecretCertificateThumbprint": null, + "issuer": "https://sts.windows.net/00000000-0000-0000-0000-000000000000", + "allowedAudiences": null, + "additionalLoginParams": null, + "isAadAutoProvisioned": false, + "googleClientId": null, + "googleClientSecret": null, + "googleOAuthScopes": null, + "facebookAppId": null, + "facebookAppSecret": null, + "facebookOAuthScopes": null, + "twitterConsumerKey": null, + "twitterConsumerSecret": null, + "microsoftAccountClientId": null, + "microsoftAccountClientSecret": null, + "microsoftAccountOAuthScopes": null + }, + "cors": null, + "push": null, + "apiDefinition": null, + "apiManagementConfig": null, + "autoSwapSlotName": null, + "localMySqlEnabled": false, + "managedServiceIdentityId": null, + "xManagedServiceIdentityId": null, + "ipSecurityRestrictions": null, + "scmIpSecurityRestrictions": null, + "scmIpSecurityRestrictionsUseMain": null, + "http20Enabled": false, + "minTlsVersion": "1.2", + "ftpsState": "Disabled", + "reservedInstanceCount": 0, + "preWarmedInstanceCount": null, + "healthCheckPath": null + }, + "ResourceGroupName": "test-rg", + "Type": "Microsoft.Web/sites/config", + "ResourceType": "Microsoft.Web/sites/config", + "ExtensionResourceType": null, + "Sku": null, + "Tags": null, + "SubscriptionId": "00000000-0000-0000-0000-000000000000", + "CreatedTime": null, + "ChangedTime": null, + "ETag": null + } + ] }, { "Name": "site-A/staging", @@ -263,7 +392,158 @@ "destinationSlotName": "Production" }, "httpsOnly": true - } + }, + "resources": [ + { + "ResourceId": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.Web/sites/site-A/slots/staging/config/web", + "Id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.Web/sites/site-A/slots/staging/config/web", + "Identity": null, + "Kind": null, + "Location": "region", + "ManagedBy": null, + "ResourceName": "site-A", + "Name": "site-A", + "ExtensionResourceName": null, + "ParentResource": null, + "Plan": null, + "Properties": { + "numberOfWorkers": 1, + "defaultDocuments": [ + "Default.htm", + "Default.html", + "Default.asp", + "index.htm", + "index.html", + "iisstart.htm", + "default.aspx", + "index.php", + "hostingstart.html" + ], + "netFrameworkVersion": "v4.0", + "phpVersion": "", + "pythonVersion": "", + "nodeVersion": "", + "linuxFxVersion": "", + "windowsFxVersion": null, + "requestTracingEnabled": false, + "remoteDebuggingEnabled": false, + "remoteDebuggingVersion": null, + "httpLoggingEnabled": false, + "logsDirectorySizeLimit": 35, + "detailedErrorLoggingEnabled": false, + "publishingUsername": "$site-A__staging", + "publishingPassword": null, + "appSettings": null, + "metadata": null, + "connectionStrings": null, + "machineKey": null, + "handlerMappings": null, + "documentRoot": null, + "scmType": "VSTSRM", + "use32BitWorkerProcess": true, + "webSocketsEnabled": false, + "alwaysOn": true, + "javaVersion": null, + "javaContainer": null, + "javaContainerVersion": null, + "appCommandLine": "", + "managedPipelineMode": "Integrated", + "virtualApplications": [ + { + "virtualPath": "/", + "physicalPath": "site\\wwwroot", + "preloadEnabled": true, + "virtualDirectories": null + } + ], + "winAuthAdminState": 0, + "winAuthTenantState": 0, + "customAppPoolIdentityAdminState": false, + "customAppPoolIdentityTenantState": false, + "runtimeADUser": null, + "runtimeADUserPassword": null, + "loadBalancing": "LeastRequests", + "routingRules": [], + "experiments": { + "rampUpRules": [] + }, + "limits": null, + "autoHealEnabled": false, + "autoHealRules": null, + "tracingOptions": null, + "vnetName": "", + "siteAuthEnabled": true, + "siteAuthSettings": { + "enabled": null, + "unauthenticatedClientAction": null, + "tokenStoreEnabled": null, + "allowedExternalRedirectUrls": null, + "defaultProvider": null, + "clientId": "00000000-0000-0000-0000-000000000000", + "clientSecret": null, + "clientSecretCertificateThumbprint": null, + "issuer": "https://sts.windows.net/00000000-0000-0000-0000-000000000000", + "allowedAudiences": null, + "additionalLoginParams": null, + "isAadAutoProvisioned": false, + "googleClientId": null, + "googleClientSecret": null, + "googleOAuthScopes": null, + "facebookAppId": null, + "facebookAppSecret": null, + "facebookOAuthScopes": null, + "twitterConsumerKey": null, + "twitterConsumerSecret": null, + "microsoftAccountClientId": null, + "microsoftAccountClientSecret": null, + "microsoftAccountOAuthScopes": null + }, + "cors": null, + "push": null, + "apiDefinition": null, + "apiManagementConfig": null, + "autoSwapSlotName": "production", + "localMySqlEnabled": false, + "managedServiceIdentityId": null, + "xManagedServiceIdentityId": null, + "ipSecurityRestrictions": [ + { + "ipAddress": "Any", + "action": "Allow", + "priority": 1, + "name": "Allow all", + "description": "Allow all access" + } + ], + "scmIpSecurityRestrictions": [ + { + "ipAddress": "Any", + "action": "Allow", + "priority": 1, + "name": "Allow all", + "description": "Allow all access" + } + ], + "scmIpSecurityRestrictionsUseMain": false, + "http20Enabled": false, + "minTlsVersion": "1.2", + "ftpsState": "Disabled", + "reservedInstanceCount": 0, + "preWarmedInstanceCount": null, + "healthCheckPath": null + }, + "ResourceGroupName": "test-rg", + "Type": "Microsoft.Web/sites/slots/config", + "ResourceType": "Microsoft.Web/sites/slots/config", + "ExtensionResourceType": null, + "Sku": null, + "Tags": null, + "SubscriptionId": "00000000-0000-0000-0000-000000000000", + "CreatedTime": null, + "ChangedTime": null, + "ETag": null + } + ] }, { "Name": "plan-B", @@ -422,6 +702,393 @@ "destinationSlotName": "Production" }, "httpsOnly": false - } + }, + "resources": [ + { + "ResourceId": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.Web/sites/site-B/config/web", + "Id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.Web/sites/site-B/config/web", + "Location": "region", + "ResourceName": "site-B", + "Name": "site-B", + "Properties": { + "numberOfWorkers": 1, + "defaultDocuments": [ + "Default.htm", + "Default.html", + "Default.asp", + "index.htm", + "index.html", + "iisstart.htm", + "default.aspx", + "index.php", + "hostingstart.html" + ], + "netFrameworkVersion": "v4.0", + "phpVersion": "", + "pythonVersion": "", + "nodeVersion": "", + "linuxFxVersion": "", + "windowsFxVersion": null, + "requestTracingEnabled": false, + "remoteDebuggingEnabled": false, + "remoteDebuggingVersion": null, + "httpLoggingEnabled": false, + "logsDirectorySizeLimit": 35, + "detailedErrorLoggingEnabled": false, + "publishingUsername": "$site-B", + "publishingPassword": null, + "appSettings": null, + "metadata": null, + "connectionStrings": null, + "machineKey": null, + "handlerMappings": null, + "documentRoot": null, + "scmType": "VSTSRM", + "use32BitWorkerProcess": true, + "webSocketsEnabled": false, + "alwaysOn": true, + "javaVersion": null, + "javaContainer": null, + "javaContainerVersion": null, + "appCommandLine": "", + "managedPipelineMode": "Integrated", + "virtualApplications": [ + { + "virtualPath": "/", + "physicalPath": "site\\wwwroot", + "preloadEnabled": true, + "virtualDirectories": null + } + ], + "winAuthAdminState": 0, + "winAuthTenantState": 0, + "customAppPoolIdentityAdminState": false, + "customAppPoolIdentityTenantState": false, + "runtimeADUser": null, + "runtimeADUserPassword": null, + "loadBalancing": "LeastRequests", + "routingRules": [], + "experiments": { + "rampUpRules": [] + }, + "limits": null, + "autoHealEnabled": false, + "autoHealRules": null, + "tracingOptions": null, + "vnetName": "", + "siteAuthEnabled": true, + "siteAuthSettings": { + "enabled": null, + "unauthenticatedClientAction": null, + "tokenStoreEnabled": null, + "allowedExternalRedirectUrls": null, + "defaultProvider": null, + "clientId": "00000000-0000-0000-0000-000000000000", + "clientSecret": null, + "clientSecretCertificateThumbprint": null, + "issuer": "https://sts.windows.net/00000000-0000-0000-0000-000000000000", + "allowedAudiences": null, + "additionalLoginParams": null, + "isAadAutoProvisioned": false, + "googleClientId": null, + "googleClientSecret": null, + "googleOAuthScopes": null, + "facebookAppId": null, + "facebookAppSecret": null, + "facebookOAuthScopes": null, + "twitterConsumerKey": null, + "twitterConsumerSecret": null, + "microsoftAccountClientId": null, + "microsoftAccountClientSecret": null, + "microsoftAccountOAuthScopes": null + }, + "cors": null, + "push": null, + "apiDefinition": null, + "apiManagementConfig": null, + "autoSwapSlotName": null, + "localMySqlEnabled": false, + "managedServiceIdentityId": null, + "xManagedServiceIdentityId": null, + "ipSecurityRestrictions": null, + "scmIpSecurityRestrictions": null, + "scmIpSecurityRestrictionsUseMain": null, + "http20Enabled": false, + "minTlsVersion": "1.1", + "ftpsState": "Disabled", + "reservedInstanceCount": 0, + "preWarmedInstanceCount": null, + "healthCheckPath": null + }, + "ResourceGroupName": "test-rg", + "Type": "Microsoft.Web/sites/config", + "ResourceType": "Microsoft.Web/sites/config", + "ExtensionResourceType": null, + "Sku": null, + "Tags": null, + "SubscriptionId": "00000000-0000-0000-0000-000000000000", + "CreatedTime": null, + "ChangedTime": null, + "ETag": null + } + ] + }, + { + "Name": "site-B/staging", + "ResourceId": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.Web/sites/site-B/slots/staging", + "ResourceName": "site-B/staging", + "ResourceType": "Microsoft.Web/sites/slots", + "Kind": "app", + "ResourceGroupName": "test-rg", + "Location": "region", + "SubscriptionId": "00000000-0000-0000-0000-000000000000", + "Properties": { + "name": "site-B(staging)", + "state": "Running", + "hostNames": [ + "site-B-staging.azurewebsites.net" + ], + "repositorySiteName": "site-B", + "owner": null, + "usageState": "Normal", + "enabled": true, + "adminEnabled": true, + "enabledHostNames": [ + "site-B-staging.azurewebsites.net", + "site-B-staging.scm.azurewebsites.net" + ], + "siteProperties": { + "metadata": null, + "properties": [ + { + "name": "LinuxFxVersion", + "value": "" + }, + { + "name": "WindowsFxVersion", + "value": null + } + ], + "appSettings": null + }, + "availabilityState": "Normal", + "sslCertificates": null, + "csrs": [], + "cers": null, + "siteMode": null, + "hostNameSslStates": [ + { + "name": "site-B-staging.azurewebsites.net", + "sslState": "Disabled", + "ipBasedSslResult": null, + "virtualIP": null, + "thumbprint": null, + "toUpdate": null, + "toUpdateIpBasedSsl": null, + "ipBasedSslState": "NotConfigured", + "hostType": "Standard" + }, + { + "name": "site-B-staging.scm.azurewebsites.net", + "sslState": "Disabled", + "ipBasedSslResult": null, + "virtualIP": null, + "thumbprint": null, + "toUpdate": null, + "toUpdateIpBasedSsl": null, + "ipBasedSslState": "NotConfigured", + "hostType": "Repository" + } + ], + "computeMode": null, + "serverFarm": null, + "serverFarmId": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.Web/serverfarms/plan-A", + "reserved": false, + "isXenon": false, + "hyperV": false, + "storageRecoveryDefaultState": "Running", + "contentAvailabilityState": "Normal", + "runtimeAvailabilityState": "Normal", + "siteConfig": null, + "deploymentId": "site-B", + "trafficManagerHostNames": null, + "sku": "Standard", + "scmSiteAlsoStopped": false, + "targetSwapSlot": null, + "hostingEnvironment": null, + "hostingEnvironmentProfile": null, + "clientAffinityEnabled": true, + "clientCertEnabled": false, + "hostNamesDisabled": false, + "domainVerificationIdentifiers": null, + "kind": "app", + "containerSize": 0, + "dailyMemoryTimeQuota": 0, + "suspendedTill": null, + "siteDisabledReason": 0, + "functionExecutionUnitsCache": null, + "maxNumberOfWorkers": null, + "cloningInfo": null, + "hostingEnvironmentId": null, + "tags": null, + "resourceGroup": "test-rg", + "defaultHostName": "site-B-staging.azurewebsites.net", + "slotSwapStatus": { + "sourceSlotName": "staging", + "destinationSlotName": "Production" + }, + "httpsOnly": false + }, + "resources": [ + { + "ResourceId": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.Web/sites/site-B/slots/staging/config/web", + "Id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/test-rg/providers/Microsoft.Web/sites/site-B/slots/staging/config/web", + "Identity": null, + "Kind": null, + "Location": "region", + "ManagedBy": null, + "ResourceName": "site-B", + "Name": "site-B", + "ExtensionResourceName": null, + "ParentResource": null, + "Plan": null, + "Properties": { + "numberOfWorkers": 1, + "defaultDocuments": [ + "Default.htm", + "Default.html", + "Default.asp", + "index.htm", + "index.html", + "iisstart.htm", + "default.aspx", + "index.php", + "hostingstart.html" + ], + "netFrameworkVersion": "v4.0", + "phpVersion": "", + "pythonVersion": "", + "nodeVersion": "", + "linuxFxVersion": "", + "windowsFxVersion": null, + "requestTracingEnabled": false, + "remoteDebuggingEnabled": false, + "remoteDebuggingVersion": null, + "httpLoggingEnabled": false, + "logsDirectorySizeLimit": 35, + "detailedErrorLoggingEnabled": false, + "publishingUsername": "$site-B__staging", + "publishingPassword": null, + "appSettings": null, + "metadata": null, + "connectionStrings": null, + "machineKey": null, + "handlerMappings": null, + "documentRoot": null, + "scmType": "VSTSRM", + "use32BitWorkerProcess": true, + "webSocketsEnabled": false, + "alwaysOn": true, + "javaVersion": null, + "javaContainer": null, + "javaContainerVersion": null, + "appCommandLine": "", + "managedPipelineMode": "Integrated", + "virtualApplications": [ + { + "virtualPath": "/", + "physicalPath": "site\\wwwroot", + "preloadEnabled": true, + "virtualDirectories": null + } + ], + "winAuthAdminState": 0, + "winAuthTenantState": 0, + "customAppPoolIdentityAdminState": false, + "customAppPoolIdentityTenantState": false, + "runtimeADUser": null, + "runtimeADUserPassword": null, + "loadBalancing": "LeastRequests", + "routingRules": [], + "experiments": { + "rampUpRules": [] + }, + "limits": null, + "autoHealEnabled": false, + "autoHealRules": null, + "tracingOptions": null, + "vnetName": "", + "siteAuthEnabled": true, + "siteAuthSettings": { + "enabled": null, + "unauthenticatedClientAction": null, + "tokenStoreEnabled": null, + "allowedExternalRedirectUrls": null, + "defaultProvider": null, + "clientId": "00000000-0000-0000-0000-000000000000", + "clientSecret": null, + "clientSecretCertificateThumbprint": null, + "issuer": "https://sts.windows.net/00000000-0000-0000-0000-000000000000", + "allowedAudiences": null, + "additionalLoginParams": null, + "isAadAutoProvisioned": false, + "googleClientId": null, + "googleClientSecret": null, + "googleOAuthScopes": null, + "facebookAppId": null, + "facebookAppSecret": null, + "facebookOAuthScopes": null, + "twitterConsumerKey": null, + "twitterConsumerSecret": null, + "microsoftAccountClientId": null, + "microsoftAccountClientSecret": null, + "microsoftAccountOAuthScopes": null + }, + "cors": null, + "push": null, + "apiDefinition": null, + "apiManagementConfig": null, + "autoSwapSlotName": "production", + "localMySqlEnabled": false, + "managedServiceIdentityId": null, + "xManagedServiceIdentityId": null, + "ipSecurityRestrictions": [ + { + "ipAddress": "Any", + "action": "Allow", + "priority": 1, + "name": "Allow all", + "description": "Allow all access" + } + ], + "scmIpSecurityRestrictions": [ + { + "ipAddress": "Any", + "action": "Allow", + "priority": 1, + "name": "Allow all", + "description": "Allow all access" + } + ], + "scmIpSecurityRestrictionsUseMain": false, + "http20Enabled": false, + "minTlsVersion": "1.1", + "ftpsState": "Disabled", + "reservedInstanceCount": 0, + "preWarmedInstanceCount": null, + "healthCheckPath": null + }, + "ResourceGroupName": "test-rg", + "Type": "Microsoft.Web/sites/slots/config", + "ResourceType": "Microsoft.Web/sites/slots/config", + "ExtensionResourceType": null, + "Sku": null, + "Tags": null, + "SubscriptionId": "00000000-0000-0000-0000-000000000000", + "CreatedTime": null, + "ChangedTime": null, + "ETag": null + } + ] } ]