From 317cddea046b0858f12b743edbc4922d31bbebb2 Mon Sep 17 00:00:00 2001 From: Alexander Sehr Date: Wed, 19 Oct 2022 08:31:30 +0200 Subject: [PATCH] [Modules] Updated Compute/VirtualMachines to new dependency approach (#1822) * [Modules] Updated Compute/VirtualMachines to new dependency approach * Restored VM * Update to latest * Update to latest * Updated SSH ref * introduced ssh key name var * Minor rename * Adjusted SSH handling, updated role assignments, update readme generation to cut out dependsOn for bicep examples * Script update * Converted to SSH output * Update to latest * Updated readme error handling * Updated RBAC * Update to latest * Apply suggestions from code review --- .../workflows/ms.compute.virtualmachines.yml | 3 +- .../.test/.scripts/New-SSHKey.ps1 | 19 + .../.test/.scripts/Set-BlobContent.ps1 | 15 + .../.test/linux.atmg/dependencies.bicep | 87 ++ .../.test/linux.atmg/deploy.test.bicep | 95 ++ .../.test/linux.autmg.parameters.json | 64 -- .../.test/linux.min.parameters.json | 61 -- .../.test/linux.min/dependencies.bicep | 87 ++ .../.test/linux.min/deploy.test.bicep | 94 ++ .../.test/linux.parameters.json | 218 ----- .../.test/linux/dependencies.bicep | 336 +++++++ .../.test/linux/deploy.test.bicep | 225 +++++ .../.test/windows.atmg/dependencies.bicep | 28 + .../.test/windows.atmg/deploy.test.bicep | 79 ++ .../.test/windows.autmg.parameters.json | 58 -- .../.test/windows.min.parameters.json | 55 -- .../.test/windows.min/dependencies.bicep | 28 + .../.test/windows.min/deploy.test.bicep | 77 ++ .../.test/windows.parameters.json | 238 ----- .../.test/windows/dependencies.bicep | 306 +++++++ .../.test/windows/deploy.test.bicep | 233 +++++ .../virtualMachines/readme.md | 858 +++++++++--------- utilities/tools/Set-ModuleReadMe.ps1 | 33 +- 23 files changed, 2165 insertions(+), 1132 deletions(-) create mode 100644 modules/Microsoft.Compute/virtualMachines/.test/.scripts/New-SSHKey.ps1 create mode 100644 modules/Microsoft.Compute/virtualMachines/.test/.scripts/Set-BlobContent.ps1 create mode 100644 modules/Microsoft.Compute/virtualMachines/.test/linux.atmg/dependencies.bicep create mode 100644 modules/Microsoft.Compute/virtualMachines/.test/linux.atmg/deploy.test.bicep delete mode 100644 modules/Microsoft.Compute/virtualMachines/.test/linux.autmg.parameters.json delete mode 100644 modules/Microsoft.Compute/virtualMachines/.test/linux.min.parameters.json create mode 100644 modules/Microsoft.Compute/virtualMachines/.test/linux.min/dependencies.bicep create mode 100644 modules/Microsoft.Compute/virtualMachines/.test/linux.min/deploy.test.bicep delete mode 100644 modules/Microsoft.Compute/virtualMachines/.test/linux.parameters.json create mode 100644 modules/Microsoft.Compute/virtualMachines/.test/linux/dependencies.bicep create mode 100644 modules/Microsoft.Compute/virtualMachines/.test/linux/deploy.test.bicep create mode 100644 modules/Microsoft.Compute/virtualMachines/.test/windows.atmg/dependencies.bicep create mode 100644 modules/Microsoft.Compute/virtualMachines/.test/windows.atmg/deploy.test.bicep delete mode 100644 modules/Microsoft.Compute/virtualMachines/.test/windows.autmg.parameters.json delete mode 100644 modules/Microsoft.Compute/virtualMachines/.test/windows.min.parameters.json create mode 100644 modules/Microsoft.Compute/virtualMachines/.test/windows.min/dependencies.bicep create mode 100644 modules/Microsoft.Compute/virtualMachines/.test/windows.min/deploy.test.bicep delete mode 100644 modules/Microsoft.Compute/virtualMachines/.test/windows.parameters.json create mode 100644 modules/Microsoft.Compute/virtualMachines/.test/windows/dependencies.bicep create mode 100644 modules/Microsoft.Compute/virtualMachines/.test/windows/deploy.test.bicep diff --git a/.github/workflows/ms.compute.virtualmachines.yml b/.github/workflows/ms.compute.virtualmachines.yml index bec15527fa..33d214bd98 100644 --- a/.github/workflows/ms.compute.virtualmachines.yml +++ b/.github/workflows/ms.compute.virtualmachines.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.Compute/virtualMachines/.test/.scripts/New-SSHKey.ps1 b/modules/Microsoft.Compute/virtualMachines/.test/.scripts/New-SSHKey.ps1 new file mode 100644 index 0000000000..44808c3ae4 --- /dev/null +++ b/modules/Microsoft.Compute/virtualMachines/.test/.scripts/New-SSHKey.ps1 @@ -0,0 +1,19 @@ +param( + [string] $SSHKeyName, + [string] $ResourceGroupName +) + +if (-not ($sshKey = Get-AzSshKey -ResourceGroupName $ResourceGroupName | Where-Object { $_.Name -eq $SSHKeyName })) { + Write-Verbose "No SSH key [$SSHKeyName] found in Resource Group [$ResourceGroupName]. Generating new." -Verbose + $null = ssh-keygen -f generated -N (Get-Random -Maximum 99999) + $publicKey = Get-Content 'generated.pub' -Raw + # $privateKey = cat generated | Out-String +} else { + Write-Verbose "SSH key [$SSHKeyName] found in Resource Group [$ResourceGroupName]. Returning." -Verbose + $publicKey = $sshKey.publicKey +} +# Write into Deployment Script output stream +$DeploymentScriptOutputs = @{ + # Requires conversion as the script otherwise returns an object instead of the plain public key string + publicKey = ($publicKey | ConvertTo-Json | ConvertFrom-Json).Value +} diff --git a/modules/Microsoft.Compute/virtualMachines/.test/.scripts/Set-BlobContent.ps1 b/modules/Microsoft.Compute/virtualMachines/.test/.scripts/Set-BlobContent.ps1 new file mode 100644 index 0000000000..06617105f7 --- /dev/null +++ b/modules/Microsoft.Compute/virtualMachines/.test/.scripts/Set-BlobContent.ps1 @@ -0,0 +1,15 @@ +param( + [string] $StorageAccountName, + [string] $ResourceGroupName, + [string] $ContainerName, + [string] $FileName +) + +Write-Verbose "Create file [$FileName]" -Verbose +$file = New-Item -Value "Write-Host 'I am content'" -Path $FileName -Force + +Write-Verbose "Getting storage account [$StorageAccountName|$ResourceGroupName] context." -Verbose +$storageAccount = Get-AzStorageAccount -ResourceGroupName $ResourceGroupName -StorageAccountName $StorageAccountName -ErrorAction 'Stop' + +Write-Verbose 'Uploading file [$fileName]' -Verbose +Set-AzStorageBlobContent -File $file.FullName -Container $ContainerName -Context $storageAccount.Context -Force -ErrorAction 'Stop' | Out-Null diff --git a/modules/Microsoft.Compute/virtualMachines/.test/linux.atmg/dependencies.bicep b/modules/Microsoft.Compute/virtualMachines/.test/linux.atmg/dependencies.bicep new file mode 100644 index 0000000000..54adfbd454 --- /dev/null +++ b/modules/Microsoft.Compute/virtualMachines/.test/linux.atmg/dependencies.bicep @@ -0,0 +1,87 @@ +@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 Deployment Script to create for the SSH Key generation.') +param sshDeploymentScriptName string + +@description('Required. The name of the SSH Key to create.') +param sshKeyName string + +@description('Optional. The location to deploy resources to.') +param location string = resourceGroup().location + +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 managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2018-11-30' = { + name: managedIdentityName + location: location +} + +resource msiRGContrRoleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = { + name: guid('msi-${resourceGroup().id}-${location}-${managedIdentity.id}-ResourceGroup-Reader-RoleAssignment') + scope: resourceGroup() + properties: { + principalId: managedIdentity.properties.principalId + roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') // Contributor + principalType: 'ServicePrincipal' + } +} + +resource sshDeploymentScript 'Microsoft.Resources/deploymentScripts@2020-10-01' = { + name: sshDeploymentScriptName + location: location + kind: 'AzurePowerShell' + identity: { + type: 'UserAssigned' + userAssignedIdentities: { + '${managedIdentity.id}': {} + } + } + properties: { + azPowerShellVersion: '6.2.1' + retentionInterval: 'P1D' + arguments: ' -SSHKeyName "${sshKeyName}" -ResourceGroupName "${resourceGroup().name}"' + scriptContent: loadTextContent('../.scripts/New-SSHKey.ps1') + } + dependsOn: [ + msiRGContrRoleAssignment + ] +} + +resource sshKey 'Microsoft.Compute/sshPublicKeys@2022-03-01' = { + name: sshKeyName + location: location + properties: { + publicKey: sshDeploymentScript.properties.outputs.publicKey + } +} + +@description('The resource ID of the created Virtual Network Subnet') +output subnetResourceId string = virtualNetwork.properties.subnets[0].id + +@description('The resource ID of the created SSH Key') +output SSHKeyResourceID string = sshKey.id + +@description('The Public Key of the created SSH Key') +output SSHKey string = sshKey.properties.publicKey diff --git a/modules/Microsoft.Compute/virtualMachines/.test/linux.atmg/deploy.test.bicep b/modules/Microsoft.Compute/virtualMachines/.test/linux.atmg/deploy.test.bicep new file mode 100644 index 0000000000..c95de415ed --- /dev/null +++ b/modules/Microsoft.Compute/virtualMachines/.test/linux.atmg/deploy.test.bicep @@ -0,0 +1,95 @@ +targetScope = 'subscription' + +// ========== // +// Parameters // +// ========== // +@description('Optional. The name of the resource group to deploy for testing purposes.') +@maxLength(80) +param resourceGroupName string = 'ms.compute.virtualMachines-${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 = 'cvmlinatmg' + +// =========== // +// 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)}-nestedDependencies' + params: { + location: location + virtualNetworkName: 'dep-<>-vnet-${serviceShort}' + sshDeploymentScriptName: 'dep-<>-ds-${serviceShort}' + sshKeyName: 'dep-<>-ssh-${serviceShort}' + managedIdentityName: 'dep-<>-msi-${serviceShort}' + } +} + +// ============== // +// Test Execution // +// ============== // + +// resource sshKey 'Microsoft.Compute/sshPublicKeys@2022-03-01' existing = { +// name: sshKeyName +// scope: resourceGroup +// } + +module testDeployment '../../deploy.bicep' = { + scope: resourceGroup + name: '${uniqueString(deployment().name)}-test-${serviceShort}' + params: { + location: location + name: '<>${serviceShort}' + adminUsername: 'localAdminUser' + imageReference: { + offer: 'UbuntuServer' + publisher: 'Canonical' + sku: '18.04-LTS' + version: 'latest' + } + nicConfigurations: [ + { + ipConfigurations: [ + { + name: 'ipconfig01' + pipConfiguration: { + publicIpNameSuffix: '-pip-01' + } + subnetResourceId: resourceGroupResources.outputs.subnetResourceId + } + ] + nicSuffix: '-nic-01' + } + ] + osDisk: { + diskSizeGB: '128' + managedDisk: { + storageAccountType: 'Premium_LRS' + } + } + osType: 'Linux' + vmSize: 'Standard_B12ms' + configurationProfile: '/providers/Microsoft.Automanage/bestPractices/AzureBestPracticesProduction' + disablePasswordAuthentication: true + publicKeys: [ + { + keyData: resourceGroupResources.outputs.SSHKey + path: '/home/localAdminUser/.ssh/authorized_keys' + } + ] + } + dependsOn: [ + resourceGroupResources // Required to leverage `existing` SSH key reference + ] +} diff --git a/modules/Microsoft.Compute/virtualMachines/.test/linux.autmg.parameters.json b/modules/Microsoft.Compute/virtualMachines/.test/linux.autmg.parameters.json deleted file mode 100644 index f375587dcf..0000000000 --- a/modules/Microsoft.Compute/virtualMachines/.test/linux.autmg.parameters.json +++ /dev/null @@ -1,64 +0,0 @@ -{ - "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", - "contentVersion": "1.0.0.0", - "parameters": { - "name": { - "value": "<>-vm-linux-autmg-01" - }, - "osType": { - "value": "Linux" - }, - "imageReference": { - "value": { - "publisher": "Canonical", - "offer": "UbuntuServer", - "sku": "18.04-LTS", - "version": "latest" - } - }, - "osDisk": { - "value": { - "diskSizeGB": "128", - "managedDisk": { - "storageAccountType": "Premium_LRS" - } - } - }, - "vmSize": { - "value": "Standard_B12ms" - }, - "adminUsername": { - "value": "localAdminUser" - }, - "disablePasswordAuthentication": { - "value": true - }, - "publicKeys": { - "value": [ - { - "path": "/home/localAdminUser/.ssh/authorized_keys", - "keyData": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDdOir5eO28EBwxU0Dyra7g9h0HUXDyMNFp2z8PhaTUQgHjrimkMxjYRwEOG/lxnYL7+TqZk+HcPTfbZOunHBw0Wx2CITzILt6531vmIYZGfq5YyYXbxZa5MON7L/PVivoRlPj5Z/t4RhqMhyfR7EPcZ516LJ8lXPTo8dE/bkOCS+kFBEYHvPEEKAyLs19sRcK37SeHjpX04zdg62nqtuRr00Tp7oeiTXA1xn5K5mxeAswotmd8CU0lWUcJuPBWQedo649b+L2cm52kTncOBI6YChAeyEc1PDF0Tn9FmpdOWKtI9efh+S3f8qkcVEtSTXoTeroBd31nzjAunMrZeM8Ut6dre+XeQQIjT7I8oEm+ZkIuIyq0x2fls8JXP2YJDWDqu8v1+yLGTQ3Z9XVt2lMti/7bIgYxS0JvwOr5n5L4IzKvhb4fm13LLDGFa3o7Nsfe3fPb882APE0bLFCmfyIeiPh7go70WqZHakpgIr6LCWTyePez9CsI/rfWDb6eAM8= generated-by-azure" - } - ] - }, - "nicConfigurations": { - "value": [ - { - "nicSuffix": "-nic-01", - "ipConfigurations": [ - { - "name": "ipconfig01", - "subnetResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/adp-<>-az-vnet-x-001/subnets/<>-az-subnet-x-001", - "pipConfiguration": { - "publicIpNameSuffix": "-pip-01" - } - } - ] - } - ] - }, - "configurationProfile": { - "value": "/providers/Microsoft.Automanage/bestPractices/AzureBestPracticesProduction" - } - } -} diff --git a/modules/Microsoft.Compute/virtualMachines/.test/linux.min.parameters.json b/modules/Microsoft.Compute/virtualMachines/.test/linux.min.parameters.json deleted file mode 100644 index ac54d9aaee..0000000000 --- a/modules/Microsoft.Compute/virtualMachines/.test/linux.min.parameters.json +++ /dev/null @@ -1,61 +0,0 @@ -{ - "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", - "contentVersion": "1.0.0.0", - "parameters": { - "name": { - "value": "<>-vm-linux-min-01" - }, - "osType": { - "value": "Linux" - }, - "imageReference": { - "value": { - "publisher": "Canonical", - "offer": "UbuntuServer", - "sku": "18.04-LTS", - "version": "latest" - } - }, - "osDisk": { - "value": { - "diskSizeGB": "128", - "managedDisk": { - "storageAccountType": "Premium_LRS" - } - } - }, - "vmSize": { - "value": "Standard_B12ms" - }, - "adminUsername": { - "value": "localAdminUser" - }, - "disablePasswordAuthentication": { - "value": true - }, - "publicKeys": { - "value": [ - { - "path": "/home/localAdminUser/.ssh/authorized_keys", - "keyData": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDdOir5eO28EBwxU0Dyra7g9h0HUXDyMNFp2z8PhaTUQgHjrimkMxjYRwEOG/lxnYL7+TqZk+HcPTfbZOunHBw0Wx2CITzILt6531vmIYZGfq5YyYXbxZa5MON7L/PVivoRlPj5Z/t4RhqMhyfR7EPcZ516LJ8lXPTo8dE/bkOCS+kFBEYHvPEEKAyLs19sRcK37SeHjpX04zdg62nqtuRr00Tp7oeiTXA1xn5K5mxeAswotmd8CU0lWUcJuPBWQedo649b+L2cm52kTncOBI6YChAeyEc1PDF0Tn9FmpdOWKtI9efh+S3f8qkcVEtSTXoTeroBd31nzjAunMrZeM8Ut6dre+XeQQIjT7I8oEm+ZkIuIyq0x2fls8JXP2YJDWDqu8v1+yLGTQ3Z9XVt2lMti/7bIgYxS0JvwOr5n5L4IzKvhb4fm13LLDGFa3o7Nsfe3fPb882APE0bLFCmfyIeiPh7go70WqZHakpgIr6LCWTyePez9CsI/rfWDb6eAM8= generated-by-azure" - } - ] - }, - "nicConfigurations": { - "value": [ - { - "nicSuffix": "-nic-01", - "ipConfigurations": [ - { - "name": "ipconfig01", - "subnetResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/adp-<>-az-vnet-x-001/subnets/<>-az-subnet-x-001", - "pipConfiguration": { - "publicIpNameSuffix": "-pip-01" - } - } - ] - } - ] - } - } -} diff --git a/modules/Microsoft.Compute/virtualMachines/.test/linux.min/dependencies.bicep b/modules/Microsoft.Compute/virtualMachines/.test/linux.min/dependencies.bicep new file mode 100644 index 0000000000..731da6549b --- /dev/null +++ b/modules/Microsoft.Compute/virtualMachines/.test/linux.min/dependencies.bicep @@ -0,0 +1,87 @@ +@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 Deployment Script to create for the SSH Key generation.') +param sshDeploymentScriptName string + +@description('Required. The name of the SSH Key to create.') +param sshKeyName string + +@description('Optional. The location to deploy resources to.') +param location string = resourceGroup().location + +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 managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2018-11-30' = { + name: managedIdentityName + location: location +} + +resource msiRGContrRoleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = { + name: guid('msi-${resourceGroup().id}-${location}-${managedIdentity.id}-ResourceGroup-Reader-RoleAssignment') + scope: resourceGroup() + properties: { + principalId: managedIdentity.properties.principalId + roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') // Contributor + principalType: 'ServicePrincipal' + } +} + +resource sshDeploymentScript 'Microsoft.Resources/deploymentScripts@2020-10-01' = { + name: sshDeploymentScriptName + location: location + kind: 'AzurePowerShell' + identity: { + type: 'UserAssigned' + userAssignedIdentities: { + '${managedIdentity.id}': {} + } + } + properties: { + azPowerShellVersion: '6.2.1' + retentionInterval: 'P1D' + arguments: '-SSHKeyName "${sshKeyName}" -ResourceGroupName "${resourceGroup().name}"' + scriptContent: loadTextContent('../.scripts/New-SSHKey.ps1') + } + dependsOn: [ + msiRGContrRoleAssignment + ] +} + +resource sshKey 'Microsoft.Compute/sshPublicKeys@2022-03-01' = { + name: sshKeyName + location: location + properties: { + publicKey: sshDeploymentScript.properties.outputs.publicKey + } +} + +@description('The resource ID of the created Virtual Network Subnet') +output subnetResourceId string = virtualNetwork.properties.subnets[0].id + +@description('The resource ID of the created SSH Key') +output SSHKeyResourceID string = sshKey.id + +@description('The Public Key of the created SSH Key') +output SSHKey string = sshKey.properties.publicKey diff --git a/modules/Microsoft.Compute/virtualMachines/.test/linux.min/deploy.test.bicep b/modules/Microsoft.Compute/virtualMachines/.test/linux.min/deploy.test.bicep new file mode 100644 index 0000000000..f6eb2b0581 --- /dev/null +++ b/modules/Microsoft.Compute/virtualMachines/.test/linux.min/deploy.test.bicep @@ -0,0 +1,94 @@ +targetScope = 'subscription' + +// ========== // +// Parameters // +// ========== // +@description('Optional. The name of the resource group to deploy for testing purposes.') +@maxLength(80) +param resourceGroupName string = 'ms.compute.virtualMachines-${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 = 'cvmlinmin' + +// =========== // +// 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)}-nestedDependencies' + params: { + location: location + virtualNetworkName: 'dep-<>-vnet-${serviceShort}' + managedIdentityName: 'dep-<>-msi-${serviceShort}' + sshDeploymentScriptName: 'dep-<>-ds-${serviceShort}' + sshKeyName: 'dep-<>-ssh-${serviceShort}' + } +} + +// ============== // +// Test Execution // +// ============== // + +// resource sshKey 'Microsoft.Compute/sshPublicKeys@2022-03-01' existing = { +// name: sshKeyName +// scope: resourceGroup +// } + +module testDeployment '../../deploy.bicep' = { + scope: resourceGroup + name: '${uniqueString(deployment().name)}-test-${serviceShort}' + params: { + location: location + name: '<>${serviceShort}' + adminUsername: 'localAdminUser' + imageReference: { + offer: 'UbuntuServer' + publisher: 'Canonical' + sku: '18.04-LTS' + version: 'latest' + } + nicConfigurations: [ + { + ipConfigurations: [ + { + name: 'ipconfig01' + pipConfiguration: { + publicIpNameSuffix: '-pip-01' + } + subnetResourceId: resourceGroupResources.outputs.subnetResourceId + } + ] + nicSuffix: '-nic-01' + } + ] + osDisk: { + diskSizeGB: '128' + managedDisk: { + storageAccountType: 'Premium_LRS' + } + } + osType: 'Linux' + vmSize: 'Standard_B12ms' + disablePasswordAuthentication: true + publicKeys: [ + { + keyData: resourceGroupResources.outputs.SSHKey + path: '/home/localAdminUser/.ssh/authorized_keys' + } + ] + } + dependsOn: [ + resourceGroupResources // Required to leverage `existing` SSH key reference + ] +} diff --git a/modules/Microsoft.Compute/virtualMachines/.test/linux.parameters.json b/modules/Microsoft.Compute/virtualMachines/.test/linux.parameters.json deleted file mode 100644 index 05938fb23a..0000000000 --- a/modules/Microsoft.Compute/virtualMachines/.test/linux.parameters.json +++ /dev/null @@ -1,218 +0,0 @@ -{ - "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", - "contentVersion": "1.0.0.0", - "parameters": { - "name": { - "value": "<>-vm-linux-01" - }, - "lock": { - "value": "CanNotDelete" - }, - "systemAssignedIdentity": { - "value": true - }, - "userAssignedIdentities": { - "value": { - "/subscriptions/<>/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-<>-az-msi-x-001": {} - } - }, - "osType": { - "value": "Linux" - }, - "encryptionAtHost": { - "value": false - }, - "availabilityZone": { - "value": 1 - }, - "vmSize": { - "value": "Standard_B12ms" - }, - "imageReference": { - "value": { - "publisher": "Canonical", - "offer": "UbuntuServer", - "sku": "18.04-LTS", - "version": "latest" - } - }, - "osDisk": { - "value": { - "createOption": "fromImage", - "deleteOption": "Delete", - "caching": "ReadOnly", - "diskSizeGB": "128", - "managedDisk": { - "storageAccountType": "Premium_LRS" - } - } - }, - "dataDisks": { - "value": [ - { - "createOption": "Empty", - "deleteOption": "Delete", - "caching": "ReadWrite", - "diskSizeGB": "128", - "managedDisk": { - "storageAccountType": "Premium_LRS" - } - }, - { - "createOption": "Empty", - "deleteOption": "Delete", - "caching": "ReadWrite", - "diskSizeGB": "128", - "managedDisk": { - "storageAccountType": "Premium_LRS" - } - } - ] - }, - "adminUsername": { - "value": "localAdminUser" - }, - "disablePasswordAuthentication": { - "value": true - }, - "publicKeys": { - "value": [ - { - "path": "/home/localAdminUser/.ssh/authorized_keys", - "keyData": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDdOir5eO28EBwxU0Dyra7g9h0HUXDyMNFp2z8PhaTUQgHjrimkMxjYRwEOG/lxnYL7+TqZk+HcPTfbZOunHBw0Wx2CITzILt6531vmIYZGfq5YyYXbxZa5MON7L/PVivoRlPj5Z/t4RhqMhyfR7EPcZ516LJ8lXPTo8dE/bkOCS+kFBEYHvPEEKAyLs19sRcK37SeHjpX04zdg62nqtuRr00Tp7oeiTXA1xn5K5mxeAswotmd8CU0lWUcJuPBWQedo649b+L2cm52kTncOBI6YChAeyEc1PDF0Tn9FmpdOWKtI9efh+S3f8qkcVEtSTXoTeroBd31nzjAunMrZeM8Ut6dre+XeQQIjT7I8oEm+ZkIuIyq0x2fls8JXP2YJDWDqu8v1+yLGTQ3Z9XVt2lMti/7bIgYxS0JvwOr5n5L4IzKvhb4fm13LLDGFa3o7Nsfe3fPb882APE0bLFCmfyIeiPh7go70WqZHakpgIr6LCWTyePez9CsI/rfWDb6eAM8= generated-by-azure" - } - ] - }, - "nicConfigurations": { - "value": [ - { - "nicSuffix": "-nic-01", - "deleteOption": "Delete", - "ipConfigurations": [ - { - "name": "ipconfig01", - "subnetResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/adp-<>-az-vnet-x-001/subnets/<>-az-subnet-x-001", - "pipConfiguration": { - "publicIpNameSuffix": "-pip-01", - "roleAssignments": [ - { - "roleDefinitionIdOrName": "Reader", - "principalIds": [ - "<>" - ] - } - ] - }, - "loadBalancerBackendAddressPools": [ - { - "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/loadBalancers/adp-<>-az-lb-internal-001/backendAddressPools/servers" - } - ], - "applicationSecurityGroups": [ - { - "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/applicationSecurityGroups/adp-<>-az-asg-x-001" - } - ] - } - ], - "roleAssignments": [ - { - "roleDefinitionIdOrName": "Reader", - "principalIds": [ - "<>" - ] - } - ] - } - ] - }, - "backupVaultName": { - "value": "adp-<>-az-rsv-x-001" - }, - "backupVaultResourceGroup": { - "value": "validation-rg" - }, - "backupPolicyName": { - "value": "VMpolicy" - }, - "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" - }, - "extensionMonitoringAgentConfig": { - "value": { - "enabled": true - } - }, - "monitoringWorkspaceId": { - "value": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001" - }, - "extensionDependencyAgentConfig": { - "value": { - "enabled": true - } - }, - "extensionNetworkWatcherAgentConfig": { - "value": { - "enabled": true - } - }, - "extensionDiskEncryptionConfig": { - "value": { - "enabled": true, - "settings": { - "EncryptionOperation": "EnableEncryption", - "KeyVaultURL": "https://adp-<>-az-kv-x-001.vault.azure.net/", - "KeyVaultResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.KeyVault/vaults/adp-<>-az-kv-x-001", - "KeyEncryptionKeyURL": "https://adp-<>-az-kv-x-001.vault.azure.net/keys/keyEncryptionKey/bc3bb46d95c64367975d722f473eeae5", // ID must be updated for new keys - "KekVaultResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.KeyVault/vaults/adp-<>-az-kv-x-001", - "KeyEncryptionAlgorithm": "RSA-OAEP", - "VolumeType": "All", - "ResizeOSDisk": "false" - } - } - }, - "extensionDSCConfig": { - "value": { - "enabled": false - } - }, - "extensionCustomScriptConfig": { - "value": { - "enabled": true, - "fileData": [ - { - "uri": "https://adp<>azsax001.blob.core.windows.net/scripts/scriptExtensionMasterInstaller.ps1", - "storageAccountId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001" - } - ] - } - }, - "extensionCustomScriptProtectedSetting": { - "value": { - "commandToExecute": "sudo apt-get update" - } - } - } -} diff --git a/modules/Microsoft.Compute/virtualMachines/.test/linux/dependencies.bicep b/modules/Microsoft.Compute/virtualMachines/.test/linux/dependencies.bicep new file mode 100644 index 0000000000..f398b4e810 --- /dev/null +++ b/modules/Microsoft.Compute/virtualMachines/.test/linux/dependencies.bicep @@ -0,0 +1,336 @@ +@description('Required. The name of the Virtual Network to create.') +param virtualNetworkName string + +@description('Required. The name of the Application Security Group to create.') +param applicationSecurityGroupName string + +@description('Required. The name of the Managed Identity to create.') +param managedIdentityName string + +@description('Required. The name of the Load Balancer to create.') +param loadBalancerName string + +@description('Required. The name of the Recovery Services Vault to create.') +param recoveryServicesVaultName string + +@description('Required. The name of the Key Vault to create.') +param keyVaultName string + +@description('Required. The name of the Storage Account to create.') +param storageAccountName string + +@description('Required. The name of the Deployment Script used to upload data to the Storage Account.') +param storageUploadDeploymentScriptName string + +@description('Required. The name of the Deployment Script to create for the SSH Key generation.') +param sshDeploymentScriptName string + +@description('Required. The name of the SSH Key to create.') +param sshKeyName string + +@description('Optional. The location to deploy to.') +param location string = resourceGroup().location + +var storageContainerName = 'scripts' +var storageAccountCSEFileName = 'scriptExtensionMasterInstaller.ps1' +var backupPolicyName = 'backupPolicy' + +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 applicationSecurityGroup 'Microsoft.Network/applicationSecurityGroups@2022-01-01' = { + name: applicationSecurityGroupName + location: location +} + +resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2018-11-30' = { + name: managedIdentityName + location: location +} + +resource msiRGContrRoleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = { + name: guid('msi-${resourceGroup().id}-${location}-${managedIdentity.id}-ResourceGroup-Contributor-RoleAssignment') + scope: resourceGroup() + properties: { + principalId: managedIdentity.properties.principalId + roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') // Contributor + principalType: 'ServicePrincipal' + } +} + +resource loadBalancer 'Microsoft.Network/loadBalancers@2022-01-01' = { + name: loadBalancerName + location: location + sku: { + name: 'Standard' + } + properties: { + frontendIPConfigurations: [ + { + name: 'privateIPConfig1' + properties: { + subnet: virtualNetwork.properties.subnets[0] + } + } + ] + backendAddressPools: [ + { + name: 'servers' + } + ] + } +} + +resource recoveryServicesVault 'Microsoft.RecoveryServices/vaults@2022-04-01' = { + name: recoveryServicesVaultName + location: location + sku: { + name: 'RS0' + tier: 'Standard' + } + properties: { + } + + resource backupPolicy 'backupPolicies@2022-03-01' = { + name: backupPolicyName + properties: { + backupManagementType: 'AzureIaasVM' + instantRPDetails: {} + schedulePolicy: { + schedulePolicyType: 'SimpleSchedulePolicy' + scheduleRunFrequency: 'Daily' + scheduleRunTimes: [ + '2019-11-07T07:00:00Z' + ] + scheduleWeeklyFrequency: 0 + } + retentionPolicy: { + retentionPolicyType: 'LongTermRetentionPolicy' + dailySchedule: { + retentionTimes: [ + '2019-11-07T07:00:00Z' + ] + retentionDuration: { + count: 180 + durationType: 'Days' + } + } + weeklySchedule: { + daysOfTheWeek: [ + 'Sunday' + ] + retentionTimes: [ + '2019-11-07T07:00:00Z' + ] + retentionDuration: { + count: 12 + durationType: 'Weeks' + } + } + monthlySchedule: { + retentionScheduleFormatType: 'Weekly' + retentionScheduleWeekly: { + daysOfTheWeek: [ + 'Sunday' + ] + weeksOfTheMonth: [ + 'First' + ] + } + retentionTimes: [ + '2019-11-07T07:00:00Z' + ] + retentionDuration: { + count: 60 + durationType: 'Months' + } + } + yearlySchedule: { + retentionScheduleFormatType: 'Weekly' + monthsOfYear: [ + 'January' + ] + retentionScheduleWeekly: { + daysOfTheWeek: [ + 'Sunday' + ] + weeksOfTheMonth: [ + 'First' + ] + } + retentionTimes: [ + '2019-11-07T07:00:00Z' + ] + retentionDuration: { + count: 10 + durationType: 'Years' + } + } + } + instantRpRetentionRangeInDays: 2 + timeZone: 'UTC' + protectedItemsCount: 0 + } + } +} + +resource keyVault 'Microsoft.KeyVault/vaults@2022-07-01' = { + name: keyVaultName + location: location + properties: { + sku: { + family: 'A' + name: 'standard' + } + tenantId: tenant().tenantId + enablePurgeProtection: null + enabledForTemplateDeployment: true + enabledForDiskEncryption: true + enabledForDeployment: true + enableRbacAuthorization: true + accessPolicies: [] + } + + resource key 'keys@2022-07-01' = { + name: 'encryptionKey' + properties: { + kty: 'RSA' + } + } +} + +resource msiKVCryptoUserRoleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = { + name: guid('msi-${keyVault::key.id}-${location}-${managedIdentity.id}-KeyVault-Key-Read-RoleAssignment') + scope: keyVault::key + properties: { + principalId: managedIdentity.properties.principalId + roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '12338af0-0e69-4776-bea7-57ae8d297424') // Key Vault Crypto User + principalType: 'ServicePrincipal' + } +} + +resource storageAccount 'Microsoft.Storage/storageAccounts@2021-09-01' = { + name: storageAccountName + location: location + sku: { + name: 'Standard_LRS' + } + kind: 'StorageV2' + + resource blobService 'blobServices@2021-09-01' = { + name: 'default' + + resource container 'containers@2021-09-01' = { + name: storageContainerName + } + } +} + +resource storageUpload 'Microsoft.Resources/deploymentScripts@2020-10-01' = { + name: storageUploadDeploymentScriptName + location: location + kind: 'AzurePowerShell' + identity: { + type: 'UserAssigned' + userAssignedIdentities: { + '${managedIdentity.id}': {} + } + } + properties: { + azPowerShellVersion: '3.0' + retentionInterval: 'P1D' + arguments: '-StorageAccountName "${storageAccount.name}" -ResourceGroupName "${resourceGroup().name}" -ContainerName "${storageAccount::blobService::container.name}" -FileName "${storageAccountCSEFileName}"' + scriptContent: loadTextContent('../.scripts/Set-BlobContent.ps1') + } + dependsOn: [ + msiRGContrRoleAssignment + ] +} + +resource sshDeploymentScript 'Microsoft.Resources/deploymentScripts@2020-10-01' = { + name: sshDeploymentScriptName + location: location + kind: 'AzurePowerShell' + identity: { + type: 'UserAssigned' + userAssignedIdentities: { + '${managedIdentity.id}': {} + } + } + properties: { + azPowerShellVersion: '6.2.1' + retentionInterval: 'P1D' + arguments: '-SSHKeyName "${sshKeyName}" -ResourceGroupName "${resourceGroup().name}"' + scriptContent: loadTextContent('../.scripts/New-SSHKey.ps1') + } + dependsOn: [ + msiRGContrRoleAssignment + ] +} + +resource sshKey 'Microsoft.Compute/sshPublicKeys@2022-03-01' = { + name: sshKeyName + location: location + properties: { + publicKey: sshDeploymentScript.properties.outputs.publicKey + } +} + +@description('The resource ID of the created Virtual Network Subnet.') +output subnetResourceId string = virtualNetwork.properties.subnets[0].id + +@description('The resource ID of the created Application Security Group.') +output applicationSecurityGroupResourceId string = applicationSecurityGroup.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 Load Balancer Backend Pool.') +output loadBalancerBackendPoolResourceId string = loadBalancer.properties.backendAddressPools[0].id + +@description('The resource ID of the created Recovery Services Vault.') +output recoveryServicesVaultResourceId string = recoveryServicesVault.id + +@description('The name of the Backup Policy created in the Backup Recovery Vault.') +output recoveryServicesVaultBackupPolicyName string = backupPolicyName + +@description('The resource ID of the created Key Vault.') +output keyVaultResourceId string = keyVault.id + +@description('The URL of the created Key Vault.') +output keyVaultUrl string = keyVault.properties.vaultUri + +@description('The URL of the created Key Vault Encryption Key.') +output keyVaultEncryptionKeyUrl string = keyVault::key.properties.keyUriWithVersion + +@description('The resource ID of the created Storage Account.') +output storageAccountResourceId string = storageAccount.id + +@description('The URL of the Custom Script Extension in the created Storage Account') +output storageAccountCSEFileUrl string = '${storageAccount.properties.primaryEndpoints.blob}${storageContainerName}/${storageAccountCSEFileName}' + +@description('The resource ID of the created SSH Key') +output SSHKeyResourceID string = sshKey.id + +@description('The Public Key of the created SSH Key') +output SSHKey string = sshKey.properties.publicKey diff --git a/modules/Microsoft.Compute/virtualMachines/.test/linux/deploy.test.bicep b/modules/Microsoft.Compute/virtualMachines/.test/linux/deploy.test.bicep new file mode 100644 index 0000000000..f990ab5eea --- /dev/null +++ b/modules/Microsoft.Compute/virtualMachines/.test/linux/deploy.test.bicep @@ -0,0 +1,225 @@ +targetScope = 'subscription' + +// ========== // +// Parameters // +// ========== // +@description('Optional. The name of the resource group to deploy for testing purposes.') +@maxLength(80) +param resourceGroupName string = 'ms.compute.virtualMachines-${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 = 'cvmlindef' + +// =========== // +// 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)}-nestedDependencies' + params: { + location: location + virtualNetworkName: 'dep-<>-vnet-${serviceShort}' + applicationSecurityGroupName: 'adp-<>-asg-${serviceShort}' + managedIdentityName: 'dep-<>-msi-${serviceShort}' + keyVaultName: 'dep-<>-kv-${serviceShort}' + loadBalancerName: 'dep-<>-lb-${serviceShort}' + recoveryServicesVaultName: 'dep-<>-rsv-${serviceShort}' + storageAccountName: 'dep<>sa${serviceShort}01' + storageUploadDeploymentScriptName: 'dep-<>-sads-${serviceShort}' + sshDeploymentScriptName: 'dep-<>-ds-${serviceShort}' + sshKeyName: 'dep-<>-ssh-${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 // +// ============== // + +// resource sshKey 'Microsoft.Compute/sshPublicKeys@2022-03-01' existing = { +// name: sshKeyName +// scope: resourceGroup +// } + +module testDeployment '../../deploy.bicep' = { + scope: resourceGroup + name: '${uniqueString(deployment().name)}-test-${serviceShort}' + params: { + name: '<>${serviceShort}' + location: location + adminUsername: 'localAdminUser' + imageReference: { + offer: 'UbuntuServer' + publisher: 'Canonical' + sku: '18.04-LTS' + version: 'latest' + } + nicConfigurations: [ + { + deleteOption: 'Delete' + ipConfigurations: [ + { + applicationSecurityGroups: [ + { + id: resourceGroupResources.outputs.applicationSecurityGroupResourceId + } + ] + loadBalancerBackendAddressPools: [ + { + id: resourceGroupResources.outputs.loadBalancerBackendPoolResourceId + } + ] + name: 'ipconfig01' + pipConfiguration: { + publicIpNameSuffix: '-pip-01' + roleAssignments: [ + { + principalIds: [ + resourceGroupResources.outputs.managedIdentityPrincipalId + ] + roleDefinitionIdOrName: 'Reader' + } + ] + } + subnetResourceId: resourceGroupResources.outputs.subnetResourceId + } + ] + nicSuffix: '-nic-01' + roleAssignments: [ + { + principalIds: [ + resourceGroupResources.outputs.managedIdentityPrincipalId + ] + roleDefinitionIdOrName: 'Reader' + } + ] + } + ] + osDisk: { + caching: 'ReadOnly' + createOption: 'fromImage' + deleteOption: 'Delete' + diskSizeGB: '128' + managedDisk: { + storageAccountType: 'Premium_LRS' + } + } + osType: 'Linux' + vmSize: 'Standard_B12ms' + availabilityZone: 1 + backupPolicyName: resourceGroupResources.outputs.recoveryServicesVaultBackupPolicyName + backupVaultName: last(split(resourceGroupResources.outputs.recoveryServicesVaultResourceId, '/')) + backupVaultResourceGroup: (split(resourceGroupResources.outputs.recoveryServicesVaultResourceId, '/'))[4] + dataDisks: [ + { + caching: 'ReadWrite' + createOption: 'Empty' + deleteOption: 'Delete' + diskSizeGB: '128' + managedDisk: { + storageAccountType: 'Premium_LRS' + } + } + { + caching: 'ReadWrite' + createOption: 'Empty' + deleteOption: 'Delete' + diskSizeGB: '128' + managedDisk: { + storageAccountType: 'Premium_LRS' + } + } + ] + diagnosticStorageAccountId: diagnosticDependencies.outputs.storageAccountResourceId + diagnosticWorkspaceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId + diagnosticEventHubAuthorizationRuleId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId + diagnosticEventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName + diagnosticLogsRetentionInDays: 7 + disablePasswordAuthentication: true + encryptionAtHost: false + extensionCustomScriptConfig: { + enabled: true + fileData: [ + { + storageAccountId: resourceGroupResources.outputs.storageAccountResourceId + uri: resourceGroupResources.outputs.storageAccountCSEFileUrl + } + ] + } + extensionCustomScriptProtectedSetting: { + commandToExecute: 'value=$(./${last(split(resourceGroupResources.outputs.storageAccountCSEFileUrl, '/'))}); echo "$value"' + } + extensionDependencyAgentConfig: { + enabled: true + } + extensionDiskEncryptionConfig: { + enabled: true + settings: { + EncryptionOperation: 'EnableEncryption' + KekVaultResourceId: resourceGroupResources.outputs.keyVaultResourceId + KeyEncryptionAlgorithm: 'RSA-OAEP' + KeyEncryptionKeyURL: resourceGroupResources.outputs.keyVaultEncryptionKeyUrl + KeyVaultResourceId: resourceGroupResources.outputs.keyVaultResourceId + KeyVaultURL: resourceGroupResources.outputs.keyVaultUrl + ResizeOSDisk: 'false' + VolumeType: 'All' + } + } + extensionDSCConfig: { + enabled: false + } + extensionMonitoringAgentConfig: { + enabled: true + } + extensionNetworkWatcherAgentConfig: { + enabled: true + } + lock: 'CanNotDelete' + monitoringWorkspaceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId + publicKeys: [ + { + keyData: resourceGroupResources.outputs.SSHKey + path: '/home/localAdminUser/.ssh/authorized_keys' + } + ] + roleAssignments: [ + { + principalIds: [ + resourceGroupResources.outputs.managedIdentityPrincipalId + ] + roleDefinitionIdOrName: 'Reader' + } + ] + systemAssignedIdentity: true + userAssignedIdentities: { + '${resourceGroupResources.outputs.managedIdentityResourceId}': {} + } + } + dependsOn: [ + resourceGroupResources // Required to leverage `existing` SSH key reference + ] +} diff --git a/modules/Microsoft.Compute/virtualMachines/.test/windows.atmg/dependencies.bicep b/modules/Microsoft.Compute/virtualMachines/.test/windows.atmg/dependencies.bicep new file mode 100644 index 0000000000..b6ce61cfcd --- /dev/null +++ b/modules/Microsoft.Compute/virtualMachines/.test/windows.atmg/dependencies.bicep @@ -0,0 +1,28 @@ +@description('Required. The name of the Virtual Network to create.') +param virtualNetworkName string + +@description('Optional. The location to deploy resources to.') +param location string = resourceGroup().location + +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' + } + } + ] + } +} + +@description('The resource ID of the created Virtual Network Subnet') +output subnetResourceId string = virtualNetwork.properties.subnets[0].id diff --git a/modules/Microsoft.Compute/virtualMachines/.test/windows.atmg/deploy.test.bicep b/modules/Microsoft.Compute/virtualMachines/.test/windows.atmg/deploy.test.bicep new file mode 100644 index 0000000000..164199f3c5 --- /dev/null +++ b/modules/Microsoft.Compute/virtualMachines/.test/windows.atmg/deploy.test.bicep @@ -0,0 +1,79 @@ +targetScope = 'subscription' + +// ========== // +// Parameters // +// ========== // +@description('Optional. The name of the resource group to deploy for testing purposes.') +@maxLength(80) +param resourceGroupName string = 'ms.compute.virtualMachines-${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 = 'cvmwinatmg' + +@description('Optional. The password to leverage for the login.') +@secure() +param password string = newGuid() + +// =========== // +// 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)}-nestedDependencies' + params: { + location: location + virtualNetworkName: 'dep-<>-vnet-${serviceShort}' + } +} + +// ============== // +// Test Execution // +// ============== // + +module testDeployment '../../deploy.bicep' = { + scope: resourceGroup + name: '${uniqueString(deployment().name)}-test-${serviceShort}' + params: { + location: location + name: '<>${serviceShort}' + adminUsername: 'localAdminUser' + imageReference: { + offer: 'WindowsServer' + publisher: 'MicrosoftWindowsServer' + sku: '2019-Datacenter' + version: 'latest' + } + nicConfigurations: [ + { + ipConfigurations: [ + { + name: 'ipconfig01' + subnetResourceId: resourceGroupResources.outputs.subnetResourceId + } + ] + nicSuffix: '-nic-01' + } + ] + osDisk: { + diskSizeGB: '128' + managedDisk: { + storageAccountType: 'Premium_LRS' + } + } + osType: 'Windows' + vmSize: 'Standard_B12ms' + adminPassword: password + configurationProfile: '/providers/Microsoft.Automanage/bestPractices/AzureBestPracticesProduction' + } +} diff --git a/modules/Microsoft.Compute/virtualMachines/.test/windows.autmg.parameters.json b/modules/Microsoft.Compute/virtualMachines/.test/windows.autmg.parameters.json deleted file mode 100644 index cc63de20a4..0000000000 --- a/modules/Microsoft.Compute/virtualMachines/.test/windows.autmg.parameters.json +++ /dev/null @@ -1,58 +0,0 @@ -{ - "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", - "contentVersion": "1.0.0.0", - "parameters": { - "name": { - "value": "<>-vm-win-03" - }, - "imageReference": { - "value": { - "publisher": "MicrosoftWindowsServer", - "offer": "WindowsServer", - "sku": "2019-Datacenter", - "version": "latest" - } - }, - "osType": { - "value": "Windows" - }, - "vmSize": { - "value": "Standard_B12ms" - }, - "osDisk": { - "value": { - "diskSizeGB": "128", - "managedDisk": { - "storageAccountType": "Premium_LRS" - } - } - }, - "adminUsername": { - "value": "localAdminUser" - }, - "adminPassword": { - "reference": { - "keyVault": { - "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.KeyVault/vaults/adp-<>-az-kv-x-001" - }, - "secretName": "adminPassword" - } - }, - "nicConfigurations": { - "value": [ - { - "nicSuffix": "-nic-01", - "ipConfigurations": [ - { - "name": "ipconfig01", - "subnetResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/adp-<>-az-vnet-x-001/subnets/<>-az-subnet-x-001" - } - ] - } - ] - }, - "configurationProfile": { - "value": "/providers/Microsoft.Automanage/bestPractices/AzureBestPracticesProduction" - } - } -} diff --git a/modules/Microsoft.Compute/virtualMachines/.test/windows.min.parameters.json b/modules/Microsoft.Compute/virtualMachines/.test/windows.min.parameters.json deleted file mode 100644 index 8537deaacf..0000000000 --- a/modules/Microsoft.Compute/virtualMachines/.test/windows.min.parameters.json +++ /dev/null @@ -1,55 +0,0 @@ -{ - "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", - "contentVersion": "1.0.0.0", - "parameters": { - "name": { - "value": "<>-vm-win-02" - }, - "imageReference": { - "value": { - "publisher": "MicrosoftWindowsServer", - "offer": "WindowsServer", - "sku": "2022-datacenter-azure-edition", - "version": "latest" - } - }, - "osType": { - "value": "Windows" - }, - "vmSize": { - "value": "Standard_B12ms" - }, - "osDisk": { - "value": { - "diskSizeGB": "128", - "managedDisk": { - "storageAccountType": "Premium_LRS" - } - } - }, - "adminUsername": { - "value": "localAdminUser" - }, - "adminPassword": { - "reference": { - "keyVault": { - "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.KeyVault/vaults/adp-<>-az-kv-x-001" - }, - "secretName": "adminPassword" - } - }, - "nicConfigurations": { - "value": [ - { - "nicSuffix": "-nic-01", - "ipConfigurations": [ - { - "name": "ipconfig01", - "subnetResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/adp-<>-az-vnet-x-001/subnets/<>-az-subnet-x-001" - } - ] - } - ] - } - } -} diff --git a/modules/Microsoft.Compute/virtualMachines/.test/windows.min/dependencies.bicep b/modules/Microsoft.Compute/virtualMachines/.test/windows.min/dependencies.bicep new file mode 100644 index 0000000000..d4eef6887c --- /dev/null +++ b/modules/Microsoft.Compute/virtualMachines/.test/windows.min/dependencies.bicep @@ -0,0 +1,28 @@ +@description('Required. The name of the Virtual Network to create.') +param virtualNetworkName string + +@description('Optional. The location to deploy to.') +param location string = resourceGroup().location + +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' + } + } + ] + } +} + +@description('The resource ID of the created Virtual Network Subnet.') +output subnetResourceId string = virtualNetwork.properties.subnets[0].id diff --git a/modules/Microsoft.Compute/virtualMachines/.test/windows.min/deploy.test.bicep b/modules/Microsoft.Compute/virtualMachines/.test/windows.min/deploy.test.bicep new file mode 100644 index 0000000000..3c512aab11 --- /dev/null +++ b/modules/Microsoft.Compute/virtualMachines/.test/windows.min/deploy.test.bicep @@ -0,0 +1,77 @@ +targetScope = 'subscription' + +// ========== // +// Parameters // +// ========== // +@description('Optional. The name of the resource group to deploy for testing purposes.') +@maxLength(80) +param resourceGroupName string = 'ms.compute.virtualMachines-${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 = 'cvmwinmin' + +@description('Optional. The password to leverage for the login.') +@secure() +param password string = newGuid() + +// =========== // +// 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)}-nestedDependencies' + params: { + location: location + virtualNetworkName: 'dep-<>-vnet-${serviceShort}' + } +} + +// ============== // +// Test Execution // +// ============== // +module testDeployment '../../deploy.bicep' = { + scope: resourceGroup + name: '${uniqueString(deployment().name)}-test-${serviceShort}' + params: { + location: location + name: '<>${serviceShort}' + adminUsername: 'localAdminUser' + imageReference: { + offer: 'WindowsServer' + publisher: 'MicrosoftWindowsServer' + sku: '2022-datacenter-azure-edition' + version: 'latest' + } + nicConfigurations: [ + { + ipConfigurations: [ + { + name: 'ipconfig01' + subnetResourceId: resourceGroupResources.outputs.subnetResourceId + } + ] + nicSuffix: '-nic-01' + } + ] + osDisk: { + diskSizeGB: '128' + managedDisk: { + storageAccountType: 'Premium_LRS' + } + } + osType: 'Windows' + vmSize: 'Standard_B12ms' + adminPassword: password + } +} diff --git a/modules/Microsoft.Compute/virtualMachines/.test/windows.parameters.json b/modules/Microsoft.Compute/virtualMachines/.test/windows.parameters.json deleted file mode 100644 index eea472aa0f..0000000000 --- a/modules/Microsoft.Compute/virtualMachines/.test/windows.parameters.json +++ /dev/null @@ -1,238 +0,0 @@ -{ - "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", - "contentVersion": "1.0.0.0", - "parameters": { - "name": { - "value": "<>-vm-win-01" - }, - "lock": { - "value": "CanNotDelete" - }, - "encryptionAtHost": { - "value": false - }, - "imageReference": { - "value": { - "publisher": "MicrosoftWindowsServer", - "offer": "WindowsServer", - "sku": "2019-Datacenter", - "version": "latest" - } - }, - "osType": { - "value": "Windows" - }, - "vmSize": { - "value": "Standard_B12ms" - }, - "osDisk": { - "value": { - "createOption": "fromImage", - "deleteOption": "Delete", - "caching": "None", - "diskSizeGB": "128", - "managedDisk": { - "storageAccountType": "Premium_LRS" - } - } - }, - "dataDisks": { - "value": [ - { - "createOption": "Empty", - "deleteOption": "Delete", - "caching": "None", - "diskSizeGB": "128", - "managedDisk": { - "storageAccountType": "Premium_LRS" - } - }, - { - "createOption": "Empty", - "deleteOption": "Delete", - "caching": "None", - "diskSizeGB": "128", - "managedDisk": { - "storageAccountType": "Premium_LRS" - } - } - ] - }, - "availabilityZone": { - "value": 2 - }, - "adminUsername": { - "value": "localAdminUser" - }, - "adminPassword": { - "reference": { - "keyVault": { - "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.KeyVault/vaults/adp-<>-az-kv-x-001" - }, - "secretName": "adminPassword" - } - }, - "nicConfigurations": { - "value": [ - { - "nicSuffix": "-nic-01", - "deleteOption": "Delete", - "ipConfigurations": [ - { - "name": "ipconfig01", - "subnetResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/adp-<>-az-vnet-x-001/subnets/<>-az-subnet-x-001", - "pipConfiguration": { - "publicIpNameSuffix": "-pip-01", - "roleAssignments": [ - { - "roleDefinitionIdOrName": "Reader", - "principalIds": [ - "<>" - ] - } - ] - }, - "loadBalancerBackendAddressPools": [ - { - "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/loadBalancers/adp-<>-az-lb-internal-001/backendAddressPools/servers" - } - ], - "applicationSecurityGroups": [ - { - "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/applicationSecurityGroups/adp-<>-az-asg-x-001" - } - ] - } - ], - "roleAssignments": [ - { - "roleDefinitionIdOrName": "Reader", - "principalIds": [ - "<>" - ] - } - ] - } - ] - }, - "backupVaultName": { - "value": "adp-<>-az-rsv-x-001" - }, - "backupVaultResourceGroup": { - "value": "validation-rg" - }, - "backupPolicyName": { - "value": "VMpolicy" - }, - "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" - }, - "proximityPlacementGroupResourceId": { - "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Compute/proximityPlacementGroups/adp-<>-az-ppg-vm-001" - }, - "systemAssignedIdentity": { - "value": true - }, - "userAssignedIdentities": { - "value": { - "/subscriptions/<>/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-<>-az-msi-x-001": {} - } - }, - "extensionAntiMalwareConfig": { - "value": { - "enabled": true, - "settings": { - "AntimalwareEnabled": "true", - "Exclusions": { - "Extensions": ".ext1;.ext2", - "Paths": "c:\\excluded-path-1;c:\\excluded-path-2", - "Processes": "excludedproc1.exe;excludedproc2.exe" - }, - "RealtimeProtectionEnabled": "true", - "ScheduledScanSettings": { - "isEnabled": "true", - "scanType": "Quick", - "day": "7", - "time": "120" - } - } - } - }, - "extensionMonitoringAgentConfig": { - "value": { - "enabled": true - } - }, - "monitoringWorkspaceId": { - "value": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001" - }, - "extensionDependencyAgentConfig": { - "value": { - "enabled": true - } - }, - "extensionNetworkWatcherAgentConfig": { - "value": { - "enabled": true - } - }, - "extensionDiskEncryptionConfig": { - "value": { - "enabled": true, - "settings": { - "EncryptionOperation": "EnableEncryption", - "KeyVaultURL": "https://adp-<>-az-kv-x-001.vault.azure.net/", - "KeyVaultResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.KeyVault/vaults/adp-<>-az-kv-x-001", - "KeyEncryptionKeyURL": "https://adp-<>-az-kv-x-001.vault.azure.net/keys/keyEncryptionKey/bc3bb46d95c64367975d722f473eeae5", // ID must be updated for new keys - "KekVaultResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.KeyVault/vaults/adp-<>-az-kv-x-001", - "KeyEncryptionAlgorithm": "RSA-OAEP", - "VolumeType": "All", - "ResizeOSDisk": "false" - } - } - }, - "extensionDSCConfig": { - "value": { - "enabled": true - } - }, - "extensionCustomScriptConfig": { - "value": { - "enabled": true, - "fileData": [ - { - "uri": "https://adp<>azsax001.blob.core.windows.net/scripts/scriptExtensionMasterInstaller.ps1", - "storageAccountId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001" - } - ] - } - }, - "extensionCustomScriptProtectedSetting": { - "value": { - "commandToExecute": "powershell -ExecutionPolicy Unrestricted -Command \"& .\\scriptExtensionMasterInstaller.ps1\"" - } - } - } -} diff --git a/modules/Microsoft.Compute/virtualMachines/.test/windows/dependencies.bicep b/modules/Microsoft.Compute/virtualMachines/.test/windows/dependencies.bicep new file mode 100644 index 0000000000..fe18973a09 --- /dev/null +++ b/modules/Microsoft.Compute/virtualMachines/.test/windows/dependencies.bicep @@ -0,0 +1,306 @@ +@description('Required. The name of the Virtual Network to create.') +param virtualNetworkName string + +@description('Required. The name of the Application Security Group to create.') +param applicationSecurityGroupName string + +@description('Required. The name of the Managed Identity to create.') +param managedIdentityName string + +@description('Required. The name of the Load Balancer to create.') +param loadBalancerName string + +@description('Required. The name of the Recovery Services Vault to create.') +param recoveryServicesVaultName string + +@description('Required. The name of the Key Vault to create.') +param keyVaultName string + +@description('Required. The name of the Storage Account to create.') +param storageAccountName string + +@description('Required. The name of the Deployment Script used to upload data to the Storage Account.') +param storageUploadDeploymentScriptName string + +@description('Required. The name of the Proximity Placement Group to create.') +param proximityPlacementGroupName string + +@description('Optional. The location to deploy resources to.') +param location string = resourceGroup().location + +var storageContainerName = 'scripts' +var storageAccountCSEFileName = 'scriptExtensionMasterInstaller.ps1' +var backupPolicyName = 'backupPolicy' + +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 applicationSecurityGroup 'Microsoft.Network/applicationSecurityGroups@2022-01-01' = { + name: applicationSecurityGroupName + location: location +} + +resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2018-11-30' = { + name: managedIdentityName + location: location +} + +resource msiRGContrRoleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = { + name: guid('msi-${resourceGroup().id}-${location}-${managedIdentity.id}-RG-Contributor-RoleAssignment') + scope: resourceGroup() + properties: { + principalId: managedIdentity.properties.principalId + roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') // Contributor + principalType: 'ServicePrincipal' + } +} + +resource loadBalancer 'Microsoft.Network/loadBalancers@2022-01-01' = { + name: loadBalancerName + location: location + sku: { + name: 'Standard' + } + properties: { + frontendIPConfigurations: [ + { + name: 'privateIPConfig1' + properties: { + subnet: virtualNetwork.properties.subnets[0] + } + } + ] + backendAddressPools: [ + { + name: 'servers' + } + ] + } +} + +resource recoveryServicesVault 'Microsoft.RecoveryServices/vaults@2022-04-01' = { + name: recoveryServicesVaultName + location: location + sku: { + name: 'RS0' + tier: 'Standard' + } + properties: { + } + + resource backupPolicy 'backupPolicies@2022-03-01' = { + name: backupPolicyName + properties: { + backupManagementType: 'AzureIaasVM' + instantRPDetails: {} + schedulePolicy: { + schedulePolicyType: 'SimpleSchedulePolicy' + scheduleRunFrequency: 'Daily' + scheduleRunTimes: [ + '2019-11-07T07:00:00Z' + ] + scheduleWeeklyFrequency: 0 + } + retentionPolicy: { + retentionPolicyType: 'LongTermRetentionPolicy' + dailySchedule: { + retentionTimes: [ + '2019-11-07T07:00:00Z' + ] + retentionDuration: { + count: 180 + durationType: 'Days' + } + } + weeklySchedule: { + daysOfTheWeek: [ + 'Sunday' + ] + retentionTimes: [ + '2019-11-07T07:00:00Z' + ] + retentionDuration: { + count: 12 + durationType: 'Weeks' + } + } + monthlySchedule: { + retentionScheduleFormatType: 'Weekly' + retentionScheduleWeekly: { + daysOfTheWeek: [ + 'Sunday' + ] + weeksOfTheMonth: [ + 'First' + ] + } + retentionTimes: [ + '2019-11-07T07:00:00Z' + ] + retentionDuration: { + count: 60 + durationType: 'Months' + } + } + yearlySchedule: { + retentionScheduleFormatType: 'Weekly' + monthsOfYear: [ + 'January' + ] + retentionScheduleWeekly: { + daysOfTheWeek: [ + 'Sunday' + ] + weeksOfTheMonth: [ + 'First' + ] + } + retentionTimes: [ + '2019-11-07T07:00:00Z' + ] + retentionDuration: { + count: 10 + durationType: 'Years' + } + } + } + instantRpRetentionRangeInDays: 2 + timeZone: 'UTC' + protectedItemsCount: 0 + } + } +} + +resource keyVault 'Microsoft.KeyVault/vaults@2022-07-01' = { + name: keyVaultName + location: location + properties: { + sku: { + family: 'A' + name: 'standard' + } + tenantId: tenant().tenantId + enablePurgeProtection: null + enabledForTemplateDeployment: true + enabledForDiskEncryption: true + enabledForDeployment: true + enableRbacAuthorization: true + accessPolicies: [] + } + + resource key 'keys@2022-07-01' = { + name: 'encryptionKey' + properties: { + kty: 'RSA' + } + } +} + +resource msiKVReadRoleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = { + name: guid('msi-${keyVault::key.id}-${location}-${managedIdentity.id}-KeyVault-Key-Read-RoleAssignment') + scope: keyVault::key + properties: { + principalId: managedIdentity.properties.principalId + roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '12338af0-0e69-4776-bea7-57ae8d297424') // Key Vault Crypto User + principalType: 'ServicePrincipal' + } +} + +resource storageAccount 'Microsoft.Storage/storageAccounts@2021-09-01' = { + name: storageAccountName + location: location + sku: { + name: 'Standard_LRS' + } + kind: 'StorageV2' + + resource blobService 'blobServices@2021-09-01' = { + name: 'default' + + resource container 'containers@2021-09-01' = { + name: storageContainerName + } + } +} + +resource storageUpload 'Microsoft.Resources/deploymentScripts@2020-10-01' = { + name: storageUploadDeploymentScriptName + location: location + kind: 'AzurePowerShell' + identity: { + type: 'UserAssigned' + userAssignedIdentities: { + '${managedIdentity.id}': {} + } + } + properties: { + azPowerShellVersion: '6.2.1' + retentionInterval: 'P1D' + arguments: '-StorageAccountName "${storageAccount.name}" -ResourceGroupName "${resourceGroup().name}" -ContainerName "${storageAccount::blobService::container.name}" -FileName "${storageAccountCSEFileName}"' + scriptContent: loadTextContent('../.scripts/Set-BlobContent.ps1') + } + dependsOn: [ + msiRGContrRoleAssignment + ] +} + +resource proximityPlacementGroup 'Microsoft.Compute/proximityPlacementGroups@2022-03-01' = { + name: proximityPlacementGroupName + location: location +} + +@description('The resource ID of the created Virtual Network Subnet.') +output subnetResourceId string = virtualNetwork.properties.subnets[0].id + +@description('The resource ID of the created Application Security Group.') +output applicationSecurityGroupResourceId string = applicationSecurityGroup.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 Load Balancer Backend Pool.') +output loadBalancerBackendPoolResourceId string = loadBalancer.properties.backendAddressPools[0].id + +@description('The resource ID of the created Recovery Services Vault.') +output recoveryServicesVaultResourceId string = recoveryServicesVault.id + +@description('The name of the Backup Policy created in the Backup Recovery Vault.') +output recoveryServicesVaultBackupPolicyName string = backupPolicyName + +@description('The resource ID of the created Key Vault.') +output keyVaultResourceId string = keyVault.id + +@description('The URL of the created Key Vault.') +output keyVaultUrl string = keyVault.properties.vaultUri + +@description('The URL of the created Key Vault Encryption Key.') +output keyVaultEncryptionKeyUrl string = keyVault::key.properties.keyUriWithVersion + +@description('The resource ID of the created Storage Account.') +output storageAccountResourceId string = storageAccount.id + +@description('The URL of the Custom Script Extension in the created Storage Account') +output storageAccountCSEFileUrl string = '${storageAccount.properties.primaryEndpoints.blob}${storageContainerName}/${storageAccountCSEFileName}' + +@description('The resource ID of the created Proximity Placement Group.') +output proximityPlacementGroupResourceId string = proximityPlacementGroup.id diff --git a/modules/Microsoft.Compute/virtualMachines/.test/windows/deploy.test.bicep b/modules/Microsoft.Compute/virtualMachines/.test/windows/deploy.test.bicep new file mode 100644 index 0000000000..1dff4148fd --- /dev/null +++ b/modules/Microsoft.Compute/virtualMachines/.test/windows/deploy.test.bicep @@ -0,0 +1,233 @@ +targetScope = 'subscription' + +// ========== // +// Parameters // +// ========== // +@description('Optional. The name of the resource group to deploy for testing purposes.') +@maxLength(80) +param resourceGroupName string = 'ms.compute.virtualMachines-${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 = 'cvmwindef' + +@description('Optional. The password to leverage for the login.') +@secure() +param password string = newGuid() + +// =========== // +// 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)}-nestedDependencies' + params: { + location: location + virtualNetworkName: 'dep-<>-vnet-${serviceShort}' + applicationSecurityGroupName: 'adp-<>-asg-${serviceShort}' + managedIdentityName: 'dep-<>-msi-${serviceShort}' + keyVaultName: 'dep-<>-kv-${serviceShort}' + loadBalancerName: 'dep-<>-lb-${serviceShort}' + recoveryServicesVaultName: 'dep-<>-rsv-${serviceShort}' + storageAccountName: 'dep<>sa${serviceShort}01' + storageUploadDeploymentScriptName: 'dep-<>-sads-${serviceShort}' + proximityPlacementGroupName: 'dep-<>-ppg-${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: { + location: location + name: '<>${serviceShort}' + adminUsername: 'localAdminUser' + imageReference: { + offer: 'WindowsServer' + publisher: 'MicrosoftWindowsServer' + sku: '2019-Datacenter' + version: 'latest' + } + nicConfigurations: [ + { + deleteOption: 'Delete' + ipConfigurations: [ + { + applicationSecurityGroups: [ + { + id: resourceGroupResources.outputs.applicationSecurityGroupResourceId + } + ] + loadBalancerBackendAddressPools: [ + { + id: resourceGroupResources.outputs.loadBalancerBackendPoolResourceId + } + ] + name: 'ipconfig01' + pipConfiguration: { + publicIpNameSuffix: '-pip-01' + roleAssignments: [ + { + principalIds: [ + resourceGroupResources.outputs.managedIdentityPrincipalId + ] + roleDefinitionIdOrName: 'Reader' + } + ] + } + subnetResourceId: resourceGroupResources.outputs.subnetResourceId + } + ] + nicSuffix: '-nic-01' + roleAssignments: [ + { + principalIds: [ + resourceGroupResources.outputs.managedIdentityPrincipalId + ] + roleDefinitionIdOrName: 'Reader' + } + ] + } + ] + osDisk: { + caching: 'None' + createOption: 'fromImage' + deleteOption: 'Delete' + diskSizeGB: '128' + managedDisk: { + storageAccountType: 'Premium_LRS' + } + } + osType: 'Windows' + vmSize: 'Standard_B12ms' + adminPassword: password + availabilityZone: 2 + backupPolicyName: resourceGroupResources.outputs.recoveryServicesVaultBackupPolicyName + backupVaultName: last(split(resourceGroupResources.outputs.recoveryServicesVaultResourceId, '/')) + backupVaultResourceGroup: (split(resourceGroupResources.outputs.recoveryServicesVaultResourceId, '/'))[4] + dataDisks: [ + { + caching: 'None' + createOption: 'Empty' + deleteOption: 'Delete' + diskSizeGB: '128' + managedDisk: { + storageAccountType: 'Premium_LRS' + } + } + { + caching: 'None' + createOption: 'Empty' + deleteOption: 'Delete' + diskSizeGB: '128' + managedDisk: { + storageAccountType: 'Premium_LRS' + } + } + ] + diagnosticStorageAccountId: diagnosticDependencies.outputs.storageAccountResourceId + diagnosticWorkspaceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId + diagnosticEventHubAuthorizationRuleId: diagnosticDependencies.outputs.eventHubAuthorizationRuleId + diagnosticEventHubName: diagnosticDependencies.outputs.eventHubNamespaceEventHubName + diagnosticLogsRetentionInDays: 7 + encryptionAtHost: false + extensionAntiMalwareConfig: { + enabled: true + settings: { + AntimalwareEnabled: 'true' + Exclusions: { + Extensions: '.ext1;.ext2' + Paths: 'c:\\excluded-path-1;c:\\excluded-path-2' + Processes: 'excludedproc1.exe;excludedproc2.exe' + } + RealtimeProtectionEnabled: 'true' + ScheduledScanSettings: { + day: '7' + isEnabled: 'true' + scanType: 'Quick' + time: '120' + } + } + } + extensionCustomScriptConfig: { + enabled: true + fileData: [ + { + storageAccountId: resourceGroupResources.outputs.storageAccountResourceId + uri: resourceGroupResources.outputs.storageAccountCSEFileUrl + } + ] + } + extensionCustomScriptProtectedSetting: { + commandToExecute: 'powershell -ExecutionPolicy Unrestricted -Command "& ./${last(split(resourceGroupResources.outputs.storageAccountCSEFileUrl, '/'))}"' + } + extensionDependencyAgentConfig: { + enabled: true + } + extensionDiskEncryptionConfig: { + enabled: true + settings: { + EncryptionOperation: 'EnableEncryption' + KekVaultResourceId: resourceGroupResources.outputs.keyVaultResourceId + KeyEncryptionAlgorithm: 'RSA-OAEP' + KeyEncryptionKeyURL: resourceGroupResources.outputs.keyVaultEncryptionKeyUrl + KeyVaultResourceId: resourceGroupResources.outputs.keyVaultResourceId + KeyVaultURL: resourceGroupResources.outputs.keyVaultUrl + ResizeOSDisk: 'false' + VolumeType: 'All' + } + } + extensionDSCConfig: { + enabled: true + } + extensionMonitoringAgentConfig: { + enabled: true + } + extensionNetworkWatcherAgentConfig: { + enabled: true + } + lock: 'CanNotDelete' + monitoringWorkspaceId: diagnosticDependencies.outputs.logAnalyticsWorkspaceResourceId + proximityPlacementGroupResourceId: resourceGroupResources.outputs.proximityPlacementGroupResourceId + roleAssignments: [ + { + principalIds: [ + resourceGroupResources.outputs.managedIdentityPrincipalId + ] + roleDefinitionIdOrName: 'Reader' + } + ] + systemAssignedIdentity: true + userAssignedIdentities: { + '${resourceGroupResources.outputs.managedIdentityResourceId}': {} + } + } +} diff --git a/modules/Microsoft.Compute/virtualMachines/readme.md b/modules/Microsoft.Compute/virtualMachines/readme.md index 192fa46295..21cd520b3d 100644 --- a/modules/Microsoft.Compute/virtualMachines/readme.md +++ b/modules/Microsoft.Compute/virtualMachines/readme.md @@ -1,6 +1,6 @@ # Virtual Machines `[Microsoft.Compute/virtualMachines]` -This module deploys one Virtual Machine with one or multiple nics and optionally one or multiple public IPs. +This module deploys one Virtual Machine with one or multiple NICs and optionally one or multiple public IPs. ## Navigation @@ -1021,7 +1021,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: Linux Autmg

+

Example 1: Linux

@@ -1029,269 +1029,7 @@ The following module usage examples are retrieved from the content of the files ```bicep module virtualMachines './Microsoft.Compute/virtualMachines/deploy.bicep' = { - name: '${uniqueString(deployment().name)}-VirtualMachines' - params: { - // Required parameters - adminUsername: 'localAdminUser' - imageReference: { - offer: 'UbuntuServer' - publisher: 'Canonical' - sku: '18.04-LTS' - version: 'latest' - } - nicConfigurations: [ - { - ipConfigurations: [ - { - name: 'ipconfig01' - pipConfiguration: { - publicIpNameSuffix: '-pip-01' - } - subnetResourceId: '/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/adp-<>-az-vnet-x-001/subnets/<>-az-subnet-x-001' - } - ] - nicSuffix: '-nic-01' - } - ] - osDisk: { - diskSizeGB: '128' - managedDisk: { - storageAccountType: 'Premium_LRS' - } - } - osType: 'Linux' - vmSize: 'Standard_B12ms' - // Non-required parameters - configurationProfile: '/providers/Microsoft.Automanage/bestPractices/AzureBestPracticesProduction' - disablePasswordAuthentication: true - name: '<>-vm-linux-autmg-01' - publicKeys: [ - { - keyData: 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDdOir5eO28EBwxU0Dyra7g9h0HUXDyMNFp2z8PhaTUQgHjrimkMxjYRwEOG/lxnYL7+TqZk+HcPTfbZOunHBw0Wx2CITzILt6531vmIYZGfq5YyYXbxZa5MON7L/PVivoRlPj5Z/t4RhqMhyfR7EPcZ516LJ8lXPTo8dE/bkOCS+kFBEYHvPEEKAyLs19sRcK37SeHjpX04zdg62nqtuRr00Tp7oeiTXA1xn5K5mxeAswotmd8CU0lWUcJuPBWQedo649b+L2cm52kTncOBI6YChAeyEc1PDF0Tn9FmpdOWKtI9efh+S3f8qkcVEtSTXoTeroBd31nzjAunMrZeM8Ut6dre+XeQQIjT7I8oEm+ZkIuIyq0x2fls8JXP2YJDWDqu8v1+yLGTQ3Z9XVt2lMti/7bIgYxS0JvwOr5n5L4IzKvhb4fm13LLDGFa3o7Nsfe3fPb882APE0bLFCmfyIeiPh7go70WqZHakpgIr6LCWTyePez9CsI/rfWDb6eAM8= generated-by-azure' - path: '/home/localAdminUser/.ssh/authorized_keys' - } - ] - } -} -``` - -
-

- -

- -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 - "adminUsername": { - "value": "localAdminUser" - }, - "imageReference": { - "value": { - "offer": "UbuntuServer", - "publisher": "Canonical", - "sku": "18.04-LTS", - "version": "latest" - } - }, - "nicConfigurations": { - "value": [ - { - "ipConfigurations": [ - { - "name": "ipconfig01", - "pipConfiguration": { - "publicIpNameSuffix": "-pip-01" - }, - "subnetResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/adp-<>-az-vnet-x-001/subnets/<>-az-subnet-x-001" - } - ], - "nicSuffix": "-nic-01" - } - ] - }, - "osDisk": { - "value": { - "diskSizeGB": "128", - "managedDisk": { - "storageAccountType": "Premium_LRS" - } - } - }, - "osType": { - "value": "Linux" - }, - "vmSize": { - "value": "Standard_B12ms" - }, - // Non-required parameters - "configurationProfile": { - "value": "/providers/Microsoft.Automanage/bestPractices/AzureBestPracticesProduction" - }, - "disablePasswordAuthentication": { - "value": true - }, - "name": { - "value": "<>-vm-linux-autmg-01" - }, - "publicKeys": { - "value": [ - { - "keyData": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDdOir5eO28EBwxU0Dyra7g9h0HUXDyMNFp2z8PhaTUQgHjrimkMxjYRwEOG/lxnYL7+TqZk+HcPTfbZOunHBw0Wx2CITzILt6531vmIYZGfq5YyYXbxZa5MON7L/PVivoRlPj5Z/t4RhqMhyfR7EPcZ516LJ8lXPTo8dE/bkOCS+kFBEYHvPEEKAyLs19sRcK37SeHjpX04zdg62nqtuRr00Tp7oeiTXA1xn5K5mxeAswotmd8CU0lWUcJuPBWQedo649b+L2cm52kTncOBI6YChAeyEc1PDF0Tn9FmpdOWKtI9efh+S3f8qkcVEtSTXoTeroBd31nzjAunMrZeM8Ut6dre+XeQQIjT7I8oEm+ZkIuIyq0x2fls8JXP2YJDWDqu8v1+yLGTQ3Z9XVt2lMti/7bIgYxS0JvwOr5n5L4IzKvhb4fm13LLDGFa3o7Nsfe3fPb882APE0bLFCmfyIeiPh7go70WqZHakpgIr6LCWTyePez9CsI/rfWDb6eAM8= generated-by-azure", - "path": "/home/localAdminUser/.ssh/authorized_keys" - } - ] - } - } -} -``` - -
-

- -

Example 2: Linux Min

- -
- -via Bicep module - -```bicep -module virtualMachines './Microsoft.Compute/virtualMachines/deploy.bicep' = { - name: '${uniqueString(deployment().name)}-VirtualMachines' - params: { - // Required parameters - adminUsername: 'localAdminUser' - imageReference: { - offer: 'UbuntuServer' - publisher: 'Canonical' - sku: '18.04-LTS' - version: 'latest' - } - nicConfigurations: [ - { - ipConfigurations: [ - { - name: 'ipconfig01' - pipConfiguration: { - publicIpNameSuffix: '-pip-01' - } - subnetResourceId: '/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/adp-<>-az-vnet-x-001/subnets/<>-az-subnet-x-001' - } - ] - nicSuffix: '-nic-01' - } - ] - osDisk: { - diskSizeGB: '128' - managedDisk: { - storageAccountType: 'Premium_LRS' - } - } - osType: 'Linux' - vmSize: 'Standard_B12ms' - // Non-required parameters - disablePasswordAuthentication: true - name: '<>-vm-linux-min-01' - publicKeys: [ - { - keyData: 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDdOir5eO28EBwxU0Dyra7g9h0HUXDyMNFp2z8PhaTUQgHjrimkMxjYRwEOG/lxnYL7+TqZk+HcPTfbZOunHBw0Wx2CITzILt6531vmIYZGfq5YyYXbxZa5MON7L/PVivoRlPj5Z/t4RhqMhyfR7EPcZ516LJ8lXPTo8dE/bkOCS+kFBEYHvPEEKAyLs19sRcK37SeHjpX04zdg62nqtuRr00Tp7oeiTXA1xn5K5mxeAswotmd8CU0lWUcJuPBWQedo649b+L2cm52kTncOBI6YChAeyEc1PDF0Tn9FmpdOWKtI9efh+S3f8qkcVEtSTXoTeroBd31nzjAunMrZeM8Ut6dre+XeQQIjT7I8oEm+ZkIuIyq0x2fls8JXP2YJDWDqu8v1+yLGTQ3Z9XVt2lMti/7bIgYxS0JvwOr5n5L4IzKvhb4fm13LLDGFa3o7Nsfe3fPb882APE0bLFCmfyIeiPh7go70WqZHakpgIr6LCWTyePez9CsI/rfWDb6eAM8= generated-by-azure' - path: '/home/localAdminUser/.ssh/authorized_keys' - } - ] - } -} -``` - -
-

- -

- -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 - "adminUsername": { - "value": "localAdminUser" - }, - "imageReference": { - "value": { - "offer": "UbuntuServer", - "publisher": "Canonical", - "sku": "18.04-LTS", - "version": "latest" - } - }, - "nicConfigurations": { - "value": [ - { - "ipConfigurations": [ - { - "name": "ipconfig01", - "pipConfiguration": { - "publicIpNameSuffix": "-pip-01" - }, - "subnetResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/adp-<>-az-vnet-x-001/subnets/<>-az-subnet-x-001" - } - ], - "nicSuffix": "-nic-01" - } - ] - }, - "osDisk": { - "value": { - "diskSizeGB": "128", - "managedDisk": { - "storageAccountType": "Premium_LRS" - } - } - }, - "osType": { - "value": "Linux" - }, - "vmSize": { - "value": "Standard_B12ms" - }, - // Non-required parameters - "disablePasswordAuthentication": { - "value": true - }, - "name": { - "value": "<>-vm-linux-min-01" - }, - "publicKeys": { - "value": [ - { - "keyData": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDdOir5eO28EBwxU0Dyra7g9h0HUXDyMNFp2z8PhaTUQgHjrimkMxjYRwEOG/lxnYL7+TqZk+HcPTfbZOunHBw0Wx2CITzILt6531vmIYZGfq5YyYXbxZa5MON7L/PVivoRlPj5Z/t4RhqMhyfR7EPcZ516LJ8lXPTo8dE/bkOCS+kFBEYHvPEEKAyLs19sRcK37SeHjpX04zdg62nqtuRr00Tp7oeiTXA1xn5K5mxeAswotmd8CU0lWUcJuPBWQedo649b+L2cm52kTncOBI6YChAeyEc1PDF0Tn9FmpdOWKtI9efh+S3f8qkcVEtSTXoTeroBd31nzjAunMrZeM8Ut6dre+XeQQIjT7I8oEm+ZkIuIyq0x2fls8JXP2YJDWDqu8v1+yLGTQ3Z9XVt2lMti/7bIgYxS0JvwOr5n5L4IzKvhb4fm13LLDGFa3o7Nsfe3fPb882APE0bLFCmfyIeiPh7go70WqZHakpgIr6LCWTyePez9CsI/rfWDb6eAM8= generated-by-azure", - "path": "/home/localAdminUser/.ssh/authorized_keys" - } - ] - } - } -} -``` - -
-

- -

Example 3: Linux

- -
- -via Bicep module - -```bicep -module virtualMachines './Microsoft.Compute/virtualMachines/deploy.bicep' = { - name: '${uniqueString(deployment().name)}-VirtualMachines' + name: '${uniqueString(deployment().name)}-test-cvmlindef' params: { // Required parameters adminUsername: 'localAdminUser' @@ -1308,12 +1046,12 @@ module virtualMachines './Microsoft.Compute/virtualMachines/deploy.bicep' = { { applicationSecurityGroups: [ { - id: '/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/applicationSecurityGroups/adp-<>-az-asg-x-001' + id: '' } ] loadBalancerBackendAddressPools: [ { - id: '/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/loadBalancers/adp-<>-az-lb-internal-001/backendAddressPools/servers' + id: '' } ] name: 'ipconfig01' @@ -1322,20 +1060,20 @@ module virtualMachines './Microsoft.Compute/virtualMachines/deploy.bicep' = { roleAssignments: [ { principalIds: [ - '<>' + '' ] roleDefinitionIdOrName: 'Reader' } ] } - subnetResourceId: '/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/adp-<>-az-vnet-x-001/subnets/<>-az-subnet-x-001' + subnetResourceId: '' } ] nicSuffix: '-nic-01' roleAssignments: [ { principalIds: [ - '<>' + '' ] roleDefinitionIdOrName: 'Reader' } @@ -1355,9 +1093,9 @@ module virtualMachines './Microsoft.Compute/virtualMachines/deploy.bicep' = { vmSize: 'Standard_B12ms' // Non-required parameters availabilityZone: 1 - backupPolicyName: 'VMpolicy' - backupVaultName: 'adp-<>-az-rsv-x-001' - backupVaultResourceGroup: 'validation-rg' + backupPolicyName: '' + backupVaultName: '' + backupVaultResourceGroup: '' dataDisks: [ { caching: 'ReadWrite' @@ -1378,24 +1116,24 @@ module virtualMachines './Microsoft.Compute/virtualMachines/deploy.bicep' = { } } ] - 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: '' disablePasswordAuthentication: true encryptionAtHost: false extensionCustomScriptConfig: { enabled: true fileData: [ { - storageAccountId: '/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001' - uri: 'https://adp<>azsax001.blob.core.windows.net/scripts/scriptExtensionMasterInstaller.ps1' + storageAccountId: '' + uri: '' } ] } extensionCustomScriptProtectedSetting: { - commandToExecute: 'sudo apt-get update' + commandToExecute: '' } extensionDependencyAgentConfig: { enabled: true @@ -1404,11 +1142,11 @@ module virtualMachines './Microsoft.Compute/virtualMachines/deploy.bicep' = { enabled: true settings: { EncryptionOperation: 'EnableEncryption' - KekVaultResourceId: '/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.KeyVault/vaults/adp-<>-az-kv-x-001' + KekVaultResourceId: '' KeyEncryptionAlgorithm: 'RSA-OAEP' - KeyEncryptionKeyURL: 'https://adp-<>-az-kv-x-001.vault.azure.net/keys/keyEncryptionKey/bc3bb46d95c64367975d722f473eeae5' - KeyVaultResourceId: '/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.KeyVault/vaults/adp-<>-az-kv-x-001' - KeyVaultURL: 'https://adp-<>-az-kv-x-001.vault.azure.net/' + KeyEncryptionKeyURL: '' + KeyVaultResourceId: '' + KeyVaultURL: '' ResizeOSDisk: 'false' VolumeType: 'All' } @@ -1422,26 +1160,27 @@ module virtualMachines './Microsoft.Compute/virtualMachines/deploy.bicep' = { extensionNetworkWatcherAgentConfig: { enabled: true } + location: '' lock: 'CanNotDelete' - monitoringWorkspaceId: '/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001' - name: '<>-vm-linux-01' + monitoringWorkspaceId: '' + name: '<>cvmlindef' publicKeys: [ { - keyData: 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDdOir5eO28EBwxU0Dyra7g9h0HUXDyMNFp2z8PhaTUQgHjrimkMxjYRwEOG/lxnYL7+TqZk+HcPTfbZOunHBw0Wx2CITzILt6531vmIYZGfq5YyYXbxZa5MON7L/PVivoRlPj5Z/t4RhqMhyfR7EPcZ516LJ8lXPTo8dE/bkOCS+kFBEYHvPEEKAyLs19sRcK37SeHjpX04zdg62nqtuRr00Tp7oeiTXA1xn5K5mxeAswotmd8CU0lWUcJuPBWQedo649b+L2cm52kTncOBI6YChAeyEc1PDF0Tn9FmpdOWKtI9efh+S3f8qkcVEtSTXoTeroBd31nzjAunMrZeM8Ut6dre+XeQQIjT7I8oEm+ZkIuIyq0x2fls8JXP2YJDWDqu8v1+yLGTQ3Z9XVt2lMti/7bIgYxS0JvwOr5n5L4IzKvhb4fm13LLDGFa3o7Nsfe3fPb882APE0bLFCmfyIeiPh7go70WqZHakpgIr6LCWTyePez9CsI/rfWDb6eAM8= generated-by-azure' + keyData: '' path: '/home/localAdminUser/.ssh/authorized_keys' } ] roleAssignments: [ { principalIds: [ - '<>' + '' ] roleDefinitionIdOrName: 'Reader' } ] systemAssignedIdentity: true userAssignedIdentities: { - '/subscriptions/<>/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-<>-az-msi-x-001': {} + '': {} } } } @@ -1479,12 +1218,12 @@ module virtualMachines './Microsoft.Compute/virtualMachines/deploy.bicep' = { { "applicationSecurityGroups": [ { - "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/applicationSecurityGroups/adp-<>-az-asg-x-001" + "id": "" } ], "loadBalancerBackendAddressPools": [ { - "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/loadBalancers/adp-<>-az-lb-internal-001/backendAddressPools/servers" + "id": "" } ], "name": "ipconfig01", @@ -1493,20 +1232,20 @@ module virtualMachines './Microsoft.Compute/virtualMachines/deploy.bicep' = { "roleAssignments": [ { "principalIds": [ - "<>" + "" ], "roleDefinitionIdOrName": "Reader" } ] }, - "subnetResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/adp-<>-az-vnet-x-001/subnets/<>-az-subnet-x-001" + "subnetResourceId": "" } ], "nicSuffix": "-nic-01", "roleAssignments": [ { "principalIds": [ - "<>" + "" ], "roleDefinitionIdOrName": "Reader" } @@ -1536,13 +1275,13 @@ module virtualMachines './Microsoft.Compute/virtualMachines/deploy.bicep' = { "value": 1 }, "backupPolicyName": { - "value": "VMpolicy" + "value": "" }, "backupVaultName": { - "value": "adp-<>-az-rsv-x-001" + "value": "" }, "backupVaultResourceGroup": { - "value": "validation-rg" + "value": "" }, "dataDisks": { "value": [ @@ -1567,19 +1306,19 @@ module virtualMachines './Microsoft.Compute/virtualMachines/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": "" }, "disablePasswordAuthentication": { "value": true @@ -1592,15 +1331,15 @@ module virtualMachines './Microsoft.Compute/virtualMachines/deploy.bicep' = { "enabled": true, "fileData": [ { - "storageAccountId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001", - "uri": "https://adp<>azsax001.blob.core.windows.net/scripts/scriptExtensionMasterInstaller.ps1" + "storageAccountId": "", + "uri": "" } ] } }, "extensionCustomScriptProtectedSetting": { "value": { - "commandToExecute": "sudo apt-get update" + "commandToExecute": "" } }, "extensionDependencyAgentConfig": { @@ -1613,11 +1352,11 @@ module virtualMachines './Microsoft.Compute/virtualMachines/deploy.bicep' = { "enabled": true, "settings": { "EncryptionOperation": "EnableEncryption", - "KekVaultResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.KeyVault/vaults/adp-<>-az-kv-x-001", + "KekVaultResourceId": "", "KeyEncryptionAlgorithm": "RSA-OAEP", - "KeyEncryptionKeyURL": "https://adp-<>-az-kv-x-001.vault.azure.net/keys/keyEncryptionKey/bc3bb46d95c64367975d722f473eeae5", - "KeyVaultResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.KeyVault/vaults/adp-<>-az-kv-x-001", - "KeyVaultURL": "https://adp-<>-az-kv-x-001.vault.azure.net/", + "KeyEncryptionKeyURL": "", + "KeyVaultResourceId": "", + "KeyVaultURL": "", "ResizeOSDisk": "false", "VolumeType": "All" } @@ -1638,19 +1377,22 @@ module virtualMachines './Microsoft.Compute/virtualMachines/deploy.bicep' = { "enabled": true } }, + "location": { + "value": "" + }, "lock": { "value": "CanNotDelete" }, "monitoringWorkspaceId": { - "value": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001" + "value": "" }, "name": { - "value": "<>-vm-linux-01" + "value": "<>cvmlindef" }, "publicKeys": { "value": [ { - "keyData": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDdOir5eO28EBwxU0Dyra7g9h0HUXDyMNFp2z8PhaTUQgHjrimkMxjYRwEOG/lxnYL7+TqZk+HcPTfbZOunHBw0Wx2CITzILt6531vmIYZGfq5YyYXbxZa5MON7L/PVivoRlPj5Z/t4RhqMhyfR7EPcZ516LJ8lXPTo8dE/bkOCS+kFBEYHvPEEKAyLs19sRcK37SeHjpX04zdg62nqtuRr00Tp7oeiTXA1xn5K5mxeAswotmd8CU0lWUcJuPBWQedo649b+L2cm52kTncOBI6YChAeyEc1PDF0Tn9FmpdOWKtI9efh+S3f8qkcVEtSTXoTeroBd31nzjAunMrZeM8Ut6dre+XeQQIjT7I8oEm+ZkIuIyq0x2fls8JXP2YJDWDqu8v1+yLGTQ3Z9XVt2lMti/7bIgYxS0JvwOr5n5L4IzKvhb4fm13LLDGFa3o7Nsfe3fPb882APE0bLFCmfyIeiPh7go70WqZHakpgIr6LCWTyePez9CsI/rfWDb6eAM8= generated-by-azure", + "keyData": "", "path": "/home/localAdminUser/.ssh/authorized_keys" } ] @@ -1659,7 +1401,7 @@ module virtualMachines './Microsoft.Compute/virtualMachines/deploy.bicep' = { "value": [ { "principalIds": [ - "<>" + "" ], "roleDefinitionIdOrName": "Reader" } @@ -1670,7 +1412,7 @@ module virtualMachines './Microsoft.Compute/virtualMachines/deploy.bicep' = { }, "userAssignedIdentities": { "value": { - "/subscriptions/<>/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-<>-az-msi-x-001": {} + "": {} } } } @@ -1680,27 +1422,22 @@ module virtualMachines './Microsoft.Compute/virtualMachines/deploy.bicep' = {

-

Example 4: Windows Autmg

+

Example 2: Linux.Atmg

via Bicep module ```bicep -resource kv1 'Microsoft.KeyVault/vaults@2019-09-01' existing = { - name: 'adp-<>-az-kv-x-001' - scope: resourceGroup('<>','validation-rg') -} - module virtualMachines './Microsoft.Compute/virtualMachines/deploy.bicep' = { - name: '${uniqueString(deployment().name)}-VirtualMachines' + name: '${uniqueString(deployment().name)}-test-cvmlinatmg' params: { // Required parameters adminUsername: 'localAdminUser' imageReference: { - offer: 'WindowsServer' - publisher: 'MicrosoftWindowsServer' - sku: '2019-Datacenter' + offer: 'UbuntuServer' + publisher: 'Canonical' + sku: '18.04-LTS' version: 'latest' } nicConfigurations: [ @@ -1708,7 +1445,10 @@ module virtualMachines './Microsoft.Compute/virtualMachines/deploy.bicep' = { ipConfigurations: [ { name: 'ipconfig01' - subnetResourceId: '/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/adp-<>-az-vnet-x-001/subnets/<>-az-subnet-x-001' + pipConfiguration: { + publicIpNameSuffix: '-pip-01' + } + subnetResourceId: '' } ] nicSuffix: '-nic-01' @@ -1720,12 +1460,19 @@ module virtualMachines './Microsoft.Compute/virtualMachines/deploy.bicep' = { storageAccountType: 'Premium_LRS' } } - osType: 'Windows' + osType: 'Linux' vmSize: 'Standard_B12ms' // Non-required parameters - adminPassword: kv1.getSecret('adminPassword') configurationProfile: '/providers/Microsoft.Automanage/bestPractices/AzureBestPracticesProduction' - name: '<>-vm-win-03' + disablePasswordAuthentication: true + location: '' + name: '<>cvmlinatmg' + publicKeys: [ + { + keyData: '' + path: '/home/localAdminUser/.ssh/authorized_keys' + } + ] } } ``` @@ -1748,9 +1495,9 @@ module virtualMachines './Microsoft.Compute/virtualMachines/deploy.bicep' = { }, "imageReference": { "value": { - "offer": "WindowsServer", - "publisher": "MicrosoftWindowsServer", - "sku": "2019-Datacenter", + "offer": "UbuntuServer", + "publisher": "Canonical", + "sku": "18.04-LTS", "version": "latest" } }, @@ -1760,7 +1507,10 @@ module virtualMachines './Microsoft.Compute/virtualMachines/deploy.bicep' = { "ipConfigurations": [ { "name": "ipconfig01", - "subnetResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/adp-<>-az-vnet-x-001/subnets/<>-az-subnet-x-001" + "pipConfiguration": { + "publicIpNameSuffix": "-pip-01" + }, + "subnetResourceId": "" } ], "nicSuffix": "-nic-01" @@ -1776,25 +1526,31 @@ module virtualMachines './Microsoft.Compute/virtualMachines/deploy.bicep' = { } }, "osType": { - "value": "Windows" + "value": "Linux" }, "vmSize": { "value": "Standard_B12ms" }, // Non-required parameters - "adminPassword": { - "reference": { - "keyVault": { - "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.KeyVault/vaults/adp-<>-az-kv-x-001" - }, - "secretName": "adminPassword" - } - }, "configurationProfile": { "value": "/providers/Microsoft.Automanage/bestPractices/AzureBestPracticesProduction" }, + "disablePasswordAuthentication": { + "value": true + }, + "location": { + "value": "" + }, "name": { - "value": "<>-vm-win-03" + "value": "<>cvmlinatmg" + }, + "publicKeys": { + "value": [ + { + "keyData": "", + "path": "/home/localAdminUser/.ssh/authorized_keys" + } + ] } } } @@ -1803,27 +1559,22 @@ module virtualMachines './Microsoft.Compute/virtualMachines/deploy.bicep' = {

-

Example 5: Windows Min

+

Example 3: Linux.Min

via Bicep module ```bicep -resource kv1 'Microsoft.KeyVault/vaults@2019-09-01' existing = { - name: 'adp-<>-az-kv-x-001' - scope: resourceGroup('<>','validation-rg') -} - module virtualMachines './Microsoft.Compute/virtualMachines/deploy.bicep' = { - name: '${uniqueString(deployment().name)}-VirtualMachines' + name: '${uniqueString(deployment().name)}-test-cvmlinmin' params: { // Required parameters - adminUsername: 'localAdminUser' - imageReference: { - offer: 'WindowsServer' - publisher: 'MicrosoftWindowsServer' - sku: '2022-datacenter-azure-edition' + adminUsername: 'localAdminUser' + imageReference: { + offer: 'UbuntuServer' + publisher: 'Canonical' + sku: '18.04-LTS' version: 'latest' } nicConfigurations: [ @@ -1831,7 +1582,10 @@ module virtualMachines './Microsoft.Compute/virtualMachines/deploy.bicep' = { ipConfigurations: [ { name: 'ipconfig01' - subnetResourceId: '/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/adp-<>-az-vnet-x-001/subnets/<>-az-subnet-x-001' + pipConfiguration: { + publicIpNameSuffix: '-pip-01' + } + subnetResourceId: '' } ] nicSuffix: '-nic-01' @@ -1843,11 +1597,18 @@ module virtualMachines './Microsoft.Compute/virtualMachines/deploy.bicep' = { storageAccountType: 'Premium_LRS' } } - osType: 'Windows' + osType: 'Linux' vmSize: 'Standard_B12ms' // Non-required parameters - adminPassword: kv1.getSecret('adminPassword') - name: '<>-vm-win-02' + disablePasswordAuthentication: true + location: '' + name: '<>cvmlinmin' + publicKeys: [ + { + keyData: '' + path: '/home/localAdminUser/.ssh/authorized_keys' + } + ] } } ``` @@ -1870,9 +1631,9 @@ module virtualMachines './Microsoft.Compute/virtualMachines/deploy.bicep' = { }, "imageReference": { "value": { - "offer": "WindowsServer", - "publisher": "MicrosoftWindowsServer", - "sku": "2022-datacenter-azure-edition", + "offer": "UbuntuServer", + "publisher": "Canonical", + "sku": "18.04-LTS", "version": "latest" } }, @@ -1882,7 +1643,10 @@ module virtualMachines './Microsoft.Compute/virtualMachines/deploy.bicep' = { "ipConfigurations": [ { "name": "ipconfig01", - "subnetResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/adp-<>-az-vnet-x-001/subnets/<>-az-subnet-x-001" + "pipConfiguration": { + "publicIpNameSuffix": "-pip-01" + }, + "subnetResourceId": "" } ], "nicSuffix": "-nic-01" @@ -1898,22 +1662,28 @@ module virtualMachines './Microsoft.Compute/virtualMachines/deploy.bicep' = { } }, "osType": { - "value": "Windows" + "value": "Linux" }, "vmSize": { "value": "Standard_B12ms" }, // Non-required parameters - "adminPassword": { - "reference": { - "keyVault": { - "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.KeyVault/vaults/adp-<>-az-kv-x-001" - }, - "secretName": "adminPassword" - } + "disablePasswordAuthentication": { + "value": true + }, + "location": { + "value": "" }, "name": { - "value": "<>-vm-win-02" + "value": "<>cvmlinmin" + }, + "publicKeys": { + "value": [ + { + "keyData": "", + "path": "/home/localAdminUser/.ssh/authorized_keys" + } + ] } } } @@ -1922,20 +1692,15 @@ module virtualMachines './Microsoft.Compute/virtualMachines/deploy.bicep' = {

-

Example 6: Windows

+

Example 4: Windows

via Bicep module ```bicep -resource kv1 'Microsoft.KeyVault/vaults@2019-09-01' existing = { - name: 'adp-<>-az-kv-x-001' - scope: resourceGroup('<>','validation-rg') -} - module virtualMachines './Microsoft.Compute/virtualMachines/deploy.bicep' = { - name: '${uniqueString(deployment().name)}-VirtualMachines' + name: '${uniqueString(deployment().name)}-test-cvmwindef' params: { // Required parameters adminUsername: 'localAdminUser' @@ -1952,12 +1717,12 @@ module virtualMachines './Microsoft.Compute/virtualMachines/deploy.bicep' = { { applicationSecurityGroups: [ { - id: '/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/applicationSecurityGroups/adp-<>-az-asg-x-001' + id: '' } ] loadBalancerBackendAddressPools: [ { - id: '/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/loadBalancers/adp-<>-az-lb-internal-001/backendAddressPools/servers' + id: '' } ] name: 'ipconfig01' @@ -1966,20 +1731,20 @@ module virtualMachines './Microsoft.Compute/virtualMachines/deploy.bicep' = { roleAssignments: [ { principalIds: [ - '<>' + '' ] roleDefinitionIdOrName: 'Reader' } ] } - subnetResourceId: '/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/adp-<>-az-vnet-x-001/subnets/<>-az-subnet-x-001' + subnetResourceId: '' } ] nicSuffix: '-nic-01' roleAssignments: [ { principalIds: [ - '<>' + '' ] roleDefinitionIdOrName: 'Reader' } @@ -1998,11 +1763,11 @@ module virtualMachines './Microsoft.Compute/virtualMachines/deploy.bicep' = { osType: 'Windows' vmSize: 'Standard_B12ms' // Non-required parameters - adminPassword: kv1.getSecret('adminPassword') + adminPassword: '' availabilityZone: 2 - backupPolicyName: 'VMpolicy' - backupVaultName: 'adp-<>-az-rsv-x-001' - backupVaultResourceGroup: 'validation-rg' + backupPolicyName: '' + backupVaultName: '' + backupVaultResourceGroup: '' dataDisks: [ { caching: 'None' @@ -2023,11 +1788,11 @@ module virtualMachines './Microsoft.Compute/virtualMachines/deploy.bicep' = { } } ] - 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: '' encryptionAtHost: false extensionAntiMalwareConfig: { enabled: true @@ -2051,13 +1816,13 @@ module virtualMachines './Microsoft.Compute/virtualMachines/deploy.bicep' = { enabled: true fileData: [ { - storageAccountId: '/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001' - uri: 'https://adp<>azsax001.blob.core.windows.net/scripts/scriptExtensionMasterInstaller.ps1' + storageAccountId: '' + uri: '' } ] } extensionCustomScriptProtectedSetting: { - commandToExecute: 'powershell -ExecutionPolicy Unrestricted -Command \'& .\\scriptExtensionMasterInstaller.ps1\'' + commandToExecute: '' } extensionDependencyAgentConfig: { enabled: true @@ -2066,11 +1831,11 @@ module virtualMachines './Microsoft.Compute/virtualMachines/deploy.bicep' = { enabled: true settings: { EncryptionOperation: 'EnableEncryption' - KekVaultResourceId: '/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.KeyVault/vaults/adp-<>-az-kv-x-001' + KekVaultResourceId: '' KeyEncryptionAlgorithm: 'RSA-OAEP' - KeyEncryptionKeyURL: 'https://adp-<>-az-kv-x-001.vault.azure.net/keys/keyEncryptionKey/bc3bb46d95c64367975d722f473eeae5' - KeyVaultResourceId: '/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.KeyVault/vaults/adp-<>-az-kv-x-001' - KeyVaultURL: 'https://adp-<>-az-kv-x-001.vault.azure.net/' + KeyEncryptionKeyURL: '' + KeyVaultResourceId: '' + KeyVaultURL: '' ResizeOSDisk: 'false' VolumeType: 'All' } @@ -2084,21 +1849,22 @@ module virtualMachines './Microsoft.Compute/virtualMachines/deploy.bicep' = { extensionNetworkWatcherAgentConfig: { enabled: true } + location: '' lock: 'CanNotDelete' - monitoringWorkspaceId: '/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001' - name: '<>-vm-win-01' - proximityPlacementGroupResourceId: '/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Compute/proximityPlacementGroups/adp-<>-az-ppg-vm-001' + monitoringWorkspaceId: '' + name: '<>cvmwindef' + proximityPlacementGroupResourceId: '' roleAssignments: [ { principalIds: [ - '<>' + '' ] roleDefinitionIdOrName: 'Reader' } ] systemAssignedIdentity: true userAssignedIdentities: { - '/subscriptions/<>/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-<>-az-msi-x-001': {} + '': {} } } } @@ -2136,12 +1902,12 @@ module virtualMachines './Microsoft.Compute/virtualMachines/deploy.bicep' = { { "applicationSecurityGroups": [ { - "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/applicationSecurityGroups/adp-<>-az-asg-x-001" + "id": "" } ], "loadBalancerBackendAddressPools": [ { - "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/loadBalancers/adp-<>-az-lb-internal-001/backendAddressPools/servers" + "id": "" } ], "name": "ipconfig01", @@ -2150,20 +1916,20 @@ module virtualMachines './Microsoft.Compute/virtualMachines/deploy.bicep' = { "roleAssignments": [ { "principalIds": [ - "<>" + "" ], "roleDefinitionIdOrName": "Reader" } ] }, - "subnetResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/adp-<>-az-vnet-x-001/subnets/<>-az-subnet-x-001" + "subnetResourceId": "" } ], "nicSuffix": "-nic-01", "roleAssignments": [ { "principalIds": [ - "<>" + "" ], "roleDefinitionIdOrName": "Reader" } @@ -2190,24 +1956,19 @@ module virtualMachines './Microsoft.Compute/virtualMachines/deploy.bicep' = { }, // Non-required parameters "adminPassword": { - "reference": { - "keyVault": { - "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.KeyVault/vaults/adp-<>-az-kv-x-001" - }, - "secretName": "adminPassword" - } + "value": "" }, "availabilityZone": { "value": 2 }, "backupPolicyName": { - "value": "VMpolicy" + "value": "" }, "backupVaultName": { - "value": "adp-<>-az-rsv-x-001" + "value": "" }, "backupVaultResourceGroup": { - "value": "validation-rg" + "value": "" }, "dataDisks": { "value": [ @@ -2232,19 +1993,19 @@ module virtualMachines './Microsoft.Compute/virtualMachines/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": "" }, "encryptionAtHost": { "value": false @@ -2274,15 +2035,15 @@ module virtualMachines './Microsoft.Compute/virtualMachines/deploy.bicep' = { "enabled": true, "fileData": [ { - "storageAccountId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Storage/storageAccounts/adp<>azsax001", - "uri": "https://adp<>azsax001.blob.core.windows.net/scripts/scriptExtensionMasterInstaller.ps1" + "storageAccountId": "", + "uri": "" } ] } }, "extensionCustomScriptProtectedSetting": { "value": { - "commandToExecute": "powershell -ExecutionPolicy Unrestricted -Command \"& .\\scriptExtensionMasterInstaller.ps1\"" + "commandToExecute": "" } }, "extensionDependencyAgentConfig": { @@ -2295,11 +2056,11 @@ module virtualMachines './Microsoft.Compute/virtualMachines/deploy.bicep' = { "enabled": true, "settings": { "EncryptionOperation": "EnableEncryption", - "KekVaultResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.KeyVault/vaults/adp-<>-az-kv-x-001", + "KekVaultResourceId": "", "KeyEncryptionAlgorithm": "RSA-OAEP", - "KeyEncryptionKeyURL": "https://adp-<>-az-kv-x-001.vault.azure.net/keys/keyEncryptionKey/bc3bb46d95c64367975d722f473eeae5", - "KeyVaultResourceId": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.KeyVault/vaults/adp-<>-az-kv-x-001", - "KeyVaultURL": "https://adp-<>-az-kv-x-001.vault.azure.net/", + "KeyEncryptionKeyURL": "", + "KeyVaultResourceId": "", + "KeyVaultURL": "", "ResizeOSDisk": "false", "VolumeType": "All" } @@ -2320,23 +2081,26 @@ module virtualMachines './Microsoft.Compute/virtualMachines/deploy.bicep' = { "enabled": true } }, + "location": { + "value": "" + }, "lock": { "value": "CanNotDelete" }, "monitoringWorkspaceId": { - "value": "/subscriptions/<>/resourcegroups/validation-rg/providers/microsoft.operationalinsights/workspaces/adp-<>-az-law-x-001" + "value": "" }, "name": { - "value": "<>-vm-win-01" + "value": "<>cvmwindef" }, "proximityPlacementGroupResourceId": { - "value": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Compute/proximityPlacementGroups/adp-<>-az-ppg-vm-001" + "value": "" }, "roleAssignments": { "value": [ { "principalIds": [ - "<>" + "" ], "roleDefinitionIdOrName": "Reader" } @@ -2347,8 +2111,238 @@ module virtualMachines './Microsoft.Compute/virtualMachines/deploy.bicep' = { }, "userAssignedIdentities": { "value": { - "/subscriptions/<>/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-<>-az-msi-x-001": {} + "": {} + } + } + } +} +``` + +
+

+ +

Example 5: Windows.Atmg

+ +
+ +via Bicep module + +```bicep +module virtualMachines './Microsoft.Compute/virtualMachines/deploy.bicep' = { + name: '${uniqueString(deployment().name)}-test-cvmwinatmg' + params: { + // Required parameters + adminUsername: 'localAdminUser' + imageReference: { + offer: 'WindowsServer' + publisher: 'MicrosoftWindowsServer' + sku: '2019-Datacenter' + version: 'latest' + } + nicConfigurations: [ + { + ipConfigurations: [ + { + name: 'ipconfig01' + subnetResourceId: '' + } + ] + nicSuffix: '-nic-01' + } + ] + osDisk: { + diskSizeGB: '128' + managedDisk: { + storageAccountType: 'Premium_LRS' + } + } + osType: 'Windows' + vmSize: 'Standard_B12ms' + // Non-required parameters + adminPassword: '' + configurationProfile: '/providers/Microsoft.Automanage/bestPractices/AzureBestPracticesProduction' + location: '' + name: '<>cvmwinatmg' + } +} +``` + +
+

+ +

+ +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 + "adminUsername": { + "value": "localAdminUser" + }, + "imageReference": { + "value": { + "offer": "WindowsServer", + "publisher": "MicrosoftWindowsServer", + "sku": "2019-Datacenter", + "version": "latest" + } + }, + "nicConfigurations": { + "value": [ + { + "ipConfigurations": [ + { + "name": "ipconfig01", + "subnetResourceId": "" + } + ], + "nicSuffix": "-nic-01" + } + ] + }, + "osDisk": { + "value": { + "diskSizeGB": "128", + "managedDisk": { + "storageAccountType": "Premium_LRS" + } + } + }, + "osType": { + "value": "Windows" + }, + "vmSize": { + "value": "Standard_B12ms" + }, + // Non-required parameters + "adminPassword": { + "value": "" + }, + "configurationProfile": { + "value": "/providers/Microsoft.Automanage/bestPractices/AzureBestPracticesProduction" + }, + "location": { + "value": "" + }, + "name": { + "value": "<>cvmwinatmg" + } + } +} +``` + +
+

+ +

Example 6: Windows.Min

+ +
+ +via Bicep module + +```bicep +module virtualMachines './Microsoft.Compute/virtualMachines/deploy.bicep' = { + name: '${uniqueString(deployment().name)}-test-cvmwinmin' + params: { + // Required parameters + adminUsername: 'localAdminUser' + imageReference: { + offer: 'WindowsServer' + publisher: 'MicrosoftWindowsServer' + sku: '2022-datacenter-azure-edition' + version: 'latest' + } + nicConfigurations: [ + { + ipConfigurations: [ + { + name: 'ipconfig01' + subnetResourceId: '' + } + ] + nicSuffix: '-nic-01' + } + ] + osDisk: { + diskSizeGB: '128' + managedDisk: { + storageAccountType: 'Premium_LRS' + } + } + osType: 'Windows' + vmSize: 'Standard_B12ms' + // Non-required parameters + adminPassword: '' + location: '' + name: '<>cvmwinmin' + } +} +``` + +
+

+ +

+ +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 + "adminUsername": { + "value": "localAdminUser" + }, + "imageReference": { + "value": { + "offer": "WindowsServer", + "publisher": "MicrosoftWindowsServer", + "sku": "2022-datacenter-azure-edition", + "version": "latest" + } + }, + "nicConfigurations": { + "value": [ + { + "ipConfigurations": [ + { + "name": "ipconfig01", + "subnetResourceId": "" + } + ], + "nicSuffix": "-nic-01" + } + ] + }, + "osDisk": { + "value": { + "diskSizeGB": "128", + "managedDisk": { + "storageAccountType": "Premium_LRS" + } } + }, + "osType": { + "value": "Windows" + }, + "vmSize": { + "value": "Standard_B12ms" + }, + // Non-required parameters + "adminPassword": { + "value": "" + }, + "location": { + "value": "" + }, + "name": { + "value": "<>cvmwinmin" } } } diff --git a/utilities/tools/Set-ModuleReadMe.ps1 b/utilities/tools/Set-ModuleReadMe.ps1 index 2a097d2015..e1eca5fb66 100644 --- a/utilities/tools/Set-ModuleReadMe.ps1 +++ b/utilities/tools/Set-ModuleReadMe.ps1 @@ -628,8 +628,11 @@ Convert the given Bicep parameter block to JSON parameter block .PARAMETER BicepParamBlock Mandatory. The Bicep parameter block to process +.PARAMETER CurrentFilePath +Mandatory. The Path of the file containing the param block + .EXAMPLE -ConvertTo-FormattedJSONParameterObject -BicepParamBlock "name: 'carml'\nlock: 'CanNotDelete'" +ConvertTo-FormattedJSONParameterObject -BicepParamBlock "name: 'carml'\nlock: 'CanNotDelete'" -CurrentFilePath 'c:/deploy.test.bicep' Convert the Bicep string "name: 'carml'\nlock: 'CanNotDelete'" into a parameter JSON object. Would result into: @@ -647,7 +650,10 @@ function ConvertTo-FormattedJSONParameterObject { [CmdletBinding()] param ( [Parameter()] - [string] $BicepParamBlock + [string] $BicepParamBlock, + + [Parameter()] + [string] $CurrentFilePath ) if ([String]::IsNullOrEmpty($BicepParamBlock)) { @@ -736,8 +742,11 @@ function ConvertTo-FormattedJSONParameterObject { } # [2.7] Format the final JSON string to an object to enable processing - $paramInJsonFormatObject = $paramInJSONFormatArray | Out-String | ConvertFrom-Json -AsHashtable -Depth 99 - + try { + $paramInJsonFormatObject = $paramInJSONFormatArray | Out-String | ConvertFrom-Json -AsHashtable -Depth 99 -ErrorAction 'Stop' + } catch { + throw ('Failed to process file [{0}]. Please check if it properly formatted. Original error message: [{1}]' -f $CurrentFilePath, $_.Exception.Message) + } # [3/4] Inject top-level 'value`' properties $paramInJsonFormatObjectWithValue = @{} foreach ($paramKey in $topLevelParams) { @@ -983,6 +992,7 @@ function Set-DeploymentExamplesSection { # [5/6] Convert Bicep parameter block to JSON parameter block to enable processing $conversionInputObject = @{ BicepParamBlock = $paramBlock + CurrentFilePath = $testFilePath } $paramsInJSONFormat = ConvertTo-FormattedJSONParameterObject @conversionInputObject @@ -1005,6 +1015,21 @@ function Set-DeploymentExamplesSection { $formattedBicepExample = $rawBicepExample[0..($paramsStartIndex - 1)] + ($bicepExample -split '\n') + $rawBicepExample[($paramsEndIndex + 1)..($rawBicepExample.Count)] } + # Remove any dependsOn as it it test specific + if ($detected = ($formattedBicepExample | Select-String '^\s*dependsOn:\s*\[\s*$' | ForEach-Object { $_.LineNumber - 1 })) { + $dependsOnStartIndex = $detected[0] + + # Find out where the 'dependsOn' ends + $dependsOnEndIndex = $dependsOnStartIndex + do { + $dependsOnEndIndex++ + } while ($formattedBicepExample[$dependsOnEndIndex] -notmatch '^\s*\]\s*$') + + # Cut the 'dependsOn' block out + $formattedBicepExample = $formattedBicepExample[0..($dependsOnStartIndex - 1)] + $formattedBicepExample[($dependsOnEndIndex + 1)..($formattedBicepExample.Count)] + } + + # Build result $SectionContent += @( '', '
'