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