diff --git a/modules/Microsoft.Compute/images/.test/common/dependencies.bicep b/modules/Microsoft.Compute/images/.test/common/dependencies.bicep new file mode 100644 index 0000000000..3e1a47c1fb --- /dev/null +++ b/modules/Microsoft.Compute/images/.test/common/dependencies.bicep @@ -0,0 +1,152 @@ +@description('Optional. The location to deploy to.') +param location string = resourceGroup().location + +@description('Required. The name of the Managed Identity to create.') +param managedIdentityName string + +@description('Required. The name of the Storage Account to create.') +param storageAccountName string + +@description('Required. The name prefix of the Image Template to create.') +param imageTemplateNamePrefix string + +@description('Generated. Do not provide a value! This date value is used to generate a unique image template name.') +param baseTime string = utcNow('yyyy-MM-dd-HH-mm-ss') + +@description('Required. The name of the Deployment Script to create for triggering the image creation.') +param triggerImageDeploymentScriptName string + +@description('Required. The name of the Deployment Script to copy the VHD to a destination storage account.') +param copyVhdDeploymentScriptName string + +@description('Required. The name of the destination Storage Account to copy the created VHD to.') +param destinationStorageAccountName string + +resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2018-11-30' = { + name: managedIdentityName + location: location +} + +resource storageAccount 'Microsoft.Storage/storageAccounts@2021-09-01' = { + name: storageAccountName + location: location + kind: 'StorageV2' + sku: { + name: 'Standard_LRS' + } + properties: { + allowBlobPublicAccess: false + } + resource blobServices 'blobServices@2021-09-01' = { + name: 'default' + resource container 'containers@2021-09-01' = { + name: 'vhds' + properties: { + publicAccess: 'None' + } + } + } +} + +module roleAssignment 'dependencies_rbac.bicep' = { + name: '${uniqueString(deployment().name, location)}-MSI-roleAssignment' + scope: subscription() + params: { + managedIdentityPrincipalId: managedIdentity.properties.principalId + managedIdentityResourceId: managedIdentity.id + } +} + +// Deploy image template +resource imageTemplate 'Microsoft.VirtualMachineImages/imageTemplates@2022-02-14' = { + name: '${imageTemplateNamePrefix}-${baseTime}' + location: location + identity: { + type: 'UserAssigned' + userAssignedIdentities: { + '${managedIdentity.id}': {} + } + } + properties: { + buildTimeoutInMinutes: 0 + vmProfile: { + vmSize: 'Standard_D2s_v3' + osDiskSizeGB: 127 + } + source: { + type: 'PlatformImage' + publisher: 'MicrosoftWindowsDesktop' + offer: 'Windows-10' + sku: '19h2-evd' + version: 'latest' + } + distribute: [ + { + type: 'VHD' + runOutputName: '${imageTemplateNamePrefix}-VHD' + artifactTags: {} + } + ] + customize: [ + { + restartTimeout: '30m' + type: 'WindowsRestart' + } + ] + } +} + +// Trigger VHD creation +resource triggerImageDeploymentScript 'Microsoft.Resources/deploymentScripts@2020-10-01' = { + name: triggerImageDeploymentScriptName + location: location + kind: 'AzurePowerShell' + identity: { + type: 'UserAssigned' + userAssignedIdentities: { + '${managedIdentity.id}': {} + } + } + properties: { + azPowerShellVersion: '8.0' + retentionInterval: 'P1D' + arguments: '-ImageTemplateName \\"${imageTemplate.name}\\" -ImageTemplateResourceGroup \\"${resourceGroup().name}\\"' + scriptContent: loadTextContent('../.scripts/Start-ImageTemplate.ps1') + cleanupPreference: 'OnSuccess' + forceUpdateTag: baseTime + } + dependsOn: [ + roleAssignment + ] +} + +// Copy VHD to destination storage account +resource copyVhdDeploymentScript 'Microsoft.Resources/deploymentScripts@2020-10-01' = { + name: copyVhdDeploymentScriptName + location: location + kind: 'AzurePowerShell' + identity: { + type: 'UserAssigned' + userAssignedIdentities: { + '${managedIdentity.id}': {} + } + } + properties: { + azPowerShellVersion: '8.0' + retentionInterval: 'P1D' + arguments: '-ImageTemplateName \\"${imageTemplate.name}\\" -ImageTemplateResourceGroup \\"${resourceGroup().name}\\" -DestinationStorageAccountName \\"${destinationStorageAccountName}\\" -VhdName \\"${imageTemplateNamePrefix}\\" -WaitForComplete' + scriptContent: loadTextContent('../.scripts/Copy-VhdToStorageAccount.ps1') + cleanupPreference: 'OnSuccess' + forceUpdateTag: baseTime + } + dependsOn: [ triggerImageDeploymentScript ] +} + +@description('The URI of the created VHD.') +output vhdUri string = 'https://${destinationStorageAccountName}.blob.core.windows.net/vhds/${imageTemplateNamePrefix}.vhd' + +@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 diff --git a/modules/Microsoft.Compute/images/.test/common/dependencies01.bicep b/modules/Microsoft.Compute/images/.test/common/dependencies01.bicep deleted file mode 100644 index 51c195a74e..0000000000 --- a/modules/Microsoft.Compute/images/.test/common/dependencies01.bicep +++ /dev/null @@ -1,40 +0,0 @@ -@description('Optional. The location to deploy to.') -param location string = resourceGroup().location - -@description('Required. The name of the Managed Identity to create.') -param managedIdentityName string - -@description('Required. The name of the Storage Account to create.') -param storageAccountName string - -resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2018-11-30' = { - name: managedIdentityName - location: location -} - -resource storageAccount 'Microsoft.Storage/storageAccounts@2021-09-01' = { - name: storageAccountName - location: location - kind: 'StorageV2' - sku: { - name: 'Standard_LRS' - } - properties: { - allowBlobPublicAccess: false - } - resource blobServices 'blobServices@2021-09-01' = { - name: 'default' - resource container 'containers@2021-09-01' = { - name: 'vhds' - properties: { - publicAccess: 'None' - } - } - } -} - -@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 diff --git a/modules/Microsoft.Compute/images/.test/common/dependencies02.bicep b/modules/Microsoft.Compute/images/.test/common/dependencies02.bicep deleted file mode 100644 index 805792b26f..0000000000 --- a/modules/Microsoft.Compute/images/.test/common/dependencies02.bicep +++ /dev/null @@ -1,105 +0,0 @@ -@description('Optional. The location to deploy to.') -param location string = resourceGroup().location - -@description('Required. The resource ID of the Managed Identity to assign.') -param managedIdentityResourceId string - -@description('Required. The name prefix of the Image Template to create.') -param imageTemplateNamePrefix string - -@description('Generated. Do not provide a value! This date value is used to generate a unique image template name.') -param baseTime string = utcNow('yyyy-MM-dd-HH-mm-ss') - -@description('Required. The name of the Deployment Script to create for triggering the image creation.') -param triggerImageDeploymentScriptName string - -@description('Required. The name of the Deployment Script to copy the VHD to a destination storage account.') -param copyVhdDeploymentScriptName string - -@description('Required. The name of the destination Storage Account to copy the created VHD to.') -param destinationStorageAccountName string - -// Deploy image template -resource imageTemplate 'Microsoft.VirtualMachineImages/imageTemplates@2022-02-14' = { - name: '${imageTemplateNamePrefix}-${baseTime}' - location: location - identity: { - type: 'UserAssigned' - userAssignedIdentities: { - '${managedIdentityResourceId}': {} - } - } - properties: { - buildTimeoutInMinutes: 0 - vmProfile: { - vmSize: 'Standard_D2s_v3' - osDiskSizeGB: 127 - } - source: { - type: 'PlatformImage' - publisher: 'MicrosoftWindowsDesktop' - offer: 'Windows-10' - sku: '19h2-evd' - version: 'latest' - } - distribute: [ - { - type: 'VHD' - runOutputName: '${imageTemplateNamePrefix}-VHD' - artifactTags: {} - } - ] - customize: [ - { - restartTimeout: '30m' - type: 'WindowsRestart' - } - ] - } -} - -// // Trigger VHD creation -// resource triggerImageDeploymentScript 'Microsoft.Resources/deploymentScripts@2020-10-01' = { -// name: triggerImageDeploymentScriptName -// location: location -// kind: 'AzurePowerShell' -// identity: { -// type: 'UserAssigned' -// userAssignedIdentities: { -// '${managedIdentityResourceId}': {} -// } -// } -// properties: { -// azPowerShellVersion: '8.0' -// retentionInterval: 'P1D' -// arguments: '-ImageTemplateName \\"${imageTemplate.name}\\" -ImageTemplateResourceGroup \\"${resourceGroup().name}\\"' -// scriptContent: loadTextContent('../.scripts/Start-ImageTemplate.ps1') -// cleanupPreference: 'OnSuccess' -// forceUpdateTag: baseTime -// } -// } - -// // Copy VHD to destination storage account -// resource copyVhdDeploymentScript 'Microsoft.Resources/deploymentScripts@2020-10-01' = { -// name: copyVhdDeploymentScriptName -// location: location -// kind: 'AzurePowerShell' -// identity: { -// type: 'UserAssigned' -// userAssignedIdentities: { -// '${managedIdentityResourceId}': {} -// } -// } -// properties: { -// azPowerShellVersion: '8.0' -// retentionInterval: 'P1D' -// arguments: '-ImageTemplateName \\"${imageTemplate.name}\\" -ImageTemplateResourceGroup \\"${resourceGroup().name}\\" -DestinationStorageAccountName \\"${destinationStorageAccountName}\\" -VhdName \\"${imageTemplateNamePrefix}\\" -WaitForComplete' -// scriptContent: loadTextContent('../.scripts/Copy-VhdToStorageAccount.ps1') -// cleanupPreference: 'OnSuccess' -// forceUpdateTag: baseTime -// } -// dependsOn: [ triggerImageDeploymentScript ] -// } - -@description('The URI of the created VHD.') -output vhdUri string = 'https://${destinationStorageAccountName}.blob.core.windows.net/vhds/${imageTemplateNamePrefix}.vhd' diff --git a/modules/Microsoft.Compute/images/.test/common/dependencies_rbac.bicep b/modules/Microsoft.Compute/images/.test/common/dependencies_rbac.bicep new file mode 100644 index 0000000000..7fbc0ff9ed --- /dev/null +++ b/modules/Microsoft.Compute/images/.test/common/dependencies_rbac.bicep @@ -0,0 +1,13 @@ +targetScope = 'subscription' + +param managedIdentityResourceId string +param managedIdentityPrincipalId string + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = { + name: guid(subscription().subscriptionId, 'Contributor', managedIdentityResourceId) + properties: { + roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') // Contributor + principalId: managedIdentityPrincipalId + principalType: 'ServicePrincipal' + } +} diff --git a/modules/Microsoft.Compute/images/.test/common/deploy.test.bicep b/modules/Microsoft.Compute/images/.test/common/deploy.test.bicep index 81daae8396..4211526b54 100644 --- a/modules/Microsoft.Compute/images/.test/common/deploy.test.bicep +++ b/modules/Microsoft.Compute/images/.test/common/deploy.test.bicep @@ -40,43 +40,22 @@ resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { location: location } -module resourceGroupResources01 'dependencies01.bicep' = { +module resourceGroupResources 'dependencies.bicep' = { scope: resourceGroup name: '${uniqueString(deployment().name, location)}-paramNested01' params: { managedIdentityName: managedIdentityName storageAccountName: destinationStorageAccountName - } -} - -resource roleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = { - name: guid(subscription().subscriptionId, 'Contributor', managedIdentityName) - properties: { - roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') // Contributor - principalId: resourceGroupResources01.outputs.managedIdentityPrincipalId - principalType: 'ServicePrincipal' - } -} - -module resourceGroupResources02 'dependencies02.bicep' = { - scope: resourceGroup - name: '${uniqueString(deployment().name, location)}-paramNested02' - params: { - managedIdentityResourceId: resourceGroupResources01.outputs.managedIdentityResourceId imageTemplateNamePrefix: imageTemplateNamePrefix triggerImageDeploymentScriptName: triggerImageDeploymentScriptName copyVhdDeploymentScriptName: copyVhdDeploymentScriptName destinationStorageAccountName: destinationStorageAccountName } - dependsOn: [ - roleAssignment - ] } // ============== // // Test Execution // // ============== // - module testDeployment '../../deploy.bicep' = { scope: resourceGroup name: '${uniqueString(deployment().name)}-test-${serviceShort}' @@ -84,7 +63,7 @@ module testDeployment '../../deploy.bicep' = { // Required parameters name: '<>${serviceShort}001' osAccountType: 'Premium_LRS' - osDiskBlobUri: resourceGroupResources02.outputs.vhdUri + osDiskBlobUri: resourceGroupResources.outputs.vhdUri osDiskCaching: 'ReadWrite' osType: 'Windows' // Non-required parameters @@ -92,7 +71,7 @@ module testDeployment '../../deploy.bicep' = { roleAssignments: [ { principalIds: [ - resourceGroupResources01.outputs.managedIdentityPrincipalId + resourceGroupResources.outputs.managedIdentityPrincipalId ] roleDefinitionIdOrName: 'Reader' }