diff --git a/.github/workflows/ms.web.sites.yml b/.github/workflows/ms.web.sites.yml index 172f6a7571..d5a3eb08a6 100644 --- a/.github/workflows/ms.web.sites.yml +++ b/.github/workflows/ms.web.sites.yml @@ -106,8 +106,7 @@ jobs: - name: 'Using test file [${{ matrix.moduleTestFilePaths }}]' uses: ./.github/actions/templates/validateModuleDeployment with: - templateFilePath: '${{ env.modulePath }}/deploy.bicep' - parameterFilePath: '${{ env.modulePath }}/${{ matrix.moduleTestFilePaths }}' + templateFilePath: '${{ env.modulePath }}/${{ matrix.moduleTestFilePaths }}' location: '${{ env.location }}' resourceGroupName: '${{ env.resourceGroupName }}' subscriptionId: '${{ secrets.ARM_SUBSCRIPTION_ID }}' diff --git a/modules/Microsoft.Web/sites/.test/FunctionAppCommon/dependencies.bicep b/modules/Microsoft.Web/sites/.test/FunctionAppCommon/dependencies.bicep new file mode 100644 index 0000000000..fdcc085b31 --- /dev/null +++ b/modules/Microsoft.Web/sites/.test/FunctionAppCommon/dependencies.bicep @@ -0,0 +1,109 @@ +@description('Optional. The location to deploy resources to.') +param location string = resourceGroup().location + +@description('Required. The name of the Virtual Network to create.') +param virtualNetworkName string + +@description('Required. The name of the Managed Identity to create.') +param managedIdentityName string + +@description('Required. The name of the Server Farm to create.') +param serverFarmName string + +@description('Required. The name of the Storage Account to create.') +param storageAccountName string + +@description('Required. The name of the Application Insights instance to create.') +param applicationInsightsName string + +resource virtualNetwork 'Microsoft.Network/virtualNetworks@2022-01-01' = { + name: virtualNetworkName + location: location + properties: { + addressSpace: { + addressPrefixes: [ + '10.0.0.0/24' + ] + } + subnets: [ + { + name: 'defaultSubnet' + properties: { + addressPrefix: '10.0.0.0/24' + } + } + ] + } +} + +resource privateDNSZone 'Microsoft.Network/privateDnsZones@2020-06-01' = { + name: 'privatelink.azurewebsites.net' + location: 'global' + + resource virtualNetworkLinks 'virtualNetworkLinks@2020-06-01' = { + name: '${virtualNetwork.name}-vnetlink' + location: 'global' + properties: { + virtualNetwork: { + id: virtualNetwork.id + } + registrationEnabled: false + } + } +} + +resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2018-11-30' = { + name: managedIdentityName + location: location +} + +resource storageAccount 'Microsoft.Storage/storageAccounts@2021-09-01' = { + name: storageAccountName + location: location + sku: { + name: 'Standard_LRS' + } + kind: 'StorageV2' + properties: {} +} + +resource serverFarm 'Microsoft.Web/serverfarms@2022-03-01' = { + name: serverFarmName + location: location + sku: { + name: 'S1' + tier: 'Standard' + size: 'S1' + family: 'S' + capacity: 1 + } + properties: {} +} + +resource applicationInsights 'Microsoft.Insights/components@2020-02-02' = { + name: applicationInsightsName + location: location + kind: '' + properties: {} +} + +@description('The resource ID of the created Virtual Network Subnet.') +output subnetResourceId string = virtualNetwork.properties.subnets[0].id + +@description('The principal ID of the created Managed Identity.') +output managedIdentityPrincipalId string = managedIdentity.properties.principalId + +@description('The resource ID of the created Managed Identity.') +output managedIdentityResourceId string = managedIdentity.id + +@description('The resource ID of the created Server Farm.') +output serverFarmResourceId string = serverFarm.id + +@description('The resource ID of the created Storage Account.') +output storageAccountResourceId string = storageAccount.id + +@description('The resource ID of the created Application Insights instance.') +output applicationInsightsResourceId string = applicationInsights.id + +@description('The resource ID of the created Private DNS Zone.') +output privateDNSZoneResourceId string = privateDNSZone.id diff --git a/modules/Microsoft.Web/sites/.test/FunctionAppCommon/deploy.test.bicep b/modules/Microsoft.Web/sites/.test/FunctionAppCommon/deploy.test.bicep new file mode 100644 index 0000000000..3e16f08f32 --- /dev/null +++ b/modules/Microsoft.Web/sites/.test/FunctionAppCommon/deploy.test.bicep @@ -0,0 +1,169 @@ +targetScope = 'subscription' + +// ========== // +// Parameters // +// ========== // +@description('Optional. The name of the resource group to deploy for testing purposes.') +@maxLength(90) +param resourceGroupName string = 'ms.web.sites-${serviceShort}-rg' + +@description('Optional. The location to deploy resources to.') +param location string = deployment().location + +@description('Optional. A short identifier for the kind of deployment. Should be kept short to not run into resource-name length-constraints.') +param serviceShort string = 'wsfacom' + +// =========== // +// Deployments // +// =========== // + +// General resources +// ================= +resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { + name: resourceGroupName + location: location +} + +module resourceGroupResources 'dependencies.bicep' = { + scope: resourceGroup + name: '${uniqueString(deployment().name, location)}-paramNested' + params: { + virtualNetworkName: 'dep-<>-vnet-${serviceShort}' + managedIdentityName: 'dep-<>-msi-${serviceShort}' + serverFarmName: 'dep-<>-sf-${serviceShort}' + storageAccountName: 'dep<>st${serviceShort}' + applicationInsightsName: 'dep-<>-appi-${serviceShort}' + } +} + +// Diagnostics +// =========== +module diagnosticDependencies '../../../../.shared/dependencyConstructs/diagnostic.dependencies.bicep' = { + scope: resourceGroup + name: '${uniqueString(deployment().name, location)}-diagnosticDependencies' + params: { + storageAccountName: 'dep<>diasa${serviceShort}01' + logAnalyticsWorkspaceName: 'dep-<>-law-${serviceShort}' + eventHubNamespaceEventHubName: 'dep-<>-evh-${serviceShort}' + eventHubNamespaceName: 'dep-<>-evhns-${serviceShort}' + location: location + } +} + +// ============== // +// Test Execution // +// ============== // + +module testDeployment '../../deploy.bicep' = { + scope: resourceGroup + name: '${uniqueString(deployment().name)}-test-${serviceShort}' + params: { + name: '<>${serviceShort}001' + kind: 'functionapp' + serverFarmResourceId: resourceGroupResources.outputs.serverFarmResourceId + appInsightId: resourceGroupResources.outputs.applicationInsightsResourceId + appSettingsKeyValuePairs: { + AzureFunctionsJobHost__logging__logLevel__default: 'Trace' + EASYAUTH_SECRET: 'https://adp-<>-az-kv-x-001.${environment().suffixes.keyvaultDns}/secrets/Modules-Test-SP-Password' + FUNCTIONS_EXTENSION_VERSION: '~4' + FUNCTIONS_WORKER_RUNTIME: 'dotnet' + } + authSettingV2Configuration: { + globalValidation: { + requireAuthentication: true + unauthenticatedClientAction: 'Return401' + } + httpSettings: { + forwardProxy: { + convention: 'NoProxy' + } + requireHttps: true + routes: { + apiPrefix: '/.auth' + } + } + identityProviders: { + azureActiveDirectory: { + enabled: true + login: { + disableWWWAuthenticate: false + } + registration: { + clientId: 'd874dd2f-2032-4db1-a053-f0ec243685aa' + clientSecretSettingName: 'EASYAUTH_SECRET' + openIdIssuer: 'https://sts.windows.net/${tenant().tenantId}/v2.0/' + } + validation: { + allowedAudiences: [ + 'api://d874dd2f-2032-4db1-a053-f0ec243685aa' + ] + defaultAuthorizationPolicy: { + allowedPrincipals: {} + } + jwtClaimChecks: {} + } + } + } + login: { + allowedExternalRedirectUrls: [ + 'string' + ] + cookieExpiration: { + convention: 'FixedTime' + timeToExpiration: '08:00:00' + } + nonce: { + nonceExpirationInterval: '00:05:00' + validateNonce: true + } + preserveUrlFragmentsForLogins: false + routes: {} + tokenStore: { + azureBlobStorage: {} + enabled: true + fileSystem: {} + tokenRefreshExtensionHours: 72 + } + } + platform: { + enabled: true + runtimeVersion: '~1' + } + } + diagnosticLogsRetentionInDays: 7 + diagnosticStorageAccountId: diagnosticDependencies.outputs.storageAccountResourceId + diagnosticWorkspaceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId + diagnosticEventHubAuthorizationRuleId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId + diagnosticEventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName + lock: 'CanNotDelete' + privateEndpoints: [ + { + service: 'sites' + subnetResourceId: resourceGroupResources.outputs.subnetResourceId + privateDnsZoneGroup: { + privateDNSResourceIds: [ + resourceGroupResources.outputs.privateDNSZoneResourceId + ] + } + } + ] + roleAssignments: [ + { + principalIds: [ + resourceGroupResources.outputs.managedIdentityPrincipalId + ] + roleDefinitionIdOrName: 'Reader' + } + ] + setAzureWebJobsDashboard: true + siteConfig: { + alwaysOn: true + use32BitWorkerProcess: false + } + storageAccountId: resourceGroupResources.outputs.storageAccountResourceId + systemAssignedIdentity: true + userAssignedIdentities: { + '${resourceGroupResources.outputs.managedIdentityResourceId}': {} + } + } +} diff --git a/modules/Microsoft.Web/sites/.test/fa.min.parameters.json b/modules/Microsoft.Web/sites/.test/fa.min.parameters.json deleted file mode 100644 index 0d4b5e85fb..0000000000 --- a/modules/Microsoft.Web/sites/.test/fa.min.parameters.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", - "contentVersion": "1.0.0.0", - "parameters": { - "name": { - "value": "<>-az-fa-min-001" - }, - "kind": { - "value": "functionapp" - }, - "serverFarmResourceId": { - "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Web/serverFarms/adp-<>-az-asp-x-001" - }, - "siteConfig": { - "value": { - "alwaysOn": true - } - } - } -} diff --git a/modules/Microsoft.Web/sites/.test/fa.parameters.json b/modules/Microsoft.Web/sites/.test/fa.parameters.json deleted file mode 100644 index a4b733fb51..0000000000 --- a/modules/Microsoft.Web/sites/.test/fa.parameters.json +++ /dev/null @@ -1,151 +0,0 @@ -{ - "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", - "contentVersion": "1.0.0.0", - "parameters": { - "name": { - "value": "<>-az-fa-x-001" - }, - "lock": { - "value": "CanNotDelete" - }, - "kind": { - "value": "functionapp" - }, - "serverFarmResourceId": { - "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Web/serverFarms/adp-<>-az-asp-x-001" - }, - "siteConfig": { - "value": { - "alwaysOn": true, - "use32BitWorkerProcess": false - } - }, - "appInsightId": { - "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Insights/components/adp-<>-az-appi-x-001" - }, - "storageAccountId": { - "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001" - }, - "setAzureWebJobsDashboard": { - "value": true - }, - "appSettingsKeyValuePairs": { - "value": { - "FUNCTIONS_EXTENSION_VERSION": "~4", - "FUNCTIONS_WORKER_RUNTIME": "dotnet", - "AzureFunctionsJobHost__logging__logLevel__default": "Trace", - "EASYAUTH_SECRET": "https://adp-<>-az-kv-x-001.vault.azure.net/secrets/Modules-Test-SP-Password" - } - }, - "authSettingV2Configuration": { - "value": { - "globalValidation": { - "requireAuthentication": true, - "unauthenticatedClientAction": "Return401" - }, - "httpSettings": { - "forwardProxy": { - "convention": "NoProxy" - }, - "requireHttps": true, - "routes": { - "apiPrefix": "/.auth" - } - }, - "identityProviders": { - "azureActiveDirectory": { - "enabled": true, - "login": { - "disableWWWAuthenticate": false - }, - "registration": { - "openIdIssuer": "https://sts.windows.net/<>/v2.0/", - "clientId": "d874dd2f-2032-4db1-a053-f0ec243685aa", - "clientSecretSettingName": "EASYAUTH_SECRET" - }, - "validation": { - "allowedAudiences": [ - "api://d874dd2f-2032-4db1-a053-f0ec243685aa" - ], - "defaultAuthorizationPolicy": { - "allowedPrincipals": {} - }, - "jwtClaimChecks": {} - } - } - }, - "login": { - "allowedExternalRedirectUrls": [ - "string" - ], - "cookieExpiration": { - "convention": "FixedTime", - "timeToExpiration": "08:00:00" - }, - "nonce": { - "nonceExpirationInterval": "00:05:00", - "validateNonce": true - }, - "preserveUrlFragmentsForLogins": false, - "routes": {}, - "tokenStore": { - "azureBlobStorage": {}, - "enabled": true, - "fileSystem": {}, - "tokenRefreshExtensionHours": 72 - } - }, - "platform": { - "enabled": true, - "runtimeVersion": "~1" - } - } - }, - "systemAssignedIdentity": { - "value": true - }, - "userAssignedIdentities": { - "value": { - "/subscriptions/<>/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-<>-az-msi-x-001": {} - } - }, - "roleAssignments": { - "value": [ - { - "roleDefinitionIdOrName": "Reader", - "principalIds": [ - "<>" - ] - } - ] - }, - "diagnosticLogsRetentionInDays": { - "value": 7 - }, - "diagnosticStorageAccountId": { - "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001" - }, - "diagnosticWorkspaceId": { - "value": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001" - }, - "diagnosticEventHubAuthorizationRuleId": { - "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.EventHub/namespaces/adp-<>-az-evhns-x-001/AuthorizationRules/RootManageSharedAccessKey" - }, - "diagnosticEventHubName": { - "value": "adp-<>-az-evh-x-001" - }, - "privateEndpoints": { - "value": [ - { - "subnetResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/adp-<>-az-vnet-x-001/subnets/<>-az-subnet-x-005-privateEndpoints", - "service": "sites", - "privateDnsZoneGroup": { - "privateDNSResourceIds": [ - "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/privateDnsZones/privatelink.azurewebsites.net" - ] - } - } - ] - } - } -} diff --git a/modules/Microsoft.Web/sites/.test/functionAppMin/dependencies.bicep b/modules/Microsoft.Web/sites/.test/functionAppMin/dependencies.bicep new file mode 100644 index 0000000000..cd93e7ed3f --- /dev/null +++ b/modules/Microsoft.Web/sites/.test/functionAppMin/dependencies.bicep @@ -0,0 +1,21 @@ +@description('Optional. The location to deploy resources to.') +param location string = resourceGroup().location + +@description('Required. The name of the Server Farm to create.') +param serverFarmName string + +resource serverFarm 'Microsoft.Web/serverfarms@2022-03-01' = { + name: serverFarmName + location: location + sku: { + name: 'S1' + tier: 'Standard' + size: 'S1' + family: 'S' + capacity: 1 + } + properties: {} +} + +@description('The resource ID of the created Server Farm.') +output serverFarmResourceId string = serverFarm.id diff --git a/modules/Microsoft.Web/sites/.test/functionAppMin/deploy.test.bicep b/modules/Microsoft.Web/sites/.test/functionAppMin/deploy.test.bicep new file mode 100644 index 0000000000..1caea757f3 --- /dev/null +++ b/modules/Microsoft.Web/sites/.test/functionAppMin/deploy.test.bicep @@ -0,0 +1,50 @@ +targetScope = 'subscription' + +// ========== // +// Parameters // +// ========== // +@description('Optional. The name of the resource group to deploy for testing purposes.') +@maxLength(90) +param resourceGroupName string = 'ms.web.sites-${serviceShort}-rg' + +@description('Optional. The location to deploy resources to.') +param location string = deployment().location + +@description('Optional. A short identifier for the kind of deployment. Should be kept short to not run into resource-name length-constraints.') +param serviceShort string = 'wsfamin' + +// =========== // +// Deployments // +// =========== // + +// General resources +// ================= +resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { + name: resourceGroupName + location: location +} + +module resourceGroupResources 'dependencies.bicep' = { + scope: resourceGroup + name: '${uniqueString(deployment().name, location)}-paramNested' + params: { + serverFarmName: 'dep-<>-sf-${serviceShort}' + } +} + +// ============== // +// Test Execution // +// ============== // + +module testDeployment '../../deploy.bicep' = { + scope: resourceGroup + name: '${uniqueString(deployment().name)}-test-${serviceShort}' + params: { + name: '<>${serviceShort}001' + kind: 'functionapp' + serverFarmResourceId: resourceGroupResources.outputs.serverFarmResourceId + siteConfig: { + alwaysOn: true + } + } +} diff --git a/modules/Microsoft.Web/sites/.test/wa.min.parameters.json b/modules/Microsoft.Web/sites/.test/wa.min.parameters.json deleted file mode 100644 index 588beef102..0000000000 --- a/modules/Microsoft.Web/sites/.test/wa.min.parameters.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", - "contentVersion": "1.0.0.0", - "parameters": { - "name": { - "value": "<>-az-wa-min-001" - }, - "kind": { - "value": "app" - }, - "serverFarmResourceId": { - "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Web/serverFarms/adp-<>-az-asp-x-001" - } - } -} diff --git a/modules/Microsoft.Web/sites/.test/wa.parameters.json b/modules/Microsoft.Web/sites/.test/wa.parameters.json deleted file mode 100644 index ad18626351..0000000000 --- a/modules/Microsoft.Web/sites/.test/wa.parameters.json +++ /dev/null @@ -1,75 +0,0 @@ -{ - "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", - "contentVersion": "1.0.0.0", - "parameters": { - "name": { - "value": "<>-az-wa-x-001" - }, - "kind": { - "value": "app" - }, - "serverFarmResourceId": { - "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Web/serverFarms/adp-<>-az-asp-x-001" - }, - "siteConfig": { - "value": { - "metadata": [ - { - "name": "CURRENT_STACK", - "value": "dotnetcore" - } - ], - "alwaysOn": true - } - }, - "httpsOnly": { - "value": true - }, - "systemAssignedIdentity": { - "value": true - }, - "userAssignedIdentities": { - "value": { - "/subscriptions/<>/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-<>-az-msi-x-001": {} - } - }, - "roleAssignments": { - "value": [ - { - "roleDefinitionIdOrName": "Reader", - "principalIds": [ - "<>" - ] - } - ] - }, - "diagnosticLogsRetentionInDays": { - "value": 7 - }, - "diagnosticStorageAccountId": { - "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001" - }, - "diagnosticWorkspaceId": { - "value": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001" - }, - "diagnosticEventHubAuthorizationRuleId": { - "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.EventHub/namespaces/adp-<>-az-evhns-x-001/AuthorizationRules/RootManageSharedAccessKey" - }, - "diagnosticEventHubName": { - "value": "adp-<>-az-evh-x-001" - }, - "privateEndpoints": { - "value": [ - { - "subnetResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/adp-<>-az-vnet-x-001/subnets/<>-az-subnet-x-005-privateEndpoints", - "service": "sites", - "privateDnsZoneGroup": { - "privateDNSResourceIds": [ - "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/privateDnsZones/privatelink.azurewebsites.net" - ] - } - } - ] - } - } -} diff --git a/modules/Microsoft.Web/sites/.test/webAppCommon/dependencies.bicep b/modules/Microsoft.Web/sites/.test/webAppCommon/dependencies.bicep new file mode 100644 index 0000000000..542edbb9e5 --- /dev/null +++ b/modules/Microsoft.Web/sites/.test/webAppCommon/dependencies.bicep @@ -0,0 +1,80 @@ +@description('Optional. The location to deploy resources to.') +param location string = resourceGroup().location + +@description('Required. The name of the Virtual Network to create.') +param virtualNetworkName string + +@description('Required. The name of the Managed Identity to create.') +param managedIdentityName string + +@description('Required. The name of the Server Farm to create.') +param serverFarmName string + +resource virtualNetwork 'Microsoft.Network/virtualNetworks@2022-01-01' = { + name: virtualNetworkName + location: location + properties: { + addressSpace: { + addressPrefixes: [ + '10.0.0.0/24' + ] + } + subnets: [ + { + name: 'defaultSubnet' + properties: { + addressPrefix: '10.0.0.0/24' + } + } + ] + } +} + +resource privateDNSZone 'Microsoft.Network/privateDnsZones@2020-06-01' = { + name: 'privatelink.azurewebsites.net' + location: 'global' + + resource virtualNetworkLinks 'virtualNetworkLinks@2020-06-01' = { + name: '${virtualNetwork.name}-vnetlink' + location: 'global' + properties: { + virtualNetwork: { + id: virtualNetwork.id + } + registrationEnabled: false + } + } +} + +resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2018-11-30' = { + name: managedIdentityName + location: location +} + +resource serverFarm 'Microsoft.Web/serverfarms@2022-03-01' = { + name: serverFarmName + location: location + sku: { + name: 'S1' + tier: 'Standard' + size: 'S1' + family: 'S' + capacity: 1 + } + properties: {} +} + +@description('The resource ID of the created Virtual Network Subnet.') +output subnetResourceId string = virtualNetwork.properties.subnets[0].id + +@description('The principal ID of the created Managed Identity.') +output managedIdentityPrincipalId string = managedIdentity.properties.principalId + +@description('The resource ID of the created Managed Identity.') +output managedIdentityResourceId string = managedIdentity.id + +@description('The resource ID of the created Server Farm.') +output serverFarmResourceId string = serverFarm.id + +@description('The resource ID of the created Private DNS Zone.') +output privateDNSZoneResourceId string = privateDNSZone.id diff --git a/modules/Microsoft.Web/sites/.test/webAppCommon/deploy.test.bicep b/modules/Microsoft.Web/sites/.test/webAppCommon/deploy.test.bicep new file mode 100644 index 0000000000..86c087ea9c --- /dev/null +++ b/modules/Microsoft.Web/sites/.test/webAppCommon/deploy.test.bicep @@ -0,0 +1,101 @@ +targetScope = 'subscription' + +// ========== // +// Parameters // +// ========== // +@description('Optional. The name of the resource group to deploy for testing purposes.') +@maxLength(90) +param resourceGroupName string = 'ms.web.sites-${serviceShort}-rg' + +@description('Optional. The location to deploy resources to.') +param location string = deployment().location + +@description('Optional. A short identifier for the kind of deployment. Should be kept short to not run into resource-name length-constraints.') +param serviceShort string = 'wswa' + +// =========== // +// Deployments // +// =========== // + +// General resources +// ================= +resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { + name: resourceGroupName + location: location +} + +module resourceGroupResources 'dependencies.bicep' = { + scope: resourceGroup + name: '${uniqueString(deployment().name, location)}-paramNested' + params: { + virtualNetworkName: 'dep-<>-vnet-${serviceShort}' + managedIdentityName: 'dep-<>-msi-${serviceShort}' + serverFarmName: 'dep-<>-sf-${serviceShort}' + } +} + +// Diagnostics +// =========== +module diagnosticDependencies '../../../../.shared/dependencyConstructs/diagnostic.dependencies.bicep' = { + scope: resourceGroup + name: '${uniqueString(deployment().name, location)}-diagnosticDependencies' + params: { + storageAccountName: 'dep<>diasa${serviceShort}01' + logAnalyticsWorkspaceName: 'dep-<>-law-${serviceShort}' + eventHubNamespaceEventHubName: 'dep-<>-evh-${serviceShort}' + eventHubNamespaceName: 'dep-<>-evhns-${serviceShort}' + location: location + } +} + +// ============== // +// Test Execution // +// ============== // + +module testDeployment '../../deploy.bicep' = { + scope: resourceGroup + name: '${uniqueString(deployment().name)}-test-${serviceShort}' + params: { + name: '<>${serviceShort}001' + kind: 'app' + serverFarmResourceId: resourceGroupResources.outputs.serverFarmResourceId + diagnosticLogsRetentionInDays: 7 + diagnosticStorageAccountId: diagnosticDependencies.outputs.storageAccountResourceId + diagnosticWorkspaceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId + diagnosticEventHubAuthorizationRuleId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId + diagnosticEventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName + httpsOnly: true + privateEndpoints: [ + { + service: 'sites' + subnetResourceId: resourceGroupResources.outputs.subnetResourceId + privateDnsZoneGroup: { + privateDNSResourceIds: [ + resourceGroupResources.outputs.privateDNSZoneResourceId + ] + } + } + ] + roleAssignments: [ + { + principalIds: [ + resourceGroupResources.outputs.managedIdentityPrincipalId + ] + roleDefinitionIdOrName: 'Reader' + } + ] + siteConfig: { + alwaysOn: true + metadata: [ + { + name: 'CURRENT_STACK' + value: 'dotnetcore' + } + ] + } + systemAssignedIdentity: true + userAssignedIdentities: { + '${resourceGroupResources.outputs.managedIdentityResourceId}': {} + } + } +} diff --git a/modules/Microsoft.Web/sites/.test/webAppMin/dependencies.bicep b/modules/Microsoft.Web/sites/.test/webAppMin/dependencies.bicep new file mode 100644 index 0000000000..cd93e7ed3f --- /dev/null +++ b/modules/Microsoft.Web/sites/.test/webAppMin/dependencies.bicep @@ -0,0 +1,21 @@ +@description('Optional. The location to deploy resources to.') +param location string = resourceGroup().location + +@description('Required. The name of the Server Farm to create.') +param serverFarmName string + +resource serverFarm 'Microsoft.Web/serverfarms@2022-03-01' = { + name: serverFarmName + location: location + sku: { + name: 'S1' + tier: 'Standard' + size: 'S1' + family: 'S' + capacity: 1 + } + properties: {} +} + +@description('The resource ID of the created Server Farm.') +output serverFarmResourceId string = serverFarm.id diff --git a/modules/Microsoft.Web/sites/.test/webAppMin/deploy.test.bicep b/modules/Microsoft.Web/sites/.test/webAppMin/deploy.test.bicep new file mode 100644 index 0000000000..b463473993 --- /dev/null +++ b/modules/Microsoft.Web/sites/.test/webAppMin/deploy.test.bicep @@ -0,0 +1,47 @@ +targetScope = 'subscription' + +// ========== // +// Parameters // +// ========== // +@description('Optional. The name of the resource group to deploy for testing purposes.') +@maxLength(90) +param resourceGroupName string = 'ms.web.sites-${serviceShort}-rg' + +@description('Optional. The location to deploy resources to.') +param location string = deployment().location + +@description('Optional. A short identifier for the kind of deployment. Should be kept short to not run into resource-name length-constraints.') +param serviceShort string = 'wswamin' + +// =========== // +// Deployments // +// =========== // + +// General resources +// ================= +resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { + name: resourceGroupName + location: location +} + +module resourceGroupResources 'dependencies.bicep' = { + scope: resourceGroup + name: '${uniqueString(deployment().name, location)}-paramNested' + params: { + serverFarmName: 'dep-<>-sf-${serviceShort}' + } +} + +// ============== // +// Test Execution // +// ============== // + +module testDeployment '../../deploy.bicep' = { + scope: resourceGroup + name: '${uniqueString(deployment().name)}-test-${serviceShort}' + params: { + name: '<>${serviceShort}001' + kind: 'app' + serverFarmResourceId: resourceGroupResources.outputs.serverFarmResourceId + } +} diff --git a/modules/Microsoft.Web/sites/readme.md b/modules/Microsoft.Web/sites/readme.md index 96bc36f46c..0699c042ed 100644 --- a/modules/Microsoft.Web/sites/readme.md +++ b/modules/Microsoft.Web/sites/readme.md @@ -413,7 +413,7 @@ The following module usage examples are retrieved from the content of the files >**Note**: Each example lists all the required parameters first, followed by the rest - each in alphabetical order. -

Example 1: Fa Min

+

Example 1: Functionappcommon

@@ -421,74 +421,17 @@ The following module usage examples are retrieved from the content of the files ```bicep module sites './Microsoft.Web/sites/deploy.bicep' = { - name: '${uniqueString(deployment().name)}-Sites' + name: '${uniqueString(deployment().name)}-test-wsfacom' params: { // Required parameters kind: 'functionapp' - name: '<>-az-fa-min-001' - serverFarmResourceId: '/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Web/serverFarms/adp-<>-az-asp-x-001' + name: '<>wsfacom001' + serverFarmResourceId: '' // Non-required parameters - siteConfig: { - alwaysOn: true - } - } -} -``` - -
-

- -

- -via JSON Parameter file - -```json -{ - "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", - "contentVersion": "1.0.0.0", - "parameters": { - // Required parameters - "kind": { - "value": "functionapp" - }, - "name": { - "value": "<>-az-fa-min-001" - }, - "serverFarmResourceId": { - "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Web/serverFarms/adp-<>-az-asp-x-001" - }, - // Non-required parameters - "siteConfig": { - "value": { - "alwaysOn": true - } - } - } -} -``` - -
-

- -

Example 2: Fa

- -
- -via Bicep module - -```bicep -module sites './Microsoft.Web/sites/deploy.bicep' = { - name: '${uniqueString(deployment().name)}-Sites' - params: { - // Required parameters - kind: 'functionapp' - name: '<>-az-fa-x-001' - serverFarmResourceId: '/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Web/serverFarms/adp-<>-az-asp-x-001' - // Non-required parameters - appInsightId: '/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Insights/components/adp-<>-az-appi-x-001' + appInsightId: '' appSettingsKeyValuePairs: { AzureFunctionsJobHost__logging__logLevel__default: 'Trace' - EASYAUTH_SECRET: 'https://adp-<>-az-kv-x-001.vault.azure.net/secrets/Modules-Test-SP-Password' + EASYAUTH_SECRET: 'https://adp-<>-az-kv-x-001.${environment().suffixes.keyvaultDns}/secrets/Modules-Test-SP-Password' FUNCTIONS_EXTENSION_VERSION: '~4' FUNCTIONS_WORKER_RUNTIME: 'dotnet' } @@ -515,7 +458,7 @@ module sites './Microsoft.Web/sites/deploy.bicep' = { registration: { clientId: 'd874dd2f-2032-4db1-a053-f0ec243685aa' clientSecretSettingName: 'EASYAUTH_SECRET' - openIdIssuer: 'https://sts.windows.net/<>/v2.0/' + openIdIssuer: 'https://sts.windows.net/${tenant().tenantId}/v2.0/' } validation: { allowedAudiences: [ @@ -554,27 +497,27 @@ module sites './Microsoft.Web/sites/deploy.bicep' = { runtimeVersion: '~1' } } - diagnosticEventHubAuthorizationRuleId: '/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.EventHub/namespaces/adp-<>-az-evhns-x-001/AuthorizationRules/RootManageSharedAccessKey' - diagnosticEventHubName: 'adp-<>-az-evh-x-001' + diagnosticEventHubAuthorizationRuleId: '' + diagnosticEventHubName: '' diagnosticLogsRetentionInDays: 7 - diagnosticStorageAccountId: '/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001' - diagnosticWorkspaceId: '/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001' + diagnosticStorageAccountId: '' + diagnosticWorkspaceId: '' lock: 'CanNotDelete' privateEndpoints: [ { privateDnsZoneGroup: { privateDNSResourceIds: [ - '/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/privateDnsZones/privatelink.azurewebsites.net' + '' ] } service: 'sites' - subnetResourceId: '/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/adp-<>-az-vnet-x-001/subnets/<>-az-subnet-x-005-privateEndpoints' + subnetResourceId: '' } ] roleAssignments: [ { principalIds: [ - '<>' + '' ] roleDefinitionIdOrName: 'Reader' } @@ -584,10 +527,10 @@ module sites './Microsoft.Web/sites/deploy.bicep' = { alwaysOn: true use32BitWorkerProcess: false } - storageAccountId: '/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001' + storageAccountId: '' systemAssignedIdentity: true userAssignedIdentities: { - '/subscriptions/<>/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-<>-az-msi-x-001': {} + '': {} } } } @@ -610,19 +553,19 @@ module sites './Microsoft.Web/sites/deploy.bicep' = { "value": "functionapp" }, "name": { - "value": "<>-az-fa-x-001" + "value": "<>wsfacom001" }, "serverFarmResourceId": { - "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Web/serverFarms/adp-<>-az-asp-x-001" + "value": "" }, // Non-required parameters "appInsightId": { - "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Insights/components/adp-<>-az-appi-x-001" + "value": "" }, "appSettingsKeyValuePairs": { "value": { "AzureFunctionsJobHost__logging__logLevel__default": "Trace", - "EASYAUTH_SECRET": "https://adp-<>-az-kv-x-001.vault.azure.net/secrets/Modules-Test-SP-Password", + "EASYAUTH_SECRET": "https://adp-<>-az-kv-x-001.${environment().suffixes.keyvaultDns}/secrets/Modules-Test-SP-Password", "FUNCTIONS_EXTENSION_VERSION": "~4", "FUNCTIONS_WORKER_RUNTIME": "dotnet" } @@ -651,7 +594,7 @@ module sites './Microsoft.Web/sites/deploy.bicep' = { "registration": { "clientId": "d874dd2f-2032-4db1-a053-f0ec243685aa", "clientSecretSettingName": "EASYAUTH_SECRET", - "openIdIssuer": "https://sts.windows.net/<>/v2.0/" + "openIdIssuer": "https://sts.windows.net/${tenant().tenantId}/v2.0/" }, "validation": { "allowedAudiences": [ @@ -692,19 +635,19 @@ module sites './Microsoft.Web/sites/deploy.bicep' = { } }, "diagnosticEventHubAuthorizationRuleId": { - "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.EventHub/namespaces/adp-<>-az-evhns-x-001/AuthorizationRules/RootManageSharedAccessKey" + "value": "" }, "diagnosticEventHubName": { - "value": "adp-<>-az-evh-x-001" + "value": "" }, "diagnosticLogsRetentionInDays": { "value": 7 }, "diagnosticStorageAccountId": { - "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001" + "value": "" }, "diagnosticWorkspaceId": { - "value": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001" + "value": "" }, "lock": { "value": "CanNotDelete" @@ -714,11 +657,11 @@ module sites './Microsoft.Web/sites/deploy.bicep' = { { "privateDnsZoneGroup": { "privateDNSResourceIds": [ - "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/privateDnsZones/privatelink.azurewebsites.net" + "" ] }, "service": "sites", - "subnetResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/adp-<>-az-vnet-x-001/subnets/<>-az-subnet-x-005-privateEndpoints" + "subnetResourceId": "" } ] }, @@ -726,7 +669,7 @@ module sites './Microsoft.Web/sites/deploy.bicep' = { "value": [ { "principalIds": [ - "<>" + "" ], "roleDefinitionIdOrName": "Reader" } @@ -742,14 +685,14 @@ module sites './Microsoft.Web/sites/deploy.bicep' = { } }, "storageAccountId": { - "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001" + "value": "" }, "systemAssignedIdentity": { "value": true }, "userAssignedIdentities": { "value": { - "/subscriptions/<>/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-<>-az-msi-x-001": {} + "": {} } } } @@ -759,7 +702,7 @@ module sites './Microsoft.Web/sites/deploy.bicep' = {

-

Example 3: Wa Min

+

Example 2: Functionappmin

@@ -767,12 +710,16 @@ module sites './Microsoft.Web/sites/deploy.bicep' = { ```bicep module sites './Microsoft.Web/sites/deploy.bicep' = { - name: '${uniqueString(deployment().name)}-Sites' + name: '${uniqueString(deployment().name)}-test-wsfamin' params: { // Required parameters - kind: 'app' - name: '<>-az-wa-min-001' - serverFarmResourceId: '/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Web/serverFarms/adp-<>-az-asp-x-001' + kind: 'functionapp' + name: '<>wsfamin001' + serverFarmResourceId: '' + // Non-required parameters + siteConfig: { + alwaysOn: true + } } } ``` @@ -791,13 +738,19 @@ module sites './Microsoft.Web/sites/deploy.bicep' = { "parameters": { // Required parameters "kind": { - "value": "app" + "value": "functionapp" }, "name": { - "value": "<>-az-wa-min-001" + "value": "<>wsfamin001" }, "serverFarmResourceId": { - "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Web/serverFarms/adp-<>-az-asp-x-001" + "value": "" + }, + // Non-required parameters + "siteConfig": { + "value": { + "alwaysOn": true + } } } } @@ -806,7 +759,7 @@ module sites './Microsoft.Web/sites/deploy.bicep' = {

-

Example 4: Wa

+

Example 3: Webappcommon

@@ -814,34 +767,34 @@ module sites './Microsoft.Web/sites/deploy.bicep' = { ```bicep module sites './Microsoft.Web/sites/deploy.bicep' = { - name: '${uniqueString(deployment().name)}-Sites' + name: '${uniqueString(deployment().name)}-test-wswa' params: { // Required parameters kind: 'app' - name: '<>-az-wa-x-001' - serverFarmResourceId: '/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Web/serverFarms/adp-<>-az-asp-x-001' + name: '<>wswa001' + serverFarmResourceId: '' // Non-required parameters - diagnosticEventHubAuthorizationRuleId: '/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.EventHub/namespaces/adp-<>-az-evhns-x-001/AuthorizationRules/RootManageSharedAccessKey' - diagnosticEventHubName: 'adp-<>-az-evh-x-001' + diagnosticEventHubAuthorizationRuleId: '' + diagnosticEventHubName: '' diagnosticLogsRetentionInDays: 7 - diagnosticStorageAccountId: '/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001' - diagnosticWorkspaceId: '/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001' + diagnosticStorageAccountId: '' + diagnosticWorkspaceId: '' httpsOnly: true privateEndpoints: [ { privateDnsZoneGroup: { privateDNSResourceIds: [ - '/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/privateDnsZones/privatelink.azurewebsites.net' + '' ] } service: 'sites' - subnetResourceId: '/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/adp-<>-az-vnet-x-001/subnets/<>-az-subnet-x-005-privateEndpoints' + subnetResourceId: '' } ] roleAssignments: [ { principalIds: [ - '<>' + '' ] roleDefinitionIdOrName: 'Reader' } @@ -857,7 +810,7 @@ module sites './Microsoft.Web/sites/deploy.bicep' = { } systemAssignedIdentity: true userAssignedIdentities: { - '/subscriptions/<>/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-<>-az-msi-x-001': {} + '': {} } } } @@ -880,26 +833,26 @@ module sites './Microsoft.Web/sites/deploy.bicep' = { "value": "app" }, "name": { - "value": "<>-az-wa-x-001" + "value": "<>wswa001" }, "serverFarmResourceId": { - "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Web/serverFarms/adp-<>-az-asp-x-001" + "value": "" }, // Non-required parameters "diagnosticEventHubAuthorizationRuleId": { - "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.EventHub/namespaces/adp-<>-az-evhns-x-001/AuthorizationRules/RootManageSharedAccessKey" + "value": "" }, "diagnosticEventHubName": { - "value": "adp-<>-az-evh-x-001" + "value": "" }, "diagnosticLogsRetentionInDays": { "value": 7 }, "diagnosticStorageAccountId": { - "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001" + "value": "" }, "diagnosticWorkspaceId": { - "value": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001" + "value": "" }, "httpsOnly": { "value": true @@ -909,11 +862,11 @@ module sites './Microsoft.Web/sites/deploy.bicep' = { { "privateDnsZoneGroup": { "privateDNSResourceIds": [ - "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/privateDnsZones/privatelink.azurewebsites.net" + "" ] }, "service": "sites", - "subnetResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/adp-<>-az-vnet-x-001/subnets/<>-az-subnet-x-005-privateEndpoints" + "subnetResourceId": "" } ] }, @@ -921,7 +874,7 @@ module sites './Microsoft.Web/sites/deploy.bicep' = { "value": [ { "principalIds": [ - "<>" + "" ], "roleDefinitionIdOrName": "Reader" } @@ -943,7 +896,7 @@ module sites './Microsoft.Web/sites/deploy.bicep' = { }, "userAssignedIdentities": { "value": { - "/subscriptions/<>/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-<>-az-msi-x-001": {} + "": {} } } } @@ -952,3 +905,50 @@ module sites './Microsoft.Web/sites/deploy.bicep' = {

+ +

Example 4: Webappmin

+ +
+ +via Bicep module + +```bicep +module sites './Microsoft.Web/sites/deploy.bicep' = { + name: '${uniqueString(deployment().name)}-test-wswamin' + params: { + // Required parameters + kind: 'app' + name: '<>wswamin001' + serverFarmResourceId: '' + } +} +``` + +
+

+ +

+ +via JSON Parameter file + +```json +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + // Required parameters + "kind": { + "value": "app" + }, + "name": { + "value": "<>wswamin001" + }, + "serverFarmResourceId": { + "value": "" + } + } +} +``` + +
+