diff --git a/src/bicep/add-ons/Imaging/New-AzureZeroTrustImageTemplateSpec.ps1 b/src/bicep/add-ons/Imaging/New-AzureZeroTrustImageTemplateSpec.ps1
new file mode 100644
index 000000000..4385eca2a
--- /dev/null
+++ b/src/bicep/add-ons/Imaging/New-AzureZeroTrustImageTemplateSpec.ps1
@@ -0,0 +1,21 @@
+[CmdletBinding(SupportsShouldProcess)]
+param (
+ [Parameter(Mandatory)]
+ [string]$TemplateSpecName,
+
+ [Parameter(Mandatory)]
+ [string]$Location,
+
+ [Parameter(Mandatory)]
+ [string]$ResourceGroupName
+)
+
+New-AzTemplateSpec `
+ -Name $TemplateSpecName `
+ -ResourceGroupName $ResourceGroupName `
+ -Version '1.0' `
+ -Location $Location `
+ -DisplayName "Zero Trust Image Template" `
+ -TemplateFile '.\solution.json' `
+ -UIFormDefinitionFile '.\uiDefinition.json' `
+ -Force
\ No newline at end of file
diff --git a/src/bicep/add-ons/Imaging/README.md b/src/bicep/add-ons/Imaging/README.md
new file mode 100644
index 000000000..15565e1a8
--- /dev/null
+++ b/src/bicep/add-ons/Imaging/README.md
@@ -0,0 +1,414 @@
+# Zero Trust and Azure Imaging
+
+This zero trust imaging solution for Azure allows you create images in an Azure environment that adheres to zero trust. While other options exist in Azure, its either a manual process or it doesn't adhere to zero trust. Azure Image Builder (AIB) is a great imaging service in Azure but does not adhere to zero trust. The service creates a staging resource group with a storage account that cannot be configured with a private endpoint. This breaks the zero trust principles. This solution uses a storage account with a private endpoint to store applications and the existing, preconfigured resources that comply with the principles.
+
+```mermaid
+graph TD;
+
+ A[Download Software Prerequisites] -->B(Upload Scripts and Installers to Storage Account)-->C(Review Azure Resource Requirements) -->D(Clone Repo) --> E(Create TemplateSpec)--> F(Ready for Zero Trust Imaging)
+```
+
+## Prequisites
+
+### Azure Resource Provider Feature for Encryption At Host
+
+This solution adheres to Zero Trust which dictates that all virtual machine disks must be encrypted. The encryption at host feature enables disk encryption on virtual machine temp and cache disks. To use this feature, a resource provider feature must enabled on your Azure subscription. Use the following PowerShell script to enable the feature:
+
+```powershell
+Register-AzProviderFeature -FeatureName "EncryptionAtHost" -ProviderNamespace "Microsoft.Compute"
+```
+
+### Required Permissions
+
+Permissions:
+ Ensure the principal deploying the solution has "Owner" and "Key Vault Administrator" roles assigned on the target Azure subscription. This solution deploys role assignments at various scopes so the principal deploying this solution will need to be an Owner at the subscription scope for a successful deployment. It also deploys a key and secrets in a key vault to enhance security. A custom role may be used to reduce the scope of permisions required if your organization wants to use something other than they built in roles.
+
+[Creating a custom role](https://learn.microsoft.com/en-us/azure/role-based-access-control/custom-roles)
+
+### Software
+
+Ensure the following software is installed on your client workstation:
+
+* [Azure Bicep](https://learn.microsoft.com/en-us/azure/azure-resource-manager/bicep/overview?tabs=bicep)
+* [Azure PowerShell Modules](https://learn.microsoft.com/en-us/powershell/azure/install-azure-powershell?view=azps-10.2.0)
+
+### Upload the following scripts and files to your storage account container
+
+* [Scripts](https://github.com/mikedzikowski/ZTAImage/tree/main/ImageCustomizationScripts)
+* [Az.Accounts 2.12.1 PowerShell Module](https://www.powershellgallery.com/api/v2/package/Az.Accounts/2.12.1)
+* [Az.Automation 1.9.0 PowerShell Module](https://www.powershellgallery.com/api/v2/package/Az.Automation/1.9.0)
+* [Az.Compute 5.7.0 PowerShell Module](https://www.powershellgallery.com/api/v2/package/Az.Compute/5.7.0)
+* [Az.Resources 6.6.0 PowerShell Module](https://www.powershellgallery.com/api/v2/package/Az.Resources/6.6.0)
+* [Office Installer](https://www.microsoft.com/en-us/download/details.aspx?id=49117)
+* [vDot Installers](https://github.com/The-Virtual-Desktop-Team/Virtual-Desktop-Optimization-Tool/archive/refs/heads/main.zip)
+* [Teams Installer - Commercial](https://teams.microsoft.com/downloads/desktopurl?env=production&plat=windows&arch=x64&managedInstaller=true&download=true)
+* [Teams Installer - DoD](https://dod.teams.microsoft.us/downloads/desktopurl?env=production&plat=windows&arch=x64&managedInstaller=true&download=true)
+* [Teams Installer - GCC](https://teams.microsoft.com/downloads/desktopurl?env=production&plat=windows&arch=x64&managedInstaller=true&ring=general_gcc&download=true)
+* [Teams Installer - GCCH](https://gov.teams.microsoft.us/downloads/desktopurl?env=production&plat=windows&arch=x64&managedInstaller=true&download=true)
+* [Microsoft Visual C++ Redistributable](https://aka.ms/vs/16/release/vc_redist.x64.exe)
+* [Remote Desktop WebRTC Redirector Service](https://aka.ms/msrdcwebrtcsvc/msi)
+* [ArcGIS Pro Installer - as Zip File](https://pro.arcgis.com/en/pro-app/latest/get-started/download-arcgis-pro.htm)
+
+ You can download ArcGIS Pro from My Esri or your ArcGIS Online organization.
+ Once the application is downloaded, if your windows OS image requires ArcGIS Pro you will need to create a ZIP file that contains all of the installation bits including the Windows Runtime.
+
+ Example:
+ ![Alt text](images/arcGisProRuntimeExample.png)
+
+ | Software | Minimum requirement
+ |:---------|:--------:|
+ | Microsoft .NET | [Microsoft .NET Desktop Runtime 6.0.5](https://dotnet.microsoft.com/en-us/download/dotnet/thank-you/runtime-desktop-6.0.5-windows-x64-installer) or a [later patch](https://dotnet.microsoft.com/en-us/download/dotnet/6.0) release (6.0.6 and so on), using a Windows x64 installer, is required. The presence of Microsoft .NET Desktop Runtime 7 or later is inconsequential.|
+
+### Example Custom Installers
+
+![Alt text](images/image.png)
+
+### Existing Azure Resources
+
+The following resources must exist in your Azure environment before deployment:
+
+* Virtual Network
+* Storage Account
+ * Private Endpoint
+ * Private DNS Zone
+ * Blob container with executables, scripts, etc. that are required for the imaging deployment
+
+### Disk Encryption Set Requirements
+
+You must enable the feature for your subscription before you use the EncryptionAtHost property for your VM/VMSS. Use the following steps to enable the feature for your subscription.
+
+Execute the following command to register the feature for your subscription
+
+```powershell
+Register-AzProviderFeature -FeatureName "EncryptionAtHost" -ProviderNamespace "Microsoft.Compute"
+
+Get-AzProviderFeature -FeatureName "EncryptionAtHost" -ProviderNamespace "Microsoft.Compute"
+```
+
+* [Use the Azure PowerShell module to enable end-to-end encryption using encryption at host](https://learn.microsoft.com/en-us/azure/virtual-machines/windows/disks-enable-host-based-encryption-powershell)
+
+### Deploy from the Azure Portal
+
+1. Deploy Zero Trust Imaging into `AzureCloud` or `AzureUsGovernment` from the Azure Portal:
+
+ | Azure Commercial | Azure Government |
+ | :--- | :--- |
+ [![Deploy to Azure](https://aka.ms/deploytoazurebutton)](https://portal.azure.com/#blade/Microsoft_Azure_CreateUIDef/CustomDeploymentBlade/uri/https%3A%2F%2Fraw.githubusercontent.com%2FAzure%2Fmissionlz%2Fmain%2Fsrc%2Fbicep%2Fadd-ons%2FZTA%2Fsolution.json/uiFormDefinitionUri/https%3A%2F%2Fraw.githubusercontent.com%2FAzure%2Fmissionlz%2Fmain%2Fsrc%2Fbicep%2Fadd-ons%2FZTA%2FuiDefinition.json) | [![Deploy to Azure Gov](https://aka.ms/deploytoazuregovbutton)](https://portal.azure.us/#blade/Microsoft_Azure_CreateUIDef/CustomDeploymentBlade/uri/https%3A%2F%2Fraw.githubusercontent.com%2FAzure%2Fmissionlz%2Fmain%2Fsrc%2Fbicep%2Fadd-ons%2FZTA%2Fsolution.json/uiFormDefinitionUri/https%3A%2F%2Fraw.githubusercontent.com%2FAzure%2Fmissionlz%2Fmain%2Fsrc%2Fbicep%2Fadd-ons%2FZTA%2FuiDefinition.json) |
+
+
+## Creating Template Spec for AirGapped Clouds
+
+### Example
+
+```powershell
+New-AzTemplateSpec `
+ -Name 'ZeroTrustImaging' `
+ -ResourceGroupName rg-image-usgovvirginia-01 `
+ -Version '1.0' `
+ -Location usgovvirginia `
+ -DisplayName "Zero Trust Image Template" `
+ -TemplateFile '.\solution.json' `
+ -UIFormDefinitionFile '.\uiDefinition.json' `
+ -Force
+```
+
+### Parameters
+
+#### -AdminUsername
+
+Specifies the local administrator user name of the virtual machine that will be captured.
+
+```yaml
+Type: String
+```
+
+#### -ContainerName
+
+Specifies the container name where files, and scripts will be uploaded.
+
+```yaml
+Type: String
+```
+
+#### -GalleryName
+
+Specifies the existing Azure Image Gallery where the image will be created.
+
+```yaml
+Type: String
+```
+
+#### -ImageName
+
+Specifies the name of the image that will created.
+
+```yaml
+Type: String
+```
+
+#### -ImageOffer
+
+Specifies the name of the image offer of the image that will be created.
+
+```yaml
+Type: String
+```
+
+#### -ImagePublisher
+
+Specifies the name of the image publisher of the image that will be created.
+
+```yaml
+Type: String
+```
+
+#### -ImageSku
+
+Specifies the name of the image SKU of the image that will be created.
+
+```yaml
+Type: String
+```
+
+#### -ImageVersion
+
+Specifies the name of the image version of the image that will be created.
+
+```yaml
+Type: String
+```
+
+#### -InstallAccess
+
+Specifies if Access will be installed on the image created.
+
+```yaml
+Type: Boolean
+```
+
+#### -InstallExcel
+
+Specifies if Excel will be installed on the image created.
+
+```yaml
+Type: Boolean
+```
+
+#### -InstallFsLogix
+
+Specifies if FsLogix will be installed on the image created.
+
+```yaml
+Type: Boolean
+```
+
+#### -InstallOneDrive
+
+Specifies if OneDrive For Business will be installed on the image created.
+
+```yaml
+Type: Boolean
+```
+
+#### -InstallOneNote
+
+Specifies if OneNote will be installed on the image created.
+
+```yaml
+Type: Boolean
+```
+
+#### -InstallPowerPoint
+
+Specifies if PowerPoint will be installed on the image created.
+
+```yaml
+Type: Boolean
+```
+
+#### -InstallPublisher
+
+Specifies if Publisher will be installed on the image created.
+
+```yaml
+Type: Boolean
+```
+
+#### -InstallTeams
+
+Specifies if Teams will be installed on the image created.
+
+```yaml
+Type: Boolean
+```
+
+#### -InstallVirtualDesktopOptimizationTool
+
+Specifies if Virtual Desktop Optimization Tool (VDOT) will be installed on the image created.
+
+```yaml
+Type: Boolean
+```
+
+#### -InstallVisio
+
+Specifies if Visio will be installed on the image created.
+
+```yaml
+Type: Boolean
+```
+
+#### -InstallWord
+
+Specifies if Word will be installed on the image created.
+
+```yaml
+Type: Boolean
+```
+
+#### -Location
+
+Specifies a location for the resources of the solution to be deployed.
+
+```yaml
+Type: String
+```
+
+#### -MiName
+
+Specifies the name of an existing managed identity to be used during deployment of the solution.
+
+```yaml
+Type: String
+```
+
+#### -OSVersion
+
+Specifies the OS Version of the image to be captured.
+
+```yaml
+Type: String
+```
+
+#### -ResourceGroupName
+
+Specifies the name of the resource group to create resources.
+
+```yaml
+Type: String
+```
+
+#### -SecurityType
+
+Specifies the security type of the image to be captured.
+
+```yaml
+Type: String
+```
+
+#### -StorageAccountName
+
+Specifies the name of the storage account where assets will be downloaded from and used during the image process.
+
+```yaml
+Type: String
+```
+
+#### -StorageEndpoint
+
+Specifies the storage endpoint of the target storage account.
+
+```yaml
+Type: String
+```
+
+#### -SubnetName
+
+Specifies the subnet of the virtual network to be used during the image process.
+
+```yaml
+Type: String
+```
+
+#### -TenantType
+
+Specifies the tenant type used in the target environment.
+
+```yaml
+Type: String
+AllowedValues: 'Commercial', 'DepartmentOfDefense','GovernmentCommunityCloud','GovernmentCommunityCloudHigh'
+```
+
+#### -UserAssignedIdentityObjectId
+
+Specifies the object ID of the managed identity used during deployment.
+
+```yaml
+Type: String
+```
+
+#### -VirtualNetworkName
+
+Specifies the virtual network name of the vNet used during the image process.
+
+```yaml
+Type: String
+```
+
+#### -VmName
+
+Specifies the name of the virtual machine to be captuired.
+
+```yaml
+Type: String
+```
+
+#### -VmSize
+
+Specifies the size of the the virtual machine to be captuired.
+
+```yaml
+Type: String
+```
+
+### Adding Applications
+
+* Add additional applications by adding addtional blocks of installers in module image.bicep
+* Any blob called will have to be uploaded to the storage account and container that are defined in the parameter set
+* Using the enabled argument will allow the installer to be modular and flexible during image creation
+
+```bicep
+var installers = [
+ {
+ name: 'myapp1'
+ blobName: 'software1.exe'
+ arguments: '/S'
+ enabled: true
+ }
+ {
+ name: 'myapp2'
+ blobName: 'software2.exe'
+ arguments: '/S'
+ enabled: false
+ }
+]
+```
+
+### View Run Command Status
+
+The applications are installed using the Run Command extension on the Azure virtual machine. To the view and troubleshoot the status of a Run Command use the example below:
+
+``` powershell
+PS C:\git\ztaimage> $x = Get-AzVMRunCommand -ResourceGroupName rg-image -VMName vm-image -RunCommandName office -Expand InstanceView
+PS C:\git\ztaimage> $x.InstanceView
+
+
+ExecutionState : Running
+ExecutionMessage :
+ExitCode : 0
+Output :
+Error :
+StartTime : 8/2/2023 2:14:27 PM
+EndTime :
+Statuses :
+```
diff --git a/src/bicep/add-ons/Imaging/images/arcGisProRuntimeExample.png b/src/bicep/add-ons/Imaging/images/arcGisProRuntimeExample.png
new file mode 100644
index 000000000..9b7b07b6d
Binary files /dev/null and b/src/bicep/add-ons/Imaging/images/arcGisProRuntimeExample.png differ
diff --git a/src/bicep/add-ons/Imaging/images/image.png b/src/bicep/add-ons/Imaging/images/image.png
new file mode 100644
index 000000000..9ed7e921a
Binary files /dev/null and b/src/bicep/add-ons/Imaging/images/image.png differ
diff --git a/src/bicep/add-ons/Imaging/modules/automationAccount.bicep b/src/bicep/add-ons/Imaging/modules/automationAccount.bicep
new file mode 100644
index 000000000..0988ce1cb
--- /dev/null
+++ b/src/bicep/add-ons/Imaging/modules/automationAccount.bicep
@@ -0,0 +1,396 @@
+param arcGisProInstaller string
+param actionGroupName string
+param automationAccountName string
+param automationAccountPrivateDnsZoneResourceId string
+param computeGalleryImageResourceId string
+param computeGalleryResourceId string
+param containerName string
+param customizations array
+param deploymentNameSuffix string
+param diskEncryptionSetResourceId string
+param distributionGroup string
+@secure()
+param domainJoinPassword string
+param domainJoinUserPrincipalName string
+param domainName string
+param enableBuildAutomation bool
+param excludeFromLatest bool
+param hybridUseBenefit bool
+param imageDefinitionName string
+param imageMajorVersion int
+param imageMinorVersion int
+param imageVirtualMachineName string
+param installAccess bool
+param installArcGisPro bool
+param installExcel bool
+param installOneDrive bool
+param installOneNote bool
+param installOutlook bool
+param installPowerPoint bool
+param installProject bool
+param installPublisher bool
+param installSkypeForBusiness bool
+param installTeams bool
+param installVirtualDesktopOptimizationTool bool
+param installVisio bool
+param installWord bool
+param keyVaultName string
+param jobScheduleName string = newGuid()
+param location string
+param logAnalyticsWorkspaceResourceId string
+param managementVirtualMachineName string
+param marketplaceImageOffer string
+param marketplaceImagePublisher string
+param marketplaceImageSKU string
+param msrdcwebrtcsvcInstaller string
+param officeInstaller string
+param oUPath string
+param replicaCount int
+param resourceGroupName string
+param sourceImageType string
+param storageAccountResourceId string
+param subnetResourceId string
+param tags object
+param teamsInstaller string
+param templateSpecResourceId string
+param time string = utcNow()
+param timeZone string
+param userAssignedIdentityClientId string
+param userAssignedIdentityPrincipalId string
+param userAssignedIdentityResourceId string
+param vcRedistInstaller string
+param vDOTInstaller string
+param virtualMachineSize string
+
+var parameters = {
+ arcGisProInstaller: arcGisProInstaller
+ computeGalleryResourceId: computeGalleryResourceId
+ containerName: containerName
+ customizations: string(customizations)
+ diskEncryptionSetResourceId: diskEncryptionSetResourceId
+ enableBuildAutomation: string(enableBuildAutomation)
+ environmentName: environment().name
+ excludeFromLatest: excludeFromLatest
+ hybridUseBenefit: hybridUseBenefit
+ imageDefinitionName: imageDefinitionName
+ imageMajorVersion: string(imageMajorVersion)
+ imageMinorVersion: string(imageMinorVersion)
+ imageVirtualMachineName: imageVirtualMachineName
+ installAccess: string(installAccess)
+ installArcGisPro: string(installArcGisPro)
+ installExcel: string(installExcel)
+ InstallOneDrive: string(installOneDrive)
+ installOneNote: string(installOneNote)
+ installOutlook: string(installOutlook)
+ installPowerPoint: string(installPowerPoint)
+ installProject: string(installProject)
+ installPublisher: string(installPublisher)
+ installSkypeForBusiness: string(installSkypeForBusiness)
+ installTeams: string(installTeams)
+ installVirtualDesktopOptimizationTool: string(installVirtualDesktopOptimizationTool)
+ installVisio: string(installVisio)
+ installWord: string(installWord)
+ keyVaultName: keyVaultName
+ location: location
+ managementVirtualMachineName: managementVirtualMachineName
+ marketplaceImageOffer: marketplaceImageOffer
+ marketplaceImagePublisher: marketplaceImagePublisher
+ marketplaceImageSKU: marketplaceImageSKU
+ msrdcwebrtcsvcInstaller: msrdcwebrtcsvcInstaller
+ officeInstaller: officeInstaller
+ replicaCount: string(replicaCount)
+ resourceGroupName: resourceGroupName
+ computeGalleryImageResourceId: computeGalleryImageResourceId
+ sourceImageType: sourceImageType
+ storageAccountResourceId: storageAccountResourceId
+ subnetResourceId: subnetResourceId
+ subscriptionId: subscriptionId
+ tags: string(tags)
+ teamsInstaller: teamsInstaller
+ templateSpecResourceId: templateSpecResourceId
+ tenantId: tenantId
+ userAssignedIdentityClientId: userAssignedIdentityClientId
+ userAssignedIdentityPrincipalId: userAssignedIdentityPrincipalId
+ userAssignedIdentityResourceId: userAssignedIdentityResourceId
+ vcRedistInstaller: vcRedistInstaller
+ vDOTInstaller: vDOTInstaller
+ virtualMachineSize: virtualMachineSize
+}
+var privateEndpointName = 'pe-${automationAccountName}'
+var runbookName = 'New-AzureZeroTrustImageBuild'
+var storageEndpoint = environment().suffixes.storage
+var subscriptionId = subscription().subscriptionId
+var tenantId = subscription().tenantId
+
+resource virtualMachine 'Microsoft.Compute/virtualMachines@2023-07-01' existing = {
+ name: managementVirtualMachineName
+}
+
+resource automationAccount 'Microsoft.Automation/automationAccounts@2022-08-08' = {
+ name: automationAccountName
+ location: location
+ tags: contains(tags, 'Microsoft.Automation/automationAccounts') ? tags['Microsoft.Automation/automationAccounts'] : {}
+ properties: {
+ disableLocalAuth: false
+ publicNetworkAccess: false
+ sku: {
+ name: 'Basic'
+ }
+ encryption: {
+ keySource: 'Microsoft.Automation'
+ identity: {}
+ }
+ }
+}
+
+resource privateEndpoint 'Microsoft.Network/privateEndpoints@2023-05-01' = {
+ name: privateEndpointName
+ location: location
+ tags: contains(tags, 'Microsoft.Network/privateEndpoints') ? tags['Microsoft.Network/privateEndpoints'] : {}
+ properties: {
+ privateLinkServiceConnections: [
+ {
+ name: privateEndpointName
+ id: resourceId('Microsoft.Network/privateEndpoints/privateLinkServiceConnections', privateEndpointName, privateEndpointName)
+ properties: {
+ privateLinkServiceId: automationAccount.id
+ groupIds: [
+ 'DSCAndHybridWorker'
+ ]
+ }
+ }
+ ]
+ customNetworkInterfaceName: 'nic-${automationAccountName}'
+ subnet: {
+ id: subnetResourceId
+ }
+ }
+}
+
+resource privateDnsZoneGroup 'Microsoft.Network/privateEndpoints/privateDnsZoneGroups@2023-05-01' = {
+ parent: privateEndpoint
+ name: 'default'
+ properties: {
+ privateDnsZoneConfigs: [
+ {
+ name: 'privatelink-azure-automation-net'
+ properties: {
+ privateDnsZoneId: automationAccountPrivateDnsZoneResourceId
+ }
+ }
+ ]
+ }
+}
+
+resource runCommand 'Microsoft.Compute/virtualMachines/runCommands@2023-07-01' = {
+ name: 'runbook'
+ location: location
+ tags: contains(tags, 'Microsoft.Compute/virtualMachines') ? tags['Microsoft.Compute/virtualMachines'] : {}
+ parent: virtualMachine
+ properties: {
+ treatFailureAsDeploymentFailure: true
+ asyncExecution: false
+ parameters: [
+ {
+ name: 'AutomationAccountName'
+ value: automationAccountName
+ }
+ {
+ name: 'ContainerName'
+ value: containerName
+ }
+ {
+ name: 'Environment'
+ value: environment().name
+ }
+ {
+ name: 'ResourceGroupName'
+ value: resourceGroup().name
+ }
+ {
+ name: 'RunbookName'
+ value: runbookName
+ }
+ {
+ name: 'StorageAccountName'
+ value: split(storageAccountResourceId, '/')[8]
+ }
+ {
+ name: 'StorageEndpoint'
+ value: storageEndpoint
+ }
+ {
+ name: 'SubscriptionId'
+ value: subscription().subscriptionId
+ }
+ {
+ name: 'TenantId'
+ value: tenant().tenantId
+ }
+ {
+ name: 'UserAssignedIdentityClientId'
+ value: userAssignedIdentityClientId
+ }
+ {
+ name: 'UserAssignedIdentityObjectId'
+ value: userAssignedIdentityPrincipalId
+ }
+ ]
+ source: {
+ script: '''
+ param (
+ [string]$AutomationAccountName,
+ [string]$ContainerName,
+ [string]$Environment,
+ [string]$ResourceGroupName,
+ [string]$RunbookName,
+ [string]$StorageAccountName,
+ [string]$StorageEndpoint,
+ [string]$SubscriptionId,
+ [string]$TenantId,
+ [string]$UserAssignedIdentityClientId,
+ [string]$UserAssignedIdentityObjectId
+ )
+ $ErrorActionPreference = 'Stop'
+ $WarningPreference = 'SilentlyContinue'
+ $BlobName = 'New-AzureZeroTrustImageBuild.ps1'
+ $StorageAccountUrl = "https://" + $StorageAccountName + ".blob." + $StorageEndpoint + "/"
+ $TokenUri = "http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=$StorageAccountUrl&object_id=$UserAssignedIdentityObjectId"
+ $AccessToken = ((Invoke-WebRequest -Headers @{Metadata=$true} -Uri $TokenUri -UseBasicParsing).Content | ConvertFrom-Json).access_token
+ $File = "$env:windir\temp\$BlobName"
+ do
+ {
+ try
+ {
+ Write-Output "Download Attempt $i"
+ Invoke-WebRequest -Headers @{"x-ms-version"="2017-11-09"; Authorization ="Bearer $AccessToken"} -Uri "$StorageAccountUrl$ContainerName/$BlobName" -OutFile $File
+ }
+ catch [System.Net.WebException]
+ {
+ Start-Sleep -Seconds 60
+ $i++
+ if($i -gt 10){throw}
+ continue
+ }
+ catch
+ {
+ $Output = $_ | select *
+ Write-Output $Output
+ throw
+ }
+ }
+ until(Test-Path -Path $File)
+ Connect-AzAccount -Environment $Environment -Tenant $TenantId -Subscription $SubscriptionId -Identity -AccountId $UserAssignedIdentityClientId | Out-Null
+ Import-AzAutomationRunbook -Name $RunbookName -Path $File -Type PowerShell -AutomationAccountName $AutomationAccountName -ResourceGroupName $ResourceGroupName -Published -Force | Out-Null
+ '''
+ }
+ }
+}
+
+resource schedule 'Microsoft.Automation/automationAccounts/schedules@2022-08-08' = {
+ parent: automationAccount
+ name: imageDefinitionName
+ properties: {
+ frequency: 'Day'
+ interval: 1
+ startTime: dateTimeAdd(time, 'P1D')
+ timeZone: timeZone
+ }
+}
+
+resource jobSchedule 'Microsoft.Automation/automationAccounts/jobSchedules@2022-08-08' = {
+ parent: automationAccount
+ #disable-next-line use-stable-resource-identifiers
+ name: jobScheduleName
+ properties: {
+ parameters: {
+ parameters: replace(string(parameters), '"', '\\"')
+ }
+ runbook: {
+ name: runbookName
+ }
+ runOn: hybridRunbookWorkerGroup.name
+ schedule: {
+ name: schedule.name
+ }
+ }
+ dependsOn: [
+ runCommand
+ ]
+}
+
+module monitoring 'monitoring.bicep' = if (!empty(logAnalyticsWorkspaceResourceId) && !empty(distributionGroup) && !empty(actionGroupName)) {
+ name: 'monitoring-${deploymentNameSuffix}'
+ params: {
+ actionGroupName: actionGroupName
+ automationAccountName: automationAccount.name
+ distributionGroup: distributionGroup
+ location: location
+ logAnalyticsWorkspaceResourceId: logAnalyticsWorkspaceResourceId
+ tags: tags
+ }
+}
+
+resource hybridRunbookWorkerGroup 'Microsoft.Automation/automationAccounts/hybridRunbookWorkerGroups@2022-08-08' = {
+ parent: automationAccount
+ name: 'Zero Trust Image Build Automation'
+}
+
+resource hybridRunbookWorker 'Microsoft.Automation/automationAccounts/hybridRunbookWorkerGroups/hybridRunbookWorkers@2022-08-08' = {
+ parent: hybridRunbookWorkerGroup
+ name: guid(hybridRunbookWorkerGroup.id)
+ properties: {
+ vmResourceId: virtualMachine.id
+ }
+ dependsOn: [
+ runCommand
+ ]
+}
+
+resource extension_HybridWorker 'Microsoft.Compute/virtualMachines/extensions@2022-03-01' = {
+ parent: virtualMachine
+ name: 'HybridWorkerForWindows'
+ location: location
+ tags: contains(tags, 'Microsoft.Compute/virtualMachines') ? tags['Microsoft.Compute/virtualMachines'] : {}
+ properties: {
+ publisher: 'Microsoft.Azure.Automation.HybridWorker'
+ type: 'HybridWorkerForWindows'
+ typeHandlerVersion: '1.1'
+ autoUpgradeMinorVersion: true
+ enableAutomaticUpgrade: true
+ settings: {
+ AutomationAccountURL: automationAccount.properties.automationHybridServiceUrl
+ }
+ }
+ dependsOn: [
+ runCommand
+ ]
+}
+
+resource extension_JsonADDomainExtension 'Microsoft.Compute/virtualMachines/extensions@2021-03-01' = if (!empty(domainJoinUserPrincipalName) && !empty(domainName) && !empty(oUPath)) {
+ parent: virtualMachine
+ name: 'JsonADDomainExtension'
+ location: location
+ tags: contains(tags, 'Microsoft.Compute/virtualMachines') ? tags['Microsoft.Compute/virtualMachines'] : {}
+ properties: {
+ forceUpdateTag: time
+ publisher: 'Microsoft.Compute'
+ type: 'JsonADDomainExtension'
+ typeHandlerVersion: '1.3'
+ autoUpgradeMinorVersion: true
+ settings: {
+ Name: domainName
+ User: domainJoinUserPrincipalName
+ Restart: 'true'
+ Options: '3'
+ OUPath: oUPath
+ }
+ protectedSettings: {
+ Password: domainJoinPassword
+ }
+ }
+ dependsOn: [
+ extension_HybridWorker
+ runCommand
+ ]
+}
diff --git a/src/bicep/add-ons/Imaging/modules/baseline.bicep b/src/bicep/add-ons/Imaging/modules/baseline.bicep
new file mode 100644
index 000000000..a497c077b
--- /dev/null
+++ b/src/bicep/add-ons/Imaging/modules/baseline.bicep
@@ -0,0 +1,75 @@
+targetScope = 'subscription'
+
+param computeGalleryName string
+param deploymentNameSuffix string
+param diskEncryptionSetResourceId string
+param enableBuildAutomation bool
+param exemptPolicyAssignmentIds array
+param location string
+param resourceGroupName string
+param storageAccountResourceId string
+param subscriptionId string
+param tags object
+param userAssignedIdentityName string
+
+
+module userAssignedIdentity 'userAssignedIdentity.bicep' = {
+ scope: resourceGroup(subscriptionId, resourceGroupName)
+ name: 'user-assigned-identity-${deploymentNameSuffix}'
+ params: {
+ location: location
+ name: userAssignedIdentityName
+ tags: tags
+ }
+}
+
+module roleAssignments 'roleAssignments.bicep' = {
+ name: 'role-assignment-compute-${deploymentNameSuffix}'
+ scope: resourceGroup(subscriptionId, resourceGroupName)
+ params: {
+ principalId: userAssignedIdentity.outputs.principalId
+ }
+}
+
+module storageAccount 'storageAccount.bicep' = {
+ name: 'role-assignment-storage-${deploymentNameSuffix}'
+ scope: resourceGroup(subscriptionId, split(storageAccountResourceId, '/')[4])
+ params: {
+ principalId: userAssignedIdentity.outputs.principalId
+ storageAccountResourceId: storageAccountResourceId
+ }
+}
+
+module diskEncryptionSet 'diskEncryptionSet.bicep' = {
+ scope: resourceGroup(split(diskEncryptionSetResourceId, '/')[2], split(diskEncryptionSetResourceId, '/')[4])
+ name: 'disk-encryption-set-${deploymentNameSuffix}'
+ params: {
+ diskEncryptionSetName: split(diskEncryptionSetResourceId, '/')[8]
+ principalId: userAssignedIdentity.outputs.principalId
+ }
+}
+
+module computeGallery 'computeGallery.bicep' = {
+ name: 'gallery-image-${deploymentNameSuffix}'
+ scope: resourceGroup(subscriptionId, resourceGroupName)
+ params: {
+ enableBuildAutomation: enableBuildAutomation
+ location: location
+ computeGalleryName: computeGalleryName
+ tags: tags
+ userAssignedIdentityPrincipalId: userAssignedIdentity.outputs.principalId
+ }
+}
+
+module policyExemptions 'exemption.bicep' = [for i in range(0, length(exemptPolicyAssignmentIds)): if (!empty((exemptPolicyAssignmentIds)[0])) {
+ name: 'PolicyExemption_${i}'
+ scope: resourceGroup(subscriptionId, resourceGroupName)
+ params: {
+ policyAssignmentId: exemptPolicyAssignmentIds[i]
+ }
+}]
+
+output computeGalleryResourceId string = computeGallery.outputs.computeGalleryResourceId
+output userAssignedIdentityClientId string = userAssignedIdentity.outputs.clientId
+output userAssignedIdentityPrincipalId string = userAssignedIdentity.outputs.principalId
+output userAssignedIdentityResourceId string = userAssignedIdentity.outputs.resourceId
diff --git a/src/bicep/add-ons/Imaging/modules/baseline.json b/src/bicep/add-ons/Imaging/modules/baseline.json
new file mode 100644
index 000000000..bf11e5f50
--- /dev/null
+++ b/src/bicep/add-ons/Imaging/modules/baseline.json
@@ -0,0 +1,465 @@
+{
+ "$schema": "https://schema.management.azure.com/schemas/2018-05-01/subscriptionDeploymentTemplate.json#",
+ "contentVersion": "1.0.0.0",
+ "metadata": {
+ "_generator": {
+ "name": "bicep",
+ "version": "0.24.24.22086",
+ "templateHash": "3810275683162469600"
+ }
+ },
+ "parameters": {
+ "computeGalleryName": {
+ "type": "string"
+ },
+ "deploymentNameSuffix": {
+ "type": "string"
+ },
+ "diskEncryptionSetResourceId": {
+ "type": "string"
+ },
+ "enableBuildAutomation": {
+ "type": "bool"
+ },
+ "exemptPolicyAssignmentIds": {
+ "type": "array"
+ },
+ "location": {
+ "type": "string"
+ },
+ "resourceGroupName": {
+ "type": "string"
+ },
+ "storageAccountResourceId": {
+ "type": "string"
+ },
+ "subscriptionId": {
+ "type": "string"
+ },
+ "tags": {
+ "type": "object"
+ },
+ "userAssignedIdentityName": {
+ "type": "string"
+ }
+ },
+ "resources": [
+ {
+ "type": "Microsoft.Resources/deployments",
+ "apiVersion": "2022-09-01",
+ "name": "[format('user-assigned-identity-{0}', parameters('deploymentNameSuffix'))]",
+ "subscriptionId": "[parameters('subscriptionId')]",
+ "resourceGroup": "[parameters('resourceGroupName')]",
+ "properties": {
+ "expressionEvaluationOptions": {
+ "scope": "inner"
+ },
+ "mode": "Incremental",
+ "parameters": {
+ "location": {
+ "value": "[parameters('location')]"
+ },
+ "name": {
+ "value": "[parameters('userAssignedIdentityName')]"
+ },
+ "tags": {
+ "value": "[parameters('tags')]"
+ }
+ },
+ "template": {
+ "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
+ "contentVersion": "1.0.0.0",
+ "metadata": {
+ "_generator": {
+ "name": "bicep",
+ "version": "0.24.24.22086",
+ "templateHash": "13213041153837743619"
+ }
+ },
+ "parameters": {
+ "location": {
+ "type": "string"
+ },
+ "name": {
+ "type": "string"
+ },
+ "tags": {
+ "type": "object"
+ }
+ },
+ "resources": [
+ {
+ "type": "Microsoft.ManagedIdentity/userAssignedIdentities",
+ "apiVersion": "2018-11-30",
+ "name": "[parameters('name')]",
+ "location": "[parameters('location')]",
+ "tags": "[if(contains(parameters('tags'), 'Microsoft.ManagedIdentity/userAssignedIdentities'), parameters('tags')['Microsoft.ManagedIdentity/userAssignedIdentities'], createObject())]"
+ }
+ ],
+ "outputs": {
+ "clientId": {
+ "type": "string",
+ "value": "[reference(resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', parameters('name')), '2018-11-30').clientId]"
+ },
+ "principalId": {
+ "type": "string",
+ "value": "[reference(resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', parameters('name')), '2018-11-30').principalId]"
+ },
+ "resourceId": {
+ "type": "string",
+ "value": "[resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', parameters('name'))]"
+ }
+ }
+ }
+ }
+ },
+ {
+ "type": "Microsoft.Resources/deployments",
+ "apiVersion": "2022-09-01",
+ "name": "[format('role-assignment-compute-{0}', parameters('deploymentNameSuffix'))]",
+ "subscriptionId": "[parameters('subscriptionId')]",
+ "resourceGroup": "[parameters('resourceGroupName')]",
+ "properties": {
+ "expressionEvaluationOptions": {
+ "scope": "inner"
+ },
+ "mode": "Incremental",
+ "parameters": {
+ "principalId": {
+ "value": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('subscriptionId'), parameters('resourceGroupName')), 'Microsoft.Resources/deployments', format('user-assigned-identity-{0}', parameters('deploymentNameSuffix'))), '2022-09-01').outputs.principalId.value]"
+ }
+ },
+ "template": {
+ "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
+ "contentVersion": "1.0.0.0",
+ "metadata": {
+ "_generator": {
+ "name": "bicep",
+ "version": "0.24.24.22086",
+ "templateHash": "12486914288824279509"
+ }
+ },
+ "parameters": {
+ "principalId": {
+ "type": "string"
+ }
+ },
+ "variables": {
+ "roleDefinitionIds": [
+ "f353d9bd-d4a6-484e-a77a-8050b599b867",
+ "f1a07417-d97a-45cb-824c-7a7467783830",
+ "acdd72a7-3385-48ef-bd42-f606fba81ae7",
+ "9980e02c-c2be-4d73-94e8-173b1dc7cf3c"
+ ]
+ },
+ "resources": [
+ {
+ "copy": {
+ "name": "roleAssignment",
+ "count": "[length(variables('roleDefinitionIds'))]"
+ },
+ "type": "Microsoft.Authorization/roleAssignments",
+ "apiVersion": "2022-04-01",
+ "name": "[guid(parameters('principalId'), variables('roleDefinitionIds')[copyIndex()], resourceGroup().name)]",
+ "properties": {
+ "roleDefinitionId": "[resourceId('Microsoft.Authorization/roleDefinitions', variables('roleDefinitionIds')[copyIndex()])]",
+ "principalId": "[parameters('principalId')]",
+ "principalType": "ServicePrincipal"
+ }
+ }
+ ]
+ }
+ },
+ "dependsOn": [
+ "[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('subscriptionId'), parameters('resourceGroupName')), 'Microsoft.Resources/deployments', format('user-assigned-identity-{0}', parameters('deploymentNameSuffix')))]"
+ ]
+ },
+ {
+ "type": "Microsoft.Resources/deployments",
+ "apiVersion": "2022-09-01",
+ "name": "[format('role-assignment-storage-{0}', parameters('deploymentNameSuffix'))]",
+ "subscriptionId": "[parameters('subscriptionId')]",
+ "resourceGroup": "[split(parameters('storageAccountResourceId'), '/')[4]]",
+ "properties": {
+ "expressionEvaluationOptions": {
+ "scope": "inner"
+ },
+ "mode": "Incremental",
+ "parameters": {
+ "principalId": {
+ "value": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('subscriptionId'), parameters('resourceGroupName')), 'Microsoft.Resources/deployments', format('user-assigned-identity-{0}', parameters('deploymentNameSuffix'))), '2022-09-01').outputs.principalId.value]"
+ },
+ "storageAccountResourceId": {
+ "value": "[parameters('storageAccountResourceId')]"
+ }
+ },
+ "template": {
+ "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
+ "contentVersion": "1.0.0.0",
+ "metadata": {
+ "_generator": {
+ "name": "bicep",
+ "version": "0.24.24.22086",
+ "templateHash": "1100663954772220507"
+ }
+ },
+ "parameters": {
+ "principalId": {
+ "type": "string"
+ },
+ "storageAccountResourceId": {
+ "type": "string"
+ }
+ },
+ "variables": {
+ "roleDefinitionId": "2a2b9908-6ea1-4ae2-8e65-a410df84e7d1"
+ },
+ "resources": [
+ {
+ "type": "Microsoft.Authorization/roleAssignments",
+ "apiVersion": "2022-04-01",
+ "scope": "[format('Microsoft.Storage/storageAccounts/{0}', split(parameters('storageAccountResourceId'), '/')[8])]",
+ "name": "[guid(parameters('principalId'), variables('roleDefinitionId'), parameters('storageAccountResourceId'))]",
+ "properties": {
+ "roleDefinitionId": "[resourceId('Microsoft.Authorization/roleDefinitions', variables('roleDefinitionId'))]",
+ "principalId": "[parameters('principalId')]",
+ "principalType": "ServicePrincipal"
+ }
+ }
+ ]
+ }
+ },
+ "dependsOn": [
+ "[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('subscriptionId'), parameters('resourceGroupName')), 'Microsoft.Resources/deployments', format('user-assigned-identity-{0}', parameters('deploymentNameSuffix')))]"
+ ]
+ },
+ {
+ "type": "Microsoft.Resources/deployments",
+ "apiVersion": "2022-09-01",
+ "name": "[format('disk-encryption-set-{0}', parameters('deploymentNameSuffix'))]",
+ "subscriptionId": "[split(parameters('diskEncryptionSetResourceId'), '/')[2]]",
+ "resourceGroup": "[split(parameters('diskEncryptionSetResourceId'), '/')[4]]",
+ "properties": {
+ "expressionEvaluationOptions": {
+ "scope": "inner"
+ },
+ "mode": "Incremental",
+ "parameters": {
+ "diskEncryptionSetName": {
+ "value": "[split(parameters('diskEncryptionSetResourceId'), '/')[8]]"
+ },
+ "principalId": {
+ "value": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('subscriptionId'), parameters('resourceGroupName')), 'Microsoft.Resources/deployments', format('user-assigned-identity-{0}', parameters('deploymentNameSuffix'))), '2022-09-01').outputs.principalId.value]"
+ }
+ },
+ "template": {
+ "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
+ "contentVersion": "1.0.0.0",
+ "metadata": {
+ "_generator": {
+ "name": "bicep",
+ "version": "0.24.24.22086",
+ "templateHash": "8640629756451087690"
+ }
+ },
+ "parameters": {
+ "diskEncryptionSetName": {
+ "type": "string"
+ },
+ "principalId": {
+ "type": "string"
+ }
+ },
+ "variables": {
+ "roleDefinitionId": "acdd72a7-3385-48ef-bd42-f606fba81ae7"
+ },
+ "resources": [
+ {
+ "type": "Microsoft.Authorization/roleAssignments",
+ "apiVersion": "2022-04-01",
+ "scope": "[format('Microsoft.Compute/diskEncryptionSets/{0}', parameters('diskEncryptionSetName'))]",
+ "name": "[guid(parameters('principalId'), variables('roleDefinitionId'), resourceId('Microsoft.Compute/diskEncryptionSets', parameters('diskEncryptionSetName')))]",
+ "properties": {
+ "roleDefinitionId": "[resourceId('Microsoft.Authorization/roleDefinitions', variables('roleDefinitionId'))]",
+ "principalId": "[parameters('principalId')]",
+ "principalType": "ServicePrincipal"
+ }
+ }
+ ]
+ }
+ },
+ "dependsOn": [
+ "[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('subscriptionId'), parameters('resourceGroupName')), 'Microsoft.Resources/deployments', format('user-assigned-identity-{0}', parameters('deploymentNameSuffix')))]"
+ ]
+ },
+ {
+ "type": "Microsoft.Resources/deployments",
+ "apiVersion": "2022-09-01",
+ "name": "[format('gallery-image-{0}', parameters('deploymentNameSuffix'))]",
+ "subscriptionId": "[parameters('subscriptionId')]",
+ "resourceGroup": "[parameters('resourceGroupName')]",
+ "properties": {
+ "expressionEvaluationOptions": {
+ "scope": "inner"
+ },
+ "mode": "Incremental",
+ "parameters": {
+ "enableBuildAutomation": {
+ "value": "[parameters('enableBuildAutomation')]"
+ },
+ "location": {
+ "value": "[parameters('location')]"
+ },
+ "computeGalleryName": {
+ "value": "[parameters('computeGalleryName')]"
+ },
+ "tags": {
+ "value": "[parameters('tags')]"
+ },
+ "userAssignedIdentityPrincipalId": {
+ "value": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('subscriptionId'), parameters('resourceGroupName')), 'Microsoft.Resources/deployments', format('user-assigned-identity-{0}', parameters('deploymentNameSuffix'))), '2022-09-01').outputs.principalId.value]"
+ }
+ },
+ "template": {
+ "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
+ "contentVersion": "1.0.0.0",
+ "metadata": {
+ "_generator": {
+ "name": "bicep",
+ "version": "0.24.24.22086",
+ "templateHash": "3726474265381754008"
+ }
+ },
+ "parameters": {
+ "computeGalleryName": {
+ "type": "string"
+ },
+ "enableBuildAutomation": {
+ "type": "bool"
+ },
+ "location": {
+ "type": "string"
+ },
+ "tags": {
+ "type": "object"
+ },
+ "userAssignedIdentityPrincipalId": {
+ "type": "string"
+ }
+ },
+ "variables": {
+ "roleDefinitionId": "b24988ac-6180-42a0-ab88-20f7382dd24c"
+ },
+ "resources": [
+ {
+ "type": "Microsoft.Compute/galleries",
+ "apiVersion": "2022-01-03",
+ "name": "[parameters('computeGalleryName')]",
+ "location": "[parameters('location')]",
+ "tags": "[if(contains(parameters('tags'), 'Microsoft.Compute/galleries'), parameters('tags')['Microsoft.Compute/galleries'], createObject())]"
+ },
+ {
+ "condition": "[parameters('enableBuildAutomation')]",
+ "type": "Microsoft.Authorization/roleAssignments",
+ "apiVersion": "2022-04-01",
+ "scope": "[format('Microsoft.Compute/galleries/{0}', parameters('computeGalleryName'))]",
+ "name": "[guid(parameters('userAssignedIdentityPrincipalId'), variables('roleDefinitionId'), resourceId('Microsoft.Compute/galleries', parameters('computeGalleryName')))]",
+ "properties": {
+ "roleDefinitionId": "[resourceId('Microsoft.Authorization/roleDefinitions', variables('roleDefinitionId'))]",
+ "principalId": "[parameters('userAssignedIdentityPrincipalId')]",
+ "principalType": "ServicePrincipal"
+ },
+ "dependsOn": [
+ "[resourceId('Microsoft.Compute/galleries', parameters('computeGalleryName'))]"
+ ]
+ }
+ ],
+ "outputs": {
+ "computeGalleryResourceId": {
+ "type": "string",
+ "value": "[resourceId('Microsoft.Compute/galleries', parameters('computeGalleryName'))]"
+ }
+ }
+ }
+ },
+ "dependsOn": [
+ "[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('subscriptionId'), parameters('resourceGroupName')), 'Microsoft.Resources/deployments', format('user-assigned-identity-{0}', parameters('deploymentNameSuffix')))]"
+ ]
+ },
+ {
+ "copy": {
+ "name": "policyExemptions",
+ "count": "[length(range(0, length(parameters('exemptPolicyAssignmentIds'))))]"
+ },
+ "condition": "[not(empty(parameters('exemptPolicyAssignmentIds')[0]))]",
+ "type": "Microsoft.Resources/deployments",
+ "apiVersion": "2022-09-01",
+ "name": "[format('PolicyExemption_{0}', range(0, length(parameters('exemptPolicyAssignmentIds')))[copyIndex()])]",
+ "subscriptionId": "[parameters('subscriptionId')]",
+ "resourceGroup": "[parameters('resourceGroupName')]",
+ "properties": {
+ "expressionEvaluationOptions": {
+ "scope": "inner"
+ },
+ "mode": "Incremental",
+ "parameters": {
+ "policyAssignmentId": {
+ "value": "[parameters('exemptPolicyAssignmentIds')[range(0, length(parameters('exemptPolicyAssignmentIds')))[copyIndex()]]]"
+ }
+ },
+ "template": {
+ "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
+ "contentVersion": "1.0.0.0",
+ "metadata": {
+ "_generator": {
+ "name": "bicep",
+ "version": "0.24.24.22086",
+ "templateHash": "6436250754327901801"
+ }
+ },
+ "parameters": {
+ "policyAssignmentId": {
+ "type": "string"
+ }
+ },
+ "resources": [
+ {
+ "type": "Microsoft.Authorization/policyExemptions",
+ "apiVersion": "2022-07-01-preview",
+ "name": "exempt-imaging-resource-group",
+ "properties": {
+ "assignmentScopeValidation": "Default",
+ "description": "Exempts the imaging resource group to prevent issues with building images.",
+ "displayName": "Imaging resource group",
+ "exemptionCategory": "Mitigated",
+ "expiresOn": null,
+ "metadata": null,
+ "policyAssignmentId": "[parameters('policyAssignmentId')]",
+ "policyDefinitionReferenceIds": [],
+ "resourceSelectors": []
+ }
+ }
+ ]
+ }
+ }
+ }
+ ],
+ "outputs": {
+ "computeGalleryResourceId": {
+ "type": "string",
+ "value": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('subscriptionId'), parameters('resourceGroupName')), 'Microsoft.Resources/deployments', format('gallery-image-{0}', parameters('deploymentNameSuffix'))), '2022-09-01').outputs.computeGalleryResourceId.value]"
+ },
+ "userAssignedIdentityClientId": {
+ "type": "string",
+ "value": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('subscriptionId'), parameters('resourceGroupName')), 'Microsoft.Resources/deployments', format('user-assigned-identity-{0}', parameters('deploymentNameSuffix'))), '2022-09-01').outputs.clientId.value]"
+ },
+ "userAssignedIdentityPrincipalId": {
+ "type": "string",
+ "value": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('subscriptionId'), parameters('resourceGroupName')), 'Microsoft.Resources/deployments', format('user-assigned-identity-{0}', parameters('deploymentNameSuffix'))), '2022-09-01').outputs.principalId.value]"
+ },
+ "userAssignedIdentityResourceId": {
+ "type": "string",
+ "value": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('subscriptionId'), parameters('resourceGroupName')), 'Microsoft.Resources/deployments', format('user-assigned-identity-{0}', parameters('deploymentNameSuffix'))), '2022-09-01').outputs.resourceId.value]"
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/bicep/add-ons/Imaging/modules/buildAutomation.bicep b/src/bicep/add-ons/Imaging/modules/buildAutomation.bicep
new file mode 100644
index 000000000..4dc7510b7
--- /dev/null
+++ b/src/bicep/add-ons/Imaging/modules/buildAutomation.bicep
@@ -0,0 +1,208 @@
+targetScope = 'subscription'
+
+param actionGroupName string
+param arcGisProInstaller string
+param automationAccountName string
+param automationAccountPrivateDnsZoneResourceId string
+param computeGalleryResourceId string
+param containerName string
+param customizations array
+param deploymentNameSuffix string
+param diskEncryptionSetResourceId string
+param distributionGroup string
+@secure()
+param domainJoinPassword string
+param domainJoinUserPrincipalName string
+param domainName string
+param enableBuildAutomation bool
+param excludeFromLatest bool
+param hybridUseBenefit bool
+param imageDefinitionName string
+param imageMajorVersion int
+param imageMinorVersion int
+param imageVirtualMachineName string
+param installAccess bool
+param installArcGisPro bool
+param installExcel bool
+param installOneDrive bool
+param installOneNote bool
+param installOutlook bool
+param installPowerPoint bool
+param installProject bool
+param installPublisher bool
+param installSkypeForBusiness bool
+param installTeams bool
+param installVirtualDesktopOptimizationTool bool
+param installVisio bool
+param installWord bool
+param keyVaultName string
+param keyVaultPrivateDnsZoneResourceId string
+@secure()
+param localAdministratorPassword string
+param localAdministratorUsername string
+param location string
+param logAnalyticsWorkspaceResourceId string
+param managementVirtualMachineName string
+param marketplaceImageOffer string
+param marketplaceImagePublisher string
+param marketplaceImageSKU string
+param msrdcwebrtcsvcInstaller string
+param officeInstaller string
+param oUPath string
+param replicaCount int
+param resourceGroupName string
+param computeGalleryImageResourceId string
+param sourceImageType string
+param storageAccountResourceId string
+param subnetResourceId string
+param subscriptionId string
+param tags object
+param teamsInstaller string
+param timeZone string
+param userAssignedIdentityClientId string
+param userAssignedIdentityPrincipalId string
+param userAssignedIdentityResourceId string
+param vcRedistInstaller string
+param vDOTInstaller string
+param virtualMachineSize string
+
+resource roleDefinition 'Microsoft.Authorization/roleDefinitions@2022-04-01' = {
+ name: guid(subscription().id, 'KeyVaultDeployAction')
+ properties: {
+ roleName: 'KeyVaultDeployAction_${subscription().subscriptionId}'
+ description: 'Allows a principal to get but not view Key Vault secrets for ARM template deployments.'
+ assignableScopes: [
+ subscription().id
+ ]
+ permissions: [
+ {
+ actions: [
+ 'Microsoft.KeyVault/vaults/deploy/action'
+ ]
+ }
+ ]
+ }
+}
+
+module virtualNetwork 'virtualNetwork.bicep' = {
+ scope: resourceGroup(split(subnetResourceId, '/')[2], split(subnetResourceId, '/')[4])
+ name: 'virtual-network-${deploymentNameSuffix}'
+ params: {
+ principalId: userAssignedIdentityPrincipalId
+ virtualNetworkName: split(subnetResourceId, '/')[8]
+ }
+}
+
+module keyVault 'keyVault.bicep' = {
+ scope: resourceGroup(subscriptionId, resourceGroupName)
+ name: 'key-vault-${deploymentNameSuffix}'
+ params: {
+ domainJoinPassword: domainJoinPassword
+ domainJoinUserPrincipalName: domainJoinUserPrincipalName
+ keyVaultName: keyVaultName
+ keyVaultPrivateDnsZoneResourceId: keyVaultPrivateDnsZoneResourceId
+ localAdministratorPassword: localAdministratorPassword
+ localAdministratorUsername: localAdministratorUsername
+ location: location
+ roleDefinitionResourceId: roleDefinition.id
+ subnetResourceId: subnetResourceId
+ tags: tags
+ userAssignedIdentityPrincipalId: userAssignedIdentityPrincipalId
+ }
+}
+
+module templateSpec 'templateSpec.bicep' = {
+ scope: resourceGroup(subscriptionId, resourceGroupName)
+ name: 'template-spec-${deploymentNameSuffix}'
+ params: {
+ imageDefinitionName: imageDefinitionName
+ location: location
+ tags: tags
+ }
+}
+
+module managementVM 'managementVM.bicep' = {
+ name: 'management-vm-${deploymentNameSuffix}'
+ scope: resourceGroup(subscriptionId, resourceGroupName)
+ params: {
+ containerName: containerName
+ diskEncryptionSetResourceId: diskEncryptionSetResourceId
+ hybridUseBenefit: hybridUseBenefit
+ localAdministratorPassword: localAdministratorPassword
+ localAdministratorUsername: localAdministratorUsername
+ location: location
+ storageAccountName: split(storageAccountResourceId, '/')[8]
+ subnetResourceId: subnetResourceId
+ tags: tags
+ userAssignedIdentityPrincipalId: userAssignedIdentityPrincipalId
+ userAssignedIdentityResourceId: userAssignedIdentityResourceId
+ virtualMachineName: managementVirtualMachineName
+ }
+}
+
+module automationAccount 'automationAccount.bicep' = {
+ scope: resourceGroup(subscriptionId, resourceGroupName)
+ name: 'automation-account-${deploymentNameSuffix}'
+ params: {
+ arcGisProInstaller: arcGisProInstaller
+ actionGroupName: actionGroupName
+ automationAccountName: automationAccountName
+ automationAccountPrivateDnsZoneResourceId: automationAccountPrivateDnsZoneResourceId
+ computeGalleryImageResourceId: computeGalleryImageResourceId
+ computeGalleryResourceId: computeGalleryResourceId
+ containerName: containerName
+ customizations: customizations
+ deploymentNameSuffix: deploymentNameSuffix
+ diskEncryptionSetResourceId: diskEncryptionSetResourceId
+ distributionGroup: distributionGroup
+ domainJoinPassword: domainJoinPassword
+ domainJoinUserPrincipalName: domainJoinUserPrincipalName
+ domainName: domainName
+ enableBuildAutomation: enableBuildAutomation
+ excludeFromLatest: excludeFromLatest
+ hybridUseBenefit: hybridUseBenefit
+ imageDefinitionName: imageDefinitionName
+ imageMajorVersion: imageMajorVersion
+ imageMinorVersion: imageMinorVersion
+ imageVirtualMachineName: imageVirtualMachineName
+ installAccess: installAccess
+ installArcGisPro: installArcGisPro
+ installExcel: installExcel
+ installOneDrive: installOneDrive
+ installOneNote: installOneNote
+ installOutlook: installOutlook
+ installPowerPoint: installPowerPoint
+ installProject: installProject
+ installPublisher: installPublisher
+ installSkypeForBusiness: installSkypeForBusiness
+ installTeams: installTeams
+ installVirtualDesktopOptimizationTool: installVirtualDesktopOptimizationTool
+ installVisio: installVisio
+ installWord: installWord
+ keyVaultName: keyVaultName
+ location: location
+ logAnalyticsWorkspaceResourceId: logAnalyticsWorkspaceResourceId
+ managementVirtualMachineName: managementVM.outputs.name
+ marketplaceImageOffer: marketplaceImageOffer
+ marketplaceImagePublisher: marketplaceImagePublisher
+ marketplaceImageSKU: marketplaceImageSKU
+ msrdcwebrtcsvcInstaller: msrdcwebrtcsvcInstaller
+ officeInstaller: officeInstaller
+ oUPath: oUPath
+ replicaCount: replicaCount
+ resourceGroupName: resourceGroupName
+ sourceImageType: sourceImageType
+ storageAccountResourceId: storageAccountResourceId
+ subnetResourceId: subnetResourceId
+ tags: tags
+ teamsInstaller: teamsInstaller
+ templateSpecResourceId: templateSpec.outputs.resourceId
+ timeZone: timeZone
+ userAssignedIdentityClientId: userAssignedIdentityClientId
+ userAssignedIdentityPrincipalId: userAssignedIdentityPrincipalId
+ userAssignedIdentityResourceId: userAssignedIdentityResourceId
+ vcRedistInstaller: vcRedistInstaller
+ vDOTInstaller: vDOTInstaller
+ virtualMachineSize: virtualMachineSize
+ }
+}
diff --git a/src/bicep/add-ons/Imaging/modules/computeGallery.bicep b/src/bicep/add-ons/Imaging/modules/computeGallery.bicep
new file mode 100644
index 000000000..892f232df
--- /dev/null
+++ b/src/bicep/add-ons/Imaging/modules/computeGallery.bicep
@@ -0,0 +1,25 @@
+param computeGalleryName string
+param enableBuildAutomation bool
+param location string
+param tags object
+param userAssignedIdentityPrincipalId string
+
+var roleDefinitionId = 'b24988ac-6180-42a0-ab88-20f7382dd24c' // Contributor | https://learn.microsoft.com/en-us/azure/role-based-access-control/built-in-roles#contributor
+
+resource computeGallery 'Microsoft.Compute/galleries@2022-01-03' = {
+ name: computeGalleryName
+ location: location
+ tags: contains(tags, 'Microsoft.Compute/galleries') ? tags['Microsoft.Compute/galleries'] : {}
+}
+
+resource roleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = if (enableBuildAutomation) {
+ scope: computeGallery
+ name: guid(userAssignedIdentityPrincipalId, roleDefinitionId, computeGallery.id)
+ properties: {
+ roleDefinitionId: resourceId('Microsoft.Authorization/roleDefinitions', roleDefinitionId)
+ principalId: userAssignedIdentityPrincipalId
+ principalType: 'ServicePrincipal'
+ }
+}
+
+output computeGalleryResourceId string = computeGallery.id
diff --git a/src/bicep/add-ons/Imaging/modules/customizations.bicep b/src/bicep/add-ons/Imaging/modules/customizations.bicep
new file mode 100644
index 000000000..085d5f2e8
--- /dev/null
+++ b/src/bicep/add-ons/Imaging/modules/customizations.bicep
@@ -0,0 +1,610 @@
+targetScope = 'resourceGroup'
+
+param arcGisProInstaller string
+param containerName string
+param customizations array
+param installAccess bool
+param installArcGisPro bool
+param installExcel bool
+param installOneDrive bool
+param installOneNote bool
+param installOutlook bool
+param installPowerPoint bool
+param installProject bool
+param installPublisher bool
+param installSkypeForBusiness bool
+param installTeams bool
+param installVirtualDesktopOptimizationTool bool
+param installVisio bool
+param installWord bool
+param location string
+param msrdcwebrtcsvcInstaller string
+param officeInstaller string
+param storageAccountName string
+param storageEndpoint string
+param tags object
+param teamsInstaller string
+param userAssignedIdentityObjectId string
+param vcRedistInstaller string
+param vDotInstaller string
+param virtualMachineName string
+
+var installAccessVar = '${installAccess}installAccess'
+var installers = customizations
+var installExcelVar = '${installExcel}installWord'
+var installOneDriveVar = '${installOneDrive}installOneDrive'
+var installOneNoteVar = '${installOneNote}installOneNote'
+var installOutlookVar = '${installOutlook}installOutlook'
+var installPowerPointVar = '${installPowerPoint}installPowerPoint'
+var installProjectVar = '${installProject}installProject'
+var installPublisherVar = '${installPublisher}installPublisher'
+var installSkypeForBusinessVar = '${installSkypeForBusiness}installSkypeForBusiness'
+var installVisioVar = '${installVisio}installVisio'
+var installWordVar = '${installWord}installWord'
+
+resource virtualMachine 'Microsoft.Compute/virtualMachines@2022-11-01' existing = {
+ name: virtualMachineName
+}
+
+@batchSize(1)
+resource applications 'Microsoft.Compute/virtualMachines/runCommands@2023-03-01' = [for installer in installers: {
+ parent: virtualMachine
+ name: 'app-${installer.name}'
+ location: location
+ tags: contains(tags, 'Microsoft.Compute/virtualMachines') ? tags['Microsoft.Compute/virtualMachines'] : {}
+ properties: {
+ treatFailureAsDeploymentFailure: true
+ asyncExecution: false
+ parameters: [
+ {
+ name: 'UserAssignedIdentityObjectId'
+ value: userAssignedIdentityObjectId
+ }
+ {
+ name: 'StorageAccountName'
+ value: storageAccountName
+ }
+ {
+ name: 'ContainerName'
+ value: containerName
+ }
+ {
+ name: 'StorageEndpoint'
+ value: storageEndpoint
+ }
+ {
+ name: 'Blobname'
+ value: installer.blobName
+ }
+ {
+ name: 'Installer'
+ value: installer.name
+ }
+ {
+ name: 'Arguments'
+ value: installer.arguments
+ }
+ ]
+ source: {
+ script: '''
+ param(
+ [string]$UserAssignedIdentityObjectId,
+ [string]$StorageAccountName,
+ [string]$ContainerName,
+ [string]$StorageEndpoint,
+ [string]$BlobName,
+ [string]$Installer,
+ [string]$Arguments
+ )
+ $ErrorActionPreference = 'Stop'
+ $WarningPreference = 'SilentlyContinue'
+ $StorageAccountUrl = "https://" + $StorageAccountName + ".blob." + $StorageEndpoint + "/"
+ $TokenUri = "http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=$StorageAccountUrl&object_id=$UserAssignedIdentityObjectId"
+ $AccessToken = ((Invoke-WebRequest -Headers @{Metadata=$true} -Uri $TokenUri -UseBasicParsing).Content | ConvertFrom-Json).access_token
+ New-Item -Path $env:windir\temp -Name $Installer -ItemType "directory" -Force
+ New-Item -Path $env:windir\temp\$Installer -Name 'Files' -ItemType "directory" -Force
+ Invoke-WebRequest -Headers @{"x-ms-version"="2017-11-09"; Authorization ="Bearer $AccessToken"} -Uri "$StorageAccountUrl$ContainerName/$BlobName" -OutFile $env:windir\temp\$Installer\Files\$Blobname
+ Start-Sleep -Seconds 30
+ Set-Location -Path $env:windir\temp\$Installer
+ if($Blobname -like ("*.exe"))
+ {
+ Start-Process -FilePath $env:windir\temp\$Installer\Files\$Blobname -ArgumentList $Arguments -NoNewWindow -Wait -PassThru
+ $status = Get-WmiObject -Class Win32_Product | Where-Object Name -like "*$($installer)*"
+ if($status)
+ {
+ Write-Host $status.Name "is installed"
+ }
+ else
+ {
+ Write-host $Installer "did not install properly, please check arguments"
+ }
+ }
+ if($Blobname -like ("*.msi"))
+ {
+ Set-Location -Path $env:windir\temp\$Installer\Files
+ Start-Process -FilePath msiexec.exe -ArgumentList $Arguments -Wait
+ $status = Get-WmiObject -Class Win32_Product | Where-Object Name -like "*$($installer)*"
+ if($status)
+ {
+ Write-Host $status.Name "is installed"
+ }
+ else
+ {
+ Write-host $Installer "did not install properly, please check arguments"
+ }
+ }
+ if($Blobname -like ("*.bat"))
+ {
+ Start-Process -FilePath cmd.exe -ArgumentList $env:windir\temp\$Installer\Files\$Arguments -Wait
+ }
+ if($Blobname -like ("*.ps1"))
+ {
+ Start-Process -FilePath PowerShell.exe -ArgumentList $env:windir\temp\$Installer\Files\$Arguments -Wait
+ }
+ if($Blobname -like ("*.zip"))
+ {
+ Set-Location -Path $env:windir\temp\$Installer\Files
+ Expand-Archive -Path $env:windir\temp\$Installer\Files\$Blobname -DestinationPath $env:windir\temp\$Installer\Files -Force
+ Remove-Item -Path .\$Blobname -Force -Recurse
+ }
+ Write-Host "Removing $Installer Files"
+ Remove-item $env:windir\temp\$Installer -Force -Recurse -Confirm:$false
+ '''
+ }
+ }
+}]
+
+resource office 'Microsoft.Compute/virtualMachines/runCommands@2023-03-01' = if (installAccess || installExcel || installOneDrive || installOneNote || installOutlook || installPowerPoint || installPublisher || installSkypeForBusiness || installWord || installVisio || installProject) {
+ parent: virtualMachine
+ name: 'office'
+ location: location
+ tags: contains(tags, 'Microsoft.Compute/virtualMachines') ? tags['Microsoft.Compute/virtualMachines'] : {}
+ properties: {
+ treatFailureAsDeploymentFailure: true
+ asyncExecution: false
+ parameters: [
+ {
+ name: 'InstallAccess'
+ value: installAccessVar
+ }
+ {
+ name: 'InstallWord'
+ value: installWordVar
+ }
+ {
+ name: 'InstallExcel'
+ value: installExcelVar
+ }
+ {
+ name: 'InstallOneDrive'
+ value: installOneDriveVar
+ }
+ {
+ name: 'InstallOneNote'
+ value: installOneNoteVar
+ }
+ {
+ name: 'InstallOutlook'
+ value: installOutlookVar
+ }
+ {
+ name: 'InstallPowerPoint'
+ value: installPowerPointVar
+ }
+ {
+ name: 'InstallProject'
+ value: installProjectVar
+ }
+ {
+ name: 'InstallPublisher'
+ value: installPublisherVar
+ }
+ {
+ name: 'InstallSkypeForBusiness'
+ value: installSkypeForBusinessVar
+ }
+ {
+ name: 'InstallVisio'
+ value: installVisioVar
+ }
+ {
+ name: 'UserAssignedIdentityObjectId'
+ value: userAssignedIdentityObjectId
+ }
+ {
+ name: 'StorageAccountName'
+ value: storageAccountName
+ }
+ {
+ name: 'ContainerName'
+ value: containerName
+ }
+ {
+ name: 'StorageEndpoint'
+ value: storageEndpoint
+ }
+ {
+ name: 'BlobName'
+ value: officeInstaller
+ }
+ ]
+ source: {
+ script: '''
+ param(
+ [string]$InstallAccess,
+ [string]$InstallExcel,
+ [string]$InstallOneDrive,
+ [string]$InstallOutlook,
+ [string]$InstallProject,
+ [string]$InstallPublisher,
+ [string]$InstallSkypeForBusiness,
+ [string]$InstallVisio,
+ [string]$InstallWord,
+ [string]$InstallOneNote,
+ [string]$InstallPowerPoint,
+ [string]$UserAssignedIdentityObjectId,
+ [string]$StorageAccountName,
+ [string]$ContainerName,
+ [string]$StorageEndpoint,
+ [string]$BlobName
+ )
+ $ErrorActionPreference = 'Stop'
+ $WarningPreference = 'SilentlyContinue'
+ $StorageAccountUrl = "https://" + $StorageAccountName + ".blob." + $StorageEndpoint + "/"
+ $TokenUri = "http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=$StorageAccountUrl&object_id=$UserAssignedIdentityObjectId"
+ $AccessToken = ((Invoke-WebRequest -Headers @{Metadata=$true} -Uri $TokenUri -UseBasicParsing).Content | ConvertFrom-Json).access_token
+ New-Item -Path "$env:windir\temp\office" -ItemType "directory" -Force
+ $sku = (Get-ComputerInfo).OsName
+ $o365ConfigHeader = Set-Content "$env:windir\temp\office\office365x64.xml" ''
+ $o365OfficeHeader = Add-Content "$env:windir\temp\office\office365x64.xml" ''
+ if($InstallAccess -notlike '*true*'){
+ Add-Content "$env:windir\temp\office\office365x64.xml" ''
+ }
+ if($InstallExcel -notlike '*true*'){
+ Add-Content "$env:windir\temp\office\office365x64.xml" ''
+ }
+ if($InstallOneDrive -notlike '*true*'){
+ Add-Content "$env:windir\temp\office\office365x64.xml" ''
+ }
+ if($InstallOneNote -notlike '*true*'){
+ Add-Content "$env:windir\temp\office\office365x64.xml" ''
+ }
+ if($InstallOutlook -notlike '*true*'){
+ Add-Content "$env:windir\temp\office\office365x64.xml" ''
+ }
+ if($InstallPowerPoint -notlike '*true*'){
+ Add-Content "$env:windir\temp\office\office365x64.xml" ''
+ }
+ if($InstallPublisher -notlike '*true*'){
+ Add-Content "$env:windir\temp\office\office365x64.xml" ''
+ }
+ if($InstallSkypeForBusiness -notlike '*true*'){
+ Add-Content "$env:windir\temp\office\office365x64.xml" ''
+ }
+ if($InstallWord -notlike '*true*'){
+ Add-Content "$env:windir\temp\office\office365x64.xml" ''
+ }
+ $addOfficefooter = Add-Content "$env:windir\temp\office\office365x64.xml" ''
+ if($InstallProject -like '*true*'){
+ Add-Content "$env:windir\temp\office\office365x64.xml" ''
+ }
+ if($InstallVisio -like '*true*'){
+ Add-Content "$env:windir\temp\office\office365x64.xml" ''
+ }
+ Add-Content "$env:windir\temp\office\office365x64.xml" ''
+ $PerMachineConfiguration = if(($Sku).Contains("multi") -eq "true"){
+ Add-Content "$env:windir\temp\office\office365x64.xml" ''
+ }
+ Add-Content "$env:windir\temp\office\office365x64.xml" ''
+ $Installer = "$env:windir\temp\office\office.exe"
+ #$DownloadLinks = Invoke-WebRequest -Uri "https://www.microsoft.com/en-us/download/confirmation.aspx?id=49117" -UseBasicParsing
+ #$URL = $DownloadLinks.Links.href | Where-Object {$_ -like "https://download.microsoft.com/download/*officedeploymenttool*"} | Select-Object -First 1
+ #Invoke-WebRequest -Uri $URL -OutFile $Installer -UseBasicParsing
+ Invoke-WebRequest -Headers @{"x-ms-version"="2017-11-09"; Authorization ="Bearer $AccessToken"} -Uri "$StorageAccountUrl$ContainerName/$BlobName" -OutFile $Installer
+ Start-Process -FilePath $Installer -ArgumentList "/extract:$env:windir\temp\office /quiet /passive /norestart" -Wait -PassThru | Out-Null
+ Write-Host "Downloaded & extracted the Office 365 Deployment Toolkit"
+ Start-Process -FilePath "$env:windir\temp\office\setup.exe" -ArgumentList "/configure $env:windir\temp\office\office365x64.xml" -Wait -PassThru -ErrorAction "Stop" | Out-Null
+ Write-Host "Installed the selected Office365 applications"
+ Write-Host "Removing Office FIles"
+ Remove-item -Path "$env:windir\temp\office" -Force -Confirm:$false -Recurse
+ '''
+ }
+ }
+ dependsOn: [
+ applications
+ ]
+}
+
+resource vdot 'Microsoft.Compute/virtualMachines/runCommands@2023-03-01' = if (installVirtualDesktopOptimizationTool) {
+ parent: virtualMachine
+ name: 'vdot'
+ location: location
+ tags: contains(tags, 'Microsoft.Compute/virtualMachines') ? tags['Microsoft.Compute/virtualMachines'] : {}
+ properties: {
+ treatFailureAsDeploymentFailure: true
+ asyncExecution: false
+ parameters: [
+ {
+ name: 'UserAssignedIdentityObjectId'
+ value: userAssignedIdentityObjectId
+ }
+ {
+ name: 'StorageAccountName'
+ value: storageAccountName
+ }
+ {
+ name: 'ContainerName'
+ value: containerName
+ }
+ {
+ name: 'StorageEndpoint'
+ value: storageEndpoint
+ }
+ {
+ name: 'BlobName'
+ value: vDotInstaller
+ }
+ ]
+ source: {
+ script: '''
+ param(
+ [string]$UserAssignedIdentityObjectId,
+ [string]$StorageAccountName,
+ [string]$ContainerName,
+ [string]$StorageEndpoint,
+ [string]$BlobName
+ )
+ $ErrorActionPreference = 'Stop'
+ $WarningPreference = 'SilentlyContinue'
+ $StorageAccountUrl = "https://" + $StorageAccountName + ".blob." + $StorageEndpoint + "/"
+ $TokenUri = "http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=$StorageAccountUrl&object_id=$UserAssignedIdentityObjectId"
+ $AccessToken = ((Invoke-WebRequest -Headers @{Metadata=$true} -Uri $TokenUri -UseBasicParsing).Content | ConvertFrom-Json).access_token
+ $ZIP = "$env:windir\temp\VDOT.zip"
+ Invoke-WebRequest -Headers @{"x-ms-version"="2017-11-09"; Authorization ="Bearer $AccessToken"} -Uri "$StorageAccountUrl$ContainerName/$BlobName" -OutFile $ZIP
+ Start-Sleep -Seconds 30
+ Set-Location -Path $env:windir\temp
+ Unblock-File -Path $ZIP
+ Expand-Archive -LiteralPath $ZIP -DestinationPath "$env:windir\temp" -Force
+ $Path = (Get-ChildItem -Path "$env:windir\temp" -Recurse | Where-Object {$_.Name -eq "Windows_VDOT.ps1"}).FullName
+ $Script = Get-Content -Path $Path
+ $ScriptUpdate = $Script.Replace("Set-NetAdapterAdvancedProperty","#Set-NetAdapterAdvancedProperty")
+ $ScriptUpdate | Set-Content -Path $Path
+ & $Path -Optimizations @("AppxPackages","Autologgers","DefaultUserSettings","LGPO";"NetworkOptimizations","ScheduledTasks","Services","WindowsMediaPlayer") -AdvancedOptimizations "All" -AcceptEULA
+ Write-Host "Removing VDOT Files"
+ # Expecting this format for vDot ZIP, update if using a different ZIP format for folder structure
+ Remove-Item -Path $env:windir\temp\Virtual-Desktop-Optimization-Tool-main -Force -Recurse -Confirm:$false
+ '''
+ }
+ timeoutInSeconds: 640
+ }
+ dependsOn: [
+ teams
+ applications
+ office
+ ]
+}
+
+// resource fslogix 'Microsoft.Compute/virtualMachines/runCommands@2023-03-01' = if (installFsLogix) {
+// parent: virtualMachine
+// name: 'fslogix'
+// location: location
+// tags: contains(tags, 'Microsoft.Compute/virtualMachines') ? tags['Microsoft.Compute/virtualMachines'] : {}
+// properties: {
+// treatFailureAsDeploymentFailure: true
+// asyncExecution: false
+// source: {
+// script: '''
+// $ErrorActionPreference = "Stop"
+// $ZIP = "$env:windir\temp\fslogix.zip"
+// Invoke-WebRequest -Uri "https://aka.ms/fslogix_download" -OutFile $ZIP
+// Unblock-File -Path $ZIP
+// Expand-Archive -LiteralPath $ZIP -DestinationPath "$env:windir\temp\fslogix" -Force
+// Write-Host "Downloaded the latest version of FSLogix"
+// $ErrorActionPreference = "Stop"
+// Start-Process -FilePath "$env:windir\temp\fslogix\x64\Release\FSLogixAppsSetup.exe" -ArgumentList "/install /quiet /norestart" -Wait -PassThru | Out-Null
+// Write-Host "Installed the latest version of FSLogix"
+// '''
+// }
+// timeoutInSeconds: 640
+// }
+// dependsOn: [
+// applications
+// teams
+// office
+// ]
+// }
+
+resource teams 'Microsoft.Compute/virtualMachines/runCommands@2023-03-01' = if (installTeams) {
+ parent: virtualMachine
+ name: 'teams'
+ location: location
+ tags: contains(tags, 'Microsoft.Compute/virtualMachines') ? tags['Microsoft.Compute/virtualMachines'] : {}
+ properties: {
+ treatFailureAsDeploymentFailure: true
+ asyncExecution: false
+ parameters: [
+ {
+ name: 'UserAssignedIdentityObjectId'
+ value: userAssignedIdentityObjectId
+ }
+ {
+ name: 'StorageAccountName'
+ value: storageAccountName
+ }
+ {
+ name: 'ContainerName'
+ value: containerName
+ }
+ {
+ name: 'StorageEndpoint'
+ value: storageEndpoint
+ }
+ {
+ name: 'BlobName'
+ value: teamsInstaller
+ }
+ {
+ name: 'BlobName2'
+ value: vcRedistInstaller
+ }
+ {
+ name: 'BlobName3'
+ value: msrdcwebrtcsvcInstaller
+ }
+ ]
+ source: {
+ script: '''
+ param(
+ [string]$UserAssignedIdentityObjectId,
+ [string]$StorageAccountName,
+ [string]$ContainerName,
+ [string]$StorageEndpoint,
+ [string]$BlobName,
+ [string]$BlobName2,
+ [string]$BlobName3
+ )
+ $ErrorActionPreference = 'Stop'
+ $WarningPreference = 'SilentlyContinue'
+ $StorageAccountUrl = "https://" + $StorageAccountName + ".blob." + $StorageEndpoint + "/"
+ $TokenUri = "http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=$StorageAccountUrl&object_id=$UserAssignedIdentityObjectId"
+ $AccessToken = ((Invoke-WebRequest -Headers @{Metadata=$true} -Uri $TokenUri -UseBasicParsing).Content | ConvertFrom-Json).access_token
+ $vcRedistFile = "$env:windir\temp\vc_redist.x64.exe"
+ $webSocketFile = "$env:windir\temp\webSocketSvc.msi"
+ $teamsFile = "$env:windir\temp\teams.msi"
+ Invoke-WebRequest -Headers @{"x-ms-version"="2017-11-09"; Authorization ="Bearer $AccessToken"} -Uri "$StorageAccountUrl$ContainerName/$BlobName" -OutFile $teamsFile
+ Invoke-WebRequest -Headers @{"x-ms-version"="2017-11-09"; Authorization ="Bearer $AccessToken"} -Uri "$StorageAccountUrl$ContainerName/$BlobName2" -OutFile $vcRedistFile
+ Invoke-WebRequest -Headers @{"x-ms-version"="2017-11-09"; Authorization ="Bearer $AccessToken"} -Uri "$StorageAccountUrl$ContainerName/$BlobName3" -OutFile $webSocketFile
+
+ # Enable media optimizations for Team
+ Start-Process "reg" -ArgumentList "add HKLM\SOFTWARE\Microsoft\Teams /v IsWVDEnvironment /t REG_DWORD /d 1 /f" -Wait -PassThru -ErrorAction "Stop"
+ Write-Host "Enabled media optimizations for Teams"
+ # Download & install the latest version of Microsoft Visual C++ Redistributable
+ #$File = "$env:windir\temp\vc_redist.x64.exe"
+ #Invoke-WebRequest -Uri "https://aka.ms/vs/16/release/vc_redist.x64.exe" -OutFile $File
+ Start-Process -FilePath $vcRedistFile -Args "/install /quiet /norestart /log vcdist.log" -Wait -PassThru | Out-Null
+ Write-Host "Installed the latest version of Microsoft Visual C++ Redistributable"
+ # Download & install the Remote Desktop WebRTC Redirector Service
+ #$File = "$env:windir\temp\webSocketSvc.msi"
+ #Invoke-WebRequest -Uri "https://aka.ms/msrdcwebrtcsvc/msi" -OutFile $File
+ Start-Process -FilePath msiexec.exe -Args "/i $webSocketFile /quiet /qn /norestart /passive /log webSocket.log" -Wait -PassThru | Out-Null
+ Write-Host "Installed the Remote Desktop WebRTC Redirector Service"
+ # Install Teams
+ #$File = "$env:windir\temp\teams.msi"
+ #Write-host $($TeamsUrl)
+ #Invoke-WebRequest -Uri "$TeamsUrl" -OutFile $File
+ $sku = (Get-ComputerInfo).OsName
+ $PerMachineConfiguration = if(($Sku).Contains("multi") -eq "true"){"ALLUSER=1"}else{""}
+ Start-Process -FilePath msiexec.exe -Args "/i $teamsFile /quiet /qn /norestart /passive /log teams.log $PerMachineConfiguration ALLUSERS=1" -Wait -PassThru | Out-Null
+ Write-Host "Installed Teams"
+ Write-Host "Removing Teams Files"
+ Remove-Item "$teamsFile" -Force -Confirm:$false
+ Remove-Item "$vcRedistFile" -Force -Confirm:$false
+ Remove-Item "$webSocketFile" -Force -Confirm:$false
+ '''
+ }
+ }
+ dependsOn: [
+ applications
+ office
+ ]
+}
+
+resource argGisPro 'Microsoft.Compute/virtualMachines/runCommands@2023-03-01' = if (installArcGisPro) {
+ parent: virtualMachine
+ name: 'arcGisPro'
+ location: location
+ tags: contains(tags, 'Microsoft.Compute/virtualMachines') ? tags['Microsoft.Compute/virtualMachines'] : {}
+ properties: {
+ treatFailureAsDeploymentFailure: true
+ asyncExecution: false
+ parameters: [
+ {
+ name: 'UserAssignedIdentityObjectId'
+ value: userAssignedIdentityObjectId
+ }
+ {
+ name: 'StorageAccountName'
+ value: storageAccountName
+ }
+ {
+ name: 'ContainerName'
+ value: containerName
+ }
+ {
+ name: 'StorageEndpoint'
+ value: storageEndpoint
+ }
+ {
+ name: 'BlobName'
+ value: arcGisProInstaller
+ }
+ ]
+ source: {
+ script: '''
+ param(
+ [string]$UserAssignedIdentityObjectId,
+ [string]$StorageAccountName,
+ [string]$ContainerName,
+ [string]$StorageEndpoint,
+ [string]$BlobName
+ )
+ $ErrorActionPreference = 'Stop'
+ $WarningPreference = 'SilentlyContinue'
+ $StorageAccountUrl = "https://" + $StorageAccountName + ".blob." + $StorageEndpoint + "/"
+ $TokenUri = "http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=$StorageAccountUrl&object_id=$UserAssignedIdentityObjectId"
+ $AccessToken = ((Invoke-WebRequest -Headers @{Metadata=$true} -Uri $TokenUri -UseBasicParsing).Content | ConvertFrom-Json).access_token
+ # Retrieve Files
+ New-Item -Path $env:windir\temp -Name arcgis -ItemType "directory" -Force
+ $ZIP = "$env:windir\temp\arcgispro.zip"
+ Invoke-WebRequest -Headers @{"x-ms-version"="2017-11-09"; Authorization ="Bearer $AccessToken"} -Uri "$StorageAccountUrl$ContainerName/$BlobName" -OutFile $ZIP
+ Start-Sleep -Seconds 30
+ Set-Location -Path $env:windir\temp
+ Unblock-File -Path $ZIP
+ Expand-Archive -LiteralPath $ZIP -DestinationPath "$env:windir\temp\arcgis" -Force
+
+ # Install Arcgis
+ $arcGisProMsi = (Get-ChildItem "$env:windir\temp\arcgis\" -Recurse | where {$_.Name -eq "ArcGisPro.msi"})
+ $arcGisProMsp = (Get-ChildItem "$env:windir\temp\arcgis" -Recurse | where {$_.Extension -eq ".msp"})
+ $winDesktopRuntime = (Get-ChildItem "$env:windir\temp\arcgis\" -Recurse | where {$_.Name -like "windowsdesktop-runtime-*"})
+
+ # If found Install Windows Desktop Runtime Pre-Req
+ try {
+ if ($winDesktopRuntime ){
+ Start-Process -FilePath "$($winDesktopRuntime.Directory.FullName)\$winDesktopRuntime" -ArgumentList "/install /quiet /norestart" -Wait -NoNewWindow -PassThru
+ }
+ }
+ catch {
+ Write-Output "Please validate all software requirements are included with the ArcGIS Pro Zip"
+ }
+
+ try {
+ # Install ArcGis Pro
+ $arcGisProArguments = "/i $($arcGisProMsi.Directory.FullName)\$arcGisProMsi ALLUSERS=1 ACCEPTEULA=yes ENABLEEUEI=0 SOFTWARE_CLASS=Professional AUTHORIZATION_TYPE=NAMED_USER LOCK_AUTH_SETTINGS=False ArcGIS_Connection=TRUE /qn /norestart"
+ Start-Process "msiexec.exe" -ArgumentList $arcGisProArguments -Wait -NoNewWindow -PassThru
+ }
+ catch {
+ Write-Output "Please validate all software requirements are included with the ArcGIS Pro Zip"
+ }
+
+ try {
+ # If MSP is found, patch ArcGisPro with MSP file
+ if($arcGisProMsp){
+ Start-Process "msiexec.exe" -ArgumentList "/p $($arcGisProMsp.Directory.FullName)\$arcGisProMsp /qn" -Wait -NoNewWindow -PassThru
+ }
+ }
+ catch {
+ Write-Output "Please validate all software requirements are included with the ArcGIS Pro Zip"
+ }
+ Write-Host "Removing ArcGis Files"
+ Remove-Item $ZIP -Force -Confirm:$false -Recurse
+ Remove-item -Path "$env:windir\temp\arcgis" -Force -Confirm:$false -Recurse
+ '''
+ }
+ }
+ dependsOn: [
+ applications
+ office
+ teams
+ vdot
+ ]
+}
diff --git a/src/bicep/add-ons/Imaging/modules/diskEncryptionSet.bicep b/src/bicep/add-ons/Imaging/modules/diskEncryptionSet.bicep
new file mode 100644
index 000000000..c6a7c307d
--- /dev/null
+++ b/src/bicep/add-ons/Imaging/modules/diskEncryptionSet.bicep
@@ -0,0 +1,18 @@
+param diskEncryptionSetName string
+param principalId string
+
+var roleDefinitionId = 'acdd72a7-3385-48ef-bd42-f606fba81ae7' // Reader | https://learn.microsoft.com/en-us/azure/role-based-access-control/built-in-roles#reader
+
+resource diskEncryptionSet 'Microsoft.Compute/diskEncryptionSets@2023-04-02' existing = {
+ name: diskEncryptionSetName
+}
+
+resource roleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
+ scope: diskEncryptionSet
+ name: guid(principalId, roleDefinitionId, diskEncryptionSet.id)
+ properties: {
+ roleDefinitionId: resourceId('Microsoft.Authorization/roleDefinitions', roleDefinitionId)
+ principalId: principalId
+ principalType: 'ServicePrincipal'
+ }
+}
diff --git a/src/bicep/add-ons/Imaging/modules/exemption.bicep b/src/bicep/add-ons/Imaging/modules/exemption.bicep
new file mode 100644
index 000000000..880c11129
--- /dev/null
+++ b/src/bicep/add-ons/Imaging/modules/exemption.bicep
@@ -0,0 +1,16 @@
+param policyAssignmentId string
+
+resource exemption 'Microsoft.Authorization/policyExemptions@2022-07-01-preview' = {
+ name: 'exempt-imaging-resource-group'
+ properties: {
+ assignmentScopeValidation: 'Default'
+ description: 'Exempts the imaging resource group to prevent issues with building images.'
+ displayName: 'Imaging resource group'
+ exemptionCategory: 'Mitigated'
+ expiresOn: null
+ metadata: null
+ policyAssignmentId: policyAssignmentId
+ policyDefinitionReferenceIds: []
+ resourceSelectors: []
+ }
+}
diff --git a/src/bicep/add-ons/Imaging/modules/generalizeVirtualMachine.bicep b/src/bicep/add-ons/Imaging/modules/generalizeVirtualMachine.bicep
new file mode 100644
index 000000000..fe7dc21da
--- /dev/null
+++ b/src/bicep/add-ons/Imaging/modules/generalizeVirtualMachine.bicep
@@ -0,0 +1,74 @@
+param imageVirtualMachineName string
+param resourceGroupName string
+param location string = resourceGroup().location
+param tags object
+param userAssignedIdentityClientId string
+param virtualMachineName string
+
+resource imageVirtualMachine 'Microsoft.Compute/virtualMachines@2022-03-01' existing = {
+ scope: resourceGroup(resourceGroupName)
+ name: imageVirtualMachineName
+}
+
+resource virtualMachine 'Microsoft.Compute/virtualMachines@2022-03-01' existing = {
+ name: virtualMachineName
+}
+
+resource generalizeVirtualMachine 'Microsoft.Compute/virtualMachines/runCommands@2023-03-01' = {
+ parent: virtualMachine
+ name: 'generalizeVirtualMachine'
+ location: location
+ tags: contains(tags, 'Microsoft.Compute/virtualMachines') ? tags['Microsoft.Compute/virtualMachines'] : {}
+ properties: {
+ treatFailureAsDeploymentFailure: true
+ asyncExecution: false
+ parameters: [
+ {
+ name: 'Environment'
+ value: environment().name
+ }
+ {
+ name: 'ResourceGroupName'
+ value: resourceGroupName
+ }
+ {
+ name: 'SubscriptionId'
+ value: subscription().subscriptionId
+ }
+ {
+ name: 'TenantId'
+ value: tenant().tenantId
+ }
+ {
+ name: 'UserAssignedIdentityClientId'
+ value: userAssignedIdentityClientId
+ }
+ {
+ name: 'VirtualMachineName'
+ value: imageVirtualMachine.name
+ }
+ ]
+ source: {
+ script: '''
+ param(
+ [string]$Environment,
+ [string]$ResourceGroupName,
+ [string]$SubscriptionId,
+ [string]$TenantId,
+ [string]$UserAssignedIdentityClientId,
+ [string]$VirtualMachineName
+ )
+ $ErrorActionPreference = 'Stop'
+ Connect-AzAccount -Environment $Environment -Tenant $TenantId -Subscription $SubscriptionId -Identity -AccountId $UserAssignedIdentityClientId | Out-Null
+ $PowerStatus = ''
+ while ($PowerStatus -ne 'VM stopped')
+ {
+ Start-Sleep -Seconds 5
+ $PowerStatus = (Get-AzVM -ResourceGroupName $ResourceGroupName -Name $VirtualMachineName -Status).Statuses[1].DisplayStatus
+ }
+ Set-AzVm -ResourceGroupName $ResourceGroupName -Name $VirtualMachineName -Generalized
+ Start-Sleep -Seconds 30
+ '''
+ }
+ }
+}
diff --git a/src/bicep/add-ons/Imaging/modules/hub-network-peering.bicep b/src/bicep/add-ons/Imaging/modules/hub-network-peering.bicep
new file mode 100644
index 000000000..b8929310b
--- /dev/null
+++ b/src/bicep/add-ons/Imaging/modules/hub-network-peering.bicep
@@ -0,0 +1,20 @@
+/*
+Copyright (c) Microsoft Corporation.
+Licensed under the MIT License.
+*/
+
+targetScope = 'resourceGroup'
+
+param hubResourceGroupName string
+param hubVirtualNetworkName string
+param spokeVirtualNetworkName string
+param spokeVirtualNetworkResourceId string
+
+module hubToSpokeVirtualNetworkPeering '../../../modules/virtual-network-peering.bicep' = {
+ scope: resourceGroup(hubResourceGroupName)
+ name: 'hubToSpokeVirtualNetworkPeering'
+ params: {
+ name: '${hubVirtualNetworkName}/to-${spokeVirtualNetworkName}'
+ remoteVirtualNetworkResourceId: spokeVirtualNetworkResourceId
+ }
+}
diff --git a/src/bicep/add-ons/Imaging/modules/imageBuild.bicep b/src/bicep/add-ons/Imaging/modules/imageBuild.bicep
new file mode 100644
index 000000000..8f961cf00
--- /dev/null
+++ b/src/bicep/add-ons/Imaging/modules/imageBuild.bicep
@@ -0,0 +1,221 @@
+targetScope = 'resourceGroup'
+
+param arcGisProInstaller string = ''
+param computeGalleryImageResourceId string = ''
+param computeGalleryName string
+param containerName string
+param customizations array = []
+param deploymentNameSuffix string = utcNow('yyMMddHHs')
+param diskEncryptionSetResourceId string
+param enableBuildAutomation bool = false
+param excludeFromLatest bool = true
+param hybridUseBenefit bool = false
+param imageDefinitionName string
+param imageMajorVersion int
+param imageMinorVersion int
+param imageVirtualMachineName string
+param installAccess bool = false
+param installArcGisPro bool = false
+param installExcel bool = false
+param installOneDrive bool = false
+param installOneNote bool = false
+param installOutlook bool = false
+param installPowerPoint bool = false
+param installProject bool = false
+param installPublisher bool = false
+param installSkypeForBusiness bool = false
+param installTeams bool = false
+param installVirtualDesktopOptimizationTool bool = false
+param installVisio bool = false
+param installWord bool = false
+param keyVaultName string
+@secure()
+param localAdministratorPassword string = ''
+@secure()
+param localAdministratorUsername string = ''
+param location string = resourceGroup().location
+param managementVirtualMachineName string
+param marketplaceImageOffer string
+param marketplaceImagePublisher string
+param marketplaceImageSKU string
+param msrdcwebrtcsvcInstaller string = ''
+param officeInstaller string = ''
+param replicaCount int = 1
+param runbookExecution bool = false
+param sourceImageType string = 'AzureMarketplace'
+param storageAccountResourceId string
+param subnetResourceId string
+param tags object = {}
+param teamsInstaller string = ''
+param userAssignedIdentityClientId string
+param userAssignedIdentityPrincipalId string
+param userAssignedIdentityResourceId string
+param vcRedistInstaller string = ''
+param vDOTInstaller string = ''
+param virtualMachineSize string
+
+var autoImageVersion = '${imageMajorVersion}.${imageSuffix}.${imageMinorVersion}'
+var imageSuffix = take(deploymentNameSuffix, 9)
+var resourceGroupName = resourceGroup().name
+var storageAccountName = split(storageAccountResourceId, '/')[8]
+var storageEndpoint = environment().suffixes.storage
+var subscriptionId = subscription().subscriptionId
+
+resource keyVault 'Microsoft.KeyVault/vaults@2023-02-01' existing = if (runbookExecution) {
+ name: keyVaultName
+}
+
+module managementVM 'managementVM.bicep' = if (!enableBuildAutomation) {
+ name: 'management-vm-${deploymentNameSuffix}'
+ scope: resourceGroup(subscriptionId, resourceGroupName)
+ params: {
+ containerName: containerName
+ diskEncryptionSetResourceId: diskEncryptionSetResourceId
+ hybridUseBenefit: hybridUseBenefit
+ localAdministratorPassword: localAdministratorPassword
+ localAdministratorUsername: localAdministratorUsername
+ location: location
+ storageAccountName: split(storageAccountResourceId, '/')[8]
+ subnetResourceId: subnetResourceId
+ tags: tags
+ userAssignedIdentityPrincipalId: userAssignedIdentityPrincipalId
+ userAssignedIdentityResourceId: userAssignedIdentityResourceId
+ virtualMachineName: managementVirtualMachineName
+ }
+}
+
+module virtualMachine 'virtualMachine.bicep' = {
+ name: 'image-vm-${deploymentNameSuffix}'
+ params: {
+ // diskEncryptionSetResourceId: diskEncryptionSetResourceId
+ localAdministratorPassword: runbookExecution ? keyVault.getSecret('LocalAdministratorPassword') : localAdministratorPassword
+ localAdministratorUsername: runbookExecution ? keyVault.getSecret('LocalAdministratorUsername') : localAdministratorUsername
+ location: location
+ marketplaceImageOffer: marketplaceImageOffer
+ marketplaceImagePublisher: marketplaceImagePublisher
+ marketplaceImageSKU: marketplaceImageSKU
+ computeGalleryImageResourceId: computeGalleryImageResourceId
+ sourceImageType: sourceImageType
+ subnetResourceId: subnetResourceId
+ tags: tags
+ userAssignedIdentityResourceId: userAssignedIdentityResourceId
+ virtualMachineName: imageVirtualMachineName
+ virtualMachineSize: virtualMachineSize
+ }
+ dependsOn: [
+ ]
+}
+
+module addCustomizations 'customizations.bicep' = {
+ name: 'customizations-${deploymentNameSuffix}'
+ params: {
+ arcGisProInstaller: arcGisProInstaller
+ containerName: containerName
+ customizations: customizations
+ installAccess: installAccess
+ installArcGisPro: installArcGisPro
+ installExcel: installExcel
+ installOneDrive: installOneDrive
+ installOneNote: installOneNote
+ installOutlook: installOutlook
+ installPowerPoint: installPowerPoint
+ installProject: installProject
+ installPublisher: installPublisher
+ installSkypeForBusiness: installSkypeForBusiness
+ installTeams: installTeams
+ installVirtualDesktopOptimizationTool: installVirtualDesktopOptimizationTool
+ installVisio: installVisio
+ installWord: installWord
+ location: location
+ msrdcwebrtcsvcInstaller: msrdcwebrtcsvcInstaller
+ officeInstaller: officeInstaller
+ storageAccountName: storageAccountName
+ storageEndpoint: storageEndpoint
+ tags: tags
+ teamsInstaller: teamsInstaller
+ userAssignedIdentityObjectId: userAssignedIdentityPrincipalId
+ vcRedistInstaller: vcRedistInstaller
+ vDotInstaller: vDOTInstaller
+ virtualMachineName: virtualMachine.outputs.name
+ }
+ dependsOn: [
+ ]
+}
+
+module restartVirtualMachine 'restartVirtualMachine.bicep' = {
+ name: 'restart-vm-${deploymentNameSuffix}'
+ params: {
+ imageVirtualMachineName: virtualMachine.outputs.name
+ resourceGroupName: resourceGroupName
+ location: location
+ tags: tags
+ userAssignedIdentityClientId: userAssignedIdentityClientId
+ virtualMachineName: enableBuildAutomation ? managementVirtualMachineName : managementVM.outputs.name
+ }
+ dependsOn: [
+ addCustomizations
+ ]
+}
+
+module sysprepVirtualMachine 'sysprepVirtualMachine.bicep' = {
+ name: 'sysprep-vm-${deploymentNameSuffix}'
+ params: {
+ location: location
+ tags: tags
+ virtualMachineName: virtualMachine.outputs.name
+ }
+ dependsOn: [
+ restartVirtualMachine
+ ]
+}
+
+module generalizeVirtualMachine 'generalizeVirtualMachine.bicep' = {
+ name: 'generalize-vm-${deploymentNameSuffix}'
+ params: {
+ imageVirtualMachineName: virtualMachine.outputs.name
+ resourceGroupName: resourceGroupName
+ location: location
+ tags: tags
+ userAssignedIdentityClientId: userAssignedIdentityClientId
+ virtualMachineName: enableBuildAutomation ? managementVirtualMachineName : managementVM.outputs.name
+ }
+ dependsOn: [
+ sysprepVirtualMachine
+ ]
+}
+
+module imageVersion 'imageVersion.bicep' = {
+ name: 'image-version-${deploymentNameSuffix}'
+ params: {
+ computeGalleryImageResourceId: computeGalleryImageResourceId
+ computeGalleryName: computeGalleryName
+ //diskEncryptionSetResourceId: diskEncryptionSetResourceId
+ excludeFromLatest: excludeFromLatest
+ imageDefinitionName: imageDefinitionName
+ imageVersionNumber: autoImageVersion
+ imageVirtualMachineResourceId: virtualMachine.outputs.resourceId
+ location: location
+ marketplaceImageOffer: marketplaceImageOffer
+ marketplaceImagePublisher: marketplaceImagePublisher
+ replicaCount: replicaCount
+ tags: tags
+ }
+ dependsOn: [
+ generalizeVirtualMachine
+ ]
+}
+
+module removeVirtualMachine 'removeVirtualMachine.bicep' = {
+ name: 'remove-vm-${deploymentNameSuffix}'
+ params: {
+ enableBuildAutomation: enableBuildAutomation
+ imageVirtualMachineName: virtualMachine.outputs.name
+ location: location
+ tags: tags
+ userAssignedIdentityClientId: userAssignedIdentityClientId
+ virtualMachineName: enableBuildAutomation ? managementVirtualMachineName : managementVM.outputs.name
+ }
+ dependsOn: [
+ imageVersion
+ ]
+}
diff --git a/src/bicep/add-ons/Imaging/modules/imageBuild.json b/src/bicep/add-ons/Imaging/modules/imageBuild.json
new file mode 100644
index 000000000..9b3cefe88
--- /dev/null
+++ b/src/bicep/add-ons/Imaging/modules/imageBuild.json
@@ -0,0 +1,1687 @@
+{
+ "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
+ "contentVersion": "1.0.0.0",
+ "metadata": {
+ "_generator": {
+ "name": "bicep",
+ "version": "0.24.24.22086",
+ "templateHash": "8327836886771636806"
+ }
+ },
+ "parameters": {
+ "arcGisProInstaller": {
+ "type": "string",
+ "defaultValue": ""
+ },
+ "computeGalleryImageResourceId": {
+ "type": "string",
+ "defaultValue": ""
+ },
+ "computeGalleryName": {
+ "type": "string"
+ },
+ "containerName": {
+ "type": "string"
+ },
+ "customizations": {
+ "type": "array",
+ "defaultValue": []
+ },
+ "deploymentNameSuffix": {
+ "type": "string",
+ "defaultValue": "[utcNow('yyMMddHHs')]"
+ },
+ "diskEncryptionSetResourceId": {
+ "type": "string"
+ },
+ "enableBuildAutomation": {
+ "type": "bool",
+ "defaultValue": false
+ },
+ "excludeFromLatest": {
+ "type": "bool",
+ "defaultValue": true
+ },
+ "hybridUseBenefit": {
+ "type": "bool",
+ "defaultValue": false
+ },
+ "imageDefinitionName": {
+ "type": "string"
+ },
+ "imageMajorVersion": {
+ "type": "int"
+ },
+ "imageMinorVersion": {
+ "type": "int"
+ },
+ "imageVirtualMachineName": {
+ "type": "string"
+ },
+ "installAccess": {
+ "type": "bool",
+ "defaultValue": false
+ },
+ "installArcGisPro": {
+ "type": "bool",
+ "defaultValue": false
+ },
+ "installExcel": {
+ "type": "bool",
+ "defaultValue": false
+ },
+ "installOneDrive": {
+ "type": "bool",
+ "defaultValue": false
+ },
+ "installOneNote": {
+ "type": "bool",
+ "defaultValue": false
+ },
+ "installOutlook": {
+ "type": "bool",
+ "defaultValue": false
+ },
+ "installPowerPoint": {
+ "type": "bool",
+ "defaultValue": false
+ },
+ "installProject": {
+ "type": "bool",
+ "defaultValue": false
+ },
+ "installPublisher": {
+ "type": "bool",
+ "defaultValue": false
+ },
+ "installSkypeForBusiness": {
+ "type": "bool",
+ "defaultValue": false
+ },
+ "installTeams": {
+ "type": "bool",
+ "defaultValue": false
+ },
+ "installVirtualDesktopOptimizationTool": {
+ "type": "bool",
+ "defaultValue": false
+ },
+ "installVisio": {
+ "type": "bool",
+ "defaultValue": false
+ },
+ "installWord": {
+ "type": "bool",
+ "defaultValue": false
+ },
+ "keyVaultName": {
+ "type": "string"
+ },
+ "localAdministratorPassword": {
+ "type": "securestring",
+ "defaultValue": ""
+ },
+ "localAdministratorUsername": {
+ "type": "securestring",
+ "defaultValue": ""
+ },
+ "location": {
+ "type": "string",
+ "defaultValue": "[resourceGroup().location]"
+ },
+ "managementVirtualMachineName": {
+ "type": "string"
+ },
+ "marketplaceImageOffer": {
+ "type": "string"
+ },
+ "marketplaceImagePublisher": {
+ "type": "string"
+ },
+ "marketplaceImageSKU": {
+ "type": "string"
+ },
+ "msrdcwebrtcsvcInstaller": {
+ "type": "string",
+ "defaultValue": ""
+ },
+ "officeInstaller": {
+ "type": "string",
+ "defaultValue": ""
+ },
+ "replicaCount": {
+ "type": "int",
+ "defaultValue": 1
+ },
+ "runbookExecution": {
+ "type": "bool",
+ "defaultValue": false
+ },
+ "sourceImageType": {
+ "type": "string",
+ "defaultValue": "AzureMarketplace"
+ },
+ "storageAccountResourceId": {
+ "type": "string"
+ },
+ "subnetResourceId": {
+ "type": "string"
+ },
+ "tags": {
+ "type": "object",
+ "defaultValue": {}
+ },
+ "teamsInstaller": {
+ "type": "string",
+ "defaultValue": ""
+ },
+ "userAssignedIdentityClientId": {
+ "type": "string"
+ },
+ "userAssignedIdentityPrincipalId": {
+ "type": "string"
+ },
+ "userAssignedIdentityResourceId": {
+ "type": "string"
+ },
+ "vcRedistInstaller": {
+ "type": "string",
+ "defaultValue": ""
+ },
+ "vDOTInstaller": {
+ "type": "string",
+ "defaultValue": ""
+ },
+ "virtualMachineSize": {
+ "type": "string"
+ }
+ },
+ "variables": {
+ "autoImageVersion": "[format('{0}.{1}.{2}', parameters('imageMajorVersion'), variables('imageSuffix'), parameters('imageMinorVersion'))]",
+ "imageSuffix": "[take(parameters('deploymentNameSuffix'), 9)]",
+ "resourceGroupName": "[resourceGroup().name]",
+ "storageAccountName": "[split(parameters('storageAccountResourceId'), '/')[8]]",
+ "storageEndpoint": "[environment().suffixes.storage]",
+ "subscriptionId": "[subscription().subscriptionId]"
+ },
+ "resources": [
+ {
+ "condition": "[not(parameters('enableBuildAutomation'))]",
+ "type": "Microsoft.Resources/deployments",
+ "apiVersion": "2022-09-01",
+ "name": "[format('management-vm-{0}', parameters('deploymentNameSuffix'))]",
+ "subscriptionId": "[variables('subscriptionId')]",
+ "resourceGroup": "[variables('resourceGroupName')]",
+ "properties": {
+ "expressionEvaluationOptions": {
+ "scope": "inner"
+ },
+ "mode": "Incremental",
+ "parameters": {
+ "containerName": {
+ "value": "[parameters('containerName')]"
+ },
+ "diskEncryptionSetResourceId": {
+ "value": "[parameters('diskEncryptionSetResourceId')]"
+ },
+ "hybridUseBenefit": {
+ "value": "[parameters('hybridUseBenefit')]"
+ },
+ "localAdministratorPassword": {
+ "value": "[parameters('localAdministratorPassword')]"
+ },
+ "localAdministratorUsername": {
+ "value": "[parameters('localAdministratorUsername')]"
+ },
+ "location": {
+ "value": "[parameters('location')]"
+ },
+ "storageAccountName": {
+ "value": "[split(parameters('storageAccountResourceId'), '/')[8]]"
+ },
+ "subnetResourceId": {
+ "value": "[parameters('subnetResourceId')]"
+ },
+ "tags": {
+ "value": "[parameters('tags')]"
+ },
+ "userAssignedIdentityPrincipalId": {
+ "value": "[parameters('userAssignedIdentityPrincipalId')]"
+ },
+ "userAssignedIdentityResourceId": {
+ "value": "[parameters('userAssignedIdentityResourceId')]"
+ },
+ "virtualMachineName": {
+ "value": "[parameters('managementVirtualMachineName')]"
+ }
+ },
+ "template": {
+ "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
+ "contentVersion": "1.0.0.0",
+ "metadata": {
+ "_generator": {
+ "name": "bicep",
+ "version": "0.24.24.22086",
+ "templateHash": "5351463014152522794"
+ }
+ },
+ "parameters": {
+ "containerName": {
+ "type": "string"
+ },
+ "diskEncryptionSetResourceId": {
+ "type": "string"
+ },
+ "hybridUseBenefit": {
+ "type": "bool"
+ },
+ "localAdministratorPassword": {
+ "type": "securestring"
+ },
+ "localAdministratorUsername": {
+ "type": "securestring"
+ },
+ "location": {
+ "type": "string"
+ },
+ "storageAccountName": {
+ "type": "string"
+ },
+ "subnetResourceId": {
+ "type": "string"
+ },
+ "tags": {
+ "type": "object"
+ },
+ "userAssignedIdentityPrincipalId": {
+ "type": "string"
+ },
+ "userAssignedIdentityResourceId": {
+ "type": "string"
+ },
+ "virtualMachineName": {
+ "type": "string"
+ }
+ },
+ "resources": [
+ {
+ "type": "Microsoft.Network/networkInterfaces",
+ "apiVersion": "2023-04-01",
+ "name": "[format('nic-{0}', parameters('virtualMachineName'))]",
+ "location": "[parameters('location')]",
+ "tags": "[if(contains(parameters('tags'), 'Microsoft.Network/networkInterfaces'), parameters('tags')['Microsoft.Network/networkInterfaces'], createObject())]",
+ "properties": {
+ "ipConfigurations": [
+ {
+ "name": "ipconfig",
+ "properties": {
+ "privateIPAllocationMethod": "Dynamic",
+ "subnet": {
+ "id": "[parameters('subnetResourceId')]"
+ },
+ "primary": true,
+ "privateIPAddressVersion": "IPv4"
+ }
+ }
+ ],
+ "enableAcceleratedNetworking": true,
+ "enableIPForwarding": false
+ }
+ },
+ {
+ "type": "Microsoft.Compute/virtualMachines",
+ "apiVersion": "2022-03-01",
+ "name": "[parameters('virtualMachineName')]",
+ "location": "[parameters('location')]",
+ "tags": "[if(contains(parameters('tags'), 'Microsoft.Compute/virtualMachines'), parameters('tags')['Microsoft.Compute/virtualMachines'], createObject())]",
+ "identity": {
+ "type": "UserAssigned",
+ "userAssignedIdentities": {
+ "[format('{0}', parameters('userAssignedIdentityResourceId'))]": {}
+ }
+ },
+ "properties": {
+ "hardwareProfile": {
+ "vmSize": "Standard_D2s_v3"
+ },
+ "osProfile": {
+ "computerName": "[parameters('virtualMachineName')]",
+ "adminUsername": "[parameters('localAdministratorUsername')]",
+ "adminPassword": "[parameters('localAdministratorPassword')]",
+ "windowsConfiguration": {
+ "provisionVMAgent": true,
+ "enableAutomaticUpdates": true,
+ "patchSettings": {
+ "patchMode": "AutomaticByOS",
+ "assessmentMode": "ImageDefault"
+ }
+ }
+ },
+ "storageProfile": {
+ "imageReference": {
+ "publisher": "MicrosoftWindowsServer",
+ "offer": "WindowsServer",
+ "sku": "2019-datacenter-core-g2",
+ "version": "latest"
+ },
+ "osDisk": {
+ "caching": "ReadWrite",
+ "createOption": "FromImage",
+ "deleteOption": "Delete",
+ "managedDisk": {
+ "diskEncryptionSet": {
+ "id": "[parameters('diskEncryptionSetResourceId')]"
+ },
+ "storageAccountType": "Premium_LRS"
+ },
+ "name": "[format('disk-{0}', parameters('virtualMachineName'))]",
+ "osType": "Windows"
+ }
+ },
+ "networkProfile": {
+ "networkInterfaces": [
+ {
+ "id": "[resourceId('Microsoft.Network/networkInterfaces', format('nic-{0}', parameters('virtualMachineName')))]",
+ "properties": {
+ "deleteOption": "Delete"
+ }
+ }
+ ]
+ },
+ "diagnosticsProfile": {
+ "bootDiagnostics": {
+ "enabled": false
+ }
+ },
+ "securityProfile": {
+ "encryptionAtHost": true,
+ "uefiSettings": {
+ "secureBootEnabled": true,
+ "vTpmEnabled": true
+ },
+ "securityType": "TrustedLaunch"
+ },
+ "licenseType": "[if(parameters('hybridUseBenefit'), 'Windows_Server', null())]"
+ },
+ "dependsOn": [
+ "[resourceId('Microsoft.Network/networkInterfaces', format('nic-{0}', parameters('virtualMachineName')))]"
+ ]
+ },
+ {
+ "type": "Microsoft.Compute/virtualMachines/runCommands",
+ "apiVersion": "2023-03-01",
+ "name": "[format('{0}/{1}', parameters('virtualMachineName'), 'appAzModules')]",
+ "location": "[parameters('location')]",
+ "tags": "[if(contains(parameters('tags'), 'Microsoft.Compute/virtualMachines'), parameters('tags')['Microsoft.Compute/virtualMachines'], createObject())]",
+ "properties": {
+ "treatFailureAsDeploymentFailure": true,
+ "asyncExecution": false,
+ "parameters": [
+ {
+ "name": "ContainerName",
+ "value": "[parameters('containerName')]"
+ },
+ {
+ "name": "StorageAccountName",
+ "value": "[parameters('storageAccountName')]"
+ },
+ {
+ "name": "StorageEndpoint",
+ "value": "[environment().suffixes.storage]"
+ },
+ {
+ "name": "UserAssignedIdentityObjectId",
+ "value": "[parameters('userAssignedIdentityPrincipalId')]"
+ }
+ ],
+ "source": {
+ "script": " param(\r\n [string]$ContainerName,\r\n [string]$StorageAccountName,\r\n [string]$StorageEndpoint,\r\n [string]$UserAssignedIdentityObjectId\r\n )\r\n $ErrorActionPreference = \"Stop\"\r\n $StorageAccountUrl = \"https://\" + $StorageAccountName + \".blob.\" + $StorageEndpoint + \"/\"\r\n $TokenUri = \"http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=$StorageAccountUrl&object_id=$UserAssignedIdentityObjectId\"\r\n $AccessToken = ((Invoke-WebRequest -Headers @{Metadata=$true} -Uri $TokenUri -UseBasicParsing).Content | ConvertFrom-Json).access_token\r\n $BlobNames = @('az.accounts.2.12.1.nupkg','az.automation.1.9.0.nupkg','az.compute.5.7.0.nupkg','az.resources.6.6.0.nupkg')\r\n foreach($BlobName in $BlobNames)\r\n {\r\n do\r\n {\r\n try\r\n {\r\n Write-Output \"Download Attempt $i\"\r\n Invoke-WebRequest -Headers @{\"x-ms-version\"=\"2017-11-09\"; Authorization =\"Bearer $AccessToken\"} -Uri \"$StorageAccountUrl$ContainerName/$BlobName\" -OutFile \"$env:windir\\temp\\$BlobName\"\r\n }\r\n catch [System.Net.WebException]\r\n {\r\n Start-Sleep -Seconds 60\r\n $i++\r\n if($i -gt 10){throw}\r\n continue\r\n }\r\n catch\r\n {\r\n $Output = $_ | select *\r\n Write-Output $Output\r\n throw\r\n }\r\n }\r\n until(Test-Path -Path $env:windir\\temp\\$BlobName)\r\n Start-Sleep -Seconds 5\r\n Unblock-File -Path $env:windir\\temp\\$BlobName\r\n $BlobZipName = $Blobname.Replace('nupkg','zip')\r\n Rename-Item -Path $env:windir\\temp\\$BlobName -NewName $BlobZipName\r\n $BlobNameArray = $BlobName.Split('.')\r\n $ModuleFolderName = $BlobNameArray[0] + '.' + $BlobNameArray[1]\r\n $VersionFolderName = $BlobNameArray[2] + '.' + $BlobNameArray[3]+ '.' + $BlobNameArray[4]\r\n $ModulesDirectory = \"C:\\Program Files\\WindowsPowerShell\\Modules\"\r\n New-Item -Path $ModulesDirectory -Name $ModuleFolderName -ItemType \"Directory\" -Force\r\n Expand-Archive -Path $env:windir\\temp\\$BlobZipName -DestinationPath \"$ModulesDirectory\\$ModuleFolderName\\$VersionFolderName\" -Force\r\n Remove-Item -Path \"$ModulesDirectory\\$ModuleFolderName\\$VersionFolderName\\_rels\" -Force -Recurse\r\n Remove-Item -Path \"$ModulesDirectory\\$ModuleFolderName\\$VersionFolderName\\package\" -Force -Recurse\r\n Remove-Item -LiteralPath \"$ModulesDirectory\\$ModuleFolderName\\$VersionFolderName\\[Content_Types].xml\" -Force\r\n Remove-Item -Path \"$ModulesDirectory\\$ModuleFolderName\\$VersionFolderName\\$ModuleFolderName.nuspec\" -Force\r\n }\r\n Remove-Item -Path \"$env:windir\\temp\\az*\" -Force\r\n "
+ }
+ },
+ "dependsOn": [
+ "[resourceId('Microsoft.Compute/virtualMachines', parameters('virtualMachineName'))]"
+ ]
+ }
+ ],
+ "outputs": {
+ "name": {
+ "type": "string",
+ "value": "[parameters('virtualMachineName')]"
+ }
+ }
+ }
+ }
+ },
+ {
+ "type": "Microsoft.Resources/deployments",
+ "apiVersion": "2022-09-01",
+ "name": "[format('image-vm-{0}', parameters('deploymentNameSuffix'))]",
+ "properties": {
+ "expressionEvaluationOptions": {
+ "scope": "inner"
+ },
+ "mode": "Incremental",
+ "parameters": {
+ "localAdministratorPassword": "[if(parameters('runbookExecution'), createObject('reference', createObject('keyVault', createObject('id', resourceId('Microsoft.KeyVault/vaults', parameters('keyVaultName'))), 'secretName', 'LocalAdministratorPassword')), createObject('value', parameters('localAdministratorPassword')))]",
+ "localAdministratorUsername": "[if(parameters('runbookExecution'), createObject('reference', createObject('keyVault', createObject('id', resourceId('Microsoft.KeyVault/vaults', parameters('keyVaultName'))), 'secretName', 'LocalAdministratorUsername')), createObject('value', parameters('localAdministratorUsername')))]",
+ "location": {
+ "value": "[parameters('location')]"
+ },
+ "marketplaceImageOffer": {
+ "value": "[parameters('marketplaceImageOffer')]"
+ },
+ "marketplaceImagePublisher": {
+ "value": "[parameters('marketplaceImagePublisher')]"
+ },
+ "marketplaceImageSKU": {
+ "value": "[parameters('marketplaceImageSKU')]"
+ },
+ "computeGalleryImageResourceId": {
+ "value": "[parameters('computeGalleryImageResourceId')]"
+ },
+ "sourceImageType": {
+ "value": "[parameters('sourceImageType')]"
+ },
+ "subnetResourceId": {
+ "value": "[parameters('subnetResourceId')]"
+ },
+ "tags": {
+ "value": "[parameters('tags')]"
+ },
+ "userAssignedIdentityResourceId": {
+ "value": "[parameters('userAssignedIdentityResourceId')]"
+ },
+ "virtualMachineName": {
+ "value": "[parameters('imageVirtualMachineName')]"
+ },
+ "virtualMachineSize": {
+ "value": "[parameters('virtualMachineSize')]"
+ }
+ },
+ "template": {
+ "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
+ "contentVersion": "1.0.0.0",
+ "metadata": {
+ "_generator": {
+ "name": "bicep",
+ "version": "0.24.24.22086",
+ "templateHash": "797614681408504492"
+ }
+ },
+ "parameters": {
+ "localAdministratorPassword": {
+ "type": "securestring"
+ },
+ "localAdministratorUsername": {
+ "type": "securestring"
+ },
+ "location": {
+ "type": "string"
+ },
+ "marketplaceImageOffer": {
+ "type": "string"
+ },
+ "marketplaceImagePublisher": {
+ "type": "string"
+ },
+ "marketplaceImageSKU": {
+ "type": "string"
+ },
+ "computeGalleryImageResourceId": {
+ "type": "string"
+ },
+ "sourceImageType": {
+ "type": "string"
+ },
+ "subnetResourceId": {
+ "type": "string"
+ },
+ "tags": {
+ "type": "object"
+ },
+ "userAssignedIdentityResourceId": {
+ "type": "string"
+ },
+ "virtualMachineName": {
+ "type": "string"
+ },
+ "virtualMachineSize": {
+ "type": "string"
+ }
+ },
+ "variables": {
+ "imageReference": "[if(equals(parameters('sourceImageType'), 'AzureComputeGallery'), createObject('id', parameters('computeGalleryImageResourceId')), createObject('publisher', parameters('marketplaceImagePublisher'), 'offer', parameters('marketplaceImageOffer'), 'sku', parameters('marketplaceImageSKU'), 'version', 'latest'))]"
+ },
+ "resources": [
+ {
+ "type": "Microsoft.Network/networkInterfaces",
+ "apiVersion": "2022-05-01",
+ "name": "[format('nic-{0}', parameters('virtualMachineName'))]",
+ "location": "[parameters('location')]",
+ "tags": "[if(contains(parameters('tags'), 'Microsoft.Network/networkInterfaces'), parameters('tags')['Microsoft.Network/networkInterfaces'], createObject())]",
+ "properties": {
+ "ipConfigurations": [
+ {
+ "name": "ipconfig1",
+ "properties": {
+ "privateIPAllocationMethod": "Dynamic",
+ "subnet": {
+ "id": "[parameters('subnetResourceId')]"
+ }
+ }
+ }
+ ]
+ }
+ },
+ {
+ "type": "Microsoft.Compute/virtualMachines",
+ "apiVersion": "2022-03-01",
+ "name": "[parameters('virtualMachineName')]",
+ "location": "[parameters('location')]",
+ "tags": "[if(contains(parameters('tags'), 'Microsoft.Compute/virtualMachines'), parameters('tags')['Microsoft.Compute/virtualMachines'], createObject())]",
+ "identity": {
+ "type": "UserAssigned",
+ "userAssignedIdentities": {
+ "[format('{0}', parameters('userAssignedIdentityResourceId'))]": {}
+ }
+ },
+ "properties": {
+ "hardwareProfile": {
+ "vmSize": "[parameters('virtualMachineSize')]"
+ },
+ "osProfile": {
+ "computerName": "[parameters('virtualMachineName')]",
+ "adminUsername": "[parameters('localAdministratorUsername')]",
+ "adminPassword": "[parameters('localAdministratorPassword')]"
+ },
+ "storageProfile": {
+ "imageReference": "[variables('imageReference')]",
+ "osDisk": {
+ "createOption": "FromImage",
+ "deleteOption": "Delete",
+ "managedDisk": {
+ "storageAccountType": "StandardSSD_LRS"
+ },
+ "name": "[format('disk-{0}', parameters('virtualMachineName'))]"
+ }
+ },
+ "networkProfile": {
+ "networkInterfaces": [
+ {
+ "id": "[resourceId('Microsoft.Network/networkInterfaces', format('nic-{0}', parameters('virtualMachineName')))]",
+ "properties": {
+ "deleteOption": "Delete"
+ }
+ }
+ ]
+ },
+ "diagnosticsProfile": {
+ "bootDiagnostics": {
+ "enabled": false
+ }
+ },
+ "securityProfile": {
+ "uefiSettings": {
+ "secureBootEnabled": true,
+ "vTpmEnabled": true
+ },
+ "securityType": "TrustedLaunch"
+ }
+ },
+ "dependsOn": [
+ "[resourceId('Microsoft.Network/networkInterfaces', format('nic-{0}', parameters('virtualMachineName')))]"
+ ]
+ }
+ ],
+ "outputs": {
+ "name": {
+ "type": "string",
+ "value": "[parameters('virtualMachineName')]"
+ },
+ "resourceId": {
+ "type": "string",
+ "value": "[resourceId('Microsoft.Compute/virtualMachines', parameters('virtualMachineName'))]"
+ }
+ }
+ }
+ }
+ },
+ {
+ "type": "Microsoft.Resources/deployments",
+ "apiVersion": "2022-09-01",
+ "name": "[format('customizations-{0}', parameters('deploymentNameSuffix'))]",
+ "properties": {
+ "expressionEvaluationOptions": {
+ "scope": "inner"
+ },
+ "mode": "Incremental",
+ "parameters": {
+ "arcGisProInstaller": {
+ "value": "[parameters('arcGisProInstaller')]"
+ },
+ "containerName": {
+ "value": "[parameters('containerName')]"
+ },
+ "customizations": {
+ "value": "[parameters('customizations')]"
+ },
+ "installAccess": {
+ "value": "[parameters('installAccess')]"
+ },
+ "installArcGisPro": {
+ "value": "[parameters('installArcGisPro')]"
+ },
+ "installExcel": {
+ "value": "[parameters('installExcel')]"
+ },
+ "installOneDrive": {
+ "value": "[parameters('installOneDrive')]"
+ },
+ "installOneNote": {
+ "value": "[parameters('installOneNote')]"
+ },
+ "installOutlook": {
+ "value": "[parameters('installOutlook')]"
+ },
+ "installPowerPoint": {
+ "value": "[parameters('installPowerPoint')]"
+ },
+ "installProject": {
+ "value": "[parameters('installProject')]"
+ },
+ "installPublisher": {
+ "value": "[parameters('installPublisher')]"
+ },
+ "installSkypeForBusiness": {
+ "value": "[parameters('installSkypeForBusiness')]"
+ },
+ "installTeams": {
+ "value": "[parameters('installTeams')]"
+ },
+ "installVirtualDesktopOptimizationTool": {
+ "value": "[parameters('installVirtualDesktopOptimizationTool')]"
+ },
+ "installVisio": {
+ "value": "[parameters('installVisio')]"
+ },
+ "installWord": {
+ "value": "[parameters('installWord')]"
+ },
+ "location": {
+ "value": "[parameters('location')]"
+ },
+ "msrdcwebrtcsvcInstaller": {
+ "value": "[parameters('msrdcwebrtcsvcInstaller')]"
+ },
+ "officeInstaller": {
+ "value": "[parameters('officeInstaller')]"
+ },
+ "storageAccountName": {
+ "value": "[variables('storageAccountName')]"
+ },
+ "storageEndpoint": {
+ "value": "[variables('storageEndpoint')]"
+ },
+ "tags": {
+ "value": "[parameters('tags')]"
+ },
+ "teamsInstaller": {
+ "value": "[parameters('teamsInstaller')]"
+ },
+ "userAssignedIdentityObjectId": {
+ "value": "[parameters('userAssignedIdentityPrincipalId')]"
+ },
+ "vcRedistInstaller": {
+ "value": "[parameters('vcRedistInstaller')]"
+ },
+ "vDotInstaller": {
+ "value": "[parameters('vDOTInstaller')]"
+ },
+ "virtualMachineName": {
+ "value": "[reference(resourceId('Microsoft.Resources/deployments', format('image-vm-{0}', parameters('deploymentNameSuffix'))), '2022-09-01').outputs.name.value]"
+ }
+ },
+ "template": {
+ "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
+ "contentVersion": "1.0.0.0",
+ "metadata": {
+ "_generator": {
+ "name": "bicep",
+ "version": "0.24.24.22086",
+ "templateHash": "12702244124956355874"
+ }
+ },
+ "parameters": {
+ "arcGisProInstaller": {
+ "type": "string"
+ },
+ "containerName": {
+ "type": "string"
+ },
+ "customizations": {
+ "type": "array"
+ },
+ "installAccess": {
+ "type": "bool"
+ },
+ "installArcGisPro": {
+ "type": "bool"
+ },
+ "installExcel": {
+ "type": "bool"
+ },
+ "installOneDrive": {
+ "type": "bool"
+ },
+ "installOneNote": {
+ "type": "bool"
+ },
+ "installOutlook": {
+ "type": "bool"
+ },
+ "installPowerPoint": {
+ "type": "bool"
+ },
+ "installProject": {
+ "type": "bool"
+ },
+ "installPublisher": {
+ "type": "bool"
+ },
+ "installSkypeForBusiness": {
+ "type": "bool"
+ },
+ "installTeams": {
+ "type": "bool"
+ },
+ "installVirtualDesktopOptimizationTool": {
+ "type": "bool"
+ },
+ "installVisio": {
+ "type": "bool"
+ },
+ "installWord": {
+ "type": "bool"
+ },
+ "location": {
+ "type": "string"
+ },
+ "msrdcwebrtcsvcInstaller": {
+ "type": "string"
+ },
+ "officeInstaller": {
+ "type": "string"
+ },
+ "storageAccountName": {
+ "type": "string"
+ },
+ "storageEndpoint": {
+ "type": "string"
+ },
+ "tags": {
+ "type": "object"
+ },
+ "teamsInstaller": {
+ "type": "string"
+ },
+ "userAssignedIdentityObjectId": {
+ "type": "string"
+ },
+ "vcRedistInstaller": {
+ "type": "string"
+ },
+ "vDotInstaller": {
+ "type": "string"
+ },
+ "virtualMachineName": {
+ "type": "string"
+ }
+ },
+ "variables": {
+ "installAccessVar": "[format('{0}installAccess', parameters('installAccess'))]",
+ "installers": "[parameters('customizations')]",
+ "installExcelVar": "[format('{0}installWord', parameters('installExcel'))]",
+ "installOneDriveVar": "[format('{0}installOneDrive', parameters('installOneDrive'))]",
+ "installOneNoteVar": "[format('{0}installOneNote', parameters('installOneNote'))]",
+ "installOutlookVar": "[format('{0}installOutlook', parameters('installOutlook'))]",
+ "installPowerPointVar": "[format('{0}installPowerPoint', parameters('installPowerPoint'))]",
+ "installProjectVar": "[format('{0}installProject', parameters('installProject'))]",
+ "installPublisherVar": "[format('{0}installPublisher', parameters('installPublisher'))]",
+ "installSkypeForBusinessVar": "[format('{0}installSkypeForBusiness', parameters('installSkypeForBusiness'))]",
+ "installVisioVar": "[format('{0}installVisio', parameters('installVisio'))]",
+ "installWordVar": "[format('{0}installWord', parameters('installWord'))]"
+ },
+ "resources": [
+ {
+ "copy": {
+ "name": "applications",
+ "count": "[length(variables('installers'))]",
+ "mode": "serial",
+ "batchSize": 1
+ },
+ "type": "Microsoft.Compute/virtualMachines/runCommands",
+ "apiVersion": "2023-03-01",
+ "name": "[format('{0}/{1}', parameters('virtualMachineName'), format('app-{0}', variables('installers')[copyIndex()].name))]",
+ "location": "[parameters('location')]",
+ "tags": "[if(contains(parameters('tags'), 'Microsoft.Compute/virtualMachines'), parameters('tags')['Microsoft.Compute/virtualMachines'], createObject())]",
+ "properties": {
+ "treatFailureAsDeploymentFailure": true,
+ "asyncExecution": false,
+ "parameters": [
+ {
+ "name": "UserAssignedIdentityObjectId",
+ "value": "[parameters('userAssignedIdentityObjectId')]"
+ },
+ {
+ "name": "StorageAccountName",
+ "value": "[parameters('storageAccountName')]"
+ },
+ {
+ "name": "ContainerName",
+ "value": "[parameters('containerName')]"
+ },
+ {
+ "name": "StorageEndpoint",
+ "value": "[parameters('storageEndpoint')]"
+ },
+ {
+ "name": "Blobname",
+ "value": "[variables('installers')[copyIndex()].blobName]"
+ },
+ {
+ "name": "Installer",
+ "value": "[variables('installers')[copyIndex()].name]"
+ },
+ {
+ "name": "Arguments",
+ "value": "[variables('installers')[copyIndex()].arguments]"
+ }
+ ],
+ "source": {
+ "script": " param(\r\n [string]$UserAssignedIdentityObjectId,\r\n [string]$StorageAccountName,\r\n [string]$ContainerName,\r\n [string]$StorageEndpoint,\r\n [string]$BlobName,\r\n [string]$Installer,\r\n [string]$Arguments\r\n )\r\n $ErrorActionPreference = 'Stop'\r\n $WarningPreference = 'SilentlyContinue'\r\n $StorageAccountUrl = \"https://\" + $StorageAccountName + \".blob.\" + $StorageEndpoint + \"/\"\r\n $TokenUri = \"http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=$StorageAccountUrl&object_id=$UserAssignedIdentityObjectId\"\r\n $AccessToken = ((Invoke-WebRequest -Headers @{Metadata=$true} -Uri $TokenUri -UseBasicParsing).Content | ConvertFrom-Json).access_token\r\n New-Item -Path $env:windir\\temp -Name $Installer -ItemType \"directory\" -Force\r\n New-Item -Path $env:windir\\temp\\$Installer -Name 'Files' -ItemType \"directory\" -Force\r\n Invoke-WebRequest -Headers @{\"x-ms-version\"=\"2017-11-09\"; Authorization =\"Bearer $AccessToken\"} -Uri \"$StorageAccountUrl$ContainerName/$BlobName\" -OutFile $env:windir\\temp\\$Installer\\Files\\$Blobname\r\n Start-Sleep -Seconds 30\r\n Set-Location -Path $env:windir\\temp\\$Installer\r\n if($Blobname -like (\"*.exe\"))\r\n {\r\n Start-Process -FilePath $env:windir\\temp\\$Installer\\Files\\$Blobname -ArgumentList $Arguments -NoNewWindow -Wait -PassThru\r\n $status = Get-WmiObject -Class Win32_Product | Where-Object Name -like \"*$($installer)*\"\r\n if($status)\r\n {\r\n Write-Host $status.Name \"is installed\"\r\n }\r\n else\r\n {\r\n Write-host $Installer \"did not install properly, please check arguments\"\r\n }\r\n }\r\n if($Blobname -like (\"*.msi\"))\r\n {\r\n Set-Location -Path $env:windir\\temp\\$Installer\\Files\r\n Start-Process -FilePath msiexec.exe -ArgumentList $Arguments -Wait\r\n $status = Get-WmiObject -Class Win32_Product | Where-Object Name -like \"*$($installer)*\"\r\n if($status)\r\n {\r\n Write-Host $status.Name \"is installed\"\r\n }\r\n else\r\n {\r\n Write-host $Installer \"did not install properly, please check arguments\"\r\n }\r\n }\r\n if($Blobname -like (\"*.bat\"))\r\n {\r\n Start-Process -FilePath cmd.exe -ArgumentList $env:windir\\temp\\$Installer\\Files\\$Arguments -Wait\r\n }\r\n if($Blobname -like (\"*.ps1\"))\r\n {\r\n Start-Process -FilePath PowerShell.exe -ArgumentList $env:windir\\temp\\$Installer\\Files\\$Arguments -Wait\r\n }\r\n if($Blobname -like (\"*.zip\"))\r\n {\r\n Set-Location -Path $env:windir\\temp\\$Installer\\Files\r\n Expand-Archive -Path $env:windir\\temp\\$Installer\\Files\\$Blobname -DestinationPath $env:windir\\temp\\$Installer\\Files -Force\r\n Remove-Item -Path .\\$Blobname -Force -Recurse\r\n }\r\n Write-Host \"Removing $Installer Files\"\r\n Remove-item $env:windir\\temp\\$Installer -Force -Recurse -Confirm:$false\r\n "
+ }
+ }
+ },
+ {
+ "condition": "[or(or(or(or(or(or(or(or(or(or(parameters('installAccess'), parameters('installExcel')), parameters('installOneDrive')), parameters('installOneNote')), parameters('installOutlook')), parameters('installPowerPoint')), parameters('installPublisher')), parameters('installSkypeForBusiness')), parameters('installWord')), parameters('installVisio')), parameters('installProject'))]",
+ "type": "Microsoft.Compute/virtualMachines/runCommands",
+ "apiVersion": "2023-03-01",
+ "name": "[format('{0}/{1}', parameters('virtualMachineName'), 'office')]",
+ "location": "[parameters('location')]",
+ "tags": "[if(contains(parameters('tags'), 'Microsoft.Compute/virtualMachines'), parameters('tags')['Microsoft.Compute/virtualMachines'], createObject())]",
+ "properties": {
+ "treatFailureAsDeploymentFailure": true,
+ "asyncExecution": false,
+ "parameters": [
+ {
+ "name": "InstallAccess",
+ "value": "[variables('installAccessVar')]"
+ },
+ {
+ "name": "InstallWord",
+ "value": "[variables('installWordVar')]"
+ },
+ {
+ "name": "InstallExcel",
+ "value": "[variables('installExcelVar')]"
+ },
+ {
+ "name": "InstallOneDrive",
+ "value": "[variables('installOneDriveVar')]"
+ },
+ {
+ "name": "InstallOneNote",
+ "value": "[variables('installOneNoteVar')]"
+ },
+ {
+ "name": "InstallOutlook",
+ "value": "[variables('installOutlookVar')]"
+ },
+ {
+ "name": "InstallPowerPoint",
+ "value": "[variables('installPowerPointVar')]"
+ },
+ {
+ "name": "InstallProject",
+ "value": "[variables('installProjectVar')]"
+ },
+ {
+ "name": "InstallPublisher",
+ "value": "[variables('installPublisherVar')]"
+ },
+ {
+ "name": "InstallSkypeForBusiness",
+ "value": "[variables('installSkypeForBusinessVar')]"
+ },
+ {
+ "name": "InstallVisio",
+ "value": "[variables('installVisioVar')]"
+ },
+ {
+ "name": "UserAssignedIdentityObjectId",
+ "value": "[parameters('userAssignedIdentityObjectId')]"
+ },
+ {
+ "name": "StorageAccountName",
+ "value": "[parameters('storageAccountName')]"
+ },
+ {
+ "name": "ContainerName",
+ "value": "[parameters('containerName')]"
+ },
+ {
+ "name": "StorageEndpoint",
+ "value": "[parameters('storageEndpoint')]"
+ },
+ {
+ "name": "BlobName",
+ "value": "[parameters('officeInstaller')]"
+ }
+ ],
+ "source": {
+ "script": " param(\r\n [string]$InstallAccess,\r\n [string]$InstallExcel,\r\n [string]$InstallOneDrive,\r\n [string]$InstallOutlook,\r\n [string]$InstallProject,\r\n [string]$InstallPublisher,\r\n [string]$InstallSkypeForBusiness,\r\n [string]$InstallVisio,\r\n [string]$InstallWord,\r\n [string]$InstallOneNote,\r\n [string]$InstallPowerPoint,\r\n [string]$UserAssignedIdentityObjectId,\r\n [string]$StorageAccountName,\r\n [string]$ContainerName,\r\n [string]$StorageEndpoint,\r\n [string]$BlobName\r\n )\r\n $ErrorActionPreference = 'Stop'\r\n $WarningPreference = 'SilentlyContinue'\r\n $StorageAccountUrl = \"https://\" + $StorageAccountName + \".blob.\" + $StorageEndpoint + \"/\"\r\n $TokenUri = \"http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=$StorageAccountUrl&object_id=$UserAssignedIdentityObjectId\"\r\n $AccessToken = ((Invoke-WebRequest -Headers @{Metadata=$true} -Uri $TokenUri -UseBasicParsing).Content | ConvertFrom-Json).access_token\r\n New-Item -Path \"$env:windir\\temp\\office\" -ItemType \"directory\" -Force\r\n $sku = (Get-ComputerInfo).OsName\r\n $o365ConfigHeader = Set-Content \"$env:windir\\temp\\office\\office365x64.xml\" ''\r\n $o365OfficeHeader = Add-Content \"$env:windir\\temp\\office\\office365x64.xml\" ''\r\n if($InstallAccess -notlike '*true*'){\r\n Add-Content \"$env:windir\\temp\\office\\office365x64.xml\" ''\r\n }\r\n if($InstallExcel -notlike '*true*'){\r\n Add-Content \"$env:windir\\temp\\office\\office365x64.xml\" ''\r\n }\r\n if($InstallOneDrive -notlike '*true*'){\r\n Add-Content \"$env:windir\\temp\\office\\office365x64.xml\" ''\r\n }\r\n if($InstallOneNote -notlike '*true*'){\r\n Add-Content \"$env:windir\\temp\\office\\office365x64.xml\" ''\r\n }\r\n if($InstallOutlook -notlike '*true*'){\r\n Add-Content \"$env:windir\\temp\\office\\office365x64.xml\" ''\r\n }\r\n if($InstallPowerPoint -notlike '*true*'){\r\n Add-Content \"$env:windir\\temp\\office\\office365x64.xml\" ''\r\n }\r\n if($InstallPublisher -notlike '*true*'){\r\n Add-Content \"$env:windir\\temp\\office\\office365x64.xml\" ''\r\n }\r\n if($InstallSkypeForBusiness -notlike '*true*'){\r\n Add-Content \"$env:windir\\temp\\office\\office365x64.xml\" ''\r\n }\r\n if($InstallWord -notlike '*true*'){\r\n Add-Content \"$env:windir\\temp\\office\\office365x64.xml\" ''\r\n }\r\n $addOfficefooter = Add-Content \"$env:windir\\temp\\office\\office365x64.xml\" ''\r\n if($InstallProject -like '*true*'){\r\n Add-Content \"$env:windir\\temp\\office\\office365x64.xml\" ''\r\n }\r\n if($InstallVisio -like '*true*'){\r\n Add-Content \"$env:windir\\temp\\office\\office365x64.xml\" ''\r\n }\r\n Add-Content \"$env:windir\\temp\\office\\office365x64.xml\" ''\r\n $PerMachineConfiguration = if(($Sku).Contains(\"multi\") -eq \"true\"){\r\n Add-Content \"$env:windir\\temp\\office\\office365x64.xml\" ''\r\n }\r\n Add-Content \"$env:windir\\temp\\office\\office365x64.xml\" ''\r\n $Installer = \"$env:windir\\temp\\office\\office.exe\"\r\n #$DownloadLinks = Invoke-WebRequest -Uri \"https://www.microsoft.com/en-us/download/confirmation.aspx?id=49117\" -UseBasicParsing\r\n #$URL = $DownloadLinks.Links.href | Where-Object {$_ -like \"https://download.microsoft.com/download/*officedeploymenttool*\"} | Select-Object -First 1\r\n #Invoke-WebRequest -Uri $URL -OutFile $Installer -UseBasicParsing\r\n Invoke-WebRequest -Headers @{\"x-ms-version\"=\"2017-11-09\"; Authorization =\"Bearer $AccessToken\"} -Uri \"$StorageAccountUrl$ContainerName/$BlobName\" -OutFile $Installer\r\n Start-Process -FilePath $Installer -ArgumentList \"/extract:$env:windir\\temp\\office /quiet /passive /norestart\" -Wait -PassThru | Out-Null\r\n Write-Host \"Downloaded & extracted the Office 365 Deployment Toolkit\"\r\n Start-Process -FilePath \"$env:windir\\temp\\office\\setup.exe\" -ArgumentList \"/configure $env:windir\\temp\\office\\office365x64.xml\" -Wait -PassThru -ErrorAction \"Stop\" | Out-Null\r\n Write-Host \"Installed the selected Office365 applications\"\r\n Write-Host \"Removing Office FIles\"\r\n Remove-item -Path \"$env:windir\\temp\\office\" -Force -Confirm:$false -Recurse\r\n "
+ }
+ },
+ "dependsOn": [
+ "applications"
+ ]
+ },
+ {
+ "condition": "[parameters('installVirtualDesktopOptimizationTool')]",
+ "type": "Microsoft.Compute/virtualMachines/runCommands",
+ "apiVersion": "2023-03-01",
+ "name": "[format('{0}/{1}', parameters('virtualMachineName'), 'vdot')]",
+ "location": "[parameters('location')]",
+ "tags": "[if(contains(parameters('tags'), 'Microsoft.Compute/virtualMachines'), parameters('tags')['Microsoft.Compute/virtualMachines'], createObject())]",
+ "properties": {
+ "treatFailureAsDeploymentFailure": true,
+ "asyncExecution": false,
+ "parameters": [
+ {
+ "name": "UserAssignedIdentityObjectId",
+ "value": "[parameters('userAssignedIdentityObjectId')]"
+ },
+ {
+ "name": "StorageAccountName",
+ "value": "[parameters('storageAccountName')]"
+ },
+ {
+ "name": "ContainerName",
+ "value": "[parameters('containerName')]"
+ },
+ {
+ "name": "StorageEndpoint",
+ "value": "[parameters('storageEndpoint')]"
+ },
+ {
+ "name": "BlobName",
+ "value": "[parameters('vDotInstaller')]"
+ }
+ ],
+ "source": {
+ "script": " param(\r\n [string]$UserAssignedIdentityObjectId,\r\n [string]$StorageAccountName,\r\n [string]$ContainerName,\r\n [string]$StorageEndpoint,\r\n [string]$BlobName\r\n )\r\n $ErrorActionPreference = 'Stop'\r\n $WarningPreference = 'SilentlyContinue'\r\n $StorageAccountUrl = \"https://\" + $StorageAccountName + \".blob.\" + $StorageEndpoint + \"/\"\r\n $TokenUri = \"http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=$StorageAccountUrl&object_id=$UserAssignedIdentityObjectId\"\r\n $AccessToken = ((Invoke-WebRequest -Headers @{Metadata=$true} -Uri $TokenUri -UseBasicParsing).Content | ConvertFrom-Json).access_token\r\n $ZIP = \"$env:windir\\temp\\VDOT.zip\"\r\n Invoke-WebRequest -Headers @{\"x-ms-version\"=\"2017-11-09\"; Authorization =\"Bearer $AccessToken\"} -Uri \"$StorageAccountUrl$ContainerName/$BlobName\" -OutFile $ZIP\r\n Start-Sleep -Seconds 30\r\n Set-Location -Path $env:windir\\temp\r\n Unblock-File -Path $ZIP\r\n Expand-Archive -LiteralPath $ZIP -DestinationPath \"$env:windir\\temp\" -Force\r\n $Path = (Get-ChildItem -Path \"$env:windir\\temp\" -Recurse | Where-Object {$_.Name -eq \"Windows_VDOT.ps1\"}).FullName\r\n $Script = Get-Content -Path $Path\r\n $ScriptUpdate = $Script.Replace(\"Set-NetAdapterAdvancedProperty\",\"#Set-NetAdapterAdvancedProperty\")\r\n $ScriptUpdate | Set-Content -Path $Path\r\n & $Path -Optimizations @(\"AppxPackages\",\"Autologgers\",\"DefaultUserSettings\",\"LGPO\";\"NetworkOptimizations\",\"ScheduledTasks\",\"Services\",\"WindowsMediaPlayer\") -AdvancedOptimizations \"All\" -AcceptEULA\r\n Write-Host \"Removing VDOT Files\"\r\n # Expecting this format for vDot ZIP, update if using a different ZIP format for folder structure\r\n Remove-Item -Path $env:windir\\temp\\Virtual-Desktop-Optimization-Tool-main -Force -Recurse -Confirm:$false\r\n "
+ },
+ "timeoutInSeconds": 640
+ },
+ "dependsOn": [
+ "applications",
+ "[resourceId('Microsoft.Compute/virtualMachines/runCommands', parameters('virtualMachineName'), 'office')]",
+ "[resourceId('Microsoft.Compute/virtualMachines/runCommands', parameters('virtualMachineName'), 'teams')]"
+ ]
+ },
+ {
+ "condition": "[parameters('installTeams')]",
+ "type": "Microsoft.Compute/virtualMachines/runCommands",
+ "apiVersion": "2023-03-01",
+ "name": "[format('{0}/{1}', parameters('virtualMachineName'), 'teams')]",
+ "location": "[parameters('location')]",
+ "tags": "[if(contains(parameters('tags'), 'Microsoft.Compute/virtualMachines'), parameters('tags')['Microsoft.Compute/virtualMachines'], createObject())]",
+ "properties": {
+ "treatFailureAsDeploymentFailure": true,
+ "asyncExecution": false,
+ "parameters": [
+ {
+ "name": "UserAssignedIdentityObjectId",
+ "value": "[parameters('userAssignedIdentityObjectId')]"
+ },
+ {
+ "name": "StorageAccountName",
+ "value": "[parameters('storageAccountName')]"
+ },
+ {
+ "name": "ContainerName",
+ "value": "[parameters('containerName')]"
+ },
+ {
+ "name": "StorageEndpoint",
+ "value": "[parameters('storageEndpoint')]"
+ },
+ {
+ "name": "BlobName",
+ "value": "[parameters('teamsInstaller')]"
+ },
+ {
+ "name": "BlobName2",
+ "value": "[parameters('vcRedistInstaller')]"
+ },
+ {
+ "name": "BlobName3",
+ "value": "[parameters('msrdcwebrtcsvcInstaller')]"
+ }
+ ],
+ "source": {
+ "script": " param(\r\n [string]$UserAssignedIdentityObjectId,\r\n [string]$StorageAccountName,\r\n [string]$ContainerName,\r\n [string]$StorageEndpoint,\r\n [string]$BlobName,\r\n [string]$BlobName2,\r\n [string]$BlobName3\r\n )\r\n $ErrorActionPreference = 'Stop'\r\n $WarningPreference = 'SilentlyContinue'\r\n $StorageAccountUrl = \"https://\" + $StorageAccountName + \".blob.\" + $StorageEndpoint + \"/\"\r\n $TokenUri = \"http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=$StorageAccountUrl&object_id=$UserAssignedIdentityObjectId\"\r\n $AccessToken = ((Invoke-WebRequest -Headers @{Metadata=$true} -Uri $TokenUri -UseBasicParsing).Content | ConvertFrom-Json).access_token\r\n $vcRedistFile = \"$env:windir\\temp\\vc_redist.x64.exe\"\r\n $webSocketFile = \"$env:windir\\temp\\webSocketSvc.msi\"\r\n $teamsFile = \"$env:windir\\temp\\teams.msi\"\r\n Invoke-WebRequest -Headers @{\"x-ms-version\"=\"2017-11-09\"; Authorization =\"Bearer $AccessToken\"} -Uri \"$StorageAccountUrl$ContainerName/$BlobName\" -OutFile $teamsFile\r\n Invoke-WebRequest -Headers @{\"x-ms-version\"=\"2017-11-09\"; Authorization =\"Bearer $AccessToken\"} -Uri \"$StorageAccountUrl$ContainerName/$BlobName2\" -OutFile $vcRedistFile\r\n Invoke-WebRequest -Headers @{\"x-ms-version\"=\"2017-11-09\"; Authorization =\"Bearer $AccessToken\"} -Uri \"$StorageAccountUrl$ContainerName/$BlobName3\" -OutFile $webSocketFile\r\n\r\n # Enable media optimizations for Team\r\n Start-Process \"reg\" -ArgumentList \"add HKLM\\SOFTWARE\\Microsoft\\Teams /v IsWVDEnvironment /t REG_DWORD /d 1 /f\" -Wait -PassThru -ErrorAction \"Stop\"\r\n Write-Host \"Enabled media optimizations for Teams\"\r\n # Download & install the latest version of Microsoft Visual C++ Redistributable\r\n #$File = \"$env:windir\\temp\\vc_redist.x64.exe\"\r\n #Invoke-WebRequest -Uri \"https://aka.ms/vs/16/release/vc_redist.x64.exe\" -OutFile $File\r\n Start-Process -FilePath $vcRedistFile -Args \"/install /quiet /norestart /log vcdist.log\" -Wait -PassThru | Out-Null\r\n Write-Host \"Installed the latest version of Microsoft Visual C++ Redistributable\"\r\n # Download & install the Remote Desktop WebRTC Redirector Service\r\n #$File = \"$env:windir\\temp\\webSocketSvc.msi\"\r\n #Invoke-WebRequest -Uri \"https://aka.ms/msrdcwebrtcsvc/msi\" -OutFile $File\r\n Start-Process -FilePath msiexec.exe -Args \"/i $webSocketFile /quiet /qn /norestart /passive /log webSocket.log\" -Wait -PassThru | Out-Null\r\n Write-Host \"Installed the Remote Desktop WebRTC Redirector Service\"\r\n # Install Teams\r\n #$File = \"$env:windir\\temp\\teams.msi\"\r\n #Write-host $($TeamsUrl)\r\n #Invoke-WebRequest -Uri \"$TeamsUrl\" -OutFile $File\r\n $sku = (Get-ComputerInfo).OsName\r\n $PerMachineConfiguration = if(($Sku).Contains(\"multi\") -eq \"true\"){\"ALLUSER=1\"}else{\"\"}\r\n Start-Process -FilePath msiexec.exe -Args \"/i $teamsFile /quiet /qn /norestart /passive /log teams.log $PerMachineConfiguration ALLUSERS=1\" -Wait -PassThru | Out-Null\r\n Write-Host \"Installed Teams\"\r\n Write-Host \"Removing Teams Files\"\r\n Remove-Item \"$teamsFile\" -Force -Confirm:$false\r\n Remove-Item \"$vcRedistFile\" -Force -Confirm:$false\r\n Remove-Item \"$webSocketFile\" -Force -Confirm:$false\r\n "
+ }
+ },
+ "dependsOn": [
+ "applications",
+ "[resourceId('Microsoft.Compute/virtualMachines/runCommands', parameters('virtualMachineName'), 'office')]"
+ ]
+ },
+ {
+ "condition": "[parameters('installArcGisPro')]",
+ "type": "Microsoft.Compute/virtualMachines/runCommands",
+ "apiVersion": "2023-03-01",
+ "name": "[format('{0}/{1}', parameters('virtualMachineName'), 'arcGisPro')]",
+ "location": "[parameters('location')]",
+ "tags": "[if(contains(parameters('tags'), 'Microsoft.Compute/virtualMachines'), parameters('tags')['Microsoft.Compute/virtualMachines'], createObject())]",
+ "properties": {
+ "treatFailureAsDeploymentFailure": true,
+ "asyncExecution": false,
+ "parameters": [
+ {
+ "name": "UserAssignedIdentityObjectId",
+ "value": "[parameters('userAssignedIdentityObjectId')]"
+ },
+ {
+ "name": "StorageAccountName",
+ "value": "[parameters('storageAccountName')]"
+ },
+ {
+ "name": "ContainerName",
+ "value": "[parameters('containerName')]"
+ },
+ {
+ "name": "StorageEndpoint",
+ "value": "[parameters('storageEndpoint')]"
+ },
+ {
+ "name": "BlobName",
+ "value": "[parameters('arcGisProInstaller')]"
+ }
+ ],
+ "source": {
+ "script": " param(\r\n [string]$UserAssignedIdentityObjectId,\r\n [string]$StorageAccountName,\r\n [string]$ContainerName,\r\n [string]$StorageEndpoint,\r\n [string]$BlobName\r\n )\r\n $ErrorActionPreference = 'Stop'\r\n $WarningPreference = 'SilentlyContinue'\r\n $StorageAccountUrl = \"https://\" + $StorageAccountName + \".blob.\" + $StorageEndpoint + \"/\"\r\n $TokenUri = \"http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=$StorageAccountUrl&object_id=$UserAssignedIdentityObjectId\"\r\n $AccessToken = ((Invoke-WebRequest -Headers @{Metadata=$true} -Uri $TokenUri -UseBasicParsing).Content | ConvertFrom-Json).access_token\r\n # Retrieve Files\r\n New-Item -Path $env:windir\\temp -Name arcgis -ItemType \"directory\" -Force\r\n $ZIP = \"$env:windir\\temp\\arcgispro.zip\"\r\n Invoke-WebRequest -Headers @{\"x-ms-version\"=\"2017-11-09\"; Authorization =\"Bearer $AccessToken\"} -Uri \"$StorageAccountUrl$ContainerName/$BlobName\" -OutFile $ZIP\r\n Start-Sleep -Seconds 30\r\n Set-Location -Path $env:windir\\temp\r\n Unblock-File -Path $ZIP\r\n Expand-Archive -LiteralPath $ZIP -DestinationPath \"$env:windir\\temp\\arcgis\" -Force\r\n\r\n # Install Arcgis\r\n $arcGisProMsi = (Get-ChildItem \"$env:windir\\temp\\arcgis\\\" -Recurse | where {$_.Name -eq \"ArcGisPro.msi\"})\r\n $arcGisProMsp = (Get-ChildItem \"$env:windir\\temp\\arcgis\" -Recurse | where {$_.Extension -eq \".msp\"})\r\n $winDesktopRuntime = (Get-ChildItem \"$env:windir\\temp\\arcgis\\\" -Recurse | where {$_.Name -like \"windowsdesktop-runtime-*\"})\r\n\r\n # If found Install Windows Desktop Runtime Pre-Req\r\n try {\r\n if ($winDesktopRuntime ){\r\n Start-Process -FilePath \"$($winDesktopRuntime.Directory.FullName)\\$winDesktopRuntime\" -ArgumentList \"/install /quiet /norestart\" -Wait -NoNewWindow -PassThru\r\n }\r\n }\r\n catch {\r\n Write-Output \"Please validate all software requirements are included with the ArcGIS Pro Zip\"\r\n }\r\n\r\n try {\r\n # Install ArcGis Pro\r\n $arcGisProArguments = \"/i $($arcGisProMsi.Directory.FullName)\\$arcGisProMsi ALLUSERS=1 ACCEPTEULA=yes ENABLEEUEI=0 SOFTWARE_CLASS=Professional AUTHORIZATION_TYPE=NAMED_USER LOCK_AUTH_SETTINGS=False ArcGIS_Connection=TRUE /qn /norestart\"\r\n Start-Process \"msiexec.exe\" -ArgumentList $arcGisProArguments -Wait -NoNewWindow -PassThru\r\n }\r\n catch {\r\n Write-Output \"Please validate all software requirements are included with the ArcGIS Pro Zip\"\r\n }\r\n\r\n try {\r\n # If MSP is found, patch ArcGisPro with MSP file\r\n if($arcGisProMsp){\r\n Start-Process \"msiexec.exe\" -ArgumentList \"/p $($arcGisProMsp.Directory.FullName)\\$arcGisProMsp /qn\" -Wait -NoNewWindow -PassThru\r\n }\r\n }\r\n catch {\r\n Write-Output \"Please validate all software requirements are included with the ArcGIS Pro Zip\"\r\n }\r\n Write-Host \"Removing ArcGis Files\"\r\n Remove-Item $ZIP -Force -Confirm:$false -Recurse\r\n Remove-item -Path \"$env:windir\\temp\\arcgis\" -Force -Confirm:$false -Recurse\r\n "
+ }
+ },
+ "dependsOn": [
+ "applications",
+ "[resourceId('Microsoft.Compute/virtualMachines/runCommands', parameters('virtualMachineName'), 'office')]",
+ "[resourceId('Microsoft.Compute/virtualMachines/runCommands', parameters('virtualMachineName'), 'teams')]",
+ "[resourceId('Microsoft.Compute/virtualMachines/runCommands', parameters('virtualMachineName'), 'vdot')]"
+ ]
+ }
+ ]
+ }
+ },
+ "dependsOn": [
+ "[resourceId('Microsoft.Resources/deployments', format('image-vm-{0}', parameters('deploymentNameSuffix')))]"
+ ]
+ },
+ {
+ "type": "Microsoft.Resources/deployments",
+ "apiVersion": "2022-09-01",
+ "name": "[format('restart-vm-{0}', parameters('deploymentNameSuffix'))]",
+ "properties": {
+ "expressionEvaluationOptions": {
+ "scope": "inner"
+ },
+ "mode": "Incremental",
+ "parameters": {
+ "imageVirtualMachineName": {
+ "value": "[reference(resourceId('Microsoft.Resources/deployments', format('image-vm-{0}', parameters('deploymentNameSuffix'))), '2022-09-01').outputs.name.value]"
+ },
+ "resourceGroupName": {
+ "value": "[variables('resourceGroupName')]"
+ },
+ "location": {
+ "value": "[parameters('location')]"
+ },
+ "tags": {
+ "value": "[parameters('tags')]"
+ },
+ "userAssignedIdentityClientId": {
+ "value": "[parameters('userAssignedIdentityClientId')]"
+ },
+ "virtualMachineName": "[if(parameters('enableBuildAutomation'), createObject('value', parameters('managementVirtualMachineName')), createObject('value', reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', variables('subscriptionId'), variables('resourceGroupName')), 'Microsoft.Resources/deployments', format('management-vm-{0}', parameters('deploymentNameSuffix'))), '2022-09-01').outputs.name.value))]"
+ },
+ "template": {
+ "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
+ "contentVersion": "1.0.0.0",
+ "metadata": {
+ "_generator": {
+ "name": "bicep",
+ "version": "0.24.24.22086",
+ "templateHash": "272404991735293049"
+ }
+ },
+ "parameters": {
+ "imageVirtualMachineName": {
+ "type": "string"
+ },
+ "resourceGroupName": {
+ "type": "string"
+ },
+ "location": {
+ "type": "string"
+ },
+ "tags": {
+ "type": "object"
+ },
+ "userAssignedIdentityClientId": {
+ "type": "string"
+ },
+ "virtualMachineName": {
+ "type": "string"
+ }
+ },
+ "resources": [
+ {
+ "type": "Microsoft.Compute/virtualMachines/runCommands",
+ "apiVersion": "2023-03-01",
+ "name": "[format('{0}/{1}', parameters('virtualMachineName'), 'restartVirtualMachine')]",
+ "location": "[parameters('location')]",
+ "tags": "[if(contains(parameters('tags'), 'Microsoft.Compute/virtualMachines'), parameters('tags')['Microsoft.Compute/virtualMachines'], createObject())]",
+ "properties": {
+ "treatFailureAsDeploymentFailure": true,
+ "asyncExecution": false,
+ "parameters": [
+ {
+ "name": "Environment",
+ "value": "[environment().name]"
+ },
+ {
+ "name": "ResourceGroupName",
+ "value": "[parameters('resourceGroupName')]"
+ },
+ {
+ "name": "SubscriptionId",
+ "value": "[subscription().subscriptionId]"
+ },
+ {
+ "name": "TenantId",
+ "value": "[tenant().tenantId]"
+ },
+ {
+ "name": "UserAssignedIdentityClientId",
+ "value": "[parameters('userAssignedIdentityClientId')]"
+ },
+ {
+ "name": "VirtualMachineName",
+ "value": "[parameters('imageVirtualMachineName')]"
+ }
+ ],
+ "source": {
+ "script": " param(\r\n [string]$Environment,\r\n [string]$ResourceGroupName,\r\n [string]$SubscriptionId,\r\n [string]$TenantId,\r\n [string]$UserAssignedIdentityClientId,\r\n [string]$VirtualMachineName\r\n )\r\n $ErrorActionPreference = 'Stop'\r\n Connect-AzAccount -Environment $Environment -Tenant $TenantId -Subscription $SubscriptionId -Identity -AccountId $UserAssignedIdentityClientId | Out-Null\r\n Restart-AzVM -ResourceGroupName $ResourceGroupName -Name $VirtualMachineName\r\n $AgentStatus = $Null\r\n while ($Null -eq $AgentStatus) \r\n {\r\n Start-Sleep -Seconds 5\r\n $AgentStatus = (Get-AzVM -ResourceGroupName $ResourceGroupName -Name $VirtualMachineName -Status).VMAgent\r\n }\r\n "
+ }
+ }
+ }
+ ]
+ }
+ },
+ "dependsOn": [
+ "[resourceId('Microsoft.Resources/deployments', format('customizations-{0}', parameters('deploymentNameSuffix')))]",
+ "[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', variables('subscriptionId'), variables('resourceGroupName')), 'Microsoft.Resources/deployments', format('management-vm-{0}', parameters('deploymentNameSuffix')))]",
+ "[resourceId('Microsoft.Resources/deployments', format('image-vm-{0}', parameters('deploymentNameSuffix')))]"
+ ]
+ },
+ {
+ "type": "Microsoft.Resources/deployments",
+ "apiVersion": "2022-09-01",
+ "name": "[format('sysprep-vm-{0}', parameters('deploymentNameSuffix'))]",
+ "properties": {
+ "expressionEvaluationOptions": {
+ "scope": "inner"
+ },
+ "mode": "Incremental",
+ "parameters": {
+ "location": {
+ "value": "[parameters('location')]"
+ },
+ "tags": {
+ "value": "[parameters('tags')]"
+ },
+ "virtualMachineName": {
+ "value": "[reference(resourceId('Microsoft.Resources/deployments', format('image-vm-{0}', parameters('deploymentNameSuffix'))), '2022-09-01').outputs.name.value]"
+ }
+ },
+ "template": {
+ "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
+ "contentVersion": "1.0.0.0",
+ "metadata": {
+ "_generator": {
+ "name": "bicep",
+ "version": "0.24.24.22086",
+ "templateHash": "15255297707921051029"
+ }
+ },
+ "parameters": {
+ "location": {
+ "type": "string"
+ },
+ "tags": {
+ "type": "object"
+ },
+ "virtualMachineName": {
+ "type": "string"
+ }
+ },
+ "resources": [
+ {
+ "type": "Microsoft.Compute/virtualMachines/runCommands",
+ "apiVersion": "2023-03-01",
+ "name": "[format('{0}/{1}', parameters('virtualMachineName'), 'sysprepVirtualMachine')]",
+ "location": "[parameters('location')]",
+ "tags": "[if(contains(parameters('tags'), 'Microsoft.Compute/virtualMachines'), parameters('tags')['Microsoft.Compute/virtualMachines'], createObject())]",
+ "properties": {
+ "treatFailureAsDeploymentFailure": false,
+ "asyncExecution": true,
+ "parameters": [],
+ "source": {
+ "script": " Start-Sleep -Seconds 30\r\n Remove-Item -LiteralPath 'C:\\Windows\\Panther' -Force -Recurse -ErrorAction SilentlyContinue\r\n Set-ItemProperty -Path 'HKLM:\\SYSTEM\\CurrentControlSet\\Services\\cdrom' -Name 'Start' -Value 1\r\n Start-Process -File 'C:\\Windows\\System32\\Sysprep\\Sysprep.exe' -ArgumentList '/generalize /oobe /shutdown /mode:vm'\r\n "
+ }
+ }
+ }
+ ]
+ }
+ },
+ "dependsOn": [
+ "[resourceId('Microsoft.Resources/deployments', format('restart-vm-{0}', parameters('deploymentNameSuffix')))]",
+ "[resourceId('Microsoft.Resources/deployments', format('image-vm-{0}', parameters('deploymentNameSuffix')))]"
+ ]
+ },
+ {
+ "type": "Microsoft.Resources/deployments",
+ "apiVersion": "2022-09-01",
+ "name": "[format('generalize-vm-{0}', parameters('deploymentNameSuffix'))]",
+ "properties": {
+ "expressionEvaluationOptions": {
+ "scope": "inner"
+ },
+ "mode": "Incremental",
+ "parameters": {
+ "imageVirtualMachineName": {
+ "value": "[reference(resourceId('Microsoft.Resources/deployments', format('image-vm-{0}', parameters('deploymentNameSuffix'))), '2022-09-01').outputs.name.value]"
+ },
+ "resourceGroupName": {
+ "value": "[variables('resourceGroupName')]"
+ },
+ "location": {
+ "value": "[parameters('location')]"
+ },
+ "tags": {
+ "value": "[parameters('tags')]"
+ },
+ "userAssignedIdentityClientId": {
+ "value": "[parameters('userAssignedIdentityClientId')]"
+ },
+ "virtualMachineName": "[if(parameters('enableBuildAutomation'), createObject('value', parameters('managementVirtualMachineName')), createObject('value', reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', variables('subscriptionId'), variables('resourceGroupName')), 'Microsoft.Resources/deployments', format('management-vm-{0}', parameters('deploymentNameSuffix'))), '2022-09-01').outputs.name.value))]"
+ },
+ "template": {
+ "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
+ "contentVersion": "1.0.0.0",
+ "metadata": {
+ "_generator": {
+ "name": "bicep",
+ "version": "0.24.24.22086",
+ "templateHash": "14089062657418312586"
+ }
+ },
+ "parameters": {
+ "imageVirtualMachineName": {
+ "type": "string"
+ },
+ "resourceGroupName": {
+ "type": "string"
+ },
+ "location": {
+ "type": "string",
+ "defaultValue": "[resourceGroup().location]"
+ },
+ "tags": {
+ "type": "object"
+ },
+ "userAssignedIdentityClientId": {
+ "type": "string"
+ },
+ "virtualMachineName": {
+ "type": "string"
+ }
+ },
+ "resources": [
+ {
+ "type": "Microsoft.Compute/virtualMachines/runCommands",
+ "apiVersion": "2023-03-01",
+ "name": "[format('{0}/{1}', parameters('virtualMachineName'), 'generalizeVirtualMachine')]",
+ "location": "[parameters('location')]",
+ "tags": "[if(contains(parameters('tags'), 'Microsoft.Compute/virtualMachines'), parameters('tags')['Microsoft.Compute/virtualMachines'], createObject())]",
+ "properties": {
+ "treatFailureAsDeploymentFailure": true,
+ "asyncExecution": false,
+ "parameters": [
+ {
+ "name": "Environment",
+ "value": "[environment().name]"
+ },
+ {
+ "name": "ResourceGroupName",
+ "value": "[parameters('resourceGroupName')]"
+ },
+ {
+ "name": "SubscriptionId",
+ "value": "[subscription().subscriptionId]"
+ },
+ {
+ "name": "TenantId",
+ "value": "[tenant().tenantId]"
+ },
+ {
+ "name": "UserAssignedIdentityClientId",
+ "value": "[parameters('userAssignedIdentityClientId')]"
+ },
+ {
+ "name": "VirtualMachineName",
+ "value": "[parameters('imageVirtualMachineName')]"
+ }
+ ],
+ "source": {
+ "script": " param(\r\n [string]$Environment,\r\n [string]$ResourceGroupName,\r\n [string]$SubscriptionId,\r\n [string]$TenantId,\r\n [string]$UserAssignedIdentityClientId,\r\n [string]$VirtualMachineName\r\n )\r\n $ErrorActionPreference = 'Stop'\r\n Connect-AzAccount -Environment $Environment -Tenant $TenantId -Subscription $SubscriptionId -Identity -AccountId $UserAssignedIdentityClientId | Out-Null\r\n $PowerStatus = ''\r\n while ($PowerStatus -ne 'VM stopped') \r\n {\r\n Start-Sleep -Seconds 5\r\n $PowerStatus = (Get-AzVM -ResourceGroupName $ResourceGroupName -Name $VirtualMachineName -Status).Statuses[1].DisplayStatus\r\n }\r\n Set-AzVm -ResourceGroupName $ResourceGroupName -Name $VirtualMachineName -Generalized\r\n Start-Sleep -Seconds 30\r\n "
+ }
+ }
+ }
+ ]
+ }
+ },
+ "dependsOn": [
+ "[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', variables('subscriptionId'), variables('resourceGroupName')), 'Microsoft.Resources/deployments', format('management-vm-{0}', parameters('deploymentNameSuffix')))]",
+ "[resourceId('Microsoft.Resources/deployments', format('sysprep-vm-{0}', parameters('deploymentNameSuffix')))]",
+ "[resourceId('Microsoft.Resources/deployments', format('image-vm-{0}', parameters('deploymentNameSuffix')))]"
+ ]
+ },
+ {
+ "type": "Microsoft.Resources/deployments",
+ "apiVersion": "2022-09-01",
+ "name": "[format('image-version-{0}', parameters('deploymentNameSuffix'))]",
+ "properties": {
+ "expressionEvaluationOptions": {
+ "scope": "inner"
+ },
+ "mode": "Incremental",
+ "parameters": {
+ "computeGalleryImageResourceId": {
+ "value": "[parameters('computeGalleryImageResourceId')]"
+ },
+ "computeGalleryName": {
+ "value": "[parameters('computeGalleryName')]"
+ },
+ "excludeFromLatest": {
+ "value": "[parameters('excludeFromLatest')]"
+ },
+ "imageDefinitionName": {
+ "value": "[parameters('imageDefinitionName')]"
+ },
+ "imageVersionNumber": {
+ "value": "[variables('autoImageVersion')]"
+ },
+ "imageVirtualMachineResourceId": {
+ "value": "[reference(resourceId('Microsoft.Resources/deployments', format('image-vm-{0}', parameters('deploymentNameSuffix'))), '2022-09-01').outputs.resourceId.value]"
+ },
+ "location": {
+ "value": "[parameters('location')]"
+ },
+ "marketplaceImageOffer": {
+ "value": "[parameters('marketplaceImageOffer')]"
+ },
+ "marketplaceImagePublisher": {
+ "value": "[parameters('marketplaceImagePublisher')]"
+ },
+ "replicaCount": {
+ "value": "[parameters('replicaCount')]"
+ },
+ "tags": {
+ "value": "[parameters('tags')]"
+ }
+ },
+ "template": {
+ "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
+ "contentVersion": "1.0.0.0",
+ "metadata": {
+ "_generator": {
+ "name": "bicep",
+ "version": "0.24.24.22086",
+ "templateHash": "6302458606004775652"
+ }
+ },
+ "parameters": {
+ "allowDeletionOfReplicatedLocations": {
+ "type": "bool",
+ "defaultValue": true
+ },
+ "computeGalleryName": {
+ "type": "string"
+ },
+ "computeGalleryImageResourceId": {
+ "type": "string"
+ },
+ "excludeFromLatest": {
+ "type": "bool"
+ },
+ "imageDefinitionName": {
+ "type": "string"
+ },
+ "imageVersionNumber": {
+ "type": "string"
+ },
+ "imageVirtualMachineResourceId": {
+ "type": "string"
+ },
+ "location": {
+ "type": "string"
+ },
+ "marketplaceImageOffer": {
+ "type": "string"
+ },
+ "marketplaceImagePublisher": {
+ "type": "string"
+ },
+ "replicaCount": {
+ "type": "int"
+ },
+ "tags": {
+ "type": "object"
+ }
+ },
+ "resources": [
+ {
+ "type": "Microsoft.Compute/galleries/images",
+ "apiVersion": "2022-03-03",
+ "name": "[format('{0}/{1}', parameters('computeGalleryName'), parameters('imageDefinitionName'))]",
+ "location": "[parameters('location')]",
+ "tags": "[if(contains(parameters('tags'), 'Microsoft.Compute/galleries'), parameters('tags')['Microsoft.Compute/galleries'], createObject())]",
+ "properties": {
+ "architecture": "x64",
+ "features": [
+ {
+ "name": "SecurityType",
+ "value": "TrustedLaunch"
+ }
+ ],
+ "hyperVGeneration": "V2",
+ "identifier": {
+ "offer": "[if(empty(parameters('computeGalleryImageResourceId')), parameters('marketplaceImageOffer'), reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', split(parameters('computeGalleryImageResourceId'), '/')[2], split(parameters('computeGalleryImageResourceId'), '/')[4]), 'Microsoft.Compute/galleries/images', split(parameters('computeGalleryImageResourceId'), '/')[8], split(parameters('computeGalleryImageResourceId'), '/')[10]), '2022-03-03').identifier.offer)]",
+ "publisher": "[if(empty(parameters('computeGalleryImageResourceId')), parameters('marketplaceImagePublisher'), reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', split(parameters('computeGalleryImageResourceId'), '/')[2], split(parameters('computeGalleryImageResourceId'), '/')[4]), 'Microsoft.Compute/galleries/images', split(parameters('computeGalleryImageResourceId'), '/')[8], split(parameters('computeGalleryImageResourceId'), '/')[10]), '2022-03-03').identifier.publisher)]",
+ "sku": "[parameters('imageDefinitionName')]"
+ },
+ "osState": "Generalized",
+ "osType": "Windows"
+ }
+ },
+ {
+ "type": "Microsoft.Compute/galleries/images/versions",
+ "apiVersion": "2022-03-03",
+ "name": "[format('{0}/{1}/{2}', parameters('computeGalleryName'), parameters('imageDefinitionName'), parameters('imageVersionNumber'))]",
+ "location": "[parameters('location')]",
+ "tags": "[if(contains(parameters('tags'), 'Microsoft.Compute/galleries'), parameters('tags')['Microsoft.Compute/galleries'], createObject())]",
+ "properties": {
+ "publishingProfile": {
+ "excludeFromLatest": "[parameters('excludeFromLatest')]",
+ "replicaCount": "[parameters('replicaCount')]",
+ "replicationMode": "Full",
+ "storageAccountType": "Standard_LRS",
+ "targetRegions": [
+ {
+ "name": "[parameters('location')]",
+ "regionalReplicaCount": "[parameters('replicaCount')]",
+ "storageAccountType": "Standard_LRS"
+ }
+ ]
+ },
+ "safetyProfile": {
+ "allowDeletionOfReplicatedLocations": "[parameters('allowDeletionOfReplicatedLocations')]"
+ },
+ "storageProfile": {
+ "source": {
+ "id": "[parameters('imageVirtualMachineResourceId')]"
+ }
+ }
+ },
+ "dependsOn": [
+ "[resourceId('Microsoft.Compute/galleries/images', parameters('computeGalleryName'), parameters('imageDefinitionName'))]"
+ ]
+ }
+ ]
+ }
+ },
+ "dependsOn": [
+ "[resourceId('Microsoft.Resources/deployments', format('generalize-vm-{0}', parameters('deploymentNameSuffix')))]",
+ "[resourceId('Microsoft.Resources/deployments', format('image-vm-{0}', parameters('deploymentNameSuffix')))]"
+ ]
+ },
+ {
+ "type": "Microsoft.Resources/deployments",
+ "apiVersion": "2022-09-01",
+ "name": "[format('remove-vm-{0}', parameters('deploymentNameSuffix'))]",
+ "properties": {
+ "expressionEvaluationOptions": {
+ "scope": "inner"
+ },
+ "mode": "Incremental",
+ "parameters": {
+ "enableBuildAutomation": {
+ "value": "[parameters('enableBuildAutomation')]"
+ },
+ "imageVirtualMachineName": {
+ "value": "[reference(resourceId('Microsoft.Resources/deployments', format('image-vm-{0}', parameters('deploymentNameSuffix'))), '2022-09-01').outputs.name.value]"
+ },
+ "location": {
+ "value": "[parameters('location')]"
+ },
+ "tags": {
+ "value": "[parameters('tags')]"
+ },
+ "userAssignedIdentityClientId": {
+ "value": "[parameters('userAssignedIdentityClientId')]"
+ },
+ "virtualMachineName": "[if(parameters('enableBuildAutomation'), createObject('value', parameters('managementVirtualMachineName')), createObject('value', reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', variables('subscriptionId'), variables('resourceGroupName')), 'Microsoft.Resources/deployments', format('management-vm-{0}', parameters('deploymentNameSuffix'))), '2022-09-01').outputs.name.value))]"
+ },
+ "template": {
+ "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
+ "contentVersion": "1.0.0.0",
+ "metadata": {
+ "_generator": {
+ "name": "bicep",
+ "version": "0.24.24.22086",
+ "templateHash": "3667781850662988906"
+ }
+ },
+ "parameters": {
+ "enableBuildAutomation": {
+ "type": "bool"
+ },
+ "imageVirtualMachineName": {
+ "type": "string"
+ },
+ "location": {
+ "type": "string",
+ "defaultValue": "[resourceGroup().location]"
+ },
+ "tags": {
+ "type": "object"
+ },
+ "userAssignedIdentityClientId": {
+ "type": "string"
+ },
+ "virtualMachineName": {
+ "type": "string"
+ }
+ },
+ "resources": [
+ {
+ "type": "Microsoft.Compute/virtualMachines/runCommands",
+ "apiVersion": "2023-03-01",
+ "name": "[format('{0}/{1}', parameters('virtualMachineName'), 'removeVirtualMachine')]",
+ "location": "[parameters('location')]",
+ "tags": "[if(contains(parameters('tags'), 'Microsoft.Compute/virtualMachines'), parameters('tags')['Microsoft.Compute/virtualMachines'], createObject())]",
+ "properties": {
+ "treatFailureAsDeploymentFailure": true,
+ "asyncExecution": "[if(parameters('enableBuildAutomation'), false(), true())]",
+ "parameters": [
+ {
+ "name": "EnableBuildAutomation",
+ "value": "[string(parameters('enableBuildAutomation'))]"
+ },
+ {
+ "name": "Environment",
+ "value": "[environment().name]"
+ },
+ {
+ "name": "ImageVmName",
+ "value": "[parameters('imageVirtualMachineName')]"
+ },
+ {
+ "name": "ManagementVmName",
+ "value": "[parameters('virtualMachineName')]"
+ },
+ {
+ "name": "ResourceGroupName",
+ "value": "[resourceGroup().name]"
+ },
+ {
+ "name": "SubscriptionId",
+ "value": "[subscription().subscriptionId]"
+ },
+ {
+ "name": "TenantId",
+ "value": "[tenant().tenantId]"
+ },
+ {
+ "name": "UserAssignedIdentityClientId",
+ "value": "[parameters('userAssignedIdentityClientId')]"
+ }
+ ],
+ "source": {
+ "script": " param(\r\n [string]$EnableBuildAutomation,\r\n [string]$Environment,\r\n [string]$ImageVmName,\r\n [string]$ManagementVmName,\r\n [string]$ResourceGroupName,\r\n [string]$SubscriptionId,\r\n [string]$TenantId,\r\n [string]$UserAssignedIdentityClientId\r\n )\r\n $ErrorActionPreference = 'Stop'\r\n Connect-AzAccount -Environment $Environment -Tenant $TenantId -Subscription $SubscriptionId -Identity -AccountId $UserAssignedIdentityClientId | Out-Null\r\n Remove-AzVM -ResourceGroupName $ResourceGroupName -Name $ImageVmName -Force\r\n if($EnableBuildAutomation -eq 'false')\r\n {\r\n Remove-AzVM -ResourceGroupName $ResourceGroupName -Name $ManagementVmName -NoWait -Force -AsJob\r\n }\r\n "
+ }
+ }
+ }
+ ]
+ }
+ },
+ "dependsOn": [
+ "[resourceId('Microsoft.Resources/deployments', format('image-version-{0}', parameters('deploymentNameSuffix')))]",
+ "[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', variables('subscriptionId'), variables('resourceGroupName')), 'Microsoft.Resources/deployments', format('management-vm-{0}', parameters('deploymentNameSuffix')))]",
+ "[resourceId('Microsoft.Resources/deployments', format('image-vm-{0}', parameters('deploymentNameSuffix')))]"
+ ]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/src/bicep/add-ons/Imaging/modules/imageVersion.bicep b/src/bicep/add-ons/Imaging/modules/imageVersion.bicep
new file mode 100644
index 000000000..d6e0b0704
--- /dev/null
+++ b/src/bicep/add-ons/Imaging/modules/imageVersion.bicep
@@ -0,0 +1,98 @@
+param allowDeletionOfReplicatedLocations bool = true
+param computeGalleryName string
+param computeGalleryImageResourceId string
+//param diskEncryptionSetResourceId string
+param excludeFromLatest bool
+param imageDefinitionName string
+param imageVersionNumber string
+param imageVirtualMachineResourceId string
+param location string
+param marketplaceImageOffer string
+param marketplaceImagePublisher string
+param replicaCount int
+param tags object
+
+resource computeGallery 'Microsoft.Compute/galleries@2022-01-03' existing = {
+ name: computeGalleryName
+}
+
+resource sourceComputeGallery 'Microsoft.Compute/galleries@2022-01-03' existing = if (!empty(computeGalleryImageResourceId)) {
+ scope: resourceGroup(split(computeGalleryImageResourceId, '/')[2], split(computeGalleryImageResourceId, '/')[4])
+ name: split(computeGalleryImageResourceId, '/')[8]
+}
+
+resource sourceImageDefinition 'Microsoft.Compute/galleries/images@2022-03-03' existing = if (!empty(computeGalleryImageResourceId)) {
+ parent: sourceComputeGallery
+ name: split(computeGalleryImageResourceId, '/')[10]
+}
+
+resource imageDefinition 'Microsoft.Compute/galleries/images@2022-03-03' = {
+ parent: computeGallery
+ name: imageDefinitionName
+ location: location
+ tags: contains(tags, 'Microsoft.Compute/galleries') ? tags['Microsoft.Compute/galleries'] : {}
+ properties: {
+ architecture: 'x64'
+ features: [
+ /* Uncomment features when generally available
+ {
+ name: 'IsHibernateSupported'
+ value: 'True'
+ }
+ {
+ name: 'IsAcceleratedNetworkSupported'
+ value: 'True'
+ }
+ */
+ {
+ name: 'SecurityType'
+ value: 'TrustedLaunch'
+ }
+ ]
+ hyperVGeneration: 'V2'
+ identifier: {
+ offer: empty(computeGalleryImageResourceId) ? marketplaceImageOffer : sourceImageDefinition.properties.identifier.offer
+ publisher: empty(computeGalleryImageResourceId) ? marketplaceImagePublisher : sourceImageDefinition.properties.identifier.publisher
+ sku: imageDefinitionName
+ }
+ osState: 'Generalized'
+ osType: 'Windows'
+ }
+}
+
+resource imageVersion 'Microsoft.Compute/galleries/images/versions@2022-03-03' = {
+ parent: imageDefinition
+ name: imageVersionNumber
+ location: location
+ tags: contains(tags, 'Microsoft.Compute/galleries') ? tags['Microsoft.Compute/galleries'] : {}
+ properties: {
+ publishingProfile: {
+ excludeFromLatest: excludeFromLatest
+ replicaCount: replicaCount
+ replicationMode: 'Full'
+ storageAccountType: 'Standard_LRS'
+ targetRegions: [
+ {
+ /* Not supported yet: https://learn.microsoft.com/en-us/azure/virtual-machines/image-version-encryption#limitations
+ encryption: {
+ osDiskImage: {
+ diskEncryptionSetId: diskEncryptionSetResourceId
+ }
+ }
+ */
+ name: location
+ regionalReplicaCount: replicaCount
+ storageAccountType: 'Standard_LRS'
+ }
+ ]
+ }
+ safetyProfile: {
+ allowDeletionOfReplicatedLocations: allowDeletionOfReplicatedLocations
+ }
+ storageProfile: {
+ source: {
+ id: imageVirtualMachineResourceId
+ }
+ }
+ }
+}
diff --git a/src/bicep/add-ons/Imaging/modules/keyVault.bicep b/src/bicep/add-ons/Imaging/modules/keyVault.bicep
new file mode 100644
index 000000000..dd33dd850
--- /dev/null
+++ b/src/bicep/add-ons/Imaging/modules/keyVault.bicep
@@ -0,0 +1,123 @@
+@secure()
+param domainJoinPassword string
+@secure()
+param domainJoinUserPrincipalName string
+param keyVaultName string
+param keyVaultPrivateDnsZoneResourceId string
+param location string
+@secure()
+param localAdministratorPassword string
+@secure()
+param localAdministratorUsername string
+param roleDefinitionResourceId string
+param subnetResourceId string
+param tags object
+param userAssignedIdentityPrincipalId string
+
+var privateEndpointName = 'pe-${keyVaultName}'
+
+var Secrets = [
+ {
+ name: 'DomainJoinPassword'
+ value: domainJoinPassword
+ }
+ {
+ name: 'DomainJoinUserPrincipalName'
+ value: domainJoinUserPrincipalName
+ }
+ {
+ name: 'LocalAdministratorPassword'
+ value: localAdministratorPassword
+ }
+ {
+ name: 'LocalAdministratorUsername'
+ value: localAdministratorUsername
+ }
+]
+
+// The Key Vault stores the secrets to deploy virtual machines
+resource keyVault 'Microsoft.KeyVault/vaults@2021-10-01' = {
+ name: keyVaultName
+ location: location
+ tags: contains(tags, 'Microsoft.KeyVault/vaults') ? tags['Microsoft.KeyVault/vaults'] : {}
+ properties: {
+ tenantId: subscription().tenantId
+ sku: {
+ family: 'A'
+ name: 'standard'
+ }
+ enabledForDeployment: true
+ enabledForTemplateDeployment: true
+ enabledForDiskEncryption: false
+ enableRbacAuthorization: true
+ enableSoftDelete: false
+ networkAcls: {
+ bypass: 'AzureServices'
+ defaultAction: 'Deny'
+ ipRules: []
+ virtualNetworkRules: []
+ }
+ publicNetworkAccess: 'Disabled'
+ }
+}
+
+resource privateEndpoint 'Microsoft.Network/privateEndpoints@2023-05-01' = {
+ name: privateEndpointName
+ location: location
+ tags: contains(tags, 'Microsoft.Network/privateEndpoints') ? tags['Microsoft.Network/privateEndpoints'] : {}
+ properties: {
+ privateLinkServiceConnections: [
+ {
+ name: privateEndpointName
+ id: resourceId('Microsoft.Network/privateEndpoints/privateLinkServiceConnections', privateEndpointName, privateEndpointName)
+ properties: {
+ privateLinkServiceId: keyVault.id
+ groupIds: [
+ 'vault'
+ ]
+ }
+ }
+ ]
+ customNetworkInterfaceName: 'nic-${keyVaultName}'
+ subnet: {
+ id: subnetResourceId
+ }
+ }
+}
+
+resource privateDnsZoneGroup 'Microsoft.Network/privateEndpoints/privateDnsZoneGroups@2023-05-01' = {
+ parent: privateEndpoint
+ name: 'default'
+ properties: {
+ privateDnsZoneConfigs: [
+ {
+ name: 'privatelink-azure-automation-net'
+ properties: {
+ privateDnsZoneId: keyVaultPrivateDnsZoneResourceId
+ }
+ }
+ ]
+ }
+}
+
+resource secrets 'Microsoft.KeyVault/vaults/secrets@2021-10-01' = [for Secret in Secrets: {
+ parent: keyVault
+ name: Secret.name
+ tags: contains(tags, 'Microsoft.KeyVault/vaults') ? tags['Microsoft.KeyVault/vaults'] : {}
+ properties: {
+ value: Secret.value
+ }
+}]
+
+// Gives the selected users rights to get key vault secrets in deployments
+resource roleAssignment 'Microsoft.Authorization/roleAssignments@2020-10-01-preview' = {
+ name: guid(userAssignedIdentityPrincipalId, roleDefinitionResourceId, resourceGroup().id)
+ scope: keyVault
+ properties: {
+ roleDefinitionId: roleDefinitionResourceId
+ principalId: userAssignedIdentityPrincipalId
+ principalType: 'ServicePrincipal'
+ }
+}
+
+output resourceId string = keyVault.id
diff --git a/src/bicep/add-ons/Imaging/modules/managementVM.bicep b/src/bicep/add-ons/Imaging/modules/managementVM.bicep
new file mode 100644
index 000000000..dfda4e8c2
--- /dev/null
+++ b/src/bicep/add-ons/Imaging/modules/managementVM.bicep
@@ -0,0 +1,198 @@
+param containerName string
+param diskEncryptionSetResourceId string
+param hybridUseBenefit bool
+@secure()
+param localAdministratorPassword string
+@secure()
+param localAdministratorUsername string
+param location string
+param storageAccountName string
+param subnetResourceId string
+param tags object
+param userAssignedIdentityPrincipalId string
+param userAssignedIdentityResourceId string
+param virtualMachineName string
+
+resource networkInterface 'Microsoft.Network/networkInterfaces@2023-04-01' = {
+ name: 'nic-${virtualMachineName}'
+ location: location
+ tags: contains(tags, 'Microsoft.Network/networkInterfaces') ? tags['Microsoft.Network/networkInterfaces'] : {}
+ properties: {
+ ipConfigurations: [
+ {
+ name: 'ipconfig'
+ properties: {
+ privateIPAllocationMethod: 'Dynamic'
+ subnet: {
+ id: subnetResourceId
+ }
+ primary: true
+ privateIPAddressVersion: 'IPv4'
+ }
+ }
+ ]
+ enableAcceleratedNetworking: true
+ enableIPForwarding: false
+ }
+}
+
+resource virtualMachine 'Microsoft.Compute/virtualMachines@2022-03-01' = {
+ name: virtualMachineName
+ location: location
+ tags: contains(tags, 'Microsoft.Compute/virtualMachines') ? tags['Microsoft.Compute/virtualMachines'] : {}
+ identity: {
+ type: 'UserAssigned'
+ userAssignedIdentities: {
+ '${userAssignedIdentityResourceId}': {}
+ }
+ }
+ properties: {
+ hardwareProfile: {
+ vmSize: 'Standard_D2s_v3'
+ }
+ osProfile: {
+ computerName: virtualMachineName
+ adminUsername: localAdministratorUsername
+ adminPassword: localAdministratorPassword
+ windowsConfiguration: {
+ provisionVMAgent: true
+ enableAutomaticUpdates: true
+ patchSettings: {
+ patchMode: 'AutomaticByOS'
+ assessmentMode: 'ImageDefault'
+ }
+ }
+ }
+ storageProfile: {
+ imageReference: {
+ publisher: 'MicrosoftWindowsServer'
+ offer: 'WindowsServer'
+ sku: '2019-datacenter-core-g2'
+ version: 'latest'
+ }
+ osDisk: {
+ caching: 'ReadWrite'
+ createOption: 'FromImage'
+ deleteOption: 'Delete'
+ managedDisk: {
+ diskEncryptionSet: {
+ id: diskEncryptionSetResourceId
+ }
+ storageAccountType: 'Premium_LRS'
+ }
+ name: 'disk-${virtualMachineName}'
+ osType: 'Windows'
+ }
+ }
+ networkProfile: {
+ networkInterfaces: [
+ {
+ id: networkInterface.id
+ properties: {
+ deleteOption: 'Delete'
+ }
+ }
+ ]
+ }
+ diagnosticsProfile: {
+ bootDiagnostics: {
+ enabled: false
+ }
+ }
+ securityProfile: {
+ encryptionAtHost: true
+ uefiSettings: {
+ secureBootEnabled: true
+ vTpmEnabled: true
+ }
+ securityType: 'TrustedLaunch'
+ }
+ licenseType: hybridUseBenefit ? 'Windows_Server' : null
+ }
+}
+
+resource modules 'Microsoft.Compute/virtualMachines/runCommands@2023-03-01' = {
+ name: 'appAzModules'
+ location: location
+ tags: contains(tags, 'Microsoft.Compute/virtualMachines') ? tags['Microsoft.Compute/virtualMachines'] : {}
+ parent: virtualMachine
+ properties: {
+ treatFailureAsDeploymentFailure: true
+ asyncExecution: false
+ parameters: [
+ {
+ name: 'ContainerName'
+ value: containerName
+ }
+ {
+ name: 'StorageAccountName'
+ value: storageAccountName
+ }
+ {
+ name: 'StorageEndpoint'
+ value: environment().suffixes.storage
+ }
+ {
+ name: 'UserAssignedIdentityObjectId'
+ value: userAssignedIdentityPrincipalId
+ }
+ ]
+ source: {
+ script: '''
+ param(
+ [string]$ContainerName,
+ [string]$StorageAccountName,
+ [string]$StorageEndpoint,
+ [string]$UserAssignedIdentityObjectId
+ )
+ $ErrorActionPreference = "Stop"
+ $StorageAccountUrl = "https://" + $StorageAccountName + ".blob." + $StorageEndpoint + "/"
+ $TokenUri = "http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=$StorageAccountUrl&object_id=$UserAssignedIdentityObjectId"
+ $AccessToken = ((Invoke-WebRequest -Headers @{Metadata=$true} -Uri $TokenUri -UseBasicParsing).Content | ConvertFrom-Json).access_token
+ $BlobNames = @('az.accounts.2.12.1.nupkg','az.automation.1.9.0.nupkg','az.compute.5.7.0.nupkg','az.resources.6.6.0.nupkg')
+ foreach($BlobName in $BlobNames)
+ {
+ do
+ {
+ try
+ {
+ Write-Output "Download Attempt $i"
+ Invoke-WebRequest -Headers @{"x-ms-version"="2017-11-09"; Authorization ="Bearer $AccessToken"} -Uri "$StorageAccountUrl$ContainerName/$BlobName" -OutFile "$env:windir\temp\$BlobName"
+ }
+ catch [System.Net.WebException]
+ {
+ Start-Sleep -Seconds 60
+ $i++
+ if($i -gt 10){throw}
+ continue
+ }
+ catch
+ {
+ $Output = $_ | select *
+ Write-Output $Output
+ throw
+ }
+ }
+ until(Test-Path -Path $env:windir\temp\$BlobName)
+ Start-Sleep -Seconds 5
+ Unblock-File -Path $env:windir\temp\$BlobName
+ $BlobZipName = $Blobname.Replace('nupkg','zip')
+ Rename-Item -Path $env:windir\temp\$BlobName -NewName $BlobZipName
+ $BlobNameArray = $BlobName.Split('.')
+ $ModuleFolderName = $BlobNameArray[0] + '.' + $BlobNameArray[1]
+ $VersionFolderName = $BlobNameArray[2] + '.' + $BlobNameArray[3]+ '.' + $BlobNameArray[4]
+ $ModulesDirectory = "C:\Program Files\WindowsPowerShell\Modules"
+ New-Item -Path $ModulesDirectory -Name $ModuleFolderName -ItemType "Directory" -Force
+ Expand-Archive -Path $env:windir\temp\$BlobZipName -DestinationPath "$ModulesDirectory\$ModuleFolderName\$VersionFolderName" -Force
+ Remove-Item -Path "$ModulesDirectory\$ModuleFolderName\$VersionFolderName\_rels" -Force -Recurse
+ Remove-Item -Path "$ModulesDirectory\$ModuleFolderName\$VersionFolderName\package" -Force -Recurse
+ Remove-Item -LiteralPath "$ModulesDirectory\$ModuleFolderName\$VersionFolderName\[Content_Types].xml" -Force
+ Remove-Item -Path "$ModulesDirectory\$ModuleFolderName\$VersionFolderName\$ModuleFolderName.nuspec" -Force
+ }
+ Remove-Item -Path "$env:windir\temp\az*" -Force
+ '''
+ }
+ }
+}
+
+output name string = virtualMachine.name
diff --git a/src/bicep/add-ons/Imaging/modules/monitoring.bicep b/src/bicep/add-ons/Imaging/modules/monitoring.bicep
new file mode 100644
index 000000000..b5017d494
--- /dev/null
+++ b/src/bicep/add-ons/Imaging/modules/monitoring.bicep
@@ -0,0 +1,134 @@
+param actionGroupName string
+param automationAccountName string
+param distributionGroup string
+param location string
+param logAnalyticsWorkspaceResourceId string
+param tags object
+
+var alerts = [
+ {
+ name: 'Zero Trust Image Build - Failure (${automationAccountName})'
+ description: 'Sends an error alert when the runbook build fails.'
+ severity: 0
+ evaluationFrequency: 'PT5M'
+ windowSize: 'PT5M'
+ criteria: {
+ allOf: [
+ {
+ query: 'AzureDiagnostics\n| where ResourceProvider == "MICROSOFT.AUTOMATION"\n| where Category == "JobStreams"\n| where ResultDescription has "Image build failed"'
+ timeAggregation: 'Count'
+ dimensions: [
+ {
+ name: 'ResultDescription'
+ operator: 'Include'
+ values: [
+ '*'
+ ]
+ }
+ ]
+ operator: 'GreaterThanOrEqual'
+ threshold: 1
+ failingPeriods: {
+ numberOfEvaluationPeriods: 1
+ minFailingPeriodsToAlert: 1
+ }
+ }
+ ]
+ }
+ }
+ {
+ name: 'Zero Trust Image Build - Success (${automationAccountName})'
+ description: 'Sends an informational alert when the runbook build succeeds.'
+ severity: 3
+ evaluationFrequency: 'PT5M'
+ windowSize: 'PT5M'
+ criteria: {
+ allOf: [
+ {
+ query: 'AzureDiagnostics\n| where ResourceProvider == "MICROSOFT.AUTOMATION"\n| where Category == "JobStreams"\n| where ResultDescription has "Image build succeeded"'
+ timeAggregation: 'Count'
+ dimensions: [
+ {
+ name: 'ResultDescription'
+ operator: 'Include'
+ values: [
+ '*'
+ ]
+ }
+ ]
+ operator: 'GreaterThanOrEqual'
+ threshold: 1
+ failingPeriods: {
+ numberOfEvaluationPeriods: 1
+ minFailingPeriodsToAlert: 1
+ }
+ }
+ ]
+ }
+ }
+]
+
+resource automationAccount 'Microsoft.Automation/automationAccounts@2022-08-08' existing = {
+ name: automationAccountName
+}
+
+resource diagnostics 'Microsoft.Insights/diagnosticsettings@2017-05-01-preview' = {
+ scope: automationAccount
+ name: 'diag-${automationAccount.name}'
+ properties: {
+ logs: [
+ {
+ category: 'JobLogs'
+ enabled: true
+ }
+ {
+ category: 'JobStreams'
+ enabled: true
+ }
+ ]
+ workspaceId: logAnalyticsWorkspaceResourceId
+ }
+}
+
+resource actionGroup 'Microsoft.Insights/actionGroups@2022-06-01' = if (!empty(actionGroupName) && !empty(distributionGroup)) {
+ name: actionGroupName
+ location: 'global'
+ tags: contains(tags, 'Microsoft.Insights/actionGroups') ? tags['Microsoft.Insights/actionGroups'] : {}
+ properties: {
+ emailReceivers: [
+ {
+ emailAddress: distributionGroup
+ name: distributionGroup
+ useCommonAlertSchema: true
+ }
+ ]
+ enabled: true
+ groupShortName: 'Image Builds'
+ }
+}
+
+resource scheduledQueryRules 'Microsoft.Insights/scheduledQueryRules@2022-06-15' = [for i in range(0, length(alerts)): if (!empty(actionGroupName) && !empty(logAnalyticsWorkspaceResourceId)) {
+ name: alerts[i].name
+ location: location
+ tags: contains(tags, 'Microsoft.Insights/scheduledQueryRules') ? tags['Microsoft.Insights/scheduledQueryRules'] : {}
+ kind: 'LogAlert'
+ properties: {
+ actions: {
+ actionGroups: [
+ actionGroup.id
+ ]
+ }
+ autoMitigate: false
+ skipQueryValidation: false
+ criteria: alerts[i].criteria
+ description: alerts[i].description
+ displayName: alerts[i].name
+ enabled: true
+ evaluationFrequency: alerts[i].evaluationFrequency
+ severity: alerts[i].severity
+ windowSize: alerts[i].windowSize
+ scopes: [
+ logAnalyticsWorkspaceResourceId
+ ]
+ }
+}]
diff --git a/src/bicep/add-ons/Imaging/modules/removeRunCommands.bicep b/src/bicep/add-ons/Imaging/modules/removeRunCommands.bicep
new file mode 100644
index 000000000..d8d81ae87
--- /dev/null
+++ b/src/bicep/add-ons/Imaging/modules/removeRunCommands.bicep
@@ -0,0 +1,43 @@
+param containerName string
+param location string
+param tags object
+param storageAccountName string
+param storageEndpoint string
+param timestamp string = utcNow('yyyyMMddhhmmss')
+param userAssignedIdentityClientId string
+param virtualMachineName string
+
+var runCommands = [
+ 'generalizeVirtualMachine'
+ 'removeVirtualMachine'
+ 'restartVirtualMachine'
+]
+
+resource virtualMachine 'Microsoft.Compute/virtualMachines@2023-07-01' existing = {
+ name: virtualMachineName
+}
+
+resource customScriptExtension 'Microsoft.Compute/virtualMachines/extensions@2023-03-01' = {
+ parent: virtualMachine
+ name: 'CustomScriptExtension'
+ location: location
+ tags: contains(tags, 'Microsoft.Compute/virtualMachines') ? tags['Microsoft.Compute/virtualMachines'] : {}
+ properties: {
+ publisher: 'Microsoft.Compute'
+ type: 'CustomScriptExtension'
+ typeHandlerVersion: '1.10'
+ autoUpgradeMinorVersion: true
+ settings: {
+ timestamp: timestamp
+ }
+ protectedSettings: {
+ commandToExecute: 'powershell -ExecutionPolicy Unrestricted -File Remove-AzureRunCommands.ps1 -Environment ${environment().name} -ResourceGroupName ${resourceGroup().name} -RunCommands ${runCommands} -SubscriptionId ${subscription().subscriptionId} -TenantId ${tenant().tenantId} -UserAssignedIdentityClientId ${userAssignedIdentityClientId} -VirtualMachineName ${virtualMachineName}'
+ fileUris: [
+ 'https://${storageAccountName}.blob.${storageEndpoint}/${containerName}/Remove-AzureRunCommands.ps1'
+ ]
+ managedIdentity: {
+ clientId: userAssignedIdentityClientId
+ }
+ }
+ }
+}
diff --git a/src/bicep/add-ons/Imaging/modules/removeVirtualMachine.bicep b/src/bicep/add-ons/Imaging/modules/removeVirtualMachine.bicep
new file mode 100644
index 000000000..f829069d9
--- /dev/null
+++ b/src/bicep/add-ons/Imaging/modules/removeVirtualMachine.bicep
@@ -0,0 +1,80 @@
+param enableBuildAutomation bool
+param imageVirtualMachineName string
+param location string = resourceGroup().location
+param tags object
+param userAssignedIdentityClientId string
+param virtualMachineName string
+
+resource imageVirtualMachine 'Microsoft.Compute/virtualMachines@2022-03-01' existing = {
+ name: imageVirtualMachineName
+}
+
+resource virtualMachine 'Microsoft.Compute/virtualMachines@2022-03-01' existing = {
+ name: virtualMachineName
+}
+
+resource removeVirtualMachine 'Microsoft.Compute/virtualMachines/runCommands@2023-03-01' = {
+ parent: virtualMachine
+ name: 'removeVirtualMachine'
+ location: location
+ tags: contains(tags, 'Microsoft.Compute/virtualMachines') ? tags['Microsoft.Compute/virtualMachines'] : {}
+ properties: {
+ treatFailureAsDeploymentFailure: true
+ asyncExecution: enableBuildAutomation ? false : true
+ parameters: [
+ {
+ name: 'EnableBuildAutomation'
+ value: string(enableBuildAutomation)
+ }
+ {
+ name: 'Environment'
+ value: environment().name
+ }
+ {
+ name: 'ImageVmName'
+ value: imageVirtualMachine.name
+ }
+ {
+ name: 'ManagementVmName'
+ value: virtualMachine.name
+ }
+ {
+ name: 'ResourceGroupName'
+ value: resourceGroup().name
+ }
+ {
+ name: 'SubscriptionId'
+ value: subscription().subscriptionId
+ }
+ {
+ name: 'TenantId'
+ value: tenant().tenantId
+ }
+ {
+ name: 'UserAssignedIdentityClientId'
+ value: userAssignedIdentityClientId
+ }
+ ]
+ source: {
+ script: '''
+ param(
+ [string]$EnableBuildAutomation,
+ [string]$Environment,
+ [string]$ImageVmName,
+ [string]$ManagementVmName,
+ [string]$ResourceGroupName,
+ [string]$SubscriptionId,
+ [string]$TenantId,
+ [string]$UserAssignedIdentityClientId
+ )
+ $ErrorActionPreference = 'Stop'
+ Connect-AzAccount -Environment $Environment -Tenant $TenantId -Subscription $SubscriptionId -Identity -AccountId $UserAssignedIdentityClientId | Out-Null
+ Remove-AzVM -ResourceGroupName $ResourceGroupName -Name $ImageVmName -Force
+ if($EnableBuildAutomation -eq 'false')
+ {
+ Remove-AzVM -ResourceGroupName $ResourceGroupName -Name $ManagementVmName -NoWait -Force -AsJob
+ }
+ '''
+ }
+ }
+}
diff --git a/src/bicep/add-ons/Imaging/modules/restartVirtualMachine.bicep b/src/bicep/add-ons/Imaging/modules/restartVirtualMachine.bicep
new file mode 100644
index 000000000..b168ff35e
--- /dev/null
+++ b/src/bicep/add-ons/Imaging/modules/restartVirtualMachine.bicep
@@ -0,0 +1,73 @@
+param imageVirtualMachineName string
+param resourceGroupName string
+param location string
+param tags object
+param userAssignedIdentityClientId string
+param virtualMachineName string
+
+resource imageVirtualMachine 'Microsoft.Compute/virtualMachines@2022-03-01' existing = {
+ scope: resourceGroup(resourceGroupName)
+ name: imageVirtualMachineName
+}
+
+resource virtualMachine 'Microsoft.Compute/virtualMachines@2022-03-01' existing = {
+ name: virtualMachineName
+}
+
+resource restartVirtualMachine 'Microsoft.Compute/virtualMachines/runCommands@2023-03-01' = {
+ name: 'restartVirtualMachine'
+ location: location
+ tags: contains(tags, 'Microsoft.Compute/virtualMachines') ? tags['Microsoft.Compute/virtualMachines'] : {}
+ parent: virtualMachine
+ properties: {
+ treatFailureAsDeploymentFailure: true
+ asyncExecution: false
+ parameters: [
+ {
+ name: 'Environment'
+ value: environment().name
+ }
+ {
+ name: 'ResourceGroupName'
+ value: resourceGroupName
+ }
+ {
+ name: 'SubscriptionId'
+ value: subscription().subscriptionId
+ }
+ {
+ name: 'TenantId'
+ value: tenant().tenantId
+ }
+ {
+ name: 'UserAssignedIdentityClientId'
+ value: userAssignedIdentityClientId
+ }
+ {
+ name: 'VirtualMachineName'
+ value: imageVirtualMachine.name
+ }
+ ]
+ source: {
+ script: '''
+ param(
+ [string]$Environment,
+ [string]$ResourceGroupName,
+ [string]$SubscriptionId,
+ [string]$TenantId,
+ [string]$UserAssignedIdentityClientId,
+ [string]$VirtualMachineName
+ )
+ $ErrorActionPreference = 'Stop'
+ Connect-AzAccount -Environment $Environment -Tenant $TenantId -Subscription $SubscriptionId -Identity -AccountId $UserAssignedIdentityClientId | Out-Null
+ Restart-AzVM -ResourceGroupName $ResourceGroupName -Name $VirtualMachineName
+ $AgentStatus = $Null
+ while ($Null -eq $AgentStatus)
+ {
+ Start-Sleep -Seconds 5
+ $AgentStatus = (Get-AzVM -ResourceGroupName $ResourceGroupName -Name $VirtualMachineName -Status).VMAgent
+ }
+ '''
+ }
+ }
+}
diff --git a/src/bicep/add-ons/Imaging/modules/roleAssignments.bicep b/src/bicep/add-ons/Imaging/modules/roleAssignments.bicep
new file mode 100644
index 000000000..ff1b6dfe2
--- /dev/null
+++ b/src/bicep/add-ons/Imaging/modules/roleAssignments.bicep
@@ -0,0 +1,17 @@
+param principalId string
+
+var roleDefinitionIds = [
+ 'f353d9bd-d4a6-484e-a77a-8050b599b867' // Automation Contributor | https://learn.microsoft.com/en-us/azure/role-based-access-control/built-in-roles#automation-contributor
+ 'f1a07417-d97a-45cb-824c-7a7467783830' // Managed Identity Operator | https://learn.microsoft.com/en-us/azure/role-based-access-control/built-in-roles#managed-identity-operator
+ 'acdd72a7-3385-48ef-bd42-f606fba81ae7' // Reader | https://learn.microsoft.com/en-us/azure/role-based-access-control/built-in-roles#reader
+ '9980e02c-c2be-4d73-94e8-173b1dc7cf3c' // Virtual Machine Contributor | https://learn.microsoft.com/en-us/azure/role-based-access-control/built-in-roles#virtual-machine-contributor
+]
+
+resource roleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for roleDefinitionId in roleDefinitionIds: {
+ name: guid(principalId, roleDefinitionId, resourceGroup().name)
+ properties: {
+ roleDefinitionId: resourceId('Microsoft.Authorization/roleDefinitions', roleDefinitionId)
+ principalId: principalId
+ principalType: 'ServicePrincipal'
+ }
+}]
diff --git a/src/bicep/add-ons/Imaging/modules/spoke-network-peering.bicep b/src/bicep/add-ons/Imaging/modules/spoke-network-peering.bicep
new file mode 100644
index 000000000..060677eff
--- /dev/null
+++ b/src/bicep/add-ons/Imaging/modules/spoke-network-peering.bicep
@@ -0,0 +1,22 @@
+/*
+Copyright (c) Microsoft Corporation.
+Licensed under the MIT License.
+*/
+
+targetScope = 'subscription'
+
+param spokeName string
+param spokeResourceGroupName string
+param spokeVirtualNetworkName string
+
+param hubVirtualNetworkName string
+param hubVirtualNetworkResourceId string
+
+module spokeNetworkPeering './virtual-network-peerings.bicep' = {
+ name: '${spokeName}-to-hub-vnet-peering'
+ scope: resourceGroup(spokeResourceGroupName)
+ params: {
+ name: '${spokeVirtualNetworkName}/to-${hubVirtualNetworkName}'
+ remoteVirtualNetworkResourceId: hubVirtualNetworkResourceId
+ }
+}
diff --git a/src/bicep/add-ons/Imaging/modules/storageAccount.bicep b/src/bicep/add-ons/Imaging/modules/storageAccount.bicep
new file mode 100644
index 000000000..ede6b3954
--- /dev/null
+++ b/src/bicep/add-ons/Imaging/modules/storageAccount.bicep
@@ -0,0 +1,18 @@
+param principalId string
+param storageAccountResourceId string
+
+var roleDefinitionId = '2a2b9908-6ea1-4ae2-8e65-a410df84e7d1' // Storage Blob Data Reader | https://learn.microsoft.com/en-us/azure/role-based-access-control/built-in-roles#storage-blob-data-reader
+
+resource storageAccount 'Microsoft.Storage/storageAccounts@2023-01-01' existing = {
+ name: split(storageAccountResourceId, '/')[8]
+}
+
+resource roleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
+ scope: storageAccount
+ name: guid(principalId, roleDefinitionId, storageAccountResourceId)
+ properties: {
+ roleDefinitionId: resourceId('Microsoft.Authorization/roleDefinitions', roleDefinitionId)
+ principalId: principalId
+ principalType: 'ServicePrincipal'
+ }
+}
diff --git a/src/bicep/add-ons/Imaging/modules/sysprepVirtualMachine.bicep b/src/bicep/add-ons/Imaging/modules/sysprepVirtualMachine.bicep
new file mode 100644
index 000000000..dacf1182b
--- /dev/null
+++ b/src/bicep/add-ons/Imaging/modules/sysprepVirtualMachine.bicep
@@ -0,0 +1,29 @@
+targetScope = 'resourceGroup'
+
+param location string
+param tags object
+param virtualMachineName string
+
+resource virtualMachine 'Microsoft.Compute/virtualMachines@2022-11-01' existing = {
+ name: virtualMachineName
+}
+
+resource sysprepVirtualMachine 'Microsoft.Compute/virtualMachines/runCommands@2023-03-01' = {
+ parent: virtualMachine
+ name: 'sysprepVirtualMachine'
+ location: location
+ tags: contains(tags, 'Microsoft.Compute/virtualMachines') ? tags['Microsoft.Compute/virtualMachines'] : {}
+ properties: {
+ treatFailureAsDeploymentFailure: false
+ asyncExecution: true
+ parameters: []
+ source: {
+ script: '''
+ Start-Sleep -Seconds 30
+ Remove-Item -LiteralPath 'C:\Windows\Panther' -Force -Recurse -ErrorAction SilentlyContinue
+ Set-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Services\cdrom' -Name 'Start' -Value 1
+ Start-Process -File 'C:\Windows\System32\Sysprep\Sysprep.exe' -ArgumentList '/generalize /oobe /shutdown /mode:vm'
+ '''
+ }
+ }
+}
diff --git a/src/bicep/add-ons/Imaging/modules/templateSpec.bicep b/src/bicep/add-ons/Imaging/modules/templateSpec.bicep
new file mode 100644
index 000000000..028e95052
--- /dev/null
+++ b/src/bicep/add-ons/Imaging/modules/templateSpec.bicep
@@ -0,0 +1,25 @@
+param imageDefinitionName string
+param location string
+param tags object
+
+resource templateSpec 'Microsoft.Resources/templateSpecs@2022-02-01' = {
+ name: 'ts-${imageDefinitionName}'
+ location: location
+ tags: contains(tags, 'Microsoft.Resources/templateSpecs') ? tags['Microsoft.Resources/templateSpecs'] : {}
+ properties: {
+ description: 'An automation runbook deploys a new image version for the "${imageDefinitionName}" image definition from this template spec.'
+ displayName: 'Zero Trust Image Build Automation: ${imageDefinitionName}'
+ }
+}
+
+resource version 'Microsoft.Resources/templateSpecs/versions@2022-02-01' = {
+ parent: templateSpec
+ name: '1.0'
+ location: location
+ tags: contains(tags, 'Microsoft.Resources/templateSpecs') ? tags['Microsoft.Resources/templateSpecs'] : {}
+ properties: {
+ mainTemplate: loadJsonContent('imageBuild.json')
+ }
+}
+
+output resourceId string = version.id
diff --git a/src/bicep/add-ons/Imaging/modules/tier3.bicep b/src/bicep/add-ons/Imaging/modules/tier3.bicep
new file mode 100644
index 000000000..1c67fd110
--- /dev/null
+++ b/src/bicep/add-ons/Imaging/modules/tier3.bicep
@@ -0,0 +1,199 @@
+/*
+Copyright (c) Microsoft Corporation.
+Licensed under the MIT License.
+*/
+targetScope = 'resourceGroup'
+/*
+
+ PARAMETERS
+
+ Here are all the parameters a user can override.
+
+ These are the required parameters that Mission LZ Tier 3 workload does not provide a default for:
+ - resourcePrefix
+
+*/
+
+// REQUIRED PARAMETERS
+
+@minLength(3)
+@maxLength(10)
+@description('A prefix, 3 to 10 characters in length, to append to resource names (e.g. "dev", "test", "prod", "mlz"). It defaults to "mlz".')
+param resourcePrefix string = 'zta'
+
+@minLength(3)
+@maxLength(6)
+@description('A suffix, 3 to 6 characters in length, to append to resource names (e.g. "dev", "test", "prod", "mlz"). It defaults to "mlz".')
+param resourceSuffix string = 'mlz'
+
+param deployDefender bool
+param deploymentNameSuffix string = utcNow()
+param deployPolicy bool
+param emailSecurityContact string
+param existingResourceGroup bool
+param firewallPrivateIPAddress string
+param hubResourceGroupName string
+param hubSubscriptionId string
+param hubVirtualNetworkName string
+param hubVirtualNetworkResourceId string
+param location string
+param logAnalyticsWorkspaceName string
+param logAnalyticsWorkspaceResourceId string
+param logStorageSkuName string = 'Standard_GRS'
+param networkSecurityGroupDiagnosticsMetrics array = []
+param networkSecurityGroupRules array = []
+param policy string
+param resourceGroupName string
+param subnetAddressPrefix string
+param subnetServiceEndpoints array = []
+param tags object = {}
+param virtualNetworkAddressPrefix string
+param virtualNetworkDiagnosticsLogs array = []
+param virtualNetworkDiagnosticsMetrics array = []
+param vNetDnsServers array = [firewallPrivateIPAddress]
+param workloadLogStorageAccountNameParameter string = 'null'
+param workloadName string = 'zta'
+param workloadSubscriptionId string
+@description('An array of Network Security Group diagnostic logs to apply to the workload Virtual Network. See https://docs.microsoft.com/en-us/azure/virtual-network/virtual-network-nsg-manage-log#log-categories for valid settings.')
+param networkSecurityGroupDiagnosticsLogs array = [
+ {
+ category: 'NetworkSecurityGroupEvent'
+ enabled: true
+ }
+ {
+ category: 'NetworkSecurityGroupRuleCounter'
+ enabled: true
+ }
+]
+
+
+/*
+
+ NAMING CONVENTION
+
+ Here we define a naming conventions for resources.
+
+ First, we take `resourcePrefix` and `resourceSuffix` by params.
+ Then, using string interpolation "${}", we insert those values into a naming convention.
+
+*/
+
+var resourceToken = 'resource_token'
+var nameToken = 'name_token'
+var namingConvention = '${toLower(resourcePrefix)}-${resourceToken}-${nameToken}-${toLower(resourceSuffix)}'
+var virtualNetworkNamingConvention = replace(namingConvention, resourceToken, 'vnet')
+var networkSecurityGroupNamingConvention = replace(namingConvention, resourceToken, 'nsg')
+var storageAccountNamingConvention = toLower('${resourcePrefix}st${nameToken}unique_storage_token')
+var subnetNamingConvention = replace(namingConvention, resourceToken, 'snet')
+var workloadLogStorageAccountNameTemplate = replace(storageAccountNamingConvention, nameToken, toLower(workloadName))
+var workloadLogStorageAccountUniqueName = replace(workloadLogStorageAccountNameTemplate, 'unique_storage_token', uniqueString(resourcePrefix, resourceSuffix, workloadSubscriptionId))
+var workloadLogStorageAccountNameVariable = take(workloadLogStorageAccountUniqueName, 23)
+var workloadVirtualNetworkName = replace(virtualNetworkNamingConvention, nameToken, workloadName)
+var workloadNetworkSecurityGroupName = replace(networkSecurityGroupNamingConvention, nameToken, workloadName)
+var workloadSubnetName = replace(subnetNamingConvention, nameToken, workloadName)
+var logAnalyticsWorkspaceResourceId_split = split(logAnalyticsWorkspaceResourceId, '/')
+var workloadLogStorageAccountName = 'null' != workloadLogStorageAccountNameParameter ? workloadLogStorageAccountNameParameter : workloadLogStorageAccountNameVariable
+var defaultTags = {
+ DeploymentType: 'MissionLandingZoneARM'
+}
+var calculatedTags = union(tags, defaultTags)
+
+
+resource rg 'Microsoft.Resources/resourceGroups@2021-04-01' existing = {
+ name: resourceGroupName
+ scope: subscription(workloadSubscriptionId)
+}
+
+module spokeNetwork '../../../core/spoke-network.bicep' = {
+ name: 'spokeNetwork'
+ scope: az.resourceGroup(workloadSubscriptionId, (existingResourceGroup ? rg.name : resourceGroupName))
+ params: {
+ tags: calculatedTags
+ location:location
+ logStorageAccountName: workloadLogStorageAccountName
+ logStorageSkuName: logStorageSkuName
+ logAnalyticsWorkspaceResourceId: logAnalyticsWorkspaceResourceId
+ firewallPrivateIPAddress: firewallPrivateIPAddress
+ virtualNetworkName: workloadVirtualNetworkName
+ virtualNetworkAddressPrefix: virtualNetworkAddressPrefix
+ vNetDnsServers: vNetDnsServers
+ virtualNetworkDiagnosticsLogs: virtualNetworkDiagnosticsLogs
+ virtualNetworkDiagnosticsMetrics: virtualNetworkDiagnosticsMetrics
+ networkSecurityGroupName: workloadNetworkSecurityGroupName
+ networkSecurityGroupRules: networkSecurityGroupRules
+ networkSecurityGroupDiagnosticsLogs: networkSecurityGroupDiagnosticsLogs
+ networkSecurityGroupDiagnosticsMetrics: networkSecurityGroupDiagnosticsMetrics
+ subnetName: workloadSubnetName
+ subnetAddressPrefix: subnetAddressPrefix
+ subnetServiceEndpoints: subnetServiceEndpoints
+ subnetPrivateEndpointNetworkPolicies: 'Disabled'
+ subnetPrivateLinkServiceNetworkPolicies: 'Disabled'
+ }
+}
+
+module workloadVirtualNetworkPeerings './spoke-network-peering.bicep' = {
+ name: take('${workloadName}-to-hub-vnet-peering', 64)
+ scope: subscription(workloadSubscriptionId)
+ params: {
+ spokeName: workloadName
+ spokeResourceGroupName: (existingResourceGroup ? rg.name : resourceGroupName)
+ spokeVirtualNetworkName: spokeNetwork.outputs.virtualNetworkName
+ hubVirtualNetworkName: hubVirtualNetworkName
+ hubVirtualNetworkResourceId: hubVirtualNetworkResourceId
+ }
+}
+
+module hubToWorkloadVirtualNetworkPeering './hub-network-peering.bicep' = {
+ scope: az.resourceGroup(workloadSubscriptionId, (existingResourceGroup ? rg.name : resourceGroupName))
+ name: take('hub-to-${workloadName}-vnet-peering', 64)
+ params: {
+ hubVirtualNetworkName: hubVirtualNetworkName
+ hubResourceGroupName: hubResourceGroupName
+ spokeVirtualNetworkName: spokeNetwork.outputs.virtualNetworkName
+ spokeVirtualNetworkResourceId: spokeNetwork.outputs.virtualNetworkResourceId
+ }
+}
+
+module workloadSubscriptionActivityLogging '../../../modules/central-logging.bicep' = if (workloadSubscriptionId != hubSubscriptionId) {
+ name: 'activity-logs-${spokeNetwork.name}-${resourceSuffix}'
+ scope: subscription(workloadSubscriptionId)
+ params: {
+ diagnosticSettingName: 'log-${spokeNetwork.name}-sub-activity-to-${logAnalyticsWorkspaceName}'
+ logAnalyticsWorkspaceId: logAnalyticsWorkspaceResourceId
+ }
+ dependsOn: [
+ spokeNetwork
+ ]
+}
+
+module workloadPolicyAssignment '../../../modules/policy-assignment.bicep' = if (deployPolicy) {
+ name: 'assign-policy-${workloadName}-${deploymentNameSuffix}'
+ scope: az.resourceGroup(workloadSubscriptionId, (existingResourceGroup ? rg.name : resourceGroupName))
+ params: {
+ builtInAssignment: policy
+ logAnalyticsWorkspaceName: logAnalyticsWorkspaceResourceId_split[8]
+ logAnalyticsWorkspaceResourceGroupName: logAnalyticsWorkspaceResourceId_split[4]
+ location: location
+ operationsSubscriptionId: logAnalyticsWorkspaceResourceId_split[2]
+ }
+ }
+
+module spokeDefender '../../../modules/defender.bicep' = if (deployDefender) {
+ name: 'set-${workloadName}-sub-defender'
+ scope: subscription(workloadSubscriptionId)
+ params: {
+ logAnalyticsWorkspaceId: logAnalyticsWorkspaceResourceId
+ emailSecurityContact: emailSecurityContact
+ }
+}
+
+output rg string = (existingResourceGroup ? rg.name : resourceGroupName)
+output location string = location
+output virtualNetworkName string = spokeNetwork.outputs.virtualNetworkName
+output virtualNetworkAddressPrefix string = spokeNetwork.outputs.virtualNetworkAddressPrefix
+output virtualNetworkResourceId string = spokeNetwork.outputs.virtualNetworkResourceId
+output subnetName string = spokeNetwork.outputs.subnetName
+output subnetAddressPrefix string = spokeNetwork.outputs.subnetAddressPrefix
+output subnetResourceId string = spokeNetwork.outputs.subnetResourceId
+output networkSecurityGroupName string = spokeNetwork.outputs.networkSecurityGroupName
+output networkSecurityGroupResourceId string = spokeNetwork.outputs.networkSecurityGroupResourceId
diff --git a/src/bicep/add-ons/Imaging/modules/tier3.json b/src/bicep/add-ons/Imaging/modules/tier3.json
new file mode 100644
index 000000000..025583ec2
--- /dev/null
+++ b/src/bicep/add-ons/Imaging/modules/tier3.json
@@ -0,0 +1,1683 @@
+{
+ "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
+ "contentVersion": "1.0.0.0",
+ "metadata": {
+ "_generator": {
+ "name": "bicep",
+ "version": "0.24.24.22086",
+ "templateHash": "12438304025953191912"
+ }
+ },
+ "parameters": {
+ "resourcePrefix": {
+ "type": "string",
+ "defaultValue": "zta",
+ "minLength": 3,
+ "maxLength": 10,
+ "metadata": {
+ "description": "A prefix, 3 to 10 characters in length, to append to resource names (e.g. \"dev\", \"test\", \"prod\", \"mlz\"). It defaults to \"mlz\"."
+ }
+ },
+ "resourceSuffix": {
+ "type": "string",
+ "defaultValue": "mlz",
+ "minLength": 3,
+ "maxLength": 6,
+ "metadata": {
+ "description": "A suffix, 3 to 6 characters in length, to append to resource names (e.g. \"dev\", \"test\", \"prod\", \"mlz\"). It defaults to \"mlz\"."
+ }
+ },
+ "location": {
+ "type": "string",
+ "metadata": {
+ "description": "The region to deploy resources into. It defaults to the deployment location."
+ }
+ },
+ "workloadSubscriptionId": {
+ "type": "string",
+ "metadata": {
+ "description": "The subscription ID for the Identity Network and resources. It defaults to the deployment subscription."
+ }
+ },
+ "hubSubscriptionId": {
+ "type": "string",
+ "metadata": {
+ "description": "MLZ Deployment output variables in json format. It defaults to the deploymentVariables.json."
+ }
+ },
+ "hubVirtualNetworkName": {
+ "type": "string",
+ "metadata": {
+ "description": "The name of the hub virtual network. It defaults to the deployment output variable."
+ }
+ },
+ "hubVirtualNetworkResourceId": {
+ "type": "string",
+ "metadata": {
+ "description": "The resource ID of the hub virtual network. It defaults to the deployment output variable."
+ }
+ },
+ "logAnalyticsWorkspaceResourceId": {
+ "type": "string",
+ "metadata": {
+ "description": "The resource ID of the log analytics workspace. It defaults to the deployment output variable."
+ }
+ },
+ "logAnalyticsWorkspaceName": {
+ "type": "string",
+ "metadata": {
+ "description": "The name of the log analytics workspace. It defaults to the deployment output variable."
+ }
+ },
+ "firewallPrivateIPAddress": {
+ "type": "string",
+ "metadata": {
+ "description": "The private IP address of the firewall. It defaults to the deployment output variable."
+ }
+ },
+ "policy": {
+ "type": "string",
+ "defaultValue": "NISTRev4",
+ "metadata": {
+ "description": "[NISTRev4/NISTRev5/IL5/CMMC] Built-in policy assignments to assign, it defaults to \"NISTRev4\". IL5 is only available for AzureUsGovernment and will switch to NISTRev4 if tried in AzureCloud."
+ }
+ },
+ "deployPolicy": {
+ "type": "bool",
+ "metadata": {
+ "description": "When set to \"true\", deploys the Azure Policy set defined at by the parameter \"policy\" to the resource groups generated in the deployment. It defaults to \"false\"."
+ }
+ },
+ "deployDefender": {
+ "type": "bool",
+ "metadata": {
+ "description": "When set to \"true\", enables Microsoft Defender for Cloud for the subscriptions used in the deployment. It defaults to \"false\"."
+ }
+ },
+ "emailSecurityContact": {
+ "type": "string",
+ "metadata": {
+ "description": "Email address of the contact, in the form of john@doe.com"
+ }
+ },
+ "virtualNetworkAddressPrefix": {
+ "type": "string",
+ "metadata": {
+ "description": "The address prefix for the network spoke vnet."
+ }
+ },
+ "virtualNetworkDiagnosticsLogs": {
+ "type": "array",
+ "defaultValue": [],
+ "metadata": {
+ "description": "An array of Network Diagnostic Logs to enable for the workload Virtual Network. See https://docs.microsoft.com/en-us/azure/azure-monitor/essentials/diagnostic-settings?tabs=CMD#logs for valid settings."
+ }
+ },
+ "virtualNetworkDiagnosticsMetrics": {
+ "type": "array",
+ "defaultValue": [],
+ "metadata": {
+ "description": "An array of Network Diagnostic Metrics to enable for the workload Virtual Network. See https://docs.microsoft.com/en-us/azure/azure-monitor/essentials/diagnostic-settings?tabs=CMD#metrics for valid settings."
+ }
+ },
+ "vNetDnsServers": {
+ "type": "array",
+ "defaultValue": [
+ "[parameters('firewallPrivateIPAddress')]"
+ ]
+ },
+ "networkSecurityGroupRules": {
+ "type": "array",
+ "defaultValue": [],
+ "metadata": {
+ "description": "An array of Network Security Group rules to apply to the workload Virtual Network. See https://docs.microsoft.com/en-us/azure/templates/microsoft.network/networksecuritygroups/securityrules?tabs=bicep#securityrulepropertiesformat for valid settings."
+ }
+ },
+ "networkSecurityGroupDiagnosticsLogs": {
+ "type": "array",
+ "defaultValue": [
+ {
+ "category": "NetworkSecurityGroupEvent",
+ "enabled": true
+ },
+ {
+ "category": "NetworkSecurityGroupRuleCounter",
+ "enabled": true
+ }
+ ],
+ "metadata": {
+ "description": "An array of Network Security Group diagnostic logs to apply to the workload Virtual Network. See https://docs.microsoft.com/en-us/azure/virtual-network/virtual-network-nsg-manage-log#log-categories for valid settings."
+ }
+ },
+ "networkSecurityGroupDiagnosticsMetrics": {
+ "type": "array",
+ "defaultValue": [],
+ "metadata": {
+ "description": "An array of Network Security Group diagnostic logs to apply to the SharedServices Virtual Network. See https://docs.microsoft.com/en-us/azure/virtual-network/virtual-network-nsg-manage-log#log-categories for valid settings."
+ }
+ },
+ "subnetAddressPrefix": {
+ "type": "string",
+ "metadata": {
+ "description": "The CIDR Virtual Network Address Prefix for the Workload Virtual Network."
+ }
+ },
+ "subnetServiceEndpoints": {
+ "type": "array",
+ "defaultValue": [],
+ "metadata": {
+ "description": "An array of Service Endpoints to enable for the Operations subnet. See https://docs.microsoft.com/en-us/azure/virtual-network/virtual-network-service-endpoints-overview for valid settings."
+ }
+ },
+ "logStorageSkuName": {
+ "type": "string",
+ "defaultValue": "Standard_GRS",
+ "metadata": {
+ "description": "The Storage Account SKU to use for log storage. It defaults to \"Standard_GRS\". See https://docs.microsoft.com/en-us/rest/api/storagerp/srp_sku_types for valid settings."
+ }
+ },
+ "tags": {
+ "type": "object",
+ "defaultValue": {},
+ "metadata": {
+ "description": "A string dictionary of tags to add to deployed resources. See https://docs.microsoft.com/en-us/azure/azure-resource-manager/management/tag-resources?tabs=json#arm-templates for valid settings."
+ }
+ },
+ "deploymentNameSuffix": {
+ "type": "string",
+ "defaultValue": "[utcNow()]",
+ "metadata": {
+ "description": "A suffix to use for naming deployments uniquely. It defaults to the Bicep resolution of the \"utcNow()\" function."
+ }
+ },
+ "workloadName": {
+ "type": "string",
+ "defaultValue": "ZTA",
+ "metadata": {
+ "description": "The name of the tier 3 workload"
+ }
+ },
+ "workloadLogStorageAccountNameParameter": {
+ "type": "string",
+ "defaultValue": "null",
+ "maxLength": 24,
+ "metadata": {
+ "description": "The name of the Storage Account if using this Parameter. Otherwise it will be a calculated value."
+ }
+ },
+ "existingResourceGroup": {
+ "type": "bool"
+ },
+ "resourceGroupName": {
+ "type": "string"
+ },
+ "hubResourceGroupName": {
+ "type": "string"
+ }
+ },
+ "variables": {
+ "resourceToken": "resource_token",
+ "nameToken": "name_token",
+ "namingConvention": "[format('{0}-{1}-{2}-{3}', toLower(parameters('resourcePrefix')), variables('resourceToken'), variables('nameToken'), toLower(parameters('resourceSuffix')))]",
+ "virtualNetworkNamingConvention": "[replace(variables('namingConvention'), variables('resourceToken'), 'vnet')]",
+ "networkSecurityGroupNamingConvention": "[replace(variables('namingConvention'), variables('resourceToken'), 'nsg')]",
+ "storageAccountNamingConvention": "[toLower(format('{0}st{1}unique_storage_token', parameters('resourcePrefix'), variables('nameToken')))]",
+ "subnetNamingConvention": "[replace(variables('namingConvention'), variables('resourceToken'), 'snet')]",
+ "workloadLogStorageAccountNameTemplate": "[replace(variables('storageAccountNamingConvention'), variables('nameToken'), toLower(parameters('workloadName')))]",
+ "workloadLogStorageAccountUniqueName": "[replace(variables('workloadLogStorageAccountNameTemplate'), 'unique_storage_token', uniqueString(parameters('resourcePrefix'), parameters('resourceSuffix'), parameters('workloadSubscriptionId')))]",
+ "workloadLogStorageAccountNameVariable": "[take(variables('workloadLogStorageAccountUniqueName'), 23)]",
+ "workloadVirtualNetworkName": "[replace(variables('virtualNetworkNamingConvention'), variables('nameToken'), parameters('workloadName'))]",
+ "workloadNetworkSecurityGroupName": "[replace(variables('networkSecurityGroupNamingConvention'), variables('nameToken'), parameters('workloadName'))]",
+ "workloadSubnetName": "[replace(variables('subnetNamingConvention'), variables('nameToken'), parameters('workloadName'))]",
+ "logAnalyticsWorkspaceResourceId_split": "[split(parameters('logAnalyticsWorkspaceResourceId'), '/')]",
+ "workloadLogStorageAccountName": "[if(not(equals('null', parameters('workloadLogStorageAccountNameParameter'))), parameters('workloadLogStorageAccountNameParameter'), variables('workloadLogStorageAccountNameVariable'))]",
+ "defaultTags": {
+ "DeploymentType": "MissionLandingZoneARM"
+ },
+ "calculatedTags": "[union(parameters('tags'), variables('defaultTags'))]"
+ },
+ "resources": [
+ {
+ "type": "Microsoft.Resources/deployments",
+ "apiVersion": "2022-09-01",
+ "name": "spokeNetwork",
+ "subscriptionId": "[parameters('workloadSubscriptionId')]",
+ "resourceGroup": "[if(parameters('existingResourceGroup'), parameters('resourceGroupName'), parameters('resourceGroupName'))]",
+ "properties": {
+ "expressionEvaluationOptions": {
+ "scope": "inner"
+ },
+ "mode": "Incremental",
+ "parameters": {
+ "tags": {
+ "value": "[variables('calculatedTags')]"
+ },
+ "location": {
+ "value": "[parameters('location')]"
+ },
+ "logStorageAccountName": {
+ "value": "[variables('workloadLogStorageAccountName')]"
+ },
+ "logStorageSkuName": {
+ "value": "[parameters('logStorageSkuName')]"
+ },
+ "logAnalyticsWorkspaceResourceId": {
+ "value": "[parameters('logAnalyticsWorkspaceResourceId')]"
+ },
+ "firewallPrivateIPAddress": {
+ "value": "[parameters('firewallPrivateIPAddress')]"
+ },
+ "virtualNetworkName": {
+ "value": "[variables('workloadVirtualNetworkName')]"
+ },
+ "virtualNetworkAddressPrefix": {
+ "value": "[parameters('virtualNetworkAddressPrefix')]"
+ },
+ "vNetDnsServers": {
+ "value": "[parameters('vNetDnsServers')]"
+ },
+ "virtualNetworkDiagnosticsLogs": {
+ "value": "[parameters('virtualNetworkDiagnosticsLogs')]"
+ },
+ "virtualNetworkDiagnosticsMetrics": {
+ "value": "[parameters('virtualNetworkDiagnosticsMetrics')]"
+ },
+ "networkSecurityGroupName": {
+ "value": "[variables('workloadNetworkSecurityGroupName')]"
+ },
+ "networkSecurityGroupRules": {
+ "value": "[parameters('networkSecurityGroupRules')]"
+ },
+ "networkSecurityGroupDiagnosticsLogs": {
+ "value": "[parameters('networkSecurityGroupDiagnosticsLogs')]"
+ },
+ "networkSecurityGroupDiagnosticsMetrics": {
+ "value": "[parameters('networkSecurityGroupDiagnosticsMetrics')]"
+ },
+ "subnetName": {
+ "value": "[variables('workloadSubnetName')]"
+ },
+ "subnetAddressPrefix": {
+ "value": "[parameters('subnetAddressPrefix')]"
+ },
+ "subnetServiceEndpoints": {
+ "value": "[parameters('subnetServiceEndpoints')]"
+ },
+ "subnetPrivateEndpointNetworkPolicies": {
+ "value": "Disabled"
+ },
+ "subnetPrivateLinkServiceNetworkPolicies": {
+ "value": "Disabled"
+ }
+ },
+ "template": {
+ "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
+ "contentVersion": "1.0.0.0",
+ "metadata": {
+ "_generator": {
+ "name": "bicep",
+ "version": "0.24.24.22086",
+ "templateHash": "3636586928348301463"
+ }
+ },
+ "parameters": {
+ "location": {
+ "type": "string",
+ "defaultValue": "[resourceGroup().location]"
+ },
+ "tags": {
+ "type": "object",
+ "defaultValue": {}
+ },
+ "logStorageAccountName": {
+ "type": "string"
+ },
+ "logStorageSkuName": {
+ "type": "string"
+ },
+ "logAnalyticsWorkspaceResourceId": {
+ "type": "string"
+ },
+ "firewallPrivateIPAddress": {
+ "type": "string"
+ },
+ "virtualNetworkName": {
+ "type": "string"
+ },
+ "virtualNetworkAddressPrefix": {
+ "type": "string"
+ },
+ "virtualNetworkDiagnosticsLogs": {
+ "type": "array"
+ },
+ "virtualNetworkDiagnosticsMetrics": {
+ "type": "array"
+ },
+ "vNetDnsServers": {
+ "type": "array"
+ },
+ "networkSecurityGroupName": {
+ "type": "string"
+ },
+ "networkSecurityGroupRules": {
+ "type": "array"
+ },
+ "networkSecurityGroupDiagnosticsLogs": {
+ "type": "array"
+ },
+ "networkSecurityGroupDiagnosticsMetrics": {
+ "type": "array"
+ },
+ "subnetName": {
+ "type": "string"
+ },
+ "subnetAddressPrefix": {
+ "type": "string"
+ },
+ "subnetServiceEndpoints": {
+ "type": "array"
+ },
+ "routeTableName": {
+ "type": "string",
+ "defaultValue": "[format('{0}-routetable', parameters('subnetName'))]"
+ },
+ "routeTableRouteName": {
+ "type": "string",
+ "defaultValue": "default_route"
+ },
+ "routeTableRouteAddressPrefix": {
+ "type": "string",
+ "defaultValue": "0.0.0.0/0"
+ },
+ "routeTableRouteNextHopIpAddress": {
+ "type": "string",
+ "defaultValue": "[parameters('firewallPrivateIPAddress')]"
+ },
+ "routeTableRouteNextHopType": {
+ "type": "string",
+ "defaultValue": "VirtualAppliance"
+ },
+ "subnetPrivateEndpointNetworkPolicies": {
+ "type": "string"
+ },
+ "subnetPrivateLinkServiceNetworkPolicies": {
+ "type": "string"
+ }
+ },
+ "resources": [
+ {
+ "type": "Microsoft.Resources/deployments",
+ "apiVersion": "2022-09-01",
+ "name": "logStorage",
+ "properties": {
+ "expressionEvaluationOptions": {
+ "scope": "inner"
+ },
+ "mode": "Incremental",
+ "parameters": {
+ "storageAccountName": {
+ "value": "[parameters('logStorageAccountName')]"
+ },
+ "location": {
+ "value": "[parameters('location')]"
+ },
+ "skuName": {
+ "value": "[parameters('logStorageSkuName')]"
+ },
+ "tags": {
+ "value": "[parameters('tags')]"
+ }
+ },
+ "template": {
+ "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
+ "contentVersion": "1.0.0.0",
+ "metadata": {
+ "_generator": {
+ "name": "bicep",
+ "version": "0.24.24.22086",
+ "templateHash": "11432560412215968310"
+ }
+ },
+ "parameters": {
+ "storageAccountName": {
+ "type": "string"
+ },
+ "location": {
+ "type": "string"
+ },
+ "skuName": {
+ "type": "string"
+ },
+ "tags": {
+ "type": "object",
+ "defaultValue": {}
+ }
+ },
+ "resources": [
+ {
+ "type": "Microsoft.Storage/storageAccounts",
+ "apiVersion": "2021-01-01",
+ "name": "[parameters('storageAccountName')]",
+ "location": "[parameters('location')]",
+ "kind": "StorageV2",
+ "sku": {
+ "name": "[parameters('skuName')]"
+ },
+ "tags": "[parameters('tags')]",
+ "properties": {
+ "minimumTlsVersion": "TLS1_2",
+ "encryption": {
+ "keySource": "Microsoft.Storage",
+ "requireInfrastructureEncryption": true,
+ "services": {
+ "blob": {
+ "enabled": true
+ },
+ "file": {
+ "enabled": true
+ },
+ "queue": {
+ "enabled": true
+ },
+ "table": {
+ "enabled": true
+ }
+ }
+ }
+ }
+ }
+ ],
+ "outputs": {
+ "id": {
+ "type": "string",
+ "value": "[resourceId('Microsoft.Storage/storageAccounts', parameters('storageAccountName'))]"
+ }
+ }
+ }
+ }
+ },
+ {
+ "type": "Microsoft.Resources/deployments",
+ "apiVersion": "2022-09-01",
+ "name": "networkSecurityGroup",
+ "properties": {
+ "expressionEvaluationOptions": {
+ "scope": "inner"
+ },
+ "mode": "Incremental",
+ "parameters": {
+ "name": {
+ "value": "[parameters('networkSecurityGroupName')]"
+ },
+ "location": {
+ "value": "[parameters('location')]"
+ },
+ "tags": {
+ "value": "[parameters('tags')]"
+ },
+ "securityRules": {
+ "value": "[parameters('networkSecurityGroupRules')]"
+ },
+ "logAnalyticsWorkspaceResourceId": {
+ "value": "[parameters('logAnalyticsWorkspaceResourceId')]"
+ },
+ "logStorageAccountResourceId": {
+ "value": "[reference(resourceId('Microsoft.Resources/deployments', 'logStorage'), '2022-09-01').outputs.id.value]"
+ },
+ "logs": {
+ "value": "[parameters('networkSecurityGroupDiagnosticsLogs')]"
+ },
+ "metrics": {
+ "value": "[parameters('networkSecurityGroupDiagnosticsMetrics')]"
+ }
+ },
+ "template": {
+ "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
+ "contentVersion": "1.0.0.0",
+ "metadata": {
+ "_generator": {
+ "name": "bicep",
+ "version": "0.24.24.22086",
+ "templateHash": "11977507194028278079"
+ }
+ },
+ "parameters": {
+ "name": {
+ "type": "string"
+ },
+ "location": {
+ "type": "string"
+ },
+ "tags": {
+ "type": "object",
+ "defaultValue": {}
+ },
+ "securityRules": {
+ "type": "array"
+ },
+ "logStorageAccountResourceId": {
+ "type": "string"
+ },
+ "logAnalyticsWorkspaceResourceId": {
+ "type": "string"
+ },
+ "logs": {
+ "type": "array"
+ },
+ "metrics": {
+ "type": "array"
+ }
+ },
+ "resources": [
+ {
+ "type": "Microsoft.Network/networkSecurityGroups",
+ "apiVersion": "2021-02-01",
+ "name": "[parameters('name')]",
+ "location": "[parameters('location')]",
+ "tags": "[parameters('tags')]",
+ "properties": {
+ "securityRules": "[parameters('securityRules')]"
+ }
+ },
+ {
+ "type": "Microsoft.Insights/diagnosticSettings",
+ "apiVersion": "2017-05-01-preview",
+ "scope": "[format('Microsoft.Network/networkSecurityGroups/{0}', parameters('name'))]",
+ "name": "[format('{0}-diagnostics', parameters('name'))]",
+ "properties": {
+ "storageAccountId": "[parameters('logStorageAccountResourceId')]",
+ "workspaceId": "[parameters('logAnalyticsWorkspaceResourceId')]",
+ "logs": "[parameters('logs')]",
+ "metrics": "[parameters('metrics')]"
+ },
+ "dependsOn": [
+ "[resourceId('Microsoft.Network/networkSecurityGroups', parameters('name'))]"
+ ]
+ }
+ ],
+ "outputs": {
+ "id": {
+ "type": "string",
+ "value": "[resourceId('Microsoft.Network/networkSecurityGroups', parameters('name'))]"
+ },
+ "name": {
+ "type": "string",
+ "value": "[parameters('name')]"
+ }
+ }
+ }
+ },
+ "dependsOn": [
+ "[resourceId('Microsoft.Resources/deployments', 'logStorage')]"
+ ]
+ },
+ {
+ "type": "Microsoft.Resources/deployments",
+ "apiVersion": "2022-09-01",
+ "name": "routeTable",
+ "properties": {
+ "expressionEvaluationOptions": {
+ "scope": "inner"
+ },
+ "mode": "Incremental",
+ "parameters": {
+ "name": {
+ "value": "[parameters('routeTableName')]"
+ },
+ "location": {
+ "value": "[parameters('location')]"
+ },
+ "tags": {
+ "value": "[parameters('tags')]"
+ },
+ "routeName": {
+ "value": "[parameters('routeTableRouteName')]"
+ },
+ "routeAddressPrefix": {
+ "value": "[parameters('routeTableRouteAddressPrefix')]"
+ },
+ "routeNextHopIpAddress": {
+ "value": "[parameters('routeTableRouteNextHopIpAddress')]"
+ },
+ "routeNextHopType": {
+ "value": "[parameters('routeTableRouteNextHopType')]"
+ }
+ },
+ "template": {
+ "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
+ "contentVersion": "1.0.0.0",
+ "metadata": {
+ "_generator": {
+ "name": "bicep",
+ "version": "0.24.24.22086",
+ "templateHash": "13858235086546968061"
+ }
+ },
+ "parameters": {
+ "name": {
+ "type": "string"
+ },
+ "location": {
+ "type": "string"
+ },
+ "tags": {
+ "type": "object",
+ "defaultValue": {}
+ },
+ "routeName": {
+ "type": "string"
+ },
+ "routeAddressPrefix": {
+ "type": "string"
+ },
+ "routeNextHopIpAddress": {
+ "type": "string"
+ },
+ "routeNextHopType": {
+ "type": "string"
+ }
+ },
+ "resources": [
+ {
+ "type": "Microsoft.Network/routeTables",
+ "apiVersion": "2021-02-01",
+ "name": "[parameters('name')]",
+ "location": "[parameters('location')]",
+ "tags": "[parameters('tags')]",
+ "properties": {
+ "routes": [
+ {
+ "name": "[parameters('routeName')]",
+ "properties": {
+ "addressPrefix": "[parameters('routeAddressPrefix')]",
+ "nextHopIpAddress": "[parameters('routeNextHopIpAddress')]",
+ "nextHopType": "[parameters('routeNextHopType')]"
+ }
+ }
+ ]
+ }
+ }
+ ],
+ "outputs": {
+ "id": {
+ "type": "string",
+ "value": "[resourceId('Microsoft.Network/routeTables', parameters('name'))]"
+ },
+ "name": {
+ "type": "string",
+ "value": "[parameters('name')]"
+ }
+ }
+ }
+ }
+ },
+ {
+ "type": "Microsoft.Resources/deployments",
+ "apiVersion": "2022-09-01",
+ "name": "virtualNetwork",
+ "properties": {
+ "expressionEvaluationOptions": {
+ "scope": "inner"
+ },
+ "mode": "Incremental",
+ "parameters": {
+ "name": {
+ "value": "[parameters('virtualNetworkName')]"
+ },
+ "location": {
+ "value": "[parameters('location')]"
+ },
+ "tags": {
+ "value": "[parameters('tags')]"
+ },
+ "addressPrefix": {
+ "value": "[parameters('virtualNetworkAddressPrefix')]"
+ },
+ "vNetDnsServers": {
+ "value": "[parameters('vNetDnsServers')]"
+ },
+ "subnets": {
+ "value": [
+ {
+ "name": "[parameters('subnetName')]",
+ "properties": {
+ "addressPrefix": "[parameters('subnetAddressPrefix')]",
+ "networkSecurityGroup": {
+ "id": "[reference(resourceId('Microsoft.Resources/deployments', 'networkSecurityGroup'), '2022-09-01').outputs.id.value]"
+ },
+ "routeTable": {
+ "id": "[reference(resourceId('Microsoft.Resources/deployments', 'routeTable'), '2022-09-01').outputs.id.value]"
+ },
+ "serviceEndpoints": "[parameters('subnetServiceEndpoints')]",
+ "privateEndpointNetworkPolicies": "[parameters('subnetPrivateEndpointNetworkPolicies')]",
+ "privateLinkServiceNetworkPolicies": "[parameters('subnetPrivateLinkServiceNetworkPolicies')]"
+ }
+ }
+ ]
+ },
+ "logAnalyticsWorkspaceResourceId": {
+ "value": "[parameters('logAnalyticsWorkspaceResourceId')]"
+ },
+ "logStorageAccountResourceId": {
+ "value": "[reference(resourceId('Microsoft.Resources/deployments', 'logStorage'), '2022-09-01').outputs.id.value]"
+ },
+ "logs": {
+ "value": "[parameters('virtualNetworkDiagnosticsLogs')]"
+ },
+ "metrics": {
+ "value": "[parameters('virtualNetworkDiagnosticsMetrics')]"
+ }
+ },
+ "template": {
+ "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
+ "contentVersion": "1.0.0.0",
+ "metadata": {
+ "_generator": {
+ "name": "bicep",
+ "version": "0.24.24.22086",
+ "templateHash": "3610049520534333304"
+ }
+ },
+ "parameters": {
+ "name": {
+ "type": "string"
+ },
+ "location": {
+ "type": "string"
+ },
+ "tags": {
+ "type": "object",
+ "defaultValue": {}
+ },
+ "addressPrefix": {
+ "type": "string"
+ },
+ "vNetDnsServers": {
+ "type": "array",
+ "defaultValue": []
+ },
+ "logAnalyticsWorkspaceResourceId": {
+ "type": "string"
+ },
+ "logStorageAccountResourceId": {
+ "type": "string"
+ },
+ "subnets": {
+ "type": "array"
+ },
+ "logs": {
+ "type": "array"
+ },
+ "metrics": {
+ "type": "array"
+ }
+ },
+ "resources": [
+ {
+ "type": "Microsoft.Network/virtualNetworks",
+ "apiVersion": "2021-02-01",
+ "name": "[parameters('name')]",
+ "location": "[parameters('location')]",
+ "tags": "[parameters('tags')]",
+ "properties": {
+ "addressSpace": {
+ "addressPrefixes": [
+ "[parameters('addressPrefix')]"
+ ]
+ },
+ "subnets": "[parameters('subnets')]",
+ "dhcpOptions": "[if(not(equals(parameters('vNetDnsServers'), null())), createObject('dnsServers', parameters('vNetDnsServers')), null())]"
+ }
+ },
+ {
+ "type": "Microsoft.Insights/diagnosticSettings",
+ "apiVersion": "2017-05-01-preview",
+ "scope": "[format('Microsoft.Network/virtualNetworks/{0}', parameters('name'))]",
+ "name": "[format('{0}-diagnostics', parameters('name'))]",
+ "properties": {
+ "storageAccountId": "[parameters('logStorageAccountResourceId')]",
+ "workspaceId": "[parameters('logAnalyticsWorkspaceResourceId')]",
+ "logs": "[parameters('logs')]",
+ "metrics": "[parameters('metrics')]"
+ },
+ "dependsOn": [
+ "[resourceId('Microsoft.Network/virtualNetworks', parameters('name'))]"
+ ]
+ }
+ ],
+ "outputs": {
+ "name": {
+ "type": "string",
+ "value": "[parameters('name')]"
+ },
+ "id": {
+ "type": "string",
+ "value": "[resourceId('Microsoft.Network/virtualNetworks', parameters('name'))]"
+ },
+ "subnets": {
+ "type": "array",
+ "value": "[reference(resourceId('Microsoft.Network/virtualNetworks', parameters('name')), '2021-02-01').subnets]"
+ },
+ "addressPrefix": {
+ "type": "string",
+ "value": "[reference(resourceId('Microsoft.Network/virtualNetworks', parameters('name')), '2021-02-01').addressSpace.addressPrefixes[0]]"
+ }
+ }
+ }
+ },
+ "dependsOn": [
+ "[resourceId('Microsoft.Resources/deployments', 'logStorage')]",
+ "[resourceId('Microsoft.Resources/deployments', 'networkSecurityGroup')]",
+ "[resourceId('Microsoft.Resources/deployments', 'routeTable')]"
+ ]
+ }
+ ],
+ "outputs": {
+ "virtualNetworkName": {
+ "type": "string",
+ "value": "[reference(resourceId('Microsoft.Resources/deployments', 'virtualNetwork'), '2022-09-01').outputs.name.value]"
+ },
+ "virtualNetworkResourceId": {
+ "type": "string",
+ "value": "[reference(resourceId('Microsoft.Resources/deployments', 'virtualNetwork'), '2022-09-01').outputs.id.value]"
+ },
+ "virtualNetworkAddressPrefix": {
+ "type": "string",
+ "value": "[reference(resourceId('Microsoft.Resources/deployments', 'virtualNetwork'), '2022-09-01').outputs.addressPrefix.value]"
+ },
+ "subnetName": {
+ "type": "string",
+ "value": "[reference(resourceId('Microsoft.Resources/deployments', 'virtualNetwork'), '2022-09-01').outputs.subnets.value[0].name]"
+ },
+ "subnetAddressPrefix": {
+ "type": "string",
+ "value": "[reference(resourceId('Microsoft.Resources/deployments', 'virtualNetwork'), '2022-09-01').outputs.subnets.value[0].properties.addressPrefix]"
+ },
+ "subnetResourceId": {
+ "type": "string",
+ "value": "[reference(resourceId('Microsoft.Resources/deployments', 'virtualNetwork'), '2022-09-01').outputs.subnets.value[0].id]"
+ },
+ "networkSecurityGroupName": {
+ "type": "string",
+ "value": "[reference(resourceId('Microsoft.Resources/deployments', 'networkSecurityGroup'), '2022-09-01').outputs.name.value]"
+ },
+ "networkSecurityGroupResourceId": {
+ "type": "string",
+ "value": "[reference(resourceId('Microsoft.Resources/deployments', 'networkSecurityGroup'), '2022-09-01').outputs.id.value]"
+ }
+ }
+ }
+ }
+ },
+ {
+ "type": "Microsoft.Resources/deployments",
+ "apiVersion": "2022-09-01",
+ "name": "[take(format('{0}-to-hub-vnet-peering', parameters('workloadName')), 64)]",
+ "subscriptionId": "[parameters('workloadSubscriptionId')]",
+ "location": "[resourceGroup().location]",
+ "properties": {
+ "expressionEvaluationOptions": {
+ "scope": "inner"
+ },
+ "mode": "Incremental",
+ "parameters": {
+ "spokeName": {
+ "value": "[parameters('workloadName')]"
+ },
+ "spokeResourceGroupName": "[if(parameters('existingResourceGroup'), createObject('value', parameters('resourceGroupName')), createObject('value', parameters('resourceGroupName')))]",
+ "spokeVirtualNetworkName": {
+ "value": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('workloadSubscriptionId'), if(parameters('existingResourceGroup'), parameters('resourceGroupName'), parameters('resourceGroupName'))), 'Microsoft.Resources/deployments', 'spokeNetwork'), '2022-09-01').outputs.virtualNetworkName.value]"
+ },
+ "hubVirtualNetworkName": {
+ "value": "[parameters('hubVirtualNetworkName')]"
+ },
+ "hubVirtualNetworkResourceId": {
+ "value": "[parameters('hubVirtualNetworkResourceId')]"
+ }
+ },
+ "template": {
+ "$schema": "https://schema.management.azure.com/schemas/2018-05-01/subscriptionDeploymentTemplate.json#",
+ "contentVersion": "1.0.0.0",
+ "metadata": {
+ "_generator": {
+ "name": "bicep",
+ "version": "0.24.24.22086",
+ "templateHash": "1352997920612289656"
+ }
+ },
+ "parameters": {
+ "spokeName": {
+ "type": "string"
+ },
+ "spokeResourceGroupName": {
+ "type": "string"
+ },
+ "spokeVirtualNetworkName": {
+ "type": "string"
+ },
+ "hubVirtualNetworkName": {
+ "type": "string"
+ },
+ "hubVirtualNetworkResourceId": {
+ "type": "string"
+ }
+ },
+ "resources": [
+ {
+ "type": "Microsoft.Resources/deployments",
+ "apiVersion": "2022-09-01",
+ "name": "[format('{0}-to-hub-vnet-peering', parameters('spokeName'))]",
+ "resourceGroup": "[parameters('spokeResourceGroupName')]",
+ "properties": {
+ "expressionEvaluationOptions": {
+ "scope": "inner"
+ },
+ "mode": "Incremental",
+ "parameters": {
+ "name": {
+ "value": "[format('{0}/to-{1}', parameters('spokeVirtualNetworkName'), parameters('hubVirtualNetworkName'))]"
+ },
+ "remoteVirtualNetworkResourceId": {
+ "value": "[parameters('hubVirtualNetworkResourceId')]"
+ }
+ },
+ "template": {
+ "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
+ "contentVersion": "1.0.0.0",
+ "metadata": {
+ "_generator": {
+ "name": "bicep",
+ "version": "0.24.24.22086",
+ "templateHash": "9853575474833495545"
+ }
+ },
+ "parameters": {
+ "name": {
+ "type": "string"
+ },
+ "remoteVirtualNetworkResourceId": {
+ "type": "string"
+ }
+ },
+ "resources": [
+ {
+ "type": "Microsoft.Network/virtualNetworks/virtualNetworkPeerings",
+ "apiVersion": "2021-02-01",
+ "name": "[parameters('name')]",
+ "properties": {
+ "allowForwardedTraffic": true,
+ "remoteVirtualNetwork": {
+ "id": "[parameters('remoteVirtualNetworkResourceId')]"
+ }
+ }
+ }
+ ]
+ }
+ }
+ }
+ ]
+ }
+ },
+ "dependsOn": [
+ "[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('workloadSubscriptionId'), if(parameters('existingResourceGroup'), parameters('resourceGroupName'), parameters('resourceGroupName'))), 'Microsoft.Resources/deployments', 'spokeNetwork')]"
+ ]
+ },
+ {
+ "type": "Microsoft.Resources/deployments",
+ "apiVersion": "2022-09-01",
+ "name": "[take(format('hub-to-{0}-vnet-peering', parameters('workloadName')), 64)]",
+ "subscriptionId": "[parameters('workloadSubscriptionId')]",
+ "resourceGroup": "[if(parameters('existingResourceGroup'), parameters('resourceGroupName'), parameters('resourceGroupName'))]",
+ "properties": {
+ "expressionEvaluationOptions": {
+ "scope": "inner"
+ },
+ "mode": "Incremental",
+ "parameters": {
+ "hubVirtualNetworkName": {
+ "value": "[parameters('hubVirtualNetworkName')]"
+ },
+ "hubResourceGroupName": {
+ "value": "[parameters('hubResourceGroupName')]"
+ },
+ "spokeVirtualNetworkName": {
+ "value": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('workloadSubscriptionId'), if(parameters('existingResourceGroup'), parameters('resourceGroupName'), parameters('resourceGroupName'))), 'Microsoft.Resources/deployments', 'spokeNetwork'), '2022-09-01').outputs.virtualNetworkName.value]"
+ },
+ "spokeVirtualNetworkResourceId": {
+ "value": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('workloadSubscriptionId'), if(parameters('existingResourceGroup'), parameters('resourceGroupName'), parameters('resourceGroupName'))), 'Microsoft.Resources/deployments', 'spokeNetwork'), '2022-09-01').outputs.virtualNetworkResourceId.value]"
+ }
+ },
+ "template": {
+ "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
+ "contentVersion": "1.0.0.0",
+ "metadata": {
+ "_generator": {
+ "name": "bicep",
+ "version": "0.24.24.22086",
+ "templateHash": "2058971036831358476"
+ }
+ },
+ "parameters": {
+ "hubResourceGroupName": {
+ "type": "string"
+ },
+ "hubVirtualNetworkName": {
+ "type": "string"
+ },
+ "spokeVirtualNetworkName": {
+ "type": "string"
+ },
+ "spokeVirtualNetworkResourceId": {
+ "type": "string"
+ }
+ },
+ "resources": [
+ {
+ "type": "Microsoft.Resources/deployments",
+ "apiVersion": "2022-09-01",
+ "name": "hubToSpokeVirtualNetworkPeering",
+ "resourceGroup": "[parameters('hubResourceGroupName')]",
+ "properties": {
+ "expressionEvaluationOptions": {
+ "scope": "inner"
+ },
+ "mode": "Incremental",
+ "parameters": {
+ "name": {
+ "value": "[format('{0}/to-{1}', parameters('hubVirtualNetworkName'), parameters('spokeVirtualNetworkName'))]"
+ },
+ "remoteVirtualNetworkResourceId": {
+ "value": "[parameters('spokeVirtualNetworkResourceId')]"
+ }
+ },
+ "template": {
+ "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
+ "contentVersion": "1.0.0.0",
+ "metadata": {
+ "_generator": {
+ "name": "bicep",
+ "version": "0.24.24.22086",
+ "templateHash": "9853575474833495545"
+ }
+ },
+ "parameters": {
+ "name": {
+ "type": "string"
+ },
+ "remoteVirtualNetworkResourceId": {
+ "type": "string"
+ }
+ },
+ "resources": [
+ {
+ "type": "Microsoft.Network/virtualNetworks/virtualNetworkPeerings",
+ "apiVersion": "2021-02-01",
+ "name": "[parameters('name')]",
+ "properties": {
+ "allowForwardedTraffic": true,
+ "remoteVirtualNetwork": {
+ "id": "[parameters('remoteVirtualNetworkResourceId')]"
+ }
+ }
+ }
+ ]
+ }
+ }
+ }
+ ]
+ }
+ },
+ "dependsOn": [
+ "[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('workloadSubscriptionId'), if(parameters('existingResourceGroup'), parameters('resourceGroupName'), parameters('resourceGroupName'))), 'Microsoft.Resources/deployments', 'spokeNetwork')]"
+ ]
+ },
+ {
+ "condition": "[not(equals(parameters('workloadSubscriptionId'), parameters('hubSubscriptionId')))]",
+ "type": "Microsoft.Resources/deployments",
+ "apiVersion": "2022-09-01",
+ "name": "[format('activity-logs-{0}-{1}', 'spokeNetwork', parameters('resourceSuffix'))]",
+ "subscriptionId": "[parameters('workloadSubscriptionId')]",
+ "location": "[resourceGroup().location]",
+ "properties": {
+ "expressionEvaluationOptions": {
+ "scope": "inner"
+ },
+ "mode": "Incremental",
+ "parameters": {
+ "diagnosticSettingName": {
+ "value": "[format('log-{0}-sub-activity-to-{1}', 'spokeNetwork', parameters('logAnalyticsWorkspaceName'))]"
+ },
+ "logAnalyticsWorkspaceId": {
+ "value": "[parameters('logAnalyticsWorkspaceResourceId')]"
+ }
+ },
+ "template": {
+ "$schema": "https://schema.management.azure.com/schemas/2018-05-01/subscriptionDeploymentTemplate.json#",
+ "contentVersion": "1.0.0.0",
+ "metadata": {
+ "_generator": {
+ "name": "bicep",
+ "version": "0.24.24.22086",
+ "templateHash": "3850477028148266020"
+ }
+ },
+ "parameters": {
+ "diagnosticSettingName": {
+ "type": "string"
+ },
+ "logAnalyticsWorkspaceId": {
+ "type": "string"
+ },
+ "supportedClouds": {
+ "type": "array",
+ "defaultValue": [
+ "AzureCloud",
+ "AzureUSGovernment"
+ ]
+ }
+ },
+ "resources": [
+ {
+ "condition": "[contains(parameters('supportedClouds'), environment().name)]",
+ "type": "Microsoft.Insights/diagnosticSettings",
+ "apiVersion": "2017-05-01-preview",
+ "name": "[parameters('diagnosticSettingName')]",
+ "properties": {
+ "workspaceId": "[parameters('logAnalyticsWorkspaceId')]",
+ "logs": [
+ {
+ "category": "Administrative",
+ "enabled": true
+ },
+ {
+ "category": "Security",
+ "enabled": true
+ },
+ {
+ "category": "ServiceHealth",
+ "enabled": true
+ },
+ {
+ "category": "Alert",
+ "enabled": true
+ },
+ {
+ "category": "Recommendation",
+ "enabled": true
+ },
+ {
+ "category": "Policy",
+ "enabled": true
+ },
+ {
+ "category": "Autoscale",
+ "enabled": true
+ },
+ {
+ "category": "ResourceHealth",
+ "enabled": true
+ }
+ ]
+ }
+ }
+ ]
+ }
+ },
+ "dependsOn": [
+ "[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('workloadSubscriptionId'), if(parameters('existingResourceGroup'), parameters('resourceGroupName'), parameters('resourceGroupName'))), 'Microsoft.Resources/deployments', 'spokeNetwork')]"
+ ]
+ },
+ {
+ "condition": "[parameters('deployPolicy')]",
+ "type": "Microsoft.Resources/deployments",
+ "apiVersion": "2022-09-01",
+ "name": "[format('assign-policy-{0}-{1}', parameters('workloadName'), parameters('deploymentNameSuffix'))]",
+ "subscriptionId": "[parameters('workloadSubscriptionId')]",
+ "resourceGroup": "[if(parameters('existingResourceGroup'), parameters('resourceGroupName'), parameters('resourceGroupName'))]",
+ "properties": {
+ "expressionEvaluationOptions": {
+ "scope": "inner"
+ },
+ "mode": "Incremental",
+ "parameters": {
+ "builtInAssignment": {
+ "value": "[parameters('policy')]"
+ },
+ "logAnalyticsWorkspaceName": {
+ "value": "[variables('logAnalyticsWorkspaceResourceId_split')[8]]"
+ },
+ "logAnalyticsWorkspaceResourceGroupName": {
+ "value": "[variables('logAnalyticsWorkspaceResourceId_split')[4]]"
+ },
+ "location": {
+ "value": "[parameters('location')]"
+ },
+ "operationsSubscriptionId": {
+ "value": "[variables('logAnalyticsWorkspaceResourceId_split')[2]]"
+ }
+ },
+ "template": {
+ "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
+ "contentVersion": "1.0.0.0",
+ "metadata": {
+ "_generator": {
+ "name": "bicep",
+ "version": "0.24.24.22086",
+ "templateHash": "16693295535307781768"
+ }
+ },
+ "parameters": {
+ "builtInAssignment": {
+ "type": "string",
+ "defaultValue": "NISTRev4",
+ "allowedValues": [
+ "NISTRev4",
+ "NISTRev5",
+ "IL5",
+ "CMMC"
+ ],
+ "metadata": {
+ "description": "[NISTRev4/NISTRev5/IL5/CMMC] Built-in policy assignments to assign, default is NISTRev4. IL5 is only available for AzureUsGovernment and will switch to NISTRev4 if tried in AzureCloud."
+ }
+ },
+ "logAnalyticsWorkspaceName": {
+ "type": "string"
+ },
+ "logAnalyticsWorkspaceResourceGroupName": {
+ "type": "string"
+ },
+ "operationsSubscriptionId": {
+ "type": "string"
+ },
+ "deployRemediation": {
+ "type": "bool",
+ "defaultValue": false,
+ "metadata": {
+ "description": "Starts a policy remediation for the VM Agent policies in hub RG. Set to false by default since this is time consuming in deployment."
+ }
+ },
+ "location": {
+ "type": "string",
+ "defaultValue": "[resourceGroup().location]",
+ "metadata": {
+ "description": "The location of this resource"
+ }
+ }
+ },
+ "variables": {
+ "$fxv#0": " {\r\n \"listOfMembersToExcludeFromWindowsVMAdministratorsGroup\": \r\n {\r\n \"value\": \"admin\"\r\n },\r\n \"listOfMembersToIncludeInWindowsVMAdministratorsGroup\": \r\n {\r\n \"value\": \"azureuser\"\r\n },\r\n \"logAnalyticsWorkspaceIdforVMReporting\": \r\n {\r\n \"value\": \"\"\r\n },\r\n \"IncludeArcMachines\": \r\n {\r\n \"value\": \"true\"\r\n },\r\n \"MinimumTLSVersion-5752e6d6-1206-46d8-8ab1-ecc2f71a8112\": \r\n {\r\n \"value\": \"1.2\"\r\n },\r\n \"NotAvailableMachineState-bed48b13-6647-468e-aa2f-1af1d3f4dd40\": \r\n {\r\n \"value\": \"Compliant\"\r\n },\r\n \"requiredRetentionDays\": \r\n {\r\n \"value\": \"365\"\r\n },\r\n \"resourceGroupName-b6e2945c-0b7b-40f5-9233-7a5323b5cdc6\": \r\n {\r\n \"value\": \"NetworkWatcherRG\"\r\n }\r\n }",
+ "$fxv#1": " {\r\n \"IncludeArcMachines\": \r\n {\r\n \"value\": \"true\"\r\n },\r\n \"MinimumTLSVersion-5752e6d6-1206-46d8-8ab1-ecc2f71a8112\": \r\n {\r\n \"value\": \"1.2\"\r\n },\r\n \"NotAvailableMachineState-bed48b13-6647-468e-aa2f-1af1d3f4dd40\": \r\n {\r\n \"value\": \"Compliant\"\r\n },\r\n \"requiredRetentionDays\": \r\n {\r\n \"value\": \"365\"\r\n },\r\n \"resourceGroupName-b6e2945c-0b7b-40f5-9233-7a5323b5cdc6\": \r\n {\r\n \"value\": \"NetworkWatcherRG\"\r\n }\r\n }",
+ "$fxv#2": "{\r\n \"IncludeArcMachines\" : { \r\n \"value\" : \"false\"\r\n },\r\n \"NotAvailableMachineState-bed48b13-6647-468e-aa2f-1af1d3f4dd40\" : { \r\n \"value\" : \"Compliant\"\r\n },\r\n \"MinimumTLSVersionForWindowsServers\" : { \r\n \"value\" : \"1.2\"\r\n },\r\n \"requiredRetentionDays\" : { \r\n \"value\" : \"365\"\r\n },\r\n \"effect-febd0533-8e55-448f-b837-bd0e06f16469\" : { \r\n \"value\" : \"audit\"\r\n },\r\n \"allowedContainerImagesRegex-febd0533-8e55-448f-b837-bd0e06f16469\" : { \r\n \"value\" : \"^(.+){0}$\"\r\n },\r\n \"effect-95edb821-ddaf-4404-9732-666045e056b4\" : { \r\n \"value\" : \"audit\"\r\n },\r\n \"effect-440b515e-a580-421e-abeb-b159a61ddcbc\" : { \r\n \"value\" : \"audit\"\r\n },\r\n \"effect-233a2a17-77ca-4fb1-9b6b-69223d272a44\" : { \r\n \"value\" : \"audit\"\r\n },\r\n \"effect-e345eecc-fa47-480f-9e88-67dcc122b164\" : { \r\n \"value\" : \"audit\"\r\n },\r\n \"cpuLimit-e345eecc-fa47-480f-9e88-67dcc122b164\" : { \r\n \"value\" : \"0\"\r\n },\r\n \"memoryLimit-e345eecc-fa47-480f-9e88-67dcc122b164\" : { \r\n \"value\" : \"0\"\r\n },\r\n \"effect-f06ddb64-5fa3-4b77-b166-acb36f7f6042\" : { \r\n \"value\" : \"audit\"\r\n },\r\n \"runAsUserRule-f06ddb64-5fa3-4b77-b166-acb36f7f6042\" : { \r\n \"value\" : \"MustRunAsNonRoot\"\r\n },\r\n \"runAsGroupRule-f06ddb64-5fa3-4b77-b166-acb36f7f6042\" : { \r\n \"value\" : \"RunAsAny\"\r\n },\r\n \"supplementalGroupsRule-f06ddb64-5fa3-4b77-b166-acb36f7f6042\" : { \r\n \"value\" : \"RunAsAny\"\r\n },\r\n \"fsGroupRule-f06ddb64-5fa3-4b77-b166-acb36f7f6042\" : { \r\n \"value\" : \"RunAsAny\"\r\n },\r\n \"effect-1c6e92c9-99f0-4e55-9cf2-0c234dc48f99\" : { \r\n \"value\" : \"audit\"\r\n },\r\n \"effect-47a1ee2f-2a2a-4576-bf2a-e0e36709c2b8\" : { \r\n \"value\" : \"audit\"\r\n },\r\n \"effect-df49d893-a74c-421d-bc95-c663042e5b80\" : { \r\n \"value\" : \"audit\"\r\n },\r\n \"effect-1a5b4dca-0b6f-4cf5-907c-56316bc1bf3d\" : { \r\n \"value\" : \"audit\"\r\n },\r\n \"effect-c26596ff-4d70-4e6a-9a30-c2506bd2f80c\" : { \r\n \"value\" : \"audit\"\r\n },\r\n \"effect-511f5417-5d12-434d-ab2e-816901e72a5e\" : { \r\n \"value\" : \"audit\"\r\n },\r\n \"effect-82985f06-dc18-4a48-bc1c-b9f4f0098cfe\" : { \r\n \"value\" : \"audit\"\r\n },\r\n \"effect-098fc59e-46c7-4d99-9b16-64990e543d75\" : { \r\n \"value\" : \"audit\"\r\n },\r\n \"NetworkWatcherResourceGroupName\" : { \r\n \"value\" : \"NetworkWatcherRG\"\r\n },\r\n \"setting-a6fb4358-5bf4-4ad7-ba82-2cd2f41ce5e9\" : { \r\n \"value\" : \"enabled\"\r\n },\r\n \"aadAuthenticationInServiceFabricMonitoringEffect\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-71ef260a-8f18-47b7-abcb-62d0673d94dc\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-055aa869-bc98-4af8-bafc-23f1ab6ffe2c\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-564feb30-bf6a-4854-b4bb-0d2d2d1e6c66\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-862e97cf-49fc-4a5c-9de4-40d4e2e7c8eb\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-d9da03a1-f3c3-412a-9709-947156872263\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-617c02be-7f02-4efd-8836-3180d47b6c68\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-0b60c0b2-2dc2-4e1c-b5c9-abbed971de53\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-1e66c121-a66a-4b1f-9b83-0fd99bf0fc2d\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-ec068d99-e9c7-401f-8cef-5bdde4e6ccf1\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-c349d81b-9985-44ae-a8da-ff98d108ede8\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-3657f5a0-770e-44a3-b44e-9431ba1e9735\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-b4ac1030-89c5-4697-8e00-28b5ba6a8811\" : { \r\n \"value\" : \"audit\"\r\n },\r\n \"effect-ea0dfaed-95fb-448c-934e-d6e713ce393d\" : { \r\n \"value\" : \"audit\"\r\n },\r\n \"effect-4733ea7b-a883-42fe-8cac-97454c2a9e4a\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-f4b53539-8df9-40e4-86c6-6b607703bd4e\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-41425d9f-d1a5-499a-9932-f8ed8453932c\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-fc4d8e41-e223-45ea-9bf5-eada37891d87\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-86efb160-8de7-451d-bc08-5d475b0aadae\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-4ec52d6d-beb7-40c4-9a9e-fe753254690e\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-64d314f6-6062-4780-a861-c23e8951bee5\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-1fd32ebd-e4c3-4e13-a54a-d7422d4d95f6\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-fa298e57-9444-42ba-bf04-86e8470e32c7\" : { \r\n \"value\" : \"audit\"\r\n },\r\n \"effect-67121cc7-ff39-4ab8-b7e3-95b84dab487d\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-1f905d99-2ab7-462c-a6b0-f709acca6c8f\" : { \r\n \"value\" : \"audit\"\r\n },\r\n \"effect-5b9159ae-1701-4a6f-9a7a-aa9c8ddd0580\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-ba769a63-b8cc-4b2d-abf6-ac33c7204be8\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-81e74cea-30fd-40d5-802f-d72103c2aaaa\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-0aa61e00-0a01-4a3c-9945-e93cffedf0e6\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-47031206-ce96-41f8-861b-6a915f3de284\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-87ba29ef-1ab3-4d82-b763-87fcd4f531f7\" : { \r\n \"value\" : \"audit\"\r\n },\r\n \"effect-51522a96-0869-4791-82f3-981000c2c67f\" : { \r\n \"value\" : \"audit\"\r\n },\r\n \"effect-b5ec538c-daa0-4006-8596-35468b9148e8\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-56a5ee18-2ae6-4810-86f7-18e39ce5629b\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-2e94d99a-8a36-4563-bc77-810d8893b671\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-1fafeaf6-7927-4059-a50a-8eb2a7a6f2b5\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-99e9ccd8-3db9-4592-b0d1-14b1715a4d8a\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-1f68a601-6e6d-4e42-babf-3f643a047ea2\" : { \r\n \"value\" : \"audit\"\r\n },\r\n \"effect-f7d52b2d-e161-4dfa-a82b-55e564167385\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-7d7be79c-23ba-4033-84dd-45e2a5ccdd67\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-ca91455f-eace-4f96-be59-e6e2c35b4816\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-702dd420-7fcc-42c5-afe8-4026edd20fe0\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"diagnosticsLogsInRedisCacheMonitoringEffect\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"secureTransferToStorageAccountMonitoringEffect\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-d0793b48-0edc-4296-a390-4c75d1bdfd71\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-7d092e0a-7acd-40d2-a975-dca21cae48c4\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-2a1a9cdf-e04d-429a-8416-3bfb72a1b26f\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"disableUnrestrictedNetworkToStorageAccountMonitoringEffect\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-55615ac9-af46-4a59-874e-391cc3dfb490\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-1b8ca024-1d5c-4dec-8995-b1a932b41780\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-037eea7a-bd0a-46c5-9a66-03aea78705d3\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-53503636-bcc9-4748-9663-5348217f160f\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-40cec1dd-a100-4920-b15b-3024fe8901ab\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-0725b4dd-7e76-479c-a735-68e7ee23d5ca\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-a049bf77-880b-470f-ba6d-9f21c530cf83\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-ee980b6d-0eca-4501-8d54-f6290fd512c3\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-1d84d5fb-01f6-4d12-ba4f-4a26081d403d\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-37e0d2fe-28a5-43d6-a273-67d37d1f5606\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"identityDesignateMoreThanOneOwnerMonitoringEffect\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"diskEncryptionMonitoringEffect\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"emailNotificationToSubscriptionOwnerHighSeverityAlertsEnabledEffect\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"functionAppDisableRemoteDebuggingMonitoringEffect\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"sqlDbEncryptionMonitoringEffect\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"vulnerabilityAssessmentOnManagedInstanceMonitoringEffect\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"ensurePHPVersionLatestForAPIAppEffect\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"aadAuthenticationInSqlServerMonitoringEffect\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"vmssEndpointProtectionMonitoringEffect\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"vmssOsVulnerabilitiesMonitoringEffect\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"adaptiveApplicationControlsMonitoringEffect\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"geoRedundantBackupShouldBeEnabledForAzureDatabaseForPostgreSQLEffect\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"ensureJavaVersionLatestForWebAppEffect\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"identityDesignateLessThanOwnersMonitoringEffect\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"securityContactEmailAddressForSubscriptionEffect\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"webAppRestrictCORSAccessMonitoringEffect\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"identityRemoveExternalAccountWithWritePermissionsMonitoringEffect\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"identityRemoveExternalAccountWithReadPermissionsMonitoringEffect\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"identityRemoveDeprecatedAccountMonitoringEffect\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"functionAppEnforceHttpsMonitoringEffect\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"ensurePythonVersionLatestForWebAppEffect\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"ensurePythonVersionLatestForFunctionAppEffect\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"ensurePHPVersionLatestForWebAppEffect\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"ensurePythonVersionLatestForAPIAppEffect\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"geoRedundantBackupShouldBeEnabledForAzureDatabaseForMySQLEffect\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"systemUpdatesMonitoringEffect\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"ensureJavaVersionLatestForAPIAppEffect\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"ensureHTTPVersionLatestForWebAppEffect\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"apiAppRequireLatestTlsMonitoringEffect\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"identityEnableMFAForWritePermissionsMonitoringEffect\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"ensureHTTPVersionLatestForAPIAppEffect\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"ensureJavaVersionLatestForFunctionAppEffect\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"nextGenerationFirewallMonitoringEffect\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"useRbacRulesMonitoringEffect\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"webAppEnforceHttpsMonitoringEffect\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"sqlServerAuditingMonitoringEffect\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"vnetEnableDDoSProtectionMonitoringEffect\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"identityEnableMFAForOwnerPermissionsMonitoringEffect\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"sqlServerAdvancedDataSecurityMonitoringEffect\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"sqlManagedInstanceAdvancedDataSecurityMonitoringEffect\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"endpointProtectionMonitoringEffect\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"jitNetworkAccessMonitoringEffect\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"apiAppEnforceHttpsMonitoringEffect\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"geoRedundantStorageShouldBeEnabledForStorageAccountsEffect\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"vmssSystemUpdatesMonitoringEffect\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"webAppDisableRemoteDebuggingMonitoringEffect\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"longtermGeoRedundantBackupEnabledAzureSQLDatabasesEffect\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"systemConfigurationsMonitoringEffect\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"ensureHTTPVersionLatestForFunctionAppEffect\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"identityEnableMFAForReadPermissionsMonitoringEffect\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"containerBenchmarkMonitoringEffect\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"apiAppDisableRemoteDebuggingMonitoringEffect\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"identityRemoveDeprecatedAccountWithOwnerPermissionsMonitoringEffect\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"vulnerabilityAssessmentOnServerMonitoringEffect\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"webAppRequireLatestTlsMonitoringEffect\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"identityRemoveExternalAccountWithOwnerPermissionsMonitoringEffect\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"functionAppRequireLatestTlsMonitoringEffect\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"kubernetesServiceVersionUpToDateMonitoringEffect\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"sqlDbVulnerabilityAssesmentMonitoringEffect\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"membersToIncludeInLocalAdministratorsGroup\" : { \r\n \"value\" : \"\"\r\n },\r\n \"membersToExcludeInLocalAdministratorsGroup\" : { \r\n \"value\" : \"\"\r\n },\r\n \"logAnalyticsWorkspaceIDForVMAgents\" : { \r\n \"value\" : \"\"\r\n },\r\n \"PHPLatestVersionForAppServices\" : { \r\n \"value\" : \"7.4\"\r\n },\r\n \"JavaLatestVersionForAppServices\" : { \r\n \"value\" : \"11\"\r\n },\r\n \"WindowsPythonLatestVersionForAppServices\" : { \r\n \"value\" : \"3.6\"\r\n },\r\n \"LinuxPythonLatestVersionForAppServices\" : { \r\n \"value\" : \"3.9\"\r\n },\r\n \"ensureDotNetFrameworkLatestForFunctionAppEffect\" : { \r\n \"value\" : \"Disabled\"\r\n },\r\n \"sqlManagedInstanceAdvancedDataSecurityEmailsMonitoringEffect\" : { \r\n \"value\" : \"Disabled\"\r\n },\r\n \"vulnerabilityAssessmentMonitoringEffect\" : { \r\n \"value\" : \"Disabled\"\r\n },\r\n \"ensureDotNetFrameworkLatestForWebAppEffect\" : { \r\n \"value\" : \"Disabled\"\r\n },\r\n \"sqlServerAdvancedDataSecurityEmailsMonitoringEffect\" : { \r\n \"value\" : \"Disabled\"\r\n },\r\n \"microsoftIaaSAntimalwareExtensionShouldBeDeployedOnWindowsServersEffect\" : { \r\n \"value\" : \"Disabled\"\r\n },\r\n \"securityCenterStandardPricingTierShouldBeSelectedEffect\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"theLogAnalyticsAgentShouldBeInstalledOnVirtualMachinesEffect\" : { \r\n \"value\" : \"Disabled\"\r\n },\r\n \"ensurePHPVersionLatestForFunctionAppEffect\" : { \r\n \"value\" : \"Disabled\"\r\n },\r\n \"sqlManagedInstanceAdvancedDataSecurityEmailAdminsMonitoringEffect\" : { \r\n \"value\" : \"Disabled\"\r\n },\r\n \"securityContactPhoneNumberShouldBeProvidedForSubscriptionEffect\" : { \r\n \"value\" : \"Disabled\"\r\n },\r\n \"threatDetectionTypesOnManagedInstanceMonitoringEffect\" : { \r\n \"value\" : \"Disabled\"\r\n },\r\n \"ensureDotNetFrameworkLatestForAPIAppEffect\" : { \r\n \"value\" : \"Disabled\"\r\n },\r\n \"sqlServerAdvancedDataSecurityEmailAdminsMonitoringEffect\" : { \r\n \"value\" : \"Disabled\"\r\n },\r\n \"threatDetectionTypesOnServerMonitoringEffect\" : { \r\n \"value\" : \"Disabled\"\r\n },\r\n \"theLogAnalyticsAgentShouldBeInstalledOnVirtualMachineScaleSetsEffect\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n }\r\n}",
+ "$fxv#3": "{\r\n \"logAnalyticsWorkspaceId-f47b5582-33ec-4c5c-87c0-b010a6b2e917\" : { \r\n \"value\" : \"\"\r\n },\r\n \"effect-09024ccc-0c5f-475e-9457-b7c0d9ed487b\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"MembersToExclude-69bf4abd-ca1e-4cf6-8b5a-762d42e61d4f\" :{\r\n \"value\": \"\"\r\n },\r\n \"MembersToInclude-30f71ea1-ac77-4f26-9fc5-2d926bbd4ba7\": {\r\n \"value\": \"\"\r\n },\r\n \"effect-0961003e-5a0a-4549-abde-af6a37f2724d\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"effect-0b15565f-aa9e-48ba-8619-45960f2c314d\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"effect-0e60b895-3786-45da-8377-9c6b4b6ac5f9\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"effect-17k78e20-9358-41c9-923c-fb736d382a12\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"effect-1bc1795e-d44a-4d48-9b3b-6fff0fd5f9ba\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"PHPLatestVersion\" : { \r\n \"value\" : \"7.3\"\r\n },\r\n \"effect-22bee202-a82f-4305-9a2a-6d7f44d4dedb\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-26a828e1-e88f-464e-bbb3-c134a282b9de\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"effect-34c877ad-507e-4c82-993e-3452a6e0ad3c\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-3c735d8a-a4ba-4a3a-b7cf-db7754cf57f4\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"effect-404c3081-a854-4457-ae30-26a93ef643f9\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-47a6b606-51aa-4496-8bb7-64b11cf66adc\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"effect-496223c3-ad65-4ecd-878a-bae78737e9ed\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"JavaLatestVersion\" : { \r\n \"value\" : \"11\"\r\n },\r\n \"effect-4f11b553-d42e-4e3a-89be-32ca364cad4c\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"effect-4f4f78b8-e367-4b10-a341-d9a4ad5cf1c7\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"effect-5c607a2e-c700-4744-8254-d77e7c9eb5e4\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"effect-5f76cf89-fbf2-47fd-a3f4-b891fa780b60\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"effect-6b1cbf55-e8b6-442f-ba4c-7246b6381474\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"effect-6d555dd1-86f2-4f1c-8ed7-5abae7c6cbab\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-7008174a-fd10-4ef0-817e-fc820a951d73\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"LinuxPythonLatestVersion\" : { \r\n \"value\" : \"3.8\"\r\n },\r\n \"effect-7238174a-fd10-4ef0-817e-fc820a951d73\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"effect-7261b898-8a84-4db8-9e04-18527132abb3\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"effect-74c3584d-afae-46f7-a20a-6f8adba71a16\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"effect-86b3d65f-7626-441e-b690-81a8b71cff60\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"effect-88999f4c-376a-45c8-bcb3-4058f713cf39\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"effect-8c122334-9d20-4eb8-89ea-ac9a705b74ae\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"effect-8cb6aa8b-9e41-4f4e-aa25-089a7ac2581e\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"effect-9297c21d-2ed6-4474-b48f-163f75654ce3\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"effect-991310cd-e9f3-47bc-b7b6-f57b557d07db\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"effect-9b597639-28e4-48eb-b506-56b05d366257\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"effect-9d0b6ea4-93e2-4578-bf2f-6bb17d22b4bc\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"effect-9daedab3-fb2d-461e-b861-71790eead4f6\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"effect-a4af4a39-4135-47fb-b175-47fbdf85311d\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-a6fb4358-5bf4-4ad7-ba82-2cd2f41ce5e9\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"setting-a6fb4358-5bf4-4ad7-ba82-2cd2f41ce5e9\" : { \r\n \"value\" : \"enabled\"\r\n },\r\n \"effect-a70ca396-0a34-413a-88e1-b956c1e683be\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"effect-aa633080-8b72-40c4-a2d7-d00c03e80bed\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"effect-abfb4388-5bf4-4ad7-ba82-2cd2f41ceae9\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"effect-abfb7388-5bf4-4ad7-ba99-2cd2f41cebb9\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"effect-af6cd1bd-1635-48cb-bde7-5b15693900b9\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"resourceGroupName-b6e2945c-0b7b-40f5-9233-7a5323b5cdc6\" : { \r\n \"value\" : \"NetworkWatcherRG\"\r\n },\r\n \"effect-b7ddfbdc-1260-477d-91fd-98bd9be789a6\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-c3f317a7-a95c-4547-b7e7-11017ebdf2fe\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"effect-cb510bfd-1cba-4d9f-a230-cb0976f4bb71\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"effect-e1e5fd5d-3e4c-4ce1-8661-7d1873ae6b15\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"effect-e2c1c086-2d84-4019-bff3-c44ccd95113c\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"effect-e3576e28-8b17-4677-84c3-db2990658d64\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"effect-e8cbc669-f12d-49eb-93e7-9273119e9933\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"effect-e9c8d085-d9cc-4b17-9cdc-059f1f01f19e\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"effect-ebb62a0c-3560-49e1-89ed-27e074e9f8ad\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"effect-efbde977-ba53-4479-b8e9-10b957924fbf\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"effect-f0e6e85b-9b9f-4a4b-b67b-f730d42f1b0b\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"effect-f6de0be7-9a8a-4b8a-b349-43cf02d22f7c\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"effect-f8456c1c-aa66-4dfb-861a-25d127b775c9\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"effect-f9d614c5-c173-4d56-95a7-b4437057d193\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"effect-fb893a29-21bb-418c-a157-e99480ec364c\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-feedbf84-6b99-488c-acc2-71c829aa5ffc\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"effect-3b980d31-7904-4bb7-8575-5665739a8052\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"effect-6e2593d9-add6-4083-9c9b-4b7d2188c899\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"effect-b607c5de-e7d9-4eee-9e5c-83f1bcee4fa0\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"effect-12430be1-6cc8-4527-a9a8-e3d38f250096\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"modeRequirement-12430be1-6cc8-4527-a9a8-e3d38f250096\" : { \r\n \"value\" : \"Detection\"\r\n },\r\n \"effect-425bea59-a659-4cbb-8d31-34499bd030b8\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"modeRequirement-425bea59-a659-4cbb-8d31-34499bd030b8\" : { \r\n \"value\" : \"Detection\"\r\n },\r\n \"effect-564feb30-bf6a-4854-b4bb-0d2d2d1e6c66\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-055aa869-bc98-4af8-bafc-23f1ab6ffe2c\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-013e242c-8828-4970-87b3-ab247555486d\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"effect-d38fc420-0735-4ef3-ac11-c806f651a570\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"effect-a1181c5f-672a-477a-979a-7d58aa086233\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-308fbb08-4ab8-4e67-9b29-592e93fb94fa\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"effect-4da35fc9-c9e7-4960-aec9-797fe7d9051d\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"effect-523b5cd1-3e23-492f-a539-13118b6d1e3a\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"effect-7fe3b40f-802b-4cdd-8bd4-fd799c948cc2\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"effect-c25d9a16-bc35-4e15-a7e5-9db606bf9ed4\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"effect-b0f33259-77d7-4c9e-aac6-3aabcfae693c\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"effect-037eea7a-bd0a-46c5-9a66-03aea78705d3\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-0725b4dd-7e76-479c-a735-68e7ee23d5ca\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-0820b7b9-23aa-4725-a1ce-ae4558f718e5\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"effect-2c89a2e5-7285-40fe-afe0-ae8654b92fab\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-358c20a6-3f9e-4f0e-97ff-c6ce485e2aac\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"effect-5744710e-cc2f-4ee8-8809-3b11e89f4bc9\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"effect-ac4a19c2-fa67-49b4-8ae5-0b2e78c49457\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-c9d007d0-c057-4772-b18c-01e546713bcd\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-d0793b48-0edc-4296-a390-4c75d1bdfd71\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-e372f825-a257-4fb8-9175-797a8a8627d6\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-d158790f-bfb0-486c-8631-2dc6b4e8e6af\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-e802a67a-daf5-4436-9ea6-f6d821dd0c5d\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-a451c1ef-c6ca-483d-87ed-f49761e3ffb5\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-b954148f-4c11-4c38-8221-be76711e194a-MicrosoftSql-servers-firewallRules-delete\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"effect-b954148f-4c11-4c38-8221-be76711e194a-MicrosoftNetwork-networkSecurityGroups-delete\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"effect-b954148f-4c11-4c38-8221-be76711e194a-MicrosoftClassicNetwork-networkSecurityGroups-delete\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"effect-b954148f-4c11-4c38-8221-be76711e194a-MicrosoftNetwork-networkSecurityGroups-securityRules-delete\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"effect-b954148f-4c11-4c38-8221-be76711e194a-MicrosoftClassicNetwork-networkSecurityGroups-securityRules-delete\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"effect-ae89ebca-1c92-4898-ac2c-9f63decb045c\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"effect-d26f7642-7545-4e18-9b75-8c9bbdee3a9a\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"effect-1a4e592a-6a6e-44a5-9814-e36264ca96e7\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"effect-7796937f-307b-4598-941c-67d3a05ebfe7\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"effect-c5447c04-a4d7-4ba8-a263-c9ee321a6858\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"effect-41388f1c-2db0-4c25-95b2-35d7f5ccbfa9\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"effect-b02aacc0-b073-424e-8298-42b22829ee0a\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"effect-057d6cfe-9c4f-4a6d-bc60-14420ea1f1a9\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"effect-0ec47710-77ff-4a3d-9181-6aa50af424d0\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-48af4db5-9b8b-401c-8e74-076be876a430\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-82339799-d096-41ae-8538-b108becf0970\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-1b7aa243-30e4-4c9e-bca8-d0d3022b634a\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"effect-ef2a8f2a-b3d9-49cd-a8a8-9a3aaaf647d9\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"effect-bb91dfba-c30d-4263-9add-9c2384e659a6\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"effect-e71308d3-144b-4262-b144-efdc3cc90517\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"effect-2bdd0062-9d75-436e-89df-487dd8e4b3c7\" : { \r\n \"value\" : \"Disabled\"\r\n },\r\n \"effect-4733ea7b-a883-42fe-8cac-97454c2a9e4a\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-67121cc7-ff39-4ab8-b7e3-95b84dab487d\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-6fac406b-40ca-413b-bf8e-0bf964659c25\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-81e74cea-30fd-40d5-802f-d72103c2aaaa\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-c349d81b-9985-44ae-a8da-ff98d108ede8\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-f4b53539-8df9-40e4-86c6-6b607703bd4e\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-ec068d99-e9c7-401f-8cef-5bdde4e6ccf1\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-048248b0-55cd-46da-b1ff-39efd52db260\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"effect-0d134df8-db83-46fb-ad72-fe0c9428c8dd\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"effect-2c89a2e5-7285-40fe-afe0-ae8654b92fb2\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-3657f5a0-770e-44a3-b44e-9431ba1e9735\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-5b9159ae-1701-4a6f-9a7a-aa9c8ddd0580\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-617c02be-7f02-4efd-8836-3180d47b6c68\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-7d7be79c-23ba-4033-84dd-45e2a5ccdd67\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-87ba29ef-1ab3-4d82-b763-87fcd4f531f7\" : { \r\n \"value\" : \"audit\"\r\n },\r\n \"effect-f7d52b2d-e161-4dfa-a82b-55e564167385\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-c43e4a30-77cb-48ab-a4dd-93f175c63b57\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"effect-0b60c0b2-2dc2-4e1c-b5c9-abbed971de53\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-1e66c121-a66a-4b1f-9b83-0fd99bf0fc2d\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-1f314764-cb73-4fc9-b863-8eca98ac36e9\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"effect-123a3936-f020-408a-ba0c-47873faf1534\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n }\r\n}\r\n",
+ "modifiedAssignment": "[if(and(equals(toLower(environment().name), toLower('AzureCloud')), equals(toLower(parameters('builtInAssignment')), toLower('IL5'))), 'NISTRev4', parameters('builtInAssignment'))]",
+ "assignmentName": "[format('{0} {1}', variables('modifiedAssignment'), resourceGroup().name)]",
+ "agentVmssAssignmentName": "[format('Deploy VMSS Agents {0}', resourceGroup().name)]",
+ "agentVmAssignmentName": "[format('Deploy VM Agents {0}', resourceGroup().name)]",
+ "contributorRoleDefinitionId": "[resourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]",
+ "lawsReaderRoleDefinitionId": "[resourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293')]"
+ },
+ "resources": [
+ {
+ "type": "Microsoft.Authorization/policyAssignments",
+ "apiVersion": "2020-09-01",
+ "name": "[variables('assignmentName')]",
+ "location": "[parameters('location')]",
+ "properties": {
+ "policyDefinitionId": "[createObject('NISTRev4', createObject('id', '/providers/Microsoft.Authorization/policySetDefinitions/cf25b9c1-bd23-4eb6-bd2c-f4f3ac644a5f', 'parameters', json(replace(variables('$fxv#0'), '', extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('operationsSubscriptionId'), parameters('logAnalyticsWorkspaceResourceGroupName')), 'Microsoft.OperationalInsights/workspaces', parameters('logAnalyticsWorkspaceName'))))), 'NISTRev5', createObject('id', '/providers/Microsoft.Authorization/policySetDefinitions/179d1daa-458f-4e47-8086-2a68d0d6c38f', 'parameters', json(variables('$fxv#1'))), 'IL5', createObject('id', '/providers/Microsoft.Authorization/policySetDefinitions/f9a961fa-3241-4b20-adc4-bbf8ad9d7197', 'parameters', json(replace(variables('$fxv#2'), '', extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('operationsSubscriptionId'), parameters('logAnalyticsWorkspaceResourceGroupName')), 'Microsoft.OperationalInsights/workspaces', parameters('logAnalyticsWorkspaceName'))))), 'CMMC', createObject('id', '/providers/Microsoft.Authorization/policySetDefinitions/b5629c75-5c77-4422-87b9-2509e680f8de', 'parameters', json(replace(variables('$fxv#3'), '', reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('operationsSubscriptionId'), parameters('logAnalyticsWorkspaceResourceGroupName')), 'Microsoft.OperationalInsights/workspaces', parameters('logAnalyticsWorkspaceName')), '2021-06-01').customerId))))[variables('modifiedAssignment')].id]",
+ "parameters": "[createObject('NISTRev4', createObject('id', '/providers/Microsoft.Authorization/policySetDefinitions/cf25b9c1-bd23-4eb6-bd2c-f4f3ac644a5f', 'parameters', json(replace(variables('$fxv#0'), '', extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('operationsSubscriptionId'), parameters('logAnalyticsWorkspaceResourceGroupName')), 'Microsoft.OperationalInsights/workspaces', parameters('logAnalyticsWorkspaceName'))))), 'NISTRev5', createObject('id', '/providers/Microsoft.Authorization/policySetDefinitions/179d1daa-458f-4e47-8086-2a68d0d6c38f', 'parameters', json(variables('$fxv#1'))), 'IL5', createObject('id', '/providers/Microsoft.Authorization/policySetDefinitions/f9a961fa-3241-4b20-adc4-bbf8ad9d7197', 'parameters', json(replace(variables('$fxv#2'), '', extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('operationsSubscriptionId'), parameters('logAnalyticsWorkspaceResourceGroupName')), 'Microsoft.OperationalInsights/workspaces', parameters('logAnalyticsWorkspaceName'))))), 'CMMC', createObject('id', '/providers/Microsoft.Authorization/policySetDefinitions/b5629c75-5c77-4422-87b9-2509e680f8de', 'parameters', json(replace(variables('$fxv#3'), '', reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('operationsSubscriptionId'), parameters('logAnalyticsWorkspaceResourceGroupName')), 'Microsoft.OperationalInsights/workspaces', parameters('logAnalyticsWorkspaceName')), '2021-06-01').customerId))))[variables('modifiedAssignment')].parameters]"
+ },
+ "identity": {
+ "type": "SystemAssigned"
+ }
+ },
+ {
+ "type": "Microsoft.Authorization/policyAssignments",
+ "apiVersion": "2020-09-01",
+ "name": "[variables('agentVmssAssignmentName')]",
+ "location": "[parameters('location')]",
+ "properties": {
+ "policyDefinitionId": "[tenantResourceId('Microsoft.Authorization/policySetDefinitions', '75714362-cae7-409e-9b99-a8e5075b7fad')]",
+ "parameters": {
+ "logAnalytics_1": {
+ "value": "[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('operationsSubscriptionId'), parameters('logAnalyticsWorkspaceResourceGroupName')), 'Microsoft.OperationalInsights/workspaces', parameters('logAnalyticsWorkspaceName'))]"
+ }
+ }
+ },
+ "identity": {
+ "type": "SystemAssigned"
+ }
+ },
+ {
+ "type": "Microsoft.Authorization/policyAssignments",
+ "apiVersion": "2020-09-01",
+ "name": "[variables('agentVmAssignmentName')]",
+ "location": "[parameters('location')]",
+ "properties": {
+ "policyDefinitionId": "[tenantResourceId('Microsoft.Authorization/policySetDefinitions', '55f3eceb-5573-4f18-9695-226972c6d74a')]",
+ "parameters": {
+ "logAnalytics_1": {
+ "value": "[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('operationsSubscriptionId'), parameters('logAnalyticsWorkspaceResourceGroupName')), 'Microsoft.OperationalInsights/workspaces', parameters('logAnalyticsWorkspaceName'))]"
+ }
+ }
+ },
+ "identity": {
+ "type": "SystemAssigned"
+ }
+ },
+ {
+ "type": "Microsoft.Authorization/roleAssignments",
+ "apiVersion": "2020-04-01-preview",
+ "name": "[guid(variables('contributorRoleDefinitionId'), variables('assignmentName'))]",
+ "properties": {
+ "roleDefinitionId": "[variables('contributorRoleDefinitionId')]",
+ "principalId": "[if(empty(variables('modifiedAssignment')), '', reference(resourceId('Microsoft.Authorization/policyAssignments', variables('assignmentName')), '2020-09-01', 'full').identity.principalId)]",
+ "principalType": "ServicePrincipal"
+ },
+ "dependsOn": [
+ "[resourceId('Microsoft.Authorization/policyAssignments', variables('assignmentName'))]"
+ ]
+ },
+ {
+ "type": "Microsoft.Authorization/roleAssignments",
+ "apiVersion": "2020-04-01-preview",
+ "name": "[guid(variables('contributorRoleDefinitionId'), variables('agentVmssAssignmentName'))]",
+ "properties": {
+ "roleDefinitionId": "[variables('contributorRoleDefinitionId')]",
+ "principalId": "[reference(resourceId('Microsoft.Authorization/policyAssignments', variables('agentVmssAssignmentName')), '2020-09-01', 'full').identity.principalId]",
+ "principalType": "ServicePrincipal"
+ },
+ "dependsOn": [
+ "[resourceId('Microsoft.Authorization/policyAssignments', variables('agentVmssAssignmentName'))]"
+ ]
+ },
+ {
+ "type": "Microsoft.Authorization/roleAssignments",
+ "apiVersion": "2020-04-01-preview",
+ "name": "[guid(variables('contributorRoleDefinitionId'), variables('agentVmAssignmentName'))]",
+ "properties": {
+ "roleDefinitionId": "[variables('contributorRoleDefinitionId')]",
+ "principalId": "[reference(resourceId('Microsoft.Authorization/policyAssignments', variables('agentVmAssignmentName')), '2020-09-01', 'full').identity.principalId]",
+ "principalType": "ServicePrincipal"
+ },
+ "dependsOn": [
+ "[resourceId('Microsoft.Authorization/policyAssignments', variables('agentVmAssignmentName'))]"
+ ]
+ },
+ {
+ "condition": "[parameters('deployRemediation')]",
+ "type": "Microsoft.PolicyInsights/remediations",
+ "apiVersion": "2019-07-01",
+ "name": "VM-Agent-Policy-Remediation",
+ "properties": {
+ "policyAssignmentId": "[resourceId('Microsoft.Authorization/policyAssignments', variables('agentVmAssignmentName'))]",
+ "resourceDiscoveryMode": "ReEvaluateCompliance"
+ },
+ "dependsOn": [
+ "[resourceId('Microsoft.Authorization/policyAssignments', variables('agentVmAssignmentName'))]"
+ ]
+ },
+ {
+ "type": "Microsoft.Resources/deployments",
+ "apiVersion": "2022-09-01",
+ "name": "[format('Assign-Laws-Role-Policy-{0}', resourceGroup().name)]",
+ "subscriptionId": "[parameters('operationsSubscriptionId')]",
+ "resourceGroup": "[parameters('logAnalyticsWorkspaceResourceGroupName')]",
+ "properties": {
+ "expressionEvaluationOptions": {
+ "scope": "inner"
+ },
+ "mode": "Incremental",
+ "parameters": {
+ "targetResourceId": {
+ "value": "[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('operationsSubscriptionId'), parameters('logAnalyticsWorkspaceResourceGroupName')), 'Microsoft.OperationalInsights/workspaces', parameters('logAnalyticsWorkspaceName'))]"
+ },
+ "roleDefinitionId": {
+ "value": "[variables('lawsReaderRoleDefinitionId')]"
+ },
+ "principalId": {
+ "value": "[reference(resourceId('Microsoft.Authorization/policyAssignments', variables('agentVmAssignmentName')), '2020-09-01', 'full').identity.principalId]"
+ }
+ },
+ "template": {
+ "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
+ "contentVersion": "1.0.0.0",
+ "metadata": {
+ "_generator": {
+ "name": "bicep",
+ "version": "0.24.24.22086",
+ "templateHash": "8686326864657481429"
+ }
+ },
+ "parameters": {
+ "targetResourceId": {
+ "type": "string"
+ },
+ "roleDefinitionId": {
+ "type": "string"
+ },
+ "principalId": {
+ "type": "string"
+ },
+ "principalType": {
+ "type": "string",
+ "defaultValue": "ServicePrincipal",
+ "allowedValues": [
+ "ForeignGroup",
+ "Group",
+ "ServicePrincipal",
+ "User"
+ ]
+ },
+ "description": {
+ "type": "string",
+ "defaultValue": ""
+ }
+ },
+ "resources": [
+ {
+ "type": "Microsoft.Authorization/roleAssignments",
+ "apiVersion": "2020-04-01-preview",
+ "name": "[guid(parameters('targetResourceId'), parameters('roleDefinitionId'), parameters('principalId'))]",
+ "properties": {
+ "principalId": "[parameters('principalId')]",
+ "principalType": "[parameters('principalType')]",
+ "roleDefinitionId": "[parameters('roleDefinitionId')]",
+ "description": "[parameters('description')]"
+ }
+ }
+ ]
+ }
+ },
+ "dependsOn": [
+ "[resourceId('Microsoft.Authorization/policyAssignments', variables('agentVmAssignmentName'))]"
+ ]
+ }
+ ]
+ }
+ }
+ },
+ {
+ "condition": "[parameters('deployDefender')]",
+ "type": "Microsoft.Resources/deployments",
+ "apiVersion": "2022-09-01",
+ "name": "[format('set-{0}-sub-defender', parameters('workloadName'))]",
+ "subscriptionId": "[parameters('workloadSubscriptionId')]",
+ "location": "[resourceGroup().location]",
+ "properties": {
+ "expressionEvaluationOptions": {
+ "scope": "inner"
+ },
+ "mode": "Incremental",
+ "parameters": {
+ "logAnalyticsWorkspaceId": {
+ "value": "[parameters('logAnalyticsWorkspaceResourceId')]"
+ },
+ "emailSecurityContact": {
+ "value": "[parameters('emailSecurityContact')]"
+ }
+ },
+ "template": {
+ "$schema": "https://schema.management.azure.com/schemas/2018-05-01/subscriptionDeploymentTemplate.json#",
+ "contentVersion": "1.0.0.0",
+ "metadata": {
+ "_generator": {
+ "name": "bicep",
+ "version": "0.24.24.22086",
+ "templateHash": "17349871984393503749"
+ }
+ },
+ "parameters": {
+ "bundle": {
+ "type": "array",
+ "defaultValue": "[if(equals(environment().name, 'AzureCloud'), createArray('Api', 'AppServices', 'Arm', 'CloudPosture', 'Containers', 'CosmosDbs', 'KeyVaults', 'OpenSourceRelationalDatabases', 'SqlServers', 'SqlServerVirtualMachines', 'StorageAccounts', 'VirtualMachines'), if(equals(environment().name, 'AzureUSGovernment'), createArray('Arm', 'Containers', 'OpenSourceRelationalDatabases', 'SqlServers', 'SqlServerVirtualMachines', 'StorageAccounts', 'VirtualMachines'), createArray()))]"
+ },
+ "enableAutoProvisioning": {
+ "type": "bool",
+ "defaultValue": true,
+ "metadata": {
+ "description": "Turn automatic deployment by Defender of the MMA (OMS VM extension) on or off"
+ }
+ },
+ "logAnalyticsWorkspaceId": {
+ "type": "string",
+ "metadata": {
+ "description": "Specify the ID of your custom Log Analytics workspace to collect Defender data."
+ }
+ },
+ "emailSecurityContact": {
+ "type": "string",
+ "metadata": {
+ "description": "Email address of the contact, in the form of john@doe.com"
+ }
+ },
+ "policySetDescription": {
+ "type": "string",
+ "defaultValue": "The Microsoft Cloud Security Benchmark initiative represents the policies and controls implementing security recommendations defined in Microsoft Cloud Security Benchmark v2, see https://aka.ms/azsecbm. This also serves as the Microsoft Defender for Cloud default policy initiative. You can directly assign this initiative, or manage its policies and compliance results within Microsoft Defender.",
+ "metadata": {
+ "description": "Policy Initiative description field"
+ }
+ },
+ "defenderSkuTier": {
+ "type": "string",
+ "defaultValue": "Standard",
+ "metadata": {
+ "description": "[Standard/Free] The SKU for Defender. It defaults to \"Standard\"."
+ }
+ }
+ },
+ "variables": {
+ "autoProvisioning": "[if(parameters('enableAutoProvisioning'), 'On', 'Off')]"
+ },
+ "resources": [
+ {
+ "copy": {
+ "name": "defenderPricing",
+ "count": "[length(parameters('bundle'))]",
+ "mode": "serial",
+ "batchSize": 1
+ },
+ "type": "Microsoft.Security/pricings",
+ "apiVersion": "2023-01-01",
+ "name": "[parameters('bundle')[copyIndex()]]",
+ "properties": {
+ "pricingTier": "[parameters('defenderSkuTier')]"
+ }
+ },
+ {
+ "type": "Microsoft.Security/autoProvisioningSettings",
+ "apiVersion": "2019-01-01",
+ "name": "default",
+ "properties": {
+ "autoProvision": "[variables('autoProvisioning')]"
+ }
+ },
+ {
+ "type": "Microsoft.Security/workspaceSettings",
+ "apiVersion": "2019-01-01",
+ "name": "default",
+ "properties": {
+ "workspaceId": "[parameters('logAnalyticsWorkspaceId')]",
+ "scope": "[subscription().id]"
+ }
+ },
+ {
+ "condition": "[not(empty(parameters('emailSecurityContact')))]",
+ "type": "Microsoft.Security/securityContacts",
+ "apiVersion": "2020-01-01-preview",
+ "name": "default",
+ "properties": {
+ "notificationsByRole": {
+ "roles": [
+ "AccountAdmin",
+ "Contributor",
+ "Owner",
+ "ServiceAdmin"
+ ],
+ "state": "On"
+ },
+ "alertNotifications": {
+ "state": "On"
+ },
+ "emails": "[parameters('emailSecurityContact')]"
+ }
+ },
+ {
+ "type": "Microsoft.Authorization/policyAssignments",
+ "apiVersion": "2022-06-01",
+ "name": "Microsoft Cloud Security Benchmark",
+ "properties": {
+ "displayName": "Defender Default",
+ "description": "[parameters('policySetDescription')]",
+ "enforcementMode": "DoNotEnforce",
+ "parameters": {},
+ "policyDefinitionId": "[tenantResourceId('Microsoft.Authorization/policySetDefinitions', '1f3afdf9-d0c9-4c3d-847f-89da613e70a8')]"
+ }
+ }
+ ]
+ }
+ }
+ }
+ ],
+ "outputs": {
+ "rg": {
+ "type": "string",
+ "value": "[if(parameters('existingResourceGroup'), parameters('resourceGroupName'), parameters('resourceGroupName'))]"
+ },
+ "location": {
+ "type": "string",
+ "value": "[parameters('location')]"
+ },
+ "virtualNetworkName": {
+ "type": "string",
+ "value": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('workloadSubscriptionId'), if(parameters('existingResourceGroup'), parameters('resourceGroupName'), parameters('resourceGroupName'))), 'Microsoft.Resources/deployments', 'spokeNetwork'), '2022-09-01').outputs.virtualNetworkName.value]"
+ },
+ "virtualNetworkAddressPrefix": {
+ "type": "string",
+ "value": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('workloadSubscriptionId'), if(parameters('existingResourceGroup'), parameters('resourceGroupName'), parameters('resourceGroupName'))), 'Microsoft.Resources/deployments', 'spokeNetwork'), '2022-09-01').outputs.virtualNetworkAddressPrefix.value]"
+ },
+ "virtualNetworkResourceId": {
+ "type": "string",
+ "value": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('workloadSubscriptionId'), if(parameters('existingResourceGroup'), parameters('resourceGroupName'), parameters('resourceGroupName'))), 'Microsoft.Resources/deployments', 'spokeNetwork'), '2022-09-01').outputs.virtualNetworkResourceId.value]"
+ },
+ "subnetName": {
+ "type": "string",
+ "value": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('workloadSubscriptionId'), if(parameters('existingResourceGroup'), parameters('resourceGroupName'), parameters('resourceGroupName'))), 'Microsoft.Resources/deployments', 'spokeNetwork'), '2022-09-01').outputs.subnetName.value]"
+ },
+ "subnetAddressPrefix": {
+ "type": "string",
+ "value": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('workloadSubscriptionId'), if(parameters('existingResourceGroup'), parameters('resourceGroupName'), parameters('resourceGroupName'))), 'Microsoft.Resources/deployments', 'spokeNetwork'), '2022-09-01').outputs.subnetAddressPrefix.value]"
+ },
+ "subnetResourceId": {
+ "type": "string",
+ "value": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('workloadSubscriptionId'), if(parameters('existingResourceGroup'), parameters('resourceGroupName'), parameters('resourceGroupName'))), 'Microsoft.Resources/deployments', 'spokeNetwork'), '2022-09-01').outputs.subnetResourceId.value]"
+ },
+ "networkSecurityGroupName": {
+ "type": "string",
+ "value": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('workloadSubscriptionId'), if(parameters('existingResourceGroup'), parameters('resourceGroupName'), parameters('resourceGroupName'))), 'Microsoft.Resources/deployments', 'spokeNetwork'), '2022-09-01').outputs.networkSecurityGroupName.value]"
+ },
+ "networkSecurityGroupResourceId": {
+ "type": "string",
+ "value": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('workloadSubscriptionId'), if(parameters('existingResourceGroup'), parameters('resourceGroupName'), parameters('resourceGroupName'))), 'Microsoft.Resources/deployments', 'spokeNetwork'), '2022-09-01').outputs.networkSecurityGroupResourceId.value]"
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/bicep/add-ons/Imaging/modules/userAssignedIdentity.bicep b/src/bicep/add-ons/Imaging/modules/userAssignedIdentity.bicep
new file mode 100644
index 000000000..7c1e6860f
--- /dev/null
+++ b/src/bicep/add-ons/Imaging/modules/userAssignedIdentity.bicep
@@ -0,0 +1,13 @@
+param location string
+param name string
+param tags object
+
+resource userAssignedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2018-11-30' = {
+ name: name
+ location: location
+ tags: contains(tags, 'Microsoft.ManagedIdentity/userAssignedIdentities') ? tags['Microsoft.ManagedIdentity/userAssignedIdentities'] : {}
+}
+
+output clientId string = userAssignedIdentity.properties.clientId
+output principalId string = userAssignedIdentity.properties.principalId
+output resourceId string = userAssignedIdentity.id
diff --git a/src/bicep/add-ons/Imaging/modules/virtual-network-peerings.bicep b/src/bicep/add-ons/Imaging/modules/virtual-network-peerings.bicep
new file mode 100644
index 000000000..6142ac788
--- /dev/null
+++ b/src/bicep/add-ons/Imaging/modules/virtual-network-peerings.bicep
@@ -0,0 +1,12 @@
+param name string
+param remoteVirtualNetworkResourceId string
+
+resource virtualNetworkPeering 'Microsoft.Network/virtualNetworks/virtualNetworkPeerings@2021-02-01' = {
+ name: name
+ properties: {
+ allowForwardedTraffic: true
+ remoteVirtualNetwork: {
+ id: remoteVirtualNetworkResourceId
+ }
+ }
+}
diff --git a/src/bicep/add-ons/Imaging/modules/virtualMachine.bicep b/src/bicep/add-ons/Imaging/modules/virtualMachine.bicep
new file mode 100644
index 000000000..659080cc2
--- /dev/null
+++ b/src/bicep/add-ons/Imaging/modules/virtualMachine.bicep
@@ -0,0 +1,108 @@
+// param diskEncryptionSetResourceId string
+@secure()
+param localAdministratorPassword string
+@secure()
+param localAdministratorUsername string
+param location string
+param marketplaceImageOffer string
+param marketplaceImagePublisher string
+param marketplaceImageSKU string
+param computeGalleryImageResourceId string
+param sourceImageType string
+param subnetResourceId string
+param tags object
+param userAssignedIdentityResourceId string
+param virtualMachineName string
+param virtualMachineSize string
+
+var imageReference = sourceImageType == 'AzureComputeGallery' ? {
+ id: computeGalleryImageResourceId
+} : {
+ publisher: marketplaceImagePublisher
+ offer: marketplaceImageOffer
+ sku: marketplaceImageSKU
+ version: 'latest'
+}
+
+resource nic 'Microsoft.Network/networkInterfaces@2022-05-01' = {
+ name: 'nic-${virtualMachineName}'
+ location: location
+ tags: contains(tags, 'Microsoft.Network/networkInterfaces') ? tags['Microsoft.Network/networkInterfaces'] : {}
+ properties: {
+ ipConfigurations: [
+ {
+ name: 'ipconfig1'
+ properties: {
+ privateIPAllocationMethod: 'Dynamic'
+ subnet: {
+ id: subnetResourceId
+ }
+ }
+ }
+ ]
+ }
+}
+
+resource virtualMachine 'Microsoft.Compute/virtualMachines@2022-03-01' = {
+ name: virtualMachineName
+ location: location
+ tags: contains(tags, 'Microsoft.Compute/virtualMachines') ? tags['Microsoft.Compute/virtualMachines'] : {}
+ identity: {
+ type: 'UserAssigned'
+ userAssignedIdentities: {
+ '${userAssignedIdentityResourceId}': {}
+ }
+ }
+ properties: {
+ hardwareProfile: {
+ vmSize: virtualMachineSize
+ }
+ osProfile: {
+ computerName: virtualMachineName
+ adminUsername: localAdministratorUsername
+ adminPassword: localAdministratorPassword
+ }
+ storageProfile: {
+ imageReference: imageReference
+ osDisk: {
+ createOption: 'FromImage'
+ deleteOption: 'Delete'
+ managedDisk: {
+ /* Not supported yet: https://learn.microsoft.com/en-us/azure/virtual-machines/image-version-encryption#limitations
+ diskEncryptionSet: {
+ id: diskEncryptionSetResourceId
+ }
+ */
+ storageAccountType: 'StandardSSD_LRS'
+ }
+ name: 'disk-${virtualMachineName}'
+ }
+ }
+ networkProfile: {
+ networkInterfaces: [
+ {
+ id: nic.id
+ properties: {
+ deleteOption: 'Delete'
+ }
+ }
+ ]
+ }
+ diagnosticsProfile: {
+ bootDiagnostics: {
+ enabled: false
+ }
+ }
+ securityProfile: {
+ // encryptionAtHost: true
+ uefiSettings: {
+ secureBootEnabled: true
+ vTpmEnabled: true
+ }
+ securityType: 'TrustedLaunch'
+ }
+ }
+}
+
+output name string = virtualMachine.name
+output resourceId string = virtualMachine.id
diff --git a/src/bicep/add-ons/Imaging/modules/virtualNetwork.bicep b/src/bicep/add-ons/Imaging/modules/virtualNetwork.bicep
new file mode 100644
index 000000000..a051d411b
--- /dev/null
+++ b/src/bicep/add-ons/Imaging/modules/virtualNetwork.bicep
@@ -0,0 +1,18 @@
+param principalId string
+param virtualNetworkName string
+
+var roleDefinitionId = '9980e02c-c2be-4d73-94e8-173b1dc7cf3c' // Virtual Machine Contributor | https://learn.microsoft.com/en-us/azure/role-based-access-control/built-in-roles#virtual-machine-contributor
+
+resource virtualNetwork 'Microsoft.Network/virtualNetworks@2023-05-01' existing = {
+ name: virtualNetworkName
+}
+
+resource roleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
+ scope: virtualNetwork
+ name: guid(principalId, roleDefinitionId, virtualNetwork.id)
+ properties: {
+ roleDefinitionId: resourceId('Microsoft.Authorization/roleDefinitions', roleDefinitionId)
+ principalId: principalId
+ principalType: 'ServicePrincipal'
+ }
+}
diff --git a/src/bicep/add-ons/Imaging/modules/virtualNetworkPeerings.bicep b/src/bicep/add-ons/Imaging/modules/virtualNetworkPeerings.bicep
new file mode 100644
index 000000000..70053bfa3
--- /dev/null
+++ b/src/bicep/add-ons/Imaging/modules/virtualNetworkPeerings.bicep
@@ -0,0 +1,16 @@
+param existingLocalVirtualNetworkName string
+param existingRemoteVirtualNetworkName string
+param existingRemoteVirtualNetworkResourceGroupName string
+
+resource existingLocalVirtualNetworkName_peering_to_remote_vnet 'Microsoft.Network/virtualNetworks/virtualNetworkPeerings@2021-02-01' = {
+ name: '${existingLocalVirtualNetworkName}/to-vnet-${existingRemoteVirtualNetworkName}'
+ properties: {
+ allowVirtualNetworkAccess: true
+ allowForwardedTraffic: true
+ allowGatewayTransit: false
+ useRemoteGateways: false
+ remoteVirtualNetwork: {
+ id: resourceId(existingRemoteVirtualNetworkResourceGroupName, 'Microsoft.Network/virtualNetworks', existingRemoteVirtualNetworkName)
+ }
+ }
+}
diff --git a/src/bicep/add-ons/Imaging/scripts/New-AzureZeroTrustImageBuild.ps1 b/src/bicep/add-ons/Imaging/scripts/New-AzureZeroTrustImageBuild.ps1
new file mode 100644
index 000000000..4dc7d04a2
--- /dev/null
+++ b/src/bicep/add-ons/Imaging/scripts/New-AzureZeroTrustImageBuild.ps1
@@ -0,0 +1,132 @@
+[CmdletBinding(SupportsShouldProcess)]
+param(
+ [Parameter(Mandatory)]
+ [string]$Parameters
+)
+
+$ErrorActionPreference = 'Stop'
+
+try
+{
+ # Convert JSON string to PowerShell
+ $Values = $Parameters.Replace('\"', '"') | ConvertFrom-Json
+
+ # Set Variables
+ $DestinationGalleryName = $Values.computeGalleryResourceId.Split('/')[8]
+ $DestinationGalleryResourceGroupName = $Values.computeGalleryResourceId.Split('/')[4]
+ $DestinationImageDefinitionName = $Values.imageDefinitionName
+
+ # Import Modules
+ Import-Module -Name 'Az.Accounts','Az.Compute','Az.Resources'
+ Write-Output "$DestinationImageDefinitionName | $DestinationGalleryResourceGroupName | Imported the required modules."
+
+ # Disable saving of Azure Context
+ Disable-AzContextAutosave -Scope Process | Out-Null
+ Write-Output "$DestinationImageDefinitionName | $DestinationGalleryResourceGroupName | Disabled saving of Azure Context."
+
+ # Connect to Azure using the System Assigned Identity
+ $AzureContext = (Connect-AzAccount -Environment $Values.environmentName -Subscription $Values.subscriptionId -Tenant $Values.tenantId -Identity -AccountId $Values.userAssignedIdentityClientId).Context
+ Write-Output "$DestinationImageDefinitionName | $DestinationGalleryResourceGroupName | Connected to Azure."
+
+ # Cleanup previous image build
+ $RunCommandNames = @('generalizeVirtualMachine','removeVirtualMachine','restartVirtualMachine')
+ foreach($RunCommandName in $RunCommandNames)
+ {
+ Remove-AzVMRunCommand -ResourceGroupName $Values.resourceGroupName -VMName $Values.managementVirtualMachineName -RunCommandName $RunCommandName
+ Write-Output "$DestinationImageDefinitionName | $DestinationGalleryResourceGroupName | Removed '$RunCommandName' Run Command"
+ }
+
+ # Get date on the latest image gallery version
+ $CurrentImageVersionDate = (Get-AzGalleryImageVersion -ResourceGroupName $DestinationGalleryResourceGroupName -GalleryName $DestinationGalleryName -GalleryImageDefinitionName $DestinationImageDefinitionName -DefaultProfile $AzureContext | Where-Object {$_.ProvisioningState -eq 'Succeeded'}).PublishingProfile.PublishedDate | Sort-Object | Select-Object -Last 1
+ Write-Output "$DestinationImageDefinitionName | $DestinationGalleryResourceGroupName | Compute Gallery Image (Destination), Latest Version Date: $CurrentImageVersionDate."
+
+ switch($Values.sourceImageType)
+ {
+ 'AzureComputeGallery' {
+ # Set Variables
+ $SourceGalleryName = $Values.computeGalleryImageResourceId.Split('/')[8]
+ $SourceGalleryResourceGroupName = $Values.computeGalleryImageResourceId.Split('/')[4]
+ $SourceImageDefinitionName = $Values.computeGalleryImageResourceId.Split('/')[10]
+
+ # Get the date of the latest image definition version
+ $SourceImageVersionDate = (Get-AzGalleryImageVersion -ResourceGroupName $SourceGalleryResourceGroupName -GalleryName $SourceGalleryName -GalleryImageDefinitionName $SourceImageDefinitionName -DefaultProfile $AzureContext | Where-Object {$_.PublishingProfile.ExcludeFromLatest -eq $false -and $_.ProvisioningState -eq 'Succeeded'}).PublishingProfile.PublishedDate | Sort-Object | Select-Object -Last 1
+ Write-Output "$DestinationImageDefinitionName | $DestinationGalleryResourceGroupName | Compute Gallery Image (Source), Latest Version Date: $SourceImageVersionDate."
+ }
+ 'AzureMarketplace' {
+ # Get the date of the latest marketplace image version
+ $ImageVersionDateRaw = (Get-AzVMImage -Location $Values.location -PublisherName $Values.marketplaceImagePublisher -Offer $Values.marketplaceImageOffer -Skus $Values.marketplaceImageSku -DefaultProfile $AzureContext | Sort-Object -Property 'Version' -Descending | Select-Object -First 1).Version.Split('.')[-1]
+ $Year = '20' + $ImageVersionDateRaw.Substring(0,2)
+ $Month = $ImageVersionDateRaw.Substring(2,2)
+ $Day = $ImageVersionDateRaw.Substring(4,2)
+ $SourceImageVersionDate = Get-Date -Year $Year -Month $Month -Day $Day -Hour 00 -Minute 00 -Second 00
+ Write-Output "$DestinationImageDefinitionName | $DestinationGalleryResourceGroupName | Marketplace Image (Source), Latest Version Date: $SourceImageVersionDate."
+ }
+ }
+
+ # If the latest source image was released after the last image build then trigger a new image build
+ if($SourceImageVersionDate -gt $CurrentImageVersionDate -or !$CurrentImageVersionDate)
+ {
+ Write-Output "$DestinationImageDefinitionName | $DestinationGalleryResourceGroupName | Image build initiated with a new source image version."
+ $TemplateParameters = @{
+ arcGisProInstaller = $Values.arcGisProInstaller
+ computeGalleryImageResourceId = $Values.computeGalleryImageResourceId
+ computeGalleryName = $Values.computeGalleryResourceId.Split('/')[8]
+ containerName = $Values.containerName
+ diskEncryptionSetResourceId = $Values.diskEncryptionSetResourceId
+ enableBuildAutomation = if($Values.enableBuildAutomation -eq 'true'){$true}else{$false}
+ excludeFromLatest = $Values.excludeFromLatest
+ hybridUseBenefit = if($Values.hybridUseBenefit -eq 'true'){$true}else{$false}
+ imageDefinitionName = $Values.imageDefinitionName
+ imageMajorVersion = [int]$Values.imageMajorVersion
+ imageMinorVersion = [int]$Values.imageMinorVersion
+ imageVirtualMachineName = $Values.imageVirtualMachineName
+ installAccess = if($Values.installAccess -eq 'true'){$true}else{$false}
+ installArcGisPro = if($Values.installArcGisPro -eq 'true'){$true}else{$false}
+ installExcel = if($Values.installExcel -eq 'true'){$true}else{$false}
+ installOneDrive = if($Values.installOneDrive -eq 'true'){$true}else{$false}
+ installOneNote = if($Values.installOneNote -eq 'true'){$true}else{$false}
+ installOutlook = if($Values.installOutlook -eq 'true'){$true}else{$false}
+ installPowerPoint = if($Values.installPowerPoint -eq 'true'){$true}else{$false}
+ installProject = if($Values.installProject -eq 'true'){$true}else{$false}
+ installPublisher = if($Values.installPublisher -eq 'true'){$true}else{$false}
+ installSkypeForBusiness = if($Values.installSkypeForBusiness -eq 'true'){$true}else{$false}
+ installTeams = if($Values.installTeams -eq 'true'){$true}else{$false}
+ installVirtualDesktopOptimizationTool = if($Values.installVirtualDesktopOptimizationTool -eq 'true'){$true}else{$false}
+ installVisio = if($Values.installVisio -eq 'true'){$true}else{$false}
+ installWord = if($Values.installWord -eq 'true'){$true}else{$false}
+ keyVaultName = $Values.keyVaultName
+ managementVirtualMachineName = $Values.managementVirtualMachineName
+ marketplaceImageOffer = $Values.marketplaceImageOffer
+ marketplaceImagePublisher = $Values.marketplaceImagePublisher
+ marketplaceImageSKU = $Values.marketplaceImageSKU
+ msrdcwebrtcsvcInstaller = $Values.msrdcwebrtcsvcInstaller
+ officeInstaller = $Values.officeInstaller
+ replicaCount = [int]$Values.replicaCount
+ runbookExecution = $true
+ sourceImageType = $Values.sourceImageType
+ storageAccountResourceId = $Values.storageAccountResourceId
+ subnetResourceId = $Values.subnetResourceId
+ teamsInstaller = $Values.teamsInstaller
+ userAssignedIdentityClientId = $Values.userAssignedIdentityClientId
+ userAssignedIdentityPrincipalId = $Values.userAssignedIdentityPrincipalId
+ userAssignedIdentityResourceId = $Values.userAssignedIdentityResourceId
+ vcRedistInstaller = $Values.vcRedistInstaller
+ vDOTInstaller = $Values.vDOTInstaller
+ virtualMachineSize = $Values.virtualMachineSize
+ }
+ if($Values.customizations -ne '[]'){$TemplateParameters.Add('customizations', $Values.customizations)}
+ if($Values.tags -ne '{}'){$TemplateParameters.Add('tags', $Values.tags)}
+ New-AzResourceGroupDeployment -ResourceGroupName $Values.resourceGroupName -TemplateSpecId $Values.templateSpecResourceId -TemplateParameterObject $TemplateParameters -DefaultProfile $AzureContext
+ Write-Output "$DestinationImageDefinitionName | $DestinationGalleryResourceGroupName | Image build succeeded. New image version available in the destination Compute Gallery."
+ }
+ else
+ {
+ Write-Output "$DestinationImageDefinitionName | $DestinationGalleryResourceGroupName | Image build not required. The source image version is older than the latest destination image version."
+ }
+}
+catch
+{
+ Write-Output "$DestinationImageDefinitionName | $DestinationGalleryResourceGroupName | Image build failed. Review the deployment errors in the Azure Portal and correct the issue."
+ Write-Output $($Error[0] | Select-Object *)
+ throw
+}
\ No newline at end of file
diff --git a/src/bicep/add-ons/Imaging/solution.bicep b/src/bicep/add-ons/Imaging/solution.bicep
new file mode 100644
index 000000000..3f9fe5a9f
--- /dev/null
+++ b/src/bicep/add-ons/Imaging/solution.bicep
@@ -0,0 +1,484 @@
+targetScope = 'subscription'
+
+@description('The file name of the ArcGIS Pro installer in Azure Blobs.')
+param arcGisProInstaller string = ''
+
+@description('The name for the action group resource.')
+param actionGroupName string = ''
+
+@description('The name for the automation account resource.')
+param automationAccountName string
+
+@description('The private DNS zone resource ID for the automation account resource.')
+param automationAccountPrivateDnsZoneResourceId string
+
+@description('The name of the Azure Firewall.')
+param azureFirewallName string
+
+@description('The resource ID of the compute gallery image.')
+param computeGalleryImageResourceId string = ''
+
+@description('The name of the compute gallery resource.')
+param computeGalleryName string
+
+@description('The name of the container in the storage account where the installer files are located.')
+param containerName string
+
+@description('The array of customizations to apply to the image.')
+param customizations array = []
+
+@description('The resource ID of the disk encryption set to use for the management virtual machine.')
+param diskEncryptionSetResourceId string = ''
+
+@description('The distribution group for email notifications.')
+param distributionGroup string = ''
+
+
+@description('Defender for Cloud enabled.')
+param deployDefender bool = false
+
+@description('Deploy Policy enabled.')
+param deployPolicy bool = false
+
+
+@description('The suffix to append to deployment names.')
+param deploymentNameSuffix string = utcNow('yyMMddHHs')
+
+@secure()
+@description('The password for the domain join account.')
+param domainJoinPassword string = ''
+
+@description('The user principal name for the domain join account.')
+param domainJoinUserPrincipalName string = ''
+
+@description('The domain name to join.')
+param domainName string = ''
+
+@description('The email address for the security contact.')
+param emailSecurityContact string
+
+@description('Determines whether to enable build automation.')
+param enableBuildAutomation bool
+
+@description('Determines whether to exclude the image from the latest version.')
+param excludeFromLatest bool = true
+
+@description('Determines whether to use an existing resource group.')
+param existingResourceGroup bool = false
+
+@description('The array of policy assignment IDs to exempt to prevent issues with the build process.')
+param exemptPolicyAssignmentIds array = []
+
+@description('The hub resource group name.')
+param hubResourceGroupName string
+
+@description('The name of hub subscription.')
+param hubSubscriptionId string
+
+@description('The hub virtual network name.')
+param hubVirtualNetworkName string
+
+@description('Determines whether to use the hybrid use benefit.')
+param hybridUseBenefit bool
+
+@description('The name of the hybrid worker (virtual machine) if using build automation.')
+param hybridWorkerName string = ''
+
+@description('The name prefix for the image definition resource.')
+param imageDefinitionNamePrefix string
+
+@description('The major version for the name of the image version resource.')
+param imageMajorVersion int
+
+@description('The minor version for the name of the image version resource.')
+param imageMinorVersion int
+
+@description('Determines whether to install Access.')
+param installAccess bool
+
+@description('Determines whether to install ArcGIS Pro.')
+param installArcGisPro bool
+
+@description('Determines whether to install Excel.')
+param installExcel bool
+
+@description('Determines whether to install OneDrive.')
+param installOneDrive bool
+
+@description('Determines whether to install OneNote.')
+param installOneNote bool
+
+@description('Determines whether to install Outlook.')
+param installOutlook bool
+
+@description('Determines whether to install PowerPoint.')
+param installPowerPoint bool
+
+@description('Determines whether to install Project.')
+param installProject bool
+
+@description('Determines whether to install Publisher.')
+param installPublisher bool
+
+@description('Determines whether to install Skype for Business.')
+param installSkypeForBusiness bool
+
+@description('Determines whether to install Teams.')
+param installTeams bool
+
+@description('Determines whether to install the Virtual Desktop Optimization Tool.')
+param installVirtualDesktopOptimizationTool bool
+
+@description('Determines whether to install Visio.')
+param installVisio bool
+
+@description('Determines whether to install Word.')
+param installWord bool
+
+@description('The name of the key vault resource.')
+param keyVaultName string
+
+@description('The private DNS zone resource ID for the key vault resource.')
+param keyVaultPrivateDnsZoneResourceId string
+
+@secure()
+@description('The password for the local administrator account.')
+param localAdministratorPassword string
+
+@description('The username for the local administrator account.')
+param localAdministratorUsername string
+
+@description('The location for the resources.')
+param location string = deployment().location
+
+@description('The resource ID of the log analytics workspace if using build automation and desired.')
+param logAnalyticsWorkspaceResourceId string = ''
+
+@description('The log analytics workspace name.')
+param logAnalyticsWorkspaceName string
+
+@description('The resource ID of the log analytics workspace if using build automation and desired.')
+param spokelogAnalyticsWorkspaceResourceId string
+
+@description('The marketplace image offer.')
+param marketplaceImageOffer string = ''
+
+@description('The marketplace image publisher.')
+param marketplaceImagePublisher string = ''
+
+@description('The marketplace image SKU.')
+param marketplaceImageSKU string = ''
+
+@description('The file name of the msrdcwebrtcsvc installer in Azure Blobs.')
+param msrdcwebrtcsvcInstaller string = ''
+
+@description('The file name of the Office installer in Azure Blobs.')
+param officeInstaller string = ''
+
+@description('The distinguished name of the organizational unit to join.')
+param oUPath string = ''
+
+@description('The policy name')
+param policy string = ''
+
+@description('The count of replicas for the image version resource.')
+param replicaCount int
+
+@description('The name of the resource group.')
+param resourceGroupName string
+
+@description('The prefix for the resource names.')
+param resourcePrefix string
+
+
+@allowed([
+ 'AzureComputeGallery'
+ 'AzureMarketplace'
+])
+@description('The type of source image.')
+param sourceImageType string
+
+@description('The resource ID of the storage account where the installers and scripts are stored in Azure Blobs.')
+param storageAccountResourceId string
+
+@description('The subnet address prefix.')
+param subnetAddressPrefix string
+
+@description('The key value pairs of meta data to apply to the resources.')
+param tags object = {}
+
+@description('The file name of the Teams installer in Azure Blobs.')
+param teamsInstaller string = ''
+
+@description('The name of the user assigned identity resource.')
+param userAssignedIdentityName string
+
+@description('The file name of the vcRedist installer in Azure Blobs.')
+param vcRedistInstaller string = ''
+
+@description('The file name of the vDOT installer in Azure Blobs.')
+param vDOTInstaller string = ''
+
+@description('The virtual network address prefix.')
+param virtualNetworkAddressPrefix string
+
+@description('The size of the image virtual machine.')
+param virtualMachineSize string
+
+@description('The workload subscription id.')
+param workloadSubscriptionId string
+
+var imageDefinitionName = empty(computeGalleryImageResourceId) ? '${imageDefinitionNamePrefix}-${marketplaceImageSKU}' : '${imageDefinitionNamePrefix}-${split(computeGalleryImageResourceId, '/')[10]}'
+var imageVirtualMachineName = take('vmimg-${uniqueString(deploymentNameSuffix)}', 15)
+var managementVirtualMachineName = empty(hybridWorkerName) ? take('vmmgt-${uniqueString(deploymentNameSuffix)}', 15) : hybridWorkerName
+var subscriptionId = subscription().subscriptionId
+var timeZones = {
+ australiacentral: 'AUS Eastern Standard Time'
+ australiacentral2: 'AUS Eastern Standard Time'
+ australiaeast: 'AUS Eastern Standard Time'
+ australiasoutheast: 'AUS Eastern Standard Time'
+ brazilsouth: 'E. South America Standard Time'
+ brazilsoutheast: 'E. South America Standard Time'
+ canadacentral: 'Eastern Standard Time'
+ canadaeast: 'Eastern Standard Time'
+ centralindia: 'India Standard Time'
+ centralus: 'Central Standard Time'
+ chinaeast: 'China Standard Time'
+ chinaeast2: 'China Standard Time'
+ chinanorth: 'China Standard Time'
+ chinanorth2: 'China Standard Time'
+ eastasia: 'China Standard Time'
+ eastus: 'Eastern Standard Time'
+ eastus2: 'Eastern Standard Time'
+ francecentral: 'Central Europe Standard Time'
+ francesouth: 'Central Europe Standard Time'
+ germanynorth: 'Central Europe Standard Time'
+ germanywestcentral: 'Central Europe Standard Time'
+ japaneast: 'Tokyo Standard Time'
+ japanwest: 'Tokyo Standard Time'
+ jioindiacentral: 'India Standard Time'
+ jioindiawest: 'India Standard Time'
+ koreacentral: 'Korea Standard Time'
+ koreasouth: 'Korea Standard Time'
+ northcentralus: 'Central Standard Time'
+ northeurope: 'GMT Standard Time'
+ norwayeast: 'Central Europe Standard Time'
+ norwaywest: 'Central Europe Standard Time'
+ southafricanorth: 'South Africa Standard Time'
+ southafricawest: 'South Africa Standard Time'
+ southcentralus: 'Central Standard Time'
+ southeastasia: 'Singapore Standard Time'
+ southindia: 'India Standard Time'
+ swedencentral: 'Central Europe Standard Time'
+ switzerlandnorth: 'Central Europe Standard Time'
+ switzerlandwest: 'Central Europe Standard Time'
+ uaecentral: 'Arabian Standard Time'
+ uaenorth: 'Arabian Standard Time'
+ uksouth: 'GMT Standard Time'
+ ukwest: 'GMT Standard Time'
+ usdodcentral: 'Central Standard Time'
+ usdodeast: 'Eastern Standard Time'
+ usgovarizona: 'Mountain Standard Time'
+ usgovtexas: 'Central Standard Time'
+ usgovvirginia: 'Eastern Standard Time'
+ westcentralus: 'Mountain Standard Time'
+ westeurope: 'Central Europe Standard Time'
+ westindia: 'India Standard Time'
+ westus: 'Pacific Standard Time'
+ westus2: 'Pacific Standard Time'
+ westus3: 'Mountain Standard Time'
+}
+
+resource hubVirtualNetwork 'Microsoft.Network/virtualNetworks@2023-05-01' existing = {
+ scope: resourceGroup(hubSubscriptionId, hubResourceGroupName)
+ name: hubVirtualNetworkName
+}
+
+resource azureFirewall 'Microsoft.Network/azureFirewalls@2023-05-01' existing = {
+ scope: resourceGroup(hubSubscriptionId, hubResourceGroupName)
+ name: azureFirewallName
+}
+
+resource rg 'Microsoft.Resources/resourceGroups@2019-05-01' = if (!existingResourceGroup) {
+ name: resourceGroupName
+ location: location
+ tags: tags
+}
+
+module tier3 'modules/tier3.bicep' = {
+ name: 'tier3-${deploymentNameSuffix}'
+ scope: resourceGroup(subscriptionId, (existingResourceGroup ? rg.name : resourceGroupName))
+ params: {
+ deployDefender: deployDefender
+ deployPolicy: deployPolicy
+ emailSecurityContact: emailSecurityContact
+ existingResourceGroup: existingResourceGroup
+ firewallPrivateIPAddress: azureFirewall.properties.ipConfigurations[0].properties.privateIPAddress
+ hubResourceGroupName: hubResourceGroupName
+ hubSubscriptionId: hubSubscriptionId
+ hubVirtualNetworkName: hubVirtualNetwork.name
+ hubVirtualNetworkResourceId: hubVirtualNetwork.id
+ location: location
+ logAnalyticsWorkspaceName: logAnalyticsWorkspaceName
+ logAnalyticsWorkspaceResourceId: spokelogAnalyticsWorkspaceResourceId
+ policy: policy
+ resourceGroupName: existingResourceGroup ? resourceGroupName : rg.name
+ resourcePrefix: resourcePrefix
+ subnetAddressPrefix: subnetAddressPrefix
+ virtualNetworkAddressPrefix: virtualNetworkAddressPrefix
+ workloadSubscriptionId: workloadSubscriptionId
+ }
+}
+
+module baseline 'modules/baseline.bicep' = {
+ name: 'baseline-${deploymentNameSuffix}'
+ params: {
+ computeGalleryName: computeGalleryName
+ deploymentNameSuffix: deploymentNameSuffix
+ diskEncryptionSetResourceId: diskEncryptionSetResourceId
+ enableBuildAutomation: enableBuildAutomation
+ exemptPolicyAssignmentIds: exemptPolicyAssignmentIds
+ location: location
+ resourceGroupName: existingResourceGroup ? resourceGroupName : rg.name
+ storageAccountResourceId: storageAccountResourceId
+ subscriptionId: subscriptionId
+ tags: tags
+ userAssignedIdentityName: userAssignedIdentityName
+ }
+ dependsOn: [
+ tier3
+ ]
+}
+
+module buildAutomation 'modules/buildAutomation.bicep' = if (enableBuildAutomation) {
+ name: 'build-automation-${deploymentNameSuffix}'
+ params: {
+ actionGroupName: actionGroupName
+ arcGisProInstaller: arcGisProInstaller
+ automationAccountName: automationAccountName
+ automationAccountPrivateDnsZoneResourceId: automationAccountPrivateDnsZoneResourceId
+ computeGalleryImageResourceId: computeGalleryImageResourceId
+ computeGalleryResourceId: baseline.outputs.computeGalleryResourceId
+ containerName: containerName
+ customizations: customizations
+ deploymentNameSuffix: deploymentNameSuffix
+ diskEncryptionSetResourceId: diskEncryptionSetResourceId
+ distributionGroup: distributionGroup
+ domainJoinPassword: domainJoinPassword
+ domainJoinUserPrincipalName: domainJoinUserPrincipalName
+ domainName: domainName
+ enableBuildAutomation: enableBuildAutomation
+ excludeFromLatest: excludeFromLatest
+ hybridUseBenefit: hybridUseBenefit
+ imageDefinitionName: imageDefinitionName
+ imageMajorVersion: imageMajorVersion
+ imageMinorVersion: imageMinorVersion
+ imageVirtualMachineName: imageVirtualMachineName
+ installAccess: installAccess
+ installArcGisPro: installArcGisPro
+ installExcel: installExcel
+ installOneDrive: installOneDrive
+ installOneNote: installOneNote
+ installOutlook: installOutlook
+ installPowerPoint: installPowerPoint
+ installProject: installProject
+ installPublisher: installPublisher
+ installSkypeForBusiness: installSkypeForBusiness
+ installTeams: installTeams
+ installVirtualDesktopOptimizationTool: installVirtualDesktopOptimizationTool
+ installVisio: installVisio
+ installWord: installWord
+ keyVaultName: keyVaultName
+ keyVaultPrivateDnsZoneResourceId: keyVaultPrivateDnsZoneResourceId
+ localAdministratorPassword: localAdministratorPassword
+ localAdministratorUsername: localAdministratorUsername
+ location: location
+ logAnalyticsWorkspaceResourceId: logAnalyticsWorkspaceResourceId
+ managementVirtualMachineName: managementVirtualMachineName
+ marketplaceImageOffer: marketplaceImageOffer
+ marketplaceImagePublisher: marketplaceImagePublisher
+ marketplaceImageSKU: marketplaceImageSKU
+ msrdcwebrtcsvcInstaller: msrdcwebrtcsvcInstaller
+ officeInstaller: officeInstaller
+ oUPath: oUPath
+ replicaCount: replicaCount
+ resourceGroupName: existingResourceGroup ? resourceGroupName : rg.name
+ sourceImageType: sourceImageType
+ storageAccountResourceId: storageAccountResourceId
+ subnetResourceId: tier3.outputs.subnetResourceId
+ subscriptionId: subscriptionId
+ tags: tags
+ teamsInstaller: teamsInstaller
+ timeZone: timeZones[location]
+ userAssignedIdentityClientId: baseline.outputs.userAssignedIdentityClientId
+ userAssignedIdentityPrincipalId: baseline.outputs.userAssignedIdentityPrincipalId
+ userAssignedIdentityResourceId: baseline.outputs.userAssignedIdentityResourceId
+ vcRedistInstaller: vcRedistInstaller
+ vDOTInstaller: vDOTInstaller
+ virtualMachineSize: virtualMachineSize
+ }
+ dependsOn: [
+ tier3
+ ]
+}
+
+module imageBuild 'modules/imageBuild.bicep' = {
+ name: 'image-build-${deploymentNameSuffix}'
+ scope: resourceGroup(subscriptionId, (existingResourceGroup ? rg.name : resourceGroupName))
+ params: {
+ arcGisProInstaller: arcGisProInstaller
+ computeGalleryImageResourceId: computeGalleryImageResourceId
+ computeGalleryName: computeGalleryName
+ containerName: containerName
+ customizations: customizations
+ deploymentNameSuffix: deploymentNameSuffix
+ diskEncryptionSetResourceId: diskEncryptionSetResourceId
+ enableBuildAutomation: enableBuildAutomation
+ excludeFromLatest: excludeFromLatest
+ hybridUseBenefit: hybridUseBenefit
+ imageDefinitionName: imageDefinitionName
+ imageMajorVersion: imageMajorVersion
+ imageMinorVersion: imageMinorVersion
+ imageVirtualMachineName: imageVirtualMachineName
+ installAccess: installAccess
+ installArcGisPro: installArcGisPro
+ installExcel: installExcel
+ installOneDrive: installOneDrive
+ installOneNote: installOneNote
+ installOutlook: installOutlook
+ installPowerPoint: installPowerPoint
+ installProject: installProject
+ installPublisher: installPublisher
+ installSkypeForBusiness: installSkypeForBusiness
+ installTeams: installTeams
+ installVirtualDesktopOptimizationTool: installVirtualDesktopOptimizationTool
+ installVisio: installVisio
+ installWord: installWord
+ keyVaultName: keyVaultName
+ localAdministratorPassword: localAdministratorPassword
+ localAdministratorUsername: localAdministratorUsername
+ location: location
+ managementVirtualMachineName: managementVirtualMachineName
+ marketplaceImageOffer: marketplaceImageOffer
+ marketplaceImagePublisher: marketplaceImagePublisher
+ marketplaceImageSKU: marketplaceImageSKU
+ msrdcwebrtcsvcInstaller: msrdcwebrtcsvcInstaller
+ officeInstaller: officeInstaller
+ replicaCount: replicaCount
+ sourceImageType: sourceImageType
+ storageAccountResourceId: storageAccountResourceId
+ subnetResourceId: tier3.outputs.subnetResourceId
+ tags: tags
+ teamsInstaller: teamsInstaller
+ userAssignedIdentityClientId: baseline.outputs.userAssignedIdentityClientId
+ userAssignedIdentityPrincipalId: baseline.outputs.userAssignedIdentityPrincipalId
+ userAssignedIdentityResourceId: baseline.outputs.userAssignedIdentityResourceId
+ vcRedistInstaller: vcRedistInstaller
+ vDOTInstaller: vDOTInstaller
+ virtualMachineSize: virtualMachineSize
+ }
+ dependsOn: [
+ buildAutomation
+ tier3
+ ]
+}
diff --git a/src/bicep/add-ons/Imaging/solution.json b/src/bicep/add-ons/Imaging/solution.json
new file mode 100644
index 000000000..d35fd8ccc
--- /dev/null
+++ b/src/bicep/add-ons/Imaging/solution.json
@@ -0,0 +1,8276 @@
+{
+ "$schema": "https://schema.management.azure.com/schemas/2018-05-01/subscriptionDeploymentTemplate.json#",
+ "contentVersion": "1.0.0.0",
+ "metadata": {
+ "_generator": {
+ "name": "bicep",
+ "version": "0.24.24.22086",
+ "templateHash": "3036657114362594574"
+ }
+ },
+ "parameters": {
+ "arcGisProInstaller": {
+ "type": "string",
+ "defaultValue": "",
+ "metadata": {
+ "description": "The file name of the ArcGIS Pro installer in Azure Blobs."
+ }
+ },
+ "actionGroupName": {
+ "type": "string",
+ "defaultValue": "",
+ "metadata": {
+ "description": "The name for the action group resource."
+ }
+ },
+ "automationAccountName": {
+ "type": "string",
+ "metadata": {
+ "description": "The name for the automation account resource."
+ }
+ },
+ "automationAccountPrivateDnsZoneResourceId": {
+ "type": "string",
+ "metadata": {
+ "description": "The private DNS zone resource ID for the automation account resource."
+ }
+ },
+ "computeGalleryImageResourceId": {
+ "type": "string",
+ "defaultValue": "",
+ "metadata": {
+ "description": "The resource ID of the compute gallery image."
+ }
+ },
+ "computeGalleryName": {
+ "type": "string",
+ "metadata": {
+ "description": "The name of the compute gallery resource."
+ }
+ },
+ "containerName": {
+ "type": "string",
+ "metadata": {
+ "description": "The name of the container in the storage account where the installer files are located."
+ }
+ },
+ "customizations": {
+ "type": "array",
+ "defaultValue": [],
+ "metadata": {
+ "description": "The array of customizations to apply to the image."
+ }
+ },
+ "diskEncryptionSetResourceId": {
+ "type": "string",
+ "defaultValue": "",
+ "metadata": {
+ "description": "The resource ID of the disk encryption set to use for the management virtual machine."
+ }
+ },
+ "distributionGroup": {
+ "type": "string",
+ "defaultValue": "",
+ "metadata": {
+ "description": "The distribution group for email notifications."
+ }
+ },
+ "deploymentNameSuffix": {
+ "type": "string",
+ "defaultValue": "[utcNow('yyMMddHHs')]",
+ "metadata": {
+ "description": "The suffix to append to deployment names."
+ }
+ },
+ "domainJoinPassword": {
+ "type": "securestring",
+ "defaultValue": "",
+ "metadata": {
+ "description": "The password for the domain join account."
+ }
+ },
+ "domainJoinUserPrincipalName": {
+ "type": "string",
+ "defaultValue": "",
+ "metadata": {
+ "description": "The user principal name for the domain join account."
+ }
+ },
+ "domainName": {
+ "type": "string",
+ "defaultValue": "",
+ "metadata": {
+ "description": "The domain name to join."
+ }
+ },
+ "enableBuildAutomation": {
+ "type": "bool",
+ "metadata": {
+ "description": "Determines whether to enable build automation."
+ }
+ },
+ "excludeFromLatest": {
+ "type": "bool",
+ "defaultValue": true,
+ "metadata": {
+ "description": "Determines whether to exclude the image from the latest version."
+ }
+ },
+ "exemptPolicyAssignmentIds": {
+ "type": "array",
+ "defaultValue": [],
+ "metadata": {
+ "description": "The array of policy assignment IDs to exempt to prevent issues with the build process."
+ }
+ },
+ "hybridUseBenefit": {
+ "type": "bool",
+ "metadata": {
+ "description": "Determines whether to use the hybrid use benefit."
+ }
+ },
+ "hybridWorkerName": {
+ "type": "string",
+ "defaultValue": "",
+ "metadata": {
+ "description": "The name of the hybrid worker (virtual machine) if using build automation."
+ }
+ },
+ "imageDefinitionNamePrefix": {
+ "type": "string",
+ "metadata": {
+ "description": "The name prefix for the image definition resource."
+ }
+ },
+ "imageMajorVersion": {
+ "type": "int",
+ "metadata": {
+ "description": "The major version for the name of the image version resource."
+ }
+ },
+ "imageMinorVersion": {
+ "type": "int",
+ "metadata": {
+ "description": "The minor version for the name of the image version resource."
+ }
+ },
+ "installAccess": {
+ "type": "bool",
+ "metadata": {
+ "description": "Determines whether to install Access."
+ }
+ },
+ "installArcGisPro": {
+ "type": "bool",
+ "metadata": {
+ "description": "Determines whether to install ArcGIS Pro."
+ }
+ },
+ "installExcel": {
+ "type": "bool",
+ "metadata": {
+ "description": "Determines whether to install Excel."
+ }
+ },
+ "installOneDrive": {
+ "type": "bool",
+ "metadata": {
+ "description": "Determines whether to install OneDrive."
+ }
+ },
+ "installOneNote": {
+ "type": "bool",
+ "metadata": {
+ "description": "Determines whether to install OneNote."
+ }
+ },
+ "installOutlook": {
+ "type": "bool",
+ "metadata": {
+ "description": "Determines whether to install Outlook."
+ }
+ },
+ "installPowerPoint": {
+ "type": "bool",
+ "metadata": {
+ "description": "Determines whether to install PowerPoint."
+ }
+ },
+ "installProject": {
+ "type": "bool",
+ "metadata": {
+ "description": "Determines whether to install Project."
+ }
+ },
+ "installPublisher": {
+ "type": "bool",
+ "metadata": {
+ "description": "Determines whether to install Publisher."
+ }
+ },
+ "installSkypeForBusiness": {
+ "type": "bool",
+ "metadata": {
+ "description": "Determines whether to install Skype for Business."
+ }
+ },
+ "installTeams": {
+ "type": "bool",
+ "metadata": {
+ "description": "Determines whether to install Teams."
+ }
+ },
+ "installVirtualDesktopOptimizationTool": {
+ "type": "bool",
+ "metadata": {
+ "description": "Determines whether to install the Virtual Desktop Optimization Tool."
+ }
+ },
+ "installVisio": {
+ "type": "bool",
+ "metadata": {
+ "description": "Determines whether to install Visio."
+ }
+ },
+ "installWord": {
+ "type": "bool",
+ "metadata": {
+ "description": "Determines whether to install Word."
+ }
+ },
+ "keyVaultName": {
+ "type": "string",
+ "metadata": {
+ "description": "The name of the key vault resource."
+ }
+ },
+ "keyVaultPrivateDnsZoneResourceId": {
+ "type": "string",
+ "metadata": {
+ "description": "The private DNS zone resource ID for the key vault resource."
+ }
+ },
+ "localAdministratorPassword": {
+ "type": "securestring",
+ "metadata": {
+ "description": "The password for the local administrator account."
+ }
+ },
+ "localAdministratorUsername": {
+ "type": "string",
+ "metadata": {
+ "description": "The username for the local administrator account."
+ }
+ },
+ "location": {
+ "type": "string",
+ "defaultValue": "[deployment().location]",
+ "metadata": {
+ "description": "The location for the resources."
+ }
+ },
+ "logAnalyticsWorkspaceResourceId": {
+ "type": "string",
+ "defaultValue": "",
+ "metadata": {
+ "description": "The resource ID of the log analytics workspace if using build automation and desired."
+ }
+ },
+ "spokelogAnalyticsWorkspaceResourceId": {
+ "type": "string",
+ "metadata": {
+ "description": "The resource ID of the log analytics workspace if using build automation and desired."
+ }
+ },
+ "marketplaceImageOffer": {
+ "type": "string",
+ "defaultValue": "",
+ "metadata": {
+ "description": "The marketplace image offer."
+ }
+ },
+ "marketplaceImagePublisher": {
+ "type": "string",
+ "defaultValue": "",
+ "metadata": {
+ "description": "The marketplace image publisher."
+ }
+ },
+ "marketplaceImageSKU": {
+ "type": "string",
+ "defaultValue": "",
+ "metadata": {
+ "description": "The marketplace image SKU."
+ }
+ },
+ "msrdcwebrtcsvcInstaller": {
+ "type": "string",
+ "defaultValue": "",
+ "metadata": {
+ "description": "The file name of the msrdcwebrtcsvc installer in Azure Blobs."
+ }
+ },
+ "existingResourceGroup": {
+ "type": "bool",
+ "defaultValue": false,
+ "metadata": {
+ "description": "Determines whether to use an existing resource group."
+ }
+ },
+ "officeInstaller": {
+ "type": "string",
+ "defaultValue": "",
+ "metadata": {
+ "description": "The file name of the Office installer in Azure Blobs."
+ }
+ },
+ "oUPath": {
+ "type": "string",
+ "defaultValue": "",
+ "metadata": {
+ "description": "The distinguished name of the organizational unit to join."
+ }
+ },
+ "replicaCount": {
+ "type": "int",
+ "metadata": {
+ "description": "The count of replicas for the image version resource."
+ }
+ },
+ "resourceGroupName": {
+ "type": "string",
+ "metadata": {
+ "description": "The name of the resource group."
+ }
+ },
+ "sourceImageType": {
+ "type": "string",
+ "allowedValues": [
+ "AzureComputeGallery",
+ "AzureMarketplace"
+ ],
+ "metadata": {
+ "description": "The type of source image."
+ }
+ },
+ "storageAccountResourceId": {
+ "type": "string",
+ "metadata": {
+ "description": "The resource ID of the storage account where the installers and scripts are stored in Azure Blobs."
+ }
+ },
+ "tags": {
+ "type": "object",
+ "defaultValue": {},
+ "metadata": {
+ "description": "The key value pairs of meta data to apply to the resources."
+ }
+ },
+ "teamsInstaller": {
+ "type": "string",
+ "defaultValue": "",
+ "metadata": {
+ "description": "The file name of the Teams installer in Azure Blobs."
+ }
+ },
+ "userAssignedIdentityName": {
+ "type": "string",
+ "metadata": {
+ "description": "The name of the user assigned identity resource."
+ }
+ },
+ "vcRedistInstaller": {
+ "type": "string",
+ "defaultValue": "",
+ "metadata": {
+ "description": "The file name of the vcRedist installer in Azure Blobs."
+ }
+ },
+ "vDOTInstaller": {
+ "type": "string",
+ "defaultValue": "",
+ "metadata": {
+ "description": "The file name of the vDOT installer in Azure Blobs."
+ }
+ },
+ "virtualMachineSize": {
+ "type": "string",
+ "metadata": {
+ "description": "The size of the image virtual machine."
+ }
+ },
+ "deployDefender": {
+ "type": "bool",
+ "defaultValue": false
+ },
+ "deployPolicy": {
+ "type": "bool",
+ "defaultValue": false
+ },
+ "emailSecurityContact": {
+ "type": "string"
+ },
+ "hubSubscriptionId": {
+ "type": "string"
+ },
+ "hubVirtualNetworkName": {
+ "type": "string"
+ },
+ "logAnalyticsWorkspaceName": {
+ "type": "string"
+ },
+ "policy": {
+ "type": "string",
+ "defaultValue": ""
+ },
+ "resourcePrefix": {
+ "type": "string"
+ },
+ "hubResourceGroupName": {
+ "type": "string"
+ },
+ "subnetAddressPrefix": {
+ "type": "string"
+ },
+ "virtualNetworkAddressPrefix": {
+ "type": "string"
+ },
+ "workloadSubscriptionId": {
+ "type": "string"
+ },
+ "azureFirewallName": {
+ "type": "string",
+ "metadata": {
+ "description": "The name of the Azure Firewall."
+ }
+ }
+ },
+ "variables": {
+ "imageDefinitionName": "[if(empty(parameters('computeGalleryImageResourceId')), format('{0}-{1}', parameters('imageDefinitionNamePrefix'), parameters('marketplaceImageSKU')), format('{0}-{1}', parameters('imageDefinitionNamePrefix'), split(parameters('computeGalleryImageResourceId'), '/')[10]))]",
+ "imageVirtualMachineName": "[take(format('vmimg-{0}', uniqueString(parameters('deploymentNameSuffix'))), 15)]",
+ "managementVirtualMachineName": "[if(empty(parameters('hybridWorkerName')), take(format('vmmgt-{0}', uniqueString(parameters('deploymentNameSuffix'))), 15), parameters('hybridWorkerName'))]",
+ "subscriptionId": "[subscription().subscriptionId]",
+ "timeZones": {
+ "australiacentral": "AUS Eastern Standard Time",
+ "australiacentral2": "AUS Eastern Standard Time",
+ "australiaeast": "AUS Eastern Standard Time",
+ "australiasoutheast": "AUS Eastern Standard Time",
+ "brazilsouth": "E. South America Standard Time",
+ "brazilsoutheast": "E. South America Standard Time",
+ "canadacentral": "Eastern Standard Time",
+ "canadaeast": "Eastern Standard Time",
+ "centralindia": "India Standard Time",
+ "centralus": "Central Standard Time",
+ "chinaeast": "China Standard Time",
+ "chinaeast2": "China Standard Time",
+ "chinanorth": "China Standard Time",
+ "chinanorth2": "China Standard Time",
+ "eastasia": "China Standard Time",
+ "eastus": "Eastern Standard Time",
+ "eastus2": "Eastern Standard Time",
+ "francecentral": "Central Europe Standard Time",
+ "francesouth": "Central Europe Standard Time",
+ "germanynorth": "Central Europe Standard Time",
+ "germanywestcentral": "Central Europe Standard Time",
+ "japaneast": "Tokyo Standard Time",
+ "japanwest": "Tokyo Standard Time",
+ "jioindiacentral": "India Standard Time",
+ "jioindiawest": "India Standard Time",
+ "koreacentral": "Korea Standard Time",
+ "koreasouth": "Korea Standard Time",
+ "northcentralus": "Central Standard Time",
+ "northeurope": "GMT Standard Time",
+ "norwayeast": "Central Europe Standard Time",
+ "norwaywest": "Central Europe Standard Time",
+ "southafricanorth": "South Africa Standard Time",
+ "southafricawest": "South Africa Standard Time",
+ "southcentralus": "Central Standard Time",
+ "southeastasia": "Singapore Standard Time",
+ "southindia": "India Standard Time",
+ "swedencentral": "Central Europe Standard Time",
+ "switzerlandnorth": "Central Europe Standard Time",
+ "switzerlandwest": "Central Europe Standard Time",
+ "uaecentral": "Arabian Standard Time",
+ "uaenorth": "Arabian Standard Time",
+ "uksouth": "GMT Standard Time",
+ "ukwest": "GMT Standard Time",
+ "usdodcentral": "Central Standard Time",
+ "usdodeast": "Eastern Standard Time",
+ "usgovarizona": "Mountain Standard Time",
+ "usgovtexas": "Central Standard Time",
+ "usgovvirginia": "Eastern Standard Time",
+ "westcentralus": "Mountain Standard Time",
+ "westeurope": "Central Europe Standard Time",
+ "westindia": "India Standard Time",
+ "westus": "Pacific Standard Time",
+ "westus2": "Pacific Standard Time",
+ "westus3": "Mountain Standard Time"
+ }
+ },
+ "resources": [
+ {
+ "condition": "[not(parameters('existingResourceGroup'))]",
+ "type": "Microsoft.Resources/resourceGroups",
+ "apiVersion": "2019-05-01",
+ "name": "[parameters('resourceGroupName')]",
+ "location": "[parameters('location')]",
+ "tags": "[parameters('tags')]"
+ },
+ {
+ "type": "Microsoft.Resources/deployments",
+ "apiVersion": "2022-09-01",
+ "name": "[format('tier3-{0}', parameters('deploymentNameSuffix'))]",
+ "subscriptionId": "[variables('subscriptionId')]",
+ "resourceGroup": "[if(parameters('existingResourceGroup'), parameters('resourceGroupName'), parameters('resourceGroupName'))]",
+ "properties": {
+ "expressionEvaluationOptions": {
+ "scope": "inner"
+ },
+ "mode": "Incremental",
+ "parameters": {
+ "deployDefender": {
+ "value": "[parameters('deployDefender')]"
+ },
+ "deployPolicy": {
+ "value": "[parameters('deployPolicy')]"
+ },
+ "emailSecurityContact": {
+ "value": "[parameters('emailSecurityContact')]"
+ },
+ "existingResourceGroup": {
+ "value": "[parameters('existingResourceGroup')]"
+ },
+ "firewallPrivateIPAddress": {
+ "value": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('hubSubscriptionId'), parameters('hubResourceGroupName')), 'Microsoft.Network/azureFirewalls', parameters('azureFirewallName')), '2023-05-01').ipConfigurations[0].properties.privateIPAddress]"
+ },
+ "hubResourceGroupName": {
+ "value": "[parameters('hubResourceGroupName')]"
+ },
+ "hubSubscriptionId": {
+ "value": "[parameters('hubSubscriptionId')]"
+ },
+ "hubVirtualNetworkName": {
+ "value": "[parameters('hubVirtualNetworkName')]"
+ },
+ "hubVirtualNetworkResourceId": {
+ "value": "[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('hubSubscriptionId'), parameters('hubResourceGroupName')), 'Microsoft.Network/virtualNetworks', parameters('hubVirtualNetworkName'))]"
+ },
+ "location": {
+ "value": "[parameters('location')]"
+ },
+ "logAnalyticsWorkspaceName": {
+ "value": "[parameters('logAnalyticsWorkspaceName')]"
+ },
+ "logAnalyticsWorkspaceResourceId": {
+ "value": "[parameters('spokelogAnalyticsWorkspaceResourceId')]"
+ },
+ "policy": {
+ "value": "[parameters('policy')]"
+ },
+ "resourceGroupName": "[if(parameters('existingResourceGroup'), createObject('value', parameters('resourceGroupName')), createObject('value', parameters('resourceGroupName')))]",
+ "resourcePrefix": {
+ "value": "[parameters('resourcePrefix')]"
+ },
+ "subnetAddressPrefix": {
+ "value": "[parameters('subnetAddressPrefix')]"
+ },
+ "virtualNetworkAddressPrefix": {
+ "value": "[parameters('virtualNetworkAddressPrefix')]"
+ },
+ "workloadSubscriptionId": {
+ "value": "[parameters('workloadSubscriptionId')]"
+ }
+ },
+ "template": {
+ "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
+ "contentVersion": "1.0.0.0",
+ "metadata": {
+ "_generator": {
+ "name": "bicep",
+ "version": "0.24.24.22086",
+ "templateHash": "10134746884955031932"
+ }
+ },
+ "parameters": {
+ "resourcePrefix": {
+ "type": "string",
+ "defaultValue": "zta",
+ "minLength": 3,
+ "maxLength": 10,
+ "metadata": {
+ "description": "A prefix, 3 to 10 characters in length, to append to resource names (e.g. \"dev\", \"test\", \"prod\", \"mlz\"). It defaults to \"mlz\"."
+ }
+ },
+ "resourceSuffix": {
+ "type": "string",
+ "defaultValue": "mlz",
+ "minLength": 3,
+ "maxLength": 6,
+ "metadata": {
+ "description": "A suffix, 3 to 6 characters in length, to append to resource names (e.g. \"dev\", \"test\", \"prod\", \"mlz\"). It defaults to \"mlz\"."
+ }
+ },
+ "location": {
+ "type": "string",
+ "metadata": {
+ "description": "The region to deploy resources into. It defaults to the deployment location."
+ }
+ },
+ "workloadSubscriptionId": {
+ "type": "string",
+ "metadata": {
+ "description": "The subscription ID for the Identity Network and resources. It defaults to the deployment subscription."
+ }
+ },
+ "hubSubscriptionId": {
+ "type": "string",
+ "metadata": {
+ "description": "MLZ Deployment output variables in json format. It defaults to the deploymentVariables.json."
+ }
+ },
+ "hubVirtualNetworkName": {
+ "type": "string",
+ "metadata": {
+ "description": "The name of the hub virtual network. It defaults to the deployment output variable."
+ }
+ },
+ "hubVirtualNetworkResourceId": {
+ "type": "string",
+ "metadata": {
+ "description": "The resource ID of the hub virtual network. It defaults to the deployment output variable."
+ }
+ },
+ "logAnalyticsWorkspaceResourceId": {
+ "type": "string",
+ "metadata": {
+ "description": "The resource ID of the log analytics workspace. It defaults to the deployment output variable."
+ }
+ },
+ "logAnalyticsWorkspaceName": {
+ "type": "string",
+ "metadata": {
+ "description": "The name of the log analytics workspace. It defaults to the deployment output variable."
+ }
+ },
+ "firewallPrivateIPAddress": {
+ "type": "string",
+ "metadata": {
+ "description": "The private IP address of the firewall. It defaults to the deployment output variable."
+ }
+ },
+ "policy": {
+ "type": "string",
+ "metadata": {
+ "description": "[NISTRev4/NISTRev5/IL5/CMMC] Built-in policy assignments to assign, it defaults to \"NISTRev4\". IL5 is only available for AzureUsGovernment and will switch to NISTRev4 if tried in AzureCloud."
+ }
+ },
+ "deployPolicy": {
+ "type": "bool",
+ "metadata": {
+ "description": "When set to \"true\", deploys the Azure Policy set defined at by the parameter \"policy\" to the resource groups generated in the deployment. It defaults to \"false\"."
+ }
+ },
+ "deployDefender": {
+ "type": "bool",
+ "metadata": {
+ "description": "When set to \"true\", enables Microsoft Defender for Cloud for the subscriptions used in the deployment. It defaults to \"false\"."
+ }
+ },
+ "emailSecurityContact": {
+ "type": "string",
+ "metadata": {
+ "description": "Email address of the contact, in the form of john@doe.com"
+ }
+ },
+ "virtualNetworkAddressPrefix": {
+ "type": "string",
+ "metadata": {
+ "description": "The address prefix for the network spoke vnet."
+ }
+ },
+ "virtualNetworkDiagnosticsLogs": {
+ "type": "array",
+ "defaultValue": [],
+ "metadata": {
+ "description": "An array of Network Diagnostic Logs to enable for the workload Virtual Network. See https://docs.microsoft.com/en-us/azure/azure-monitor/essentials/diagnostic-settings?tabs=CMD#logs for valid settings."
+ }
+ },
+ "virtualNetworkDiagnosticsMetrics": {
+ "type": "array",
+ "defaultValue": [],
+ "metadata": {
+ "description": "An array of Network Diagnostic Metrics to enable for the workload Virtual Network. See https://docs.microsoft.com/en-us/azure/azure-monitor/essentials/diagnostic-settings?tabs=CMD#metrics for valid settings."
+ }
+ },
+ "vNetDnsServers": {
+ "type": "array",
+ "defaultValue": [
+ "[parameters('firewallPrivateIPAddress')]"
+ ]
+ },
+ "networkSecurityGroupRules": {
+ "type": "array",
+ "defaultValue": [],
+ "metadata": {
+ "description": "An array of Network Security Group rules to apply to the workload Virtual Network. See https://docs.microsoft.com/en-us/azure/templates/microsoft.network/networksecuritygroups/securityrules?tabs=bicep#securityrulepropertiesformat for valid settings."
+ }
+ },
+ "networkSecurityGroupDiagnosticsLogs": {
+ "type": "array",
+ "defaultValue": [
+ {
+ "category": "NetworkSecurityGroupEvent",
+ "enabled": true
+ },
+ {
+ "category": "NetworkSecurityGroupRuleCounter",
+ "enabled": true
+ }
+ ],
+ "metadata": {
+ "description": "An array of Network Security Group diagnostic logs to apply to the workload Virtual Network. See https://docs.microsoft.com/en-us/azure/virtual-network/virtual-network-nsg-manage-log#log-categories for valid settings."
+ }
+ },
+ "networkSecurityGroupDiagnosticsMetrics": {
+ "type": "array",
+ "defaultValue": [],
+ "metadata": {
+ "description": "An array of Network Security Group diagnostic logs to apply to the SharedServices Virtual Network. See https://docs.microsoft.com/en-us/azure/virtual-network/virtual-network-nsg-manage-log#log-categories for valid settings."
+ }
+ },
+ "subnetAddressPrefix": {
+ "type": "string",
+ "metadata": {
+ "description": "The CIDR Virtual Network Address Prefix for the Workload Virtual Network."
+ }
+ },
+ "subnetServiceEndpoints": {
+ "type": "array",
+ "defaultValue": [],
+ "metadata": {
+ "description": "An array of Service Endpoints to enable for the Operations subnet. See https://docs.microsoft.com/en-us/azure/virtual-network/virtual-network-service-endpoints-overview for valid settings."
+ }
+ },
+ "logStorageSkuName": {
+ "type": "string",
+ "defaultValue": "Standard_GRS",
+ "metadata": {
+ "description": "The Storage Account SKU to use for log storage. It defaults to \"Standard_GRS\". See https://docs.microsoft.com/en-us/rest/api/storagerp/srp_sku_types for valid settings."
+ }
+ },
+ "tags": {
+ "type": "object",
+ "defaultValue": {},
+ "metadata": {
+ "description": "A string dictionary of tags to add to deployed resources. See https://docs.microsoft.com/en-us/azure/azure-resource-manager/management/tag-resources?tabs=json#arm-templates for valid settings."
+ }
+ },
+ "deploymentNameSuffix": {
+ "type": "string",
+ "defaultValue": "[utcNow()]",
+ "metadata": {
+ "description": "A suffix to use for naming deployments uniquely. It defaults to the Bicep resolution of the \"utcNow()\" function."
+ }
+ },
+ "workloadName": {
+ "type": "string",
+ "defaultValue": "zta",
+ "metadata": {
+ "description": "The name of the tier 3 workload"
+ }
+ },
+ "workloadLogStorageAccountNameParameter": {
+ "type": "string",
+ "defaultValue": "null",
+ "maxLength": 24,
+ "metadata": {
+ "description": "The name of the Storage Account if using this Parameter. Otherwise it will be a calculated value."
+ }
+ },
+ "existingResourceGroup": {
+ "type": "bool"
+ },
+ "resourceGroupName": {
+ "type": "string"
+ },
+ "hubResourceGroupName": {
+ "type": "string"
+ }
+ },
+ "variables": {
+ "resourceToken": "resource_token",
+ "nameToken": "name_token",
+ "namingConvention": "[format('{0}-{1}-{2}-{3}', toLower(parameters('resourcePrefix')), variables('resourceToken'), variables('nameToken'), toLower(parameters('resourceSuffix')))]",
+ "virtualNetworkNamingConvention": "[replace(variables('namingConvention'), variables('resourceToken'), 'vnet')]",
+ "networkSecurityGroupNamingConvention": "[replace(variables('namingConvention'), variables('resourceToken'), 'nsg')]",
+ "storageAccountNamingConvention": "[toLower(format('{0}st{1}unique_storage_token', parameters('resourcePrefix'), variables('nameToken')))]",
+ "subnetNamingConvention": "[replace(variables('namingConvention'), variables('resourceToken'), 'snet')]",
+ "workloadLogStorageAccountNameTemplate": "[replace(variables('storageAccountNamingConvention'), variables('nameToken'), toLower(parameters('workloadName')))]",
+ "workloadLogStorageAccountUniqueName": "[replace(variables('workloadLogStorageAccountNameTemplate'), 'unique_storage_token', uniqueString(parameters('resourcePrefix'), parameters('resourceSuffix'), parameters('workloadSubscriptionId')))]",
+ "workloadLogStorageAccountNameVariable": "[take(variables('workloadLogStorageAccountUniqueName'), 23)]",
+ "workloadVirtualNetworkName": "[replace(variables('virtualNetworkNamingConvention'), variables('nameToken'), parameters('workloadName'))]",
+ "workloadNetworkSecurityGroupName": "[replace(variables('networkSecurityGroupNamingConvention'), variables('nameToken'), parameters('workloadName'))]",
+ "workloadSubnetName": "[replace(variables('subnetNamingConvention'), variables('nameToken'), parameters('workloadName'))]",
+ "logAnalyticsWorkspaceResourceId_split": "[split(parameters('logAnalyticsWorkspaceResourceId'), '/')]",
+ "workloadLogStorageAccountName": "[if(not(equals('null', parameters('workloadLogStorageAccountNameParameter'))), parameters('workloadLogStorageAccountNameParameter'), variables('workloadLogStorageAccountNameVariable'))]",
+ "defaultTags": {
+ "DeploymentType": "MissionLandingZoneARM"
+ },
+ "calculatedTags": "[union(parameters('tags'), variables('defaultTags'))]"
+ },
+ "resources": [
+ {
+ "type": "Microsoft.Resources/deployments",
+ "apiVersion": "2022-09-01",
+ "name": "spokeNetwork",
+ "subscriptionId": "[parameters('workloadSubscriptionId')]",
+ "resourceGroup": "[if(parameters('existingResourceGroup'), parameters('resourceGroupName'), parameters('resourceGroupName'))]",
+ "properties": {
+ "expressionEvaluationOptions": {
+ "scope": "inner"
+ },
+ "mode": "Incremental",
+ "parameters": {
+ "tags": {
+ "value": "[variables('calculatedTags')]"
+ },
+ "location": {
+ "value": "[parameters('location')]"
+ },
+ "logStorageAccountName": {
+ "value": "[variables('workloadLogStorageAccountName')]"
+ },
+ "logStorageSkuName": {
+ "value": "[parameters('logStorageSkuName')]"
+ },
+ "logAnalyticsWorkspaceResourceId": {
+ "value": "[parameters('logAnalyticsWorkspaceResourceId')]"
+ },
+ "firewallPrivateIPAddress": {
+ "value": "[parameters('firewallPrivateIPAddress')]"
+ },
+ "virtualNetworkName": {
+ "value": "[variables('workloadVirtualNetworkName')]"
+ },
+ "virtualNetworkAddressPrefix": {
+ "value": "[parameters('virtualNetworkAddressPrefix')]"
+ },
+ "vNetDnsServers": {
+ "value": "[parameters('vNetDnsServers')]"
+ },
+ "virtualNetworkDiagnosticsLogs": {
+ "value": "[parameters('virtualNetworkDiagnosticsLogs')]"
+ },
+ "virtualNetworkDiagnosticsMetrics": {
+ "value": "[parameters('virtualNetworkDiagnosticsMetrics')]"
+ },
+ "networkSecurityGroupName": {
+ "value": "[variables('workloadNetworkSecurityGroupName')]"
+ },
+ "networkSecurityGroupRules": {
+ "value": "[parameters('networkSecurityGroupRules')]"
+ },
+ "networkSecurityGroupDiagnosticsLogs": {
+ "value": "[parameters('networkSecurityGroupDiagnosticsLogs')]"
+ },
+ "networkSecurityGroupDiagnosticsMetrics": {
+ "value": "[parameters('networkSecurityGroupDiagnosticsMetrics')]"
+ },
+ "subnetName": {
+ "value": "[variables('workloadSubnetName')]"
+ },
+ "subnetAddressPrefix": {
+ "value": "[parameters('subnetAddressPrefix')]"
+ },
+ "subnetServiceEndpoints": {
+ "value": "[parameters('subnetServiceEndpoints')]"
+ },
+ "subnetPrivateEndpointNetworkPolicies": {
+ "value": "Disabled"
+ },
+ "subnetPrivateLinkServiceNetworkPolicies": {
+ "value": "Disabled"
+ }
+ },
+ "template": {
+ "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
+ "contentVersion": "1.0.0.0",
+ "metadata": {
+ "_generator": {
+ "name": "bicep",
+ "version": "0.24.24.22086",
+ "templateHash": "3636586928348301463"
+ }
+ },
+ "parameters": {
+ "location": {
+ "type": "string",
+ "defaultValue": "[resourceGroup().location]"
+ },
+ "tags": {
+ "type": "object",
+ "defaultValue": {}
+ },
+ "logStorageAccountName": {
+ "type": "string"
+ },
+ "logStorageSkuName": {
+ "type": "string"
+ },
+ "logAnalyticsWorkspaceResourceId": {
+ "type": "string"
+ },
+ "firewallPrivateIPAddress": {
+ "type": "string"
+ },
+ "virtualNetworkName": {
+ "type": "string"
+ },
+ "virtualNetworkAddressPrefix": {
+ "type": "string"
+ },
+ "virtualNetworkDiagnosticsLogs": {
+ "type": "array"
+ },
+ "virtualNetworkDiagnosticsMetrics": {
+ "type": "array"
+ },
+ "vNetDnsServers": {
+ "type": "array"
+ },
+ "networkSecurityGroupName": {
+ "type": "string"
+ },
+ "networkSecurityGroupRules": {
+ "type": "array"
+ },
+ "networkSecurityGroupDiagnosticsLogs": {
+ "type": "array"
+ },
+ "networkSecurityGroupDiagnosticsMetrics": {
+ "type": "array"
+ },
+ "subnetName": {
+ "type": "string"
+ },
+ "subnetAddressPrefix": {
+ "type": "string"
+ },
+ "subnetServiceEndpoints": {
+ "type": "array"
+ },
+ "routeTableName": {
+ "type": "string",
+ "defaultValue": "[format('{0}-routetable', parameters('subnetName'))]"
+ },
+ "routeTableRouteName": {
+ "type": "string",
+ "defaultValue": "default_route"
+ },
+ "routeTableRouteAddressPrefix": {
+ "type": "string",
+ "defaultValue": "0.0.0.0/0"
+ },
+ "routeTableRouteNextHopIpAddress": {
+ "type": "string",
+ "defaultValue": "[parameters('firewallPrivateIPAddress')]"
+ },
+ "routeTableRouteNextHopType": {
+ "type": "string",
+ "defaultValue": "VirtualAppliance"
+ },
+ "subnetPrivateEndpointNetworkPolicies": {
+ "type": "string"
+ },
+ "subnetPrivateLinkServiceNetworkPolicies": {
+ "type": "string"
+ }
+ },
+ "resources": [
+ {
+ "type": "Microsoft.Resources/deployments",
+ "apiVersion": "2022-09-01",
+ "name": "logStorage",
+ "properties": {
+ "expressionEvaluationOptions": {
+ "scope": "inner"
+ },
+ "mode": "Incremental",
+ "parameters": {
+ "storageAccountName": {
+ "value": "[parameters('logStorageAccountName')]"
+ },
+ "location": {
+ "value": "[parameters('location')]"
+ },
+ "skuName": {
+ "value": "[parameters('logStorageSkuName')]"
+ },
+ "tags": {
+ "value": "[parameters('tags')]"
+ }
+ },
+ "template": {
+ "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
+ "contentVersion": "1.0.0.0",
+ "metadata": {
+ "_generator": {
+ "name": "bicep",
+ "version": "0.24.24.22086",
+ "templateHash": "11432560412215968310"
+ }
+ },
+ "parameters": {
+ "storageAccountName": {
+ "type": "string"
+ },
+ "location": {
+ "type": "string"
+ },
+ "skuName": {
+ "type": "string"
+ },
+ "tags": {
+ "type": "object",
+ "defaultValue": {}
+ }
+ },
+ "resources": [
+ {
+ "type": "Microsoft.Storage/storageAccounts",
+ "apiVersion": "2021-01-01",
+ "name": "[parameters('storageAccountName')]",
+ "location": "[parameters('location')]",
+ "kind": "StorageV2",
+ "sku": {
+ "name": "[parameters('skuName')]"
+ },
+ "tags": "[parameters('tags')]",
+ "properties": {
+ "minimumTlsVersion": "TLS1_2",
+ "encryption": {
+ "keySource": "Microsoft.Storage",
+ "requireInfrastructureEncryption": true,
+ "services": {
+ "blob": {
+ "enabled": true
+ },
+ "file": {
+ "enabled": true
+ },
+ "queue": {
+ "enabled": true
+ },
+ "table": {
+ "enabled": true
+ }
+ }
+ }
+ }
+ }
+ ],
+ "outputs": {
+ "id": {
+ "type": "string",
+ "value": "[resourceId('Microsoft.Storage/storageAccounts', parameters('storageAccountName'))]"
+ }
+ }
+ }
+ }
+ },
+ {
+ "type": "Microsoft.Resources/deployments",
+ "apiVersion": "2022-09-01",
+ "name": "networkSecurityGroup",
+ "properties": {
+ "expressionEvaluationOptions": {
+ "scope": "inner"
+ },
+ "mode": "Incremental",
+ "parameters": {
+ "name": {
+ "value": "[parameters('networkSecurityGroupName')]"
+ },
+ "location": {
+ "value": "[parameters('location')]"
+ },
+ "tags": {
+ "value": "[parameters('tags')]"
+ },
+ "securityRules": {
+ "value": "[parameters('networkSecurityGroupRules')]"
+ },
+ "logAnalyticsWorkspaceResourceId": {
+ "value": "[parameters('logAnalyticsWorkspaceResourceId')]"
+ },
+ "logStorageAccountResourceId": {
+ "value": "[reference(resourceId('Microsoft.Resources/deployments', 'logStorage'), '2022-09-01').outputs.id.value]"
+ },
+ "logs": {
+ "value": "[parameters('networkSecurityGroupDiagnosticsLogs')]"
+ },
+ "metrics": {
+ "value": "[parameters('networkSecurityGroupDiagnosticsMetrics')]"
+ }
+ },
+ "template": {
+ "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
+ "contentVersion": "1.0.0.0",
+ "metadata": {
+ "_generator": {
+ "name": "bicep",
+ "version": "0.24.24.22086",
+ "templateHash": "11977507194028278079"
+ }
+ },
+ "parameters": {
+ "name": {
+ "type": "string"
+ },
+ "location": {
+ "type": "string"
+ },
+ "tags": {
+ "type": "object",
+ "defaultValue": {}
+ },
+ "securityRules": {
+ "type": "array"
+ },
+ "logStorageAccountResourceId": {
+ "type": "string"
+ },
+ "logAnalyticsWorkspaceResourceId": {
+ "type": "string"
+ },
+ "logs": {
+ "type": "array"
+ },
+ "metrics": {
+ "type": "array"
+ }
+ },
+ "resources": [
+ {
+ "type": "Microsoft.Network/networkSecurityGroups",
+ "apiVersion": "2021-02-01",
+ "name": "[parameters('name')]",
+ "location": "[parameters('location')]",
+ "tags": "[parameters('tags')]",
+ "properties": {
+ "securityRules": "[parameters('securityRules')]"
+ }
+ },
+ {
+ "type": "Microsoft.Insights/diagnosticSettings",
+ "apiVersion": "2017-05-01-preview",
+ "scope": "[format('Microsoft.Network/networkSecurityGroups/{0}', parameters('name'))]",
+ "name": "[format('{0}-diagnostics', parameters('name'))]",
+ "properties": {
+ "storageAccountId": "[parameters('logStorageAccountResourceId')]",
+ "workspaceId": "[parameters('logAnalyticsWorkspaceResourceId')]",
+ "logs": "[parameters('logs')]",
+ "metrics": "[parameters('metrics')]"
+ },
+ "dependsOn": [
+ "[resourceId('Microsoft.Network/networkSecurityGroups', parameters('name'))]"
+ ]
+ }
+ ],
+ "outputs": {
+ "id": {
+ "type": "string",
+ "value": "[resourceId('Microsoft.Network/networkSecurityGroups', parameters('name'))]"
+ },
+ "name": {
+ "type": "string",
+ "value": "[parameters('name')]"
+ }
+ }
+ }
+ },
+ "dependsOn": [
+ "[resourceId('Microsoft.Resources/deployments', 'logStorage')]"
+ ]
+ },
+ {
+ "type": "Microsoft.Resources/deployments",
+ "apiVersion": "2022-09-01",
+ "name": "routeTable",
+ "properties": {
+ "expressionEvaluationOptions": {
+ "scope": "inner"
+ },
+ "mode": "Incremental",
+ "parameters": {
+ "name": {
+ "value": "[parameters('routeTableName')]"
+ },
+ "location": {
+ "value": "[parameters('location')]"
+ },
+ "tags": {
+ "value": "[parameters('tags')]"
+ },
+ "routeName": {
+ "value": "[parameters('routeTableRouteName')]"
+ },
+ "routeAddressPrefix": {
+ "value": "[parameters('routeTableRouteAddressPrefix')]"
+ },
+ "routeNextHopIpAddress": {
+ "value": "[parameters('routeTableRouteNextHopIpAddress')]"
+ },
+ "routeNextHopType": {
+ "value": "[parameters('routeTableRouteNextHopType')]"
+ }
+ },
+ "template": {
+ "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
+ "contentVersion": "1.0.0.0",
+ "metadata": {
+ "_generator": {
+ "name": "bicep",
+ "version": "0.24.24.22086",
+ "templateHash": "13858235086546968061"
+ }
+ },
+ "parameters": {
+ "name": {
+ "type": "string"
+ },
+ "location": {
+ "type": "string"
+ },
+ "tags": {
+ "type": "object",
+ "defaultValue": {}
+ },
+ "routeName": {
+ "type": "string"
+ },
+ "routeAddressPrefix": {
+ "type": "string"
+ },
+ "routeNextHopIpAddress": {
+ "type": "string"
+ },
+ "routeNextHopType": {
+ "type": "string"
+ }
+ },
+ "resources": [
+ {
+ "type": "Microsoft.Network/routeTables",
+ "apiVersion": "2021-02-01",
+ "name": "[parameters('name')]",
+ "location": "[parameters('location')]",
+ "tags": "[parameters('tags')]",
+ "properties": {
+ "routes": [
+ {
+ "name": "[parameters('routeName')]",
+ "properties": {
+ "addressPrefix": "[parameters('routeAddressPrefix')]",
+ "nextHopIpAddress": "[parameters('routeNextHopIpAddress')]",
+ "nextHopType": "[parameters('routeNextHopType')]"
+ }
+ }
+ ]
+ }
+ }
+ ],
+ "outputs": {
+ "id": {
+ "type": "string",
+ "value": "[resourceId('Microsoft.Network/routeTables', parameters('name'))]"
+ },
+ "name": {
+ "type": "string",
+ "value": "[parameters('name')]"
+ }
+ }
+ }
+ }
+ },
+ {
+ "type": "Microsoft.Resources/deployments",
+ "apiVersion": "2022-09-01",
+ "name": "virtualNetwork",
+ "properties": {
+ "expressionEvaluationOptions": {
+ "scope": "inner"
+ },
+ "mode": "Incremental",
+ "parameters": {
+ "name": {
+ "value": "[parameters('virtualNetworkName')]"
+ },
+ "location": {
+ "value": "[parameters('location')]"
+ },
+ "tags": {
+ "value": "[parameters('tags')]"
+ },
+ "addressPrefix": {
+ "value": "[parameters('virtualNetworkAddressPrefix')]"
+ },
+ "vNetDnsServers": {
+ "value": "[parameters('vNetDnsServers')]"
+ },
+ "subnets": {
+ "value": [
+ {
+ "name": "[parameters('subnetName')]",
+ "properties": {
+ "addressPrefix": "[parameters('subnetAddressPrefix')]",
+ "networkSecurityGroup": {
+ "id": "[reference(resourceId('Microsoft.Resources/deployments', 'networkSecurityGroup'), '2022-09-01').outputs.id.value]"
+ },
+ "routeTable": {
+ "id": "[reference(resourceId('Microsoft.Resources/deployments', 'routeTable'), '2022-09-01').outputs.id.value]"
+ },
+ "serviceEndpoints": "[parameters('subnetServiceEndpoints')]",
+ "privateEndpointNetworkPolicies": "[parameters('subnetPrivateEndpointNetworkPolicies')]",
+ "privateLinkServiceNetworkPolicies": "[parameters('subnetPrivateLinkServiceNetworkPolicies')]"
+ }
+ }
+ ]
+ },
+ "logAnalyticsWorkspaceResourceId": {
+ "value": "[parameters('logAnalyticsWorkspaceResourceId')]"
+ },
+ "logStorageAccountResourceId": {
+ "value": "[reference(resourceId('Microsoft.Resources/deployments', 'logStorage'), '2022-09-01').outputs.id.value]"
+ },
+ "logs": {
+ "value": "[parameters('virtualNetworkDiagnosticsLogs')]"
+ },
+ "metrics": {
+ "value": "[parameters('virtualNetworkDiagnosticsMetrics')]"
+ }
+ },
+ "template": {
+ "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
+ "contentVersion": "1.0.0.0",
+ "metadata": {
+ "_generator": {
+ "name": "bicep",
+ "version": "0.24.24.22086",
+ "templateHash": "3610049520534333304"
+ }
+ },
+ "parameters": {
+ "name": {
+ "type": "string"
+ },
+ "location": {
+ "type": "string"
+ },
+ "tags": {
+ "type": "object",
+ "defaultValue": {}
+ },
+ "addressPrefix": {
+ "type": "string"
+ },
+ "vNetDnsServers": {
+ "type": "array",
+ "defaultValue": []
+ },
+ "logAnalyticsWorkspaceResourceId": {
+ "type": "string"
+ },
+ "logStorageAccountResourceId": {
+ "type": "string"
+ },
+ "subnets": {
+ "type": "array"
+ },
+ "logs": {
+ "type": "array"
+ },
+ "metrics": {
+ "type": "array"
+ }
+ },
+ "resources": [
+ {
+ "type": "Microsoft.Network/virtualNetworks",
+ "apiVersion": "2021-02-01",
+ "name": "[parameters('name')]",
+ "location": "[parameters('location')]",
+ "tags": "[parameters('tags')]",
+ "properties": {
+ "addressSpace": {
+ "addressPrefixes": [
+ "[parameters('addressPrefix')]"
+ ]
+ },
+ "subnets": "[parameters('subnets')]",
+ "dhcpOptions": "[if(not(equals(parameters('vNetDnsServers'), null())), createObject('dnsServers', parameters('vNetDnsServers')), null())]"
+ }
+ },
+ {
+ "type": "Microsoft.Insights/diagnosticSettings",
+ "apiVersion": "2017-05-01-preview",
+ "scope": "[format('Microsoft.Network/virtualNetworks/{0}', parameters('name'))]",
+ "name": "[format('{0}-diagnostics', parameters('name'))]",
+ "properties": {
+ "storageAccountId": "[parameters('logStorageAccountResourceId')]",
+ "workspaceId": "[parameters('logAnalyticsWorkspaceResourceId')]",
+ "logs": "[parameters('logs')]",
+ "metrics": "[parameters('metrics')]"
+ },
+ "dependsOn": [
+ "[resourceId('Microsoft.Network/virtualNetworks', parameters('name'))]"
+ ]
+ }
+ ],
+ "outputs": {
+ "name": {
+ "type": "string",
+ "value": "[parameters('name')]"
+ },
+ "id": {
+ "type": "string",
+ "value": "[resourceId('Microsoft.Network/virtualNetworks', parameters('name'))]"
+ },
+ "subnets": {
+ "type": "array",
+ "value": "[reference(resourceId('Microsoft.Network/virtualNetworks', parameters('name')), '2021-02-01').subnets]"
+ },
+ "addressPrefix": {
+ "type": "string",
+ "value": "[reference(resourceId('Microsoft.Network/virtualNetworks', parameters('name')), '2021-02-01').addressSpace.addressPrefixes[0]]"
+ }
+ }
+ }
+ },
+ "dependsOn": [
+ "[resourceId('Microsoft.Resources/deployments', 'logStorage')]",
+ "[resourceId('Microsoft.Resources/deployments', 'networkSecurityGroup')]",
+ "[resourceId('Microsoft.Resources/deployments', 'routeTable')]"
+ ]
+ }
+ ],
+ "outputs": {
+ "virtualNetworkName": {
+ "type": "string",
+ "value": "[reference(resourceId('Microsoft.Resources/deployments', 'virtualNetwork'), '2022-09-01').outputs.name.value]"
+ },
+ "virtualNetworkResourceId": {
+ "type": "string",
+ "value": "[reference(resourceId('Microsoft.Resources/deployments', 'virtualNetwork'), '2022-09-01').outputs.id.value]"
+ },
+ "virtualNetworkAddressPrefix": {
+ "type": "string",
+ "value": "[reference(resourceId('Microsoft.Resources/deployments', 'virtualNetwork'), '2022-09-01').outputs.addressPrefix.value]"
+ },
+ "subnetName": {
+ "type": "string",
+ "value": "[reference(resourceId('Microsoft.Resources/deployments', 'virtualNetwork'), '2022-09-01').outputs.subnets.value[0].name]"
+ },
+ "subnetAddressPrefix": {
+ "type": "string",
+ "value": "[reference(resourceId('Microsoft.Resources/deployments', 'virtualNetwork'), '2022-09-01').outputs.subnets.value[0].properties.addressPrefix]"
+ },
+ "subnetResourceId": {
+ "type": "string",
+ "value": "[reference(resourceId('Microsoft.Resources/deployments', 'virtualNetwork'), '2022-09-01').outputs.subnets.value[0].id]"
+ },
+ "networkSecurityGroupName": {
+ "type": "string",
+ "value": "[reference(resourceId('Microsoft.Resources/deployments', 'networkSecurityGroup'), '2022-09-01').outputs.name.value]"
+ },
+ "networkSecurityGroupResourceId": {
+ "type": "string",
+ "value": "[reference(resourceId('Microsoft.Resources/deployments', 'networkSecurityGroup'), '2022-09-01').outputs.id.value]"
+ }
+ }
+ }
+ }
+ },
+ {
+ "type": "Microsoft.Resources/deployments",
+ "apiVersion": "2022-09-01",
+ "name": "[take(format('{0}-to-hub-vnet-peering', parameters('workloadName')), 64)]",
+ "subscriptionId": "[parameters('workloadSubscriptionId')]",
+ "location": "[resourceGroup().location]",
+ "properties": {
+ "expressionEvaluationOptions": {
+ "scope": "inner"
+ },
+ "mode": "Incremental",
+ "parameters": {
+ "spokeName": {
+ "value": "[parameters('workloadName')]"
+ },
+ "spokeResourceGroupName": "[if(parameters('existingResourceGroup'), createObject('value', parameters('resourceGroupName')), createObject('value', parameters('resourceGroupName')))]",
+ "spokeVirtualNetworkName": {
+ "value": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('workloadSubscriptionId'), if(parameters('existingResourceGroup'), parameters('resourceGroupName'), parameters('resourceGroupName'))), 'Microsoft.Resources/deployments', 'spokeNetwork'), '2022-09-01').outputs.virtualNetworkName.value]"
+ },
+ "hubVirtualNetworkName": {
+ "value": "[parameters('hubVirtualNetworkName')]"
+ },
+ "hubVirtualNetworkResourceId": {
+ "value": "[parameters('hubVirtualNetworkResourceId')]"
+ }
+ },
+ "template": {
+ "$schema": "https://schema.management.azure.com/schemas/2018-05-01/subscriptionDeploymentTemplate.json#",
+ "contentVersion": "1.0.0.0",
+ "metadata": {
+ "_generator": {
+ "name": "bicep",
+ "version": "0.24.24.22086",
+ "templateHash": "1352997920612289656"
+ }
+ },
+ "parameters": {
+ "spokeName": {
+ "type": "string"
+ },
+ "spokeResourceGroupName": {
+ "type": "string"
+ },
+ "spokeVirtualNetworkName": {
+ "type": "string"
+ },
+ "hubVirtualNetworkName": {
+ "type": "string"
+ },
+ "hubVirtualNetworkResourceId": {
+ "type": "string"
+ }
+ },
+ "resources": [
+ {
+ "type": "Microsoft.Resources/deployments",
+ "apiVersion": "2022-09-01",
+ "name": "[format('{0}-to-hub-vnet-peering', parameters('spokeName'))]",
+ "resourceGroup": "[parameters('spokeResourceGroupName')]",
+ "properties": {
+ "expressionEvaluationOptions": {
+ "scope": "inner"
+ },
+ "mode": "Incremental",
+ "parameters": {
+ "name": {
+ "value": "[format('{0}/to-{1}', parameters('spokeVirtualNetworkName'), parameters('hubVirtualNetworkName'))]"
+ },
+ "remoteVirtualNetworkResourceId": {
+ "value": "[parameters('hubVirtualNetworkResourceId')]"
+ }
+ },
+ "template": {
+ "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
+ "contentVersion": "1.0.0.0",
+ "metadata": {
+ "_generator": {
+ "name": "bicep",
+ "version": "0.24.24.22086",
+ "templateHash": "9853575474833495545"
+ }
+ },
+ "parameters": {
+ "name": {
+ "type": "string"
+ },
+ "remoteVirtualNetworkResourceId": {
+ "type": "string"
+ }
+ },
+ "resources": [
+ {
+ "type": "Microsoft.Network/virtualNetworks/virtualNetworkPeerings",
+ "apiVersion": "2021-02-01",
+ "name": "[parameters('name')]",
+ "properties": {
+ "allowForwardedTraffic": true,
+ "remoteVirtualNetwork": {
+ "id": "[parameters('remoteVirtualNetworkResourceId')]"
+ }
+ }
+ }
+ ]
+ }
+ }
+ }
+ ]
+ }
+ },
+ "dependsOn": [
+ "[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('workloadSubscriptionId'), if(parameters('existingResourceGroup'), parameters('resourceGroupName'), parameters('resourceGroupName'))), 'Microsoft.Resources/deployments', 'spokeNetwork')]"
+ ]
+ },
+ {
+ "type": "Microsoft.Resources/deployments",
+ "apiVersion": "2022-09-01",
+ "name": "[take(format('hub-to-{0}-vnet-peering', parameters('workloadName')), 64)]",
+ "subscriptionId": "[parameters('workloadSubscriptionId')]",
+ "resourceGroup": "[if(parameters('existingResourceGroup'), parameters('resourceGroupName'), parameters('resourceGroupName'))]",
+ "properties": {
+ "expressionEvaluationOptions": {
+ "scope": "inner"
+ },
+ "mode": "Incremental",
+ "parameters": {
+ "hubVirtualNetworkName": {
+ "value": "[parameters('hubVirtualNetworkName')]"
+ },
+ "hubResourceGroupName": {
+ "value": "[parameters('hubResourceGroupName')]"
+ },
+ "spokeVirtualNetworkName": {
+ "value": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('workloadSubscriptionId'), if(parameters('existingResourceGroup'), parameters('resourceGroupName'), parameters('resourceGroupName'))), 'Microsoft.Resources/deployments', 'spokeNetwork'), '2022-09-01').outputs.virtualNetworkName.value]"
+ },
+ "spokeVirtualNetworkResourceId": {
+ "value": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('workloadSubscriptionId'), if(parameters('existingResourceGroup'), parameters('resourceGroupName'), parameters('resourceGroupName'))), 'Microsoft.Resources/deployments', 'spokeNetwork'), '2022-09-01').outputs.virtualNetworkResourceId.value]"
+ }
+ },
+ "template": {
+ "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
+ "contentVersion": "1.0.0.0",
+ "metadata": {
+ "_generator": {
+ "name": "bicep",
+ "version": "0.24.24.22086",
+ "templateHash": "2058971036831358476"
+ }
+ },
+ "parameters": {
+ "hubResourceGroupName": {
+ "type": "string"
+ },
+ "hubVirtualNetworkName": {
+ "type": "string"
+ },
+ "spokeVirtualNetworkName": {
+ "type": "string"
+ },
+ "spokeVirtualNetworkResourceId": {
+ "type": "string"
+ }
+ },
+ "resources": [
+ {
+ "type": "Microsoft.Resources/deployments",
+ "apiVersion": "2022-09-01",
+ "name": "hubToSpokeVirtualNetworkPeering",
+ "resourceGroup": "[parameters('hubResourceGroupName')]",
+ "properties": {
+ "expressionEvaluationOptions": {
+ "scope": "inner"
+ },
+ "mode": "Incremental",
+ "parameters": {
+ "name": {
+ "value": "[format('{0}/to-{1}', parameters('hubVirtualNetworkName'), parameters('spokeVirtualNetworkName'))]"
+ },
+ "remoteVirtualNetworkResourceId": {
+ "value": "[parameters('spokeVirtualNetworkResourceId')]"
+ }
+ },
+ "template": {
+ "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
+ "contentVersion": "1.0.0.0",
+ "metadata": {
+ "_generator": {
+ "name": "bicep",
+ "version": "0.24.24.22086",
+ "templateHash": "9853575474833495545"
+ }
+ },
+ "parameters": {
+ "name": {
+ "type": "string"
+ },
+ "remoteVirtualNetworkResourceId": {
+ "type": "string"
+ }
+ },
+ "resources": [
+ {
+ "type": "Microsoft.Network/virtualNetworks/virtualNetworkPeerings",
+ "apiVersion": "2021-02-01",
+ "name": "[parameters('name')]",
+ "properties": {
+ "allowForwardedTraffic": true,
+ "remoteVirtualNetwork": {
+ "id": "[parameters('remoteVirtualNetworkResourceId')]"
+ }
+ }
+ }
+ ]
+ }
+ }
+ }
+ ]
+ }
+ },
+ "dependsOn": [
+ "[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('workloadSubscriptionId'), if(parameters('existingResourceGroup'), parameters('resourceGroupName'), parameters('resourceGroupName'))), 'Microsoft.Resources/deployments', 'spokeNetwork')]"
+ ]
+ },
+ {
+ "condition": "[not(equals(parameters('workloadSubscriptionId'), parameters('hubSubscriptionId')))]",
+ "type": "Microsoft.Resources/deployments",
+ "apiVersion": "2022-09-01",
+ "name": "[format('activity-logs-{0}-{1}', 'spokeNetwork', parameters('resourceSuffix'))]",
+ "subscriptionId": "[parameters('workloadSubscriptionId')]",
+ "location": "[resourceGroup().location]",
+ "properties": {
+ "expressionEvaluationOptions": {
+ "scope": "inner"
+ },
+ "mode": "Incremental",
+ "parameters": {
+ "diagnosticSettingName": {
+ "value": "[format('log-{0}-sub-activity-to-{1}', 'spokeNetwork', parameters('logAnalyticsWorkspaceName'))]"
+ },
+ "logAnalyticsWorkspaceId": {
+ "value": "[parameters('logAnalyticsWorkspaceResourceId')]"
+ }
+ },
+ "template": {
+ "$schema": "https://schema.management.azure.com/schemas/2018-05-01/subscriptionDeploymentTemplate.json#",
+ "contentVersion": "1.0.0.0",
+ "metadata": {
+ "_generator": {
+ "name": "bicep",
+ "version": "0.24.24.22086",
+ "templateHash": "3850477028148266020"
+ }
+ },
+ "parameters": {
+ "diagnosticSettingName": {
+ "type": "string"
+ },
+ "logAnalyticsWorkspaceId": {
+ "type": "string"
+ },
+ "supportedClouds": {
+ "type": "array",
+ "defaultValue": [
+ "AzureCloud",
+ "AzureUSGovernment"
+ ]
+ }
+ },
+ "resources": [
+ {
+ "condition": "[contains(parameters('supportedClouds'), environment().name)]",
+ "type": "Microsoft.Insights/diagnosticSettings",
+ "apiVersion": "2017-05-01-preview",
+ "name": "[parameters('diagnosticSettingName')]",
+ "properties": {
+ "workspaceId": "[parameters('logAnalyticsWorkspaceId')]",
+ "logs": [
+ {
+ "category": "Administrative",
+ "enabled": true
+ },
+ {
+ "category": "Security",
+ "enabled": true
+ },
+ {
+ "category": "ServiceHealth",
+ "enabled": true
+ },
+ {
+ "category": "Alert",
+ "enabled": true
+ },
+ {
+ "category": "Recommendation",
+ "enabled": true
+ },
+ {
+ "category": "Policy",
+ "enabled": true
+ },
+ {
+ "category": "Autoscale",
+ "enabled": true
+ },
+ {
+ "category": "ResourceHealth",
+ "enabled": true
+ }
+ ]
+ }
+ }
+ ]
+ }
+ },
+ "dependsOn": [
+ "[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('workloadSubscriptionId'), if(parameters('existingResourceGroup'), parameters('resourceGroupName'), parameters('resourceGroupName'))), 'Microsoft.Resources/deployments', 'spokeNetwork')]"
+ ]
+ },
+ {
+ "condition": "[parameters('deployPolicy')]",
+ "type": "Microsoft.Resources/deployments",
+ "apiVersion": "2022-09-01",
+ "name": "[format('assign-policy-{0}-{1}', parameters('workloadName'), parameters('deploymentNameSuffix'))]",
+ "subscriptionId": "[parameters('workloadSubscriptionId')]",
+ "resourceGroup": "[if(parameters('existingResourceGroup'), parameters('resourceGroupName'), parameters('resourceGroupName'))]",
+ "properties": {
+ "expressionEvaluationOptions": {
+ "scope": "inner"
+ },
+ "mode": "Incremental",
+ "parameters": {
+ "builtInAssignment": {
+ "value": "[parameters('policy')]"
+ },
+ "logAnalyticsWorkspaceName": {
+ "value": "[variables('logAnalyticsWorkspaceResourceId_split')[8]]"
+ },
+ "logAnalyticsWorkspaceResourceGroupName": {
+ "value": "[variables('logAnalyticsWorkspaceResourceId_split')[4]]"
+ },
+ "location": {
+ "value": "[parameters('location')]"
+ },
+ "operationsSubscriptionId": {
+ "value": "[variables('logAnalyticsWorkspaceResourceId_split')[2]]"
+ }
+ },
+ "template": {
+ "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
+ "contentVersion": "1.0.0.0",
+ "metadata": {
+ "_generator": {
+ "name": "bicep",
+ "version": "0.24.24.22086",
+ "templateHash": "16693295535307781768"
+ }
+ },
+ "parameters": {
+ "builtInAssignment": {
+ "type": "string",
+ "defaultValue": "NISTRev4",
+ "allowedValues": [
+ "NISTRev4",
+ "NISTRev5",
+ "IL5",
+ "CMMC"
+ ],
+ "metadata": {
+ "description": "[NISTRev4/NISTRev5/IL5/CMMC] Built-in policy assignments to assign, default is NISTRev4. IL5 is only available for AzureUsGovernment and will switch to NISTRev4 if tried in AzureCloud."
+ }
+ },
+ "logAnalyticsWorkspaceName": {
+ "type": "string"
+ },
+ "logAnalyticsWorkspaceResourceGroupName": {
+ "type": "string"
+ },
+ "operationsSubscriptionId": {
+ "type": "string"
+ },
+ "deployRemediation": {
+ "type": "bool",
+ "defaultValue": false,
+ "metadata": {
+ "description": "Starts a policy remediation for the VM Agent policies in hub RG. Set to false by default since this is time consuming in deployment."
+ }
+ },
+ "location": {
+ "type": "string",
+ "defaultValue": "[resourceGroup().location]",
+ "metadata": {
+ "description": "The location of this resource"
+ }
+ }
+ },
+ "variables": {
+ "$fxv#0": " {\r\n \"listOfMembersToExcludeFromWindowsVMAdministratorsGroup\": \r\n {\r\n \"value\": \"admin\"\r\n },\r\n \"listOfMembersToIncludeInWindowsVMAdministratorsGroup\": \r\n {\r\n \"value\": \"azureuser\"\r\n },\r\n \"logAnalyticsWorkspaceIdforVMReporting\": \r\n {\r\n \"value\": \"\"\r\n },\r\n \"IncludeArcMachines\": \r\n {\r\n \"value\": \"true\"\r\n },\r\n \"MinimumTLSVersion-5752e6d6-1206-46d8-8ab1-ecc2f71a8112\": \r\n {\r\n \"value\": \"1.2\"\r\n },\r\n \"NotAvailableMachineState-bed48b13-6647-468e-aa2f-1af1d3f4dd40\": \r\n {\r\n \"value\": \"Compliant\"\r\n },\r\n \"requiredRetentionDays\": \r\n {\r\n \"value\": \"365\"\r\n },\r\n \"resourceGroupName-b6e2945c-0b7b-40f5-9233-7a5323b5cdc6\": \r\n {\r\n \"value\": \"NetworkWatcherRG\"\r\n }\r\n }",
+ "$fxv#1": " {\r\n \"IncludeArcMachines\": \r\n {\r\n \"value\": \"true\"\r\n },\r\n \"MinimumTLSVersion-5752e6d6-1206-46d8-8ab1-ecc2f71a8112\": \r\n {\r\n \"value\": \"1.2\"\r\n },\r\n \"NotAvailableMachineState-bed48b13-6647-468e-aa2f-1af1d3f4dd40\": \r\n {\r\n \"value\": \"Compliant\"\r\n },\r\n \"requiredRetentionDays\": \r\n {\r\n \"value\": \"365\"\r\n },\r\n \"resourceGroupName-b6e2945c-0b7b-40f5-9233-7a5323b5cdc6\": \r\n {\r\n \"value\": \"NetworkWatcherRG\"\r\n }\r\n }",
+ "$fxv#2": "{\r\n \"IncludeArcMachines\" : { \r\n \"value\" : \"false\"\r\n },\r\n \"NotAvailableMachineState-bed48b13-6647-468e-aa2f-1af1d3f4dd40\" : { \r\n \"value\" : \"Compliant\"\r\n },\r\n \"MinimumTLSVersionForWindowsServers\" : { \r\n \"value\" : \"1.2\"\r\n },\r\n \"requiredRetentionDays\" : { \r\n \"value\" : \"365\"\r\n },\r\n \"effect-febd0533-8e55-448f-b837-bd0e06f16469\" : { \r\n \"value\" : \"audit\"\r\n },\r\n \"allowedContainerImagesRegex-febd0533-8e55-448f-b837-bd0e06f16469\" : { \r\n \"value\" : \"^(.+){0}$\"\r\n },\r\n \"effect-95edb821-ddaf-4404-9732-666045e056b4\" : { \r\n \"value\" : \"audit\"\r\n },\r\n \"effect-440b515e-a580-421e-abeb-b159a61ddcbc\" : { \r\n \"value\" : \"audit\"\r\n },\r\n \"effect-233a2a17-77ca-4fb1-9b6b-69223d272a44\" : { \r\n \"value\" : \"audit\"\r\n },\r\n \"effect-e345eecc-fa47-480f-9e88-67dcc122b164\" : { \r\n \"value\" : \"audit\"\r\n },\r\n \"cpuLimit-e345eecc-fa47-480f-9e88-67dcc122b164\" : { \r\n \"value\" : \"0\"\r\n },\r\n \"memoryLimit-e345eecc-fa47-480f-9e88-67dcc122b164\" : { \r\n \"value\" : \"0\"\r\n },\r\n \"effect-f06ddb64-5fa3-4b77-b166-acb36f7f6042\" : { \r\n \"value\" : \"audit\"\r\n },\r\n \"runAsUserRule-f06ddb64-5fa3-4b77-b166-acb36f7f6042\" : { \r\n \"value\" : \"MustRunAsNonRoot\"\r\n },\r\n \"runAsGroupRule-f06ddb64-5fa3-4b77-b166-acb36f7f6042\" : { \r\n \"value\" : \"RunAsAny\"\r\n },\r\n \"supplementalGroupsRule-f06ddb64-5fa3-4b77-b166-acb36f7f6042\" : { \r\n \"value\" : \"RunAsAny\"\r\n },\r\n \"fsGroupRule-f06ddb64-5fa3-4b77-b166-acb36f7f6042\" : { \r\n \"value\" : \"RunAsAny\"\r\n },\r\n \"effect-1c6e92c9-99f0-4e55-9cf2-0c234dc48f99\" : { \r\n \"value\" : \"audit\"\r\n },\r\n \"effect-47a1ee2f-2a2a-4576-bf2a-e0e36709c2b8\" : { \r\n \"value\" : \"audit\"\r\n },\r\n \"effect-df49d893-a74c-421d-bc95-c663042e5b80\" : { \r\n \"value\" : \"audit\"\r\n },\r\n \"effect-1a5b4dca-0b6f-4cf5-907c-56316bc1bf3d\" : { \r\n \"value\" : \"audit\"\r\n },\r\n \"effect-c26596ff-4d70-4e6a-9a30-c2506bd2f80c\" : { \r\n \"value\" : \"audit\"\r\n },\r\n \"effect-511f5417-5d12-434d-ab2e-816901e72a5e\" : { \r\n \"value\" : \"audit\"\r\n },\r\n \"effect-82985f06-dc18-4a48-bc1c-b9f4f0098cfe\" : { \r\n \"value\" : \"audit\"\r\n },\r\n \"effect-098fc59e-46c7-4d99-9b16-64990e543d75\" : { \r\n \"value\" : \"audit\"\r\n },\r\n \"NetworkWatcherResourceGroupName\" : { \r\n \"value\" : \"NetworkWatcherRG\"\r\n },\r\n \"setting-a6fb4358-5bf4-4ad7-ba82-2cd2f41ce5e9\" : { \r\n \"value\" : \"enabled\"\r\n },\r\n \"aadAuthenticationInServiceFabricMonitoringEffect\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-71ef260a-8f18-47b7-abcb-62d0673d94dc\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-055aa869-bc98-4af8-bafc-23f1ab6ffe2c\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-564feb30-bf6a-4854-b4bb-0d2d2d1e6c66\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-862e97cf-49fc-4a5c-9de4-40d4e2e7c8eb\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-d9da03a1-f3c3-412a-9709-947156872263\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-617c02be-7f02-4efd-8836-3180d47b6c68\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-0b60c0b2-2dc2-4e1c-b5c9-abbed971de53\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-1e66c121-a66a-4b1f-9b83-0fd99bf0fc2d\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-ec068d99-e9c7-401f-8cef-5bdde4e6ccf1\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-c349d81b-9985-44ae-a8da-ff98d108ede8\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-3657f5a0-770e-44a3-b44e-9431ba1e9735\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-b4ac1030-89c5-4697-8e00-28b5ba6a8811\" : { \r\n \"value\" : \"audit\"\r\n },\r\n \"effect-ea0dfaed-95fb-448c-934e-d6e713ce393d\" : { \r\n \"value\" : \"audit\"\r\n },\r\n \"effect-4733ea7b-a883-42fe-8cac-97454c2a9e4a\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-f4b53539-8df9-40e4-86c6-6b607703bd4e\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-41425d9f-d1a5-499a-9932-f8ed8453932c\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-fc4d8e41-e223-45ea-9bf5-eada37891d87\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-86efb160-8de7-451d-bc08-5d475b0aadae\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-4ec52d6d-beb7-40c4-9a9e-fe753254690e\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-64d314f6-6062-4780-a861-c23e8951bee5\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-1fd32ebd-e4c3-4e13-a54a-d7422d4d95f6\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-fa298e57-9444-42ba-bf04-86e8470e32c7\" : { \r\n \"value\" : \"audit\"\r\n },\r\n \"effect-67121cc7-ff39-4ab8-b7e3-95b84dab487d\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-1f905d99-2ab7-462c-a6b0-f709acca6c8f\" : { \r\n \"value\" : \"audit\"\r\n },\r\n \"effect-5b9159ae-1701-4a6f-9a7a-aa9c8ddd0580\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-ba769a63-b8cc-4b2d-abf6-ac33c7204be8\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-81e74cea-30fd-40d5-802f-d72103c2aaaa\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-0aa61e00-0a01-4a3c-9945-e93cffedf0e6\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-47031206-ce96-41f8-861b-6a915f3de284\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-87ba29ef-1ab3-4d82-b763-87fcd4f531f7\" : { \r\n \"value\" : \"audit\"\r\n },\r\n \"effect-51522a96-0869-4791-82f3-981000c2c67f\" : { \r\n \"value\" : \"audit\"\r\n },\r\n \"effect-b5ec538c-daa0-4006-8596-35468b9148e8\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-56a5ee18-2ae6-4810-86f7-18e39ce5629b\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-2e94d99a-8a36-4563-bc77-810d8893b671\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-1fafeaf6-7927-4059-a50a-8eb2a7a6f2b5\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-99e9ccd8-3db9-4592-b0d1-14b1715a4d8a\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-1f68a601-6e6d-4e42-babf-3f643a047ea2\" : { \r\n \"value\" : \"audit\"\r\n },\r\n \"effect-f7d52b2d-e161-4dfa-a82b-55e564167385\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-7d7be79c-23ba-4033-84dd-45e2a5ccdd67\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-ca91455f-eace-4f96-be59-e6e2c35b4816\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-702dd420-7fcc-42c5-afe8-4026edd20fe0\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"diagnosticsLogsInRedisCacheMonitoringEffect\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"secureTransferToStorageAccountMonitoringEffect\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-d0793b48-0edc-4296-a390-4c75d1bdfd71\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-7d092e0a-7acd-40d2-a975-dca21cae48c4\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-2a1a9cdf-e04d-429a-8416-3bfb72a1b26f\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"disableUnrestrictedNetworkToStorageAccountMonitoringEffect\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-55615ac9-af46-4a59-874e-391cc3dfb490\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-1b8ca024-1d5c-4dec-8995-b1a932b41780\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-037eea7a-bd0a-46c5-9a66-03aea78705d3\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-53503636-bcc9-4748-9663-5348217f160f\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-40cec1dd-a100-4920-b15b-3024fe8901ab\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-0725b4dd-7e76-479c-a735-68e7ee23d5ca\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-a049bf77-880b-470f-ba6d-9f21c530cf83\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-ee980b6d-0eca-4501-8d54-f6290fd512c3\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-1d84d5fb-01f6-4d12-ba4f-4a26081d403d\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-37e0d2fe-28a5-43d6-a273-67d37d1f5606\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"identityDesignateMoreThanOneOwnerMonitoringEffect\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"diskEncryptionMonitoringEffect\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"emailNotificationToSubscriptionOwnerHighSeverityAlertsEnabledEffect\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"functionAppDisableRemoteDebuggingMonitoringEffect\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"sqlDbEncryptionMonitoringEffect\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"vulnerabilityAssessmentOnManagedInstanceMonitoringEffect\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"ensurePHPVersionLatestForAPIAppEffect\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"aadAuthenticationInSqlServerMonitoringEffect\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"vmssEndpointProtectionMonitoringEffect\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"vmssOsVulnerabilitiesMonitoringEffect\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"adaptiveApplicationControlsMonitoringEffect\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"geoRedundantBackupShouldBeEnabledForAzureDatabaseForPostgreSQLEffect\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"ensureJavaVersionLatestForWebAppEffect\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"identityDesignateLessThanOwnersMonitoringEffect\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"securityContactEmailAddressForSubscriptionEffect\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"webAppRestrictCORSAccessMonitoringEffect\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"identityRemoveExternalAccountWithWritePermissionsMonitoringEffect\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"identityRemoveExternalAccountWithReadPermissionsMonitoringEffect\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"identityRemoveDeprecatedAccountMonitoringEffect\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"functionAppEnforceHttpsMonitoringEffect\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"ensurePythonVersionLatestForWebAppEffect\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"ensurePythonVersionLatestForFunctionAppEffect\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"ensurePHPVersionLatestForWebAppEffect\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"ensurePythonVersionLatestForAPIAppEffect\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"geoRedundantBackupShouldBeEnabledForAzureDatabaseForMySQLEffect\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"systemUpdatesMonitoringEffect\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"ensureJavaVersionLatestForAPIAppEffect\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"ensureHTTPVersionLatestForWebAppEffect\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"apiAppRequireLatestTlsMonitoringEffect\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"identityEnableMFAForWritePermissionsMonitoringEffect\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"ensureHTTPVersionLatestForAPIAppEffect\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"ensureJavaVersionLatestForFunctionAppEffect\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"nextGenerationFirewallMonitoringEffect\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"useRbacRulesMonitoringEffect\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"webAppEnforceHttpsMonitoringEffect\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"sqlServerAuditingMonitoringEffect\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"vnetEnableDDoSProtectionMonitoringEffect\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"identityEnableMFAForOwnerPermissionsMonitoringEffect\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"sqlServerAdvancedDataSecurityMonitoringEffect\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"sqlManagedInstanceAdvancedDataSecurityMonitoringEffect\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"endpointProtectionMonitoringEffect\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"jitNetworkAccessMonitoringEffect\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"apiAppEnforceHttpsMonitoringEffect\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"geoRedundantStorageShouldBeEnabledForStorageAccountsEffect\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"vmssSystemUpdatesMonitoringEffect\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"webAppDisableRemoteDebuggingMonitoringEffect\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"longtermGeoRedundantBackupEnabledAzureSQLDatabasesEffect\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"systemConfigurationsMonitoringEffect\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"ensureHTTPVersionLatestForFunctionAppEffect\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"identityEnableMFAForReadPermissionsMonitoringEffect\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"containerBenchmarkMonitoringEffect\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"apiAppDisableRemoteDebuggingMonitoringEffect\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"identityRemoveDeprecatedAccountWithOwnerPermissionsMonitoringEffect\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"vulnerabilityAssessmentOnServerMonitoringEffect\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"webAppRequireLatestTlsMonitoringEffect\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"identityRemoveExternalAccountWithOwnerPermissionsMonitoringEffect\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"functionAppRequireLatestTlsMonitoringEffect\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"kubernetesServiceVersionUpToDateMonitoringEffect\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"sqlDbVulnerabilityAssesmentMonitoringEffect\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"membersToIncludeInLocalAdministratorsGroup\" : { \r\n \"value\" : \"\"\r\n },\r\n \"membersToExcludeInLocalAdministratorsGroup\" : { \r\n \"value\" : \"\"\r\n },\r\n \"logAnalyticsWorkspaceIDForVMAgents\" : { \r\n \"value\" : \"\"\r\n },\r\n \"PHPLatestVersionForAppServices\" : { \r\n \"value\" : \"7.4\"\r\n },\r\n \"JavaLatestVersionForAppServices\" : { \r\n \"value\" : \"11\"\r\n },\r\n \"WindowsPythonLatestVersionForAppServices\" : { \r\n \"value\" : \"3.6\"\r\n },\r\n \"LinuxPythonLatestVersionForAppServices\" : { \r\n \"value\" : \"3.9\"\r\n },\r\n \"ensureDotNetFrameworkLatestForFunctionAppEffect\" : { \r\n \"value\" : \"Disabled\"\r\n },\r\n \"sqlManagedInstanceAdvancedDataSecurityEmailsMonitoringEffect\" : { \r\n \"value\" : \"Disabled\"\r\n },\r\n \"vulnerabilityAssessmentMonitoringEffect\" : { \r\n \"value\" : \"Disabled\"\r\n },\r\n \"ensureDotNetFrameworkLatestForWebAppEffect\" : { \r\n \"value\" : \"Disabled\"\r\n },\r\n \"sqlServerAdvancedDataSecurityEmailsMonitoringEffect\" : { \r\n \"value\" : \"Disabled\"\r\n },\r\n \"microsoftIaaSAntimalwareExtensionShouldBeDeployedOnWindowsServersEffect\" : { \r\n \"value\" : \"Disabled\"\r\n },\r\n \"securityCenterStandardPricingTierShouldBeSelectedEffect\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"theLogAnalyticsAgentShouldBeInstalledOnVirtualMachinesEffect\" : { \r\n \"value\" : \"Disabled\"\r\n },\r\n \"ensurePHPVersionLatestForFunctionAppEffect\" : { \r\n \"value\" : \"Disabled\"\r\n },\r\n \"sqlManagedInstanceAdvancedDataSecurityEmailAdminsMonitoringEffect\" : { \r\n \"value\" : \"Disabled\"\r\n },\r\n \"securityContactPhoneNumberShouldBeProvidedForSubscriptionEffect\" : { \r\n \"value\" : \"Disabled\"\r\n },\r\n \"threatDetectionTypesOnManagedInstanceMonitoringEffect\" : { \r\n \"value\" : \"Disabled\"\r\n },\r\n \"ensureDotNetFrameworkLatestForAPIAppEffect\" : { \r\n \"value\" : \"Disabled\"\r\n },\r\n \"sqlServerAdvancedDataSecurityEmailAdminsMonitoringEffect\" : { \r\n \"value\" : \"Disabled\"\r\n },\r\n \"threatDetectionTypesOnServerMonitoringEffect\" : { \r\n \"value\" : \"Disabled\"\r\n },\r\n \"theLogAnalyticsAgentShouldBeInstalledOnVirtualMachineScaleSetsEffect\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n }\r\n}",
+ "$fxv#3": "{\r\n \"logAnalyticsWorkspaceId-f47b5582-33ec-4c5c-87c0-b010a6b2e917\" : { \r\n \"value\" : \"\"\r\n },\r\n \"effect-09024ccc-0c5f-475e-9457-b7c0d9ed487b\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"MembersToExclude-69bf4abd-ca1e-4cf6-8b5a-762d42e61d4f\" :{\r\n \"value\": \"\"\r\n },\r\n \"MembersToInclude-30f71ea1-ac77-4f26-9fc5-2d926bbd4ba7\": {\r\n \"value\": \"\"\r\n },\r\n \"effect-0961003e-5a0a-4549-abde-af6a37f2724d\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"effect-0b15565f-aa9e-48ba-8619-45960f2c314d\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"effect-0e60b895-3786-45da-8377-9c6b4b6ac5f9\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"effect-17k78e20-9358-41c9-923c-fb736d382a12\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"effect-1bc1795e-d44a-4d48-9b3b-6fff0fd5f9ba\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"PHPLatestVersion\" : { \r\n \"value\" : \"7.3\"\r\n },\r\n \"effect-22bee202-a82f-4305-9a2a-6d7f44d4dedb\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-26a828e1-e88f-464e-bbb3-c134a282b9de\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"effect-34c877ad-507e-4c82-993e-3452a6e0ad3c\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-3c735d8a-a4ba-4a3a-b7cf-db7754cf57f4\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"effect-404c3081-a854-4457-ae30-26a93ef643f9\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-47a6b606-51aa-4496-8bb7-64b11cf66adc\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"effect-496223c3-ad65-4ecd-878a-bae78737e9ed\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"JavaLatestVersion\" : { \r\n \"value\" : \"11\"\r\n },\r\n \"effect-4f11b553-d42e-4e3a-89be-32ca364cad4c\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"effect-4f4f78b8-e367-4b10-a341-d9a4ad5cf1c7\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"effect-5c607a2e-c700-4744-8254-d77e7c9eb5e4\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"effect-5f76cf89-fbf2-47fd-a3f4-b891fa780b60\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"effect-6b1cbf55-e8b6-442f-ba4c-7246b6381474\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"effect-6d555dd1-86f2-4f1c-8ed7-5abae7c6cbab\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-7008174a-fd10-4ef0-817e-fc820a951d73\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"LinuxPythonLatestVersion\" : { \r\n \"value\" : \"3.8\"\r\n },\r\n \"effect-7238174a-fd10-4ef0-817e-fc820a951d73\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"effect-7261b898-8a84-4db8-9e04-18527132abb3\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"effect-74c3584d-afae-46f7-a20a-6f8adba71a16\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"effect-86b3d65f-7626-441e-b690-81a8b71cff60\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"effect-88999f4c-376a-45c8-bcb3-4058f713cf39\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"effect-8c122334-9d20-4eb8-89ea-ac9a705b74ae\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"effect-8cb6aa8b-9e41-4f4e-aa25-089a7ac2581e\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"effect-9297c21d-2ed6-4474-b48f-163f75654ce3\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"effect-991310cd-e9f3-47bc-b7b6-f57b557d07db\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"effect-9b597639-28e4-48eb-b506-56b05d366257\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"effect-9d0b6ea4-93e2-4578-bf2f-6bb17d22b4bc\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"effect-9daedab3-fb2d-461e-b861-71790eead4f6\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"effect-a4af4a39-4135-47fb-b175-47fbdf85311d\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-a6fb4358-5bf4-4ad7-ba82-2cd2f41ce5e9\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"setting-a6fb4358-5bf4-4ad7-ba82-2cd2f41ce5e9\" : { \r\n \"value\" : \"enabled\"\r\n },\r\n \"effect-a70ca396-0a34-413a-88e1-b956c1e683be\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"effect-aa633080-8b72-40c4-a2d7-d00c03e80bed\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"effect-abfb4388-5bf4-4ad7-ba82-2cd2f41ceae9\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"effect-abfb7388-5bf4-4ad7-ba99-2cd2f41cebb9\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"effect-af6cd1bd-1635-48cb-bde7-5b15693900b9\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"resourceGroupName-b6e2945c-0b7b-40f5-9233-7a5323b5cdc6\" : { \r\n \"value\" : \"NetworkWatcherRG\"\r\n },\r\n \"effect-b7ddfbdc-1260-477d-91fd-98bd9be789a6\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-c3f317a7-a95c-4547-b7e7-11017ebdf2fe\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"effect-cb510bfd-1cba-4d9f-a230-cb0976f4bb71\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"effect-e1e5fd5d-3e4c-4ce1-8661-7d1873ae6b15\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"effect-e2c1c086-2d84-4019-bff3-c44ccd95113c\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"effect-e3576e28-8b17-4677-84c3-db2990658d64\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"effect-e8cbc669-f12d-49eb-93e7-9273119e9933\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"effect-e9c8d085-d9cc-4b17-9cdc-059f1f01f19e\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"effect-ebb62a0c-3560-49e1-89ed-27e074e9f8ad\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"effect-efbde977-ba53-4479-b8e9-10b957924fbf\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"effect-f0e6e85b-9b9f-4a4b-b67b-f730d42f1b0b\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"effect-f6de0be7-9a8a-4b8a-b349-43cf02d22f7c\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"effect-f8456c1c-aa66-4dfb-861a-25d127b775c9\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"effect-f9d614c5-c173-4d56-95a7-b4437057d193\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"effect-fb893a29-21bb-418c-a157-e99480ec364c\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-feedbf84-6b99-488c-acc2-71c829aa5ffc\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"effect-3b980d31-7904-4bb7-8575-5665739a8052\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"effect-6e2593d9-add6-4083-9c9b-4b7d2188c899\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"effect-b607c5de-e7d9-4eee-9e5c-83f1bcee4fa0\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"effect-12430be1-6cc8-4527-a9a8-e3d38f250096\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"modeRequirement-12430be1-6cc8-4527-a9a8-e3d38f250096\" : { \r\n \"value\" : \"Detection\"\r\n },\r\n \"effect-425bea59-a659-4cbb-8d31-34499bd030b8\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"modeRequirement-425bea59-a659-4cbb-8d31-34499bd030b8\" : { \r\n \"value\" : \"Detection\"\r\n },\r\n \"effect-564feb30-bf6a-4854-b4bb-0d2d2d1e6c66\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-055aa869-bc98-4af8-bafc-23f1ab6ffe2c\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-013e242c-8828-4970-87b3-ab247555486d\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"effect-d38fc420-0735-4ef3-ac11-c806f651a570\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"effect-a1181c5f-672a-477a-979a-7d58aa086233\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-308fbb08-4ab8-4e67-9b29-592e93fb94fa\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"effect-4da35fc9-c9e7-4960-aec9-797fe7d9051d\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"effect-523b5cd1-3e23-492f-a539-13118b6d1e3a\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"effect-7fe3b40f-802b-4cdd-8bd4-fd799c948cc2\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"effect-c25d9a16-bc35-4e15-a7e5-9db606bf9ed4\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"effect-b0f33259-77d7-4c9e-aac6-3aabcfae693c\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"effect-037eea7a-bd0a-46c5-9a66-03aea78705d3\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-0725b4dd-7e76-479c-a735-68e7ee23d5ca\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-0820b7b9-23aa-4725-a1ce-ae4558f718e5\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"effect-2c89a2e5-7285-40fe-afe0-ae8654b92fab\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-358c20a6-3f9e-4f0e-97ff-c6ce485e2aac\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"effect-5744710e-cc2f-4ee8-8809-3b11e89f4bc9\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"effect-ac4a19c2-fa67-49b4-8ae5-0b2e78c49457\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-c9d007d0-c057-4772-b18c-01e546713bcd\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-d0793b48-0edc-4296-a390-4c75d1bdfd71\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-e372f825-a257-4fb8-9175-797a8a8627d6\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-d158790f-bfb0-486c-8631-2dc6b4e8e6af\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-e802a67a-daf5-4436-9ea6-f6d821dd0c5d\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-a451c1ef-c6ca-483d-87ed-f49761e3ffb5\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-b954148f-4c11-4c38-8221-be76711e194a-MicrosoftSql-servers-firewallRules-delete\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"effect-b954148f-4c11-4c38-8221-be76711e194a-MicrosoftNetwork-networkSecurityGroups-delete\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"effect-b954148f-4c11-4c38-8221-be76711e194a-MicrosoftClassicNetwork-networkSecurityGroups-delete\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"effect-b954148f-4c11-4c38-8221-be76711e194a-MicrosoftNetwork-networkSecurityGroups-securityRules-delete\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"effect-b954148f-4c11-4c38-8221-be76711e194a-MicrosoftClassicNetwork-networkSecurityGroups-securityRules-delete\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"effect-ae89ebca-1c92-4898-ac2c-9f63decb045c\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"effect-d26f7642-7545-4e18-9b75-8c9bbdee3a9a\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"effect-1a4e592a-6a6e-44a5-9814-e36264ca96e7\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"effect-7796937f-307b-4598-941c-67d3a05ebfe7\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"effect-c5447c04-a4d7-4ba8-a263-c9ee321a6858\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"effect-41388f1c-2db0-4c25-95b2-35d7f5ccbfa9\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"effect-b02aacc0-b073-424e-8298-42b22829ee0a\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"effect-057d6cfe-9c4f-4a6d-bc60-14420ea1f1a9\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"effect-0ec47710-77ff-4a3d-9181-6aa50af424d0\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-48af4db5-9b8b-401c-8e74-076be876a430\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-82339799-d096-41ae-8538-b108becf0970\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-1b7aa243-30e4-4c9e-bca8-d0d3022b634a\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"effect-ef2a8f2a-b3d9-49cd-a8a8-9a3aaaf647d9\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"effect-bb91dfba-c30d-4263-9add-9c2384e659a6\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"effect-e71308d3-144b-4262-b144-efdc3cc90517\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"effect-2bdd0062-9d75-436e-89df-487dd8e4b3c7\" : { \r\n \"value\" : \"Disabled\"\r\n },\r\n \"effect-4733ea7b-a883-42fe-8cac-97454c2a9e4a\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-67121cc7-ff39-4ab8-b7e3-95b84dab487d\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-6fac406b-40ca-413b-bf8e-0bf964659c25\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-81e74cea-30fd-40d5-802f-d72103c2aaaa\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-c349d81b-9985-44ae-a8da-ff98d108ede8\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-f4b53539-8df9-40e4-86c6-6b607703bd4e\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-ec068d99-e9c7-401f-8cef-5bdde4e6ccf1\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-048248b0-55cd-46da-b1ff-39efd52db260\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"effect-0d134df8-db83-46fb-ad72-fe0c9428c8dd\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"effect-2c89a2e5-7285-40fe-afe0-ae8654b92fb2\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-3657f5a0-770e-44a3-b44e-9431ba1e9735\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-5b9159ae-1701-4a6f-9a7a-aa9c8ddd0580\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-617c02be-7f02-4efd-8836-3180d47b6c68\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-7d7be79c-23ba-4033-84dd-45e2a5ccdd67\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-87ba29ef-1ab3-4d82-b763-87fcd4f531f7\" : { \r\n \"value\" : \"audit\"\r\n },\r\n \"effect-f7d52b2d-e161-4dfa-a82b-55e564167385\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-c43e4a30-77cb-48ab-a4dd-93f175c63b57\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"effect-0b60c0b2-2dc2-4e1c-b5c9-abbed971de53\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-1e66c121-a66a-4b1f-9b83-0fd99bf0fc2d\" : { \r\n \"value\" : \"Audit\"\r\n },\r\n \"effect-1f314764-cb73-4fc9-b863-8eca98ac36e9\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n },\r\n \"effect-123a3936-f020-408a-ba0c-47873faf1534\" : { \r\n \"value\" : \"AuditIfNotExists\"\r\n }\r\n}\r\n",
+ "modifiedAssignment": "[if(and(equals(toLower(environment().name), toLower('AzureCloud')), equals(toLower(parameters('builtInAssignment')), toLower('IL5'))), 'NISTRev4', parameters('builtInAssignment'))]",
+ "assignmentName": "[format('{0} {1}', variables('modifiedAssignment'), resourceGroup().name)]",
+ "agentVmssAssignmentName": "[format('Deploy VMSS Agents {0}', resourceGroup().name)]",
+ "agentVmAssignmentName": "[format('Deploy VM Agents {0}', resourceGroup().name)]",
+ "contributorRoleDefinitionId": "[resourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]",
+ "lawsReaderRoleDefinitionId": "[resourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293')]"
+ },
+ "resources": [
+ {
+ "type": "Microsoft.Authorization/policyAssignments",
+ "apiVersion": "2020-09-01",
+ "name": "[variables('assignmentName')]",
+ "location": "[parameters('location')]",
+ "properties": {
+ "policyDefinitionId": "[createObject('NISTRev4', createObject('id', '/providers/Microsoft.Authorization/policySetDefinitions/cf25b9c1-bd23-4eb6-bd2c-f4f3ac644a5f', 'parameters', json(replace(variables('$fxv#0'), '', extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('operationsSubscriptionId'), parameters('logAnalyticsWorkspaceResourceGroupName')), 'Microsoft.OperationalInsights/workspaces', parameters('logAnalyticsWorkspaceName'))))), 'NISTRev5', createObject('id', '/providers/Microsoft.Authorization/policySetDefinitions/179d1daa-458f-4e47-8086-2a68d0d6c38f', 'parameters', json(variables('$fxv#1'))), 'IL5', createObject('id', '/providers/Microsoft.Authorization/policySetDefinitions/f9a961fa-3241-4b20-adc4-bbf8ad9d7197', 'parameters', json(replace(variables('$fxv#2'), '', extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('operationsSubscriptionId'), parameters('logAnalyticsWorkspaceResourceGroupName')), 'Microsoft.OperationalInsights/workspaces', parameters('logAnalyticsWorkspaceName'))))), 'CMMC', createObject('id', '/providers/Microsoft.Authorization/policySetDefinitions/b5629c75-5c77-4422-87b9-2509e680f8de', 'parameters', json(replace(variables('$fxv#3'), '', reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('operationsSubscriptionId'), parameters('logAnalyticsWorkspaceResourceGroupName')), 'Microsoft.OperationalInsights/workspaces', parameters('logAnalyticsWorkspaceName')), '2021-06-01').customerId))))[variables('modifiedAssignment')].id]",
+ "parameters": "[createObject('NISTRev4', createObject('id', '/providers/Microsoft.Authorization/policySetDefinitions/cf25b9c1-bd23-4eb6-bd2c-f4f3ac644a5f', 'parameters', json(replace(variables('$fxv#0'), '', extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('operationsSubscriptionId'), parameters('logAnalyticsWorkspaceResourceGroupName')), 'Microsoft.OperationalInsights/workspaces', parameters('logAnalyticsWorkspaceName'))))), 'NISTRev5', createObject('id', '/providers/Microsoft.Authorization/policySetDefinitions/179d1daa-458f-4e47-8086-2a68d0d6c38f', 'parameters', json(variables('$fxv#1'))), 'IL5', createObject('id', '/providers/Microsoft.Authorization/policySetDefinitions/f9a961fa-3241-4b20-adc4-bbf8ad9d7197', 'parameters', json(replace(variables('$fxv#2'), '', extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('operationsSubscriptionId'), parameters('logAnalyticsWorkspaceResourceGroupName')), 'Microsoft.OperationalInsights/workspaces', parameters('logAnalyticsWorkspaceName'))))), 'CMMC', createObject('id', '/providers/Microsoft.Authorization/policySetDefinitions/b5629c75-5c77-4422-87b9-2509e680f8de', 'parameters', json(replace(variables('$fxv#3'), '', reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('operationsSubscriptionId'), parameters('logAnalyticsWorkspaceResourceGroupName')), 'Microsoft.OperationalInsights/workspaces', parameters('logAnalyticsWorkspaceName')), '2021-06-01').customerId))))[variables('modifiedAssignment')].parameters]"
+ },
+ "identity": {
+ "type": "SystemAssigned"
+ }
+ },
+ {
+ "type": "Microsoft.Authorization/policyAssignments",
+ "apiVersion": "2020-09-01",
+ "name": "[variables('agentVmssAssignmentName')]",
+ "location": "[parameters('location')]",
+ "properties": {
+ "policyDefinitionId": "[tenantResourceId('Microsoft.Authorization/policySetDefinitions', '75714362-cae7-409e-9b99-a8e5075b7fad')]",
+ "parameters": {
+ "logAnalytics_1": {
+ "value": "[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('operationsSubscriptionId'), parameters('logAnalyticsWorkspaceResourceGroupName')), 'Microsoft.OperationalInsights/workspaces', parameters('logAnalyticsWorkspaceName'))]"
+ }
+ }
+ },
+ "identity": {
+ "type": "SystemAssigned"
+ }
+ },
+ {
+ "type": "Microsoft.Authorization/policyAssignments",
+ "apiVersion": "2020-09-01",
+ "name": "[variables('agentVmAssignmentName')]",
+ "location": "[parameters('location')]",
+ "properties": {
+ "policyDefinitionId": "[tenantResourceId('Microsoft.Authorization/policySetDefinitions', '55f3eceb-5573-4f18-9695-226972c6d74a')]",
+ "parameters": {
+ "logAnalytics_1": {
+ "value": "[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('operationsSubscriptionId'), parameters('logAnalyticsWorkspaceResourceGroupName')), 'Microsoft.OperationalInsights/workspaces', parameters('logAnalyticsWorkspaceName'))]"
+ }
+ }
+ },
+ "identity": {
+ "type": "SystemAssigned"
+ }
+ },
+ {
+ "type": "Microsoft.Authorization/roleAssignments",
+ "apiVersion": "2020-04-01-preview",
+ "name": "[guid(variables('contributorRoleDefinitionId'), variables('assignmentName'))]",
+ "properties": {
+ "roleDefinitionId": "[variables('contributorRoleDefinitionId')]",
+ "principalId": "[if(empty(variables('modifiedAssignment')), '', reference(resourceId('Microsoft.Authorization/policyAssignments', variables('assignmentName')), '2020-09-01', 'full').identity.principalId)]",
+ "principalType": "ServicePrincipal"
+ },
+ "dependsOn": [
+ "[resourceId('Microsoft.Authorization/policyAssignments', variables('assignmentName'))]"
+ ]
+ },
+ {
+ "type": "Microsoft.Authorization/roleAssignments",
+ "apiVersion": "2020-04-01-preview",
+ "name": "[guid(variables('contributorRoleDefinitionId'), variables('agentVmssAssignmentName'))]",
+ "properties": {
+ "roleDefinitionId": "[variables('contributorRoleDefinitionId')]",
+ "principalId": "[reference(resourceId('Microsoft.Authorization/policyAssignments', variables('agentVmssAssignmentName')), '2020-09-01', 'full').identity.principalId]",
+ "principalType": "ServicePrincipal"
+ },
+ "dependsOn": [
+ "[resourceId('Microsoft.Authorization/policyAssignments', variables('agentVmssAssignmentName'))]"
+ ]
+ },
+ {
+ "type": "Microsoft.Authorization/roleAssignments",
+ "apiVersion": "2020-04-01-preview",
+ "name": "[guid(variables('contributorRoleDefinitionId'), variables('agentVmAssignmentName'))]",
+ "properties": {
+ "roleDefinitionId": "[variables('contributorRoleDefinitionId')]",
+ "principalId": "[reference(resourceId('Microsoft.Authorization/policyAssignments', variables('agentVmAssignmentName')), '2020-09-01', 'full').identity.principalId]",
+ "principalType": "ServicePrincipal"
+ },
+ "dependsOn": [
+ "[resourceId('Microsoft.Authorization/policyAssignments', variables('agentVmAssignmentName'))]"
+ ]
+ },
+ {
+ "condition": "[parameters('deployRemediation')]",
+ "type": "Microsoft.PolicyInsights/remediations",
+ "apiVersion": "2019-07-01",
+ "name": "VM-Agent-Policy-Remediation",
+ "properties": {
+ "policyAssignmentId": "[resourceId('Microsoft.Authorization/policyAssignments', variables('agentVmAssignmentName'))]",
+ "resourceDiscoveryMode": "ReEvaluateCompliance"
+ },
+ "dependsOn": [
+ "[resourceId('Microsoft.Authorization/policyAssignments', variables('agentVmAssignmentName'))]"
+ ]
+ },
+ {
+ "type": "Microsoft.Resources/deployments",
+ "apiVersion": "2022-09-01",
+ "name": "[format('Assign-Laws-Role-Policy-{0}', resourceGroup().name)]",
+ "subscriptionId": "[parameters('operationsSubscriptionId')]",
+ "resourceGroup": "[parameters('logAnalyticsWorkspaceResourceGroupName')]",
+ "properties": {
+ "expressionEvaluationOptions": {
+ "scope": "inner"
+ },
+ "mode": "Incremental",
+ "parameters": {
+ "targetResourceId": {
+ "value": "[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('operationsSubscriptionId'), parameters('logAnalyticsWorkspaceResourceGroupName')), 'Microsoft.OperationalInsights/workspaces', parameters('logAnalyticsWorkspaceName'))]"
+ },
+ "roleDefinitionId": {
+ "value": "[variables('lawsReaderRoleDefinitionId')]"
+ },
+ "principalId": {
+ "value": "[reference(resourceId('Microsoft.Authorization/policyAssignments', variables('agentVmAssignmentName')), '2020-09-01', 'full').identity.principalId]"
+ }
+ },
+ "template": {
+ "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
+ "contentVersion": "1.0.0.0",
+ "metadata": {
+ "_generator": {
+ "name": "bicep",
+ "version": "0.24.24.22086",
+ "templateHash": "8686326864657481429"
+ }
+ },
+ "parameters": {
+ "targetResourceId": {
+ "type": "string"
+ },
+ "roleDefinitionId": {
+ "type": "string"
+ },
+ "principalId": {
+ "type": "string"
+ },
+ "principalType": {
+ "type": "string",
+ "defaultValue": "ServicePrincipal",
+ "allowedValues": [
+ "ForeignGroup",
+ "Group",
+ "ServicePrincipal",
+ "User"
+ ]
+ },
+ "description": {
+ "type": "string",
+ "defaultValue": ""
+ }
+ },
+ "resources": [
+ {
+ "type": "Microsoft.Authorization/roleAssignments",
+ "apiVersion": "2020-04-01-preview",
+ "name": "[guid(parameters('targetResourceId'), parameters('roleDefinitionId'), parameters('principalId'))]",
+ "properties": {
+ "principalId": "[parameters('principalId')]",
+ "principalType": "[parameters('principalType')]",
+ "roleDefinitionId": "[parameters('roleDefinitionId')]",
+ "description": "[parameters('description')]"
+ }
+ }
+ ]
+ }
+ },
+ "dependsOn": [
+ "[resourceId('Microsoft.Authorization/policyAssignments', variables('agentVmAssignmentName'))]"
+ ]
+ }
+ ]
+ }
+ }
+ },
+ {
+ "condition": "[parameters('deployDefender')]",
+ "type": "Microsoft.Resources/deployments",
+ "apiVersion": "2022-09-01",
+ "name": "[format('set-{0}-sub-defender', parameters('workloadName'))]",
+ "subscriptionId": "[parameters('workloadSubscriptionId')]",
+ "location": "[resourceGroup().location]",
+ "properties": {
+ "expressionEvaluationOptions": {
+ "scope": "inner"
+ },
+ "mode": "Incremental",
+ "parameters": {
+ "logAnalyticsWorkspaceId": {
+ "value": "[parameters('logAnalyticsWorkspaceResourceId')]"
+ },
+ "emailSecurityContact": {
+ "value": "[parameters('emailSecurityContact')]"
+ }
+ },
+ "template": {
+ "$schema": "https://schema.management.azure.com/schemas/2018-05-01/subscriptionDeploymentTemplate.json#",
+ "contentVersion": "1.0.0.0",
+ "metadata": {
+ "_generator": {
+ "name": "bicep",
+ "version": "0.24.24.22086",
+ "templateHash": "17349871984393503749"
+ }
+ },
+ "parameters": {
+ "bundle": {
+ "type": "array",
+ "defaultValue": "[if(equals(environment().name, 'AzureCloud'), createArray('Api', 'AppServices', 'Arm', 'CloudPosture', 'Containers', 'CosmosDbs', 'KeyVaults', 'OpenSourceRelationalDatabases', 'SqlServers', 'SqlServerVirtualMachines', 'StorageAccounts', 'VirtualMachines'), if(equals(environment().name, 'AzureUSGovernment'), createArray('Arm', 'Containers', 'OpenSourceRelationalDatabases', 'SqlServers', 'SqlServerVirtualMachines', 'StorageAccounts', 'VirtualMachines'), createArray()))]"
+ },
+ "enableAutoProvisioning": {
+ "type": "bool",
+ "defaultValue": true,
+ "metadata": {
+ "description": "Turn automatic deployment by Defender of the MMA (OMS VM extension) on or off"
+ }
+ },
+ "logAnalyticsWorkspaceId": {
+ "type": "string",
+ "metadata": {
+ "description": "Specify the ID of your custom Log Analytics workspace to collect Defender data."
+ }
+ },
+ "emailSecurityContact": {
+ "type": "string",
+ "metadata": {
+ "description": "Email address of the contact, in the form of john@doe.com"
+ }
+ },
+ "policySetDescription": {
+ "type": "string",
+ "defaultValue": "The Microsoft Cloud Security Benchmark initiative represents the policies and controls implementing security recommendations defined in Microsoft Cloud Security Benchmark v2, see https://aka.ms/azsecbm. This also serves as the Microsoft Defender for Cloud default policy initiative. You can directly assign this initiative, or manage its policies and compliance results within Microsoft Defender.",
+ "metadata": {
+ "description": "Policy Initiative description field"
+ }
+ },
+ "defenderSkuTier": {
+ "type": "string",
+ "defaultValue": "Standard",
+ "metadata": {
+ "description": "[Standard/Free] The SKU for Defender. It defaults to \"Standard\"."
+ }
+ }
+ },
+ "variables": {
+ "autoProvisioning": "[if(parameters('enableAutoProvisioning'), 'On', 'Off')]"
+ },
+ "resources": [
+ {
+ "copy": {
+ "name": "defenderPricing",
+ "count": "[length(parameters('bundle'))]",
+ "mode": "serial",
+ "batchSize": 1
+ },
+ "type": "Microsoft.Security/pricings",
+ "apiVersion": "2023-01-01",
+ "name": "[parameters('bundle')[copyIndex()]]",
+ "properties": {
+ "pricingTier": "[parameters('defenderSkuTier')]"
+ }
+ },
+ {
+ "type": "Microsoft.Security/autoProvisioningSettings",
+ "apiVersion": "2019-01-01",
+ "name": "default",
+ "properties": {
+ "autoProvision": "[variables('autoProvisioning')]"
+ }
+ },
+ {
+ "type": "Microsoft.Security/workspaceSettings",
+ "apiVersion": "2019-01-01",
+ "name": "default",
+ "properties": {
+ "workspaceId": "[parameters('logAnalyticsWorkspaceId')]",
+ "scope": "[subscription().id]"
+ }
+ },
+ {
+ "condition": "[not(empty(parameters('emailSecurityContact')))]",
+ "type": "Microsoft.Security/securityContacts",
+ "apiVersion": "2020-01-01-preview",
+ "name": "default",
+ "properties": {
+ "notificationsByRole": {
+ "roles": [
+ "AccountAdmin",
+ "Contributor",
+ "Owner",
+ "ServiceAdmin"
+ ],
+ "state": "On"
+ },
+ "alertNotifications": {
+ "state": "On"
+ },
+ "emails": "[parameters('emailSecurityContact')]"
+ }
+ },
+ {
+ "type": "Microsoft.Authorization/policyAssignments",
+ "apiVersion": "2022-06-01",
+ "name": "Microsoft Cloud Security Benchmark",
+ "properties": {
+ "displayName": "Defender Default",
+ "description": "[parameters('policySetDescription')]",
+ "enforcementMode": "DoNotEnforce",
+ "parameters": {},
+ "policyDefinitionId": "[tenantResourceId('Microsoft.Authorization/policySetDefinitions', '1f3afdf9-d0c9-4c3d-847f-89da613e70a8')]"
+ }
+ }
+ ]
+ }
+ }
+ }
+ ],
+ "outputs": {
+ "rg": {
+ "type": "string",
+ "value": "[if(parameters('existingResourceGroup'), parameters('resourceGroupName'), parameters('resourceGroupName'))]"
+ },
+ "location": {
+ "type": "string",
+ "value": "[parameters('location')]"
+ },
+ "virtualNetworkName": {
+ "type": "string",
+ "value": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('workloadSubscriptionId'), if(parameters('existingResourceGroup'), parameters('resourceGroupName'), parameters('resourceGroupName'))), 'Microsoft.Resources/deployments', 'spokeNetwork'), '2022-09-01').outputs.virtualNetworkName.value]"
+ },
+ "virtualNetworkAddressPrefix": {
+ "type": "string",
+ "value": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('workloadSubscriptionId'), if(parameters('existingResourceGroup'), parameters('resourceGroupName'), parameters('resourceGroupName'))), 'Microsoft.Resources/deployments', 'spokeNetwork'), '2022-09-01').outputs.virtualNetworkAddressPrefix.value]"
+ },
+ "virtualNetworkResourceId": {
+ "type": "string",
+ "value": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('workloadSubscriptionId'), if(parameters('existingResourceGroup'), parameters('resourceGroupName'), parameters('resourceGroupName'))), 'Microsoft.Resources/deployments', 'spokeNetwork'), '2022-09-01').outputs.virtualNetworkResourceId.value]"
+ },
+ "subnetName": {
+ "type": "string",
+ "value": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('workloadSubscriptionId'), if(parameters('existingResourceGroup'), parameters('resourceGroupName'), parameters('resourceGroupName'))), 'Microsoft.Resources/deployments', 'spokeNetwork'), '2022-09-01').outputs.subnetName.value]"
+ },
+ "subnetAddressPrefix": {
+ "type": "string",
+ "value": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('workloadSubscriptionId'), if(parameters('existingResourceGroup'), parameters('resourceGroupName'), parameters('resourceGroupName'))), 'Microsoft.Resources/deployments', 'spokeNetwork'), '2022-09-01').outputs.subnetAddressPrefix.value]"
+ },
+ "subnetResourceId": {
+ "type": "string",
+ "value": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('workloadSubscriptionId'), if(parameters('existingResourceGroup'), parameters('resourceGroupName'), parameters('resourceGroupName'))), 'Microsoft.Resources/deployments', 'spokeNetwork'), '2022-09-01').outputs.subnetResourceId.value]"
+ },
+ "networkSecurityGroupName": {
+ "type": "string",
+ "value": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('workloadSubscriptionId'), if(parameters('existingResourceGroup'), parameters('resourceGroupName'), parameters('resourceGroupName'))), 'Microsoft.Resources/deployments', 'spokeNetwork'), '2022-09-01').outputs.networkSecurityGroupName.value]"
+ },
+ "networkSecurityGroupResourceId": {
+ "type": "string",
+ "value": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('workloadSubscriptionId'), if(parameters('existingResourceGroup'), parameters('resourceGroupName'), parameters('resourceGroupName'))), 'Microsoft.Resources/deployments', 'spokeNetwork'), '2022-09-01').outputs.networkSecurityGroupResourceId.value]"
+ }
+ }
+ }
+ },
+ "dependsOn": [
+ "[subscriptionResourceId('Microsoft.Resources/resourceGroups', parameters('resourceGroupName'))]"
+ ]
+ },
+ {
+ "type": "Microsoft.Resources/deployments",
+ "apiVersion": "2022-09-01",
+ "name": "[format('baseline-{0}', parameters('deploymentNameSuffix'))]",
+ "location": "[deployment().location]",
+ "properties": {
+ "expressionEvaluationOptions": {
+ "scope": "inner"
+ },
+ "mode": "Incremental",
+ "parameters": {
+ "computeGalleryName": {
+ "value": "[parameters('computeGalleryName')]"
+ },
+ "deploymentNameSuffix": {
+ "value": "[parameters('deploymentNameSuffix')]"
+ },
+ "diskEncryptionSetResourceId": {
+ "value": "[parameters('diskEncryptionSetResourceId')]"
+ },
+ "enableBuildAutomation": {
+ "value": "[parameters('enableBuildAutomation')]"
+ },
+ "exemptPolicyAssignmentIds": {
+ "value": "[parameters('exemptPolicyAssignmentIds')]"
+ },
+ "location": {
+ "value": "[parameters('location')]"
+ },
+ "resourceGroupName": "[if(parameters('existingResourceGroup'), createObject('value', parameters('resourceGroupName')), createObject('value', parameters('resourceGroupName')))]",
+ "storageAccountResourceId": {
+ "value": "[parameters('storageAccountResourceId')]"
+ },
+ "subscriptionId": {
+ "value": "[variables('subscriptionId')]"
+ },
+ "tags": {
+ "value": "[parameters('tags')]"
+ },
+ "userAssignedIdentityName": {
+ "value": "[parameters('userAssignedIdentityName')]"
+ }
+ },
+ "template": {
+ "$schema": "https://schema.management.azure.com/schemas/2018-05-01/subscriptionDeploymentTemplate.json#",
+ "contentVersion": "1.0.0.0",
+ "metadata": {
+ "_generator": {
+ "name": "bicep",
+ "version": "0.24.24.22086",
+ "templateHash": "3810275683162469600"
+ }
+ },
+ "parameters": {
+ "computeGalleryName": {
+ "type": "string"
+ },
+ "deploymentNameSuffix": {
+ "type": "string"
+ },
+ "diskEncryptionSetResourceId": {
+ "type": "string"
+ },
+ "enableBuildAutomation": {
+ "type": "bool"
+ },
+ "exemptPolicyAssignmentIds": {
+ "type": "array"
+ },
+ "location": {
+ "type": "string"
+ },
+ "resourceGroupName": {
+ "type": "string"
+ },
+ "storageAccountResourceId": {
+ "type": "string"
+ },
+ "subscriptionId": {
+ "type": "string"
+ },
+ "tags": {
+ "type": "object"
+ },
+ "userAssignedIdentityName": {
+ "type": "string"
+ }
+ },
+ "resources": [
+ {
+ "type": "Microsoft.Resources/deployments",
+ "apiVersion": "2022-09-01",
+ "name": "[format('user-assigned-identity-{0}', parameters('deploymentNameSuffix'))]",
+ "subscriptionId": "[parameters('subscriptionId')]",
+ "resourceGroup": "[parameters('resourceGroupName')]",
+ "properties": {
+ "expressionEvaluationOptions": {
+ "scope": "inner"
+ },
+ "mode": "Incremental",
+ "parameters": {
+ "location": {
+ "value": "[parameters('location')]"
+ },
+ "name": {
+ "value": "[parameters('userAssignedIdentityName')]"
+ },
+ "tags": {
+ "value": "[parameters('tags')]"
+ }
+ },
+ "template": {
+ "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
+ "contentVersion": "1.0.0.0",
+ "metadata": {
+ "_generator": {
+ "name": "bicep",
+ "version": "0.24.24.22086",
+ "templateHash": "13213041153837743619"
+ }
+ },
+ "parameters": {
+ "location": {
+ "type": "string"
+ },
+ "name": {
+ "type": "string"
+ },
+ "tags": {
+ "type": "object"
+ }
+ },
+ "resources": [
+ {
+ "type": "Microsoft.ManagedIdentity/userAssignedIdentities",
+ "apiVersion": "2018-11-30",
+ "name": "[parameters('name')]",
+ "location": "[parameters('location')]",
+ "tags": "[if(contains(parameters('tags'), 'Microsoft.ManagedIdentity/userAssignedIdentities'), parameters('tags')['Microsoft.ManagedIdentity/userAssignedIdentities'], createObject())]"
+ }
+ ],
+ "outputs": {
+ "clientId": {
+ "type": "string",
+ "value": "[reference(resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', parameters('name')), '2018-11-30').clientId]"
+ },
+ "principalId": {
+ "type": "string",
+ "value": "[reference(resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', parameters('name')), '2018-11-30').principalId]"
+ },
+ "resourceId": {
+ "type": "string",
+ "value": "[resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', parameters('name'))]"
+ }
+ }
+ }
+ }
+ },
+ {
+ "type": "Microsoft.Resources/deployments",
+ "apiVersion": "2022-09-01",
+ "name": "[format('role-assignment-compute-{0}', parameters('deploymentNameSuffix'))]",
+ "subscriptionId": "[parameters('subscriptionId')]",
+ "resourceGroup": "[parameters('resourceGroupName')]",
+ "properties": {
+ "expressionEvaluationOptions": {
+ "scope": "inner"
+ },
+ "mode": "Incremental",
+ "parameters": {
+ "principalId": {
+ "value": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('subscriptionId'), parameters('resourceGroupName')), 'Microsoft.Resources/deployments', format('user-assigned-identity-{0}', parameters('deploymentNameSuffix'))), '2022-09-01').outputs.principalId.value]"
+ }
+ },
+ "template": {
+ "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
+ "contentVersion": "1.0.0.0",
+ "metadata": {
+ "_generator": {
+ "name": "bicep",
+ "version": "0.24.24.22086",
+ "templateHash": "12486914288824279509"
+ }
+ },
+ "parameters": {
+ "principalId": {
+ "type": "string"
+ }
+ },
+ "variables": {
+ "roleDefinitionIds": [
+ "f353d9bd-d4a6-484e-a77a-8050b599b867",
+ "f1a07417-d97a-45cb-824c-7a7467783830",
+ "acdd72a7-3385-48ef-bd42-f606fba81ae7",
+ "9980e02c-c2be-4d73-94e8-173b1dc7cf3c"
+ ]
+ },
+ "resources": [
+ {
+ "copy": {
+ "name": "roleAssignment",
+ "count": "[length(variables('roleDefinitionIds'))]"
+ },
+ "type": "Microsoft.Authorization/roleAssignments",
+ "apiVersion": "2022-04-01",
+ "name": "[guid(parameters('principalId'), variables('roleDefinitionIds')[copyIndex()], resourceGroup().name)]",
+ "properties": {
+ "roleDefinitionId": "[resourceId('Microsoft.Authorization/roleDefinitions', variables('roleDefinitionIds')[copyIndex()])]",
+ "principalId": "[parameters('principalId')]",
+ "principalType": "ServicePrincipal"
+ }
+ }
+ ]
+ }
+ },
+ "dependsOn": [
+ "[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('subscriptionId'), parameters('resourceGroupName')), 'Microsoft.Resources/deployments', format('user-assigned-identity-{0}', parameters('deploymentNameSuffix')))]"
+ ]
+ },
+ {
+ "type": "Microsoft.Resources/deployments",
+ "apiVersion": "2022-09-01",
+ "name": "[format('role-assignment-storage-{0}', parameters('deploymentNameSuffix'))]",
+ "subscriptionId": "[parameters('subscriptionId')]",
+ "resourceGroup": "[split(parameters('storageAccountResourceId'), '/')[4]]",
+ "properties": {
+ "expressionEvaluationOptions": {
+ "scope": "inner"
+ },
+ "mode": "Incremental",
+ "parameters": {
+ "principalId": {
+ "value": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('subscriptionId'), parameters('resourceGroupName')), 'Microsoft.Resources/deployments', format('user-assigned-identity-{0}', parameters('deploymentNameSuffix'))), '2022-09-01').outputs.principalId.value]"
+ },
+ "storageAccountResourceId": {
+ "value": "[parameters('storageAccountResourceId')]"
+ }
+ },
+ "template": {
+ "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
+ "contentVersion": "1.0.0.0",
+ "metadata": {
+ "_generator": {
+ "name": "bicep",
+ "version": "0.24.24.22086",
+ "templateHash": "1100663954772220507"
+ }
+ },
+ "parameters": {
+ "principalId": {
+ "type": "string"
+ },
+ "storageAccountResourceId": {
+ "type": "string"
+ }
+ },
+ "variables": {
+ "roleDefinitionId": "2a2b9908-6ea1-4ae2-8e65-a410df84e7d1"
+ },
+ "resources": [
+ {
+ "type": "Microsoft.Authorization/roleAssignments",
+ "apiVersion": "2022-04-01",
+ "scope": "[format('Microsoft.Storage/storageAccounts/{0}', split(parameters('storageAccountResourceId'), '/')[8])]",
+ "name": "[guid(parameters('principalId'), variables('roleDefinitionId'), parameters('storageAccountResourceId'))]",
+ "properties": {
+ "roleDefinitionId": "[resourceId('Microsoft.Authorization/roleDefinitions', variables('roleDefinitionId'))]",
+ "principalId": "[parameters('principalId')]",
+ "principalType": "ServicePrincipal"
+ }
+ }
+ ]
+ }
+ },
+ "dependsOn": [
+ "[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('subscriptionId'), parameters('resourceGroupName')), 'Microsoft.Resources/deployments', format('user-assigned-identity-{0}', parameters('deploymentNameSuffix')))]"
+ ]
+ },
+ {
+ "type": "Microsoft.Resources/deployments",
+ "apiVersion": "2022-09-01",
+ "name": "[format('disk-encryption-set-{0}', parameters('deploymentNameSuffix'))]",
+ "subscriptionId": "[split(parameters('diskEncryptionSetResourceId'), '/')[2]]",
+ "resourceGroup": "[split(parameters('diskEncryptionSetResourceId'), '/')[4]]",
+ "properties": {
+ "expressionEvaluationOptions": {
+ "scope": "inner"
+ },
+ "mode": "Incremental",
+ "parameters": {
+ "diskEncryptionSetName": {
+ "value": "[split(parameters('diskEncryptionSetResourceId'), '/')[8]]"
+ },
+ "principalId": {
+ "value": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('subscriptionId'), parameters('resourceGroupName')), 'Microsoft.Resources/deployments', format('user-assigned-identity-{0}', parameters('deploymentNameSuffix'))), '2022-09-01').outputs.principalId.value]"
+ }
+ },
+ "template": {
+ "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
+ "contentVersion": "1.0.0.0",
+ "metadata": {
+ "_generator": {
+ "name": "bicep",
+ "version": "0.24.24.22086",
+ "templateHash": "8640629756451087690"
+ }
+ },
+ "parameters": {
+ "diskEncryptionSetName": {
+ "type": "string"
+ },
+ "principalId": {
+ "type": "string"
+ }
+ },
+ "variables": {
+ "roleDefinitionId": "acdd72a7-3385-48ef-bd42-f606fba81ae7"
+ },
+ "resources": [
+ {
+ "type": "Microsoft.Authorization/roleAssignments",
+ "apiVersion": "2022-04-01",
+ "scope": "[format('Microsoft.Compute/diskEncryptionSets/{0}', parameters('diskEncryptionSetName'))]",
+ "name": "[guid(parameters('principalId'), variables('roleDefinitionId'), resourceId('Microsoft.Compute/diskEncryptionSets', parameters('diskEncryptionSetName')))]",
+ "properties": {
+ "roleDefinitionId": "[resourceId('Microsoft.Authorization/roleDefinitions', variables('roleDefinitionId'))]",
+ "principalId": "[parameters('principalId')]",
+ "principalType": "ServicePrincipal"
+ }
+ }
+ ]
+ }
+ },
+ "dependsOn": [
+ "[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('subscriptionId'), parameters('resourceGroupName')), 'Microsoft.Resources/deployments', format('user-assigned-identity-{0}', parameters('deploymentNameSuffix')))]"
+ ]
+ },
+ {
+ "type": "Microsoft.Resources/deployments",
+ "apiVersion": "2022-09-01",
+ "name": "[format('gallery-image-{0}', parameters('deploymentNameSuffix'))]",
+ "subscriptionId": "[parameters('subscriptionId')]",
+ "resourceGroup": "[parameters('resourceGroupName')]",
+ "properties": {
+ "expressionEvaluationOptions": {
+ "scope": "inner"
+ },
+ "mode": "Incremental",
+ "parameters": {
+ "enableBuildAutomation": {
+ "value": "[parameters('enableBuildAutomation')]"
+ },
+ "location": {
+ "value": "[parameters('location')]"
+ },
+ "computeGalleryName": {
+ "value": "[parameters('computeGalleryName')]"
+ },
+ "tags": {
+ "value": "[parameters('tags')]"
+ },
+ "userAssignedIdentityPrincipalId": {
+ "value": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('subscriptionId'), parameters('resourceGroupName')), 'Microsoft.Resources/deployments', format('user-assigned-identity-{0}', parameters('deploymentNameSuffix'))), '2022-09-01').outputs.principalId.value]"
+ }
+ },
+ "template": {
+ "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
+ "contentVersion": "1.0.0.0",
+ "metadata": {
+ "_generator": {
+ "name": "bicep",
+ "version": "0.24.24.22086",
+ "templateHash": "3726474265381754008"
+ }
+ },
+ "parameters": {
+ "computeGalleryName": {
+ "type": "string"
+ },
+ "enableBuildAutomation": {
+ "type": "bool"
+ },
+ "location": {
+ "type": "string"
+ },
+ "tags": {
+ "type": "object"
+ },
+ "userAssignedIdentityPrincipalId": {
+ "type": "string"
+ }
+ },
+ "variables": {
+ "roleDefinitionId": "b24988ac-6180-42a0-ab88-20f7382dd24c"
+ },
+ "resources": [
+ {
+ "type": "Microsoft.Compute/galleries",
+ "apiVersion": "2022-01-03",
+ "name": "[parameters('computeGalleryName')]",
+ "location": "[parameters('location')]",
+ "tags": "[if(contains(parameters('tags'), 'Microsoft.Compute/galleries'), parameters('tags')['Microsoft.Compute/galleries'], createObject())]"
+ },
+ {
+ "condition": "[parameters('enableBuildAutomation')]",
+ "type": "Microsoft.Authorization/roleAssignments",
+ "apiVersion": "2022-04-01",
+ "scope": "[format('Microsoft.Compute/galleries/{0}', parameters('computeGalleryName'))]",
+ "name": "[guid(parameters('userAssignedIdentityPrincipalId'), variables('roleDefinitionId'), resourceId('Microsoft.Compute/galleries', parameters('computeGalleryName')))]",
+ "properties": {
+ "roleDefinitionId": "[resourceId('Microsoft.Authorization/roleDefinitions', variables('roleDefinitionId'))]",
+ "principalId": "[parameters('userAssignedIdentityPrincipalId')]",
+ "principalType": "ServicePrincipal"
+ },
+ "dependsOn": [
+ "[resourceId('Microsoft.Compute/galleries', parameters('computeGalleryName'))]"
+ ]
+ }
+ ],
+ "outputs": {
+ "computeGalleryResourceId": {
+ "type": "string",
+ "value": "[resourceId('Microsoft.Compute/galleries', parameters('computeGalleryName'))]"
+ }
+ }
+ }
+ },
+ "dependsOn": [
+ "[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('subscriptionId'), parameters('resourceGroupName')), 'Microsoft.Resources/deployments', format('user-assigned-identity-{0}', parameters('deploymentNameSuffix')))]"
+ ]
+ },
+ {
+ "copy": {
+ "name": "policyExemptions",
+ "count": "[length(range(0, length(parameters('exemptPolicyAssignmentIds'))))]"
+ },
+ "condition": "[not(empty(parameters('exemptPolicyAssignmentIds')[0]))]",
+ "type": "Microsoft.Resources/deployments",
+ "apiVersion": "2022-09-01",
+ "name": "[format('PolicyExemption_{0}', range(0, length(parameters('exemptPolicyAssignmentIds')))[copyIndex()])]",
+ "subscriptionId": "[parameters('subscriptionId')]",
+ "resourceGroup": "[parameters('resourceGroupName')]",
+ "properties": {
+ "expressionEvaluationOptions": {
+ "scope": "inner"
+ },
+ "mode": "Incremental",
+ "parameters": {
+ "policyAssignmentId": {
+ "value": "[parameters('exemptPolicyAssignmentIds')[range(0, length(parameters('exemptPolicyAssignmentIds')))[copyIndex()]]]"
+ }
+ },
+ "template": {
+ "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
+ "contentVersion": "1.0.0.0",
+ "metadata": {
+ "_generator": {
+ "name": "bicep",
+ "version": "0.24.24.22086",
+ "templateHash": "6436250754327901801"
+ }
+ },
+ "parameters": {
+ "policyAssignmentId": {
+ "type": "string"
+ }
+ },
+ "resources": [
+ {
+ "type": "Microsoft.Authorization/policyExemptions",
+ "apiVersion": "2022-07-01-preview",
+ "name": "exempt-imaging-resource-group",
+ "properties": {
+ "assignmentScopeValidation": "Default",
+ "description": "Exempts the imaging resource group to prevent issues with building images.",
+ "displayName": "Imaging resource group",
+ "exemptionCategory": "Mitigated",
+ "expiresOn": null,
+ "metadata": null,
+ "policyAssignmentId": "[parameters('policyAssignmentId')]",
+ "policyDefinitionReferenceIds": [],
+ "resourceSelectors": []
+ }
+ }
+ ]
+ }
+ }
+ }
+ ],
+ "outputs": {
+ "computeGalleryResourceId": {
+ "type": "string",
+ "value": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('subscriptionId'), parameters('resourceGroupName')), 'Microsoft.Resources/deployments', format('gallery-image-{0}', parameters('deploymentNameSuffix'))), '2022-09-01').outputs.computeGalleryResourceId.value]"
+ },
+ "userAssignedIdentityClientId": {
+ "type": "string",
+ "value": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('subscriptionId'), parameters('resourceGroupName')), 'Microsoft.Resources/deployments', format('user-assigned-identity-{0}', parameters('deploymentNameSuffix'))), '2022-09-01').outputs.clientId.value]"
+ },
+ "userAssignedIdentityPrincipalId": {
+ "type": "string",
+ "value": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('subscriptionId'), parameters('resourceGroupName')), 'Microsoft.Resources/deployments', format('user-assigned-identity-{0}', parameters('deploymentNameSuffix'))), '2022-09-01').outputs.principalId.value]"
+ },
+ "userAssignedIdentityResourceId": {
+ "type": "string",
+ "value": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('subscriptionId'), parameters('resourceGroupName')), 'Microsoft.Resources/deployments', format('user-assigned-identity-{0}', parameters('deploymentNameSuffix'))), '2022-09-01').outputs.resourceId.value]"
+ }
+ }
+ }
+ },
+ "dependsOn": [
+ "[subscriptionResourceId('Microsoft.Resources/resourceGroups', parameters('resourceGroupName'))]",
+ "[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', variables('subscriptionId'), if(parameters('existingResourceGroup'), parameters('resourceGroupName'), parameters('resourceGroupName'))), 'Microsoft.Resources/deployments', format('tier3-{0}', parameters('deploymentNameSuffix')))]"
+ ]
+ },
+ {
+ "condition": "[parameters('enableBuildAutomation')]",
+ "type": "Microsoft.Resources/deployments",
+ "apiVersion": "2022-09-01",
+ "name": "[format('build-automation-{0}', parameters('deploymentNameSuffix'))]",
+ "location": "[deployment().location]",
+ "properties": {
+ "expressionEvaluationOptions": {
+ "scope": "inner"
+ },
+ "mode": "Incremental",
+ "parameters": {
+ "actionGroupName": {
+ "value": "[parameters('actionGroupName')]"
+ },
+ "arcGisProInstaller": {
+ "value": "[parameters('arcGisProInstaller')]"
+ },
+ "automationAccountName": {
+ "value": "[parameters('automationAccountName')]"
+ },
+ "automationAccountPrivateDnsZoneResourceId": {
+ "value": "[parameters('automationAccountPrivateDnsZoneResourceId')]"
+ },
+ "computeGalleryImageResourceId": {
+ "value": "[parameters('computeGalleryImageResourceId')]"
+ },
+ "computeGalleryResourceId": {
+ "value": "[reference(subscriptionResourceId('Microsoft.Resources/deployments', format('baseline-{0}', parameters('deploymentNameSuffix'))), '2022-09-01').outputs.computeGalleryResourceId.value]"
+ },
+ "containerName": {
+ "value": "[parameters('containerName')]"
+ },
+ "customizations": {
+ "value": "[parameters('customizations')]"
+ },
+ "deploymentNameSuffix": {
+ "value": "[parameters('deploymentNameSuffix')]"
+ },
+ "diskEncryptionSetResourceId": {
+ "value": "[parameters('diskEncryptionSetResourceId')]"
+ },
+ "distributionGroup": {
+ "value": "[parameters('distributionGroup')]"
+ },
+ "domainJoinPassword": {
+ "value": "[parameters('domainJoinPassword')]"
+ },
+ "domainJoinUserPrincipalName": {
+ "value": "[parameters('domainJoinUserPrincipalName')]"
+ },
+ "domainName": {
+ "value": "[parameters('domainName')]"
+ },
+ "enableBuildAutomation": {
+ "value": "[parameters('enableBuildAutomation')]"
+ },
+ "excludeFromLatest": {
+ "value": "[parameters('excludeFromLatest')]"
+ },
+ "hybridUseBenefit": {
+ "value": "[parameters('hybridUseBenefit')]"
+ },
+ "imageDefinitionName": {
+ "value": "[variables('imageDefinitionName')]"
+ },
+ "imageMajorVersion": {
+ "value": "[parameters('imageMajorVersion')]"
+ },
+ "imageMinorVersion": {
+ "value": "[parameters('imageMinorVersion')]"
+ },
+ "imageVirtualMachineName": {
+ "value": "[variables('imageVirtualMachineName')]"
+ },
+ "installAccess": {
+ "value": "[parameters('installAccess')]"
+ },
+ "installArcGisPro": {
+ "value": "[parameters('installArcGisPro')]"
+ },
+ "installExcel": {
+ "value": "[parameters('installExcel')]"
+ },
+ "installOneDrive": {
+ "value": "[parameters('installOneDrive')]"
+ },
+ "installOneNote": {
+ "value": "[parameters('installOneNote')]"
+ },
+ "installOutlook": {
+ "value": "[parameters('installOutlook')]"
+ },
+ "installPowerPoint": {
+ "value": "[parameters('installPowerPoint')]"
+ },
+ "installProject": {
+ "value": "[parameters('installProject')]"
+ },
+ "installPublisher": {
+ "value": "[parameters('installPublisher')]"
+ },
+ "installSkypeForBusiness": {
+ "value": "[parameters('installSkypeForBusiness')]"
+ },
+ "installTeams": {
+ "value": "[parameters('installTeams')]"
+ },
+ "installVirtualDesktopOptimizationTool": {
+ "value": "[parameters('installVirtualDesktopOptimizationTool')]"
+ },
+ "installVisio": {
+ "value": "[parameters('installVisio')]"
+ },
+ "installWord": {
+ "value": "[parameters('installWord')]"
+ },
+ "keyVaultName": {
+ "value": "[parameters('keyVaultName')]"
+ },
+ "keyVaultPrivateDnsZoneResourceId": {
+ "value": "[parameters('keyVaultPrivateDnsZoneResourceId')]"
+ },
+ "localAdministratorPassword": {
+ "value": "[parameters('localAdministratorPassword')]"
+ },
+ "localAdministratorUsername": {
+ "value": "[parameters('localAdministratorUsername')]"
+ },
+ "location": {
+ "value": "[parameters('location')]"
+ },
+ "logAnalyticsWorkspaceResourceId": {
+ "value": "[parameters('logAnalyticsWorkspaceResourceId')]"
+ },
+ "managementVirtualMachineName": {
+ "value": "[variables('managementVirtualMachineName')]"
+ },
+ "marketplaceImageOffer": {
+ "value": "[parameters('marketplaceImageOffer')]"
+ },
+ "marketplaceImagePublisher": {
+ "value": "[parameters('marketplaceImagePublisher')]"
+ },
+ "marketplaceImageSKU": {
+ "value": "[parameters('marketplaceImageSKU')]"
+ },
+ "msrdcwebrtcsvcInstaller": {
+ "value": "[parameters('msrdcwebrtcsvcInstaller')]"
+ },
+ "officeInstaller": {
+ "value": "[parameters('officeInstaller')]"
+ },
+ "oUPath": {
+ "value": "[parameters('oUPath')]"
+ },
+ "replicaCount": {
+ "value": "[parameters('replicaCount')]"
+ },
+ "resourceGroupName": "[if(parameters('existingResourceGroup'), createObject('value', parameters('resourceGroupName')), createObject('value', parameters('resourceGroupName')))]",
+ "sourceImageType": {
+ "value": "[parameters('sourceImageType')]"
+ },
+ "storageAccountResourceId": {
+ "value": "[parameters('storageAccountResourceId')]"
+ },
+ "subnetResourceId": {
+ "value": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', variables('subscriptionId'), if(parameters('existingResourceGroup'), parameters('resourceGroupName'), parameters('resourceGroupName'))), 'Microsoft.Resources/deployments', format('tier3-{0}', parameters('deploymentNameSuffix'))), '2022-09-01').outputs.subnetResourceId.value]"
+ },
+ "subscriptionId": {
+ "value": "[variables('subscriptionId')]"
+ },
+ "tags": {
+ "value": "[parameters('tags')]"
+ },
+ "teamsInstaller": {
+ "value": "[parameters('teamsInstaller')]"
+ },
+ "timeZone": {
+ "value": "[variables('timeZones')[parameters('location')]]"
+ },
+ "userAssignedIdentityClientId": {
+ "value": "[reference(subscriptionResourceId('Microsoft.Resources/deployments', format('baseline-{0}', parameters('deploymentNameSuffix'))), '2022-09-01').outputs.userAssignedIdentityClientId.value]"
+ },
+ "userAssignedIdentityPrincipalId": {
+ "value": "[reference(subscriptionResourceId('Microsoft.Resources/deployments', format('baseline-{0}', parameters('deploymentNameSuffix'))), '2022-09-01').outputs.userAssignedIdentityPrincipalId.value]"
+ },
+ "userAssignedIdentityResourceId": {
+ "value": "[reference(subscriptionResourceId('Microsoft.Resources/deployments', format('baseline-{0}', parameters('deploymentNameSuffix'))), '2022-09-01').outputs.userAssignedIdentityResourceId.value]"
+ },
+ "vcRedistInstaller": {
+ "value": "[parameters('vcRedistInstaller')]"
+ },
+ "vDOTInstaller": {
+ "value": "[parameters('vDOTInstaller')]"
+ },
+ "virtualMachineSize": {
+ "value": "[parameters('virtualMachineSize')]"
+ }
+ },
+ "template": {
+ "$schema": "https://schema.management.azure.com/schemas/2018-05-01/subscriptionDeploymentTemplate.json#",
+ "contentVersion": "1.0.0.0",
+ "metadata": {
+ "_generator": {
+ "name": "bicep",
+ "version": "0.24.24.22086",
+ "templateHash": "11475024915445016861"
+ }
+ },
+ "parameters": {
+ "actionGroupName": {
+ "type": "string"
+ },
+ "arcGisProInstaller": {
+ "type": "string"
+ },
+ "automationAccountName": {
+ "type": "string"
+ },
+ "automationAccountPrivateDnsZoneResourceId": {
+ "type": "string"
+ },
+ "computeGalleryResourceId": {
+ "type": "string"
+ },
+ "containerName": {
+ "type": "string"
+ },
+ "customizations": {
+ "type": "array"
+ },
+ "deploymentNameSuffix": {
+ "type": "string"
+ },
+ "diskEncryptionSetResourceId": {
+ "type": "string"
+ },
+ "distributionGroup": {
+ "type": "string"
+ },
+ "domainJoinPassword": {
+ "type": "securestring"
+ },
+ "domainJoinUserPrincipalName": {
+ "type": "string"
+ },
+ "domainName": {
+ "type": "string"
+ },
+ "enableBuildAutomation": {
+ "type": "bool"
+ },
+ "excludeFromLatest": {
+ "type": "bool"
+ },
+ "hybridUseBenefit": {
+ "type": "bool"
+ },
+ "imageDefinitionName": {
+ "type": "string"
+ },
+ "imageMajorVersion": {
+ "type": "int"
+ },
+ "imageMinorVersion": {
+ "type": "int"
+ },
+ "imageVirtualMachineName": {
+ "type": "string"
+ },
+ "installAccess": {
+ "type": "bool"
+ },
+ "installArcGisPro": {
+ "type": "bool"
+ },
+ "installExcel": {
+ "type": "bool"
+ },
+ "installOneDrive": {
+ "type": "bool"
+ },
+ "installOneNote": {
+ "type": "bool"
+ },
+ "installOutlook": {
+ "type": "bool"
+ },
+ "installPowerPoint": {
+ "type": "bool"
+ },
+ "installProject": {
+ "type": "bool"
+ },
+ "installPublisher": {
+ "type": "bool"
+ },
+ "installSkypeForBusiness": {
+ "type": "bool"
+ },
+ "installTeams": {
+ "type": "bool"
+ },
+ "installVirtualDesktopOptimizationTool": {
+ "type": "bool"
+ },
+ "installVisio": {
+ "type": "bool"
+ },
+ "installWord": {
+ "type": "bool"
+ },
+ "keyVaultName": {
+ "type": "string"
+ },
+ "keyVaultPrivateDnsZoneResourceId": {
+ "type": "string"
+ },
+ "localAdministratorPassword": {
+ "type": "securestring"
+ },
+ "localAdministratorUsername": {
+ "type": "string"
+ },
+ "location": {
+ "type": "string"
+ },
+ "logAnalyticsWorkspaceResourceId": {
+ "type": "string"
+ },
+ "managementVirtualMachineName": {
+ "type": "string"
+ },
+ "marketplaceImageOffer": {
+ "type": "string"
+ },
+ "marketplaceImagePublisher": {
+ "type": "string"
+ },
+ "marketplaceImageSKU": {
+ "type": "string"
+ },
+ "msrdcwebrtcsvcInstaller": {
+ "type": "string"
+ },
+ "officeInstaller": {
+ "type": "string"
+ },
+ "oUPath": {
+ "type": "string"
+ },
+ "replicaCount": {
+ "type": "int"
+ },
+ "resourceGroupName": {
+ "type": "string"
+ },
+ "computeGalleryImageResourceId": {
+ "type": "string"
+ },
+ "sourceImageType": {
+ "type": "string"
+ },
+ "storageAccountResourceId": {
+ "type": "string"
+ },
+ "subnetResourceId": {
+ "type": "string"
+ },
+ "subscriptionId": {
+ "type": "string"
+ },
+ "tags": {
+ "type": "object"
+ },
+ "teamsInstaller": {
+ "type": "string"
+ },
+ "timeZone": {
+ "type": "string"
+ },
+ "userAssignedIdentityClientId": {
+ "type": "string"
+ },
+ "userAssignedIdentityPrincipalId": {
+ "type": "string"
+ },
+ "userAssignedIdentityResourceId": {
+ "type": "string"
+ },
+ "vcRedistInstaller": {
+ "type": "string"
+ },
+ "vDOTInstaller": {
+ "type": "string"
+ },
+ "virtualMachineSize": {
+ "type": "string"
+ }
+ },
+ "resources": [
+ {
+ "type": "Microsoft.Authorization/roleDefinitions",
+ "apiVersion": "2022-04-01",
+ "name": "[guid(subscription().id, 'KeyVaultDeployAction')]",
+ "properties": {
+ "roleName": "[format('KeyVaultDeployAction_{0}', subscription().subscriptionId)]",
+ "description": "Allows a principal to get but not view Key Vault secrets for ARM template deployments.",
+ "assignableScopes": [
+ "[subscription().id]"
+ ],
+ "permissions": [
+ {
+ "actions": [
+ "Microsoft.KeyVault/vaults/deploy/action"
+ ]
+ }
+ ]
+ }
+ },
+ {
+ "type": "Microsoft.Resources/deployments",
+ "apiVersion": "2022-09-01",
+ "name": "[format('virtual-network-{0}', parameters('deploymentNameSuffix'))]",
+ "subscriptionId": "[split(parameters('subnetResourceId'), '/')[2]]",
+ "resourceGroup": "[split(parameters('subnetResourceId'), '/')[4]]",
+ "properties": {
+ "expressionEvaluationOptions": {
+ "scope": "inner"
+ },
+ "mode": "Incremental",
+ "parameters": {
+ "principalId": {
+ "value": "[parameters('userAssignedIdentityPrincipalId')]"
+ },
+ "virtualNetworkName": {
+ "value": "[split(parameters('subnetResourceId'), '/')[8]]"
+ }
+ },
+ "template": {
+ "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
+ "contentVersion": "1.0.0.0",
+ "metadata": {
+ "_generator": {
+ "name": "bicep",
+ "version": "0.24.24.22086",
+ "templateHash": "8258243830055263714"
+ }
+ },
+ "parameters": {
+ "principalId": {
+ "type": "string"
+ },
+ "virtualNetworkName": {
+ "type": "string"
+ }
+ },
+ "variables": {
+ "roleDefinitionId": "9980e02c-c2be-4d73-94e8-173b1dc7cf3c"
+ },
+ "resources": [
+ {
+ "type": "Microsoft.Authorization/roleAssignments",
+ "apiVersion": "2022-04-01",
+ "scope": "[format('Microsoft.Network/virtualNetworks/{0}', parameters('virtualNetworkName'))]",
+ "name": "[guid(parameters('principalId'), variables('roleDefinitionId'), resourceId('Microsoft.Network/virtualNetworks', parameters('virtualNetworkName')))]",
+ "properties": {
+ "roleDefinitionId": "[resourceId('Microsoft.Authorization/roleDefinitions', variables('roleDefinitionId'))]",
+ "principalId": "[parameters('principalId')]",
+ "principalType": "ServicePrincipal"
+ }
+ }
+ ]
+ }
+ }
+ },
+ {
+ "type": "Microsoft.Resources/deployments",
+ "apiVersion": "2022-09-01",
+ "name": "[format('key-vault-{0}', parameters('deploymentNameSuffix'))]",
+ "subscriptionId": "[parameters('subscriptionId')]",
+ "resourceGroup": "[parameters('resourceGroupName')]",
+ "properties": {
+ "expressionEvaluationOptions": {
+ "scope": "inner"
+ },
+ "mode": "Incremental",
+ "parameters": {
+ "domainJoinPassword": {
+ "value": "[parameters('domainJoinPassword')]"
+ },
+ "domainJoinUserPrincipalName": {
+ "value": "[parameters('domainJoinUserPrincipalName')]"
+ },
+ "keyVaultName": {
+ "value": "[parameters('keyVaultName')]"
+ },
+ "keyVaultPrivateDnsZoneResourceId": {
+ "value": "[parameters('keyVaultPrivateDnsZoneResourceId')]"
+ },
+ "localAdministratorPassword": {
+ "value": "[parameters('localAdministratorPassword')]"
+ },
+ "localAdministratorUsername": {
+ "value": "[parameters('localAdministratorUsername')]"
+ },
+ "location": {
+ "value": "[parameters('location')]"
+ },
+ "roleDefinitionResourceId": {
+ "value": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', guid(subscription().id, 'KeyVaultDeployAction'))]"
+ },
+ "subnetResourceId": {
+ "value": "[parameters('subnetResourceId')]"
+ },
+ "tags": {
+ "value": "[parameters('tags')]"
+ },
+ "userAssignedIdentityPrincipalId": {
+ "value": "[parameters('userAssignedIdentityPrincipalId')]"
+ }
+ },
+ "template": {
+ "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
+ "contentVersion": "1.0.0.0",
+ "metadata": {
+ "_generator": {
+ "name": "bicep",
+ "version": "0.24.24.22086",
+ "templateHash": "10229391374220360401"
+ }
+ },
+ "parameters": {
+ "domainJoinPassword": {
+ "type": "securestring"
+ },
+ "domainJoinUserPrincipalName": {
+ "type": "securestring"
+ },
+ "keyVaultName": {
+ "type": "string"
+ },
+ "keyVaultPrivateDnsZoneResourceId": {
+ "type": "string"
+ },
+ "location": {
+ "type": "string"
+ },
+ "localAdministratorPassword": {
+ "type": "securestring"
+ },
+ "localAdministratorUsername": {
+ "type": "securestring"
+ },
+ "roleDefinitionResourceId": {
+ "type": "string"
+ },
+ "subnetResourceId": {
+ "type": "string"
+ },
+ "tags": {
+ "type": "object"
+ },
+ "userAssignedIdentityPrincipalId": {
+ "type": "string"
+ }
+ },
+ "variables": {
+ "privateEndpointName": "[format('pe-{0}', parameters('keyVaultName'))]",
+ "Secrets": [
+ {
+ "name": "DomainJoinPassword",
+ "value": "[parameters('domainJoinPassword')]"
+ },
+ {
+ "name": "DomainJoinUserPrincipalName",
+ "value": "[parameters('domainJoinUserPrincipalName')]"
+ },
+ {
+ "name": "LocalAdministratorPassword",
+ "value": "[parameters('localAdministratorPassword')]"
+ },
+ {
+ "name": "LocalAdministratorUsername",
+ "value": "[parameters('localAdministratorUsername')]"
+ }
+ ]
+ },
+ "resources": [
+ {
+ "type": "Microsoft.KeyVault/vaults",
+ "apiVersion": "2021-10-01",
+ "name": "[parameters('keyVaultName')]",
+ "location": "[parameters('location')]",
+ "tags": "[if(contains(parameters('tags'), 'Microsoft.KeyVault/vaults'), parameters('tags')['Microsoft.KeyVault/vaults'], createObject())]",
+ "properties": {
+ "tenantId": "[subscription().tenantId]",
+ "sku": {
+ "family": "A",
+ "name": "standard"
+ },
+ "enabledForDeployment": true,
+ "enabledForTemplateDeployment": true,
+ "enabledForDiskEncryption": false,
+ "enableRbacAuthorization": true,
+ "enableSoftDelete": false,
+ "networkAcls": {
+ "bypass": "AzureServices",
+ "defaultAction": "Deny",
+ "ipRules": [],
+ "virtualNetworkRules": []
+ },
+ "publicNetworkAccess": "Disabled"
+ }
+ },
+ {
+ "type": "Microsoft.Network/privateEndpoints",
+ "apiVersion": "2023-05-01",
+ "name": "[variables('privateEndpointName')]",
+ "location": "[parameters('location')]",
+ "tags": "[if(contains(parameters('tags'), 'Microsoft.Network/privateEndpoints'), parameters('tags')['Microsoft.Network/privateEndpoints'], createObject())]",
+ "properties": {
+ "privateLinkServiceConnections": [
+ {
+ "name": "[variables('privateEndpointName')]",
+ "id": "[resourceId('Microsoft.Network/privateEndpoints/privateLinkServiceConnections', variables('privateEndpointName'), variables('privateEndpointName'))]",
+ "properties": {
+ "privateLinkServiceId": "[resourceId('Microsoft.KeyVault/vaults', parameters('keyVaultName'))]",
+ "groupIds": [
+ "vault"
+ ]
+ }
+ }
+ ],
+ "customNetworkInterfaceName": "[format('nic-{0}', parameters('keyVaultName'))]",
+ "subnet": {
+ "id": "[parameters('subnetResourceId')]"
+ }
+ },
+ "dependsOn": [
+ "[resourceId('Microsoft.KeyVault/vaults', parameters('keyVaultName'))]"
+ ]
+ },
+ {
+ "type": "Microsoft.Network/privateEndpoints/privateDnsZoneGroups",
+ "apiVersion": "2023-05-01",
+ "name": "[format('{0}/{1}', variables('privateEndpointName'), 'default')]",
+ "properties": {
+ "privateDnsZoneConfigs": [
+ {
+ "name": "privatelink-azure-automation-net",
+ "properties": {
+ "privateDnsZoneId": "[parameters('keyVaultPrivateDnsZoneResourceId')]"
+ }
+ }
+ ]
+ },
+ "dependsOn": [
+ "[resourceId('Microsoft.Network/privateEndpoints', variables('privateEndpointName'))]"
+ ]
+ },
+ {
+ "copy": {
+ "name": "secrets",
+ "count": "[length(variables('Secrets'))]"
+ },
+ "type": "Microsoft.KeyVault/vaults/secrets",
+ "apiVersion": "2021-10-01",
+ "name": "[format('{0}/{1}', parameters('keyVaultName'), variables('Secrets')[copyIndex()].name)]",
+ "tags": "[if(contains(parameters('tags'), 'Microsoft.KeyVault/vaults'), parameters('tags')['Microsoft.KeyVault/vaults'], createObject())]",
+ "properties": {
+ "value": "[variables('Secrets')[copyIndex()].value]"
+ },
+ "dependsOn": [
+ "[resourceId('Microsoft.KeyVault/vaults', parameters('keyVaultName'))]"
+ ]
+ },
+ {
+ "type": "Microsoft.Authorization/roleAssignments",
+ "apiVersion": "2020-10-01-preview",
+ "scope": "[format('Microsoft.KeyVault/vaults/{0}', parameters('keyVaultName'))]",
+ "name": "[guid(parameters('userAssignedIdentityPrincipalId'), parameters('roleDefinitionResourceId'), resourceGroup().id)]",
+ "properties": {
+ "roleDefinitionId": "[parameters('roleDefinitionResourceId')]",
+ "principalId": "[parameters('userAssignedIdentityPrincipalId')]",
+ "principalType": "ServicePrincipal"
+ },
+ "dependsOn": [
+ "[resourceId('Microsoft.KeyVault/vaults', parameters('keyVaultName'))]"
+ ]
+ }
+ ],
+ "outputs": {
+ "resourceId": {
+ "type": "string",
+ "value": "[resourceId('Microsoft.KeyVault/vaults', parameters('keyVaultName'))]"
+ }
+ }
+ }
+ },
+ "dependsOn": [
+ "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', guid(subscription().id, 'KeyVaultDeployAction'))]"
+ ]
+ },
+ {
+ "type": "Microsoft.Resources/deployments",
+ "apiVersion": "2022-09-01",
+ "name": "[format('template-spec-{0}', parameters('deploymentNameSuffix'))]",
+ "subscriptionId": "[parameters('subscriptionId')]",
+ "resourceGroup": "[parameters('resourceGroupName')]",
+ "properties": {
+ "expressionEvaluationOptions": {
+ "scope": "inner"
+ },
+ "mode": "Incremental",
+ "parameters": {
+ "imageDefinitionName": {
+ "value": "[parameters('imageDefinitionName')]"
+ },
+ "location": {
+ "value": "[parameters('location')]"
+ },
+ "tags": {
+ "value": "[parameters('tags')]"
+ }
+ },
+ "template": {
+ "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
+ "contentVersion": "1.0.0.0",
+ "metadata": {
+ "_generator": {
+ "name": "bicep",
+ "version": "0.24.24.22086",
+ "templateHash": "11416852755834315904"
+ }
+ },
+ "parameters": {
+ "imageDefinitionName": {
+ "type": "string"
+ },
+ "location": {
+ "type": "string"
+ },
+ "tags": {
+ "type": "object"
+ }
+ },
+ "variables": {
+ "$fxv#0": {
+ "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
+ "contentVersion": "1.0.0.0",
+ "metadata": {
+ "_generator": {
+ "name": "bicep",
+ "version": "0.24.24.22086",
+ "templateHash": "6609998574317511230"
+ }
+ },
+ "parameters": {
+ "arcGisProInstaller": {
+ "type": "string",
+ "defaultValue": ""
+ },
+ "computeGalleryImageResourceId": {
+ "type": "string",
+ "defaultValue": ""
+ },
+ "computeGalleryName": {
+ "type": "string"
+ },
+ "containerName": {
+ "type": "string"
+ },
+ "customizations": {
+ "type": "array",
+ "defaultValue": []
+ },
+ "deploymentNameSuffix": {
+ "type": "string",
+ "defaultValue": "[[utcNow('yyMMddHHs')]"
+ },
+ "diskEncryptionSetResourceId": {
+ "type": "string"
+ },
+ "enableBuildAutomation": {
+ "type": "bool",
+ "defaultValue": false
+ },
+ "excludeFromLatest": {
+ "type": "bool",
+ "defaultValue": true
+ },
+ "hybridUseBenefit": {
+ "type": "bool",
+ "defaultValue": false
+ },
+ "imageDefinitionName": {
+ "type": "string"
+ },
+ "imageMajorVersion": {
+ "type": "int"
+ },
+ "imageMinorVersion": {
+ "type": "int"
+ },
+ "imageVirtualMachineName": {
+ "type": "string"
+ },
+ "installAccess": {
+ "type": "bool",
+ "defaultValue": false
+ },
+ "installArcGisPro": {
+ "type": "bool",
+ "defaultValue": false
+ },
+ "installExcel": {
+ "type": "bool",
+ "defaultValue": false
+ },
+ "installOneDrive": {
+ "type": "bool",
+ "defaultValue": false
+ },
+ "installOneNote": {
+ "type": "bool",
+ "defaultValue": false
+ },
+ "installOutlook": {
+ "type": "bool",
+ "defaultValue": false
+ },
+ "installPowerPoint": {
+ "type": "bool",
+ "defaultValue": false
+ },
+ "installProject": {
+ "type": "bool",
+ "defaultValue": false
+ },
+ "installPublisher": {
+ "type": "bool",
+ "defaultValue": false
+ },
+ "installSkypeForBusiness": {
+ "type": "bool",
+ "defaultValue": false
+ },
+ "installTeams": {
+ "type": "bool",
+ "defaultValue": false
+ },
+ "installVirtualDesktopOptimizationTool": {
+ "type": "bool",
+ "defaultValue": false
+ },
+ "installVisio": {
+ "type": "bool",
+ "defaultValue": false
+ },
+ "installWord": {
+ "type": "bool",
+ "defaultValue": false
+ },
+ "keyVaultName": {
+ "type": "string"
+ },
+ "localAdministratorPassword": {
+ "type": "securestring",
+ "defaultValue": ""
+ },
+ "localAdministratorUsername": {
+ "type": "securestring",
+ "defaultValue": ""
+ },
+ "location": {
+ "type": "string",
+ "defaultValue": "[[resourceGroup().location]"
+ },
+ "managementVirtualMachineName": {
+ "type": "string"
+ },
+ "marketplaceImageOffer": {
+ "type": "string"
+ },
+ "marketplaceImagePublisher": {
+ "type": "string"
+ },
+ "marketplaceImageSKU": {
+ "type": "string"
+ },
+ "msrdcwebrtcsvcInstaller": {
+ "type": "string",
+ "defaultValue": ""
+ },
+ "officeInstaller": {
+ "type": "string",
+ "defaultValue": ""
+ },
+ "replicaCount": {
+ "type": "int",
+ "defaultValue": 1
+ },
+ "runbookExecution": {
+ "type": "bool",
+ "defaultValue": false
+ },
+ "sourceImageType": {
+ "type": "string",
+ "defaultValue": "AzureMarketplace"
+ },
+ "storageAccountResourceId": {
+ "type": "string"
+ },
+ "subnetResourceId": {
+ "type": "string"
+ },
+ "tags": {
+ "type": "object",
+ "defaultValue": {}
+ },
+ "teamsInstaller": {
+ "type": "string",
+ "defaultValue": ""
+ },
+ "userAssignedIdentityClientId": {
+ "type": "string"
+ },
+ "userAssignedIdentityPrincipalId": {
+ "type": "string"
+ },
+ "userAssignedIdentityResourceId": {
+ "type": "string"
+ },
+ "vcRedistInstaller": {
+ "type": "string",
+ "defaultValue": ""
+ },
+ "vDOTInstaller": {
+ "type": "string",
+ "defaultValue": ""
+ },
+ "virtualMachineSize": {
+ "type": "string"
+ }
+ },
+ "variables": {
+ "autoImageVersion": "[[format('{0}.{1}.{2}', parameters('imageMajorVersion'), variables('imageSuffix'), parameters('imageMinorVersion'))]",
+ "imageSuffix": "[[take(parameters('deploymentNameSuffix'), 9)]",
+ "resourceGroupName": "[[resourceGroup().name]",
+ "storageAccountName": "[[split(parameters('storageAccountResourceId'), '/')[8]]",
+ "storageEndpoint": "[[environment().suffixes.storage]",
+ "subscriptionId": "[[subscription().subscriptionId]"
+ },
+ "resources": [
+ {
+ "condition": "[[not(parameters('enableBuildAutomation'))]",
+ "type": "Microsoft.Resources/deployments",
+ "apiVersion": "2022-09-01",
+ "name": "[[format('management-vm-{0}', parameters('deploymentNameSuffix'))]",
+ "subscriptionId": "[[variables('subscriptionId')]",
+ "resourceGroup": "[[variables('resourceGroupName')]",
+ "properties": {
+ "expressionEvaluationOptions": {
+ "scope": "inner"
+ },
+ "mode": "Incremental",
+ "parameters": {
+ "containerName": {
+ "value": "[[parameters('containerName')]"
+ },
+ "diskEncryptionSetResourceId": {
+ "value": "[[parameters('diskEncryptionSetResourceId')]"
+ },
+ "hybridUseBenefit": {
+ "value": "[[parameters('hybridUseBenefit')]"
+ },
+ "localAdministratorPassword": {
+ "value": "[[parameters('localAdministratorPassword')]"
+ },
+ "localAdministratorUsername": {
+ "value": "[[parameters('localAdministratorUsername')]"
+ },
+ "location": {
+ "value": "[[parameters('location')]"
+ },
+ "storageAccountName": {
+ "value": "[[split(parameters('storageAccountResourceId'), '/')[8]]"
+ },
+ "subnetResourceId": {
+ "value": "[[parameters('subnetResourceId')]"
+ },
+ "tags": {
+ "value": "[[parameters('tags')]"
+ },
+ "userAssignedIdentityPrincipalId": {
+ "value": "[[parameters('userAssignedIdentityPrincipalId')]"
+ },
+ "userAssignedIdentityResourceId": {
+ "value": "[[parameters('userAssignedIdentityResourceId')]"
+ },
+ "virtualMachineName": {
+ "value": "[[parameters('managementVirtualMachineName')]"
+ }
+ },
+ "template": {
+ "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
+ "contentVersion": "1.0.0.0",
+ "metadata": {
+ "_generator": {
+ "name": "bicep",
+ "version": "0.24.24.22086",
+ "templateHash": "5351463014152522794"
+ }
+ },
+ "parameters": {
+ "containerName": {
+ "type": "string"
+ },
+ "diskEncryptionSetResourceId": {
+ "type": "string"
+ },
+ "hybridUseBenefit": {
+ "type": "bool"
+ },
+ "localAdministratorPassword": {
+ "type": "securestring"
+ },
+ "localAdministratorUsername": {
+ "type": "securestring"
+ },
+ "location": {
+ "type": "string"
+ },
+ "storageAccountName": {
+ "type": "string"
+ },
+ "subnetResourceId": {
+ "type": "string"
+ },
+ "tags": {
+ "type": "object"
+ },
+ "userAssignedIdentityPrincipalId": {
+ "type": "string"
+ },
+ "userAssignedIdentityResourceId": {
+ "type": "string"
+ },
+ "virtualMachineName": {
+ "type": "string"
+ }
+ },
+ "resources": [
+ {
+ "type": "Microsoft.Network/networkInterfaces",
+ "apiVersion": "2023-04-01",
+ "name": "[[format('nic-{0}', parameters('virtualMachineName'))]",
+ "location": "[[parameters('location')]",
+ "tags": "[[if(contains(parameters('tags'), 'Microsoft.Network/networkInterfaces'), parameters('tags')['Microsoft.Network/networkInterfaces'], createObject())]",
+ "properties": {
+ "ipConfigurations": [
+ {
+ "name": "ipconfig",
+ "properties": {
+ "privateIPAllocationMethod": "Dynamic",
+ "subnet": {
+ "id": "[[parameters('subnetResourceId')]"
+ },
+ "primary": true,
+ "privateIPAddressVersion": "IPv4"
+ }
+ }
+ ],
+ "enableAcceleratedNetworking": true,
+ "enableIPForwarding": false
+ }
+ },
+ {
+ "type": "Microsoft.Compute/virtualMachines",
+ "apiVersion": "2022-03-01",
+ "name": "[[parameters('virtualMachineName')]",
+ "location": "[[parameters('location')]",
+ "tags": "[[if(contains(parameters('tags'), 'Microsoft.Compute/virtualMachines'), parameters('tags')['Microsoft.Compute/virtualMachines'], createObject())]",
+ "identity": {
+ "type": "UserAssigned",
+ "userAssignedIdentities": {
+ "[[format('{0}', parameters('userAssignedIdentityResourceId'))]": {}
+ }
+ },
+ "properties": {
+ "hardwareProfile": {
+ "vmSize": "Standard_D2s_v3"
+ },
+ "osProfile": {
+ "computerName": "[[parameters('virtualMachineName')]",
+ "adminUsername": "[[parameters('localAdministratorUsername')]",
+ "adminPassword": "[[parameters('localAdministratorPassword')]",
+ "windowsConfiguration": {
+ "provisionVMAgent": true,
+ "enableAutomaticUpdates": true,
+ "patchSettings": {
+ "patchMode": "AutomaticByOS",
+ "assessmentMode": "ImageDefault"
+ }
+ }
+ },
+ "storageProfile": {
+ "imageReference": {
+ "publisher": "MicrosoftWindowsServer",
+ "offer": "WindowsServer",
+ "sku": "2019-datacenter-core-g2",
+ "version": "latest"
+ },
+ "osDisk": {
+ "caching": "ReadWrite",
+ "createOption": "FromImage",
+ "deleteOption": "Delete",
+ "managedDisk": {
+ "diskEncryptionSet": {
+ "id": "[[parameters('diskEncryptionSetResourceId')]"
+ },
+ "storageAccountType": "Premium_LRS"
+ },
+ "name": "[[format('disk-{0}', parameters('virtualMachineName'))]",
+ "osType": "Windows"
+ }
+ },
+ "networkProfile": {
+ "networkInterfaces": [
+ {
+ "id": "[[resourceId('Microsoft.Network/networkInterfaces', format('nic-{0}', parameters('virtualMachineName')))]",
+ "properties": {
+ "deleteOption": "Delete"
+ }
+ }
+ ]
+ },
+ "diagnosticsProfile": {
+ "bootDiagnostics": {
+ "enabled": false
+ }
+ },
+ "securityProfile": {
+ "encryptionAtHost": true,
+ "uefiSettings": {
+ "secureBootEnabled": true,
+ "vTpmEnabled": true
+ },
+ "securityType": "TrustedLaunch"
+ },
+ "licenseType": "[[if(parameters('hybridUseBenefit'), 'Windows_Server', null())]"
+ },
+ "dependsOn": [
+ "[[resourceId('Microsoft.Network/networkInterfaces', format('nic-{0}', parameters('virtualMachineName')))]"
+ ]
+ },
+ {
+ "type": "Microsoft.Compute/virtualMachines/runCommands",
+ "apiVersion": "2023-03-01",
+ "name": "[[format('{0}/{1}', parameters('virtualMachineName'), 'appAzModules')]",
+ "location": "[[parameters('location')]",
+ "tags": "[[if(contains(parameters('tags'), 'Microsoft.Compute/virtualMachines'), parameters('tags')['Microsoft.Compute/virtualMachines'], createObject())]",
+ "properties": {
+ "treatFailureAsDeploymentFailure": true,
+ "asyncExecution": false,
+ "parameters": [
+ {
+ "name": "ContainerName",
+ "value": "[[parameters('containerName')]"
+ },
+ {
+ "name": "StorageAccountName",
+ "value": "[[parameters('storageAccountName')]"
+ },
+ {
+ "name": "StorageEndpoint",
+ "value": "[[environment().suffixes.storage]"
+ },
+ {
+ "name": "UserAssignedIdentityObjectId",
+ "value": "[[parameters('userAssignedIdentityPrincipalId')]"
+ }
+ ],
+ "source": {
+ "script": " param(\r\n [string]$ContainerName,\r\n [string]$StorageAccountName,\r\n [string]$StorageEndpoint,\r\n [string]$UserAssignedIdentityObjectId\r\n )\r\n $ErrorActionPreference = \"Stop\"\r\n $StorageAccountUrl = \"https://\" + $StorageAccountName + \".blob.\" + $StorageEndpoint + \"/\"\r\n $TokenUri = \"http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=$StorageAccountUrl&object_id=$UserAssignedIdentityObjectId\"\r\n $AccessToken = ((Invoke-WebRequest -Headers @{Metadata=$true} -Uri $TokenUri -UseBasicParsing).Content | ConvertFrom-Json).access_token\r\n $BlobNames = @('az.accounts.2.12.1.nupkg','az.automation.1.9.0.nupkg','az.compute.5.7.0.nupkg','az.resources.6.6.0.nupkg')\r\n foreach($BlobName in $BlobNames)\r\n {\r\n do\r\n {\r\n try\r\n {\r\n Write-Output \"Download Attempt $i\"\r\n Invoke-WebRequest -Headers @{\"x-ms-version\"=\"2017-11-09\"; Authorization =\"Bearer $AccessToken\"} -Uri \"$StorageAccountUrl$ContainerName/$BlobName\" -OutFile \"$env:windir\\temp\\$BlobName\"\r\n }\r\n catch [System.Net.WebException]\r\n {\r\n Start-Sleep -Seconds 60\r\n $i++\r\n if($i -gt 10){throw}\r\n continue\r\n }\r\n catch\r\n {\r\n $Output = $_ | select *\r\n Write-Output $Output\r\n throw\r\n }\r\n }\r\n until(Test-Path -Path $env:windir\\temp\\$BlobName)\r\n Start-Sleep -Seconds 5\r\n Unblock-File -Path $env:windir\\temp\\$BlobName\r\n $BlobZipName = $Blobname.Replace('nupkg','zip')\r\n Rename-Item -Path $env:windir\\temp\\$BlobName -NewName $BlobZipName\r\n $BlobNameArray = $BlobName.Split('.')\r\n $ModuleFolderName = $BlobNameArray[0] + '.' + $BlobNameArray[1]\r\n $VersionFolderName = $BlobNameArray[2] + '.' + $BlobNameArray[3]+ '.' + $BlobNameArray[4]\r\n $ModulesDirectory = \"C:\\Program Files\\WindowsPowerShell\\Modules\"\r\n New-Item -Path $ModulesDirectory -Name $ModuleFolderName -ItemType \"Directory\" -Force\r\n Expand-Archive -Path $env:windir\\temp\\$BlobZipName -DestinationPath \"$ModulesDirectory\\$ModuleFolderName\\$VersionFolderName\" -Force\r\n Remove-Item -Path \"$ModulesDirectory\\$ModuleFolderName\\$VersionFolderName\\_rels\" -Force -Recurse\r\n Remove-Item -Path \"$ModulesDirectory\\$ModuleFolderName\\$VersionFolderName\\package\" -Force -Recurse\r\n Remove-Item -LiteralPath \"$ModulesDirectory\\$ModuleFolderName\\$VersionFolderName\\[Content_Types].xml\" -Force\r\n Remove-Item -Path \"$ModulesDirectory\\$ModuleFolderName\\$VersionFolderName\\$ModuleFolderName.nuspec\" -Force\r\n }\r\n Remove-Item -Path \"$env:windir\\temp\\az*\" -Force\r\n "
+ }
+ },
+ "dependsOn": [
+ "[[resourceId('Microsoft.Compute/virtualMachines', parameters('virtualMachineName'))]"
+ ]
+ }
+ ],
+ "outputs": {
+ "name": {
+ "type": "string",
+ "value": "[[parameters('virtualMachineName')]"
+ }
+ }
+ }
+ }
+ },
+ {
+ "type": "Microsoft.Resources/deployments",
+ "apiVersion": "2022-09-01",
+ "name": "[[format('image-vm-{0}', parameters('deploymentNameSuffix'))]",
+ "properties": {
+ "expressionEvaluationOptions": {
+ "scope": "inner"
+ },
+ "mode": "Incremental",
+ "parameters": {
+ "diskEncryptionSetResourceId": {
+ "value": "[[parameters('diskEncryptionSetResourceId')]"
+ },
+ "localAdministratorPassword": "[[if(parameters('runbookExecution'), createObject('reference', createObject('keyVault', createObject('id', resourceId('Microsoft.KeyVault/vaults', parameters('keyVaultName'))), 'secretName', 'LocalAdministratorPassword')), createObject('value', parameters('localAdministratorPassword')))]",
+ "localAdministratorUsername": "[[if(parameters('runbookExecution'), createObject('reference', createObject('keyVault', createObject('id', resourceId('Microsoft.KeyVault/vaults', parameters('keyVaultName'))), 'secretName', 'LocalAdministratorUsername')), createObject('value', parameters('localAdministratorUsername')))]",
+ "location": {
+ "value": "[[parameters('location')]"
+ },
+ "marketplaceImageOffer": {
+ "value": "[[parameters('marketplaceImageOffer')]"
+ },
+ "marketplaceImagePublisher": {
+ "value": "[[parameters('marketplaceImagePublisher')]"
+ },
+ "marketplaceImageSKU": {
+ "value": "[[parameters('marketplaceImageSKU')]"
+ },
+ "computeGalleryImageResourceId": {
+ "value": "[[parameters('computeGalleryImageResourceId')]"
+ },
+ "sourceImageType": {
+ "value": "[[parameters('sourceImageType')]"
+ },
+ "subnetResourceId": {
+ "value": "[[parameters('subnetResourceId')]"
+ },
+ "tags": {
+ "value": "[[parameters('tags')]"
+ },
+ "userAssignedIdentityResourceId": {
+ "value": "[[parameters('userAssignedIdentityResourceId')]"
+ },
+ "virtualMachineName": {
+ "value": "[[parameters('imageVirtualMachineName')]"
+ },
+ "virtualMachineSize": {
+ "value": "[[parameters('virtualMachineSize')]"
+ }
+ },
+ "template": {
+ "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
+ "contentVersion": "1.0.0.0",
+ "metadata": {
+ "_generator": {
+ "name": "bicep",
+ "version": "0.24.24.22086",
+ "templateHash": "666417518081719909"
+ }
+ },
+ "parameters": {
+ "diskEncryptionSetResourceId": {
+ "type": "string"
+ },
+ "localAdministratorPassword": {
+ "type": "securestring"
+ },
+ "localAdministratorUsername": {
+ "type": "securestring"
+ },
+ "location": {
+ "type": "string"
+ },
+ "marketplaceImageOffer": {
+ "type": "string"
+ },
+ "marketplaceImagePublisher": {
+ "type": "string"
+ },
+ "marketplaceImageSKU": {
+ "type": "string"
+ },
+ "computeGalleryImageResourceId": {
+ "type": "string"
+ },
+ "sourceImageType": {
+ "type": "string"
+ },
+ "subnetResourceId": {
+ "type": "string"
+ },
+ "tags": {
+ "type": "object"
+ },
+ "userAssignedIdentityResourceId": {
+ "type": "string"
+ },
+ "virtualMachineName": {
+ "type": "string"
+ },
+ "virtualMachineSize": {
+ "type": "string"
+ }
+ },
+ "variables": {
+ "imageReference": "[[if(equals(parameters('sourceImageType'), 'AzureComputeGallery'), createObject('id', parameters('computeGalleryImageResourceId')), createObject('publisher', parameters('marketplaceImagePublisher'), 'offer', parameters('marketplaceImageOffer'), 'sku', parameters('marketplaceImageSKU'), 'version', 'latest'))]"
+ },
+ "resources": [
+ {
+ "type": "Microsoft.Network/networkInterfaces",
+ "apiVersion": "2022-05-01",
+ "name": "[[format('nic-{0}', parameters('virtualMachineName'))]",
+ "location": "[[parameters('location')]",
+ "tags": "[[if(contains(parameters('tags'), 'Microsoft.Network/networkInterfaces'), parameters('tags')['Microsoft.Network/networkInterfaces'], createObject())]",
+ "properties": {
+ "ipConfigurations": [
+ {
+ "name": "ipconfig1",
+ "properties": {
+ "privateIPAllocationMethod": "Dynamic",
+ "subnet": {
+ "id": "[[parameters('subnetResourceId')]"
+ }
+ }
+ }
+ ]
+ }
+ },
+ {
+ "type": "Microsoft.Compute/virtualMachines",
+ "apiVersion": "2022-03-01",
+ "name": "[[parameters('virtualMachineName')]",
+ "location": "[[parameters('location')]",
+ "tags": "[[if(contains(parameters('tags'), 'Microsoft.Compute/virtualMachines'), parameters('tags')['Microsoft.Compute/virtualMachines'], createObject())]",
+ "identity": {
+ "type": "UserAssigned",
+ "userAssignedIdentities": {
+ "[[format('{0}', parameters('userAssignedIdentityResourceId'))]": {}
+ }
+ },
+ "properties": {
+ "hardwareProfile": {
+ "vmSize": "[[parameters('virtualMachineSize')]"
+ },
+ "osProfile": {
+ "computerName": "[[parameters('virtualMachineName')]",
+ "adminUsername": "[[parameters('localAdministratorUsername')]",
+ "adminPassword": "[[parameters('localAdministratorPassword')]"
+ },
+ "storageProfile": {
+ "imageReference": "[[variables('imageReference')]",
+ "osDisk": {
+ "createOption": "FromImage",
+ "deleteOption": "Delete",
+ "managedDisk": {
+ "storageAccountType": "StandardSSD_LRS"
+ },
+ "name": "[[format('disk-{0}', parameters('virtualMachineName'))]"
+ }
+ },
+ "networkProfile": {
+ "networkInterfaces": [
+ {
+ "id": "[[resourceId('Microsoft.Network/networkInterfaces', format('nic-{0}', parameters('virtualMachineName')))]",
+ "properties": {
+ "deleteOption": "Delete"
+ }
+ }
+ ]
+ },
+ "diagnosticsProfile": {
+ "bootDiagnostics": {
+ "enabled": false
+ }
+ },
+ "securityProfile": {
+ "uefiSettings": {
+ "secureBootEnabled": true,
+ "vTpmEnabled": true
+ },
+ "securityType": "TrustedLaunch"
+ }
+ },
+ "dependsOn": [
+ "[[resourceId('Microsoft.Network/networkInterfaces', format('nic-{0}', parameters('virtualMachineName')))]"
+ ]
+ }
+ ],
+ "outputs": {
+ "name": {
+ "type": "string",
+ "value": "[[parameters('virtualMachineName')]"
+ },
+ "resourceId": {
+ "type": "string",
+ "value": "[[resourceId('Microsoft.Compute/virtualMachines', parameters('virtualMachineName'))]"
+ }
+ }
+ }
+ }
+ },
+ {
+ "type": "Microsoft.Resources/deployments",
+ "apiVersion": "2022-09-01",
+ "name": "[[format('customizations-{0}', parameters('deploymentNameSuffix'))]",
+ "properties": {
+ "expressionEvaluationOptions": {
+ "scope": "inner"
+ },
+ "mode": "Incremental",
+ "parameters": {
+ "arcGisProInstaller": {
+ "value": "[[parameters('arcGisProInstaller')]"
+ },
+ "containerName": {
+ "value": "[[parameters('containerName')]"
+ },
+ "customizations": {
+ "value": "[[parameters('customizations')]"
+ },
+ "installAccess": {
+ "value": "[[parameters('installAccess')]"
+ },
+ "installArcGisPro": {
+ "value": "[[parameters('installArcGisPro')]"
+ },
+ "installExcel": {
+ "value": "[[parameters('installExcel')]"
+ },
+ "installOneDrive": {
+ "value": "[[parameters('installOneDrive')]"
+ },
+ "installOneNote": {
+ "value": "[[parameters('installOneNote')]"
+ },
+ "installOutlook": {
+ "value": "[[parameters('installOutlook')]"
+ },
+ "installPowerPoint": {
+ "value": "[[parameters('installPowerPoint')]"
+ },
+ "installProject": {
+ "value": "[[parameters('installProject')]"
+ },
+ "installPublisher": {
+ "value": "[[parameters('installPublisher')]"
+ },
+ "installSkypeForBusiness": {
+ "value": "[[parameters('installSkypeForBusiness')]"
+ },
+ "installTeams": {
+ "value": "[[parameters('installTeams')]"
+ },
+ "installVirtualDesktopOptimizationTool": {
+ "value": "[[parameters('installVirtualDesktopOptimizationTool')]"
+ },
+ "installVisio": {
+ "value": "[[parameters('installVisio')]"
+ },
+ "installWord": {
+ "value": "[[parameters('installWord')]"
+ },
+ "location": {
+ "value": "[[parameters('location')]"
+ },
+ "msrdcwebrtcsvcInstaller": {
+ "value": "[[parameters('msrdcwebrtcsvcInstaller')]"
+ },
+ "officeInstaller": {
+ "value": "[[parameters('officeInstaller')]"
+ },
+ "storageAccountName": {
+ "value": "[[variables('storageAccountName')]"
+ },
+ "storageEndpoint": {
+ "value": "[[variables('storageEndpoint')]"
+ },
+ "tags": {
+ "value": "[[parameters('tags')]"
+ },
+ "teamsInstaller": {
+ "value": "[[parameters('teamsInstaller')]"
+ },
+ "userAssignedIdentityObjectId": {
+ "value": "[[parameters('userAssignedIdentityPrincipalId')]"
+ },
+ "vcRedistInstaller": {
+ "value": "[[parameters('vcRedistInstaller')]"
+ },
+ "vDotInstaller": {
+ "value": "[[parameters('vDOTInstaller')]"
+ },
+ "virtualMachineName": {
+ "value": "[[reference(resourceId('Microsoft.Resources/deployments', format('image-vm-{0}', parameters('deploymentNameSuffix'))), '2022-09-01').outputs.name.value]"
+ }
+ },
+ "template": {
+ "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
+ "contentVersion": "1.0.0.0",
+ "metadata": {
+ "_generator": {
+ "name": "bicep",
+ "version": "0.24.24.22086",
+ "templateHash": "12702244124956355874"
+ }
+ },
+ "parameters": {
+ "arcGisProInstaller": {
+ "type": "string"
+ },
+ "containerName": {
+ "type": "string"
+ },
+ "customizations": {
+ "type": "array"
+ },
+ "installAccess": {
+ "type": "bool"
+ },
+ "installArcGisPro": {
+ "type": "bool"
+ },
+ "installExcel": {
+ "type": "bool"
+ },
+ "installOneDrive": {
+ "type": "bool"
+ },
+ "installOneNote": {
+ "type": "bool"
+ },
+ "installOutlook": {
+ "type": "bool"
+ },
+ "installPowerPoint": {
+ "type": "bool"
+ },
+ "installProject": {
+ "type": "bool"
+ },
+ "installPublisher": {
+ "type": "bool"
+ },
+ "installSkypeForBusiness": {
+ "type": "bool"
+ },
+ "installTeams": {
+ "type": "bool"
+ },
+ "installVirtualDesktopOptimizationTool": {
+ "type": "bool"
+ },
+ "installVisio": {
+ "type": "bool"
+ },
+ "installWord": {
+ "type": "bool"
+ },
+ "location": {
+ "type": "string"
+ },
+ "msrdcwebrtcsvcInstaller": {
+ "type": "string"
+ },
+ "officeInstaller": {
+ "type": "string"
+ },
+ "storageAccountName": {
+ "type": "string"
+ },
+ "storageEndpoint": {
+ "type": "string"
+ },
+ "tags": {
+ "type": "object"
+ },
+ "teamsInstaller": {
+ "type": "string"
+ },
+ "userAssignedIdentityObjectId": {
+ "type": "string"
+ },
+ "vcRedistInstaller": {
+ "type": "string"
+ },
+ "vDotInstaller": {
+ "type": "string"
+ },
+ "virtualMachineName": {
+ "type": "string"
+ }
+ },
+ "variables": {
+ "installAccessVar": "[[format('{0}installAccess', parameters('installAccess'))]",
+ "installers": "[[parameters('customizations')]",
+ "installExcelVar": "[[format('{0}installWord', parameters('installExcel'))]",
+ "installOneDriveVar": "[[format('{0}installOneDrive', parameters('installOneDrive'))]",
+ "installOneNoteVar": "[[format('{0}installOneNote', parameters('installOneNote'))]",
+ "installOutlookVar": "[[format('{0}installOutlook', parameters('installOutlook'))]",
+ "installPowerPointVar": "[[format('{0}installPowerPoint', parameters('installPowerPoint'))]",
+ "installProjectVar": "[[format('{0}installProject', parameters('installProject'))]",
+ "installPublisherVar": "[[format('{0}installPublisher', parameters('installPublisher'))]",
+ "installSkypeForBusinessVar": "[[format('{0}installSkypeForBusiness', parameters('installSkypeForBusiness'))]",
+ "installVisioVar": "[[format('{0}installVisio', parameters('installVisio'))]",
+ "installWordVar": "[[format('{0}installWord', parameters('installWord'))]"
+ },
+ "resources": [
+ {
+ "[string('copy')]": {
+ "name": "applications",
+ "count": "[[length(variables('installers'))]",
+ "mode": "serial",
+ "batchSize": 1
+ },
+ "type": "Microsoft.Compute/virtualMachines/runCommands",
+ "apiVersion": "2023-03-01",
+ "name": "[[format('{0}/{1}', parameters('virtualMachineName'), format('app-{0}', variables('installers')[copyIndex()].name))]",
+ "location": "[[parameters('location')]",
+ "tags": "[[if(contains(parameters('tags'), 'Microsoft.Compute/virtualMachines'), parameters('tags')['Microsoft.Compute/virtualMachines'], createObject())]",
+ "properties": {
+ "treatFailureAsDeploymentFailure": true,
+ "asyncExecution": false,
+ "parameters": [
+ {
+ "name": "UserAssignedIdentityObjectId",
+ "value": "[[parameters('userAssignedIdentityObjectId')]"
+ },
+ {
+ "name": "StorageAccountName",
+ "value": "[[parameters('storageAccountName')]"
+ },
+ {
+ "name": "ContainerName",
+ "value": "[[parameters('containerName')]"
+ },
+ {
+ "name": "StorageEndpoint",
+ "value": "[[parameters('storageEndpoint')]"
+ },
+ {
+ "name": "Blobname",
+ "value": "[[variables('installers')[copyIndex()].blobName]"
+ },
+ {
+ "name": "Installer",
+ "value": "[[variables('installers')[copyIndex()].name]"
+ },
+ {
+ "name": "Arguments",
+ "value": "[[variables('installers')[copyIndex()].arguments]"
+ }
+ ],
+ "source": {
+ "script": " param(\r\n [string]$UserAssignedIdentityObjectId,\r\n [string]$StorageAccountName,\r\n [string]$ContainerName,\r\n [string]$StorageEndpoint,\r\n [string]$BlobName,\r\n [string]$Installer,\r\n [string]$Arguments\r\n )\r\n $ErrorActionPreference = 'Stop'\r\n $WarningPreference = 'SilentlyContinue'\r\n $StorageAccountUrl = \"https://\" + $StorageAccountName + \".blob.\" + $StorageEndpoint + \"/\"\r\n $TokenUri = \"http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=$StorageAccountUrl&object_id=$UserAssignedIdentityObjectId\"\r\n $AccessToken = ((Invoke-WebRequest -Headers @{Metadata=$true} -Uri $TokenUri -UseBasicParsing).Content | ConvertFrom-Json).access_token\r\n New-Item -Path $env:windir\\temp -Name $Installer -ItemType \"directory\" -Force\r\n New-Item -Path $env:windir\\temp\\$Installer -Name 'Files' -ItemType \"directory\" -Force\r\n Invoke-WebRequest -Headers @{\"x-ms-version\"=\"2017-11-09\"; Authorization =\"Bearer $AccessToken\"} -Uri \"$StorageAccountUrl$ContainerName/$BlobName\" -OutFile $env:windir\\temp\\$Installer\\Files\\$Blobname\r\n Start-Sleep -Seconds 30\r\n Set-Location -Path $env:windir\\temp\\$Installer\r\n if($Blobname -like (\"*.exe\"))\r\n {\r\n Start-Process -FilePath $env:windir\\temp\\$Installer\\Files\\$Blobname -ArgumentList $Arguments -NoNewWindow -Wait -PassThru\r\n $status = Get-WmiObject -Class Win32_Product | Where-Object Name -like \"*$($installer)*\"\r\n if($status)\r\n {\r\n Write-Host $status.Name \"is installed\"\r\n }\r\n else\r\n {\r\n Write-host $Installer \"did not install properly, please check arguments\"\r\n }\r\n }\r\n if($Blobname -like (\"*.msi\"))\r\n {\r\n Set-Location -Path $env:windir\\temp\\$Installer\\Files\r\n Start-Process -FilePath msiexec.exe -ArgumentList $Arguments -Wait\r\n $status = Get-WmiObject -Class Win32_Product | Where-Object Name -like \"*$($installer)*\"\r\n if($status)\r\n {\r\n Write-Host $status.Name \"is installed\"\r\n }\r\n else\r\n {\r\n Write-host $Installer \"did not install properly, please check arguments\"\r\n }\r\n }\r\n if($Blobname -like (\"*.bat\"))\r\n {\r\n Start-Process -FilePath cmd.exe -ArgumentList $env:windir\\temp\\$Installer\\Files\\$Arguments -Wait\r\n }\r\n if($Blobname -like (\"*.ps1\"))\r\n {\r\n Start-Process -FilePath PowerShell.exe -ArgumentList $env:windir\\temp\\$Installer\\Files\\$Arguments -Wait\r\n }\r\n if($Blobname -like (\"*.zip\"))\r\n {\r\n Set-Location -Path $env:windir\\temp\\$Installer\\Files\r\n Expand-Archive -Path $env:windir\\temp\\$Installer\\Files\\$Blobname -DestinationPath $env:windir\\temp\\$Installer\\Files -Force\r\n Remove-Item -Path .\\$Blobname -Force -Recurse\r\n }\r\n Write-Host \"Removing $Installer Files\"\r\n Remove-item $env:windir\\temp\\$Installer -Force -Recurse -Confirm:$false\r\n "
+ }
+ }
+ },
+ {
+ "condition": "[[or(or(or(or(or(or(or(or(or(or(parameters('installAccess'), parameters('installExcel')), parameters('installOneDrive')), parameters('installOneNote')), parameters('installOutlook')), parameters('installPowerPoint')), parameters('installPublisher')), parameters('installSkypeForBusiness')), parameters('installWord')), parameters('installVisio')), parameters('installProject'))]",
+ "type": "Microsoft.Compute/virtualMachines/runCommands",
+ "apiVersion": "2023-03-01",
+ "name": "[[format('{0}/{1}', parameters('virtualMachineName'), 'office')]",
+ "location": "[[parameters('location')]",
+ "tags": "[[if(contains(parameters('tags'), 'Microsoft.Compute/virtualMachines'), parameters('tags')['Microsoft.Compute/virtualMachines'], createObject())]",
+ "properties": {
+ "treatFailureAsDeploymentFailure": true,
+ "asyncExecution": false,
+ "parameters": [
+ {
+ "name": "InstallAccess",
+ "value": "[[variables('installAccessVar')]"
+ },
+ {
+ "name": "InstallWord",
+ "value": "[[variables('installWordVar')]"
+ },
+ {
+ "name": "InstallExcel",
+ "value": "[[variables('installExcelVar')]"
+ },
+ {
+ "name": "InstallOneDrive",
+ "value": "[[variables('installOneDriveVar')]"
+ },
+ {
+ "name": "InstallOneNote",
+ "value": "[[variables('installOneNoteVar')]"
+ },
+ {
+ "name": "InstallOutlook",
+ "value": "[[variables('installOutlookVar')]"
+ },
+ {
+ "name": "InstallPowerPoint",
+ "value": "[[variables('installPowerPointVar')]"
+ },
+ {
+ "name": "InstallProject",
+ "value": "[[variables('installProjectVar')]"
+ },
+ {
+ "name": "InstallPublisher",
+ "value": "[[variables('installPublisherVar')]"
+ },
+ {
+ "name": "InstallSkypeForBusiness",
+ "value": "[[variables('installSkypeForBusinessVar')]"
+ },
+ {
+ "name": "InstallVisio",
+ "value": "[[variables('installVisioVar')]"
+ },
+ {
+ "name": "UserAssignedIdentityObjectId",
+ "value": "[[parameters('userAssignedIdentityObjectId')]"
+ },
+ {
+ "name": "StorageAccountName",
+ "value": "[[parameters('storageAccountName')]"
+ },
+ {
+ "name": "ContainerName",
+ "value": "[[parameters('containerName')]"
+ },
+ {
+ "name": "StorageEndpoint",
+ "value": "[[parameters('storageEndpoint')]"
+ },
+ {
+ "name": "BlobName",
+ "value": "[[parameters('officeInstaller')]"
+ }
+ ],
+ "source": {
+ "script": " param(\r\n [string]$InstallAccess,\r\n [string]$InstallExcel,\r\n [string]$InstallOneDrive,\r\n [string]$InstallOutlook,\r\n [string]$InstallProject,\r\n [string]$InstallPublisher,\r\n [string]$InstallSkypeForBusiness,\r\n [string]$InstallVisio,\r\n [string]$InstallWord,\r\n [string]$InstallOneNote,\r\n [string]$InstallPowerPoint,\r\n [string]$UserAssignedIdentityObjectId,\r\n [string]$StorageAccountName,\r\n [string]$ContainerName,\r\n [string]$StorageEndpoint,\r\n [string]$BlobName\r\n )\r\n $ErrorActionPreference = 'Stop'\r\n $WarningPreference = 'SilentlyContinue'\r\n $StorageAccountUrl = \"https://\" + $StorageAccountName + \".blob.\" + $StorageEndpoint + \"/\"\r\n $TokenUri = \"http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=$StorageAccountUrl&object_id=$UserAssignedIdentityObjectId\"\r\n $AccessToken = ((Invoke-WebRequest -Headers @{Metadata=$true} -Uri $TokenUri -UseBasicParsing).Content | ConvertFrom-Json).access_token\r\n New-Item -Path \"$env:windir\\temp\\office\" -ItemType \"directory\" -Force\r\n $sku = (Get-ComputerInfo).OsName\r\n $o365ConfigHeader = Set-Content \"$env:windir\\temp\\office\\office365x64.xml\" ''\r\n $o365OfficeHeader = Add-Content \"$env:windir\\temp\\office\\office365x64.xml\" ''\r\n if($InstallAccess -notlike '*true*'){\r\n Add-Content \"$env:windir\\temp\\office\\office365x64.xml\" ''\r\n }\r\n if($InstallExcel -notlike '*true*'){\r\n Add-Content \"$env:windir\\temp\\office\\office365x64.xml\" ''\r\n }\r\n if($InstallOneDrive -notlike '*true*'){\r\n Add-Content \"$env:windir\\temp\\office\\office365x64.xml\" ''\r\n }\r\n if($InstallOneNote -notlike '*true*'){\r\n Add-Content \"$env:windir\\temp\\office\\office365x64.xml\" ''\r\n }\r\n if($InstallOutlook -notlike '*true*'){\r\n Add-Content \"$env:windir\\temp\\office\\office365x64.xml\" ''\r\n }\r\n if($InstallPowerPoint -notlike '*true*'){\r\n Add-Content \"$env:windir\\temp\\office\\office365x64.xml\" ''\r\n }\r\n if($InstallPublisher -notlike '*true*'){\r\n Add-Content \"$env:windir\\temp\\office\\office365x64.xml\" ''\r\n }\r\n if($InstallSkypeForBusiness -notlike '*true*'){\r\n Add-Content \"$env:windir\\temp\\office\\office365x64.xml\" ''\r\n }\r\n if($InstallWord -notlike '*true*'){\r\n Add-Content \"$env:windir\\temp\\office\\office365x64.xml\" ''\r\n }\r\n $addOfficefooter = Add-Content \"$env:windir\\temp\\office\\office365x64.xml\" ''\r\n if($InstallProject -like '*true*'){\r\n Add-Content \"$env:windir\\temp\\office\\office365x64.xml\" ''\r\n }\r\n if($InstallVisio -like '*true*'){\r\n Add-Content \"$env:windir\\temp\\office\\office365x64.xml\" ''\r\n }\r\n Add-Content \"$env:windir\\temp\\office\\office365x64.xml\" ''\r\n $PerMachineConfiguration = if(($Sku).Contains(\"multi\") -eq \"true\"){\r\n Add-Content \"$env:windir\\temp\\office\\office365x64.xml\" ''\r\n }\r\n Add-Content \"$env:windir\\temp\\office\\office365x64.xml\" ''\r\n $Installer = \"$env:windir\\temp\\office\\office.exe\"\r\n #$DownloadLinks = Invoke-WebRequest -Uri \"https://www.microsoft.com/en-us/download/confirmation.aspx?id=49117\" -UseBasicParsing\r\n #$URL = $DownloadLinks.Links.href | Where-Object {$_ -like \"https://download.microsoft.com/download/*officedeploymenttool*\"} | Select-Object -First 1\r\n #Invoke-WebRequest -Uri $URL -OutFile $Installer -UseBasicParsing\r\n Invoke-WebRequest -Headers @{\"x-ms-version\"=\"2017-11-09\"; Authorization =\"Bearer $AccessToken\"} -Uri \"$StorageAccountUrl$ContainerName/$BlobName\" -OutFile $Installer\r\n Start-Process -FilePath $Installer -ArgumentList \"/extract:$env:windir\\temp\\office /quiet /passive /norestart\" -Wait -PassThru | Out-Null\r\n Write-Host \"Downloaded & extracted the Office 365 Deployment Toolkit\"\r\n Start-Process -FilePath \"$env:windir\\temp\\office\\setup.exe\" -ArgumentList \"/configure $env:windir\\temp\\office\\office365x64.xml\" -Wait -PassThru -ErrorAction \"Stop\" | Out-Null\r\n Write-Host \"Installed the selected Office365 applications\"\r\n Write-Host \"Removing Office FIles\"\r\n Remove-item -Path \"$env:windir\\temp\\office\" -Force -Confirm:$false -Recurse\r\n "
+ }
+ },
+ "dependsOn": [
+ "applications"
+ ]
+ },
+ {
+ "condition": "[[parameters('installVirtualDesktopOptimizationTool')]",
+ "type": "Microsoft.Compute/virtualMachines/runCommands",
+ "apiVersion": "2023-03-01",
+ "name": "[[format('{0}/{1}', parameters('virtualMachineName'), 'vdot')]",
+ "location": "[[parameters('location')]",
+ "tags": "[[if(contains(parameters('tags'), 'Microsoft.Compute/virtualMachines'), parameters('tags')['Microsoft.Compute/virtualMachines'], createObject())]",
+ "properties": {
+ "treatFailureAsDeploymentFailure": true,
+ "asyncExecution": false,
+ "parameters": [
+ {
+ "name": "UserAssignedIdentityObjectId",
+ "value": "[[parameters('userAssignedIdentityObjectId')]"
+ },
+ {
+ "name": "StorageAccountName",
+ "value": "[[parameters('storageAccountName')]"
+ },
+ {
+ "name": "ContainerName",
+ "value": "[[parameters('containerName')]"
+ },
+ {
+ "name": "StorageEndpoint",
+ "value": "[[parameters('storageEndpoint')]"
+ },
+ {
+ "name": "BlobName",
+ "value": "[[parameters('vDotInstaller')]"
+ }
+ ],
+ "source": {
+ "script": " param(\r\n [string]$UserAssignedIdentityObjectId,\r\n [string]$StorageAccountName,\r\n [string]$ContainerName,\r\n [string]$StorageEndpoint,\r\n [string]$BlobName\r\n )\r\n $ErrorActionPreference = 'Stop'\r\n $WarningPreference = 'SilentlyContinue'\r\n $StorageAccountUrl = \"https://\" + $StorageAccountName + \".blob.\" + $StorageEndpoint + \"/\"\r\n $TokenUri = \"http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=$StorageAccountUrl&object_id=$UserAssignedIdentityObjectId\"\r\n $AccessToken = ((Invoke-WebRequest -Headers @{Metadata=$true} -Uri $TokenUri -UseBasicParsing).Content | ConvertFrom-Json).access_token\r\n $ZIP = \"$env:windir\\temp\\VDOT.zip\"\r\n Invoke-WebRequest -Headers @{\"x-ms-version\"=\"2017-11-09\"; Authorization =\"Bearer $AccessToken\"} -Uri \"$StorageAccountUrl$ContainerName/$BlobName\" -OutFile $ZIP\r\n Start-Sleep -Seconds 30\r\n Set-Location -Path $env:windir\\temp\r\n Unblock-File -Path $ZIP\r\n Expand-Archive -LiteralPath $ZIP -DestinationPath \"$env:windir\\temp\" -Force\r\n $Path = (Get-ChildItem -Path \"$env:windir\\temp\" -Recurse | Where-Object {$_.Name -eq \"Windows_VDOT.ps1\"}).FullName\r\n $Script = Get-Content -Path $Path\r\n $ScriptUpdate = $Script.Replace(\"Set-NetAdapterAdvancedProperty\",\"#Set-NetAdapterAdvancedProperty\")\r\n $ScriptUpdate | Set-Content -Path $Path\r\n & $Path -Optimizations @(\"AppxPackages\",\"Autologgers\",\"DefaultUserSettings\",\"LGPO\";\"NetworkOptimizations\",\"ScheduledTasks\",\"Services\",\"WindowsMediaPlayer\") -AdvancedOptimizations \"All\" -AcceptEULA\r\n Write-Host \"Removing VDOT Files\"\r\n # Expecting this format for vDot ZIP, update if using a different ZIP format for folder structure\r\n Remove-Item -Path $env:windir\\temp\\Virtual-Desktop-Optimization-Tool-main -Force -Recurse -Confirm:$false\r\n "
+ },
+ "timeoutInSeconds": 640
+ },
+ "dependsOn": [
+ "applications",
+ "[[resourceId('Microsoft.Compute/virtualMachines/runCommands', parameters('virtualMachineName'), 'office')]",
+ "[[resourceId('Microsoft.Compute/virtualMachines/runCommands', parameters('virtualMachineName'), 'teams')]"
+ ]
+ },
+ {
+ "condition": "[[parameters('installTeams')]",
+ "type": "Microsoft.Compute/virtualMachines/runCommands",
+ "apiVersion": "2023-03-01",
+ "name": "[[format('{0}/{1}', parameters('virtualMachineName'), 'teams')]",
+ "location": "[[parameters('location')]",
+ "tags": "[[if(contains(parameters('tags'), 'Microsoft.Compute/virtualMachines'), parameters('tags')['Microsoft.Compute/virtualMachines'], createObject())]",
+ "properties": {
+ "treatFailureAsDeploymentFailure": true,
+ "asyncExecution": false,
+ "parameters": [
+ {
+ "name": "UserAssignedIdentityObjectId",
+ "value": "[[parameters('userAssignedIdentityObjectId')]"
+ },
+ {
+ "name": "StorageAccountName",
+ "value": "[[parameters('storageAccountName')]"
+ },
+ {
+ "name": "ContainerName",
+ "value": "[[parameters('containerName')]"
+ },
+ {
+ "name": "StorageEndpoint",
+ "value": "[[parameters('storageEndpoint')]"
+ },
+ {
+ "name": "BlobName",
+ "value": "[[parameters('teamsInstaller')]"
+ },
+ {
+ "name": "BlobName2",
+ "value": "[[parameters('vcRedistInstaller')]"
+ },
+ {
+ "name": "BlobName3",
+ "value": "[[parameters('msrdcwebrtcsvcInstaller')]"
+ }
+ ],
+ "source": {
+ "script": " param(\r\n [string]$UserAssignedIdentityObjectId,\r\n [string]$StorageAccountName,\r\n [string]$ContainerName,\r\n [string]$StorageEndpoint,\r\n [string]$BlobName,\r\n [string]$BlobName2,\r\n [string]$BlobName3\r\n )\r\n $ErrorActionPreference = 'Stop'\r\n $WarningPreference = 'SilentlyContinue'\r\n $StorageAccountUrl = \"https://\" + $StorageAccountName + \".blob.\" + $StorageEndpoint + \"/\"\r\n $TokenUri = \"http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=$StorageAccountUrl&object_id=$UserAssignedIdentityObjectId\"\r\n $AccessToken = ((Invoke-WebRequest -Headers @{Metadata=$true} -Uri $TokenUri -UseBasicParsing).Content | ConvertFrom-Json).access_token\r\n $vcRedistFile = \"$env:windir\\temp\\vc_redist.x64.exe\"\r\n $webSocketFile = \"$env:windir\\temp\\webSocketSvc.msi\"\r\n $teamsFile = \"$env:windir\\temp\\teams.msi\"\r\n Invoke-WebRequest -Headers @{\"x-ms-version\"=\"2017-11-09\"; Authorization =\"Bearer $AccessToken\"} -Uri \"$StorageAccountUrl$ContainerName/$BlobName\" -OutFile $teamsFile\r\n Invoke-WebRequest -Headers @{\"x-ms-version\"=\"2017-11-09\"; Authorization =\"Bearer $AccessToken\"} -Uri \"$StorageAccountUrl$ContainerName/$BlobName2\" -OutFile $vcRedistFile\r\n Invoke-WebRequest -Headers @{\"x-ms-version\"=\"2017-11-09\"; Authorization =\"Bearer $AccessToken\"} -Uri \"$StorageAccountUrl$ContainerName/$BlobName3\" -OutFile $webSocketFile\r\n\r\n # Enable media optimizations for Team\r\n Start-Process \"reg\" -ArgumentList \"add HKLM\\SOFTWARE\\Microsoft\\Teams /v IsWVDEnvironment /t REG_DWORD /d 1 /f\" -Wait -PassThru -ErrorAction \"Stop\"\r\n Write-Host \"Enabled media optimizations for Teams\"\r\n # Download & install the latest version of Microsoft Visual C++ Redistributable\r\n #$File = \"$env:windir\\temp\\vc_redist.x64.exe\"\r\n #Invoke-WebRequest -Uri \"https://aka.ms/vs/16/release/vc_redist.x64.exe\" -OutFile $File\r\n Start-Process -FilePath $vcRedistFile -Args \"/install /quiet /norestart /log vcdist.log\" -Wait -PassThru | Out-Null\r\n Write-Host \"Installed the latest version of Microsoft Visual C++ Redistributable\"\r\n # Download & install the Remote Desktop WebRTC Redirector Service\r\n #$File = \"$env:windir\\temp\\webSocketSvc.msi\"\r\n #Invoke-WebRequest -Uri \"https://aka.ms/msrdcwebrtcsvc/msi\" -OutFile $File\r\n Start-Process -FilePath msiexec.exe -Args \"/i $webSocketFile /quiet /qn /norestart /passive /log webSocket.log\" -Wait -PassThru | Out-Null\r\n Write-Host \"Installed the Remote Desktop WebRTC Redirector Service\"\r\n # Install Teams\r\n #$File = \"$env:windir\\temp\\teams.msi\"\r\n #Write-host $($TeamsUrl)\r\n #Invoke-WebRequest -Uri \"$TeamsUrl\" -OutFile $File\r\n $sku = (Get-ComputerInfo).OsName\r\n $PerMachineConfiguration = if(($Sku).Contains(\"multi\") -eq \"true\"){\"ALLUSER=1\"}else{\"\"}\r\n Start-Process -FilePath msiexec.exe -Args \"/i $teamsFile /quiet /qn /norestart /passive /log teams.log $PerMachineConfiguration ALLUSERS=1\" -Wait -PassThru | Out-Null\r\n Write-Host \"Installed Teams\"\r\n Write-Host \"Removing Teams Files\"\r\n Remove-Item \"$teamsFile\" -Force -Confirm:$false\r\n Remove-Item \"$vcRedistFile\" -Force -Confirm:$false\r\n Remove-Item \"$webSocketFile\" -Force -Confirm:$false\r\n "
+ }
+ },
+ "dependsOn": [
+ "applications",
+ "[[resourceId('Microsoft.Compute/virtualMachines/runCommands', parameters('virtualMachineName'), 'office')]"
+ ]
+ },
+ {
+ "condition": "[[parameters('installArcGisPro')]",
+ "type": "Microsoft.Compute/virtualMachines/runCommands",
+ "apiVersion": "2023-03-01",
+ "name": "[[format('{0}/{1}', parameters('virtualMachineName'), 'arcGisPro')]",
+ "location": "[[parameters('location')]",
+ "tags": "[[if(contains(parameters('tags'), 'Microsoft.Compute/virtualMachines'), parameters('tags')['Microsoft.Compute/virtualMachines'], createObject())]",
+ "properties": {
+ "treatFailureAsDeploymentFailure": true,
+ "asyncExecution": false,
+ "parameters": [
+ {
+ "name": "UserAssignedIdentityObjectId",
+ "value": "[[parameters('userAssignedIdentityObjectId')]"
+ },
+ {
+ "name": "StorageAccountName",
+ "value": "[[parameters('storageAccountName')]"
+ },
+ {
+ "name": "ContainerName",
+ "value": "[[parameters('containerName')]"
+ },
+ {
+ "name": "StorageEndpoint",
+ "value": "[[parameters('storageEndpoint')]"
+ },
+ {
+ "name": "BlobName",
+ "value": "[[parameters('arcGisProInstaller')]"
+ }
+ ],
+ "source": {
+ "script": " param(\r\n [string]$UserAssignedIdentityObjectId,\r\n [string]$StorageAccountName,\r\n [string]$ContainerName,\r\n [string]$StorageEndpoint,\r\n [string]$BlobName\r\n )\r\n $ErrorActionPreference = 'Stop'\r\n $WarningPreference = 'SilentlyContinue'\r\n $StorageAccountUrl = \"https://\" + $StorageAccountName + \".blob.\" + $StorageEndpoint + \"/\"\r\n $TokenUri = \"http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=$StorageAccountUrl&object_id=$UserAssignedIdentityObjectId\"\r\n $AccessToken = ((Invoke-WebRequest -Headers @{Metadata=$true} -Uri $TokenUri -UseBasicParsing).Content | ConvertFrom-Json).access_token\r\n # Retrieve Files\r\n New-Item -Path $env:windir\\temp -Name arcgis -ItemType \"directory\" -Force\r\n $ZIP = \"$env:windir\\temp\\arcgispro.zip\"\r\n Invoke-WebRequest -Headers @{\"x-ms-version\"=\"2017-11-09\"; Authorization =\"Bearer $AccessToken\"} -Uri \"$StorageAccountUrl$ContainerName/$BlobName\" -OutFile $ZIP\r\n Start-Sleep -Seconds 30\r\n Set-Location -Path $env:windir\\temp\r\n Unblock-File -Path $ZIP\r\n Expand-Archive -LiteralPath $ZIP -DestinationPath \"$env:windir\\temp\\arcgis\" -Force\r\n\r\n # Install Arcgis\r\n $arcGisProMsi = (Get-ChildItem \"$env:windir\\temp\\arcgis\\\" -Recurse | where {$_.Name -eq \"ArcGisPro.msi\"})\r\n $arcGisProMsp = (Get-ChildItem \"$env:windir\\temp\\arcgis\" -Recurse | where {$_.Extension -eq \".msp\"})\r\n $winDesktopRuntime = (Get-ChildItem \"$env:windir\\temp\\arcgis\\\" -Recurse | where {$_.Name -like \"windowsdesktop-runtime-*\"})\r\n\r\n # If found Install Windows Desktop Runtime Pre-Req\r\n try {\r\n if ($winDesktopRuntime ){\r\n Start-Process -FilePath \"$($winDesktopRuntime.Directory.FullName)\\$winDesktopRuntime\" -ArgumentList \"/install /quiet /norestart\" -Wait -NoNewWindow -PassThru\r\n }\r\n }\r\n catch {\r\n Write-Output \"Please validate all software requirements are included with the ArcGIS Pro Zip\"\r\n }\r\n\r\n try {\r\n # Install ArcGis Pro\r\n $arcGisProArguments = \"/i $($arcGisProMsi.Directory.FullName)\\$arcGisProMsi ALLUSERS=1 ACCEPTEULA=yes ENABLEEUEI=0 SOFTWARE_CLASS=Professional AUTHORIZATION_TYPE=NAMED_USER LOCK_AUTH_SETTINGS=False ArcGIS_Connection=TRUE /qn /norestart\"\r\n Start-Process \"msiexec.exe\" -ArgumentList $arcGisProArguments -Wait -NoNewWindow -PassThru\r\n }\r\n catch {\r\n Write-Output \"Please validate all software requirements are included with the ArcGIS Pro Zip\"\r\n }\r\n\r\n try {\r\n # If MSP is found, patch ArcGisPro with MSP file\r\n if($arcGisProMsp){\r\n Start-Process \"msiexec.exe\" -ArgumentList \"/p $($arcGisProMsp.Directory.FullName)\\$arcGisProMsp /qn\" -Wait -NoNewWindow -PassThru\r\n }\r\n }\r\n catch {\r\n Write-Output \"Please validate all software requirements are included with the ArcGIS Pro Zip\"\r\n }\r\n Write-Host \"Removing ArcGis Files\"\r\n Remove-Item $ZIP -Force -Confirm:$false -Recurse\r\n Remove-item -Path \"$env:windir\\temp\\arcgis\" -Force -Confirm:$false -Recurse\r\n "
+ }
+ },
+ "dependsOn": [
+ "applications",
+ "[[resourceId('Microsoft.Compute/virtualMachines/runCommands', parameters('virtualMachineName'), 'office')]",
+ "[[resourceId('Microsoft.Compute/virtualMachines/runCommands', parameters('virtualMachineName'), 'teams')]",
+ "[[resourceId('Microsoft.Compute/virtualMachines/runCommands', parameters('virtualMachineName'), 'vdot')]"
+ ]
+ }
+ ]
+ }
+ },
+ "dependsOn": [
+ "[[resourceId('Microsoft.Resources/deployments', format('image-vm-{0}', parameters('deploymentNameSuffix')))]"
+ ]
+ },
+ {
+ "type": "Microsoft.Resources/deployments",
+ "apiVersion": "2022-09-01",
+ "name": "[[format('restart-vm-{0}', parameters('deploymentNameSuffix'))]",
+ "properties": {
+ "expressionEvaluationOptions": {
+ "scope": "inner"
+ },
+ "mode": "Incremental",
+ "parameters": {
+ "imageVirtualMachineName": {
+ "value": "[[reference(resourceId('Microsoft.Resources/deployments', format('image-vm-{0}', parameters('deploymentNameSuffix'))), '2022-09-01').outputs.name.value]"
+ },
+ "resourceGroupName": {
+ "value": "[[variables('resourceGroupName')]"
+ },
+ "location": {
+ "value": "[[parameters('location')]"
+ },
+ "tags": {
+ "value": "[[parameters('tags')]"
+ },
+ "userAssignedIdentityClientId": {
+ "value": "[[parameters('userAssignedIdentityClientId')]"
+ },
+ "virtualMachineName": "[[if(parameters('enableBuildAutomation'), createObject('value', parameters('managementVirtualMachineName')), createObject('value', reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', variables('subscriptionId'), variables('resourceGroupName')), 'Microsoft.Resources/deployments', format('management-vm-{0}', parameters('deploymentNameSuffix'))), '2022-09-01').outputs.name.value))]"
+ },
+ "template": {
+ "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
+ "contentVersion": "1.0.0.0",
+ "metadata": {
+ "_generator": {
+ "name": "bicep",
+ "version": "0.24.24.22086",
+ "templateHash": "272404991735293049"
+ }
+ },
+ "parameters": {
+ "imageVirtualMachineName": {
+ "type": "string"
+ },
+ "resourceGroupName": {
+ "type": "string"
+ },
+ "location": {
+ "type": "string"
+ },
+ "tags": {
+ "type": "object"
+ },
+ "userAssignedIdentityClientId": {
+ "type": "string"
+ },
+ "virtualMachineName": {
+ "type": "string"
+ }
+ },
+ "resources": [
+ {
+ "type": "Microsoft.Compute/virtualMachines/runCommands",
+ "apiVersion": "2023-03-01",
+ "name": "[[format('{0}/{1}', parameters('virtualMachineName'), 'restartVirtualMachine')]",
+ "location": "[[parameters('location')]",
+ "tags": "[[if(contains(parameters('tags'), 'Microsoft.Compute/virtualMachines'), parameters('tags')['Microsoft.Compute/virtualMachines'], createObject())]",
+ "properties": {
+ "treatFailureAsDeploymentFailure": true,
+ "asyncExecution": false,
+ "parameters": [
+ {
+ "name": "Environment",
+ "value": "[[environment().name]"
+ },
+ {
+ "name": "ResourceGroupName",
+ "value": "[[parameters('resourceGroupName')]"
+ },
+ {
+ "name": "SubscriptionId",
+ "value": "[[subscription().subscriptionId]"
+ },
+ {
+ "name": "TenantId",
+ "value": "[[tenant().tenantId]"
+ },
+ {
+ "name": "UserAssignedIdentityClientId",
+ "value": "[[parameters('userAssignedIdentityClientId')]"
+ },
+ {
+ "name": "VirtualMachineName",
+ "value": "[[parameters('imageVirtualMachineName')]"
+ }
+ ],
+ "source": {
+ "script": " param(\r\n [string]$Environment,\r\n [string]$ResourceGroupName,\r\n [string]$SubscriptionId,\r\n [string]$TenantId,\r\n [string]$UserAssignedIdentityClientId,\r\n [string]$VirtualMachineName\r\n )\r\n $ErrorActionPreference = 'Stop'\r\n Connect-AzAccount -Environment $Environment -Tenant $TenantId -Subscription $SubscriptionId -Identity -AccountId $UserAssignedIdentityClientId | Out-Null\r\n Restart-AzVM -ResourceGroupName $ResourceGroupName -Name $VirtualMachineName\r\n $AgentStatus = $Null\r\n while ($Null -eq $AgentStatus) \r\n {\r\n Start-Sleep -Seconds 5\r\n $AgentStatus = (Get-AzVM -ResourceGroupName $ResourceGroupName -Name $VirtualMachineName -Status).VMAgent\r\n }\r\n "
+ }
+ }
+ }
+ ]
+ }
+ },
+ "dependsOn": [
+ "[[resourceId('Microsoft.Resources/deployments', format('customizations-{0}', parameters('deploymentNameSuffix')))]",
+ "[[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', variables('subscriptionId'), variables('resourceGroupName')), 'Microsoft.Resources/deployments', format('management-vm-{0}', parameters('deploymentNameSuffix')))]",
+ "[[resourceId('Microsoft.Resources/deployments', format('image-vm-{0}', parameters('deploymentNameSuffix')))]"
+ ]
+ },
+ {
+ "type": "Microsoft.Resources/deployments",
+ "apiVersion": "2022-09-01",
+ "name": "[[format('sysprep-vm-{0}', parameters('deploymentNameSuffix'))]",
+ "properties": {
+ "expressionEvaluationOptions": {
+ "scope": "inner"
+ },
+ "mode": "Incremental",
+ "parameters": {
+ "location": {
+ "value": "[[parameters('location')]"
+ },
+ "tags": {
+ "value": "[[parameters('tags')]"
+ },
+ "virtualMachineName": {
+ "value": "[[reference(resourceId('Microsoft.Resources/deployments', format('image-vm-{0}', parameters('deploymentNameSuffix'))), '2022-09-01').outputs.name.value]"
+ }
+ },
+ "template": {
+ "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
+ "contentVersion": "1.0.0.0",
+ "metadata": {
+ "_generator": {
+ "name": "bicep",
+ "version": "0.24.24.22086",
+ "templateHash": "15255297707921051029"
+ }
+ },
+ "parameters": {
+ "location": {
+ "type": "string"
+ },
+ "tags": {
+ "type": "object"
+ },
+ "virtualMachineName": {
+ "type": "string"
+ }
+ },
+ "resources": [
+ {
+ "type": "Microsoft.Compute/virtualMachines/runCommands",
+ "apiVersion": "2023-03-01",
+ "name": "[[format('{0}/{1}', parameters('virtualMachineName'), 'sysprepVirtualMachine')]",
+ "location": "[[parameters('location')]",
+ "tags": "[[if(contains(parameters('tags'), 'Microsoft.Compute/virtualMachines'), parameters('tags')['Microsoft.Compute/virtualMachines'], createObject())]",
+ "properties": {
+ "treatFailureAsDeploymentFailure": false,
+ "asyncExecution": true,
+ "parameters": [],
+ "source": {
+ "script": " Start-Sleep -Seconds 30\r\n Remove-Item -LiteralPath 'C:\\Windows\\Panther' -Force -Recurse -ErrorAction SilentlyContinue\r\n Set-ItemProperty -Path 'HKLM:\\SYSTEM\\CurrentControlSet\\Services\\cdrom' -Name 'Start' -Value 1\r\n Start-Process -File 'C:\\Windows\\System32\\Sysprep\\Sysprep.exe' -ArgumentList '/generalize /oobe /shutdown /mode:vm'\r\n "
+ }
+ }
+ }
+ ]
+ }
+ },
+ "dependsOn": [
+ "[[resourceId('Microsoft.Resources/deployments', format('restart-vm-{0}', parameters('deploymentNameSuffix')))]",
+ "[[resourceId('Microsoft.Resources/deployments', format('image-vm-{0}', parameters('deploymentNameSuffix')))]"
+ ]
+ },
+ {
+ "type": "Microsoft.Resources/deployments",
+ "apiVersion": "2022-09-01",
+ "name": "[[format('generalize-vm-{0}', parameters('deploymentNameSuffix'))]",
+ "properties": {
+ "expressionEvaluationOptions": {
+ "scope": "inner"
+ },
+ "mode": "Incremental",
+ "parameters": {
+ "imageVirtualMachineName": {
+ "value": "[[reference(resourceId('Microsoft.Resources/deployments', format('image-vm-{0}', parameters('deploymentNameSuffix'))), '2022-09-01').outputs.name.value]"
+ },
+ "resourceGroupName": {
+ "value": "[[variables('resourceGroupName')]"
+ },
+ "location": {
+ "value": "[[parameters('location')]"
+ },
+ "tags": {
+ "value": "[[parameters('tags')]"
+ },
+ "userAssignedIdentityClientId": {
+ "value": "[[parameters('userAssignedIdentityClientId')]"
+ },
+ "virtualMachineName": "[[if(parameters('enableBuildAutomation'), createObject('value', parameters('managementVirtualMachineName')), createObject('value', reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', variables('subscriptionId'), variables('resourceGroupName')), 'Microsoft.Resources/deployments', format('management-vm-{0}', parameters('deploymentNameSuffix'))), '2022-09-01').outputs.name.value))]"
+ },
+ "template": {
+ "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
+ "contentVersion": "1.0.0.0",
+ "metadata": {
+ "_generator": {
+ "name": "bicep",
+ "version": "0.24.24.22086",
+ "templateHash": "14089062657418312586"
+ }
+ },
+ "parameters": {
+ "imageVirtualMachineName": {
+ "type": "string"
+ },
+ "resourceGroupName": {
+ "type": "string"
+ },
+ "location": {
+ "type": "string",
+ "defaultValue": "[[resourceGroup().location]"
+ },
+ "tags": {
+ "type": "object"
+ },
+ "userAssignedIdentityClientId": {
+ "type": "string"
+ },
+ "virtualMachineName": {
+ "type": "string"
+ }
+ },
+ "resources": [
+ {
+ "type": "Microsoft.Compute/virtualMachines/runCommands",
+ "apiVersion": "2023-03-01",
+ "name": "[[format('{0}/{1}', parameters('virtualMachineName'), 'generalizeVirtualMachine')]",
+ "location": "[[parameters('location')]",
+ "tags": "[[if(contains(parameters('tags'), 'Microsoft.Compute/virtualMachines'), parameters('tags')['Microsoft.Compute/virtualMachines'], createObject())]",
+ "properties": {
+ "treatFailureAsDeploymentFailure": true,
+ "asyncExecution": false,
+ "parameters": [
+ {
+ "name": "Environment",
+ "value": "[[environment().name]"
+ },
+ {
+ "name": "ResourceGroupName",
+ "value": "[[parameters('resourceGroupName')]"
+ },
+ {
+ "name": "SubscriptionId",
+ "value": "[[subscription().subscriptionId]"
+ },
+ {
+ "name": "TenantId",
+ "value": "[[tenant().tenantId]"
+ },
+ {
+ "name": "UserAssignedIdentityClientId",
+ "value": "[[parameters('userAssignedIdentityClientId')]"
+ },
+ {
+ "name": "VirtualMachineName",
+ "value": "[[parameters('imageVirtualMachineName')]"
+ }
+ ],
+ "source": {
+ "script": " param(\r\n [string]$Environment,\r\n [string]$ResourceGroupName,\r\n [string]$SubscriptionId,\r\n [string]$TenantId,\r\n [string]$UserAssignedIdentityClientId,\r\n [string]$VirtualMachineName\r\n )\r\n $ErrorActionPreference = 'Stop'\r\n Connect-AzAccount -Environment $Environment -Tenant $TenantId -Subscription $SubscriptionId -Identity -AccountId $UserAssignedIdentityClientId | Out-Null\r\n $PowerStatus = ''\r\n while ($PowerStatus -ne 'VM stopped') \r\n {\r\n Start-Sleep -Seconds 5\r\n $PowerStatus = (Get-AzVM -ResourceGroupName $ResourceGroupName -Name $VirtualMachineName -Status).Statuses[1].DisplayStatus\r\n }\r\n Set-AzVm -ResourceGroupName $ResourceGroupName -Name $VirtualMachineName -Generalized\r\n Start-Sleep -Seconds 30\r\n "
+ }
+ }
+ }
+ ]
+ }
+ },
+ "dependsOn": [
+ "[[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', variables('subscriptionId'), variables('resourceGroupName')), 'Microsoft.Resources/deployments', format('management-vm-{0}', parameters('deploymentNameSuffix')))]",
+ "[[resourceId('Microsoft.Resources/deployments', format('sysprep-vm-{0}', parameters('deploymentNameSuffix')))]",
+ "[[resourceId('Microsoft.Resources/deployments', format('image-vm-{0}', parameters('deploymentNameSuffix')))]"
+ ]
+ },
+ {
+ "type": "Microsoft.Resources/deployments",
+ "apiVersion": "2022-09-01",
+ "name": "[[format('image-version-{0}', parameters('deploymentNameSuffix'))]",
+ "properties": {
+ "expressionEvaluationOptions": {
+ "scope": "inner"
+ },
+ "mode": "Incremental",
+ "parameters": {
+ "computeGalleryImageResourceId": {
+ "value": "[[parameters('computeGalleryImageResourceId')]"
+ },
+ "computeGalleryName": {
+ "value": "[[parameters('computeGalleryName')]"
+ },
+ "excludeFromLatest": {
+ "value": "[[parameters('excludeFromLatest')]"
+ },
+ "imageDefinitionName": {
+ "value": "[[parameters('imageDefinitionName')]"
+ },
+ "imageVersionNumber": {
+ "value": "[[variables('autoImageVersion')]"
+ },
+ "imageVirtualMachineResourceId": {
+ "value": "[[reference(resourceId('Microsoft.Resources/deployments', format('image-vm-{0}', parameters('deploymentNameSuffix'))), '2022-09-01').outputs.resourceId.value]"
+ },
+ "location": {
+ "value": "[[parameters('location')]"
+ },
+ "marketplaceImageOffer": {
+ "value": "[[parameters('marketplaceImageOffer')]"
+ },
+ "marketplaceImagePublisher": {
+ "value": "[[parameters('marketplaceImagePublisher')]"
+ },
+ "replicaCount": {
+ "value": "[[parameters('replicaCount')]"
+ },
+ "tags": {
+ "value": "[[parameters('tags')]"
+ }
+ },
+ "template": {
+ "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
+ "contentVersion": "1.0.0.0",
+ "metadata": {
+ "_generator": {
+ "name": "bicep",
+ "version": "0.24.24.22086",
+ "templateHash": "6302458606004775652"
+ }
+ },
+ "parameters": {
+ "allowDeletionOfReplicatedLocations": {
+ "type": "bool",
+ "defaultValue": true
+ },
+ "computeGalleryName": {
+ "type": "string"
+ },
+ "computeGalleryImageResourceId": {
+ "type": "string"
+ },
+ "excludeFromLatest": {
+ "type": "bool"
+ },
+ "imageDefinitionName": {
+ "type": "string"
+ },
+ "imageVersionNumber": {
+ "type": "string"
+ },
+ "imageVirtualMachineResourceId": {
+ "type": "string"
+ },
+ "location": {
+ "type": "string"
+ },
+ "marketplaceImageOffer": {
+ "type": "string"
+ },
+ "marketplaceImagePublisher": {
+ "type": "string"
+ },
+ "replicaCount": {
+ "type": "int"
+ },
+ "tags": {
+ "type": "object"
+ }
+ },
+ "resources": [
+ {
+ "type": "Microsoft.Compute/galleries/images",
+ "apiVersion": "2022-03-03",
+ "name": "[[format('{0}/{1}', parameters('computeGalleryName'), parameters('imageDefinitionName'))]",
+ "location": "[[parameters('location')]",
+ "tags": "[[if(contains(parameters('tags'), 'Microsoft.Compute/galleries'), parameters('tags')['Microsoft.Compute/galleries'], createObject())]",
+ "properties": {
+ "architecture": "x64",
+ "features": [
+ {
+ "name": "SecurityType",
+ "value": "TrustedLaunch"
+ }
+ ],
+ "hyperVGeneration": "V2",
+ "identifier": {
+ "offer": "[[if(empty(parameters('computeGalleryImageResourceId')), parameters('marketplaceImageOffer'), reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', split(parameters('computeGalleryImageResourceId'), '/')[2], split(parameters('computeGalleryImageResourceId'), '/')[4]), 'Microsoft.Compute/galleries/images', split(parameters('computeGalleryImageResourceId'), '/')[8], split(parameters('computeGalleryImageResourceId'), '/')[10]), '2022-03-03').identifier.offer)]",
+ "publisher": "[[if(empty(parameters('computeGalleryImageResourceId')), parameters('marketplaceImagePublisher'), reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', split(parameters('computeGalleryImageResourceId'), '/')[2], split(parameters('computeGalleryImageResourceId'), '/')[4]), 'Microsoft.Compute/galleries/images', split(parameters('computeGalleryImageResourceId'), '/')[8], split(parameters('computeGalleryImageResourceId'), '/')[10]), '2022-03-03').identifier.publisher)]",
+ "sku": "[[parameters('imageDefinitionName')]"
+ },
+ "osState": "Generalized",
+ "osType": "Windows"
+ }
+ },
+ {
+ "type": "Microsoft.Compute/galleries/images/versions",
+ "apiVersion": "2022-03-03",
+ "name": "[[format('{0}/{1}/{2}', parameters('computeGalleryName'), parameters('imageDefinitionName'), parameters('imageVersionNumber'))]",
+ "location": "[[parameters('location')]",
+ "tags": "[[if(contains(parameters('tags'), 'Microsoft.Compute/galleries'), parameters('tags')['Microsoft.Compute/galleries'], createObject())]",
+ "properties": {
+ "publishingProfile": {
+ "excludeFromLatest": "[[parameters('excludeFromLatest')]",
+ "replicaCount": "[[parameters('replicaCount')]",
+ "replicationMode": "Full",
+ "storageAccountType": "Standard_LRS",
+ "targetRegions": [
+ {
+ "name": "[[parameters('location')]",
+ "regionalReplicaCount": "[[parameters('replicaCount')]",
+ "storageAccountType": "Standard_LRS"
+ }
+ ]
+ },
+ "safetyProfile": {
+ "allowDeletionOfReplicatedLocations": "[[parameters('allowDeletionOfReplicatedLocations')]"
+ },
+ "storageProfile": {
+ "source": {
+ "id": "[[parameters('imageVirtualMachineResourceId')]"
+ }
+ }
+ },
+ "dependsOn": [
+ "[[resourceId('Microsoft.Compute/galleries/images', parameters('computeGalleryName'), parameters('imageDefinitionName'))]"
+ ]
+ }
+ ]
+ }
+ },
+ "dependsOn": [
+ "[[resourceId('Microsoft.Resources/deployments', format('generalize-vm-{0}', parameters('deploymentNameSuffix')))]",
+ "[[resourceId('Microsoft.Resources/deployments', format('image-vm-{0}', parameters('deploymentNameSuffix')))]"
+ ]
+ },
+ {
+ "type": "Microsoft.Resources/deployments",
+ "apiVersion": "2022-09-01",
+ "name": "[[format('remove-vm-{0}', parameters('deploymentNameSuffix'))]",
+ "properties": {
+ "expressionEvaluationOptions": {
+ "scope": "inner"
+ },
+ "mode": "Incremental",
+ "parameters": {
+ "enableBuildAutomation": {
+ "value": "[[parameters('enableBuildAutomation')]"
+ },
+ "imageVirtualMachineName": {
+ "value": "[[reference(resourceId('Microsoft.Resources/deployments', format('image-vm-{0}', parameters('deploymentNameSuffix'))), '2022-09-01').outputs.name.value]"
+ },
+ "location": {
+ "value": "[[parameters('location')]"
+ },
+ "tags": {
+ "value": "[[parameters('tags')]"
+ },
+ "userAssignedIdentityClientId": {
+ "value": "[[parameters('userAssignedIdentityClientId')]"
+ },
+ "virtualMachineName": "[[if(parameters('enableBuildAutomation'), createObject('value', parameters('managementVirtualMachineName')), createObject('value', reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', variables('subscriptionId'), variables('resourceGroupName')), 'Microsoft.Resources/deployments', format('management-vm-{0}', parameters('deploymentNameSuffix'))), '2022-09-01').outputs.name.value))]"
+ },
+ "template": {
+ "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
+ "contentVersion": "1.0.0.0",
+ "metadata": {
+ "_generator": {
+ "name": "bicep",
+ "version": "0.24.24.22086",
+ "templateHash": "3667781850662988906"
+ }
+ },
+ "parameters": {
+ "enableBuildAutomation": {
+ "type": "bool"
+ },
+ "imageVirtualMachineName": {
+ "type": "string"
+ },
+ "location": {
+ "type": "string",
+ "defaultValue": "[[resourceGroup().location]"
+ },
+ "tags": {
+ "type": "object"
+ },
+ "userAssignedIdentityClientId": {
+ "type": "string"
+ },
+ "virtualMachineName": {
+ "type": "string"
+ }
+ },
+ "resources": [
+ {
+ "type": "Microsoft.Compute/virtualMachines/runCommands",
+ "apiVersion": "2023-03-01",
+ "name": "[[format('{0}/{1}', parameters('virtualMachineName'), 'removeVirtualMachine')]",
+ "location": "[[parameters('location')]",
+ "tags": "[[if(contains(parameters('tags'), 'Microsoft.Compute/virtualMachines'), parameters('tags')['Microsoft.Compute/virtualMachines'], createObject())]",
+ "properties": {
+ "treatFailureAsDeploymentFailure": true,
+ "asyncExecution": "[[if(parameters('enableBuildAutomation'), false(), true())]",
+ "parameters": [
+ {
+ "name": "EnableBuildAutomation",
+ "value": "[[string(parameters('enableBuildAutomation'))]"
+ },
+ {
+ "name": "Environment",
+ "value": "[[environment().name]"
+ },
+ {
+ "name": "ImageVmName",
+ "value": "[[parameters('imageVirtualMachineName')]"
+ },
+ {
+ "name": "ManagementVmName",
+ "value": "[[parameters('virtualMachineName')]"
+ },
+ {
+ "name": "ResourceGroupName",
+ "value": "[[resourceGroup().name]"
+ },
+ {
+ "name": "SubscriptionId",
+ "value": "[[subscription().subscriptionId]"
+ },
+ {
+ "name": "TenantId",
+ "value": "[[tenant().tenantId]"
+ },
+ {
+ "name": "UserAssignedIdentityClientId",
+ "value": "[[parameters('userAssignedIdentityClientId')]"
+ }
+ ],
+ "source": {
+ "script": " param(\r\n [string]$EnableBuildAutomation,\r\n [string]$Environment,\r\n [string]$ImageVmName,\r\n [string]$ManagementVmName,\r\n [string]$ResourceGroupName,\r\n [string]$SubscriptionId,\r\n [string]$TenantId,\r\n [string]$UserAssignedIdentityClientId\r\n )\r\n $ErrorActionPreference = 'Stop'\r\n Connect-AzAccount -Environment $Environment -Tenant $TenantId -Subscription $SubscriptionId -Identity -AccountId $UserAssignedIdentityClientId | Out-Null\r\n Remove-AzVM -ResourceGroupName $ResourceGroupName -Name $ImageVmName -Force\r\n if($EnableBuildAutomation -eq 'false')\r\n {\r\n Remove-AzVM -ResourceGroupName $ResourceGroupName -Name $ManagementVmName -NoWait -Force -AsJob\r\n }\r\n "
+ }
+ }
+ }
+ ]
+ }
+ },
+ "dependsOn": [
+ "[[resourceId('Microsoft.Resources/deployments', format('image-version-{0}', parameters('deploymentNameSuffix')))]",
+ "[[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', variables('subscriptionId'), variables('resourceGroupName')), 'Microsoft.Resources/deployments', format('management-vm-{0}', parameters('deploymentNameSuffix')))]",
+ "[[resourceId('Microsoft.Resources/deployments', format('image-vm-{0}', parameters('deploymentNameSuffix')))]"
+ ]
+ }
+ ]
+ }
+ },
+ "resources": [
+ {
+ "type": "Microsoft.Resources/templateSpecs",
+ "apiVersion": "2022-02-01",
+ "name": "[format('ts-{0}', parameters('imageDefinitionName'))]",
+ "location": "[parameters('location')]",
+ "tags": "[if(contains(parameters('tags'), 'Microsoft.Resources/templateSpecs'), parameters('tags')['Microsoft.Resources/templateSpecs'], createObject())]",
+ "properties": {
+ "description": "[format('An automation runbook deploys a new image version for the \"{0}\" image definition from this template spec.', parameters('imageDefinitionName'))]",
+ "displayName": "[format('Zero Trust Image Build Automation: {0}', parameters('imageDefinitionName'))]"
+ }
+ },
+ {
+ "type": "Microsoft.Resources/templateSpecs/versions",
+ "apiVersion": "2022-02-01",
+ "name": "[format('{0}/{1}', format('ts-{0}', parameters('imageDefinitionName')), '1.0')]",
+ "location": "[parameters('location')]",
+ "tags": "[if(contains(parameters('tags'), 'Microsoft.Resources/templateSpecs'), parameters('tags')['Microsoft.Resources/templateSpecs'], createObject())]",
+ "properties": {
+ "mainTemplate": "[variables('$fxv#0')]"
+ },
+ "dependsOn": [
+ "[resourceId('Microsoft.Resources/templateSpecs', format('ts-{0}', parameters('imageDefinitionName')))]"
+ ]
+ }
+ ],
+ "outputs": {
+ "resourceId": {
+ "type": "string",
+ "value": "[resourceId('Microsoft.Resources/templateSpecs/versions', format('ts-{0}', parameters('imageDefinitionName')), '1.0')]"
+ }
+ }
+ }
+ }
+ },
+ {
+ "type": "Microsoft.Resources/deployments",
+ "apiVersion": "2022-09-01",
+ "name": "[format('management-vm-{0}', parameters('deploymentNameSuffix'))]",
+ "subscriptionId": "[parameters('subscriptionId')]",
+ "resourceGroup": "[parameters('resourceGroupName')]",
+ "properties": {
+ "expressionEvaluationOptions": {
+ "scope": "inner"
+ },
+ "mode": "Incremental",
+ "parameters": {
+ "containerName": {
+ "value": "[parameters('containerName')]"
+ },
+ "diskEncryptionSetResourceId": {
+ "value": "[parameters('diskEncryptionSetResourceId')]"
+ },
+ "hybridUseBenefit": {
+ "value": "[parameters('hybridUseBenefit')]"
+ },
+ "localAdministratorPassword": {
+ "value": "[parameters('localAdministratorPassword')]"
+ },
+ "localAdministratorUsername": {
+ "value": "[parameters('localAdministratorUsername')]"
+ },
+ "location": {
+ "value": "[parameters('location')]"
+ },
+ "storageAccountName": {
+ "value": "[split(parameters('storageAccountResourceId'), '/')[8]]"
+ },
+ "subnetResourceId": {
+ "value": "[parameters('subnetResourceId')]"
+ },
+ "tags": {
+ "value": "[parameters('tags')]"
+ },
+ "userAssignedIdentityPrincipalId": {
+ "value": "[parameters('userAssignedIdentityPrincipalId')]"
+ },
+ "userAssignedIdentityResourceId": {
+ "value": "[parameters('userAssignedIdentityResourceId')]"
+ },
+ "virtualMachineName": {
+ "value": "[parameters('managementVirtualMachineName')]"
+ }
+ },
+ "template": {
+ "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
+ "contentVersion": "1.0.0.0",
+ "metadata": {
+ "_generator": {
+ "name": "bicep",
+ "version": "0.24.24.22086",
+ "templateHash": "5351463014152522794"
+ }
+ },
+ "parameters": {
+ "containerName": {
+ "type": "string"
+ },
+ "diskEncryptionSetResourceId": {
+ "type": "string"
+ },
+ "hybridUseBenefit": {
+ "type": "bool"
+ },
+ "localAdministratorPassword": {
+ "type": "securestring"
+ },
+ "localAdministratorUsername": {
+ "type": "securestring"
+ },
+ "location": {
+ "type": "string"
+ },
+ "storageAccountName": {
+ "type": "string"
+ },
+ "subnetResourceId": {
+ "type": "string"
+ },
+ "tags": {
+ "type": "object"
+ },
+ "userAssignedIdentityPrincipalId": {
+ "type": "string"
+ },
+ "userAssignedIdentityResourceId": {
+ "type": "string"
+ },
+ "virtualMachineName": {
+ "type": "string"
+ }
+ },
+ "resources": [
+ {
+ "type": "Microsoft.Network/networkInterfaces",
+ "apiVersion": "2023-04-01",
+ "name": "[format('nic-{0}', parameters('virtualMachineName'))]",
+ "location": "[parameters('location')]",
+ "tags": "[if(contains(parameters('tags'), 'Microsoft.Network/networkInterfaces'), parameters('tags')['Microsoft.Network/networkInterfaces'], createObject())]",
+ "properties": {
+ "ipConfigurations": [
+ {
+ "name": "ipconfig",
+ "properties": {
+ "privateIPAllocationMethod": "Dynamic",
+ "subnet": {
+ "id": "[parameters('subnetResourceId')]"
+ },
+ "primary": true,
+ "privateIPAddressVersion": "IPv4"
+ }
+ }
+ ],
+ "enableAcceleratedNetworking": true,
+ "enableIPForwarding": false
+ }
+ },
+ {
+ "type": "Microsoft.Compute/virtualMachines",
+ "apiVersion": "2022-03-01",
+ "name": "[parameters('virtualMachineName')]",
+ "location": "[parameters('location')]",
+ "tags": "[if(contains(parameters('tags'), 'Microsoft.Compute/virtualMachines'), parameters('tags')['Microsoft.Compute/virtualMachines'], createObject())]",
+ "identity": {
+ "type": "UserAssigned",
+ "userAssignedIdentities": {
+ "[format('{0}', parameters('userAssignedIdentityResourceId'))]": {}
+ }
+ },
+ "properties": {
+ "hardwareProfile": {
+ "vmSize": "Standard_D2s_v3"
+ },
+ "osProfile": {
+ "computerName": "[parameters('virtualMachineName')]",
+ "adminUsername": "[parameters('localAdministratorUsername')]",
+ "adminPassword": "[parameters('localAdministratorPassword')]",
+ "windowsConfiguration": {
+ "provisionVMAgent": true,
+ "enableAutomaticUpdates": true,
+ "patchSettings": {
+ "patchMode": "AutomaticByOS",
+ "assessmentMode": "ImageDefault"
+ }
+ }
+ },
+ "storageProfile": {
+ "imageReference": {
+ "publisher": "MicrosoftWindowsServer",
+ "offer": "WindowsServer",
+ "sku": "2019-datacenter-core-g2",
+ "version": "latest"
+ },
+ "osDisk": {
+ "caching": "ReadWrite",
+ "createOption": "FromImage",
+ "deleteOption": "Delete",
+ "managedDisk": {
+ "diskEncryptionSet": {
+ "id": "[parameters('diskEncryptionSetResourceId')]"
+ },
+ "storageAccountType": "Premium_LRS"
+ },
+ "name": "[format('disk-{0}', parameters('virtualMachineName'))]",
+ "osType": "Windows"
+ }
+ },
+ "networkProfile": {
+ "networkInterfaces": [
+ {
+ "id": "[resourceId('Microsoft.Network/networkInterfaces', format('nic-{0}', parameters('virtualMachineName')))]",
+ "properties": {
+ "deleteOption": "Delete"
+ }
+ }
+ ]
+ },
+ "diagnosticsProfile": {
+ "bootDiagnostics": {
+ "enabled": false
+ }
+ },
+ "securityProfile": {
+ "encryptionAtHost": true,
+ "uefiSettings": {
+ "secureBootEnabled": true,
+ "vTpmEnabled": true
+ },
+ "securityType": "TrustedLaunch"
+ },
+ "licenseType": "[if(parameters('hybridUseBenefit'), 'Windows_Server', null())]"
+ },
+ "dependsOn": [
+ "[resourceId('Microsoft.Network/networkInterfaces', format('nic-{0}', parameters('virtualMachineName')))]"
+ ]
+ },
+ {
+ "type": "Microsoft.Compute/virtualMachines/runCommands",
+ "apiVersion": "2023-03-01",
+ "name": "[format('{0}/{1}', parameters('virtualMachineName'), 'appAzModules')]",
+ "location": "[parameters('location')]",
+ "tags": "[if(contains(parameters('tags'), 'Microsoft.Compute/virtualMachines'), parameters('tags')['Microsoft.Compute/virtualMachines'], createObject())]",
+ "properties": {
+ "treatFailureAsDeploymentFailure": true,
+ "asyncExecution": false,
+ "parameters": [
+ {
+ "name": "ContainerName",
+ "value": "[parameters('containerName')]"
+ },
+ {
+ "name": "StorageAccountName",
+ "value": "[parameters('storageAccountName')]"
+ },
+ {
+ "name": "StorageEndpoint",
+ "value": "[environment().suffixes.storage]"
+ },
+ {
+ "name": "UserAssignedIdentityObjectId",
+ "value": "[parameters('userAssignedIdentityPrincipalId')]"
+ }
+ ],
+ "source": {
+ "script": " param(\r\n [string]$ContainerName,\r\n [string]$StorageAccountName,\r\n [string]$StorageEndpoint,\r\n [string]$UserAssignedIdentityObjectId\r\n )\r\n $ErrorActionPreference = \"Stop\"\r\n $StorageAccountUrl = \"https://\" + $StorageAccountName + \".blob.\" + $StorageEndpoint + \"/\"\r\n $TokenUri = \"http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=$StorageAccountUrl&object_id=$UserAssignedIdentityObjectId\"\r\n $AccessToken = ((Invoke-WebRequest -Headers @{Metadata=$true} -Uri $TokenUri -UseBasicParsing).Content | ConvertFrom-Json).access_token\r\n $BlobNames = @('az.accounts.2.12.1.nupkg','az.automation.1.9.0.nupkg','az.compute.5.7.0.nupkg','az.resources.6.6.0.nupkg')\r\n foreach($BlobName in $BlobNames)\r\n {\r\n do\r\n {\r\n try\r\n {\r\n Write-Output \"Download Attempt $i\"\r\n Invoke-WebRequest -Headers @{\"x-ms-version\"=\"2017-11-09\"; Authorization =\"Bearer $AccessToken\"} -Uri \"$StorageAccountUrl$ContainerName/$BlobName\" -OutFile \"$env:windir\\temp\\$BlobName\"\r\n }\r\n catch [System.Net.WebException]\r\n {\r\n Start-Sleep -Seconds 60\r\n $i++\r\n if($i -gt 10){throw}\r\n continue\r\n }\r\n catch\r\n {\r\n $Output = $_ | select *\r\n Write-Output $Output\r\n throw\r\n }\r\n }\r\n until(Test-Path -Path $env:windir\\temp\\$BlobName)\r\n Start-Sleep -Seconds 5\r\n Unblock-File -Path $env:windir\\temp\\$BlobName\r\n $BlobZipName = $Blobname.Replace('nupkg','zip')\r\n Rename-Item -Path $env:windir\\temp\\$BlobName -NewName $BlobZipName\r\n $BlobNameArray = $BlobName.Split('.')\r\n $ModuleFolderName = $BlobNameArray[0] + '.' + $BlobNameArray[1]\r\n $VersionFolderName = $BlobNameArray[2] + '.' + $BlobNameArray[3]+ '.' + $BlobNameArray[4]\r\n $ModulesDirectory = \"C:\\Program Files\\WindowsPowerShell\\Modules\"\r\n New-Item -Path $ModulesDirectory -Name $ModuleFolderName -ItemType \"Directory\" -Force\r\n Expand-Archive -Path $env:windir\\temp\\$BlobZipName -DestinationPath \"$ModulesDirectory\\$ModuleFolderName\\$VersionFolderName\" -Force\r\n Remove-Item -Path \"$ModulesDirectory\\$ModuleFolderName\\$VersionFolderName\\_rels\" -Force -Recurse\r\n Remove-Item -Path \"$ModulesDirectory\\$ModuleFolderName\\$VersionFolderName\\package\" -Force -Recurse\r\n Remove-Item -LiteralPath \"$ModulesDirectory\\$ModuleFolderName\\$VersionFolderName\\[Content_Types].xml\" -Force\r\n Remove-Item -Path \"$ModulesDirectory\\$ModuleFolderName\\$VersionFolderName\\$ModuleFolderName.nuspec\" -Force\r\n }\r\n Remove-Item -Path \"$env:windir\\temp\\az*\" -Force\r\n "
+ }
+ },
+ "dependsOn": [
+ "[resourceId('Microsoft.Compute/virtualMachines', parameters('virtualMachineName'))]"
+ ]
+ }
+ ],
+ "outputs": {
+ "name": {
+ "type": "string",
+ "value": "[parameters('virtualMachineName')]"
+ }
+ }
+ }
+ }
+ },
+ {
+ "type": "Microsoft.Resources/deployments",
+ "apiVersion": "2022-09-01",
+ "name": "[format('automation-account-{0}', parameters('deploymentNameSuffix'))]",
+ "subscriptionId": "[parameters('subscriptionId')]",
+ "resourceGroup": "[parameters('resourceGroupName')]",
+ "properties": {
+ "expressionEvaluationOptions": {
+ "scope": "inner"
+ },
+ "mode": "Incremental",
+ "parameters": {
+ "arcGisProInstaller": {
+ "value": "[parameters('arcGisProInstaller')]"
+ },
+ "actionGroupName": {
+ "value": "[parameters('actionGroupName')]"
+ },
+ "automationAccountName": {
+ "value": "[parameters('automationAccountName')]"
+ },
+ "automationAccountPrivateDnsZoneResourceId": {
+ "value": "[parameters('automationAccountPrivateDnsZoneResourceId')]"
+ },
+ "computeGalleryImageResourceId": {
+ "value": "[parameters('computeGalleryImageResourceId')]"
+ },
+ "computeGalleryResourceId": {
+ "value": "[parameters('computeGalleryResourceId')]"
+ },
+ "containerName": {
+ "value": "[parameters('containerName')]"
+ },
+ "customizations": {
+ "value": "[parameters('customizations')]"
+ },
+ "deploymentNameSuffix": {
+ "value": "[parameters('deploymentNameSuffix')]"
+ },
+ "diskEncryptionSetResourceId": {
+ "value": "[parameters('diskEncryptionSetResourceId')]"
+ },
+ "distributionGroup": {
+ "value": "[parameters('distributionGroup')]"
+ },
+ "domainJoinPassword": {
+ "value": "[parameters('domainJoinPassword')]"
+ },
+ "domainJoinUserPrincipalName": {
+ "value": "[parameters('domainJoinUserPrincipalName')]"
+ },
+ "domainName": {
+ "value": "[parameters('domainName')]"
+ },
+ "enableBuildAutomation": {
+ "value": "[parameters('enableBuildAutomation')]"
+ },
+ "excludeFromLatest": {
+ "value": "[parameters('excludeFromLatest')]"
+ },
+ "hybridUseBenefit": {
+ "value": "[parameters('hybridUseBenefit')]"
+ },
+ "imageDefinitionName": {
+ "value": "[parameters('imageDefinitionName')]"
+ },
+ "imageMajorVersion": {
+ "value": "[parameters('imageMajorVersion')]"
+ },
+ "imageMinorVersion": {
+ "value": "[parameters('imageMinorVersion')]"
+ },
+ "imageVirtualMachineName": {
+ "value": "[parameters('imageVirtualMachineName')]"
+ },
+ "installAccess": {
+ "value": "[parameters('installAccess')]"
+ },
+ "installArcGisPro": {
+ "value": "[parameters('installArcGisPro')]"
+ },
+ "installExcel": {
+ "value": "[parameters('installExcel')]"
+ },
+ "installOneDrive": {
+ "value": "[parameters('installOneDrive')]"
+ },
+ "installOneNote": {
+ "value": "[parameters('installOneNote')]"
+ },
+ "installOutlook": {
+ "value": "[parameters('installOutlook')]"
+ },
+ "installPowerPoint": {
+ "value": "[parameters('installPowerPoint')]"
+ },
+ "installProject": {
+ "value": "[parameters('installProject')]"
+ },
+ "installPublisher": {
+ "value": "[parameters('installPublisher')]"
+ },
+ "installSkypeForBusiness": {
+ "value": "[parameters('installSkypeForBusiness')]"
+ },
+ "installTeams": {
+ "value": "[parameters('installTeams')]"
+ },
+ "installVirtualDesktopOptimizationTool": {
+ "value": "[parameters('installVirtualDesktopOptimizationTool')]"
+ },
+ "installVisio": {
+ "value": "[parameters('installVisio')]"
+ },
+ "installWord": {
+ "value": "[parameters('installWord')]"
+ },
+ "keyVaultName": {
+ "value": "[parameters('keyVaultName')]"
+ },
+ "location": {
+ "value": "[parameters('location')]"
+ },
+ "logAnalyticsWorkspaceResourceId": {
+ "value": "[parameters('logAnalyticsWorkspaceResourceId')]"
+ },
+ "managementVirtualMachineName": {
+ "value": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('subscriptionId'), parameters('resourceGroupName')), 'Microsoft.Resources/deployments', format('management-vm-{0}', parameters('deploymentNameSuffix'))), '2022-09-01').outputs.name.value]"
+ },
+ "marketplaceImageOffer": {
+ "value": "[parameters('marketplaceImageOffer')]"
+ },
+ "marketplaceImagePublisher": {
+ "value": "[parameters('marketplaceImagePublisher')]"
+ },
+ "marketplaceImageSKU": {
+ "value": "[parameters('marketplaceImageSKU')]"
+ },
+ "msrdcwebrtcsvcInstaller": {
+ "value": "[parameters('msrdcwebrtcsvcInstaller')]"
+ },
+ "officeInstaller": {
+ "value": "[parameters('officeInstaller')]"
+ },
+ "oUPath": {
+ "value": "[parameters('oUPath')]"
+ },
+ "replicaCount": {
+ "value": "[parameters('replicaCount')]"
+ },
+ "resourceGroupName": {
+ "value": "[parameters('resourceGroupName')]"
+ },
+ "sourceImageType": {
+ "value": "[parameters('sourceImageType')]"
+ },
+ "storageAccountResourceId": {
+ "value": "[parameters('storageAccountResourceId')]"
+ },
+ "subnetResourceId": {
+ "value": "[parameters('subnetResourceId')]"
+ },
+ "tags": {
+ "value": "[parameters('tags')]"
+ },
+ "teamsInstaller": {
+ "value": "[parameters('teamsInstaller')]"
+ },
+ "templateSpecResourceId": {
+ "value": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('subscriptionId'), parameters('resourceGroupName')), 'Microsoft.Resources/deployments', format('template-spec-{0}', parameters('deploymentNameSuffix'))), '2022-09-01').outputs.resourceId.value]"
+ },
+ "timeZone": {
+ "value": "[parameters('timeZone')]"
+ },
+ "userAssignedIdentityClientId": {
+ "value": "[parameters('userAssignedIdentityClientId')]"
+ },
+ "userAssignedIdentityPrincipalId": {
+ "value": "[parameters('userAssignedIdentityPrincipalId')]"
+ },
+ "userAssignedIdentityResourceId": {
+ "value": "[parameters('userAssignedIdentityResourceId')]"
+ },
+ "vcRedistInstaller": {
+ "value": "[parameters('vcRedistInstaller')]"
+ },
+ "vDOTInstaller": {
+ "value": "[parameters('vDOTInstaller')]"
+ },
+ "virtualMachineSize": {
+ "value": "[parameters('virtualMachineSize')]"
+ }
+ },
+ "template": {
+ "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
+ "contentVersion": "1.0.0.0",
+ "metadata": {
+ "_generator": {
+ "name": "bicep",
+ "version": "0.24.24.22086",
+ "templateHash": "4131143920973627460"
+ }
+ },
+ "parameters": {
+ "arcGisProInstaller": {
+ "type": "string"
+ },
+ "actionGroupName": {
+ "type": "string"
+ },
+ "automationAccountName": {
+ "type": "string"
+ },
+ "automationAccountPrivateDnsZoneResourceId": {
+ "type": "string"
+ },
+ "computeGalleryImageResourceId": {
+ "type": "string"
+ },
+ "computeGalleryResourceId": {
+ "type": "string"
+ },
+ "containerName": {
+ "type": "string"
+ },
+ "customizations": {
+ "type": "array"
+ },
+ "deploymentNameSuffix": {
+ "type": "string"
+ },
+ "diskEncryptionSetResourceId": {
+ "type": "string"
+ },
+ "distributionGroup": {
+ "type": "string"
+ },
+ "domainJoinPassword": {
+ "type": "securestring"
+ },
+ "domainJoinUserPrincipalName": {
+ "type": "string"
+ },
+ "domainName": {
+ "type": "string"
+ },
+ "enableBuildAutomation": {
+ "type": "bool"
+ },
+ "excludeFromLatest": {
+ "type": "bool"
+ },
+ "hybridUseBenefit": {
+ "type": "bool"
+ },
+ "imageDefinitionName": {
+ "type": "string"
+ },
+ "imageMajorVersion": {
+ "type": "int"
+ },
+ "imageMinorVersion": {
+ "type": "int"
+ },
+ "imageVirtualMachineName": {
+ "type": "string"
+ },
+ "installAccess": {
+ "type": "bool"
+ },
+ "installArcGisPro": {
+ "type": "bool"
+ },
+ "installExcel": {
+ "type": "bool"
+ },
+ "installOneDrive": {
+ "type": "bool"
+ },
+ "installOneNote": {
+ "type": "bool"
+ },
+ "installOutlook": {
+ "type": "bool"
+ },
+ "installPowerPoint": {
+ "type": "bool"
+ },
+ "installProject": {
+ "type": "bool"
+ },
+ "installPublisher": {
+ "type": "bool"
+ },
+ "installSkypeForBusiness": {
+ "type": "bool"
+ },
+ "installTeams": {
+ "type": "bool"
+ },
+ "installVirtualDesktopOptimizationTool": {
+ "type": "bool"
+ },
+ "installVisio": {
+ "type": "bool"
+ },
+ "installWord": {
+ "type": "bool"
+ },
+ "keyVaultName": {
+ "type": "string"
+ },
+ "jobScheduleName": {
+ "type": "string",
+ "defaultValue": "[newGuid()]"
+ },
+ "location": {
+ "type": "string"
+ },
+ "logAnalyticsWorkspaceResourceId": {
+ "type": "string"
+ },
+ "managementVirtualMachineName": {
+ "type": "string"
+ },
+ "marketplaceImageOffer": {
+ "type": "string"
+ },
+ "marketplaceImagePublisher": {
+ "type": "string"
+ },
+ "marketplaceImageSKU": {
+ "type": "string"
+ },
+ "msrdcwebrtcsvcInstaller": {
+ "type": "string"
+ },
+ "officeInstaller": {
+ "type": "string"
+ },
+ "oUPath": {
+ "type": "string"
+ },
+ "replicaCount": {
+ "type": "int"
+ },
+ "resourceGroupName": {
+ "type": "string"
+ },
+ "sourceImageType": {
+ "type": "string"
+ },
+ "storageAccountResourceId": {
+ "type": "string"
+ },
+ "subnetResourceId": {
+ "type": "string"
+ },
+ "tags": {
+ "type": "object"
+ },
+ "teamsInstaller": {
+ "type": "string"
+ },
+ "templateSpecResourceId": {
+ "type": "string"
+ },
+ "time": {
+ "type": "string",
+ "defaultValue": "[utcNow()]"
+ },
+ "timeZone": {
+ "type": "string"
+ },
+ "userAssignedIdentityClientId": {
+ "type": "string"
+ },
+ "userAssignedIdentityPrincipalId": {
+ "type": "string"
+ },
+ "userAssignedIdentityResourceId": {
+ "type": "string"
+ },
+ "vcRedistInstaller": {
+ "type": "string"
+ },
+ "vDOTInstaller": {
+ "type": "string"
+ },
+ "virtualMachineSize": {
+ "type": "string"
+ }
+ },
+ "variables": {
+ "parameters": {
+ "arcGisProInstaller": "[parameters('arcGisProInstaller')]",
+ "computeGalleryResourceId": "[parameters('computeGalleryResourceId')]",
+ "containerName": "[parameters('containerName')]",
+ "customizations": "[string(parameters('customizations'))]",
+ "diskEncryptionSetResourceId": "[parameters('diskEncryptionSetResourceId')]",
+ "enableBuildAutomation": "[string(parameters('enableBuildAutomation'))]",
+ "environmentName": "[environment().name]",
+ "excludeFromLatest": "[parameters('excludeFromLatest')]",
+ "hybridUseBenefit": "[parameters('hybridUseBenefit')]",
+ "imageDefinitionName": "[parameters('imageDefinitionName')]",
+ "imageMajorVersion": "[string(parameters('imageMajorVersion'))]",
+ "imageMinorVersion": "[string(parameters('imageMinorVersion'))]",
+ "imageVirtualMachineName": "[parameters('imageVirtualMachineName')]",
+ "installAccess": "[string(parameters('installAccess'))]",
+ "installArcGisPro": "[string(parameters('installArcGisPro'))]",
+ "installExcel": "[string(parameters('installExcel'))]",
+ "InstallOneDrive": "[string(parameters('installOneDrive'))]",
+ "installOneNote": "[string(parameters('installOneNote'))]",
+ "installOutlook": "[string(parameters('installOutlook'))]",
+ "installPowerPoint": "[string(parameters('installPowerPoint'))]",
+ "installProject": "[string(parameters('installProject'))]",
+ "installPublisher": "[string(parameters('installPublisher'))]",
+ "installSkypeForBusiness": "[string(parameters('installSkypeForBusiness'))]",
+ "installTeams": "[string(parameters('installTeams'))]",
+ "installVirtualDesktopOptimizationTool": "[string(parameters('installVirtualDesktopOptimizationTool'))]",
+ "installVisio": "[string(parameters('installVisio'))]",
+ "installWord": "[string(parameters('installWord'))]",
+ "keyVaultName": "[parameters('keyVaultName')]",
+ "location": "[parameters('location')]",
+ "managementVirtualMachineName": "[parameters('managementVirtualMachineName')]",
+ "marketplaceImageOffer": "[parameters('marketplaceImageOffer')]",
+ "marketplaceImagePublisher": "[parameters('marketplaceImagePublisher')]",
+ "marketplaceImageSKU": "[parameters('marketplaceImageSKU')]",
+ "msrdcwebrtcsvcInstaller": "[parameters('msrdcwebrtcsvcInstaller')]",
+ "officeInstaller": "[parameters('officeInstaller')]",
+ "replicaCount": "[string(parameters('replicaCount'))]",
+ "resourceGroupName": "[parameters('resourceGroupName')]",
+ "computeGalleryImageResourceId": "[parameters('computeGalleryImageResourceId')]",
+ "sourceImageType": "[parameters('sourceImageType')]",
+ "storageAccountResourceId": "[parameters('storageAccountResourceId')]",
+ "subnetResourceId": "[parameters('subnetResourceId')]",
+ "subscriptionId": "[variables('subscriptionId')]",
+ "tags": "[string(parameters('tags'))]",
+ "teamsInstaller": "[parameters('teamsInstaller')]",
+ "templateSpecResourceId": "[parameters('templateSpecResourceId')]",
+ "tenantId": "[variables('tenantId')]",
+ "userAssignedIdentityClientId": "[parameters('userAssignedIdentityClientId')]",
+ "userAssignedIdentityPrincipalId": "[parameters('userAssignedIdentityPrincipalId')]",
+ "userAssignedIdentityResourceId": "[parameters('userAssignedIdentityResourceId')]",
+ "vcRedistInstaller": "[parameters('vcRedistInstaller')]",
+ "vDOTInstaller": "[parameters('vDOTInstaller')]",
+ "virtualMachineSize": "[parameters('virtualMachineSize')]"
+ },
+ "privateEndpointName": "[format('pe-{0}', parameters('automationAccountName'))]",
+ "runbookName": "New-AzureZeroTrustImageBuild",
+ "storageEndpoint": "[environment().suffixes.storage]",
+ "subscriptionId": "[subscription().subscriptionId]",
+ "tenantId": "[subscription().tenantId]"
+ },
+ "resources": [
+ {
+ "type": "Microsoft.Automation/automationAccounts",
+ "apiVersion": "2022-08-08",
+ "name": "[parameters('automationAccountName')]",
+ "location": "[parameters('location')]",
+ "tags": "[if(contains(parameters('tags'), 'Microsoft.Automation/automationAccounts'), parameters('tags')['Microsoft.Automation/automationAccounts'], createObject())]",
+ "properties": {
+ "disableLocalAuth": false,
+ "publicNetworkAccess": false,
+ "sku": {
+ "name": "Basic"
+ },
+ "encryption": {
+ "keySource": "Microsoft.Automation",
+ "identity": {}
+ }
+ }
+ },
+ {
+ "type": "Microsoft.Network/privateEndpoints",
+ "apiVersion": "2023-05-01",
+ "name": "[variables('privateEndpointName')]",
+ "location": "[parameters('location')]",
+ "tags": "[if(contains(parameters('tags'), 'Microsoft.Network/privateEndpoints'), parameters('tags')['Microsoft.Network/privateEndpoints'], createObject())]",
+ "properties": {
+ "privateLinkServiceConnections": [
+ {
+ "name": "[variables('privateEndpointName')]",
+ "id": "[resourceId('Microsoft.Network/privateEndpoints/privateLinkServiceConnections', variables('privateEndpointName'), variables('privateEndpointName'))]",
+ "properties": {
+ "privateLinkServiceId": "[resourceId('Microsoft.Automation/automationAccounts', parameters('automationAccountName'))]",
+ "groupIds": [
+ "DSCAndHybridWorker"
+ ]
+ }
+ }
+ ],
+ "customNetworkInterfaceName": "[format('nic-{0}', parameters('automationAccountName'))]",
+ "subnet": {
+ "id": "[parameters('subnetResourceId')]"
+ }
+ },
+ "dependsOn": [
+ "[resourceId('Microsoft.Automation/automationAccounts', parameters('automationAccountName'))]"
+ ]
+ },
+ {
+ "type": "Microsoft.Network/privateEndpoints/privateDnsZoneGroups",
+ "apiVersion": "2023-05-01",
+ "name": "[format('{0}/{1}', variables('privateEndpointName'), 'default')]",
+ "properties": {
+ "privateDnsZoneConfigs": [
+ {
+ "name": "privatelink-azure-automation-net",
+ "properties": {
+ "privateDnsZoneId": "[parameters('automationAccountPrivateDnsZoneResourceId')]"
+ }
+ }
+ ]
+ },
+ "dependsOn": [
+ "[resourceId('Microsoft.Network/privateEndpoints', variables('privateEndpointName'))]"
+ ]
+ },
+ {
+ "type": "Microsoft.Compute/virtualMachines/runCommands",
+ "apiVersion": "2023-07-01",
+ "name": "[format('{0}/{1}', parameters('managementVirtualMachineName'), 'runbook')]",
+ "location": "[parameters('location')]",
+ "tags": "[if(contains(parameters('tags'), 'Microsoft.Compute/virtualMachines'), parameters('tags')['Microsoft.Compute/virtualMachines'], createObject())]",
+ "properties": {
+ "treatFailureAsDeploymentFailure": true,
+ "asyncExecution": false,
+ "parameters": [
+ {
+ "name": "AutomationAccountName",
+ "value": "[parameters('automationAccountName')]"
+ },
+ {
+ "name": "ContainerName",
+ "value": "[parameters('containerName')]"
+ },
+ {
+ "name": "Environment",
+ "value": "[environment().name]"
+ },
+ {
+ "name": "ResourceGroupName",
+ "value": "[resourceGroup().name]"
+ },
+ {
+ "name": "RunbookName",
+ "value": "[variables('runbookName')]"
+ },
+ {
+ "name": "StorageAccountName",
+ "value": "[split(parameters('storageAccountResourceId'), '/')[8]]"
+ },
+ {
+ "name": "StorageEndpoint",
+ "value": "[variables('storageEndpoint')]"
+ },
+ {
+ "name": "SubscriptionId",
+ "value": "[subscription().subscriptionId]"
+ },
+ {
+ "name": "TenantId",
+ "value": "[tenant().tenantId]"
+ },
+ {
+ "name": "UserAssignedIdentityClientId",
+ "value": "[parameters('userAssignedIdentityClientId')]"
+ },
+ {
+ "name": "UserAssignedIdentityObjectId",
+ "value": "[parameters('userAssignedIdentityPrincipalId')]"
+ }
+ ],
+ "source": {
+ "script": " param (\r\n [string]$AutomationAccountName,\r\n [string]$ContainerName,\r\n [string]$Environment,\r\n [string]$ResourceGroupName,\r\n [string]$RunbookName,\r\n [string]$StorageAccountName,\r\n [string]$StorageEndpoint,\r\n [string]$SubscriptionId,\r\n [string]$TenantId,\r\n [string]$UserAssignedIdentityClientId,\r\n [string]$UserAssignedIdentityObjectId\r\n )\r\n $ErrorActionPreference = 'Stop'\r\n $WarningPreference = 'SilentlyContinue'\r\n $BlobName = 'New-AzureZeroTrustImageBuild.ps1'\r\n $StorageAccountUrl = \"https://\" + $StorageAccountName + \".blob.\" + $StorageEndpoint + \"/\"\r\n $TokenUri = \"http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=$StorageAccountUrl&object_id=$UserAssignedIdentityObjectId\"\r\n $AccessToken = ((Invoke-WebRequest -Headers @{Metadata=$true} -Uri $TokenUri -UseBasicParsing).Content | ConvertFrom-Json).access_token\r\n $File = \"$env:windir\\temp\\$BlobName\"\r\n do\r\n {\r\n try\r\n {\r\n Write-Output \"Download Attempt $i\"\r\n Invoke-WebRequest -Headers @{\"x-ms-version\"=\"2017-11-09\"; Authorization =\"Bearer $AccessToken\"} -Uri \"$StorageAccountUrl$ContainerName/$BlobName\" -OutFile $File\r\n }\r\n catch [System.Net.WebException]\r\n {\r\n Start-Sleep -Seconds 60\r\n $i++\r\n if($i -gt 10){throw}\r\n continue\r\n }\r\n catch\r\n {\r\n $Output = $_ | select *\r\n Write-Output $Output\r\n throw\r\n }\r\n }\r\n until(Test-Path -Path $File)\r\n Connect-AzAccount -Environment $Environment -Tenant $TenantId -Subscription $SubscriptionId -Identity -AccountId $UserAssignedIdentityClientId | Out-Null\r\n Import-AzAutomationRunbook -Name $RunbookName -Path $File -Type PowerShell -AutomationAccountName $AutomationAccountName -ResourceGroupName $ResourceGroupName -Published -Force | Out-Null\r\n "
+ }
+ }
+ },
+ {
+ "type": "Microsoft.Automation/automationAccounts/schedules",
+ "apiVersion": "2022-08-08",
+ "name": "[format('{0}/{1}', parameters('automationAccountName'), parameters('imageDefinitionName'))]",
+ "properties": {
+ "frequency": "Day",
+ "interval": 1,
+ "startTime": "[dateTimeAdd(parameters('time'), 'P1D')]",
+ "timeZone": "[parameters('timeZone')]"
+ },
+ "dependsOn": [
+ "[resourceId('Microsoft.Automation/automationAccounts', parameters('automationAccountName'))]"
+ ]
+ },
+ {
+ "type": "Microsoft.Automation/automationAccounts/jobSchedules",
+ "apiVersion": "2022-08-08",
+ "name": "[format('{0}/{1}', parameters('automationAccountName'), parameters('jobScheduleName'))]",
+ "properties": {
+ "parameters": {
+ "parameters": "[replace(string(variables('parameters')), '\"', '\\\"')]"
+ },
+ "runbook": {
+ "name": "[variables('runbookName')]"
+ },
+ "runOn": "Zero Trust Image Build Automation",
+ "schedule": {
+ "name": "[parameters('imageDefinitionName')]"
+ }
+ },
+ "dependsOn": [
+ "[resourceId('Microsoft.Automation/automationAccounts', parameters('automationAccountName'))]",
+ "[resourceId('Microsoft.Automation/automationAccounts/hybridRunbookWorkerGroups', parameters('automationAccountName'), 'Zero Trust Image Build Automation')]",
+ "[resourceId('Microsoft.Compute/virtualMachines/runCommands', parameters('managementVirtualMachineName'), 'runbook')]",
+ "[resourceId('Microsoft.Automation/automationAccounts/schedules', parameters('automationAccountName'), parameters('imageDefinitionName'))]"
+ ]
+ },
+ {
+ "type": "Microsoft.Automation/automationAccounts/hybridRunbookWorkerGroups",
+ "apiVersion": "2022-08-08",
+ "name": "[format('{0}/{1}', parameters('automationAccountName'), 'Zero Trust Image Build Automation')]",
+ "dependsOn": [
+ "[resourceId('Microsoft.Automation/automationAccounts', parameters('automationAccountName'))]"
+ ]
+ },
+ {
+ "type": "Microsoft.Automation/automationAccounts/hybridRunbookWorkerGroups/hybridRunbookWorkers",
+ "apiVersion": "2022-08-08",
+ "name": "[format('{0}/{1}/{2}', parameters('automationAccountName'), 'Zero Trust Image Build Automation', guid(resourceId('Microsoft.Automation/automationAccounts/hybridRunbookWorkerGroups', parameters('automationAccountName'), 'Zero Trust Image Build Automation')))]",
+ "properties": {
+ "vmResourceId": "[resourceId('Microsoft.Compute/virtualMachines', parameters('managementVirtualMachineName'))]"
+ },
+ "dependsOn": [
+ "[resourceId('Microsoft.Automation/automationAccounts/hybridRunbookWorkerGroups', parameters('automationAccountName'), 'Zero Trust Image Build Automation')]",
+ "[resourceId('Microsoft.Compute/virtualMachines/runCommands', parameters('managementVirtualMachineName'), 'runbook')]"
+ ]
+ },
+ {
+ "type": "Microsoft.Compute/virtualMachines/extensions",
+ "apiVersion": "2022-03-01",
+ "name": "[format('{0}/{1}', parameters('managementVirtualMachineName'), 'HybridWorkerForWindows')]",
+ "location": "[parameters('location')]",
+ "tags": "[if(contains(parameters('tags'), 'Microsoft.Compute/virtualMachines'), parameters('tags')['Microsoft.Compute/virtualMachines'], createObject())]",
+ "properties": {
+ "publisher": "Microsoft.Azure.Automation.HybridWorker",
+ "type": "HybridWorkerForWindows",
+ "typeHandlerVersion": "1.1",
+ "autoUpgradeMinorVersion": true,
+ "enableAutomaticUpgrade": true,
+ "settings": {
+ "AutomationAccountURL": "[reference(resourceId('Microsoft.Automation/automationAccounts', parameters('automationAccountName')), '2022-08-08').automationHybridServiceUrl]"
+ }
+ },
+ "dependsOn": [
+ "[resourceId('Microsoft.Automation/automationAccounts', parameters('automationAccountName'))]",
+ "[resourceId('Microsoft.Compute/virtualMachines/runCommands', parameters('managementVirtualMachineName'), 'runbook')]"
+ ]
+ },
+ {
+ "condition": "[and(and(not(empty(parameters('domainJoinUserPrincipalName'))), not(empty(parameters('domainName')))), not(empty(parameters('oUPath'))))]",
+ "type": "Microsoft.Compute/virtualMachines/extensions",
+ "apiVersion": "2021-03-01",
+ "name": "[format('{0}/{1}', parameters('managementVirtualMachineName'), 'JsonADDomainExtension')]",
+ "location": "[parameters('location')]",
+ "tags": "[if(contains(parameters('tags'), 'Microsoft.Compute/virtualMachines'), parameters('tags')['Microsoft.Compute/virtualMachines'], createObject())]",
+ "properties": {
+ "forceUpdateTag": "[parameters('time')]",
+ "publisher": "Microsoft.Compute",
+ "type": "JsonADDomainExtension",
+ "typeHandlerVersion": "1.3",
+ "autoUpgradeMinorVersion": true,
+ "settings": {
+ "Name": "[parameters('domainName')]",
+ "User": "[parameters('domainJoinUserPrincipalName')]",
+ "Restart": "true",
+ "Options": "3",
+ "OUPath": "[parameters('oUPath')]"
+ },
+ "protectedSettings": {
+ "Password": "[parameters('domainJoinPassword')]"
+ }
+ },
+ "dependsOn": [
+ "[resourceId('Microsoft.Compute/virtualMachines/extensions', parameters('managementVirtualMachineName'), 'HybridWorkerForWindows')]",
+ "[resourceId('Microsoft.Compute/virtualMachines/runCommands', parameters('managementVirtualMachineName'), 'runbook')]"
+ ]
+ },
+ {
+ "condition": "[and(and(not(empty(parameters('logAnalyticsWorkspaceResourceId'))), not(empty(parameters('distributionGroup')))), not(empty(parameters('actionGroupName'))))]",
+ "type": "Microsoft.Resources/deployments",
+ "apiVersion": "2022-09-01",
+ "name": "[format('monitoring-{0}', parameters('deploymentNameSuffix'))]",
+ "properties": {
+ "expressionEvaluationOptions": {
+ "scope": "inner"
+ },
+ "mode": "Incremental",
+ "parameters": {
+ "actionGroupName": {
+ "value": "[parameters('actionGroupName')]"
+ },
+ "automationAccountName": {
+ "value": "[parameters('automationAccountName')]"
+ },
+ "distributionGroup": {
+ "value": "[parameters('distributionGroup')]"
+ },
+ "location": {
+ "value": "[parameters('location')]"
+ },
+ "logAnalyticsWorkspaceResourceId": {
+ "value": "[parameters('logAnalyticsWorkspaceResourceId')]"
+ },
+ "tags": {
+ "value": "[parameters('tags')]"
+ }
+ },
+ "template": {
+ "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
+ "contentVersion": "1.0.0.0",
+ "metadata": {
+ "_generator": {
+ "name": "bicep",
+ "version": "0.24.24.22086",
+ "templateHash": "4235135717413422630"
+ }
+ },
+ "parameters": {
+ "actionGroupName": {
+ "type": "string"
+ },
+ "automationAccountName": {
+ "type": "string"
+ },
+ "distributionGroup": {
+ "type": "string"
+ },
+ "location": {
+ "type": "string"
+ },
+ "logAnalyticsWorkspaceResourceId": {
+ "type": "string"
+ },
+ "tags": {
+ "type": "object"
+ }
+ },
+ "variables": {
+ "alerts": [
+ {
+ "name": "[format('Zero Trust Image Build - Failure ({0})', parameters('automationAccountName'))]",
+ "description": "Sends an error alert when the runbook build fails.",
+ "severity": 0,
+ "evaluationFrequency": "PT5M",
+ "windowSize": "PT5M",
+ "criteria": {
+ "allOf": [
+ {
+ "query": "AzureDiagnostics\n| where ResourceProvider == \"MICROSOFT.AUTOMATION\"\n| where Category == \"JobStreams\"\n| where ResultDescription has \"Image build failed\"",
+ "timeAggregation": "Count",
+ "dimensions": [
+ {
+ "name": "ResultDescription",
+ "operator": "Include",
+ "values": [
+ "*"
+ ]
+ }
+ ],
+ "operator": "GreaterThanOrEqual",
+ "threshold": 1,
+ "failingPeriods": {
+ "numberOfEvaluationPeriods": 1,
+ "minFailingPeriodsToAlert": 1
+ }
+ }
+ ]
+ }
+ },
+ {
+ "name": "[format('Zero Trust Image Build - Success ({0})', parameters('automationAccountName'))]",
+ "description": "Sends an informational alert when the runbook build succeeds.",
+ "severity": 3,
+ "evaluationFrequency": "PT5M",
+ "windowSize": "PT5M",
+ "criteria": {
+ "allOf": [
+ {
+ "query": "AzureDiagnostics\n| where ResourceProvider == \"MICROSOFT.AUTOMATION\"\n| where Category == \"JobStreams\"\n| where ResultDescription has \"Image build succeeded\"",
+ "timeAggregation": "Count",
+ "dimensions": [
+ {
+ "name": "ResultDescription",
+ "operator": "Include",
+ "values": [
+ "*"
+ ]
+ }
+ ],
+ "operator": "GreaterThanOrEqual",
+ "threshold": 1,
+ "failingPeriods": {
+ "numberOfEvaluationPeriods": 1,
+ "minFailingPeriodsToAlert": 1
+ }
+ }
+ ]
+ }
+ }
+ ]
+ },
+ "resources": [
+ {
+ "type": "Microsoft.Insights/diagnosticSettings",
+ "apiVersion": "2017-05-01-preview",
+ "scope": "[format('Microsoft.Automation/automationAccounts/{0}', parameters('automationAccountName'))]",
+ "name": "[format('diag-{0}', parameters('automationAccountName'))]",
+ "properties": {
+ "logs": [
+ {
+ "category": "JobLogs",
+ "enabled": true
+ },
+ {
+ "category": "JobStreams",
+ "enabled": true
+ }
+ ],
+ "workspaceId": "[parameters('logAnalyticsWorkspaceResourceId')]"
+ }
+ },
+ {
+ "condition": "[and(not(empty(parameters('actionGroupName'))), not(empty(parameters('distributionGroup'))))]",
+ "type": "Microsoft.Insights/actionGroups",
+ "apiVersion": "2022-06-01",
+ "name": "[parameters('actionGroupName')]",
+ "location": "global",
+ "tags": "[if(contains(parameters('tags'), 'Microsoft.Insights/actionGroups'), parameters('tags')['Microsoft.Insights/actionGroups'], createObject())]",
+ "properties": {
+ "emailReceivers": [
+ {
+ "emailAddress": "[parameters('distributionGroup')]",
+ "name": "[parameters('distributionGroup')]",
+ "useCommonAlertSchema": true
+ }
+ ],
+ "enabled": true,
+ "groupShortName": "Image Builds"
+ }
+ },
+ {
+ "copy": {
+ "name": "scheduledQueryRules",
+ "count": "[length(range(0, length(variables('alerts'))))]"
+ },
+ "condition": "[and(not(empty(parameters('actionGroupName'))), not(empty(parameters('logAnalyticsWorkspaceResourceId'))))]",
+ "type": "Microsoft.Insights/scheduledQueryRules",
+ "apiVersion": "2022-06-15",
+ "name": "[variables('alerts')[range(0, length(variables('alerts')))[copyIndex()]].name]",
+ "location": "[parameters('location')]",
+ "tags": "[if(contains(parameters('tags'), 'Microsoft.Insights/scheduledQueryRules'), parameters('tags')['Microsoft.Insights/scheduledQueryRules'], createObject())]",
+ "kind": "LogAlert",
+ "properties": {
+ "actions": {
+ "actionGroups": [
+ "[resourceId('Microsoft.Insights/actionGroups', parameters('actionGroupName'))]"
+ ]
+ },
+ "autoMitigate": false,
+ "skipQueryValidation": false,
+ "criteria": "[variables('alerts')[range(0, length(variables('alerts')))[copyIndex()]].criteria]",
+ "description": "[variables('alerts')[range(0, length(variables('alerts')))[copyIndex()]].description]",
+ "displayName": "[variables('alerts')[range(0, length(variables('alerts')))[copyIndex()]].name]",
+ "enabled": true,
+ "evaluationFrequency": "[variables('alerts')[range(0, length(variables('alerts')))[copyIndex()]].evaluationFrequency]",
+ "severity": "[variables('alerts')[range(0, length(variables('alerts')))[copyIndex()]].severity]",
+ "windowSize": "[variables('alerts')[range(0, length(variables('alerts')))[copyIndex()]].windowSize]",
+ "scopes": [
+ "[parameters('logAnalyticsWorkspaceResourceId')]"
+ ]
+ },
+ "dependsOn": [
+ "[resourceId('Microsoft.Insights/actionGroups', parameters('actionGroupName'))]"
+ ]
+ }
+ ]
+ }
+ },
+ "dependsOn": [
+ "[resourceId('Microsoft.Automation/automationAccounts', parameters('automationAccountName'))]"
+ ]
+ }
+ ]
+ }
+ },
+ "dependsOn": [
+ "[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('subscriptionId'), parameters('resourceGroupName')), 'Microsoft.Resources/deployments', format('management-vm-{0}', parameters('deploymentNameSuffix')))]",
+ "[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('subscriptionId'), parameters('resourceGroupName')), 'Microsoft.Resources/deployments', format('template-spec-{0}', parameters('deploymentNameSuffix')))]"
+ ]
+ }
+ ]
+ }
+ },
+ "dependsOn": [
+ "[subscriptionResourceId('Microsoft.Resources/deployments', format('baseline-{0}', parameters('deploymentNameSuffix')))]",
+ "[subscriptionResourceId('Microsoft.Resources/resourceGroups', parameters('resourceGroupName'))]",
+ "[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', variables('subscriptionId'), if(parameters('existingResourceGroup'), parameters('resourceGroupName'), parameters('resourceGroupName'))), 'Microsoft.Resources/deployments', format('tier3-{0}', parameters('deploymentNameSuffix')))]"
+ ]
+ },
+ {
+ "type": "Microsoft.Resources/deployments",
+ "apiVersion": "2022-09-01",
+ "name": "[format('image-build-{0}', parameters('deploymentNameSuffix'))]",
+ "subscriptionId": "[variables('subscriptionId')]",
+ "resourceGroup": "[if(parameters('existingResourceGroup'), parameters('resourceGroupName'), parameters('resourceGroupName'))]",
+ "properties": {
+ "expressionEvaluationOptions": {
+ "scope": "inner"
+ },
+ "mode": "Incremental",
+ "parameters": {
+ "arcGisProInstaller": {
+ "value": "[parameters('arcGisProInstaller')]"
+ },
+ "computeGalleryImageResourceId": {
+ "value": "[parameters('computeGalleryImageResourceId')]"
+ },
+ "computeGalleryName": {
+ "value": "[parameters('computeGalleryName')]"
+ },
+ "containerName": {
+ "value": "[parameters('containerName')]"
+ },
+ "customizations": {
+ "value": "[parameters('customizations')]"
+ },
+ "deploymentNameSuffix": {
+ "value": "[parameters('deploymentNameSuffix')]"
+ },
+ "diskEncryptionSetResourceId": {
+ "value": "[parameters('diskEncryptionSetResourceId')]"
+ },
+ "enableBuildAutomation": {
+ "value": "[parameters('enableBuildAutomation')]"
+ },
+ "excludeFromLatest": {
+ "value": "[parameters('excludeFromLatest')]"
+ },
+ "hybridUseBenefit": {
+ "value": "[parameters('hybridUseBenefit')]"
+ },
+ "imageDefinitionName": {
+ "value": "[variables('imageDefinitionName')]"
+ },
+ "imageMajorVersion": {
+ "value": "[parameters('imageMajorVersion')]"
+ },
+ "imageMinorVersion": {
+ "value": "[parameters('imageMinorVersion')]"
+ },
+ "imageVirtualMachineName": {
+ "value": "[variables('imageVirtualMachineName')]"
+ },
+ "installAccess": {
+ "value": "[parameters('installAccess')]"
+ },
+ "installArcGisPro": {
+ "value": "[parameters('installArcGisPro')]"
+ },
+ "installExcel": {
+ "value": "[parameters('installExcel')]"
+ },
+ "installOneDrive": {
+ "value": "[parameters('installOneDrive')]"
+ },
+ "installOneNote": {
+ "value": "[parameters('installOneNote')]"
+ },
+ "installOutlook": {
+ "value": "[parameters('installOutlook')]"
+ },
+ "installPowerPoint": {
+ "value": "[parameters('installPowerPoint')]"
+ },
+ "installProject": {
+ "value": "[parameters('installProject')]"
+ },
+ "installPublisher": {
+ "value": "[parameters('installPublisher')]"
+ },
+ "installSkypeForBusiness": {
+ "value": "[parameters('installSkypeForBusiness')]"
+ },
+ "installTeams": {
+ "value": "[parameters('installTeams')]"
+ },
+ "installVirtualDesktopOptimizationTool": {
+ "value": "[parameters('installVirtualDesktopOptimizationTool')]"
+ },
+ "installVisio": {
+ "value": "[parameters('installVisio')]"
+ },
+ "installWord": {
+ "value": "[parameters('installWord')]"
+ },
+ "keyVaultName": {
+ "value": "[parameters('keyVaultName')]"
+ },
+ "localAdministratorPassword": {
+ "value": "[parameters('localAdministratorPassword')]"
+ },
+ "localAdministratorUsername": {
+ "value": "[parameters('localAdministratorUsername')]"
+ },
+ "location": {
+ "value": "[parameters('location')]"
+ },
+ "managementVirtualMachineName": {
+ "value": "[variables('managementVirtualMachineName')]"
+ },
+ "marketplaceImageOffer": {
+ "value": "[parameters('marketplaceImageOffer')]"
+ },
+ "marketplaceImagePublisher": {
+ "value": "[parameters('marketplaceImagePublisher')]"
+ },
+ "marketplaceImageSKU": {
+ "value": "[parameters('marketplaceImageSKU')]"
+ },
+ "msrdcwebrtcsvcInstaller": {
+ "value": "[parameters('msrdcwebrtcsvcInstaller')]"
+ },
+ "officeInstaller": {
+ "value": "[parameters('officeInstaller')]"
+ },
+ "replicaCount": {
+ "value": "[parameters('replicaCount')]"
+ },
+ "sourceImageType": {
+ "value": "[parameters('sourceImageType')]"
+ },
+ "storageAccountResourceId": {
+ "value": "[parameters('storageAccountResourceId')]"
+ },
+ "subnetResourceId": {
+ "value": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', variables('subscriptionId'), if(parameters('existingResourceGroup'), parameters('resourceGroupName'), parameters('resourceGroupName'))), 'Microsoft.Resources/deployments', format('tier3-{0}', parameters('deploymentNameSuffix'))), '2022-09-01').outputs.subnetResourceId.value]"
+ },
+ "tags": {
+ "value": "[parameters('tags')]"
+ },
+ "teamsInstaller": {
+ "value": "[parameters('teamsInstaller')]"
+ },
+ "userAssignedIdentityClientId": {
+ "value": "[reference(subscriptionResourceId('Microsoft.Resources/deployments', format('baseline-{0}', parameters('deploymentNameSuffix'))), '2022-09-01').outputs.userAssignedIdentityClientId.value]"
+ },
+ "userAssignedIdentityPrincipalId": {
+ "value": "[reference(subscriptionResourceId('Microsoft.Resources/deployments', format('baseline-{0}', parameters('deploymentNameSuffix'))), '2022-09-01').outputs.userAssignedIdentityPrincipalId.value]"
+ },
+ "userAssignedIdentityResourceId": {
+ "value": "[reference(subscriptionResourceId('Microsoft.Resources/deployments', format('baseline-{0}', parameters('deploymentNameSuffix'))), '2022-09-01').outputs.userAssignedIdentityResourceId.value]"
+ },
+ "vcRedistInstaller": {
+ "value": "[parameters('vcRedistInstaller')]"
+ },
+ "vDOTInstaller": {
+ "value": "[parameters('vDOTInstaller')]"
+ },
+ "virtualMachineSize": {
+ "value": "[parameters('virtualMachineSize')]"
+ }
+ },
+ "template": {
+ "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
+ "contentVersion": "1.0.0.0",
+ "metadata": {
+ "_generator": {
+ "name": "bicep",
+ "version": "0.24.24.22086",
+ "templateHash": "5352929328757799648"
+ }
+ },
+ "parameters": {
+ "arcGisProInstaller": {
+ "type": "string",
+ "defaultValue": ""
+ },
+ "computeGalleryImageResourceId": {
+ "type": "string",
+ "defaultValue": ""
+ },
+ "computeGalleryName": {
+ "type": "string"
+ },
+ "containerName": {
+ "type": "string"
+ },
+ "customizations": {
+ "type": "array",
+ "defaultValue": []
+ },
+ "deploymentNameSuffix": {
+ "type": "string",
+ "defaultValue": "[utcNow('yyMMddHHs')]"
+ },
+ "diskEncryptionSetResourceId": {
+ "type": "string"
+ },
+ "enableBuildAutomation": {
+ "type": "bool",
+ "defaultValue": false
+ },
+ "excludeFromLatest": {
+ "type": "bool",
+ "defaultValue": true
+ },
+ "hybridUseBenefit": {
+ "type": "bool",
+ "defaultValue": false
+ },
+ "imageDefinitionName": {
+ "type": "string"
+ },
+ "imageMajorVersion": {
+ "type": "int"
+ },
+ "imageMinorVersion": {
+ "type": "int"
+ },
+ "imageVirtualMachineName": {
+ "type": "string"
+ },
+ "installAccess": {
+ "type": "bool",
+ "defaultValue": false
+ },
+ "installArcGisPro": {
+ "type": "bool",
+ "defaultValue": false
+ },
+ "installExcel": {
+ "type": "bool",
+ "defaultValue": false
+ },
+ "installOneDrive": {
+ "type": "bool",
+ "defaultValue": false
+ },
+ "installOneNote": {
+ "type": "bool",
+ "defaultValue": false
+ },
+ "installOutlook": {
+ "type": "bool",
+ "defaultValue": false
+ },
+ "installPowerPoint": {
+ "type": "bool",
+ "defaultValue": false
+ },
+ "installProject": {
+ "type": "bool",
+ "defaultValue": false
+ },
+ "installPublisher": {
+ "type": "bool",
+ "defaultValue": false
+ },
+ "installSkypeForBusiness": {
+ "type": "bool",
+ "defaultValue": false
+ },
+ "installTeams": {
+ "type": "bool",
+ "defaultValue": false
+ },
+ "installVirtualDesktopOptimizationTool": {
+ "type": "bool",
+ "defaultValue": false
+ },
+ "installVisio": {
+ "type": "bool",
+ "defaultValue": false
+ },
+ "installWord": {
+ "type": "bool",
+ "defaultValue": false
+ },
+ "keyVaultName": {
+ "type": "string"
+ },
+ "localAdministratorPassword": {
+ "type": "securestring",
+ "defaultValue": ""
+ },
+ "localAdministratorUsername": {
+ "type": "securestring",
+ "defaultValue": ""
+ },
+ "location": {
+ "type": "string",
+ "defaultValue": "[resourceGroup().location]"
+ },
+ "managementVirtualMachineName": {
+ "type": "string"
+ },
+ "marketplaceImageOffer": {
+ "type": "string"
+ },
+ "marketplaceImagePublisher": {
+ "type": "string"
+ },
+ "marketplaceImageSKU": {
+ "type": "string"
+ },
+ "msrdcwebrtcsvcInstaller": {
+ "type": "string",
+ "defaultValue": ""
+ },
+ "officeInstaller": {
+ "type": "string",
+ "defaultValue": ""
+ },
+ "replicaCount": {
+ "type": "int",
+ "defaultValue": 1
+ },
+ "runbookExecution": {
+ "type": "bool",
+ "defaultValue": false
+ },
+ "sourceImageType": {
+ "type": "string",
+ "defaultValue": "AzureMarketplace"
+ },
+ "storageAccountResourceId": {
+ "type": "string"
+ },
+ "subnetResourceId": {
+ "type": "string"
+ },
+ "tags": {
+ "type": "object",
+ "defaultValue": {}
+ },
+ "teamsInstaller": {
+ "type": "string",
+ "defaultValue": ""
+ },
+ "userAssignedIdentityClientId": {
+ "type": "string"
+ },
+ "userAssignedIdentityPrincipalId": {
+ "type": "string"
+ },
+ "userAssignedIdentityResourceId": {
+ "type": "string"
+ },
+ "vcRedistInstaller": {
+ "type": "string",
+ "defaultValue": ""
+ },
+ "vDOTInstaller": {
+ "type": "string",
+ "defaultValue": ""
+ },
+ "virtualMachineSize": {
+ "type": "string"
+ }
+ },
+ "variables": {
+ "autoImageVersion": "[format('{0}.{1}.{2}', parameters('imageMajorVersion'), variables('imageSuffix'), parameters('imageMinorVersion'))]",
+ "imageSuffix": "[take(parameters('deploymentNameSuffix'), 9)]",
+ "resourceGroupName": "[resourceGroup().name]",
+ "storageAccountName": "[split(parameters('storageAccountResourceId'), '/')[8]]",
+ "storageEndpoint": "[environment().suffixes.storage]",
+ "subscriptionId": "[subscription().subscriptionId]"
+ },
+ "resources": [
+ {
+ "condition": "[not(parameters('enableBuildAutomation'))]",
+ "type": "Microsoft.Resources/deployments",
+ "apiVersion": "2022-09-01",
+ "name": "[format('management-vm-{0}', parameters('deploymentNameSuffix'))]",
+ "subscriptionId": "[variables('subscriptionId')]",
+ "resourceGroup": "[variables('resourceGroupName')]",
+ "properties": {
+ "expressionEvaluationOptions": {
+ "scope": "inner"
+ },
+ "mode": "Incremental",
+ "parameters": {
+ "containerName": {
+ "value": "[parameters('containerName')]"
+ },
+ "diskEncryptionSetResourceId": {
+ "value": "[parameters('diskEncryptionSetResourceId')]"
+ },
+ "hybridUseBenefit": {
+ "value": "[parameters('hybridUseBenefit')]"
+ },
+ "localAdministratorPassword": {
+ "value": "[parameters('localAdministratorPassword')]"
+ },
+ "localAdministratorUsername": {
+ "value": "[parameters('localAdministratorUsername')]"
+ },
+ "location": {
+ "value": "[parameters('location')]"
+ },
+ "storageAccountName": {
+ "value": "[split(parameters('storageAccountResourceId'), '/')[8]]"
+ },
+ "subnetResourceId": {
+ "value": "[parameters('subnetResourceId')]"
+ },
+ "tags": {
+ "value": "[parameters('tags')]"
+ },
+ "userAssignedIdentityPrincipalId": {
+ "value": "[parameters('userAssignedIdentityPrincipalId')]"
+ },
+ "userAssignedIdentityResourceId": {
+ "value": "[parameters('userAssignedIdentityResourceId')]"
+ },
+ "virtualMachineName": {
+ "value": "[parameters('managementVirtualMachineName')]"
+ }
+ },
+ "template": {
+ "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
+ "contentVersion": "1.0.0.0",
+ "metadata": {
+ "_generator": {
+ "name": "bicep",
+ "version": "0.24.24.22086",
+ "templateHash": "5351463014152522794"
+ }
+ },
+ "parameters": {
+ "containerName": {
+ "type": "string"
+ },
+ "diskEncryptionSetResourceId": {
+ "type": "string"
+ },
+ "hybridUseBenefit": {
+ "type": "bool"
+ },
+ "localAdministratorPassword": {
+ "type": "securestring"
+ },
+ "localAdministratorUsername": {
+ "type": "securestring"
+ },
+ "location": {
+ "type": "string"
+ },
+ "storageAccountName": {
+ "type": "string"
+ },
+ "subnetResourceId": {
+ "type": "string"
+ },
+ "tags": {
+ "type": "object"
+ },
+ "userAssignedIdentityPrincipalId": {
+ "type": "string"
+ },
+ "userAssignedIdentityResourceId": {
+ "type": "string"
+ },
+ "virtualMachineName": {
+ "type": "string"
+ }
+ },
+ "resources": [
+ {
+ "type": "Microsoft.Network/networkInterfaces",
+ "apiVersion": "2023-04-01",
+ "name": "[format('nic-{0}', parameters('virtualMachineName'))]",
+ "location": "[parameters('location')]",
+ "tags": "[if(contains(parameters('tags'), 'Microsoft.Network/networkInterfaces'), parameters('tags')['Microsoft.Network/networkInterfaces'], createObject())]",
+ "properties": {
+ "ipConfigurations": [
+ {
+ "name": "ipconfig",
+ "properties": {
+ "privateIPAllocationMethod": "Dynamic",
+ "subnet": {
+ "id": "[parameters('subnetResourceId')]"
+ },
+ "primary": true,
+ "privateIPAddressVersion": "IPv4"
+ }
+ }
+ ],
+ "enableAcceleratedNetworking": true,
+ "enableIPForwarding": false
+ }
+ },
+ {
+ "type": "Microsoft.Compute/virtualMachines",
+ "apiVersion": "2022-03-01",
+ "name": "[parameters('virtualMachineName')]",
+ "location": "[parameters('location')]",
+ "tags": "[if(contains(parameters('tags'), 'Microsoft.Compute/virtualMachines'), parameters('tags')['Microsoft.Compute/virtualMachines'], createObject())]",
+ "identity": {
+ "type": "UserAssigned",
+ "userAssignedIdentities": {
+ "[format('{0}', parameters('userAssignedIdentityResourceId'))]": {}
+ }
+ },
+ "properties": {
+ "hardwareProfile": {
+ "vmSize": "Standard_D2s_v3"
+ },
+ "osProfile": {
+ "computerName": "[parameters('virtualMachineName')]",
+ "adminUsername": "[parameters('localAdministratorUsername')]",
+ "adminPassword": "[parameters('localAdministratorPassword')]",
+ "windowsConfiguration": {
+ "provisionVMAgent": true,
+ "enableAutomaticUpdates": true,
+ "patchSettings": {
+ "patchMode": "AutomaticByOS",
+ "assessmentMode": "ImageDefault"
+ }
+ }
+ },
+ "storageProfile": {
+ "imageReference": {
+ "publisher": "MicrosoftWindowsServer",
+ "offer": "WindowsServer",
+ "sku": "2019-datacenter-core-g2",
+ "version": "latest"
+ },
+ "osDisk": {
+ "caching": "ReadWrite",
+ "createOption": "FromImage",
+ "deleteOption": "Delete",
+ "managedDisk": {
+ "diskEncryptionSet": {
+ "id": "[parameters('diskEncryptionSetResourceId')]"
+ },
+ "storageAccountType": "Premium_LRS"
+ },
+ "name": "[format('disk-{0}', parameters('virtualMachineName'))]",
+ "osType": "Windows"
+ }
+ },
+ "networkProfile": {
+ "networkInterfaces": [
+ {
+ "id": "[resourceId('Microsoft.Network/networkInterfaces', format('nic-{0}', parameters('virtualMachineName')))]",
+ "properties": {
+ "deleteOption": "Delete"
+ }
+ }
+ ]
+ },
+ "diagnosticsProfile": {
+ "bootDiagnostics": {
+ "enabled": false
+ }
+ },
+ "securityProfile": {
+ "encryptionAtHost": true,
+ "uefiSettings": {
+ "secureBootEnabled": true,
+ "vTpmEnabled": true
+ },
+ "securityType": "TrustedLaunch"
+ },
+ "licenseType": "[if(parameters('hybridUseBenefit'), 'Windows_Server', null())]"
+ },
+ "dependsOn": [
+ "[resourceId('Microsoft.Network/networkInterfaces', format('nic-{0}', parameters('virtualMachineName')))]"
+ ]
+ },
+ {
+ "type": "Microsoft.Compute/virtualMachines/runCommands",
+ "apiVersion": "2023-03-01",
+ "name": "[format('{0}/{1}', parameters('virtualMachineName'), 'appAzModules')]",
+ "location": "[parameters('location')]",
+ "tags": "[if(contains(parameters('tags'), 'Microsoft.Compute/virtualMachines'), parameters('tags')['Microsoft.Compute/virtualMachines'], createObject())]",
+ "properties": {
+ "treatFailureAsDeploymentFailure": true,
+ "asyncExecution": false,
+ "parameters": [
+ {
+ "name": "ContainerName",
+ "value": "[parameters('containerName')]"
+ },
+ {
+ "name": "StorageAccountName",
+ "value": "[parameters('storageAccountName')]"
+ },
+ {
+ "name": "StorageEndpoint",
+ "value": "[environment().suffixes.storage]"
+ },
+ {
+ "name": "UserAssignedIdentityObjectId",
+ "value": "[parameters('userAssignedIdentityPrincipalId')]"
+ }
+ ],
+ "source": {
+ "script": " param(\r\n [string]$ContainerName,\r\n [string]$StorageAccountName,\r\n [string]$StorageEndpoint,\r\n [string]$UserAssignedIdentityObjectId\r\n )\r\n $ErrorActionPreference = \"Stop\"\r\n $StorageAccountUrl = \"https://\" + $StorageAccountName + \".blob.\" + $StorageEndpoint + \"/\"\r\n $TokenUri = \"http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=$StorageAccountUrl&object_id=$UserAssignedIdentityObjectId\"\r\n $AccessToken = ((Invoke-WebRequest -Headers @{Metadata=$true} -Uri $TokenUri -UseBasicParsing).Content | ConvertFrom-Json).access_token\r\n $BlobNames = @('az.accounts.2.12.1.nupkg','az.automation.1.9.0.nupkg','az.compute.5.7.0.nupkg','az.resources.6.6.0.nupkg')\r\n foreach($BlobName in $BlobNames)\r\n {\r\n do\r\n {\r\n try\r\n {\r\n Write-Output \"Download Attempt $i\"\r\n Invoke-WebRequest -Headers @{\"x-ms-version\"=\"2017-11-09\"; Authorization =\"Bearer $AccessToken\"} -Uri \"$StorageAccountUrl$ContainerName/$BlobName\" -OutFile \"$env:windir\\temp\\$BlobName\"\r\n }\r\n catch [System.Net.WebException]\r\n {\r\n Start-Sleep -Seconds 60\r\n $i++\r\n if($i -gt 10){throw}\r\n continue\r\n }\r\n catch\r\n {\r\n $Output = $_ | select *\r\n Write-Output $Output\r\n throw\r\n }\r\n }\r\n until(Test-Path -Path $env:windir\\temp\\$BlobName)\r\n Start-Sleep -Seconds 5\r\n Unblock-File -Path $env:windir\\temp\\$BlobName\r\n $BlobZipName = $Blobname.Replace('nupkg','zip')\r\n Rename-Item -Path $env:windir\\temp\\$BlobName -NewName $BlobZipName\r\n $BlobNameArray = $BlobName.Split('.')\r\n $ModuleFolderName = $BlobNameArray[0] + '.' + $BlobNameArray[1]\r\n $VersionFolderName = $BlobNameArray[2] + '.' + $BlobNameArray[3]+ '.' + $BlobNameArray[4]\r\n $ModulesDirectory = \"C:\\Program Files\\WindowsPowerShell\\Modules\"\r\n New-Item -Path $ModulesDirectory -Name $ModuleFolderName -ItemType \"Directory\" -Force\r\n Expand-Archive -Path $env:windir\\temp\\$BlobZipName -DestinationPath \"$ModulesDirectory\\$ModuleFolderName\\$VersionFolderName\" -Force\r\n Remove-Item -Path \"$ModulesDirectory\\$ModuleFolderName\\$VersionFolderName\\_rels\" -Force -Recurse\r\n Remove-Item -Path \"$ModulesDirectory\\$ModuleFolderName\\$VersionFolderName\\package\" -Force -Recurse\r\n Remove-Item -LiteralPath \"$ModulesDirectory\\$ModuleFolderName\\$VersionFolderName\\[Content_Types].xml\" -Force\r\n Remove-Item -Path \"$ModulesDirectory\\$ModuleFolderName\\$VersionFolderName\\$ModuleFolderName.nuspec\" -Force\r\n }\r\n Remove-Item -Path \"$env:windir\\temp\\az*\" -Force\r\n "
+ }
+ },
+ "dependsOn": [
+ "[resourceId('Microsoft.Compute/virtualMachines', parameters('virtualMachineName'))]"
+ ]
+ }
+ ],
+ "outputs": {
+ "name": {
+ "type": "string",
+ "value": "[parameters('virtualMachineName')]"
+ }
+ }
+ }
+ }
+ },
+ {
+ "type": "Microsoft.Resources/deployments",
+ "apiVersion": "2022-09-01",
+ "name": "[format('image-vm-{0}', parameters('deploymentNameSuffix'))]",
+ "properties": {
+ "expressionEvaluationOptions": {
+ "scope": "inner"
+ },
+ "mode": "Incremental",
+ "parameters": {
+ "localAdministratorPassword": "[if(parameters('runbookExecution'), createObject('reference', createObject('keyVault', createObject('id', resourceId('Microsoft.KeyVault/vaults', parameters('keyVaultName'))), 'secretName', 'LocalAdministratorPassword')), createObject('value', parameters('localAdministratorPassword')))]",
+ "localAdministratorUsername": "[if(parameters('runbookExecution'), createObject('reference', createObject('keyVault', createObject('id', resourceId('Microsoft.KeyVault/vaults', parameters('keyVaultName'))), 'secretName', 'LocalAdministratorUsername')), createObject('value', parameters('localAdministratorUsername')))]",
+ "location": {
+ "value": "[parameters('location')]"
+ },
+ "marketplaceImageOffer": {
+ "value": "[parameters('marketplaceImageOffer')]"
+ },
+ "marketplaceImagePublisher": {
+ "value": "[parameters('marketplaceImagePublisher')]"
+ },
+ "marketplaceImageSKU": {
+ "value": "[parameters('marketplaceImageSKU')]"
+ },
+ "computeGalleryImageResourceId": {
+ "value": "[parameters('computeGalleryImageResourceId')]"
+ },
+ "sourceImageType": {
+ "value": "[parameters('sourceImageType')]"
+ },
+ "subnetResourceId": {
+ "value": "[parameters('subnetResourceId')]"
+ },
+ "tags": {
+ "value": "[parameters('tags')]"
+ },
+ "userAssignedIdentityResourceId": {
+ "value": "[parameters('userAssignedIdentityResourceId')]"
+ },
+ "virtualMachineName": {
+ "value": "[parameters('imageVirtualMachineName')]"
+ },
+ "virtualMachineSize": {
+ "value": "[parameters('virtualMachineSize')]"
+ }
+ },
+ "template": {
+ "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
+ "contentVersion": "1.0.0.0",
+ "metadata": {
+ "_generator": {
+ "name": "bicep",
+ "version": "0.24.24.22086",
+ "templateHash": "797614681408504492"
+ }
+ },
+ "parameters": {
+ "localAdministratorPassword": {
+ "type": "securestring"
+ },
+ "localAdministratorUsername": {
+ "type": "securestring"
+ },
+ "location": {
+ "type": "string"
+ },
+ "marketplaceImageOffer": {
+ "type": "string"
+ },
+ "marketplaceImagePublisher": {
+ "type": "string"
+ },
+ "marketplaceImageSKU": {
+ "type": "string"
+ },
+ "computeGalleryImageResourceId": {
+ "type": "string"
+ },
+ "sourceImageType": {
+ "type": "string"
+ },
+ "subnetResourceId": {
+ "type": "string"
+ },
+ "tags": {
+ "type": "object"
+ },
+ "userAssignedIdentityResourceId": {
+ "type": "string"
+ },
+ "virtualMachineName": {
+ "type": "string"
+ },
+ "virtualMachineSize": {
+ "type": "string"
+ }
+ },
+ "variables": {
+ "imageReference": "[if(equals(parameters('sourceImageType'), 'AzureComputeGallery'), createObject('id', parameters('computeGalleryImageResourceId')), createObject('publisher', parameters('marketplaceImagePublisher'), 'offer', parameters('marketplaceImageOffer'), 'sku', parameters('marketplaceImageSKU'), 'version', 'latest'))]"
+ },
+ "resources": [
+ {
+ "type": "Microsoft.Network/networkInterfaces",
+ "apiVersion": "2022-05-01",
+ "name": "[format('nic-{0}', parameters('virtualMachineName'))]",
+ "location": "[parameters('location')]",
+ "tags": "[if(contains(parameters('tags'), 'Microsoft.Network/networkInterfaces'), parameters('tags')['Microsoft.Network/networkInterfaces'], createObject())]",
+ "properties": {
+ "ipConfigurations": [
+ {
+ "name": "ipconfig1",
+ "properties": {
+ "privateIPAllocationMethod": "Dynamic",
+ "subnet": {
+ "id": "[parameters('subnetResourceId')]"
+ }
+ }
+ }
+ ]
+ }
+ },
+ {
+ "type": "Microsoft.Compute/virtualMachines",
+ "apiVersion": "2022-03-01",
+ "name": "[parameters('virtualMachineName')]",
+ "location": "[parameters('location')]",
+ "tags": "[if(contains(parameters('tags'), 'Microsoft.Compute/virtualMachines'), parameters('tags')['Microsoft.Compute/virtualMachines'], createObject())]",
+ "identity": {
+ "type": "UserAssigned",
+ "userAssignedIdentities": {
+ "[format('{0}', parameters('userAssignedIdentityResourceId'))]": {}
+ }
+ },
+ "properties": {
+ "hardwareProfile": {
+ "vmSize": "[parameters('virtualMachineSize')]"
+ },
+ "osProfile": {
+ "computerName": "[parameters('virtualMachineName')]",
+ "adminUsername": "[parameters('localAdministratorUsername')]",
+ "adminPassword": "[parameters('localAdministratorPassword')]"
+ },
+ "storageProfile": {
+ "imageReference": "[variables('imageReference')]",
+ "osDisk": {
+ "createOption": "FromImage",
+ "deleteOption": "Delete",
+ "managedDisk": {
+ "storageAccountType": "StandardSSD_LRS"
+ },
+ "name": "[format('disk-{0}', parameters('virtualMachineName'))]"
+ }
+ },
+ "networkProfile": {
+ "networkInterfaces": [
+ {
+ "id": "[resourceId('Microsoft.Network/networkInterfaces', format('nic-{0}', parameters('virtualMachineName')))]",
+ "properties": {
+ "deleteOption": "Delete"
+ }
+ }
+ ]
+ },
+ "diagnosticsProfile": {
+ "bootDiagnostics": {
+ "enabled": false
+ }
+ },
+ "securityProfile": {
+ "uefiSettings": {
+ "secureBootEnabled": true,
+ "vTpmEnabled": true
+ },
+ "securityType": "TrustedLaunch"
+ }
+ },
+ "dependsOn": [
+ "[resourceId('Microsoft.Network/networkInterfaces', format('nic-{0}', parameters('virtualMachineName')))]"
+ ]
+ }
+ ],
+ "outputs": {
+ "name": {
+ "type": "string",
+ "value": "[parameters('virtualMachineName')]"
+ },
+ "resourceId": {
+ "type": "string",
+ "value": "[resourceId('Microsoft.Compute/virtualMachines', parameters('virtualMachineName'))]"
+ }
+ }
+ }
+ }
+ },
+ {
+ "type": "Microsoft.Resources/deployments",
+ "apiVersion": "2022-09-01",
+ "name": "[format('customizations-{0}', parameters('deploymentNameSuffix'))]",
+ "properties": {
+ "expressionEvaluationOptions": {
+ "scope": "inner"
+ },
+ "mode": "Incremental",
+ "parameters": {
+ "arcGisProInstaller": {
+ "value": "[parameters('arcGisProInstaller')]"
+ },
+ "containerName": {
+ "value": "[parameters('containerName')]"
+ },
+ "customizations": {
+ "value": "[parameters('customizations')]"
+ },
+ "installAccess": {
+ "value": "[parameters('installAccess')]"
+ },
+ "installArcGisPro": {
+ "value": "[parameters('installArcGisPro')]"
+ },
+ "installExcel": {
+ "value": "[parameters('installExcel')]"
+ },
+ "installOneDrive": {
+ "value": "[parameters('installOneDrive')]"
+ },
+ "installOneNote": {
+ "value": "[parameters('installOneNote')]"
+ },
+ "installOutlook": {
+ "value": "[parameters('installOutlook')]"
+ },
+ "installPowerPoint": {
+ "value": "[parameters('installPowerPoint')]"
+ },
+ "installProject": {
+ "value": "[parameters('installProject')]"
+ },
+ "installPublisher": {
+ "value": "[parameters('installPublisher')]"
+ },
+ "installSkypeForBusiness": {
+ "value": "[parameters('installSkypeForBusiness')]"
+ },
+ "installTeams": {
+ "value": "[parameters('installTeams')]"
+ },
+ "installVirtualDesktopOptimizationTool": {
+ "value": "[parameters('installVirtualDesktopOptimizationTool')]"
+ },
+ "installVisio": {
+ "value": "[parameters('installVisio')]"
+ },
+ "installWord": {
+ "value": "[parameters('installWord')]"
+ },
+ "location": {
+ "value": "[parameters('location')]"
+ },
+ "msrdcwebrtcsvcInstaller": {
+ "value": "[parameters('msrdcwebrtcsvcInstaller')]"
+ },
+ "officeInstaller": {
+ "value": "[parameters('officeInstaller')]"
+ },
+ "storageAccountName": {
+ "value": "[variables('storageAccountName')]"
+ },
+ "storageEndpoint": {
+ "value": "[variables('storageEndpoint')]"
+ },
+ "tags": {
+ "value": "[parameters('tags')]"
+ },
+ "teamsInstaller": {
+ "value": "[parameters('teamsInstaller')]"
+ },
+ "userAssignedIdentityObjectId": {
+ "value": "[parameters('userAssignedIdentityPrincipalId')]"
+ },
+ "vcRedistInstaller": {
+ "value": "[parameters('vcRedistInstaller')]"
+ },
+ "vDotInstaller": {
+ "value": "[parameters('vDOTInstaller')]"
+ },
+ "virtualMachineName": {
+ "value": "[reference(resourceId('Microsoft.Resources/deployments', format('image-vm-{0}', parameters('deploymentNameSuffix'))), '2022-09-01').outputs.name.value]"
+ }
+ },
+ "template": {
+ "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
+ "contentVersion": "1.0.0.0",
+ "metadata": {
+ "_generator": {
+ "name": "bicep",
+ "version": "0.24.24.22086",
+ "templateHash": "12702244124956355874"
+ }
+ },
+ "parameters": {
+ "arcGisProInstaller": {
+ "type": "string"
+ },
+ "containerName": {
+ "type": "string"
+ },
+ "customizations": {
+ "type": "array"
+ },
+ "installAccess": {
+ "type": "bool"
+ },
+ "installArcGisPro": {
+ "type": "bool"
+ },
+ "installExcel": {
+ "type": "bool"
+ },
+ "installOneDrive": {
+ "type": "bool"
+ },
+ "installOneNote": {
+ "type": "bool"
+ },
+ "installOutlook": {
+ "type": "bool"
+ },
+ "installPowerPoint": {
+ "type": "bool"
+ },
+ "installProject": {
+ "type": "bool"
+ },
+ "installPublisher": {
+ "type": "bool"
+ },
+ "installSkypeForBusiness": {
+ "type": "bool"
+ },
+ "installTeams": {
+ "type": "bool"
+ },
+ "installVirtualDesktopOptimizationTool": {
+ "type": "bool"
+ },
+ "installVisio": {
+ "type": "bool"
+ },
+ "installWord": {
+ "type": "bool"
+ },
+ "location": {
+ "type": "string"
+ },
+ "msrdcwebrtcsvcInstaller": {
+ "type": "string"
+ },
+ "officeInstaller": {
+ "type": "string"
+ },
+ "storageAccountName": {
+ "type": "string"
+ },
+ "storageEndpoint": {
+ "type": "string"
+ },
+ "tags": {
+ "type": "object"
+ },
+ "teamsInstaller": {
+ "type": "string"
+ },
+ "userAssignedIdentityObjectId": {
+ "type": "string"
+ },
+ "vcRedistInstaller": {
+ "type": "string"
+ },
+ "vDotInstaller": {
+ "type": "string"
+ },
+ "virtualMachineName": {
+ "type": "string"
+ }
+ },
+ "variables": {
+ "installAccessVar": "[format('{0}installAccess', parameters('installAccess'))]",
+ "installers": "[parameters('customizations')]",
+ "installExcelVar": "[format('{0}installWord', parameters('installExcel'))]",
+ "installOneDriveVar": "[format('{0}installOneDrive', parameters('installOneDrive'))]",
+ "installOneNoteVar": "[format('{0}installOneNote', parameters('installOneNote'))]",
+ "installOutlookVar": "[format('{0}installOutlook', parameters('installOutlook'))]",
+ "installPowerPointVar": "[format('{0}installPowerPoint', parameters('installPowerPoint'))]",
+ "installProjectVar": "[format('{0}installProject', parameters('installProject'))]",
+ "installPublisherVar": "[format('{0}installPublisher', parameters('installPublisher'))]",
+ "installSkypeForBusinessVar": "[format('{0}installSkypeForBusiness', parameters('installSkypeForBusiness'))]",
+ "installVisioVar": "[format('{0}installVisio', parameters('installVisio'))]",
+ "installWordVar": "[format('{0}installWord', parameters('installWord'))]"
+ },
+ "resources": [
+ {
+ "copy": {
+ "name": "applications",
+ "count": "[length(variables('installers'))]",
+ "mode": "serial",
+ "batchSize": 1
+ },
+ "type": "Microsoft.Compute/virtualMachines/runCommands",
+ "apiVersion": "2023-03-01",
+ "name": "[format('{0}/{1}', parameters('virtualMachineName'), format('app-{0}', variables('installers')[copyIndex()].name))]",
+ "location": "[parameters('location')]",
+ "tags": "[if(contains(parameters('tags'), 'Microsoft.Compute/virtualMachines'), parameters('tags')['Microsoft.Compute/virtualMachines'], createObject())]",
+ "properties": {
+ "treatFailureAsDeploymentFailure": true,
+ "asyncExecution": false,
+ "parameters": [
+ {
+ "name": "UserAssignedIdentityObjectId",
+ "value": "[parameters('userAssignedIdentityObjectId')]"
+ },
+ {
+ "name": "StorageAccountName",
+ "value": "[parameters('storageAccountName')]"
+ },
+ {
+ "name": "ContainerName",
+ "value": "[parameters('containerName')]"
+ },
+ {
+ "name": "StorageEndpoint",
+ "value": "[parameters('storageEndpoint')]"
+ },
+ {
+ "name": "Blobname",
+ "value": "[variables('installers')[copyIndex()].blobName]"
+ },
+ {
+ "name": "Installer",
+ "value": "[variables('installers')[copyIndex()].name]"
+ },
+ {
+ "name": "Arguments",
+ "value": "[variables('installers')[copyIndex()].arguments]"
+ }
+ ],
+ "source": {
+ "script": " param(\r\n [string]$UserAssignedIdentityObjectId,\r\n [string]$StorageAccountName,\r\n [string]$ContainerName,\r\n [string]$StorageEndpoint,\r\n [string]$BlobName,\r\n [string]$Installer,\r\n [string]$Arguments\r\n )\r\n $ErrorActionPreference = 'Stop'\r\n $WarningPreference = 'SilentlyContinue'\r\n $StorageAccountUrl = \"https://\" + $StorageAccountName + \".blob.\" + $StorageEndpoint + \"/\"\r\n $TokenUri = \"http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=$StorageAccountUrl&object_id=$UserAssignedIdentityObjectId\"\r\n $AccessToken = ((Invoke-WebRequest -Headers @{Metadata=$true} -Uri $TokenUri -UseBasicParsing).Content | ConvertFrom-Json).access_token\r\n New-Item -Path $env:windir\\temp -Name $Installer -ItemType \"directory\" -Force\r\n New-Item -Path $env:windir\\temp\\$Installer -Name 'Files' -ItemType \"directory\" -Force\r\n Invoke-WebRequest -Headers @{\"x-ms-version\"=\"2017-11-09\"; Authorization =\"Bearer $AccessToken\"} -Uri \"$StorageAccountUrl$ContainerName/$BlobName\" -OutFile $env:windir\\temp\\$Installer\\Files\\$Blobname\r\n Start-Sleep -Seconds 30\r\n Set-Location -Path $env:windir\\temp\\$Installer\r\n if($Blobname -like (\"*.exe\"))\r\n {\r\n Start-Process -FilePath $env:windir\\temp\\$Installer\\Files\\$Blobname -ArgumentList $Arguments -NoNewWindow -Wait -PassThru\r\n $status = Get-WmiObject -Class Win32_Product | Where-Object Name -like \"*$($installer)*\"\r\n if($status)\r\n {\r\n Write-Host $status.Name \"is installed\"\r\n }\r\n else\r\n {\r\n Write-host $Installer \"did not install properly, please check arguments\"\r\n }\r\n }\r\n if($Blobname -like (\"*.msi\"))\r\n {\r\n Set-Location -Path $env:windir\\temp\\$Installer\\Files\r\n Start-Process -FilePath msiexec.exe -ArgumentList $Arguments -Wait\r\n $status = Get-WmiObject -Class Win32_Product | Where-Object Name -like \"*$($installer)*\"\r\n if($status)\r\n {\r\n Write-Host $status.Name \"is installed\"\r\n }\r\n else\r\n {\r\n Write-host $Installer \"did not install properly, please check arguments\"\r\n }\r\n }\r\n if($Blobname -like (\"*.bat\"))\r\n {\r\n Start-Process -FilePath cmd.exe -ArgumentList $env:windir\\temp\\$Installer\\Files\\$Arguments -Wait\r\n }\r\n if($Blobname -like (\"*.ps1\"))\r\n {\r\n Start-Process -FilePath PowerShell.exe -ArgumentList $env:windir\\temp\\$Installer\\Files\\$Arguments -Wait\r\n }\r\n if($Blobname -like (\"*.zip\"))\r\n {\r\n Set-Location -Path $env:windir\\temp\\$Installer\\Files\r\n Expand-Archive -Path $env:windir\\temp\\$Installer\\Files\\$Blobname -DestinationPath $env:windir\\temp\\$Installer\\Files -Force\r\n Remove-Item -Path .\\$Blobname -Force -Recurse\r\n }\r\n Write-Host \"Removing $Installer Files\"\r\n Remove-item $env:windir\\temp\\$Installer -Force -Recurse -Confirm:$false\r\n "
+ }
+ }
+ },
+ {
+ "condition": "[or(or(or(or(or(or(or(or(or(or(parameters('installAccess'), parameters('installExcel')), parameters('installOneDrive')), parameters('installOneNote')), parameters('installOutlook')), parameters('installPowerPoint')), parameters('installPublisher')), parameters('installSkypeForBusiness')), parameters('installWord')), parameters('installVisio')), parameters('installProject'))]",
+ "type": "Microsoft.Compute/virtualMachines/runCommands",
+ "apiVersion": "2023-03-01",
+ "name": "[format('{0}/{1}', parameters('virtualMachineName'), 'office')]",
+ "location": "[parameters('location')]",
+ "tags": "[if(contains(parameters('tags'), 'Microsoft.Compute/virtualMachines'), parameters('tags')['Microsoft.Compute/virtualMachines'], createObject())]",
+ "properties": {
+ "treatFailureAsDeploymentFailure": true,
+ "asyncExecution": false,
+ "parameters": [
+ {
+ "name": "InstallAccess",
+ "value": "[variables('installAccessVar')]"
+ },
+ {
+ "name": "InstallWord",
+ "value": "[variables('installWordVar')]"
+ },
+ {
+ "name": "InstallExcel",
+ "value": "[variables('installExcelVar')]"
+ },
+ {
+ "name": "InstallOneDrive",
+ "value": "[variables('installOneDriveVar')]"
+ },
+ {
+ "name": "InstallOneNote",
+ "value": "[variables('installOneNoteVar')]"
+ },
+ {
+ "name": "InstallOutlook",
+ "value": "[variables('installOutlookVar')]"
+ },
+ {
+ "name": "InstallPowerPoint",
+ "value": "[variables('installPowerPointVar')]"
+ },
+ {
+ "name": "InstallProject",
+ "value": "[variables('installProjectVar')]"
+ },
+ {
+ "name": "InstallPublisher",
+ "value": "[variables('installPublisherVar')]"
+ },
+ {
+ "name": "InstallSkypeForBusiness",
+ "value": "[variables('installSkypeForBusinessVar')]"
+ },
+ {
+ "name": "InstallVisio",
+ "value": "[variables('installVisioVar')]"
+ },
+ {
+ "name": "UserAssignedIdentityObjectId",
+ "value": "[parameters('userAssignedIdentityObjectId')]"
+ },
+ {
+ "name": "StorageAccountName",
+ "value": "[parameters('storageAccountName')]"
+ },
+ {
+ "name": "ContainerName",
+ "value": "[parameters('containerName')]"
+ },
+ {
+ "name": "StorageEndpoint",
+ "value": "[parameters('storageEndpoint')]"
+ },
+ {
+ "name": "BlobName",
+ "value": "[parameters('officeInstaller')]"
+ }
+ ],
+ "source": {
+ "script": " param(\r\n [string]$InstallAccess,\r\n [string]$InstallExcel,\r\n [string]$InstallOneDrive,\r\n [string]$InstallOutlook,\r\n [string]$InstallProject,\r\n [string]$InstallPublisher,\r\n [string]$InstallSkypeForBusiness,\r\n [string]$InstallVisio,\r\n [string]$InstallWord,\r\n [string]$InstallOneNote,\r\n [string]$InstallPowerPoint,\r\n [string]$UserAssignedIdentityObjectId,\r\n [string]$StorageAccountName,\r\n [string]$ContainerName,\r\n [string]$StorageEndpoint,\r\n [string]$BlobName\r\n )\r\n $ErrorActionPreference = 'Stop'\r\n $WarningPreference = 'SilentlyContinue'\r\n $StorageAccountUrl = \"https://\" + $StorageAccountName + \".blob.\" + $StorageEndpoint + \"/\"\r\n $TokenUri = \"http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=$StorageAccountUrl&object_id=$UserAssignedIdentityObjectId\"\r\n $AccessToken = ((Invoke-WebRequest -Headers @{Metadata=$true} -Uri $TokenUri -UseBasicParsing).Content | ConvertFrom-Json).access_token\r\n New-Item -Path \"$env:windir\\temp\\office\" -ItemType \"directory\" -Force\r\n $sku = (Get-ComputerInfo).OsName\r\n $o365ConfigHeader = Set-Content \"$env:windir\\temp\\office\\office365x64.xml\" ''\r\n $o365OfficeHeader = Add-Content \"$env:windir\\temp\\office\\office365x64.xml\" ''\r\n if($InstallAccess -notlike '*true*'){\r\n Add-Content \"$env:windir\\temp\\office\\office365x64.xml\" ''\r\n }\r\n if($InstallExcel -notlike '*true*'){\r\n Add-Content \"$env:windir\\temp\\office\\office365x64.xml\" ''\r\n }\r\n if($InstallOneDrive -notlike '*true*'){\r\n Add-Content \"$env:windir\\temp\\office\\office365x64.xml\" ''\r\n }\r\n if($InstallOneNote -notlike '*true*'){\r\n Add-Content \"$env:windir\\temp\\office\\office365x64.xml\" ''\r\n }\r\n if($InstallOutlook -notlike '*true*'){\r\n Add-Content \"$env:windir\\temp\\office\\office365x64.xml\" ''\r\n }\r\n if($InstallPowerPoint -notlike '*true*'){\r\n Add-Content \"$env:windir\\temp\\office\\office365x64.xml\" ''\r\n }\r\n if($InstallPublisher -notlike '*true*'){\r\n Add-Content \"$env:windir\\temp\\office\\office365x64.xml\" ''\r\n }\r\n if($InstallSkypeForBusiness -notlike '*true*'){\r\n Add-Content \"$env:windir\\temp\\office\\office365x64.xml\" ''\r\n }\r\n if($InstallWord -notlike '*true*'){\r\n Add-Content \"$env:windir\\temp\\office\\office365x64.xml\" ''\r\n }\r\n $addOfficefooter = Add-Content \"$env:windir\\temp\\office\\office365x64.xml\" ''\r\n if($InstallProject -like '*true*'){\r\n Add-Content \"$env:windir\\temp\\office\\office365x64.xml\" ''\r\n }\r\n if($InstallVisio -like '*true*'){\r\n Add-Content \"$env:windir\\temp\\office\\office365x64.xml\" ''\r\n }\r\n Add-Content \"$env:windir\\temp\\office\\office365x64.xml\" ''\r\n $PerMachineConfiguration = if(($Sku).Contains(\"multi\") -eq \"true\"){\r\n Add-Content \"$env:windir\\temp\\office\\office365x64.xml\" ''\r\n }\r\n Add-Content \"$env:windir\\temp\\office\\office365x64.xml\" ''\r\n $Installer = \"$env:windir\\temp\\office\\office.exe\"\r\n #$DownloadLinks = Invoke-WebRequest -Uri \"https://www.microsoft.com/en-us/download/confirmation.aspx?id=49117\" -UseBasicParsing\r\n #$URL = $DownloadLinks.Links.href | Where-Object {$_ -like \"https://download.microsoft.com/download/*officedeploymenttool*\"} | Select-Object -First 1\r\n #Invoke-WebRequest -Uri $URL -OutFile $Installer -UseBasicParsing\r\n Invoke-WebRequest -Headers @{\"x-ms-version\"=\"2017-11-09\"; Authorization =\"Bearer $AccessToken\"} -Uri \"$StorageAccountUrl$ContainerName/$BlobName\" -OutFile $Installer\r\n Start-Process -FilePath $Installer -ArgumentList \"/extract:$env:windir\\temp\\office /quiet /passive /norestart\" -Wait -PassThru | Out-Null\r\n Write-Host \"Downloaded & extracted the Office 365 Deployment Toolkit\"\r\n Start-Process -FilePath \"$env:windir\\temp\\office\\setup.exe\" -ArgumentList \"/configure $env:windir\\temp\\office\\office365x64.xml\" -Wait -PassThru -ErrorAction \"Stop\" | Out-Null\r\n Write-Host \"Installed the selected Office365 applications\"\r\n Write-Host \"Removing Office FIles\"\r\n Remove-item -Path \"$env:windir\\temp\\office\" -Force -Confirm:$false -Recurse\r\n "
+ }
+ },
+ "dependsOn": [
+ "applications"
+ ]
+ },
+ {
+ "condition": "[parameters('installVirtualDesktopOptimizationTool')]",
+ "type": "Microsoft.Compute/virtualMachines/runCommands",
+ "apiVersion": "2023-03-01",
+ "name": "[format('{0}/{1}', parameters('virtualMachineName'), 'vdot')]",
+ "location": "[parameters('location')]",
+ "tags": "[if(contains(parameters('tags'), 'Microsoft.Compute/virtualMachines'), parameters('tags')['Microsoft.Compute/virtualMachines'], createObject())]",
+ "properties": {
+ "treatFailureAsDeploymentFailure": true,
+ "asyncExecution": false,
+ "parameters": [
+ {
+ "name": "UserAssignedIdentityObjectId",
+ "value": "[parameters('userAssignedIdentityObjectId')]"
+ },
+ {
+ "name": "StorageAccountName",
+ "value": "[parameters('storageAccountName')]"
+ },
+ {
+ "name": "ContainerName",
+ "value": "[parameters('containerName')]"
+ },
+ {
+ "name": "StorageEndpoint",
+ "value": "[parameters('storageEndpoint')]"
+ },
+ {
+ "name": "BlobName",
+ "value": "[parameters('vDotInstaller')]"
+ }
+ ],
+ "source": {
+ "script": " param(\r\n [string]$UserAssignedIdentityObjectId,\r\n [string]$StorageAccountName,\r\n [string]$ContainerName,\r\n [string]$StorageEndpoint,\r\n [string]$BlobName\r\n )\r\n $ErrorActionPreference = 'Stop'\r\n $WarningPreference = 'SilentlyContinue'\r\n $StorageAccountUrl = \"https://\" + $StorageAccountName + \".blob.\" + $StorageEndpoint + \"/\"\r\n $TokenUri = \"http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=$StorageAccountUrl&object_id=$UserAssignedIdentityObjectId\"\r\n $AccessToken = ((Invoke-WebRequest -Headers @{Metadata=$true} -Uri $TokenUri -UseBasicParsing).Content | ConvertFrom-Json).access_token\r\n $ZIP = \"$env:windir\\temp\\VDOT.zip\"\r\n Invoke-WebRequest -Headers @{\"x-ms-version\"=\"2017-11-09\"; Authorization =\"Bearer $AccessToken\"} -Uri \"$StorageAccountUrl$ContainerName/$BlobName\" -OutFile $ZIP\r\n Start-Sleep -Seconds 30\r\n Set-Location -Path $env:windir\\temp\r\n Unblock-File -Path $ZIP\r\n Expand-Archive -LiteralPath $ZIP -DestinationPath \"$env:windir\\temp\" -Force\r\n $Path = (Get-ChildItem -Path \"$env:windir\\temp\" -Recurse | Where-Object {$_.Name -eq \"Windows_VDOT.ps1\"}).FullName\r\n $Script = Get-Content -Path $Path\r\n $ScriptUpdate = $Script.Replace(\"Set-NetAdapterAdvancedProperty\",\"#Set-NetAdapterAdvancedProperty\")\r\n $ScriptUpdate | Set-Content -Path $Path\r\n & $Path -Optimizations @(\"AppxPackages\",\"Autologgers\",\"DefaultUserSettings\",\"LGPO\";\"NetworkOptimizations\",\"ScheduledTasks\",\"Services\",\"WindowsMediaPlayer\") -AdvancedOptimizations \"All\" -AcceptEULA\r\n Write-Host \"Removing VDOT Files\"\r\n # Expecting this format for vDot ZIP, update if using a different ZIP format for folder structure\r\n Remove-Item -Path $env:windir\\temp\\Virtual-Desktop-Optimization-Tool-main -Force -Recurse -Confirm:$false\r\n "
+ },
+ "timeoutInSeconds": 640
+ },
+ "dependsOn": [
+ "applications",
+ "[resourceId('Microsoft.Compute/virtualMachines/runCommands', parameters('virtualMachineName'), 'office')]",
+ "[resourceId('Microsoft.Compute/virtualMachines/runCommands', parameters('virtualMachineName'), 'teams')]"
+ ]
+ },
+ {
+ "condition": "[parameters('installTeams')]",
+ "type": "Microsoft.Compute/virtualMachines/runCommands",
+ "apiVersion": "2023-03-01",
+ "name": "[format('{0}/{1}', parameters('virtualMachineName'), 'teams')]",
+ "location": "[parameters('location')]",
+ "tags": "[if(contains(parameters('tags'), 'Microsoft.Compute/virtualMachines'), parameters('tags')['Microsoft.Compute/virtualMachines'], createObject())]",
+ "properties": {
+ "treatFailureAsDeploymentFailure": true,
+ "asyncExecution": false,
+ "parameters": [
+ {
+ "name": "UserAssignedIdentityObjectId",
+ "value": "[parameters('userAssignedIdentityObjectId')]"
+ },
+ {
+ "name": "StorageAccountName",
+ "value": "[parameters('storageAccountName')]"
+ },
+ {
+ "name": "ContainerName",
+ "value": "[parameters('containerName')]"
+ },
+ {
+ "name": "StorageEndpoint",
+ "value": "[parameters('storageEndpoint')]"
+ },
+ {
+ "name": "BlobName",
+ "value": "[parameters('teamsInstaller')]"
+ },
+ {
+ "name": "BlobName2",
+ "value": "[parameters('vcRedistInstaller')]"
+ },
+ {
+ "name": "BlobName3",
+ "value": "[parameters('msrdcwebrtcsvcInstaller')]"
+ }
+ ],
+ "source": {
+ "script": " param(\r\n [string]$UserAssignedIdentityObjectId,\r\n [string]$StorageAccountName,\r\n [string]$ContainerName,\r\n [string]$StorageEndpoint,\r\n [string]$BlobName,\r\n [string]$BlobName2,\r\n [string]$BlobName3\r\n )\r\n $ErrorActionPreference = 'Stop'\r\n $WarningPreference = 'SilentlyContinue'\r\n $StorageAccountUrl = \"https://\" + $StorageAccountName + \".blob.\" + $StorageEndpoint + \"/\"\r\n $TokenUri = \"http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=$StorageAccountUrl&object_id=$UserAssignedIdentityObjectId\"\r\n $AccessToken = ((Invoke-WebRequest -Headers @{Metadata=$true} -Uri $TokenUri -UseBasicParsing).Content | ConvertFrom-Json).access_token\r\n $vcRedistFile = \"$env:windir\\temp\\vc_redist.x64.exe\"\r\n $webSocketFile = \"$env:windir\\temp\\webSocketSvc.msi\"\r\n $teamsFile = \"$env:windir\\temp\\teams.msi\"\r\n Invoke-WebRequest -Headers @{\"x-ms-version\"=\"2017-11-09\"; Authorization =\"Bearer $AccessToken\"} -Uri \"$StorageAccountUrl$ContainerName/$BlobName\" -OutFile $teamsFile\r\n Invoke-WebRequest -Headers @{\"x-ms-version\"=\"2017-11-09\"; Authorization =\"Bearer $AccessToken\"} -Uri \"$StorageAccountUrl$ContainerName/$BlobName2\" -OutFile $vcRedistFile\r\n Invoke-WebRequest -Headers @{\"x-ms-version\"=\"2017-11-09\"; Authorization =\"Bearer $AccessToken\"} -Uri \"$StorageAccountUrl$ContainerName/$BlobName3\" -OutFile $webSocketFile\r\n\r\n # Enable media optimizations for Team\r\n Start-Process \"reg\" -ArgumentList \"add HKLM\\SOFTWARE\\Microsoft\\Teams /v IsWVDEnvironment /t REG_DWORD /d 1 /f\" -Wait -PassThru -ErrorAction \"Stop\"\r\n Write-Host \"Enabled media optimizations for Teams\"\r\n # Download & install the latest version of Microsoft Visual C++ Redistributable\r\n #$File = \"$env:windir\\temp\\vc_redist.x64.exe\"\r\n #Invoke-WebRequest -Uri \"https://aka.ms/vs/16/release/vc_redist.x64.exe\" -OutFile $File\r\n Start-Process -FilePath $vcRedistFile -Args \"/install /quiet /norestart /log vcdist.log\" -Wait -PassThru | Out-Null\r\n Write-Host \"Installed the latest version of Microsoft Visual C++ Redistributable\"\r\n # Download & install the Remote Desktop WebRTC Redirector Service\r\n #$File = \"$env:windir\\temp\\webSocketSvc.msi\"\r\n #Invoke-WebRequest -Uri \"https://aka.ms/msrdcwebrtcsvc/msi\" -OutFile $File\r\n Start-Process -FilePath msiexec.exe -Args \"/i $webSocketFile /quiet /qn /norestart /passive /log webSocket.log\" -Wait -PassThru | Out-Null\r\n Write-Host \"Installed the Remote Desktop WebRTC Redirector Service\"\r\n # Install Teams\r\n #$File = \"$env:windir\\temp\\teams.msi\"\r\n #Write-host $($TeamsUrl)\r\n #Invoke-WebRequest -Uri \"$TeamsUrl\" -OutFile $File\r\n $sku = (Get-ComputerInfo).OsName\r\n $PerMachineConfiguration = if(($Sku).Contains(\"multi\") -eq \"true\"){\"ALLUSER=1\"}else{\"\"}\r\n Start-Process -FilePath msiexec.exe -Args \"/i $teamsFile /quiet /qn /norestart /passive /log teams.log $PerMachineConfiguration ALLUSERS=1\" -Wait -PassThru | Out-Null\r\n Write-Host \"Installed Teams\"\r\n Write-Host \"Removing Teams Files\"\r\n Remove-Item \"$teamsFile\" -Force -Confirm:$false\r\n Remove-Item \"$vcRedistFile\" -Force -Confirm:$false\r\n Remove-Item \"$webSocketFile\" -Force -Confirm:$false\r\n "
+ }
+ },
+ "dependsOn": [
+ "applications",
+ "[resourceId('Microsoft.Compute/virtualMachines/runCommands', parameters('virtualMachineName'), 'office')]"
+ ]
+ },
+ {
+ "condition": "[parameters('installArcGisPro')]",
+ "type": "Microsoft.Compute/virtualMachines/runCommands",
+ "apiVersion": "2023-03-01",
+ "name": "[format('{0}/{1}', parameters('virtualMachineName'), 'arcGisPro')]",
+ "location": "[parameters('location')]",
+ "tags": "[if(contains(parameters('tags'), 'Microsoft.Compute/virtualMachines'), parameters('tags')['Microsoft.Compute/virtualMachines'], createObject())]",
+ "properties": {
+ "treatFailureAsDeploymentFailure": true,
+ "asyncExecution": false,
+ "parameters": [
+ {
+ "name": "UserAssignedIdentityObjectId",
+ "value": "[parameters('userAssignedIdentityObjectId')]"
+ },
+ {
+ "name": "StorageAccountName",
+ "value": "[parameters('storageAccountName')]"
+ },
+ {
+ "name": "ContainerName",
+ "value": "[parameters('containerName')]"
+ },
+ {
+ "name": "StorageEndpoint",
+ "value": "[parameters('storageEndpoint')]"
+ },
+ {
+ "name": "BlobName",
+ "value": "[parameters('arcGisProInstaller')]"
+ }
+ ],
+ "source": {
+ "script": " param(\r\n [string]$UserAssignedIdentityObjectId,\r\n [string]$StorageAccountName,\r\n [string]$ContainerName,\r\n [string]$StorageEndpoint,\r\n [string]$BlobName\r\n )\r\n $ErrorActionPreference = 'Stop'\r\n $WarningPreference = 'SilentlyContinue'\r\n $StorageAccountUrl = \"https://\" + $StorageAccountName + \".blob.\" + $StorageEndpoint + \"/\"\r\n $TokenUri = \"http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=$StorageAccountUrl&object_id=$UserAssignedIdentityObjectId\"\r\n $AccessToken = ((Invoke-WebRequest -Headers @{Metadata=$true} -Uri $TokenUri -UseBasicParsing).Content | ConvertFrom-Json).access_token\r\n # Retrieve Files\r\n New-Item -Path $env:windir\\temp -Name arcgis -ItemType \"directory\" -Force\r\n $ZIP = \"$env:windir\\temp\\arcgispro.zip\"\r\n Invoke-WebRequest -Headers @{\"x-ms-version\"=\"2017-11-09\"; Authorization =\"Bearer $AccessToken\"} -Uri \"$StorageAccountUrl$ContainerName/$BlobName\" -OutFile $ZIP\r\n Start-Sleep -Seconds 30\r\n Set-Location -Path $env:windir\\temp\r\n Unblock-File -Path $ZIP\r\n Expand-Archive -LiteralPath $ZIP -DestinationPath \"$env:windir\\temp\\arcgis\" -Force\r\n\r\n # Install Arcgis\r\n $arcGisProMsi = (Get-ChildItem \"$env:windir\\temp\\arcgis\\\" -Recurse | where {$_.Name -eq \"ArcGisPro.msi\"})\r\n $arcGisProMsp = (Get-ChildItem \"$env:windir\\temp\\arcgis\" -Recurse | where {$_.Extension -eq \".msp\"})\r\n $winDesktopRuntime = (Get-ChildItem \"$env:windir\\temp\\arcgis\\\" -Recurse | where {$_.Name -like \"windowsdesktop-runtime-*\"})\r\n\r\n # If found Install Windows Desktop Runtime Pre-Req\r\n try {\r\n if ($winDesktopRuntime ){\r\n Start-Process -FilePath \"$($winDesktopRuntime.Directory.FullName)\\$winDesktopRuntime\" -ArgumentList \"/install /quiet /norestart\" -Wait -NoNewWindow -PassThru\r\n }\r\n }\r\n catch {\r\n Write-Output \"Please validate all software requirements are included with the ArcGIS Pro Zip\"\r\n }\r\n\r\n try {\r\n # Install ArcGis Pro\r\n $arcGisProArguments = \"/i $($arcGisProMsi.Directory.FullName)\\$arcGisProMsi ALLUSERS=1 ACCEPTEULA=yes ENABLEEUEI=0 SOFTWARE_CLASS=Professional AUTHORIZATION_TYPE=NAMED_USER LOCK_AUTH_SETTINGS=False ArcGIS_Connection=TRUE /qn /norestart\"\r\n Start-Process \"msiexec.exe\" -ArgumentList $arcGisProArguments -Wait -NoNewWindow -PassThru\r\n }\r\n catch {\r\n Write-Output \"Please validate all software requirements are included with the ArcGIS Pro Zip\"\r\n }\r\n\r\n try {\r\n # If MSP is found, patch ArcGisPro with MSP file\r\n if($arcGisProMsp){\r\n Start-Process \"msiexec.exe\" -ArgumentList \"/p $($arcGisProMsp.Directory.FullName)\\$arcGisProMsp /qn\" -Wait -NoNewWindow -PassThru\r\n }\r\n }\r\n catch {\r\n Write-Output \"Please validate all software requirements are included with the ArcGIS Pro Zip\"\r\n }\r\n Write-Host \"Removing ArcGis Files\"\r\n Remove-Item $ZIP -Force -Confirm:$false -Recurse\r\n Remove-item -Path \"$env:windir\\temp\\arcgis\" -Force -Confirm:$false -Recurse\r\n "
+ }
+ },
+ "dependsOn": [
+ "applications",
+ "[resourceId('Microsoft.Compute/virtualMachines/runCommands', parameters('virtualMachineName'), 'office')]",
+ "[resourceId('Microsoft.Compute/virtualMachines/runCommands', parameters('virtualMachineName'), 'teams')]",
+ "[resourceId('Microsoft.Compute/virtualMachines/runCommands', parameters('virtualMachineName'), 'vdot')]"
+ ]
+ }
+ ]
+ }
+ },
+ "dependsOn": [
+ "[resourceId('Microsoft.Resources/deployments', format('image-vm-{0}', parameters('deploymentNameSuffix')))]"
+ ]
+ },
+ {
+ "type": "Microsoft.Resources/deployments",
+ "apiVersion": "2022-09-01",
+ "name": "[format('restart-vm-{0}', parameters('deploymentNameSuffix'))]",
+ "properties": {
+ "expressionEvaluationOptions": {
+ "scope": "inner"
+ },
+ "mode": "Incremental",
+ "parameters": {
+ "imageVirtualMachineName": {
+ "value": "[reference(resourceId('Microsoft.Resources/deployments', format('image-vm-{0}', parameters('deploymentNameSuffix'))), '2022-09-01').outputs.name.value]"
+ },
+ "resourceGroupName": {
+ "value": "[variables('resourceGroupName')]"
+ },
+ "location": {
+ "value": "[parameters('location')]"
+ },
+ "tags": {
+ "value": "[parameters('tags')]"
+ },
+ "userAssignedIdentityClientId": {
+ "value": "[parameters('userAssignedIdentityClientId')]"
+ },
+ "virtualMachineName": "[if(parameters('enableBuildAutomation'), createObject('value', parameters('managementVirtualMachineName')), createObject('value', reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', variables('subscriptionId'), variables('resourceGroupName')), 'Microsoft.Resources/deployments', format('management-vm-{0}', parameters('deploymentNameSuffix'))), '2022-09-01').outputs.name.value))]"
+ },
+ "template": {
+ "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
+ "contentVersion": "1.0.0.0",
+ "metadata": {
+ "_generator": {
+ "name": "bicep",
+ "version": "0.24.24.22086",
+ "templateHash": "272404991735293049"
+ }
+ },
+ "parameters": {
+ "imageVirtualMachineName": {
+ "type": "string"
+ },
+ "resourceGroupName": {
+ "type": "string"
+ },
+ "location": {
+ "type": "string"
+ },
+ "tags": {
+ "type": "object"
+ },
+ "userAssignedIdentityClientId": {
+ "type": "string"
+ },
+ "virtualMachineName": {
+ "type": "string"
+ }
+ },
+ "resources": [
+ {
+ "type": "Microsoft.Compute/virtualMachines/runCommands",
+ "apiVersion": "2023-03-01",
+ "name": "[format('{0}/{1}', parameters('virtualMachineName'), 'restartVirtualMachine')]",
+ "location": "[parameters('location')]",
+ "tags": "[if(contains(parameters('tags'), 'Microsoft.Compute/virtualMachines'), parameters('tags')['Microsoft.Compute/virtualMachines'], createObject())]",
+ "properties": {
+ "treatFailureAsDeploymentFailure": true,
+ "asyncExecution": false,
+ "parameters": [
+ {
+ "name": "Environment",
+ "value": "[environment().name]"
+ },
+ {
+ "name": "ResourceGroupName",
+ "value": "[parameters('resourceGroupName')]"
+ },
+ {
+ "name": "SubscriptionId",
+ "value": "[subscription().subscriptionId]"
+ },
+ {
+ "name": "TenantId",
+ "value": "[tenant().tenantId]"
+ },
+ {
+ "name": "UserAssignedIdentityClientId",
+ "value": "[parameters('userAssignedIdentityClientId')]"
+ },
+ {
+ "name": "VirtualMachineName",
+ "value": "[parameters('imageVirtualMachineName')]"
+ }
+ ],
+ "source": {
+ "script": " param(\r\n [string]$Environment,\r\n [string]$ResourceGroupName,\r\n [string]$SubscriptionId,\r\n [string]$TenantId,\r\n [string]$UserAssignedIdentityClientId,\r\n [string]$VirtualMachineName\r\n )\r\n $ErrorActionPreference = 'Stop'\r\n Connect-AzAccount -Environment $Environment -Tenant $TenantId -Subscription $SubscriptionId -Identity -AccountId $UserAssignedIdentityClientId | Out-Null\r\n Restart-AzVM -ResourceGroupName $ResourceGroupName -Name $VirtualMachineName\r\n $AgentStatus = $Null\r\n while ($Null -eq $AgentStatus) \r\n {\r\n Start-Sleep -Seconds 5\r\n $AgentStatus = (Get-AzVM -ResourceGroupName $ResourceGroupName -Name $VirtualMachineName -Status).VMAgent\r\n }\r\n "
+ }
+ }
+ }
+ ]
+ }
+ },
+ "dependsOn": [
+ "[resourceId('Microsoft.Resources/deployments', format('customizations-{0}', parameters('deploymentNameSuffix')))]",
+ "[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', variables('subscriptionId'), variables('resourceGroupName')), 'Microsoft.Resources/deployments', format('management-vm-{0}', parameters('deploymentNameSuffix')))]",
+ "[resourceId('Microsoft.Resources/deployments', format('image-vm-{0}', parameters('deploymentNameSuffix')))]"
+ ]
+ },
+ {
+ "type": "Microsoft.Resources/deployments",
+ "apiVersion": "2022-09-01",
+ "name": "[format('sysprep-vm-{0}', parameters('deploymentNameSuffix'))]",
+ "properties": {
+ "expressionEvaluationOptions": {
+ "scope": "inner"
+ },
+ "mode": "Incremental",
+ "parameters": {
+ "location": {
+ "value": "[parameters('location')]"
+ },
+ "tags": {
+ "value": "[parameters('tags')]"
+ },
+ "virtualMachineName": {
+ "value": "[reference(resourceId('Microsoft.Resources/deployments', format('image-vm-{0}', parameters('deploymentNameSuffix'))), '2022-09-01').outputs.name.value]"
+ }
+ },
+ "template": {
+ "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
+ "contentVersion": "1.0.0.0",
+ "metadata": {
+ "_generator": {
+ "name": "bicep",
+ "version": "0.24.24.22086",
+ "templateHash": "15255297707921051029"
+ }
+ },
+ "parameters": {
+ "location": {
+ "type": "string"
+ },
+ "tags": {
+ "type": "object"
+ },
+ "virtualMachineName": {
+ "type": "string"
+ }
+ },
+ "resources": [
+ {
+ "type": "Microsoft.Compute/virtualMachines/runCommands",
+ "apiVersion": "2023-03-01",
+ "name": "[format('{0}/{1}', parameters('virtualMachineName'), 'sysprepVirtualMachine')]",
+ "location": "[parameters('location')]",
+ "tags": "[if(contains(parameters('tags'), 'Microsoft.Compute/virtualMachines'), parameters('tags')['Microsoft.Compute/virtualMachines'], createObject())]",
+ "properties": {
+ "treatFailureAsDeploymentFailure": false,
+ "asyncExecution": true,
+ "parameters": [],
+ "source": {
+ "script": " Start-Sleep -Seconds 30\r\n Remove-Item -LiteralPath 'C:\\Windows\\Panther' -Force -Recurse -ErrorAction SilentlyContinue\r\n Set-ItemProperty -Path 'HKLM:\\SYSTEM\\CurrentControlSet\\Services\\cdrom' -Name 'Start' -Value 1\r\n Start-Process -File 'C:\\Windows\\System32\\Sysprep\\Sysprep.exe' -ArgumentList '/generalize /oobe /shutdown /mode:vm'\r\n "
+ }
+ }
+ }
+ ]
+ }
+ },
+ "dependsOn": [
+ "[resourceId('Microsoft.Resources/deployments', format('restart-vm-{0}', parameters('deploymentNameSuffix')))]",
+ "[resourceId('Microsoft.Resources/deployments', format('image-vm-{0}', parameters('deploymentNameSuffix')))]"
+ ]
+ },
+ {
+ "type": "Microsoft.Resources/deployments",
+ "apiVersion": "2022-09-01",
+ "name": "[format('generalize-vm-{0}', parameters('deploymentNameSuffix'))]",
+ "properties": {
+ "expressionEvaluationOptions": {
+ "scope": "inner"
+ },
+ "mode": "Incremental",
+ "parameters": {
+ "imageVirtualMachineName": {
+ "value": "[reference(resourceId('Microsoft.Resources/deployments', format('image-vm-{0}', parameters('deploymentNameSuffix'))), '2022-09-01').outputs.name.value]"
+ },
+ "resourceGroupName": {
+ "value": "[variables('resourceGroupName')]"
+ },
+ "location": {
+ "value": "[parameters('location')]"
+ },
+ "tags": {
+ "value": "[parameters('tags')]"
+ },
+ "userAssignedIdentityClientId": {
+ "value": "[parameters('userAssignedIdentityClientId')]"
+ },
+ "virtualMachineName": "[if(parameters('enableBuildAutomation'), createObject('value', parameters('managementVirtualMachineName')), createObject('value', reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', variables('subscriptionId'), variables('resourceGroupName')), 'Microsoft.Resources/deployments', format('management-vm-{0}', parameters('deploymentNameSuffix'))), '2022-09-01').outputs.name.value))]"
+ },
+ "template": {
+ "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
+ "contentVersion": "1.0.0.0",
+ "metadata": {
+ "_generator": {
+ "name": "bicep",
+ "version": "0.24.24.22086",
+ "templateHash": "9071697732370041967"
+ }
+ },
+ "parameters": {
+ "imageVirtualMachineName": {
+ "type": "string"
+ },
+ "resourceGroupName": {
+ "type": "string"
+ },
+ "location": {
+ "type": "string",
+ "defaultValue": "[resourceGroup().location]"
+ },
+ "tags": {
+ "type": "object"
+ },
+ "userAssignedIdentityClientId": {
+ "type": "string"
+ },
+ "virtualMachineName": {
+ "type": "string"
+ }
+ },
+ "resources": [
+ {
+ "type": "Microsoft.Compute/virtualMachines/runCommands",
+ "apiVersion": "2023-03-01",
+ "name": "[format('{0}/{1}', parameters('virtualMachineName'), 'generalizeVirtualMachine')]",
+ "location": "[parameters('location')]",
+ "tags": "[if(contains(parameters('tags'), 'Microsoft.Compute/virtualMachines'), parameters('tags')['Microsoft.Compute/virtualMachines'], createObject())]",
+ "properties": {
+ "treatFailureAsDeploymentFailure": true,
+ "asyncExecution": false,
+ "parameters": [
+ {
+ "name": "Environment",
+ "value": "[environment().name]"
+ },
+ {
+ "name": "ResourceGroupName",
+ "value": "[parameters('resourceGroupName')]"
+ },
+ {
+ "name": "SubscriptionId",
+ "value": "[subscription().subscriptionId]"
+ },
+ {
+ "name": "TenantId",
+ "value": "[tenant().tenantId]"
+ },
+ {
+ "name": "UserAssignedIdentityClientId",
+ "value": "[parameters('userAssignedIdentityClientId')]"
+ },
+ {
+ "name": "VirtualMachineName",
+ "value": "[parameters('imageVirtualMachineName')]"
+ }
+ ],
+ "source": {
+ "script": " param(\r\n [string]$Environment,\r\n [string]$ResourceGroupName,\r\n [string]$SubscriptionId,\r\n [string]$TenantId,\r\n [string]$UserAssignedIdentityClientId,\r\n [string]$VirtualMachineName\r\n )\r\n $ErrorActionPreference = 'Stop'\r\n Connect-AzAccount -Environment $Environment -Tenant $TenantId -Subscription $SubscriptionId -Identity -AccountId $UserAssignedIdentityClientId | Out-Null\r\n $PowerStatus = ''\r\n while ($PowerStatus -ne 'VM stopped')\r\n {\r\n Start-Sleep -Seconds 5\r\n $PowerStatus = (Get-AzVM -ResourceGroupName $ResourceGroupName -Name $VirtualMachineName -Status).Statuses[1].DisplayStatus\r\n }\r\n Set-AzVm -ResourceGroupName $ResourceGroupName -Name $VirtualMachineName -Generalized\r\n Start-Sleep -Seconds 30\r\n "
+ }
+ }
+ }
+ ]
+ }
+ },
+ "dependsOn": [
+ "[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', variables('subscriptionId'), variables('resourceGroupName')), 'Microsoft.Resources/deployments', format('management-vm-{0}', parameters('deploymentNameSuffix')))]",
+ "[resourceId('Microsoft.Resources/deployments', format('sysprep-vm-{0}', parameters('deploymentNameSuffix')))]",
+ "[resourceId('Microsoft.Resources/deployments', format('image-vm-{0}', parameters('deploymentNameSuffix')))]"
+ ]
+ },
+ {
+ "type": "Microsoft.Resources/deployments",
+ "apiVersion": "2022-09-01",
+ "name": "[format('image-version-{0}', parameters('deploymentNameSuffix'))]",
+ "properties": {
+ "expressionEvaluationOptions": {
+ "scope": "inner"
+ },
+ "mode": "Incremental",
+ "parameters": {
+ "computeGalleryImageResourceId": {
+ "value": "[parameters('computeGalleryImageResourceId')]"
+ },
+ "computeGalleryName": {
+ "value": "[parameters('computeGalleryName')]"
+ },
+ "excludeFromLatest": {
+ "value": "[parameters('excludeFromLatest')]"
+ },
+ "imageDefinitionName": {
+ "value": "[parameters('imageDefinitionName')]"
+ },
+ "imageVersionNumber": {
+ "value": "[variables('autoImageVersion')]"
+ },
+ "imageVirtualMachineResourceId": {
+ "value": "[reference(resourceId('Microsoft.Resources/deployments', format('image-vm-{0}', parameters('deploymentNameSuffix'))), '2022-09-01').outputs.resourceId.value]"
+ },
+ "location": {
+ "value": "[parameters('location')]"
+ },
+ "marketplaceImageOffer": {
+ "value": "[parameters('marketplaceImageOffer')]"
+ },
+ "marketplaceImagePublisher": {
+ "value": "[parameters('marketplaceImagePublisher')]"
+ },
+ "replicaCount": {
+ "value": "[parameters('replicaCount')]"
+ },
+ "tags": {
+ "value": "[parameters('tags')]"
+ }
+ },
+ "template": {
+ "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
+ "contentVersion": "1.0.0.0",
+ "metadata": {
+ "_generator": {
+ "name": "bicep",
+ "version": "0.24.24.22086",
+ "templateHash": "6302458606004775652"
+ }
+ },
+ "parameters": {
+ "allowDeletionOfReplicatedLocations": {
+ "type": "bool",
+ "defaultValue": true
+ },
+ "computeGalleryName": {
+ "type": "string"
+ },
+ "computeGalleryImageResourceId": {
+ "type": "string"
+ },
+ "excludeFromLatest": {
+ "type": "bool"
+ },
+ "imageDefinitionName": {
+ "type": "string"
+ },
+ "imageVersionNumber": {
+ "type": "string"
+ },
+ "imageVirtualMachineResourceId": {
+ "type": "string"
+ },
+ "location": {
+ "type": "string"
+ },
+ "marketplaceImageOffer": {
+ "type": "string"
+ },
+ "marketplaceImagePublisher": {
+ "type": "string"
+ },
+ "replicaCount": {
+ "type": "int"
+ },
+ "tags": {
+ "type": "object"
+ }
+ },
+ "resources": [
+ {
+ "type": "Microsoft.Compute/galleries/images",
+ "apiVersion": "2022-03-03",
+ "name": "[format('{0}/{1}', parameters('computeGalleryName'), parameters('imageDefinitionName'))]",
+ "location": "[parameters('location')]",
+ "tags": "[if(contains(parameters('tags'), 'Microsoft.Compute/galleries'), parameters('tags')['Microsoft.Compute/galleries'], createObject())]",
+ "properties": {
+ "architecture": "x64",
+ "features": [
+ {
+ "name": "SecurityType",
+ "value": "TrustedLaunch"
+ }
+ ],
+ "hyperVGeneration": "V2",
+ "identifier": {
+ "offer": "[if(empty(parameters('computeGalleryImageResourceId')), parameters('marketplaceImageOffer'), reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', split(parameters('computeGalleryImageResourceId'), '/')[2], split(parameters('computeGalleryImageResourceId'), '/')[4]), 'Microsoft.Compute/galleries/images', split(parameters('computeGalleryImageResourceId'), '/')[8], split(parameters('computeGalleryImageResourceId'), '/')[10]), '2022-03-03').identifier.offer)]",
+ "publisher": "[if(empty(parameters('computeGalleryImageResourceId')), parameters('marketplaceImagePublisher'), reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', split(parameters('computeGalleryImageResourceId'), '/')[2], split(parameters('computeGalleryImageResourceId'), '/')[4]), 'Microsoft.Compute/galleries/images', split(parameters('computeGalleryImageResourceId'), '/')[8], split(parameters('computeGalleryImageResourceId'), '/')[10]), '2022-03-03').identifier.publisher)]",
+ "sku": "[parameters('imageDefinitionName')]"
+ },
+ "osState": "Generalized",
+ "osType": "Windows"
+ }
+ },
+ {
+ "type": "Microsoft.Compute/galleries/images/versions",
+ "apiVersion": "2022-03-03",
+ "name": "[format('{0}/{1}/{2}', parameters('computeGalleryName'), parameters('imageDefinitionName'), parameters('imageVersionNumber'))]",
+ "location": "[parameters('location')]",
+ "tags": "[if(contains(parameters('tags'), 'Microsoft.Compute/galleries'), parameters('tags')['Microsoft.Compute/galleries'], createObject())]",
+ "properties": {
+ "publishingProfile": {
+ "excludeFromLatest": "[parameters('excludeFromLatest')]",
+ "replicaCount": "[parameters('replicaCount')]",
+ "replicationMode": "Full",
+ "storageAccountType": "Standard_LRS",
+ "targetRegions": [
+ {
+ "name": "[parameters('location')]",
+ "regionalReplicaCount": "[parameters('replicaCount')]",
+ "storageAccountType": "Standard_LRS"
+ }
+ ]
+ },
+ "safetyProfile": {
+ "allowDeletionOfReplicatedLocations": "[parameters('allowDeletionOfReplicatedLocations')]"
+ },
+ "storageProfile": {
+ "source": {
+ "id": "[parameters('imageVirtualMachineResourceId')]"
+ }
+ }
+ },
+ "dependsOn": [
+ "[resourceId('Microsoft.Compute/galleries/images', parameters('computeGalleryName'), parameters('imageDefinitionName'))]"
+ ]
+ }
+ ]
+ }
+ },
+ "dependsOn": [
+ "[resourceId('Microsoft.Resources/deployments', format('generalize-vm-{0}', parameters('deploymentNameSuffix')))]",
+ "[resourceId('Microsoft.Resources/deployments', format('image-vm-{0}', parameters('deploymentNameSuffix')))]"
+ ]
+ },
+ {
+ "type": "Microsoft.Resources/deployments",
+ "apiVersion": "2022-09-01",
+ "name": "[format('remove-vm-{0}', parameters('deploymentNameSuffix'))]",
+ "properties": {
+ "expressionEvaluationOptions": {
+ "scope": "inner"
+ },
+ "mode": "Incremental",
+ "parameters": {
+ "enableBuildAutomation": {
+ "value": "[parameters('enableBuildAutomation')]"
+ },
+ "imageVirtualMachineName": {
+ "value": "[reference(resourceId('Microsoft.Resources/deployments', format('image-vm-{0}', parameters('deploymentNameSuffix'))), '2022-09-01').outputs.name.value]"
+ },
+ "location": {
+ "value": "[parameters('location')]"
+ },
+ "tags": {
+ "value": "[parameters('tags')]"
+ },
+ "userAssignedIdentityClientId": {
+ "value": "[parameters('userAssignedIdentityClientId')]"
+ },
+ "virtualMachineName": "[if(parameters('enableBuildAutomation'), createObject('value', parameters('managementVirtualMachineName')), createObject('value', reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', variables('subscriptionId'), variables('resourceGroupName')), 'Microsoft.Resources/deployments', format('management-vm-{0}', parameters('deploymentNameSuffix'))), '2022-09-01').outputs.name.value))]"
+ },
+ "template": {
+ "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
+ "contentVersion": "1.0.0.0",
+ "metadata": {
+ "_generator": {
+ "name": "bicep",
+ "version": "0.24.24.22086",
+ "templateHash": "3667781850662988906"
+ }
+ },
+ "parameters": {
+ "enableBuildAutomation": {
+ "type": "bool"
+ },
+ "imageVirtualMachineName": {
+ "type": "string"
+ },
+ "location": {
+ "type": "string",
+ "defaultValue": "[resourceGroup().location]"
+ },
+ "tags": {
+ "type": "object"
+ },
+ "userAssignedIdentityClientId": {
+ "type": "string"
+ },
+ "virtualMachineName": {
+ "type": "string"
+ }
+ },
+ "resources": [
+ {
+ "type": "Microsoft.Compute/virtualMachines/runCommands",
+ "apiVersion": "2023-03-01",
+ "name": "[format('{0}/{1}', parameters('virtualMachineName'), 'removeVirtualMachine')]",
+ "location": "[parameters('location')]",
+ "tags": "[if(contains(parameters('tags'), 'Microsoft.Compute/virtualMachines'), parameters('tags')['Microsoft.Compute/virtualMachines'], createObject())]",
+ "properties": {
+ "treatFailureAsDeploymentFailure": true,
+ "asyncExecution": "[if(parameters('enableBuildAutomation'), false(), true())]",
+ "parameters": [
+ {
+ "name": "EnableBuildAutomation",
+ "value": "[string(parameters('enableBuildAutomation'))]"
+ },
+ {
+ "name": "Environment",
+ "value": "[environment().name]"
+ },
+ {
+ "name": "ImageVmName",
+ "value": "[parameters('imageVirtualMachineName')]"
+ },
+ {
+ "name": "ManagementVmName",
+ "value": "[parameters('virtualMachineName')]"
+ },
+ {
+ "name": "ResourceGroupName",
+ "value": "[resourceGroup().name]"
+ },
+ {
+ "name": "SubscriptionId",
+ "value": "[subscription().subscriptionId]"
+ },
+ {
+ "name": "TenantId",
+ "value": "[tenant().tenantId]"
+ },
+ {
+ "name": "UserAssignedIdentityClientId",
+ "value": "[parameters('userAssignedIdentityClientId')]"
+ }
+ ],
+ "source": {
+ "script": " param(\r\n [string]$EnableBuildAutomation,\r\n [string]$Environment,\r\n [string]$ImageVmName,\r\n [string]$ManagementVmName,\r\n [string]$ResourceGroupName,\r\n [string]$SubscriptionId,\r\n [string]$TenantId,\r\n [string]$UserAssignedIdentityClientId\r\n )\r\n $ErrorActionPreference = 'Stop'\r\n Connect-AzAccount -Environment $Environment -Tenant $TenantId -Subscription $SubscriptionId -Identity -AccountId $UserAssignedIdentityClientId | Out-Null\r\n Remove-AzVM -ResourceGroupName $ResourceGroupName -Name $ImageVmName -Force\r\n if($EnableBuildAutomation -eq 'false')\r\n {\r\n Remove-AzVM -ResourceGroupName $ResourceGroupName -Name $ManagementVmName -NoWait -Force -AsJob\r\n }\r\n "
+ }
+ }
+ }
+ ]
+ }
+ },
+ "dependsOn": [
+ "[resourceId('Microsoft.Resources/deployments', format('image-version-{0}', parameters('deploymentNameSuffix')))]",
+ "[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', variables('subscriptionId'), variables('resourceGroupName')), 'Microsoft.Resources/deployments', format('management-vm-{0}', parameters('deploymentNameSuffix')))]",
+ "[resourceId('Microsoft.Resources/deployments', format('image-vm-{0}', parameters('deploymentNameSuffix')))]"
+ ]
+ }
+ ]
+ }
+ },
+ "dependsOn": [
+ "[subscriptionResourceId('Microsoft.Resources/deployments', format('baseline-{0}', parameters('deploymentNameSuffix')))]",
+ "[subscriptionResourceId('Microsoft.Resources/deployments', format('build-automation-{0}', parameters('deploymentNameSuffix')))]",
+ "[subscriptionResourceId('Microsoft.Resources/resourceGroups', parameters('resourceGroupName'))]",
+ "[extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', variables('subscriptionId'), if(parameters('existingResourceGroup'), parameters('resourceGroupName'), parameters('resourceGroupName'))), 'Microsoft.Resources/deployments', format('tier3-{0}', parameters('deploymentNameSuffix')))]"
+ ]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/src/bicep/add-ons/Imaging/solution.parameters.json b/src/bicep/add-ons/Imaging/solution.parameters.json
new file mode 100644
index 000000000..2a8ed64ac
--- /dev/null
+++ b/src/bicep/add-ons/Imaging/solution.parameters.json
@@ -0,0 +1,177 @@
+{
+ "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#",
+ "contentVersion": "1.0.0.0",
+ "parameters": {
+ "actionGroupName": {
+ "value": ""
+ },
+ "automationAccountName": {
+ "value": ""
+ },
+ "automationAccountPrivateDnsZoneResourceId": {
+ "value": ""
+ },
+ "computeGalleryImageResourceId": {
+ "value": ""
+ },
+ "computeGalleryName": {
+ "value": ""
+ },
+ "containerName": {
+ "value": ""
+ },
+ "customizations": {
+ "value": []
+ },
+ "diskEncryptionSetResourceId": {
+ "value": ""
+ },
+ "distributionGroup": {
+ "value": ""
+ },
+ "deploymentNameSuffix": {
+ "value": ""
+ },
+ "domainJoinPassword": {
+ "value": ""
+ },
+ "domainJoinUserPrincipalName": {
+ "value": ""
+ },
+ "domainName": {
+ "value": ""
+ },
+ "enableBuildAutomation": {
+ "value": false
+ },
+ "excludeFromLatest": {
+ "value": false
+ },
+ "exemptPolicyAssignmentIds": {
+ "value": []
+ },
+ "hybridUseBenefit": {
+ "value": false
+ },
+ "hybridWorkerName": {
+ "value": ""
+ },
+ "imageDefinitionNamePrefix": {
+ "value": ""
+ },
+ "imageMajorVersion": {
+ "value": 0
+ },
+ "imageMinorVersion": {
+ "value": 0
+ },
+ "installAccess": {
+ "value": false
+ },
+ "installExcel": {
+ "value": false
+ },
+ "installOneDrive": {
+ "value": false
+ },
+ "installOneNote": {
+ "value": false
+ },
+ "installOutlook": {
+ "value": false
+ },
+ "installPowerPoint": {
+ "value": false
+ },
+ "installProject": {
+ "value": false
+ },
+ "installPublisher": {
+ "value": false
+ },
+ "installSkypeForBusiness": {
+ "value": false
+ },
+ "installTeams": {
+ "value": false
+ },
+ "installVirtualDesktopOptimizationTool": {
+ "value": false
+ },
+ "installVisio": {
+ "value": false
+ },
+ "installWord": {
+ "value": false
+ },
+ "keyVaultName": {
+ "value": ""
+ },
+ "keyVaultPrivateDnsZoneResourceId": {
+ "value": ""
+ },
+ "localAdministratorPassword": {
+ "value": ""
+ },
+ "localAdministratorUsername": {
+ "value": ""
+ },
+ "location": {
+ "value": ""
+ },
+ "logAnalyticsWorkspaceResourceId": {
+ "value": ""
+ },
+ "marketplaceImageOffer": {
+ "value": ""
+ },
+ "marketplaceImagePublisher": {
+ "value": ""
+ },
+ "marketplaceImageSKU": {
+ "value": ""
+ },
+ "msrdcwebrtcsvcInstaller": {
+ "value": ""
+ },
+ "officeInstaller": {
+ "value": ""
+ },
+ "oUPath": {
+ "value": ""
+ },
+ "replicaCount": {
+ "value": 0
+ },
+ "resourceGroupName": {
+ "value": ""
+ },
+ "sourceImageType": {
+ "value": ""
+ },
+ "storageAccountResourceId": {
+ "value": ""
+ },
+ "subnetResourceId": {
+ "value": ""
+ },
+ "tags": {
+ "value": {}
+ },
+ "teamsInstaller": {
+ "value": ""
+ },
+ "userAssignedIdentityName": {
+ "value": ""
+ },
+ "vcRedistInstaller": {
+ "value": ""
+ },
+ "vDOTInstaller": {
+ "value": ""
+ },
+ "virtualMachineSize": {
+ "value": ""
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/bicep/add-ons/Imaging/uiDefinition.json b/src/bicep/add-ons/Imaging/uiDefinition.json
new file mode 100644
index 000000000..3bdf6cb36
--- /dev/null
+++ b/src/bicep/add-ons/Imaging/uiDefinition.json
@@ -0,0 +1,1628 @@
+{
+ "$schema": "https://schema.management.azure.com/schemas/2021-09-09/uiFormDefinition.schema.json",
+ "view": {
+ "kind": "Form",
+ "properties": {
+ "title": "Zero Trust Image Build Solution",
+ "steps": [
+ {
+ "name": "basics",
+ "label": "Basics",
+ "elements": [
+ {
+ "name": "prerequisites",
+ "type": "Microsoft.Common.InfoBox",
+ "options": {
+ "text": "Prior to deployment, make sure you meet the prerequisites outlined in the resource pre-reqs section in Zero Trust Image solution documentation.",
+ "uri": "https://github.com/mikedzikowski/ZTAImage#prequisites",
+ "icon": "Warning"
+ }
+ },
+ {
+ "name": "subscriptions",
+ "label": "Select Subscriptions",
+ "type": "Microsoft.Common.Section",
+ "elements": [
+ {
+ "name": "api",
+ "type": "Microsoft.Solutions.ArmApiControl",
+ "request": {
+ "method": "GET",
+ "path": "subscriptions?api-version=2020-01-01"
+ }
+ },
+ {
+ "name": "hub",
+ "label": "Hub Subscription",
+ "type": "Microsoft.Common.DropDown",
+ "defaultValue": "",
+ "toolTip": "Select the subscription for your Mission Landing Zone Hub network, firewall, and remote access resources.",
+ "multiselect": false,
+ "selectAll": false,
+ "filter": true,
+ "filterPlaceholder": "Filter items ...",
+ "multiLine": true,
+ "constraints": {
+ "allowedValues": "[map(steps('basics').subscriptions.api.value, (item) => parse(concat('{\"label\":\"', item.displayName, '\",\"value\":\"', item.id, '\",\"description\":\"', 'ID: ', item.subscriptionId, '\"}')))]",
+ "required": true
+ }
+ },
+ {
+ "name": "spoke",
+ "label": "ZTA Imaging Subscription",
+ "type": "Microsoft.Common.DropDown",
+ "defaultValue": "",
+ "toolTip": "Select the subscription for your ZTA Imaging resources.",
+ "multiselect": false,
+ "selectAll": false,
+ "filter": true,
+ "filterPlaceholder": "Filter items ...",
+ "multiLine": true,
+ "constraints": {
+ "allowedValues": "[map(steps('basics').subscriptions.api.value, (item) => parse(concat('{\"label\":\"', item.displayName, '\",\"value\":\"', item.id, '\",\"description\":\"', 'ID: ', item.subscriptionId, '\"}')))]",
+ "required": true
+ }
+ }
+ ]
+ },
+ {
+ "name": "hub",
+ "label": "Hub Resources",
+ "type": "Microsoft.Common.Section",
+ "elements": [
+ {
+ "name": "virtualNetworksApi",
+ "type": "Microsoft.Solutions.ArmApiControl",
+ "request": {
+ "method": "GET",
+ "path": "[concat(steps('basics').subscriptions.hub, '/providers/Microsoft.Network/virtualNetworks?api-version=2023-05-01')]"
+ }
+ },
+ {
+ "name": "virtualNetwork",
+ "type": "Microsoft.Common.DropDown",
+ "visible": true,
+ "label": "Hub virtual network",
+ "defaultValue": "",
+ "toolTip": "Select the existing Hub virtual network.",
+ "constraints": {
+ "required": true,
+ "allowedValues": "[map(steps('basics').hub.virtualNetworksApi.value, (item) => parse(concat('{\"label\":\"', item.name, '\",\"value\":\"', item.id, '\"}')))]"
+ }
+ },
+ {
+ "name": "azureFirewallsApi",
+ "type": "Microsoft.Solutions.ArmApiControl",
+ "request": {
+ "method": "GET",
+ "path": "[concat(steps('basics').subscriptions.hub, '/providers/Microsoft.Network/azureFirewalls?api-version=2023-05-01')]"
+ }
+ },
+ {
+ "name": "azureFirewall",
+ "type": "Microsoft.Common.DropDown",
+ "visible": true,
+ "label": "Hub azure firewall",
+ "defaultValue": "",
+ "toolTip": "Select the existing Hub Azure firewall.",
+ "constraints": {
+ "required": true,
+ "allowedValues": "[map(steps('basics').hub.azureFirewallsApi.value, (item) => parse(concat('{\"label\":\"', item.name, '\",\"value\":\"', item.id, '\"}')))]"
+ }
+ }
+ ]
+ },
+ {
+ "name": "location",
+ "type": "Microsoft.Common.LocationSelector",
+ "label": "Location",
+ "toolTip": "Select the location for the ZTA resources, etc.",
+ "resourceTypes": [
+ "Microsoft.Compute/galleries"
+ ]
+ },
+ {
+ "name": "naming",
+ "type": "Microsoft.Common.Section",
+ "label": "Naming Components",
+ "elements": [
+ {
+ "name": "description",
+ "type": "Microsoft.Common.TextBlock",
+ "options": {
+ "text": "The values selected below will be used as components in your naming convention to name your Azure resource groups and resources. For more information on the naming convention used in this solution, refer to the documentation.",
+ "link": {
+ }
+ }
+ },
+ {
+ "name": "identifier",
+ "type": "Microsoft.Common.TextBox",
+ "label": "Identifier",
+ "toolTip": "Input a 3 character identifier for the resource group and resource names created with this solution. The identifier should represent a unique value within your organization, such as a business unit or project.",
+ "placeholder": "Example: ms",
+ "constraints": {
+ "required": true,
+ "regex": "^[a-z0-9A-Z]{1,3}$",
+ "validationMessage": "The value must be 1 - 3 characters in length and must be alphanumeric."
+ }
+ }
+ ]
+ },
+ {
+ "name": "ResourceGroupApi",
+ "visible": false,
+ "type": "Microsoft.Solutions.ArmApiControl",
+ "defaultValue": "",
+ "request": {
+ "method": "GET",
+ "path": "[concat(steps('basics').subscriptions.spoke, '/resourceGroups?api-version=2021-04-01')]"
+ }
+ },
+ {
+ "name": "existingResourceGroup",
+ "type": "Microsoft.Common.OptionsGroup",
+ "label": "Use an existing resource group",
+ "defaultValue": "false",
+ "toolTip": "",
+ "constraints": {
+ "allowedValues": [
+ {
+ "label": "True",
+ "value": true
+ },
+ {
+ "label": "False",
+ "value": false
+ }
+ ],
+ "required": true
+ },
+ "visible": true
+ },
+ {
+ "name": "existingResourceGroupName",
+ "label": "Existing resource group",
+ "type": "Microsoft.Common.DropDown",
+ "defaultValue": "",
+ "toolTip": "Select the existing resource group to target",
+ "multiselect": false,
+ "selectAll": false,
+ "filter": true,
+ "visible": "[equals(steps('basics').existingResourceGroup, true)]",
+ "filterPlaceholder": "Filter items ...",
+ "multiLine": true,
+ "constraints": {
+ "allowedValues": "[map(steps('basics').ResourceGroupApi.value, (item) => parse(concat('{\"label\":\"', item.name, '\",\"value\":\"', item.name, '\"}')))]",
+ "required": true
+ }
+ },
+ {
+ "name": "newResourceGroup",
+ "type": "Microsoft.Common.TextBox",
+ "label": "New resource group name",
+ "defaultValue": "",
+ "toolTip": "New resource group name",
+ "placeholder": "",
+ "multiLine": false,
+ "constraints": {
+ "required": true,
+ "validations": []
+ },
+ "visible": "[equals(steps('basics').existingResourceGroup, false)]"
+ }
+ ]
+ },
+ {
+ "name": "spoke",
+ "label": "Spoke",
+ "elements": [
+ {
+ "name": "deployDefender",
+ "type": "Microsoft.Common.OptionsGroup",
+ "label": "Deploy Defender",
+ "defaultValue": [
+ "No"
+ ],
+ "toolTip": "Select True to deploy defender to the ZTA spoke",
+ "constraints": {
+ "allowedValues": [
+ {
+ "label": "True",
+ "value": true
+ },
+ {
+ "label": "False",
+ "value": false
+ }
+ ],
+ "required": true
+ },
+ "visible": true
+ },
+ {
+ "name": "emailSecurityContact",
+ "type": "Microsoft.Common.TextBox",
+ "label": "Email",
+ "defaultValue": "",
+ "toolTip": "Please enter a valid email account",
+ "constraints": {
+ "required": false,
+ "regex": "^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\\.[a-zA-Z0-9-.]+$",
+ "validationMessage": "Email is not valid. Please re-enter."
+ },
+ "visible": "[steps('spoke').deployDefender]"
+ },
+ {
+ "name": "deployPolicy",
+ "type": "Microsoft.Common.OptionsGroup",
+ "label": "Deploy Policy",
+ "defaultValue": [
+ false
+ ],
+ "toolTip": "Select True to deploy defender to the ZTA spoke",
+ "constraints": {
+ "allowedValues": [
+ {
+ "label": "True",
+ "value": true
+ },
+ {
+ "label": "False",
+ "value": false
+ }
+ ],
+ "required": true
+ },
+ "visible": true
+ },
+ {
+ "name": "policy",
+ "type": "Microsoft.Common.OptionsGroup",
+ "label": "Select Policy",
+ "defaultValue": "",
+ "toolTip": "Select True to install Outlook",
+ "constraints": {
+ "allowedValues": [
+ {
+ "label": "NISTRev4",
+ "value": "NISTRev4"
+ },
+ {
+ "label": "NISTRev5",
+ "value": "NISTRev5"
+ },
+ {
+ "label": "IL5",
+ "value": "IL5"
+ },
+ {
+ "label": "CMMC",
+ "value": "CMMC"
+ }
+ ],
+ "required": true
+ },
+ "visible": "[steps('spoke').deployPolicy]"
+ },
+ {
+ "name": "logAnalyticsWorkspace",
+ "type": "Microsoft.Solutions.ResourceSelector",
+ "label": "Existing Log Analytics Workspace for Central Logging",
+ "visible": true,
+ "resourceType": "Microsoft.OperationalInsights/workspaces",
+ "toolTip": "Select the log analytics workspace used for collecting security data for Sentinel or Defender for Cloud.",
+ "options": {}
+ },
+ {
+ "name": "networking",
+ "label": "Networking",
+ "type": "Microsoft.Common.Section",
+ "elements": [
+ {
+ "name": "virtualNetworkAddressCidrRange",
+ "label": "Virtual network CIDR range",
+ "type": "Microsoft.Common.TextBox",
+ "defaultValue": "10.0.131.0/24",
+ "toolTip": "Specify an address CIDR range within the range [10,24].",
+ "constraints": {
+ "required": true,
+ "validations": [
+ {
+ "regex": "^(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(?:\/(1[0-9]|2[0-6]))$",
+ "message": "Invalid CIDR range. The address prefix must be in the range [10,26]."
+ }
+ ]
+ }
+ },
+ {
+ "name": "subnetAddressCidrRange",
+ "label": "Subnet CIDR range",
+ "type": "Microsoft.Common.TextBox",
+ "defaultValue": "10.0.131.0/24",
+ "toolTip": "Specify a CIDR range for the default subnet within the Shared Services Virtual Network range [24].",
+ "constraints": {
+ "required": true,
+ "validations": [
+ {
+ "regex": "^(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(?:\/(2[4-8]))$",
+ "message": "Invalid CIDR range. The address prefix must be in the range [26,28]."
+ },
+ {
+ "isValid": "[if(greaterOrEquals(last(split(steps('spoke').networking.virtualNetworkAddressCidrRange, '/')), 8), equals(last(take(split(first(split(steps('spoke').networking.virtualNetworkAddressCidrRange, '/')), '.'), 1)), last(take(split(first(split(steps('spoke').networking.subnetAddressCidrRange, '/')), '.'), 1))), true)]",
+ "message": "CIDR range not within virtual network CIDR range (first octet)."
+ },
+ {
+ "isValid": "[if(greaterOrEquals(last(split(steps('spoke').networking.virtualNetworkAddressCidrRange, '/')), 16), equals(last(take(split(first(split(steps('spoke').networking.virtualNetworkAddressCidrRange, '/')), '.'), 2)), last(take(split(first(split(steps('spoke').networking.subnetAddressCidrRange, '/')), '.'), 2))), true)]",
+ "message": "CIDR range not within virtual network CIDR range (second octet)."
+ },
+ {
+ "isValid": "[if(greaterOrEquals(last(split(steps('spoke').networking.virtualNetworkAddressCidrRange, '/')), 24), equals(last(take(split(first(split(steps('spoke').networking.virtualNetworkAddressCidrRange, '/')), '.'), 3)), last(take(split(first(split(steps('spoke').networking.subnetAddressCidrRange, '/')), '.'), 3))), true)]",
+ "message": "CIDR range not within virtual network CIDR range (third octet)."
+ },
+ {
+ "isValid": "[lessOrEquals(last(split(steps('spoke').networking.virtualNetworkAddressCidrRange, '/')), last(split(steps('spoke').networking.subnetAddressCidrRange, '/')))]",
+ "message": "CIDR range not within virtual network CIDR range (subnet mask)."
+ }
+ ]
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "name": "source",
+ "label": "Source",
+ "elements": [
+ {
+ "name": "type",
+ "type": "Microsoft.Common.OptionsGroup",
+ "label": "Type of image",
+ "defaultValue": "Azure Marketplace",
+ "toolTip": "Select the desired Azure service for the source image.",
+ "constraints": {
+ "allowedValues": [
+ {
+ "label": "Azure Compute Gallery",
+ "value": "AzureComputeGallery"
+ },
+ {
+ "label": "Azure Marketplace",
+ "value": "AzureMarketplace"
+ }
+ ],
+ "required": true
+ },
+ "visible": true
+ },
+ {
+ "name": "marketplace",
+ "type": "Microsoft.Common.Section",
+ "label": "Azure Marketplace",
+ "visible": "[equals(steps('source').type, 'AzureMarketplace')]",
+ "elements": [
+ {
+ "name": "publisher",
+ "type": "Microsoft.Common.OptionsGroup",
+ "label": "Publisher",
+ "defaultValue": "Microsoft Windows Desktop",
+ "toolTip": "Select the desired marketplace image publisher.",
+ "constraints": {
+ "allowedValues": [
+ {
+ "label": "Microsoft Windows Desktop",
+ "value": "MicrosoftWindowsDesktop"
+ },
+ {
+ "label": "Microsoft Windows Server",
+ "value": "MicrosoftWindowsServer"
+ }
+ ],
+ "required": true
+ },
+ "visible": true
+ },
+ {
+ "name": "offersApi",
+ "type": "Microsoft.Solutions.ArmApiControl",
+ "request": {
+ "method": "GET",
+ "path": "[concat(steps('basics').subscriptions.spoke, '/providers/Microsoft.Compute/locations/', steps('basics').location.name, '/publishers/', steps('source').marketplace.publisher, '/artifacttypes/vmimage/offers?api-version=2023-07-01')]"
+ }
+ },
+ {
+ "name": "offer",
+ "type": "Microsoft.Common.DropDown",
+ "label": "Offer",
+ "defaultValue": "",
+ "toolTip": "Select the desired marketplace image offer.",
+ "constraints": {
+ "allowedValues": "[map(steps('source').marketplace.offersApi, (item) => parse(concat('{\"label\":\"', item.name, '\",\"value\":\"', item.name, '\"}')))]",
+ "required": true
+ }
+ },
+ {
+ "name": "skusApi",
+ "type": "Microsoft.Solutions.ArmApiControl",
+ "request": {
+ "method": "GET",
+ "path": "[concat(steps('basics').subscriptions.spoke, '/providers/Microsoft.Compute/locations/', steps('basics').location.name, '/publishers/', steps('source').marketplace.publisher, '/artifacttypes/vmimage/offers/', steps('source').marketplace.offer, '/skus?api-version=2023-07-01')]"
+ }
+ },
+ {
+ "name": "sku",
+ "type": "Microsoft.Common.DropDown",
+ "label": "SKU",
+ "defaultValue": "win11-22h2-avd",
+ "toolTip": "Select the desired marketplace image SKU.",
+ "constraints": {
+ "allowedValues": "[map(steps('source').marketplace.skusApi, (item) => parse(concat('{\"label\":\"', item.name, '\",\"value\":\"', item.name, '\"}')))]",
+ "required": true
+ }
+ }
+ ]
+ },
+ {
+ "name": "gallery",
+ "type": "Microsoft.Common.Section",
+ "label": "Compute Gallery",
+ "visible": "[equals(steps('source').type, 'AzureComputeGallery')]",
+ "elements": [
+ {
+ "name": "gallery",
+ "type": "Microsoft.Solutions.ResourceSelector",
+ "label": "Compute gallery",
+ "resourceType": "Microsoft.Compute/galleries",
+ "options": {
+ "filter": {
+ "subscription": "onBasics",
+ "location": "onBasics"
+ }
+ }
+ },
+ {
+ "name": "imageDefinitionApi",
+ "type": "Microsoft.Solutions.ArmApiControl",
+ "request": {
+ "method": "GET",
+ "path": "[concat(steps('source').gallery.gallery.id, '/images?api-version=2022-03-03')]"
+ }
+ },
+ {
+ "name": "imageDefinition",
+ "type": "Microsoft.Common.DropDown",
+ "label": "Image Definition",
+ "defaultValue": "",
+ "toolTip": "Select the desired image definition.",
+ "constraints": {
+ "allowedValues": "[map(steps('source').gallery.imageDefinitionApi.value, (item) => parse(concat('{\"label\":\"', item.name, '\",\"value\":\"', item.id, '\"}')))]",
+ "required": true
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "name": "destination",
+ "label": "Destination",
+ "elements": [
+ {
+ "name": "computeGalleryName",
+ "type": "Microsoft.Common.TextBox",
+ "label": "Compute gallery name",
+ "defaultValue": "",
+ "placeholder": "Example: cg_avd_d_eu",
+ "toolTip": "Inpute the name for the Compute Gallery.",
+ "multiLine": false,
+ "constraints": {
+ "required": true,
+ "validations": [
+ {
+ "regex": "^(?:[a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\\._]{0,78}[a-zA-Z0-9])$",
+ "message": "The value must be between 1 - 80 characters. The value may only contain alphanumerics, periods, and underscores. The value must start and end with an alphanumeric."
+ }
+ ]
+ },
+ "visible": true
+ },
+ {
+ "name": "imageDefinitionNamePrefix",
+ "type": "Microsoft.Common.TextBox",
+ "label": "Image definition name prefix",
+ "defaultValue": "",
+ "placeholder": "Example: developer"
+ },
+ {
+ "name": "imageVersion",
+ "type": "Microsoft.Common.Section",
+ "label": "Image version",
+ "elements": [
+ {
+ "name": "replicaCount",
+ "type": "Microsoft.Common.Slider",
+ "min": 1,
+ "max": 50,
+ "label": "Replica count",
+ "subLabel": "count",
+ "defaultValue": 1,
+ "showStepMarkers": false,
+ "toolTip": "Regional replica count which specifies the number of replicas you want to create per region",
+ "constraints": {
+ "required": false
+ },
+ "visible": true
+ },
+ {
+ "name": "excludeFromLatest",
+ "type": "Microsoft.Common.CheckBox",
+ "label": "Exclude from latest",
+ "defaultValue": true,
+ "toolTip": "Determines whether the image version will be the latest available version."
+ },
+ {
+ "name": "majorVersion",
+ "type": "Microsoft.Common.Slider",
+ "min": 1,
+ "max": 12,
+ "label": "Image Major Version. The minor and patch versions will be auto generated.",
+ "subLabel": "Maj. Version",
+ "defaultValue": 1,
+ "showStepMarkers": false,
+ "toolTip": "Pick the size in MB",
+ "constraints": {
+ "required": false
+ },
+ "visible": true,
+ "required": true
+ },
+ {
+ "name": "minorVersion",
+ "type": "Microsoft.Common.Slider",
+ "min": 1,
+ "max": 12,
+ "label": "Image Patch Version. The minor version will be auto generated.",
+ "subLabel": "Patch Version",
+ "defaultValue": 1,
+ "showStepMarkers": false,
+ "toolTip": "Pick the size in MB",
+ "constraints": {
+ "required": false
+ },
+ "visible": true,
+ "required": true
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "name": "storage",
+ "label": "Storage",
+ "elements": [
+ {
+ "name": "storageSelector",
+ "type": "Microsoft.Solutions.ResourceSelector",
+ "label": "Select storage account",
+ "resourceType": "Microsoft.Storage/storageAccounts",
+ "options": {
+ "filter": {
+ "subscription": "[steps('basics').subscriptions.spoke]",
+ "location": "[steps('basics').location.name]"
+ }
+ }
+ },
+ {
+ "name": "containerApi",
+ "type": "Microsoft.Solutions.ArmApiControl",
+ "request": {
+ "method": "GET",
+ "path": "[concat(steps('storage').storageSelector.id, '/blobServices/default/containers?api-version=2023-01-01')]"
+ }
+ },
+ {
+ "name": "container",
+ "type": "Microsoft.Common.DropDown",
+ "visible": true,
+ "label": "Container",
+ "defaultValue": "",
+ "toolTip": "Select an existing container.",
+ "constraints": {
+ "required": true,
+ "allowedValues": "[map(steps('storage').containerApi.value, (item) => parse(concat('{\"label\":\"', item.name, '\",\"value\":\"', item.id, '\"}')))]"
+ }
+ }
+ ]
+ },
+ {
+ "name": "virtualMachines",
+ "label": "Virtual Machines",
+ "elements": [
+ {
+ "name": "userAssignedIdentityName",
+ "type": "Microsoft.Common.TextBox",
+ "label": "User assigned identity name",
+ "defaultValue": "",
+ "toolTip": "Input the name for the User Assigned Identity.",
+ "placeholder": "Example: uai-image-d-eu",
+ "multiLine": false,
+ "constraints": {
+ "required": true,
+ "validations": [
+ {
+ "regex": "^[a-zA-Z0-9][a-zA-Z0-9_-]{2,127}$",
+ "message": " The value must be between 2 - 127 characters. The value may only contain alphanumerics, hyphens, and underscores. The value must start with an alphanumeric."
+ }
+ ]
+ },
+ "visible": true
+ },
+ {
+ "name": "vmSkusApi",
+ "type": "Microsoft.Solutions.ArmApiControl",
+ "request": {
+ "method": "GET",
+ "path": "[decodeUriComponent(concat(encodeUriComponent(steps('basics').subscriptions.spoke), '%2Fproviders%2FMicrosoft.Compute%2Fskus%3Fapi-version%3D2021-07-01%26%24filter%3Dlocation%20eq%20%27', steps('basics').location.name, '%27'))]"
+ }
+ },
+ {
+ "name": "vmSize",
+ "type": "Microsoft.Common.DropDown",
+ "label": "Virtual Machine Size",
+ "defaultValue": [
+ "Standard_D4ads_v5"
+ ],
+ "toolTip": "Select the size of the virtual machines. Multi-session hosts should have 4 - 24 vCPUs. Single session host should have 2 or more vCPUs.",
+ "multiselect": false,
+ "selectAll": false,
+ "filter": true,
+ "filterPlaceholder": "Filter items ...",
+ "multiLine": true,
+ "defaultDescription": "",
+ "constraints": {
+ "allowedValues": "[map(filter(steps('virtualMachines').vmSkusApi.value, (item) => equals(item.resourceType, 'virtualMachines')), (item) => parse(concat('{\"label\":\"', item.name, '\",\"value\":\"', item.name, '\"}')))]",
+ "required": true
+ },
+ "visible": true
+ },
+ {
+ "name": "localAdminCredentials",
+ "type": "Microsoft.Common.Section",
+ "visible": true,
+ "label": "Local administrator credential",
+ "elements": [
+ {
+ "name": "username",
+ "type": "Microsoft.Common.TextBox",
+ "label": "Username",
+ "defaultValue": "",
+ "placeholder": "Example: xadmin",
+ "toolTip": "Input the username for the local administrator account.",
+ "constraints": {
+ "required": true,
+ "regex": "",
+ "validationMessage": ""
+ },
+ "visible": true
+ },
+ {
+ "name": "password",
+ "type": "Microsoft.Common.PasswordBox",
+ "label": {
+ "password": "Password",
+ "confirmPassword": "Confirm Password"
+ },
+ "toolTip": "Input the password for the local administrator account.",
+ "constraints": {
+ "required": true,
+ "regex": "^(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=.*[@#$%^&+=_!*<>()])(?=\\S+$).{12,123}$",
+ "validationMessage": "The value must be within 12 to 123 characters, be alphanumeric, and include 1 lower case character, 1 upper case character, 1 number, and 1 special character that is not '\\' or '-'."
+ },
+ "options": {
+ "hideConfirmation": false
+ },
+ "visible": true
+ }
+ ]
+ },
+ {
+ "name": "hybridUseBenefit",
+ "type": "Microsoft.Common.CheckBox",
+ "label": "Enable hybrid use benefit",
+ "defaultValue": false,
+ "toolTip": "Enables the hybrid use benefit to reduce the cost of Azure virutal machines when the appropriate licensing and software assurance has been purchased."
+ },
+ {
+ "name": "diskEncryptionSetSelector",
+ "type": "Microsoft.Solutions.ResourceSelector",
+ "label": "Select disk encryption set",
+ "resourceType": "Microsoft.Compute/diskEncryptionSets",
+ "options": {
+ "filter": {
+ "subscription": "onBasics",
+ "location": "onBasics"
+ }
+ }
+ },
+ {
+ "name": "exemption",
+ "type": "Microsoft.Common.EditableGrid",
+ "ariaLabel": "Enter the policy IDs to exempt to prevent virtual machine extensions on the imaging virtual machines.",
+ "label": "Policy Exemptions",
+ "constraints": {
+ "width": "Full",
+ "rows": {
+ "count": {
+ "min": 0,
+ "max": 100
+ }
+ },
+ "columns": [
+ {
+ "id": "id",
+ "header": "Policy Assignment Resource IDs for Exemption",
+ "width": "1fr",
+ "element": {
+ "type": "Microsoft.Common.TextBox",
+ "placeholder": "",
+ "constraints": {
+ "required": true,
+ "validations": []
+ }
+ }
+ }
+ ]
+ }
+ }
+ ]
+ },
+ {
+ "name": "customizations",
+ "label": "Customizations",
+ "elements": [
+ {
+ "name": "customSoftware",
+ "type": "Microsoft.Common.OptionsGroup",
+ "label": "customSoftware",
+ "defaultValue": [
+ "No"
+ ],
+ "toolTip": "Select True to add custom software to the image",
+ "constraints": {
+ "allowedValues": [
+ {
+ "label": "Yes",
+ "value": true
+ },
+ {
+ "label": "No",
+ "value": false
+ }
+ ],
+ "required": true
+ },
+ "visible": true
+ },
+ {
+ "name": "customizations",
+ "type": "Microsoft.Common.EditableGrid",
+ "ariaLabel": "Customizations",
+ "label": "Customizations",
+ "visible": "[steps('customizations').customSoftware]",
+ "constraints": {
+ "width": "Full",
+ "rows": {
+ "count": {
+ "min": 0,
+ "max": 10
+ }
+ },
+ "columns": [
+ {
+ "id": "name",
+ "header": "Name",
+ "width": "1fr",
+ "element": {
+ "type": "Microsoft.Common.TextBox",
+ "placeholder": "Example: vscode",
+ "constraints": {
+ "required": true,
+ "validations": []
+ }
+ }
+ },
+ {
+ "id": "blobname",
+ "header": "Blobname",
+ "width": "10fr",
+ "element": {
+ "type": "Microsoft.Common.TextBox",
+ "placeholder": "Example: VSCodeSetup-x64-1.81.1.exe",
+ "constraints": {
+ "allowedValues": [
+ {
+ "label": "blobname",
+ "value": "text"
+ }
+ ],
+ "required": true
+ }
+ }
+ },
+ {
+ "id": "arguments",
+ "header": "Arguments",
+ "width": "10fr",
+ "element": {
+ "type": "Microsoft.Common.TextBox",
+ "placeholder": "Example: /silent /mergetasks='!runcode'",
+ "constraints": {
+ "allowedValues": [
+ {
+ "label": "Arguments",
+ "value": "text"
+ }
+ ],
+ "required": false
+ }
+ }
+ }
+ ]
+ }
+ },
+ {
+ "name": "office",
+ "type": "Microsoft.Common.Section",
+ "label": "Software",
+ "elements": [
+ {
+ "name": "installOffice",
+ "type": "Microsoft.Common.OptionsGroup",
+ "label": "Install Office",
+ "defaultValue": "false",
+ "toolTip": "Select True to install Office",
+ "constraints": {
+ "allowedValues": [
+ {
+ "label": "true",
+ "value": true
+ },
+ {
+ "label": "false",
+ "value": false
+ }
+ ],
+ "required": true
+ }
+ },
+ {
+ "name": "officeBlob",
+ "type": "Microsoft.Common.TextBox",
+ "label": "Office Installer (.exe)",
+ "defaultValue": "officedeploymenttool_16626-20148.exe",
+ "toolTip": "Input the file / blob name for the AVD Agent installer.",
+ "placeholder": "",
+ "multiLine": false,
+ "constraints": {
+ "required": true,
+ "validations": [
+ {
+ "isValid": "[endsWith(steps('customizations').office, '.exe')]",
+ "message": "The file name must end with '.exe'."
+ }
+ ]
+ },
+ "visible": "[steps('customizations').office.installOffice]"
+ },
+ {
+ "name": "installAccess",
+ "type": "Microsoft.Common.OptionsGroup",
+ "label": "InstallAccess",
+ "defaultValue": "false",
+ "toolTip": "Select True to install Access",
+ "constraints": {
+ "allowedValues": [
+ {
+ "label": "true",
+ "value": true
+ },
+ {
+ "label": "false",
+ "value": false
+ }
+ ],
+ "required": true
+ },
+ "visible": "[steps('customizations').office.installOffice]"
+ },
+ {
+ "name": "installExcel",
+ "type": "Microsoft.Common.OptionsGroup",
+ "label": "installExcel",
+ "defaultValue": "false",
+ "toolTip": "Select True to install Excel",
+ "constraints": {
+ "allowedValues": [
+ {
+ "label": "true",
+ "value": true
+ },
+ {
+ "label": "false",
+ "value": false
+ }
+ ],
+ "required": true
+ },
+ "visible": "[steps('customizations').office.installOffice]"
+ },
+ {
+ "name": "installOneDrive",
+ "type": "Microsoft.Common.OptionsGroup",
+ "label": "Install One Dive For Business",
+ "defaultValue": "false",
+ "toolTip": "Select True to Install One Dive For Business",
+ "constraints": {
+ "allowedValues": [
+ {
+ "label": "true",
+ "value": true
+ },
+ {
+ "label": "false",
+ "value": false
+ }
+ ],
+ "required": true
+ },
+ "visible": "[steps('customizations').office.installOffice]"
+ },
+ {
+ "name": "installOneNote",
+ "type": "Microsoft.Common.OptionsGroup",
+ "label": "Install OneNote",
+ "defaultValue": "false",
+ "toolTip": "Select True to install OneNote",
+ "constraints": {
+ "allowedValues": [
+ {
+ "label": "true",
+ "value": true
+ },
+ {
+ "label": "false",
+ "value": false
+ }
+ ],
+ "required": true
+ },
+ "visible": "[steps('customizations').office.installOffice]"
+ },
+ {
+ "name": "installOutlook",
+ "type": "Microsoft.Common.OptionsGroup",
+ "label": "Install Outlook",
+ "defaultValue": "false",
+ "toolTip": "Select True to install Outlook",
+ "constraints": {
+ "allowedValues": [
+ {
+ "label": "true",
+ "value": true
+ },
+ {
+ "label": "false",
+ "value": false
+ }
+ ],
+ "required": true
+ },
+ "visible": "[steps('customizations').office.installOffice]"
+ },
+ {
+ "name": "installPowerPoint",
+ "type": "Microsoft.Common.OptionsGroup",
+ "label": "Install PowerPoint",
+ "defaultValue": "false",
+ "toolTip": "Select True to Install PowerPoint",
+ "constraints": {
+ "allowedValues": [
+ {
+ "label": "true",
+ "value": true
+ },
+ {
+ "label": "false",
+ "value": false
+ }
+ ],
+ "required": true
+ },
+ "visible": "[steps('customizations').office.installOffice]"
+ },
+ {
+ "name": "installProject",
+ "type": "Microsoft.Common.OptionsGroup",
+ "label": "Install Project",
+ "defaultValue": "false",
+ "toolTip": "Select True to install Project",
+ "constraints": {
+ "allowedValues": [
+ {
+ "label": "true",
+ "value": true
+ },
+ {
+ "label": "false",
+ "value": false
+ }
+ ],
+ "required": true
+ },
+ "visible": "[steps('customizations').office.installOffice]"
+ },
+ {
+ "name": "installPublisher",
+ "type": "Microsoft.Common.OptionsGroup",
+ "label": "Install Publisher",
+ "defaultValue": "false",
+ "toolTip": "Select True to install Publisher",
+ "constraints": {
+ "allowedValues": [
+ {
+ "label": "true",
+ "value": true
+ },
+ {
+ "label": "false",
+ "value": false
+ }
+ ],
+ "required": true
+ },
+ "visible": "[steps('customizations').office.installOffice]"
+ },
+ {
+ "name": "installSkypeForBusiness",
+ "type": "Microsoft.Common.OptionsGroup",
+ "label": "Install Skype For Business",
+ "defaultValue": "false",
+ "toolTip": "Select True to install Skype For Business",
+ "constraints": {
+ "allowedValues": [
+ {
+ "label": "true",
+ "value": true
+ },
+ {
+ "label": "false",
+ "value": false
+ }
+ ],
+ "required": true
+ },
+ "visible": "[steps('customizations').office.installOffice]"
+ },
+ {
+ "name": "installVisio",
+ "type": "Microsoft.Common.OptionsGroup",
+ "label": "installVisio",
+ "defaultValue": "false",
+ "toolTip": "Select True to install Visio",
+ "constraints": {
+ "allowedValues": [
+ {
+ "label": "true",
+ "value": true
+ },
+ {
+ "label": "false",
+ "value": false
+ }
+ ],
+ "required": true
+ },
+ "visible": "[steps('customizations').office.installOffice]"
+ },
+ {
+ "name": "installWord",
+ "type": "Microsoft.Common.OptionsGroup",
+ "label": "Install Word",
+ "defaultValue": "false",
+ "toolTip": "Select True to install Word",
+ "constraints": {
+ "allowedValues": [
+ {
+ "label": "true",
+ "value": true
+ },
+ {
+ "label": "false",
+ "value": false
+ }
+ ],
+ "required": true
+ },
+ "visible": "[steps('customizations').office.installOffice]"
+ },
+ {
+ "name": "installTeams",
+ "type": "Microsoft.Common.OptionsGroup",
+ "label": "Install Teams",
+ "defaultValue": "false",
+ "toolTip": "Select True to install Teams",
+ "constraints": {
+ "allowedValues": [
+ {
+ "label": "true",
+ "value": true
+ },
+ {
+ "label": "false",
+ "value": false
+ }
+ ],
+ "required": true
+ },
+ "visible": true
+ },
+ {
+ "name": "teamsBlob",
+ "type": "Microsoft.Common.TextBox",
+ "label": "Team Installer (.msi)",
+ "defaultValue": "Teams_windows_x64.msi",
+ "toolTip": "Input the file / blob name for the Teams installer.",
+ "placeholder": "",
+ "multiLine": false,
+ "constraints": {
+ "required": true,
+ "validations": [
+ {
+ "isValid": "[endsWith(steps('customizations').office.teamsBlob, '.msi')]",
+ "message": "The file name must end with '.msi'."
+ }
+ ]
+ },
+ "visible": "[steps('customizations').office.installTeams]"
+ },
+ {
+ "name": "msrdcwebrtcsvcInstaller",
+ "type": "Microsoft.Common.TextBox",
+ "label": "Remote Desktop WebRTC Redirector Service Installer (.msi)",
+ "defaultValue": "MsRdcWebRTCSvc_HostSetup_1.33.2302.07001_x64.msi",
+ "toolTip": "Input the file / blob name for the Remote Desktop WebRTC Redirector Service installer.",
+ "placeholder": "",
+ "multiLine": false,
+ "constraints": {
+ "required": true,
+ "validations": [
+ {
+ "isValid": "[endsWith(steps('customizations').office.msrdcwebrtcsvcInstaller, '.msi')]",
+ "message": "The file name must end with '.msi'."
+ }
+ ]
+ },
+ "visible": "[steps('customizations').office.installTeams]"
+ },
+ {
+ "name": "vcRedistInstaller",
+ "type": "Microsoft.Common.TextBox",
+ "label": "Microsoft Visual C++ Redistributable Installer (.exe)",
+ "defaultValue": "VC_redist.x64.exe",
+ "toolTip": "Input the file / blob name for the Microsoft Visual C++ Redistributable installer.",
+ "placeholder": "",
+ "multiLine": false,
+ "constraints": {
+ "required": true,
+ "validations": [
+ {
+ "isValid": "[endsWith(steps('customizations').office.vcRedistInstaller, '.exe')]",
+ "message": "The file name must end with '.exe'."
+ }
+ ]
+ },
+ "visible": "[steps('customizations').office.installTeams]"
+ },
+ {
+ "name": "installVirtualDesktopOptimizationTool",
+ "type": "Microsoft.Common.OptionsGroup",
+ "label": "Install Virtual Desktop OptimizationTool",
+ "defaultValue": "false",
+ "toolTip": "Select True to install Virtual Desktop OptimizationTool",
+ "constraints": {
+ "allowedValues": [
+ {
+ "label": "true",
+ "value": true
+ },
+ {
+ "label": "false",
+ "value": false
+ }
+ ],
+ "required": true
+ },
+ "visible": true
+ },
+ {
+ "name": "vDotBlob",
+ "type": "Microsoft.Common.TextBox",
+ "label": "Microsoft Visual C++ Redistributable Installer (.zip)",
+ "defaultValue": "Virtual-Desktop-Optimization-Tool-main.zip",
+ "toolTip": "Input the file / blob name for the VDOT installer zip.",
+ "placeholder": "",
+ "multiLine": false,
+ "constraints": {
+ "required": true,
+ "validations": [
+ {
+ "isValid": "[endsWith(steps('customizations').office.vDotBlob, '.zip')]",
+ "message": "The file name must end with '.zip'."
+ }
+ ]
+ },
+ "visible": "[steps('customizations').office.installVirtualDesktopOptimizationTool]"
+ },
+ {
+ "name": "installArcGisPro",
+ "type": "Microsoft.Common.OptionsGroup",
+ "label": "Install ArcGis Pro",
+ "defaultValue": "false",
+ "toolTip": "Select True to install ArcGisPro",
+ "constraints": {
+ "allowedValues": [
+ {
+ "label": "true",
+ "value": true
+ },
+ {
+ "label": "false",
+ "value": false
+ }
+ ],
+ "required": true
+ }
+ },
+ {
+ "name": "arcGisBlob",
+ "type": "Microsoft.Common.TextBox",
+ "label": "ArcGIS Pro Installer ZIP File (.zip)",
+ "defaultValue": "ArcGisPro.zip",
+ "toolTip": "Input the file / blob name for the arcgispro installer zip.",
+ "placeholder": "",
+ "multiLine": false,
+ "constraints": {
+ "required": true,
+ "validations": [
+ {
+ "isValid": "[endsWith(steps('customizations').office.arcGisBlob, '.zip')]",
+ "message": "The file name must end with '.zip'."
+ }
+ ]
+ },
+ "visible": "[steps('customizations').office.installArcGisPro]"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "name": "automation",
+ "label": "Build Automation",
+ "elements": [
+ {
+ "name": "enable",
+ "type": "Microsoft.Common.CheckBox",
+ "label": "Enable build automation",
+ "defaultValue": true,
+ "toolTip": "Enables the automation of image builds using an Automation Account in a zero trust compliant configuration."
+ },
+ {
+ "name": "automationAccount",
+ "type": "Microsoft.Common.TextBox",
+ "label": "Automation account name",
+ "toolTip": "Input the name for the automation account.",
+ "visible": "[steps('automation').enable]",
+ "placeholder": "Example: aa-image-d-eu",
+ "constraints": {
+ "required": true,
+ "regex": "^[a-zA-Z][a-zA-Z0-9-]{4,48}[a-zA-Z0-9]$",
+ "validationMessage": "The value must be 6 - 50 characters in length. The value must contain alphanumerics and hyphens, start with a letter, and end with an alphanumeric."
+ }
+ },
+ {
+ "name": "keyVault",
+ "type": "Microsoft.Common.TextBox",
+ "label": "Key vault name",
+ "toolTip": "Input the name for the key vault.",
+ "visible": "[steps('automation').enable]",
+ "placeholder": "Example: kv-image-d-eu",
+ "constraints": {
+ "required": true,
+ "regex": "^(?!.*-{2}.*)([a-zA-Z][a-zA-Z0-9-]{1,22}[a-zA-Z0-9])$",
+ "validationMessage": "The value must be 3 - 24 characters in length. The value must contain alphanumerics and hyphens, start with a letter, and end with an alphanumeric."
+ }
+ },
+ {
+ "name": "privateDnsZones",
+ "type": "Microsoft.Common.Section",
+ "label": "Private DNS zones",
+ "visible": "[steps('automation').enable]",
+ "elements": [
+ {
+ "name": "subscription",
+ "visible": true,
+ "type": "Microsoft.Common.SubscriptionSelector"
+ },
+ {
+ "name": "api",
+ "type": "Microsoft.Solutions.ArmApiControl",
+ "request": {
+ "method": "GET",
+ "path": "[concat('/subscriptions/', steps('automation').privateDnsZones.subscription.subscriptionId, '/providers/Microsoft.Network/privateDnsZones?api-version=2018-09-01')]"
+ }
+ },
+ {
+ "name": "automationAccount",
+ "type": "Microsoft.Common.DropDown",
+ "visible": true,
+ "label": "Automation account",
+ "defaultValue": "",
+ "multiLine": true,
+ "toolTip": "Select the existing Private DNS Zone for Azure Automation.",
+ "constraints": {
+ "required": true,
+ "allowedValues": "[map(filter(steps('automation').privateDnsZones.api.value, (item) => contains(item.name, 'privatelink.azure-automation.')), (item) => parse(concat('{\"label\":\"', item.name, '\",\"description\":\"Resource group: ', first(skip(split(item.id, '/'), 4)), '\",\"value\":\"', item.id, '\"}')))]"
+ }
+ },
+ {
+ "name": "keyVault",
+ "type": "Microsoft.Common.DropDown",
+ "visible": true,
+ "label": "Key vault",
+ "defaultValue": "",
+ "multiLine": true,
+ "toolTip": "Select the existing Private DNS Zone for Key Vaults.",
+ "constraints": {
+ "required": true,
+ "allowedValues": "[map(filter(steps('automation').privateDnsZones.api.value, (item) => contains(item.name, 'privatelink.vaultcore.')), (item) => parse(concat('{\"label\":\"', item.name, '\",\"description\":\"Resource group: ', first(skip(split(item.id, '/'), 4)), '\",\"value\":\"', item.id, '\"}')))]"
+ }
+ }
+ ]
+ },
+ {
+ "name": "hybridWorker",
+ "type": "Microsoft.Common.Section",
+ "label": "Hybrid Worker",
+ "visible": "[steps('automation').enable]",
+ "elements": [
+ {
+ "name": "name",
+ "type": "Microsoft.Common.TextBox",
+ "visible": true,
+ "label": "Virtual machine name",
+ "toolTip": "Input a custom name for the virtual machine.",
+ "placeholder": "Example: vmhwimagedeu",
+ "constraints": {
+ "required": true
+ }
+ },
+ {
+ "name": "domainJoin",
+ "type": "Microsoft.Common.CheckBox",
+ "label": "Domain Join",
+ "defaultValue": true,
+ "toolTip": "Enables the automation of image builds using an Automation Account in a zero trust compliant configuration."
+ },
+ {
+ "name": "domainName",
+ "type": "Microsoft.Common.TextBox",
+ "visible": "[steps('automation').hybridWorker.domainJoin]",
+ "label": "Domain Name",
+ "toolTip": "Provide the domain name for Active Directory Domain Services.",
+ "placeholder": "Example: contoso.com",
+ "constraints": {
+ "required": true
+ }
+ },
+ {
+ "name": "ouPath",
+ "type": "Microsoft.Common.TextBox",
+ "visible": "[steps('automation').hybridWorker.domainJoin]",
+ "label": "OU Path",
+ "toolTip": "Input the distinguished name of the desired organization unit for the AVD session hosts.",
+ "placeholder": "Example: OU=imaging,OU=avd,DC=contoso,DC=com",
+ "constraints": {
+ "required": true
+ }
+ },
+ {
+ "name": "domainJoinUserPrincipalName",
+ "type": "Microsoft.Common.TextBox",
+ "label": "Domain join user principal name",
+ "visible": "[steps('automation').hybridWorker.domainJoin]",
+ "toolTip": "Enter the user principal name with domain join privileges.",
+ "placeholder": "Example: domainjoin@contoso.com",
+ "constraints": {
+ "required": true,
+ "regex": "^[a-z0-9A-Z_.-]+@(?:[a-z0-9]+\\.)+[a-z]+$",
+ "validationMessage": "The value must be a valid user principal name."
+ }
+ },
+ {
+ "name": "domainJoinPassword",
+ "type": "Microsoft.Common.PasswordBox",
+ "label": {
+ "password": "Domain join password"
+ },
+ "visible": "[steps('automation').hybridWorker.domainJoin]",
+ "toolTip": "Enter a password that is alphanumeric, contains at least 12 characters, 1 letter, 1 number and 1 special character.",
+ "constraints": {
+ "required": true
+ },
+ "options": {
+ "hideConfirmation": true
+ }
+ }
+ ]
+ },
+ {
+ "name": "monitoring",
+ "type": "Microsoft.Common.Section",
+ "label": "Monitoring",
+ "visible": "[steps('automation').enable]",
+ "elements": [
+ {
+ "name": "enable",
+ "type": "Microsoft.Common.CheckBox",
+ "visible": true,
+ "label": "Enable monitoring",
+ "defaultValue": false,
+ "toolTip": "Deploy the required resources to enable monitoring for the automation runbook."
+ },
+ {
+ "name": "logAnalyticsWorkspace",
+ "type": "Microsoft.Solutions.ResourceSelector",
+ "label": "Existing log analytics workspace",
+ "visible": "[steps('automation').monitoring.enable]",
+ "resourceType": "Microsoft.OperationalInsights/workspaces",
+ "toolTip": "Select the log analytics workspace to capture runbook log output.",
+ "options": {}
+ },
+ {
+ "name": "actionGroup",
+ "type": "Microsoft.Common.TextBox",
+ "label": "Action Group",
+ "placeholder": "Example: ag-image-d-eu",
+ "defaultValue": "",
+ "toolTip": "Input the name for the action group.",
+ "constraints": {
+ "required": true,
+ "regex": "",
+ "validationMessage": ""
+ },
+ "visible": "[steps('automation').monitoring.enable]"
+ },
+ {
+ "name": "distributionGroup",
+ "type": "Microsoft.Common.TextBox",
+ "visible": "[steps('automation').monitoring.enable]",
+ "label": "Distribution group",
+ "toolTip": "Input the distribution group for receiving alerts on the build status.",
+ "placeholder": "Example: operations@contoso.com",
+ "constraints": {
+ "required": true,
+ "regex": "^[a-z0-9A-Z_.-]+@(?:[a-z0-9]+\\.)+[a-z]+$",
+ "validationMessage": "The value must be a valid email address."
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "name": "tags",
+ "label": "Tags",
+ "elements": [
+ {
+ "name": "tags",
+ "type": "Microsoft.Common.TagsByResource",
+ "resources": [
+ "Microsoft.Automation/automationAccounts",
+ "Microsoft.Compute/galleries",
+ "Microsoft.Compute/virtualMachines",
+ "Microsoft.Insights/actionGroups",
+ "Microsoft.Insights/scheduledQueryRules",
+ "Microsoft.KeyVault/vaults",
+ "Microsoft.ManagedIdentity/userAssignedIdentities",
+ "Microsoft.Network/networkInterfaces",
+ "Microsoft.Network/privateEndpoints",
+ "Microsoft.Resources/templateSpecs"
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ "outputs": {
+ "parameters": {
+ "actionGroupName": "[if(and(steps('automation').enable, steps('automation').monitoring.enable), steps('automation').monitoring.actionGroup, '')]",
+ "arcGisProInstaller": "[if(equals(steps('customizations').office.installArcGisPro, true), steps('customizations').office.arcGisBlob.blobName,'')]",
+ "automationAccountName": "[if(steps('automation').enable, steps('automation').automationAccount, '')]",
+ "automationAccountPrivateDnsZoneResourceId": "[if(steps('automation').enable, steps('automation').privateDnsZones.automationAccount, '')]",
+ "computeGalleryImageResourceId": "[if(equals(steps('source').type, 'AzureComputeGallery'), steps('source').gallery.imageDefinition, '')]",
+ "computeGalleryName": "[steps('destination').computeGalleryName]",
+ "containerName": "[first(skip(split(steps('storage').container, '/'), 12))]",
+ "customizations": "[if(equals(steps('customizations').customSoftware, true), steps('customizations').customizations,'')]",
+ "diskEncryptionSetResourceId": "[steps('virtualMachines').diskEncryptionSetSelector.id]",
+ "distributionGroup": "[if(and(steps('automation').enable, steps('automation').monitoring.enable), steps('automation').monitoring.distributionGroup, '')]",
+ "domainJoinPassword": "[steps('automation').hybridWorker.domainJoinPassword]",
+ "domainJoinUserPrincipalName": "[steps('automation').hybridWorker.domainJoinUserPrincipalName]",
+ "domainName": "[if(steps('automation').enable, steps('automation').hybridWorker.domainName, '')]",
+ "enableBuildAutomation": "[steps('automation').enable]",
+ "excludeFromLatest": "[steps('destination').imageVersion.excludeFromLatest]",
+ "exemptPolicyAssignmentIds": "[map(steps('virtualMachines').exemption, (item) => item.id)]",
+ "hybridUseBenefit": "[steps('virtualMachines').hybridUseBenefit]",
+ "hybridWorkerName": "[if(steps('automation').enable, steps('automation').hybridWorker.name, '')]",
+ "imageDefinitionNamePrefix": "[steps('destination').imageDefinitionNamePrefix]",
+ "imageMajorVersion": "[steps('destination').imageVersion.majorVersion]",
+ "imageMinorVersion": "[steps('destination').imageVersion.minorVersion]",
+ "installAccess": "[if(equals(steps('customizations').office.installOffice, true), steps('customizations').office.installAccess,'false')]",
+ "installArcGisPro": "[if(equals(steps('customizations').office.installArcGisPro, true), steps('customizations').office.installArcGisPro,'false')]",
+ "installExcel": "[if(equals(steps('customizations').office.installOffice, true), steps('customizations').office.installExcel,'false')]",
+ "installOneDrive": "[if(equals(steps('customizations').office.installOffice, true), steps('customizations').office.installOneDrive,'false')]",
+ "installOneNote": "[if(equals(steps('customizations').office.installOffice, true), steps('customizations').office.installOneNote,'false')]",
+ "installOutlook": "[if(equals(steps('customizations').office.installOffice, true), steps('customizations').office.installOutlook,'false')]",
+ "installPowerPoint": "[if(equals(steps('customizations').office.installOffice, true), steps('customizations').office.installPowerPoint,'false')]",
+ "installProject": "[if(equals(steps('customizations').office.installOffice, true), steps('customizations').office.installProject,'false')]",
+ "installPublisher": "[if(equals(steps('customizations').office.installOffice, true), steps('customizations').office.installPublisher,'false')]",
+ "installSkypeForBusiness": "[if(equals(steps('customizations').office.installOffice, true), steps('customizations').office.installSkypeForBusiness,'false')]",
+ "installTeams": "[steps('customizations').office.installTeams]",
+ "installVirtualDesktopOptimizationTool": "[steps('customizations').office.installVirtualDesktopOptimizationTool]",
+ "installVisio": "[if(equals(steps('customizations').office.installOffice, true), steps('customizations').office.installVisio,'false')]",
+ "installWord": "[if(equals(steps('customizations').office.installOffice, true), steps('customizations').office.installWord,'false')]",
+ "deployDefender": "[steps('spoke').deployDefender]",
+ "deployPolicy": "[steps('spoke').deployPolicy]",
+ "policy": "[steps('spoke').policy]",
+ "emailSecurityContact": "[if(equals(steps('spoke').deployDefender, true), steps('spoke').emailSecurityContact , '')]",
+ "resourcePrefix": "[steps('basics').naming.identifier]",
+ "hubSubscriptionId": "[replace(steps('basics').subscriptions.hub, '/subscriptions/', '')]",
+ "hubResourceGroupName": "[first(skip(split(steps('basics').hub.azureFirewall, '/'), 4))]",
+ "hubVirtualNetworkName": "[first(skip(split(steps('basics').hub.virtualNetwork, '/'), 8))]",
+ "workloadSubscriptionId": "[replace(steps('basics').subscriptions.spoke, '/subscriptions/', '')]",
+ "azureFirewallName": "[first(skip(split(steps('basics').hub.azureFirewall, '/'), 8))]",
+ "virtualNetworkAddressPrefix": "[steps('spoke').networking.virtualNetworkAddressCidrRange]",
+ "subnetAddressPrefix": "[steps('spoke').networking.subnetAddressCidrRange]",
+ "keyVaultName": "[if(steps('automation').enable, steps('automation').keyVault, '')]",
+ "keyVaultPrivateDnsZoneResourceId": "[if(steps('automation').enable, steps('automation').privateDnsZones.keyVault, '')]",
+ "localAdministratorPassword": "[steps('virtualMachines').localAdminCredentials.password]",
+ "localAdministratorUsername": "[steps('virtualMachines').localAdminCredentials.username]",
+ "location": "[steps('basics').location.name]",
+ "logAnalyticsWorkspaceName": "[steps('spoke').logAnalyticsWorkspace.name]",
+ "logAnalyticsWorkspaceResourceId": "[if(and(steps('automation').enable, steps('automation').monitoring.enable), steps('automation').monitoring.logAnalyticsWorkspace.id, '')]",
+ "marketplaceImageOffer": "[if(equals(steps('source').type, 'AzureMarketplace'), steps('source').marketplace.offer, '')]",
+ "marketplaceImagePublisher": "[if(equals(steps('source').type, 'AzureMarketplace'), steps('source').marketplace.publisher, '')]",
+ "marketplaceImageSKU": "[if(equals(steps('source').type, 'AzureMarketplace'), steps('source').marketplace.sku, '')]",
+ "msrdcwebrtcsvcInstaller": "[if(equals(steps('customizations').office.installTeams, true), steps('customizations').office.msrdcwebrtcsvcInstaller.blobName,'')]",
+ "existingResourceGroup": "[steps('basics').existingResourceGroup]",
+ "officeInstaller": "[if(equals(steps('customizations').office.installOffice, true), steps('customizations').office.officeBlob.blobName,'')]",
+ "oUPath": "[if(and(steps('automation').enable, steps('automation').hybridWorker.domainJoin), steps('automation').hybridWorker.ouPath, '')]",
+ "replicaCount": "[steps('destination').imageVersion.replicaCount]",
+ "resourceGroupName": "[if(equals(steps('basics').existingResourceGroup, true), steps('basics').existingResourceGroupName ,steps('basics').newResourceGroup)]",
+ "sourceImageType": "[steps('source').type]",
+ "storageAccountResourceId": "[steps('storage').storageSelector.id]",
+ "spokelogAnalyticsWorkspaceResourceId": "[steps('spoke').logAnalyticsWorkspace.id]",
+ "tags": "[steps('tags').tags]",
+ "teamsInstaller": "[if(equals(steps('customizations').office.installTeams, true), steps('customizations').office.teamsBlob.blobName,'')]",
+ "userAssignedIdentityName": "[steps('virtualMachines').userAssignedIdentityName]",
+ "vcRedistInstaller": "[if(equals(steps('customizations').office.installTeams, true), steps('customizations').office.vcRedistInstaller.blobName,'')]",
+ "vDOTInstaller": "[if(equals(steps('customizations').office.installVirtualDesktopOptimizationTool, true), steps('customizations').office.vDotBlob.blobName,'')]",
+ "virtualMachineSize": "[steps('virtualMachines').vmSize]"
+ },
+ "kind": "Subscription",
+ "location": "[steps('basics').location.name]",
+ "subscriptionId": "[steps('basics').subscriptions.spoke]"
+ }
+ }
+}
\ No newline at end of file