diff --git a/avm/1.1.0/res/compute/gallery/image/main.bicep b/avm/1.1.0/res/compute/gallery/image/main.bicep index ae277e2cf..e5f2cb520 100644 --- a/avm/1.1.0/res/compute/gallery/image/main.bicep +++ b/avm/1.1.0/res/compute/gallery/image/main.bicep @@ -180,7 +180,7 @@ resource image 'Microsoft.Compute/galleries/images@2024-03-03' = { osState: osState osType: osType privacyStatementUri: privacyStatementUri - purchasePlan: purchasePlan ?? null + //purchasePlan: purchasePlan ?? null recommended: { vCPUs: vCPUs, memory: memory } releaseNoteUri: releaseNoteUri } diff --git a/readme.md b/readme.md index f8ceec14b..e394201b9 100644 --- a/readme.md +++ b/readme.md @@ -70,20 +70,11 @@ The brownfield, add-ons and tools section, contains templates to deploy addition ### Custom image build -[Getting Started](/workload/docs/getting-started-custom-image-build.md) deploying a custom image based on the latest version of the Azure marketplace image to an Azure Compute Gallery. The following images are offered: +[Getting Started](/workload/docs/getting-started-custom-image-build.md) deploying a custom image based on the latest version of the Azure marketplace image to an Azure Compute Gallery. -- Windows 10 22H2 (Gen 2) -- Windows 11 22H2 (Gen 2) -- Windows 11 23H2 (Gen 2) -- Windows 11 24H2 (Gen 2) -- Windows 10 22H2 with O365 (Gen 2) -- Windows 11 22H2 with O365 (Gen 2) -- Windows 11 23H2 with O365 (Gen 2) -- Windows 11 24H2 with O365 (Gen 2) +You can select to enable the Trusted Launch or Confidential VM security type feature on the Azure Compute Gallery image definition. -You can also select to enable the Trusted Launch or Confidential VM security type feature on the Azure Compute Gallery image definition. - -Custom image is optimized using [Virtual Desktop Optimization Tool (VDOT)](https://github.com/The-Virtual-Desktop-Team/Virtual-Desktop-Optimization-Tool) and patched with the latest Windows updates. +Custom image is patched with the latest Windows updates. | Deployment Type | Link | |:--|:--| diff --git a/workload/arm/deploy-custom-image.json b/workload/arm/deploy-custom-image.json index 00a789eca..ede350d2f 100644 --- a/workload/arm/deploy-custom-image.json +++ b/workload/arm/deploy-custom-image.json @@ -5,7 +5,7 @@ "_generator": { "name": "bicep", "version": "0.34.44.8038", - "templateHash": "3806508458741125004" + "templateHash": "8421234447417327651" }, "name": "AVD Accelerator - Baseline Custom Image Deployment", "description": "AVD Accelerator - Custom Image Baseline" @@ -301,21 +301,32 @@ "description": "Set the data retention in the number of days for the Log Analytics Workspace. (Default: 30)" } }, - "operatingSystemImage": { + "mpImageOffer": { "type": "string", - "defaultValue": "win11_23h2", - "allowedValues": [ - "win10_22h2_g2", - "win10_22h2_office_g2", - "win11_22h2", - "win11_22h2_office", - "win11_23h2", - "win11_23h2_office", - "win11_24h2", - "win11_24h2_office" - ], + "defaultValue": "Office-365", + "metadata": { + "description": "Market place AVD OS image offer. (Default: Office-365)" + } + }, + "mpImageSku": { + "type": "string", + "defaultValue": "win11-24h2-avd-m365", + "metadata": { + "description": "Market place AVD OS image SKU. (Default: win11-24h2-avd-m365)" + } + }, + "mpImagePublisher": { + "type": "string", + "defaultValue": "MicrosoftWindowsDesktop", + "metadata": { + "description": "Market place AVD OS image publisher." + } + }, + "mpImageVersion": { + "type": "string", + "defaultValue": "latest", "metadata": { - "description": "AVD OS image source. (Default: win11_23h2)" + "description": "Market place AVD OS image version." } }, "operationsTeamTag": { @@ -680,7 +691,7 @@ "varBaseScriptUri": "https://raw.githubusercontent.com/Azure/avdaccelerator/main/workload/", "varCommonResourceTags": "[if(parameters('enableResourceTags'), createObject('ImageBuildName', parameters('imageBuildNameTag'), 'WorkloadName', parameters('workloadNameTag'), 'DataClassification', parameters('dataClassificationTag'), 'Department', parameters('departmentTag'), 'Criticality', if(equals(parameters('criticalityTag'), 'Custom'), parameters('criticalityCustomTag'), parameters('criticalityTag')), 'ApplicationName', parameters('applicationNameTag'), 'OpsTeam', parameters('operationsTeamTag'), 'Owner', parameters('ownerTag'), 'CostCenter', parameters('costCenterTag'), 'Environment', parameters('environmentTag')), createObject())]", "varCustomizationSteps": "[union(variables('varScriptCustomizers'), variables('varRemainingCustomizers'))]", - "varImageDefinitionName": "[if(parameters('customNaming'), parameters('imageDefinitionCustomName'), format('avd-{0}', parameters('operatingSystemImage')))]", + "varImageDefinitionName": "[if(parameters('customNaming'), parameters('imageDefinitionCustomName'), format('avd-{0}-{1}', parameters('mpImageOffer'), parameters('mpImageSku')))]", "varImageGalleryName": "[if(parameters('customNaming'), parameters('imageGalleryCustomName'), format('gal_avd_{0}', variables('varNamingStandard')))]", "varImageReplicationRegions": "[if(empty(parameters('imageVersionDisasterRecoveryLocation')), createArray(parameters('imageVersionPrimaryLocation')), createArray(parameters('imageVersionPrimaryLocation'), parameters('imageVersionDisasterRecoveryLocation')))]", "varImageTemplateBuildAutomationName": "Image Template Build Automation", @@ -702,7 +713,7 @@ ] } ], - "varImageTemplateName": "[if(parameters('customNaming'), parameters('imageTemplateCustomName'), format('it-avd-{0}', parameters('operatingSystemImage')))]", + "varImageTemplateName": "[if(parameters('customNaming'), parameters('imageTemplateCustomName'), format('it-avd-{0}', parameters('mpImageOffer')))]", "varLocationAcronym": "[variables('varLocations')[variables('varLocation')].acronym]", "varLocation": "[toLower(replace(parameters('deploymentLocation'), ' ', ''))]", "varLocations": "[variables('$fxv#0')]", @@ -711,95 +722,21 @@ { "name": "Az.Accounts", "uri": "https://www.powershellgallery.com/api/v2/package", - "version": "2.12.1" + "version": "4.0.2" }, { "name": "Az.ImageBuilder", "uri": "https://www.powershellgallery.com/api/v2/package", - "version": "0.3.0" + "version": "0.4.1" } ], "varNamingStandard": "[format('{0}', variables('varLocationAcronym'))]", - "varOperatingSystemImageDefinitions": { - "win10_22h2_g2": { - "osType": "Windows", - "osState": "Generalized", - "offer": "windows-10", - "publisher": "MicrosoftWindowsDesktop", - "sku": "win10-22h2-avd-g2", - "hyperVGeneration": "V2", - "version": "latest" - }, - "win10_22h2_office_g2": { - "osType": "Windows", - "osState": "Generalized", - "offer": "office-365", - "publisher": "MicrosoftWindowsDesktop", - "sku": "win10-22h2-avd-m365-g2", - "hyperVGeneration": "V2", - "version": "latest" - }, - "win11_22h2": { - "osType": "Windows", - "osState": "Generalized", - "offer": "windows-11", - "publisher": "MicrosoftWindowsDesktop", - "sku": "win11-22h2-avd", - "hyperVGeneration": "V2", - "version": "latest" - }, - "win11_22h2_office": { - "osType": "Windows", - "osState": "Generalized", - "offer": "office-365", - "publisher": "MicrosoftWindowsDesktop", - "sku": "win11-22h2-avd-m365", - "hyperVGeneration": "V2", - "version": "latest" - }, - "win11_23h2": { - "osType": "Windows", - "osState": "Generalized", - "offer": "windows-11", - "publisher": "MicrosoftWindowsDesktop", - "sku": "win11-23h2-avd", - "hyperVGeneration": "V2", - "version": "latest" - }, - "win11_23h2_office": { - "osType": "Windows", - "osState": "Generalized", - "offer": "office-365", - "publisher": "MicrosoftWindowsDesktop", - "sku": "win11-23h2-avd-m365", - "hyperVGeneration": "V2", - "version": "latest" - }, - "win11_24h2": { - "osType": "Windows", - "osState": "Generalized", - "offer": "windows-11", - "publisher": "MicrosoftWindowsDesktop", - "sku": "win11-24h2-avd", - "hyperVGeneration": "V2", - "version": "latest" - }, - "win11_24h2_office": { - "osType": "Windows", - "osState": "Generalized", - "offer": "office-365", - "publisher": "MicrosoftWindowsDesktop", - "sku": "win11-24h2-avd-m365", - "hyperVGeneration": "V2", - "version": "latest" - } - }, "varRdpShortPathCustomizer": "[if(parameters('rdpShortPathManagedNetworks'), createArray(createObject('type', 'PowerShell', 'name', 'rdpShortPath', 'runElevated', true(), 'runAsSystem', true(), 'scriptUri', format('{0}scripts/Set-RdpShortpath.ps1', variables('varBaseScriptUri')))), createArray())]", "varRemainingCustomizers": [ { "type": "WindowsRestart", "restartCheckCommand": "Write-Host \"Restarting post script customizers\"", - "restarttimeout": "10m" + "restartTimeout": "10m" }, { "type": "WindowsUpdate", @@ -823,7 +760,7 @@ { "type": "WindowsRestart", "restartCheckCommand": "Write-Host \"restarting post Windows updates\"", - "restarttimeout": "10m" + "restartTimeout": "10m" }, { "type": "PowerShell", @@ -837,7 +774,7 @@ }, { "type": "WindowsRestart", - "restarttimeout": "10m" + "restartTimeout": "10m" } ], "varResourceGroupName": "[if(parameters('customNaming'), parameters('resourceGroupCustomName'), format('rg-avd-{0}-shared-services', variables('varNamingStandard')))]", @@ -895,11 +832,117 @@ "_generator": { "name": "bicep", "version": "0.34.44.8038", - "templateHash": "5574722192240323807" + "templateHash": "13222459540303852206" }, "name": "Resource Groups", - "description": "This module deploys a Resource Group.", - "owner": "Azure/module-maintainers" + "description": "This module deploys a Resource Group." + }, + "definitions": { + "lockType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Specify the name of lock." + } + }, + "kind": { + "type": "string", + "allowedValues": [ + "CanNotDelete", + "None", + "ReadOnly" + ], + "nullable": true, + "metadata": { + "description": "Optional. Specify the type of lock." + } + } + }, + "metadata": { + "description": "An AVM-aligned type for a lock.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.4.1" + } + } + }, + "roleAssignmentType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." + } + }, + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, or its fully qualified ID in the following format: '/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11'." + } + }, + "principalId": { + "type": "string", + "metadata": { + "description": "Required. The principal ID of the principal (user/group/identity) to assign the role to." + } + }, + "principalType": { + "type": "string", + "allowedValues": [ + "Device", + "ForeignGroup", + "Group", + "ServicePrincipal", + "User" + ], + "nullable": true, + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The description of the role assignment." + } + }, + "condition": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." + } + }, + "conditionVersion": { + "type": "string", + "allowedValues": [ + "2.0" + ], + "nullable": true, + "metadata": { + "description": "Optional. Version of the condition." + } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Resource Id of the delegated managed identity resource." + } + } + }, + "metadata": { + "description": "An AVM-aligned type for a role assignment.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.4.1" + } + } + } }, "parameters": { "name": { @@ -915,6 +958,23 @@ "description": "Optional. Location of the Resource Group. It uses the deployment's location when not provided." } }, + "lock": { + "$ref": "#/definitions/lockType", + "nullable": true, + "metadata": { + "description": "Optional. The lock settings of the service." + } + }, + "roleAssignments": { + "type": "array", + "items": { + "$ref": "#/definitions/roleAssignmentType" + }, + "nullable": true, + "metadata": { + "description": "Optional. Array of role assignments to create." + } + }, "tags": { "type": "object", "nullable": true, @@ -934,7 +994,7 @@ "avmTelemetry": { "condition": "[parameters('enableTelemetry')]", "type": "Microsoft.Resources/deployments", - "apiVersion": "2023-07-01", + "apiVersion": "2024-03-01", "name": "[format('46d3xbcp.res.resources-resourcegroup.{0}.{1}', replace('-..--..-', '.', '-'), substring(uniqueString(deployment().name, parameters('location')), 0, 4))]", "location": "[parameters('location')]", "properties": { @@ -959,64 +1019,310 @@ "location": "[parameters('location')]", "tags": "[parameters('tags')]", "properties": {} - } - }, - "outputs": { - "name": { - "type": "string", - "metadata": { - "description": "The name of the resource group." - }, - "value": "[parameters('name')]" }, - "resourceId": { - "type": "string", - "metadata": { - "description": "The resource ID of the resource group." + "resourceGroup_lock": { + "condition": "[and(not(empty(coalesce(parameters('lock'), createObject()))), not(equals(tryGet(parameters('lock'), 'kind'), 'None')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-RG-Lock', uniqueString(deployment().name, parameters('location')))]", + "resourceGroup": "[parameters('name')]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "lock": { + "value": "[parameters('lock')]" + }, + "name": { + "value": "[parameters('name')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.34.44.8038", + "templateHash": "14849465419930962285" + } + }, + "definitions": { + "lockType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Specify the name of lock." + } + }, + "kind": { + "type": "string", + "allowedValues": [ + "CanNotDelete", + "None", + "ReadOnly" + ], + "nullable": true, + "metadata": { + "description": "Optional. Specify the type of lock." + } + } + }, + "nullable": true + } + }, + "parameters": { + "lock": { + "$ref": "#/definitions/lockType", + "metadata": { + "description": "Optional. The lock settings of the service." + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the Resource Group." + } + } + }, + "resources": { + "resourceGroup_lock": { + "condition": "[and(not(empty(coalesce(parameters('lock'), createObject()))), not(equals(tryGet(parameters('lock'), 'kind'), 'None')))]", + "type": "Microsoft.Authorization/locks", + "apiVersion": "2020-05-01", + "name": "[coalesce(tryGet(parameters('lock'), 'name'), format('lock-{0}', parameters('name')))]", + "properties": { + "level": "[coalesce(tryGet(parameters('lock'), 'kind'), '')]", + "notes": "[if(equals(tryGet(parameters('lock'), 'kind'), 'CanNotDelete'), 'Cannot delete resource or child resources.', 'Cannot delete or modify the resource or child resources.')]" + } + } + } + } }, - "value": "[subscriptionResourceId('Microsoft.Resources/resourceGroups', parameters('name'))]" + "dependsOn": [ + "resourceGroup" + ] }, - "location": { - "type": "string", - "metadata": { - "description": "The location the resource was deployed into." - }, - "value": "[reference('resourceGroup', '2021-04-01', 'full').location]" - } - } - } - } - }, - { - "copy": { - "name": "roleDefinitions", - "count": "[length(range(0, length(variables('varRoles'))))]" - }, - "type": "Microsoft.Resources/deployments", - "apiVersion": "2022-09-01", - "name": "[format('Role-Definition-{0}-{1}', range(0, length(variables('varRoles')))[copyIndex()], parameters('time'))]", - "subscriptionId": "[parameters('sharedServicesSubId')]", - "location": "[deployment().location]", - "properties": { - "expressionEvaluationOptions": { - "scope": "inner" - }, - "mode": "Incremental", - "parameters": { - "subscriptionId": { - "value": "[parameters('sharedServicesSubId')]" - }, - "description": { - "value": "[variables('varRoles')[range(0, length(variables('varRoles')))[copyIndex()]].description]" - }, - "roleName": { - "value": "[variables('varRoles')[range(0, length(variables('varRoles')))[copyIndex()]].name]" - }, - "actions": { - "value": "[variables('varRoles')[range(0, length(variables('varRoles')))[copyIndex()]].actions]" - }, - "assignableScopes": { - "value": [ + "resourceGroup_roleAssignments": { + "condition": "[not(empty(coalesce(parameters('roleAssignments'), createArray())))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-RG-RoleAssignments', uniqueString(deployment().name, parameters('location')))]", + "resourceGroup": "[parameters('name')]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "roleAssignments": { + "value": "[parameters('roleAssignments')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.34.44.8038", + "templateHash": "11051527294196156545" + } + }, + "definitions": { + "roleAssignmentType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." + } + }, + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, or its fully qualified ID in the following format: '/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11'." + } + }, + "principalId": { + "type": "string", + "metadata": { + "description": "Required. The principal ID of the principal (user/group/identity) to assign the role to." + } + }, + "principalType": { + "type": "string", + "allowedValues": [ + "Device", + "ForeignGroup", + "Group", + "ServicePrincipal", + "User" + ], + "nullable": true, + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The description of the role assignment." + } + }, + "condition": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." + } + }, + "conditionVersion": { + "type": "string", + "allowedValues": [ + "2.0" + ], + "nullable": true, + "metadata": { + "description": "Optional. Version of the condition." + } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Resource Id of the delegated managed identity resource." + } + } + } + }, + "nullable": true + } + }, + "parameters": { + "roleAssignments": { + "$ref": "#/definitions/roleAssignmentType", + "metadata": { + "description": "Optional. Array of role assignments to create." + } + } + }, + "variables": { + "copy": [ + { + "name": "formattedRoleAssignments", + "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]", + "input": "[union(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')], createObject('roleDefinitionId', coalesce(tryGet(variables('builtInRoleNames'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName), if(contains(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName)))))]" + } + ], + "builtInRoleNames": { + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Quota Request Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '0e5f05e5-9ab9-446b-b98d-1e2157c94125')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Resource Policy Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608')]", + "Role Based Access Control Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168')]", + "Tag Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '4a9ae827-6dc8-4573-8ac7-8239d42aa03f')]", + "Template Spec Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '1c9b6475-caf0-4164-b5a1-2142a7116f4b')]", + "Template Spec Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '392ae280-861d-42bd-9ea5-08ee6d83b80e')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]" + } + }, + "resources": { + "resourceGroup_roleAssignments": { + "copy": { + "name": "resourceGroup_roleAssignments", + "count": "[length(coalesce(variables('formattedRoleAssignments'), createArray()))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2022-04-01", + "name": "[coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'name'), guid(resourceGroup().id, coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId, coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId))]", + "properties": { + "roleDefinitionId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId]", + "principalId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId]", + "description": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'description')]", + "principalType": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'principalType')]", + "condition": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition')]", + "conditionVersion": "[if(not(empty(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition'))), coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'conditionVersion'), '2.0'), null())]", + "delegatedManagedIdentityResourceId": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'delegatedManagedIdentityResourceId')]" + } + } + } + } + }, + "dependsOn": [ + "resourceGroup" + ] + } + }, + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the resource group." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the resource group." + }, + "value": "[subscriptionResourceId('Microsoft.Resources/resourceGroups', parameters('name'))]" + }, + "location": { + "type": "string", + "metadata": { + "description": "The location the resource was deployed into." + }, + "value": "[reference('resourceGroup', '2021-04-01', 'full').location]" + } + } + } + } + }, + { + "copy": { + "name": "roleDefinitions", + "count": "[length(range(0, length(variables('varRoles'))))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('Role-Definition-{0}-{1}', range(0, length(variables('varRoles')))[copyIndex()], parameters('time'))]", + "subscriptionId": "[parameters('sharedServicesSubId')]", + "location": "[deployment().location]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "subscriptionId": { + "value": "[parameters('sharedServicesSubId')]" + }, + "description": { + "value": "[variables('varRoles')[range(0, length(variables('varRoles')))[copyIndex()]].description]" + }, + "roleName": { + "value": "[variables('varRoles')[range(0, length(variables('varRoles')))[copyIndex()]].name]" + }, + "actions": { + "value": "[variables('varRoles')[range(0, length(variables('varRoles')))[copyIndex()]].actions]" + }, + "assignableScopes": { + "value": [ "[format('/subscriptions/{0}', parameters('sharedServicesSubId'))]" ] } @@ -1163,18 +1469,49 @@ "_generator": { "name": "bicep", "version": "0.34.44.8038", - "templateHash": "11657260805865946801" + "templateHash": "8296616101364210198" }, "name": "User Assigned Identities", - "description": "This module deploys a User Assigned Identity.", - "owner": "Azure/module-maintainers" + "description": "This module deploys a User Assigned Identity." }, "definitions": { + "lockType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Specify the name of lock." + } + }, + "kind": { + "type": "string", + "allowedValues": [ + "CanNotDelete", + "None", + "ReadOnly" + ], + "nullable": true, + "metadata": { + "description": "Optional. Specify the type of lock." + } + } + }, + "nullable": true + }, "roleAssignmentType": { "type": "array", "items": { "type": "object", "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." + } + }, "roleDefinitionIdOrName": { "type": "string", "metadata": { @@ -1235,6 +1572,42 @@ } }, "nullable": true + }, + "federatedIdentityCredentialsType": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the federated identity credential." + } + }, + "audiences": { + "type": "array", + "items": { + "type": "string" + }, + "metadata": { + "description": "Required. The list of audiences that can appear in the issued token." + } + }, + "issuer": { + "type": "string", + "metadata": { + "description": "Required. The URL of the issuer to be trusted." + } + }, + "subject": { + "type": "string", + "metadata": { + "description": "Required. The identifier of the external identity." + } + } + } + }, + "nullable": true } }, "parameters": { @@ -1251,6 +1624,18 @@ "description": "Optional. Location for all resources." } }, + "federatedIdentityCredentials": { + "$ref": "#/definitions/federatedIdentityCredentialsType", + "metadata": { + "description": "Optional. The federated identity credentials list to indicate which token from the external IdP should be trusted by your application. Federated identity credentials are supported on applications only. A maximum of 20 federated identity credentials can be added per application object." + } + }, + "lock": { + "$ref": "#/definitions/lockType", + "metadata": { + "description": "Optional. The lock settings of the service." + } + }, "roleAssignments": { "$ref": "#/definitions/roleAssignmentType", "metadata": { @@ -1273,13 +1658,20 @@ } }, "variables": { + "copy": [ + { + "name": "formattedRoleAssignments", + "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]", + "input": "[union(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')], createObject('roleDefinitionId', coalesce(tryGet(variables('builtInRoleNames'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName), if(contains(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName)))))]" + } + ], "builtInRoleNames": { "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", "Managed Identity Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'e40ec5ca-96e0-45a2-b4ff-59039f2c2b59')]", "Managed Identity Operator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f1a07417-d97a-45cb-824c-7a7467783830')]", "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", - "Role Based Access Control Administrator (Preview)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168')]", + "Role Based Access Control Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168')]", "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]" } }, @@ -1287,7 +1679,7 @@ "avmTelemetry": { "condition": "[parameters('enableTelemetry')]", "type": "Microsoft.Resources/deployments", - "apiVersion": "2023-07-01", + "apiVersion": "2024-03-01", "name": "[format('46d3xbcp.res.managedidentity-userassignedidentity.{0}.{1}', replace('-..--..-', '.', '-'), substring(uniqueString(deployment().name, parameters('location')), 0, 4))]", "properties": { "mode": "Incremental", @@ -1311,23 +1703,154 @@ "location": "[parameters('location')]", "tags": "[parameters('tags')]" }, + "userAssignedIdentity_lock": { + "condition": "[and(not(empty(coalesce(parameters('lock'), createObject()))), not(equals(tryGet(parameters('lock'), 'kind'), 'None')))]", + "type": "Microsoft.Authorization/locks", + "apiVersion": "2020-05-01", + "scope": "[format('Microsoft.ManagedIdentity/userAssignedIdentities/{0}', parameters('name'))]", + "name": "[coalesce(tryGet(parameters('lock'), 'name'), format('lock-{0}', parameters('name')))]", + "properties": { + "level": "[coalesce(tryGet(parameters('lock'), 'kind'), '')]", + "notes": "[if(equals(tryGet(parameters('lock'), 'kind'), 'CanNotDelete'), 'Cannot delete resource or child resources.', 'Cannot delete or modify the resource or child resources.')]" + }, + "dependsOn": [ + "userAssignedIdentity" + ] + }, "userAssignedIdentity_roleAssignments": { "copy": { "name": "userAssignedIdentity_roleAssignments", - "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]" + "count": "[length(coalesce(variables('formattedRoleAssignments'), createArray()))]" }, "type": "Microsoft.Authorization/roleAssignments", "apiVersion": "2022-04-01", "scope": "[format('Microsoft.ManagedIdentity/userAssignedIdentities/{0}', parameters('name'))]", - "name": "[guid(resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', parameters('name')), coalesce(parameters('roleAssignments'), createArray())[copyIndex()].principalId, coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName)]", + "name": "[coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'name'), guid(resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', parameters('name')), coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId, coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId))]", + "properties": { + "roleDefinitionId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId]", + "principalId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId]", + "description": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'description')]", + "principalType": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'principalType')]", + "condition": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition')]", + "conditionVersion": "[if(not(empty(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition'))), coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'conditionVersion'), '2.0'), null())]", + "delegatedManagedIdentityResourceId": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'delegatedManagedIdentityResourceId')]" + }, + "dependsOn": [ + "userAssignedIdentity" + ] + }, + "userAssignedIdentity_federatedIdentityCredentials": { + "copy": { + "name": "userAssignedIdentity_federatedIdentityCredentials", + "count": "[length(coalesce(parameters('federatedIdentityCredentials'), createArray()))]", + "mode": "serial", + "batchSize": 1 + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-UserMSI-FederatedIdentityCredential-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", "properties": { - "roleDefinitionId": "[if(contains(variables('builtInRoleNames'), coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName), variables('builtInRoleNames')[coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName], if(contains(coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/'), coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName)))]", - "principalId": "[coalesce(parameters('roleAssignments'), createArray())[copyIndex()].principalId]", - "description": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'description')]", - "principalType": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'principalType')]", - "condition": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'condition')]", - "conditionVersion": "[if(not(empty(tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'condition'))), coalesce(tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'conditionVersion'), '2.0'), null())]", - "delegatedManagedIdentityResourceId": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'delegatedManagedIdentityResourceId')]" + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[coalesce(parameters('federatedIdentityCredentials'), createArray())[copyIndex()].name]" + }, + "userAssignedIdentityName": { + "value": "[parameters('name')]" + }, + "audiences": { + "value": "[coalesce(parameters('federatedIdentityCredentials'), createArray())[copyIndex()].audiences]" + }, + "issuer": { + "value": "[coalesce(parameters('federatedIdentityCredentials'), createArray())[copyIndex()].issuer]" + }, + "subject": { + "value": "[coalesce(parameters('federatedIdentityCredentials'), createArray())[copyIndex()].subject]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.34.44.8038", + "templateHash": "13561791622580351847" + }, + "name": "User Assigned Identity Federated Identity Credential", + "description": "This module deploys a User Assigned Identity Federated Identity Credential." + }, + "parameters": { + "userAssignedIdentityName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent user assigned identity. Required if the template is used in a standalone deployment." + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the secret." + } + }, + "audiences": { + "type": "array", + "metadata": { + "description": "Required. The list of audiences that can appear in the issued token. Should be set to api://AzureADTokenExchange for Azure AD. It says what Microsoft identity platform should accept in the aud claim in the incoming token. This value represents Azure AD in your external identity provider and has no fixed value across identity providers - you might need to create a new application registration in your IdP to serve as the audience of this token." + } + }, + "issuer": { + "type": "string", + "metadata": { + "description": "Required. The URL of the issuer to be trusted. Must match the issuer claim of the external token being exchanged." + } + }, + "subject": { + "type": "string", + "metadata": { + "description": "Required. The identifier of the external software workload within the external identity provider. Like the audience value, it has no fixed format, as each IdP uses their own - sometimes a GUID, sometimes a colon delimited identifier, sometimes arbitrary strings. The value here must match the sub claim within the token presented to Azure AD." + } + } + }, + "resources": [ + { + "type": "Microsoft.ManagedIdentity/userAssignedIdentities/federatedIdentityCredentials", + "apiVersion": "2023-01-31", + "name": "[format('{0}/{1}', parameters('userAssignedIdentityName'), parameters('name'))]", + "properties": { + "audiences": "[parameters('audiences')]", + "issuer": "[parameters('issuer')]", + "subject": "[parameters('subject')]" + } + } + ], + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the federated identity credential." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the federated identity credential." + }, + "value": "[resourceId('Microsoft.ManagedIdentity/userAssignedIdentities/federatedIdentityCredentials', parameters('userAssignedIdentityName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The name of the resource group the federated identity credential was created in." + }, + "value": "[resourceGroup().name]" + } + } + } }, "dependsOn": [ "userAssignedIdentity" @@ -1589,11 +2112,10 @@ "_generator": { "name": "bicep", "version": "0.34.44.8038", - "templateHash": "298383569508499170" + "templateHash": "12870015687080907707" }, "name": "Role Assignments (Resource Group scope)", - "description": "This module deploys a Role Assignment at a Resource Group scope.", - "owner": "Azure/module-maintainers" + "description": "This module deploys a Role Assignment at a Resource Group scope." }, "parameters": { "roleDefinitionIdOrName": { @@ -1673,10 +2195,10 @@ "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", - "Role Based Access Control Administrator (Preview)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168')]", + "Role Based Access Control Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168')]", "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]" }, - "roleDefinitionIdVar": "[if(contains(variables('builtInRoleNames'), parameters('roleDefinitionIdOrName')), variables('builtInRoleNames')[parameters('roleDefinitionIdOrName')], parameters('roleDefinitionIdOrName'))]" + "roleDefinitionIdVar": "[coalesce(tryGet(variables('builtInRoleNames'), parameters('roleDefinitionIdOrName')), parameters('roleDefinitionIdOrName'))]" }, "resources": [ { @@ -1761,189 +2283,646 @@ "_generator": { "name": "bicep", "version": "0.34.44.8038", - "templateHash": "8476574171169837262" + "templateHash": "3300039200931188757" }, "name": "Azure Compute Galleries", - "description": "This module deploys an Azure Compute Gallery (formerly known as Shared Image Gallery).", - "owner": "Azure/module-maintainers" + "description": "This module deploys an Azure Compute Gallery (formerly known as Shared Image Gallery)." }, "definitions": { - "lockType": { + "imageType": { "type": "object", "properties": { "name": { + "type": "string", + "minLength": 1, + "maxLength": 80, + "metadata": { + "description": "Required. Name of the image definition." + } + }, + "description": { "type": "string", "nullable": true, "metadata": { - "description": "Optional. Specify the name of lock." + "description": "Optional. The description of this gallery image definition resource. This property is updatable." } }, - "kind": { + "allowUpdateImage": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Must be set to true if the gallery image features are being updated." + } + }, + "osType": { "type": "string", "allowedValues": [ - "CanNotDelete", - "None", - "ReadOnly" + "Linux", + "Windows" + ], + "metadata": { + "description": "Required. This property allows you to specify the type of the OS that is included in the disk when creating a VM from a managed image." + } + }, + "osState": { + "type": "string", + "allowedValues": [ + "Generalized", + "Specialized" + ], + "metadata": { + "description": "Required. This property allows the user to specify the state of the OS of the image." + } + }, + "identifier": { + "$ref": "#/definitions/identifierType", + "metadata": { + "description": "Required. This is the gallery image definition identifier." + } + }, + "vCPUs": { + "$ref": "#/definitions/resourceRangeType", + "nullable": true, + "metadata": { + "description": "Optional. Describes the resource range (1-128 CPU cores). Defaults to min=1, max=4." + } + }, + "memory": { + "$ref": "#/definitions/resourceRangeType", + "nullable": true, + "metadata": { + "description": "Optional. Describes the resource range (1-4000 GB RAM). Defaults to min=4, max=16." + } + }, + "hyperVGeneration": { + "type": "string", + "allowedValues": [ + "V1", + "V2" ], "nullable": true, "metadata": { - "description": "Optional. Specify the type of lock." + "description": "Optional. The hypervisor generation of the Virtual Machine. If this value is not specified, then it is determined by the securityType parameter. If the securityType parameter is specified, then the value of hyperVGeneration will be V2, else V1." + } + }, + "securityType": { + "type": "string", + "allowedValues": [ + "ConfidentialVM", + "ConfidentialVMSupported", + "Standard", + "TrustedLaunch", + "TrustedLaunchAndConfidentialVmSupported", + "TrustedLaunchSupported" + ], + "nullable": true, + "metadata": { + "description": "Optional. The security type of the image. Requires a hyperVGeneration V2. Defaults to `Standard`." + } + }, + "isAcceleratedNetworkSupported": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Specify if the image supports accelerated networking. Defaults to true." + } + }, + "isHibernateSupported": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Specify if the image supports hibernation." + } + }, + "diskControllerType": { + "type": "string", + "allowedValues": [ + "NVMe, SCSI", + "SCSI", + "SCSI, NVMe" + ], + "nullable": true, + "metadata": { + "description": "Optional. The disk controllers that an OS disk supports." + } + }, + "architecture": { + "type": "string", + "allowedValues": [ + "Arm64", + "x64" + ], + "nullable": true, + "metadata": { + "description": "Optional. The architecture of the image. Applicable to OS disks only." + } + }, + "eula": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Eula agreement for the gallery image definition." + } + }, + "privacyStatementUri": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The privacy statement uri." + } + }, + "releaseNoteUri": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The release note uri. Has to be a valid URL." + } + }, + "purchasePlan": { + "$ref": "#/definitions/purchasePlanType", + "nullable": true, + "metadata": { + "description": "Optional. Describes the gallery image definition purchase plan. This is used by marketplace images." + } + }, + "endOfLife": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The end of life date of the gallery image definition. This property can be used for decommissioning purposes. This property is updatable." + } + }, + "excludedDiskTypes": { + "type": "array", + "items": { + "type": "string" + }, + "nullable": true, + "metadata": { + "description": "Optional. Describes the disallowed disk types." } } }, - "nullable": true + "metadata": { + "__bicep_export!": true + } }, - "roleAssignmentType": { - "type": "array", - "items": { - "type": "object", - "properties": { - "roleDefinitionIdOrName": { - "type": "string", - "metadata": { - "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, or its fully qualified ID in the following format: '/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11'." - } - }, - "principalId": { - "type": "string", - "metadata": { - "description": "Required. The principal ID of the principal (user/group/identity) to assign the role to." - } - }, - "principalType": { - "type": "string", - "allowedValues": [ - "Device", - "ForeignGroup", - "Group", - "ServicePrincipal", - "User" - ], - "nullable": true, - "metadata": { - "description": "Optional. The principal type of the assigned principal ID." - } - }, - "description": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The description of the role assignment." - } - }, - "condition": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." - } - }, - "conditionVersion": { - "type": "string", - "allowedValues": [ - "2.0" - ], - "nullable": true, - "metadata": { - "description": "Optional. Version of the condition." - } + "applicationsType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "minLength": 1, + "maxLength": 80, + "metadata": { + "description": "Required. Name of the application definition." + } + }, + "supportedOSType": { + "type": "string", + "allowedValues": [ + "Linux", + "Windows" + ], + "metadata": { + "description": "Required. The OS type of the application." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The description of this gallery application definition resource. This property is updatable." + } + }, + "eula": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Eula agreement for the gallery application definition." + } + }, + "privacyStatementUri": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The privacy statement uri." + } + }, + "releaseNoteUri": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The release note uri. Has to be a valid URL." + } + }, + "endOfLifeDate": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The end of life date of the gallery application definition. This property can be used for decommissioning purposes. This property is updatable." + } + }, + "roleAssignments": { + "type": "array", + "items": { + "$ref": "#/definitions/roleAssignmentType" }, - "delegatedManagedIdentityResourceId": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The Resource Id of the delegated managed identity resource." - } + "nullable": true, + "metadata": { + "description": "Optional. Array of role assignments to create." + } + }, + "customActions": { + "type": "array", + "items": { + "$ref": "#/definitions/customActionType" + }, + "nullable": true, + "metadata": { + "description": "Optional. A list of custom actions that can be performed with all of the Gallery Application Versions within this Gallery Application." + } + }, + "tags": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Tags for all resources." } } - }, - "nullable": true - } - }, - "parameters": { - "name": { - "type": "string", - "minLength": 1, - "metadata": { - "description": "Required. Name of the Azure Compute Gallery." - } - }, - "location": { - "type": "string", - "defaultValue": "[resourceGroup().location]", - "metadata": { - "description": "Optional. Location for all resources." - } - }, - "description": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. Description of the Azure Shared Image Gallery." - } - }, - "applications": { - "type": "array", - "nullable": true, - "metadata": { - "description": "Optional. Applications to create." } }, - "images": { - "type": "array", - "nullable": true, + "customActionType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the custom action. Must be unique within the Gallery Application Version." + } + }, + "script": { + "type": "string", + "metadata": { + "description": "Required. The script to run when executing this custom action." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Description to help the users understand what this custom action does." + } + }, + "parameters": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the parameter." + } + }, + "type": { + "type": "string", + "allowedValues": [ + "ConfigurationDataBlob", + "LogOutputBlob", + "String" + ], + "nullable": true, + "metadata": { + "description": "Optional. Specifies the type of the custom action parameter." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. A description to help users understand what this parameter means." + } + }, + "defaultValue": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The default value of the parameter. Only applies to string types." + } + }, + "required": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Indicates whether this parameter must be passed when running the custom action." + } + } + } + }, + "nullable": true, + "metadata": { + "description": "Optional. The parameters that this custom action uses." + } + } + }, "metadata": { - "description": "Optional. Images to create." + "__bicep_imported_from!": { + "sourceTemplate": "application/main.bicep" + } } }, - "lock": { - "$ref": "#/definitions/lockType", + "identifierType": { + "type": "object", + "properties": { + "publisher": { + "type": "string", + "metadata": { + "description": "Required. The name of the gallery image definition publisher." + } + }, + "offer": { + "type": "string", + "metadata": { + "description": "Required. The name of the gallery image definition offer." + } + }, + "sku": { + "type": "string", + "metadata": { + "description": "Required. The name of the gallery image definition SKU." + } + } + }, "metadata": { - "description": "Optional. The lock settings of the service." + "__bicep_imported_from!": { + "sourceTemplate": "image/main.bicep" + } } }, - "roleAssignments": { - "$ref": "#/definitions/roleAssignmentType", + "lockType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Specify the name of lock." + } + }, + "kind": { + "type": "string", + "allowedValues": [ + "CanNotDelete", + "None", + "ReadOnly" + ], + "nullable": true, + "metadata": { + "description": "Optional. Specify the type of lock." + } + } + }, "metadata": { - "description": "Optional. Array of role assignments to create." + "description": "An AVM-aligned type for a lock.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.3.0" + } } }, - "tags": { + "purchasePlanType": { "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The plan ID." + } + }, + "product": { + "type": "string", + "metadata": { + "description": "Required. The product ID." + } + }, + "publisher": { + "type": "string", + "metadata": { + "description": "Required. The publisher ID." + } + } + }, "nullable": true, "metadata": { - "description": "Optional. Tags for all resources." - } - }, - "enableTelemetry": { - "type": "bool", - "defaultValue": true, - "metadata": { - "description": "Optional. Enable/Disable usage telemetry for module." + "__bicep_imported_from!": { + "sourceTemplate": "image/main.bicep" + } } }, - "sharingProfile": { + "resourceRangeType": { "type": "object", - "nullable": true, + "properties": { + "min": { + "type": "int", + "nullable": true, + "minValue": 1, + "metadata": { + "description": "Optional. The minimum number of the resource." + } + }, + "max": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. The minimum number of the resource." + } + } + }, "metadata": { - "description": "Optional. Profile for gallery sharing to subscription or tenant." + "__bicep_imported_from!": { + "sourceTemplate": "image/main.bicep" + } } }, - "softDeletePolicy": { + "roleAssignmentType": { "type": "object", - "nullable": true, - "metadata": { - "description": "Optional. Soft deletion policy of the gallery." - } - } - }, + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." + } + }, + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, or its fully qualified ID in the following format: '/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11'." + } + }, + "principalId": { + "type": "string", + "metadata": { + "description": "Required. The principal ID of the principal (user/group/identity) to assign the role to." + } + }, + "principalType": { + "type": "string", + "allowedValues": [ + "Device", + "ForeignGroup", + "Group", + "ServicePrincipal", + "User" + ], + "nullable": true, + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The description of the role assignment." + } + }, + "condition": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." + } + }, + "conditionVersion": { + "type": "string", + "allowedValues": [ + "2.0" + ], + "nullable": true, + "metadata": { + "description": "Optional. Version of the condition." + } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Resource Id of the delegated managed identity resource." + } + } + }, + "metadata": { + "description": "An AVM-aligned type for a role assignment.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.3.0" + } + } + } + }, + "parameters": { + "name": { + "type": "string", + "minLength": 1, + "metadata": { + "description": "Required. Name of the Azure Compute Gallery." + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. Location for all resources." + } + }, + "enableTelemetry": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Enable/Disable usage telemetry for module." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Description of the Azure Shared Image Gallery." + } + }, + "applications": { + "type": "array", + "items": { + "$ref": "#/definitions/applicationsType" + }, + "nullable": true, + "metadata": { + "description": "Optional. Applications to create." + } + }, + "images": { + "type": "array", + "items": { + "$ref": "#/definitions/imageType" + }, + "nullable": true, + "metadata": { + "description": "Optional. Images to create." + } + }, + "lock": { + "$ref": "#/definitions/lockType", + "nullable": true, + "metadata": { + "description": "Optional. The lock settings of the service." + } + }, + "roleAssignments": { + "type": "array", + "items": { + "$ref": "#/definitions/roleAssignmentType" + }, + "nullable": true, + "metadata": { + "description": "Optional. Array of role assignments to create." + } + }, + "tags": { + "type": "object", + "nullable": true, + "metadata": { + "example": " {\r\n key1: 'value1'\r\n key2: 'value2'\r\n }\r\n ", + "description": "Optional. Tags for all resources." + } + }, + "sharingProfile": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Profile for gallery sharing to subscription or tenant." + } + }, + "softDeletePolicy": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Soft deletion policy of the gallery." + } + } + }, "variables": { + "copy": [ + { + "name": "formattedRoleAssignments", + "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]", + "input": "[union(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')], createObject('roleDefinitionId', coalesce(tryGet(variables('builtInRoleNames'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName), if(contains(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName)))))]" + } + ], "builtInRoleNames": { "Compute Gallery Sharing Admin": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '1ef6a3be-d0ac-425d-8c01-acb62866290b')]", "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", - "Role Based Access Control Administrator (Preview)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168')]", + "Role Based Access Control Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168')]", "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]" } }, @@ -1951,7 +2930,7 @@ "avmTelemetry": { "condition": "[parameters('enableTelemetry')]", "type": "Microsoft.Resources/deployments", - "apiVersion": "2023-07-01", + "apiVersion": "2024-03-01", "name": "[format('46d3xbcp.res.compute-gallery.{0}.{1}', replace('-..--..-', '.', '-'), substring(uniqueString(deployment().name, parameters('location')), 0, 4))]", "properties": { "mode": "Incremental", @@ -1970,7 +2949,7 @@ }, "gallery": { "type": "Microsoft.Compute/galleries", - "apiVersion": "2022-03-03", + "apiVersion": "2024-03-03", "name": "[parameters('name')]", "location": "[parameters('location')]", "tags": "[parameters('tags')]", @@ -1997,20 +2976,20 @@ "gallery_roleAssignments": { "copy": { "name": "gallery_roleAssignments", - "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]" + "count": "[length(coalesce(variables('formattedRoleAssignments'), createArray()))]" }, "type": "Microsoft.Authorization/roleAssignments", "apiVersion": "2022-04-01", "scope": "[format('Microsoft.Compute/galleries/{0}', parameters('name'))]", - "name": "[guid(resourceId('Microsoft.Compute/galleries', parameters('name')), coalesce(parameters('roleAssignments'), createArray())[copyIndex()].principalId, coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName)]", + "name": "[coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'name'), guid(resourceId('Microsoft.Compute/galleries', parameters('name')), coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId, coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId))]", "properties": { - "roleDefinitionId": "[if(contains(variables('builtInRoleNames'), coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName), variables('builtInRoleNames')[coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName], if(contains(coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/'), coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName)))]", - "principalId": "[coalesce(parameters('roleAssignments'), createArray())[copyIndex()].principalId]", - "description": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'description')]", - "principalType": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'principalType')]", - "condition": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'condition')]", - "conditionVersion": "[if(not(empty(tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'condition'))), coalesce(tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'conditionVersion'), '2.0'), null())]", - "delegatedManagedIdentityResourceId": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'delegatedManagedIdentityResourceId')]" + "roleDefinitionId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId]", + "principalId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId]", + "description": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'description')]", + "principalType": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'principalType')]", + "condition": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition')]", + "conditionVersion": "[if(not(empty(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition'))), coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'conditionVersion'), '2.0'), null())]", + "delegatedManagedIdentityResourceId": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'delegatedManagedIdentityResourceId')]" }, "dependsOn": [ "gallery" @@ -2075,90 +3054,176 @@ "_generator": { "name": "bicep", "version": "0.34.44.8038", - "templateHash": "3301279441949286765" + "templateHash": "6238662274509774384" }, "name": "Compute Galleries Applications", - "description": "This module deploys an Azure Compute Gallery Application.", - "owner": "Azure/module-maintainers" + "description": "This module deploys an Azure Compute Gallery Application." }, "definitions": { - "roleAssignmentType": { - "type": "array", - "items": { - "type": "object", - "properties": { - "roleDefinitionIdOrName": { - "type": "string", - "metadata": { - "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, or its fully qualified ID in the following format: '/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11'." - } - }, - "principalId": { - "type": "string", - "metadata": { - "description": "Required. The principal ID of the principal (user/group/identity) to assign the role to." - } - }, - "principalType": { - "type": "string", - "allowedValues": [ - "Device", - "ForeignGroup", - "Group", - "ServicePrincipal", - "User" - ], - "nullable": true, - "metadata": { - "description": "Optional. The principal type of the assigned principal ID." - } - }, - "description": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The description of the role assignment." - } - }, - "condition": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." - } - }, - "conditionVersion": { - "type": "string", - "allowedValues": [ - "2.0" - ], - "nullable": true, - "metadata": { - "description": "Optional. Version of the condition." + "customActionType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the custom action. Must be unique within the Gallery Application Version." + } + }, + "script": { + "type": "string", + "metadata": { + "description": "Required. The script to run when executing this custom action." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Description to help the users understand what this custom action does." + } + }, + "parameters": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the parameter." + } + }, + "type": { + "type": "string", + "allowedValues": [ + "ConfigurationDataBlob", + "LogOutputBlob", + "String" + ], + "nullable": true, + "metadata": { + "description": "Optional. Specifies the type of the custom action parameter." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. A description to help users understand what this parameter means." + } + }, + "defaultValue": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The default value of the parameter. Only applies to string types." + } + }, + "required": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Indicates whether this parameter must be passed when running the custom action." + } + } } }, - "delegatedManagedIdentityResourceId": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The Resource Id of the delegated managed identity resource." - } + "nullable": true, + "metadata": { + "description": "Optional. The parameters that this custom action uses." } } }, - "nullable": true - } - }, - "parameters": { - "name": { - "type": "string", "metadata": { - "description": "Required. Name of the application definition." + "__bicep_export!": true } }, - "location": { - "type": "string", - "defaultValue": "[resourceGroup().location]", + "roleAssignmentType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." + } + }, + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, or its fully qualified ID in the following format: '/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11'." + } + }, + "principalId": { + "type": "string", + "metadata": { + "description": "Required. The principal ID of the principal (user/group/identity) to assign the role to." + } + }, + "principalType": { + "type": "string", + "allowedValues": [ + "Device", + "ForeignGroup", + "Group", + "ServicePrincipal", + "User" + ], + "nullable": true, + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The description of the role assignment." + } + }, + "condition": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." + } + }, + "conditionVersion": { + "type": "string", + "allowedValues": [ + "2.0" + ], + "nullable": true, + "metadata": { + "description": "Optional. Version of the condition." + } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Resource Id of the delegated managed identity resource." + } + } + }, + "metadata": { + "description": "An AVM-aligned type for a role assignment.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.3.0" + } + } + } + }, + "parameters": { + "name": { + "type": "string", + "metadata": { + "description": "Required. Name of the application definition." + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", "metadata": { "description": "Optional. Location for all resources." } @@ -2216,7 +3281,11 @@ } }, "roleAssignments": { - "$ref": "#/definitions/roleAssignmentType", + "type": "array", + "items": { + "$ref": "#/definitions/roleAssignmentType" + }, + "nullable": true, "metadata": { "description": "Optional. Array of role assignments to create." } @@ -2230,6 +3299,9 @@ }, "customActions": { "type": "array", + "items": { + "$ref": "#/definitions/customActionType" + }, "nullable": true, "metadata": { "description": "Optional. A list of custom actions that can be performed with all of the Gallery Application Versions within this Gallery Application." @@ -2237,12 +3309,19 @@ } }, "variables": { + "copy": [ + { + "name": "formattedRoleAssignments", + "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]", + "input": "[union(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')], createObject('roleDefinitionId', coalesce(tryGet(variables('builtInRoleNames'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName), if(contains(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName)))))]" + } + ], "builtInRoleNames": { "Compute Gallery Sharing Admin": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '1ef6a3be-d0ac-425d-8c01-acb62866290b')]", "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", - "Role Based Access Control Administrator (Preview)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168')]", + "Role Based Access Control Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168')]", "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]" } }, @@ -2250,12 +3329,12 @@ "gallery": { "existing": true, "type": "Microsoft.Compute/galleries", - "apiVersion": "2022-03-03", + "apiVersion": "2024-03-03", "name": "[parameters('galleryName')]" }, "application": { "type": "Microsoft.Compute/galleries/applications", - "apiVersion": "2022-03-03", + "apiVersion": "2024-03-03", "name": "[format('{0}/{1}', parameters('galleryName'), parameters('name'))]", "location": "[parameters('location')]", "tags": "[parameters('tags')]", @@ -2272,20 +3351,20 @@ "application_roleAssignments": { "copy": { "name": "application_roleAssignments", - "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]" + "count": "[length(coalesce(variables('formattedRoleAssignments'), createArray()))]" }, "type": "Microsoft.Authorization/roleAssignments", "apiVersion": "2022-04-01", "scope": "[format('Microsoft.Compute/galleries/{0}/applications/{1}', parameters('galleryName'), parameters('name'))]", - "name": "[guid(resourceId('Microsoft.Compute/galleries/applications', parameters('galleryName'), parameters('name')), coalesce(parameters('roleAssignments'), createArray())[copyIndex()].principalId, coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName)]", + "name": "[coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'name'), guid(resourceId('Microsoft.Compute/galleries/applications', parameters('galleryName'), parameters('name')), coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId, coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId))]", "properties": { - "roleDefinitionId": "[if(contains(variables('builtInRoleNames'), coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName), variables('builtInRoleNames')[coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName], if(contains(coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/'), coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName)))]", - "principalId": "[coalesce(parameters('roleAssignments'), createArray())[copyIndex()].principalId]", - "description": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'description')]", - "principalType": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'principalType')]", - "condition": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'condition')]", - "conditionVersion": "[if(not(empty(tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'condition'))), coalesce(tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'conditionVersion'), '2.0'), null())]", - "delegatedManagedIdentityResourceId": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'delegatedManagedIdentityResourceId')]" + "roleDefinitionId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId]", + "principalId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId]", + "description": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'description')]", + "principalType": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'principalType')]", + "condition": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition')]", + "conditionVersion": "[if(not(empty(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition'))), coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'conditionVersion'), '2.0'), null())]", + "delegatedManagedIdentityResourceId": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'delegatedManagedIdentityResourceId')]" }, "dependsOn": [ "application" @@ -2319,7 +3398,7 @@ "metadata": { "description": "The location the resource was deployed into." }, - "value": "[reference('application', '2022-03-03', 'full').location]" + "value": "[reference('application', '2024-03-03', 'full').location]" } } } @@ -2342,41 +3421,35 @@ }, "mode": "Incremental", "parameters": { - "location": { - "value": "[parameters('location')]" - }, "name": { "value": "[coalesce(parameters('images'), createArray())[copyIndex()].name]" }, + "location": { + "value": "[coalesce(tryGet(coalesce(parameters('images'), createArray())[copyIndex()], 'location'), parameters('location'))]" + }, "galleryName": { "value": "[parameters('name')]" }, + "description": { + "value": "[tryGet(coalesce(parameters('images'), createArray())[copyIndex()], 'description')]" + }, + "allowUpdateImage": { + "value": "[tryGet(coalesce(parameters('images'), createArray())[copyIndex()], 'allowUpdateImage')]" + }, "osType": { "value": "[coalesce(parameters('images'), createArray())[copyIndex()].osType]" }, "osState": { - "value": "[tryGet(coalesce(parameters('images'), createArray())[copyIndex()], 'osState')]" + "value": "[coalesce(parameters('images'), createArray())[copyIndex()].osState]" }, - "publisher": { - "value": "[coalesce(parameters('images'), createArray())[copyIndex()].publisher]" + "identifier": { + "value": "[coalesce(parameters('images'), createArray())[copyIndex()].identifier]" }, - "offer": { - "value": "[coalesce(parameters('images'), createArray())[copyIndex()].offer]" - }, - "sku": { - "value": "[coalesce(parameters('images'), createArray())[copyIndex()].sku]" - }, - "minRecommendedvCPUs": { - "value": "[tryGet(coalesce(parameters('images'), createArray())[copyIndex()], 'minRecommendedvCPUs')]" - }, - "maxRecommendedvCPUs": { - "value": "[tryGet(coalesce(parameters('images'), createArray())[copyIndex()], 'maxRecommendedvCPUs')]" - }, - "minRecommendedMemory": { - "value": "[tryGet(coalesce(parameters('images'), createArray())[copyIndex()], 'minRecommendedMemory')]" + "vCPUs": { + "value": "[tryGet(coalesce(parameters('images'), createArray())[copyIndex()], 'vCPUs')]" }, - "maxRecommendedMemory": { - "value": "[tryGet(coalesce(parameters('images'), createArray())[copyIndex()], 'maxRecommendedMemory')]" + "memory": { + "value": "[tryGet(coalesce(parameters('images'), createArray())[copyIndex()], 'memory')]" }, "hyperVGeneration": { "value": "[tryGet(coalesce(parameters('images'), createArray())[copyIndex()], 'hyperVGeneration')]" @@ -2387,8 +3460,14 @@ "isAcceleratedNetworkSupported": { "value": "[tryGet(coalesce(parameters('images'), createArray())[copyIndex()], 'isAcceleratedNetworkSupported')]" }, - "description": { - "value": "[tryGet(coalesce(parameters('images'), createArray())[copyIndex()], 'description')]" + "isHibernateSupported": { + "value": "[tryGet(coalesce(parameters('images'), createArray())[copyIndex()], 'isHibernateSupported')]" + }, + "diskControllerType": { + "value": "[tryGet(coalesce(parameters('images'), createArray())[copyIndex()], 'diskControllerType')]" + }, + "architecture": { + "value": "[tryGet(coalesce(parameters('images'), createArray())[copyIndex()], 'architecture')]" }, "eula": { "value": "[tryGet(coalesce(parameters('images'), createArray())[copyIndex()], 'eula')]" @@ -2399,20 +3478,16 @@ "releaseNoteUri": { "value": "[tryGet(coalesce(parameters('images'), createArray())[copyIndex()], 'releaseNoteUri')]" }, - "productName": { - "value": "[tryGet(coalesce(parameters('images'), createArray())[copyIndex()], 'productName')]" - }, - "planName": { - "value": "[tryGet(coalesce(parameters('images'), createArray())[copyIndex()], 'planName')]" - }, - "planPublisherName": { - "value": "[tryGet(coalesce(parameters('images'), createArray())[copyIndex()], 'planPublisherName')]" + "purchasePlan": { + "value": "[tryGet(coalesce(parameters('images'), createArray())[copyIndex()], 'purchasePlan')]" }, - "endOfLife": { + "endOfLifeDate": { "value": "[tryGet(coalesce(parameters('images'), createArray())[copyIndex()], 'endOfLife')]" }, - "excludedDiskTypes": { - "value": "[tryGet(coalesce(parameters('images'), createArray())[copyIndex()], 'excludedDiskTypes')]" + "disallowed": { + "value": { + "diskTypes": "[coalesce(tryGet(coalesce(parameters('images'), createArray())[copyIndex()], 'excludedDiskTypes'), createArray())]" + } }, "roleAssignments": { "value": "[tryGet(coalesce(parameters('images'), createArray())[copyIndex()], 'roleAssignments')]" @@ -2429,11 +3504,10 @@ "_generator": { "name": "bicep", "version": "0.34.44.8038", - "templateHash": "11756759756344020131" + "templateHash": "12993830133554020897" }, "name": "Compute Galleries Image Definitions", - "description": "This module deploys an Azure Compute Gallery Image Definition.", - "owner": "Azure/module-maintainers" + "description": "This module deploys an Azure Compute Gallery Image Definition." }, "definitions": { "roleAssignmentType": { @@ -2441,6 +3515,13 @@ "items": { "type": "object", "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." + } + }, "roleDefinitionIdOrName": { "type": "string", "metadata": { @@ -2501,11 +3582,105 @@ } }, "nullable": true + }, + "resourceRangeType": { + "type": "object", + "properties": { + "min": { + "type": "int", + "nullable": true, + "minValue": 1, + "metadata": { + "description": "Optional. The minimum number of the resource." + } + }, + "max": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. The minimum number of the resource." + } + } + }, + "metadata": { + "__bicep_export!": true + } + }, + "disallowedType": { + "type": "object", + "properties": { + "diskTypes": { + "type": "array", + "items": { + "type": "string" + }, + "metadata": { + "example": " [\r\n 'Standard_LRS'\r\n ]", + "description": "Required. A list of disk types." + } + } + }, + "nullable": true + }, + "identifierType": { + "type": "object", + "properties": { + "publisher": { + "type": "string", + "metadata": { + "description": "Required. The name of the gallery image definition publisher." + } + }, + "offer": { + "type": "string", + "metadata": { + "description": "Required. The name of the gallery image definition offer." + } + }, + "sku": { + "type": "string", + "metadata": { + "description": "Required. The name of the gallery image definition SKU." + } + } + }, + "metadata": { + "__bicep_export!": true + } + }, + "purchasePlanType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The plan ID." + } + }, + "product": { + "type": "string", + "metadata": { + "description": "Required. The product ID." + } + }, + "publisher": { + "type": "string", + "metadata": { + "description": "Required. The publisher ID." + } + } + }, + "nullable": true, + "metadata": { + "__bicep_export!": true + } } }, "parameters": { "name": { "type": "string", + "minLength": 1, + "maxLength": 80, "metadata": { "description": "Required. Name of the image definition." } @@ -2524,180 +3699,169 @@ "description": "Conditional. The name of the parent Azure Shared Image Gallery. Required if the template is used in a standalone deployment." } }, - "osType": { - "type": "string", - "allowedValues": [ - "Windows", - "Linux" - ], + "identifier": { + "$ref": "#/definitions/identifierType", "metadata": { - "description": "Required. OS type of the image to be created." + "description": "Required. This is the gallery image definition identifier." } }, "osState": { "type": "string", - "defaultValue": "Generalized", "allowedValues": [ "Generalized", "Specialized" ], "metadata": { - "description": "Optional. This property allows the user to specify whether the virtual machines created under this image are 'Generalized' or 'Specialized'." + "description": "Required. This property allows the user to specify the state of the OS of the image." } }, - "publisher": { - "type": "string", - "metadata": { - "description": "Required. The name of the gallery Image Definition publisher." - } - }, - "offer": { + "osType": { "type": "string", + "allowedValues": [ + "Linux", + "Windows" + ], "metadata": { - "description": "Required. The name of the gallery Image Definition offer." + "description": "Required. This property allows you to specify the type of the OS that is included in the disk when creating a VM from a managed image." } }, - "sku": { + "privacyStatementUri": { "type": "string", + "nullable": true, "metadata": { - "description": "Required. The name of the gallery Image Definition SKU." - } - }, - "minRecommendedvCPUs": { - "type": "int", - "defaultValue": 1, - "minValue": 1, - "maxValue": 128, - "metadata": { - "description": "Optional. The minimum number of the CPU cores recommended for this image." + "description": "Optional. The privacy statement uri." } }, - "maxRecommendedvCPUs": { - "type": "int", - "defaultValue": 4, - "minValue": 1, - "maxValue": 128, + "purchasePlan": { + "$ref": "#/definitions/purchasePlanType", + "nullable": true, "metadata": { - "description": "Optional. The maximum number of the CPU cores recommended for this image." + "description": "Optional. Describes the gallery image definition purchase plan. This is used by marketplace images." } }, - "minRecommendedMemory": { - "type": "int", - "defaultValue": 4, - "minValue": 1, - "maxValue": 4000, + "vCPUs": { + "$ref": "#/definitions/resourceRangeType", + "defaultValue": { + "min": 1, + "max": 4 + }, "metadata": { - "description": "Optional. The minimum amount of RAM in GB recommended for this image." + "description": "Optional. Describes the resource range (1-128 CPU cores)." } }, - "maxRecommendedMemory": { - "type": "int", - "defaultValue": 16, - "minValue": 1, - "maxValue": 4000, + "memory": { + "$ref": "#/definitions/resourceRangeType", + "defaultValue": { + "min": 4, + "max": 16 + }, "metadata": { - "description": "Optional. The maximum amount of RAM in GB recommended for this image." + "description": "Optional. Describes the resource range (1-4000 GB RAM)." } }, - "hyperVGeneration": { + "releaseNoteUri": { "type": "string", "nullable": true, - "allowedValues": [ - "V1", - "V2" - ], "metadata": { - "description": "Optional. The hypervisor generation of the Virtual Machine.\n- If this value is not specified, then it is determined by the securityType parameter.\n- If the securityType parameter is specified, then the value of hyperVGeneration will be V2, else V1.\n" + "description": "Optional. The release note uri. Has to be a valid URL." } }, "securityType": { "type": "string", - "defaultValue": "Standard", "allowedValues": [ + "ConfidentialVM", + "ConfidentialVMSupported", "Standard", "TrustedLaunch", - "ConfidentialVM", - "ConfidentialVMSupported" + "TrustedLaunchAndConfidentialVmSupported", + "TrustedLaunchSupported" ], + "nullable": true, "metadata": { "description": "Optional. The security type of the image. Requires a hyperVGeneration V2." } }, - "isHibernateSupported": { + "isAcceleratedNetworkSupported": { "type": "bool", - "defaultValue": false, + "nullable": true, "metadata": { - "description": "Optional. Specifiy if the image supports hibernation." + "description": "Optional. Specify if the image supports accelerated networking." } }, - "isAcceleratedNetworkSupported": { + "isHibernateSupported": { "type": "bool", - "defaultValue": true, + "nullable": true, "metadata": { - "description": "Optional. Specify if the image supports accelerated networking.\nAccelerated networking enables single root I/O virtualization (SR-IOV) to a VM, greatly improving its networking performance.\nThis high-performance path bypasses the host from the data path, which reduces latency, jitter, and CPU utilization for the most demanding network workloads on supported VM types.\n" + "description": "Optional. Specifiy if the image supports hibernation." } }, - "description": { - "type": "string", + "allowUpdateImage": { + "type": "bool", "nullable": true, "metadata": { - "description": "Optional. The description of this gallery Image Definition resource. This property is updatable." + "description": "Optional. Must be set to true if the gallery image features are being updated." } }, - "eula": { + "architecture": { "type": "string", + "allowedValues": [ + "Arm64", + "x64" + ], "nullable": true, "metadata": { - "description": "Optional. The Eula agreement for the gallery Image Definition. Has to be a valid URL." + "description": "Optional. The architecture of the image. Applicable to OS disks only." } }, - "privacyStatementUri": { + "description": { "type": "string", "nullable": true, "metadata": { - "description": "Optional. The privacy statement uri. Has to be a valid URL." + "description": "Optional. The description of this gallery image definition resource. This property is updatable." } }, - "releaseNoteUri": { - "type": "string", + "disallowed": { + "$ref": "#/definitions/disallowedType", "nullable": true, "metadata": { - "description": "Optional. The release note uri. Has to be a valid URL." + "description": "Optional. Describes the disallowed disk types." } }, - "productName": { + "endOfLifeDate": { "type": "string", "nullable": true, "metadata": { - "description": "Optional. The product ID." + "description": "Optional. The end of life date of the gallery image definition. This property can be used for decommissioning purposes. This property is updatable." } }, - "planName": { + "eula": { "type": "string", "nullable": true, "metadata": { - "description": "Optional. The plan ID." + "description": "Optional. The Eula agreement for the gallery image definition." } }, - "planPublisherName": { + "hyperVGeneration": { "type": "string", + "allowedValues": [ + "V1", + "V2" + ], "nullable": true, "metadata": { - "description": "Optional. The publisher ID." + "description": "Optional. The hypervisor generation of the Virtual Machine. If this value is not specified, then it is determined by the securityType parameter. If the securityType parameter is specified, then the value of hyperVGeneration will be V2, else V1." } }, - "endOfLife": { + "diskControllerType": { "type": "string", - "defaultValue": "", - "metadata": { - "description": "Optional. The end of life date of the gallery Image Definition. This property can be used for decommissioning purposes. This property is updatable. Allowed format: 2020-01-10T23:00:00.000Z." - } - }, - "excludedDiskTypes": { - "type": "array", - "defaultValue": [], + "allowedValues": [ + "NVMe, SCSI", + "SCSI", + "SCSI, NVMe" + ], + "nullable": true, "metadata": { - "description": "Optional. List of the excluded disk types (e.g., Standard_LRS)." + "description": "Optional. The disk controllers that an OS disk supports." } }, "roleAssignments": { @@ -2710,17 +3874,25 @@ "type": "object", "nullable": true, "metadata": { - "description": "Optional. Tags for all resources." + "example": "{\r\n key1: 'value1'\r\n key2: 'value2'\r\n}\r\n", + "description": "Optional. Tags for all the image." } } }, "variables": { + "copy": [ + { + "name": "formattedRoleAssignments", + "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]", + "input": "[union(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')], createObject('roleDefinitionId', coalesce(tryGet(variables('builtInRoleNames'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName), if(contains(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName)))))]" + } + ], "builtInRoleNames": { "Compute Gallery Sharing Admin": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '1ef6a3be-d0ac-425d-8c01-acb62866290b')]", "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", - "Role Based Access Control Administrator (Preview)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168')]", + "Role Based Access Control Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168')]", "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]" } }, @@ -2728,67 +3900,58 @@ "gallery": { "existing": true, "type": "Microsoft.Compute/galleries", - "apiVersion": "2022-03-03", + "apiVersion": "2024-03-03", "name": "[parameters('galleryName')]" }, "image": { "type": "Microsoft.Compute/galleries/images", - "apiVersion": "2022-03-03", + "apiVersion": "2024-03-03", "name": "[format('{0}/{1}', parameters('galleryName'), parameters('name'))]", "location": "[parameters('location')]", "tags": "[parameters('tags')]", "properties": { - "osType": "[parameters('osType')]", - "osState": "[parameters('osState')]", + "allowUpdateImage": "[if(not(equals(parameters('allowUpdateImage'), null())), parameters('allowUpdateImage'), null())]", + "architecture": "[parameters('architecture')]", + "description": "[parameters('description')]", + "disallowed": { + "diskTypes": "[coalesce(tryGet(parameters('disallowed'), 'diskTypes'), createArray())]" + }, + "endOfLifeDate": "[parameters('endOfLifeDate')]", + "eula": "[parameters('eula')]", + "features": "[union(if(not(equals(parameters('isAcceleratedNetworkSupported'), null())), createArray(createObject('name', 'IsAcceleratedNetworkSupported', 'value', format('{0}', parameters('isAcceleratedNetworkSupported')))), createArray()), if(and(not(equals(parameters('securityType'), null())), not(equals(parameters('securityType'), 'Standard'))), createArray(createObject('name', 'SecurityType', 'value', format('{0}', parameters('securityType')))), createArray()), if(not(equals(parameters('isHibernateSupported'), null())), createArray(createObject('name', 'IsHibernateSupported', 'value', format('{0}', parameters('isHibernateSupported')))), createArray()), if(not(equals(parameters('diskControllerType'), null())), createArray(createObject('name', 'DiskControllerTypes', 'value', format('{0}', parameters('diskControllerType')))), createArray()))]", + "hyperVGeneration": "[coalesce(parameters('hyperVGeneration'), if(not(empty(coalesce(parameters('securityType'), ''))), 'V2', 'V1'))]", "identifier": { - "publisher": "[parameters('publisher')]", - "offer": "[parameters('offer')]", - "sku": "[parameters('sku')]" + "publisher": "[parameters('identifier').publisher]", + "offer": "[parameters('identifier').offer]", + "sku": "[parameters('identifier').sku]" }, - "recommended": { - "vCPUs": { - "min": "[parameters('minRecommendedvCPUs')]", - "max": "[parameters('maxRecommendedvCPUs')]" - }, - "memory": { - "min": "[parameters('minRecommendedMemory')]", - "max": "[parameters('maxRecommendedMemory')]" - } - }, - "hyperVGeneration": "[coalesce(parameters('hyperVGeneration'), if(not(empty(parameters('securityType'))), 'V2', 'V1'))]", - "features": "[union(createArray(createObject('name', 'IsAcceleratedNetworkSupported', 'value', format('{0}', parameters('isAcceleratedNetworkSupported'))), createObject('name', 'IsHibernateSupported', 'value', format('{0}', parameters('isHibernateSupported')))), if(not(equals(parameters('securityType'), 'Standard')), createArray(createObject('name', 'SecurityType', 'value', parameters('securityType'))), createArray()))]", - "description": "[parameters('description')]", - "eula": "[parameters('eula')]", + "osState": "[parameters('osState')]", + "osType": "[parameters('osType')]", "privacyStatementUri": "[parameters('privacyStatementUri')]", - "releaseNoteUri": "[parameters('releaseNoteUri')]", - "purchasePlan": { - "product": "[parameters('productName')]", - "name": "[parameters('planName')]", - "publisher": "[parameters('planPublisherName')]" + "recommended": { + "vCPUs": "[parameters('vCPUs')]", + "memory": "[parameters('memory')]" }, - "endOfLifeDate": "[parameters('endOfLife')]", - "disallowed": { - "diskTypes": "[parameters('excludedDiskTypes')]" - } + "releaseNoteUri": "[parameters('releaseNoteUri')]" } }, "image_roleAssignments": { "copy": { "name": "image_roleAssignments", - "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]" + "count": "[length(coalesce(variables('formattedRoleAssignments'), createArray()))]" }, "type": "Microsoft.Authorization/roleAssignments", "apiVersion": "2022-04-01", "scope": "[format('Microsoft.Compute/galleries/{0}/images/{1}', parameters('galleryName'), parameters('name'))]", - "name": "[guid(resourceId('Microsoft.Compute/galleries/images', parameters('galleryName'), parameters('name')), coalesce(parameters('roleAssignments'), createArray())[copyIndex()].principalId, coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName)]", + "name": "[coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'name'), guid(resourceId('Microsoft.Compute/galleries/images', parameters('galleryName'), parameters('name')), coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId, coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId))]", "properties": { - "roleDefinitionId": "[if(contains(variables('builtInRoleNames'), coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName), variables('builtInRoleNames')[coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName], if(contains(coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/'), coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName)))]", - "principalId": "[coalesce(parameters('roleAssignments'), createArray())[copyIndex()].principalId]", - "description": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'description')]", - "principalType": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'principalType')]", - "condition": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'condition')]", - "conditionVersion": "[if(not(empty(tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'condition'))), coalesce(tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'conditionVersion'), '2.0'), null())]", - "delegatedManagedIdentityResourceId": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'delegatedManagedIdentityResourceId')]" + "roleDefinitionId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId]", + "principalId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId]", + "description": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'description')]", + "principalType": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'principalType')]", + "condition": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition')]", + "conditionVersion": "[if(not(empty(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition'))), coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'conditionVersion'), '2.0'), null())]", + "delegatedManagedIdentityResourceId": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'delegatedManagedIdentityResourceId')]" }, "dependsOn": [ "image" @@ -2822,7 +3985,7 @@ "metadata": { "description": "The location the resource was deployed into." }, - "value": "[reference('image', '2022-03-03', 'full').location]" + "value": "[reference('image', '2024-03-03', 'full').location]" } } } @@ -2859,7 +4022,7 @@ "metadata": { "description": "The location the resource was deployed into." }, - "value": "[reference('gallery', '2022-03-03', 'full').location]" + "value": "[reference('gallery', '2024-03-03', 'full').location]" }, "imageResourceIds": { "type": "array", @@ -2897,25 +4060,23 @@ "value": "[variables('varImageDefinitionName')]" }, "osState": { - "value": "[variables('varOperatingSystemImageDefinitions')[parameters('operatingSystemImage')].osState]" + "value": "Generalized" }, "osType": { - "value": "[variables('varOperatingSystemImageDefinitions')[parameters('operatingSystemImage')].osType]" - }, - "publisher": { - "value": "[variables('varOperatingSystemImageDefinitions')[parameters('operatingSystemImage')].publisher]" + "value": "Windows" }, - "offer": { - "value": "[variables('varOperatingSystemImageDefinitions')[parameters('operatingSystemImage')].offer]" - }, - "sku": { - "value": "[variables('varOperatingSystemImageDefinitions')[parameters('operatingSystemImage')].sku]" + "identifier": { + "value": { + "publisher": "[parameters('mpImagePublisher')]", + "offer": "[parameters('mpImageOffer')]", + "sku": "[parameters('mpImageSku')]" + } }, "location": { "value": "[parameters('imageVersionPrimaryLocation')]" }, "hyperVGeneration": { - "value": "[variables('varOperatingSystemImageDefinitions')[parameters('operatingSystemImage')].hyperVGeneration]" + "value": "V2" }, "isAcceleratedNetworkSupported": { "value": "[parameters('imageDefinitionAcceleratedNetworkSupported')]" @@ -2936,11 +4097,10 @@ "_generator": { "name": "bicep", "version": "0.34.44.8038", - "templateHash": "11756759756344020131" + "templateHash": "12993830133554020897" }, "name": "Compute Galleries Image Definitions", - "description": "This module deploys an Azure Compute Gallery Image Definition.", - "owner": "Azure/module-maintainers" + "description": "This module deploys an Azure Compute Gallery Image Definition." }, "definitions": { "roleAssignmentType": { @@ -2948,6 +4108,13 @@ "items": { "type": "object", "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." + } + }, "roleDefinitionIdOrName": { "type": "string", "metadata": { @@ -3008,11 +4175,105 @@ } }, "nullable": true + }, + "resourceRangeType": { + "type": "object", + "properties": { + "min": { + "type": "int", + "nullable": true, + "minValue": 1, + "metadata": { + "description": "Optional. The minimum number of the resource." + } + }, + "max": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. The minimum number of the resource." + } + } + }, + "metadata": { + "__bicep_export!": true + } + }, + "disallowedType": { + "type": "object", + "properties": { + "diskTypes": { + "type": "array", + "items": { + "type": "string" + }, + "metadata": { + "example": " [\r\n 'Standard_LRS'\r\n ]", + "description": "Required. A list of disk types." + } + } + }, + "nullable": true + }, + "identifierType": { + "type": "object", + "properties": { + "publisher": { + "type": "string", + "metadata": { + "description": "Required. The name of the gallery image definition publisher." + } + }, + "offer": { + "type": "string", + "metadata": { + "description": "Required. The name of the gallery image definition offer." + } + }, + "sku": { + "type": "string", + "metadata": { + "description": "Required. The name of the gallery image definition SKU." + } + } + }, + "metadata": { + "__bicep_export!": true + } + }, + "purchasePlanType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The plan ID." + } + }, + "product": { + "type": "string", + "metadata": { + "description": "Required. The product ID." + } + }, + "publisher": { + "type": "string", + "metadata": { + "description": "Required. The publisher ID." + } + } + }, + "nullable": true, + "metadata": { + "__bicep_export!": true + } } }, "parameters": { "name": { "type": "string", + "minLength": 1, + "maxLength": 80, "metadata": { "description": "Required. Name of the image definition." } @@ -3031,180 +4292,169 @@ "description": "Conditional. The name of the parent Azure Shared Image Gallery. Required if the template is used in a standalone deployment." } }, - "osType": { - "type": "string", - "allowedValues": [ - "Windows", - "Linux" - ], + "identifier": { + "$ref": "#/definitions/identifierType", "metadata": { - "description": "Required. OS type of the image to be created." + "description": "Required. This is the gallery image definition identifier." } }, "osState": { "type": "string", - "defaultValue": "Generalized", "allowedValues": [ "Generalized", "Specialized" ], "metadata": { - "description": "Optional. This property allows the user to specify whether the virtual machines created under this image are 'Generalized' or 'Specialized'." - } - }, - "publisher": { - "type": "string", - "metadata": { - "description": "Required. The name of the gallery Image Definition publisher." + "description": "Required. This property allows the user to specify the state of the OS of the image." } }, - "offer": { + "osType": { "type": "string", + "allowedValues": [ + "Linux", + "Windows" + ], "metadata": { - "description": "Required. The name of the gallery Image Definition offer." + "description": "Required. This property allows you to specify the type of the OS that is included in the disk when creating a VM from a managed image." } }, - "sku": { + "privacyStatementUri": { "type": "string", + "nullable": true, "metadata": { - "description": "Required. The name of the gallery Image Definition SKU." - } - }, - "minRecommendedvCPUs": { - "type": "int", - "defaultValue": 1, - "minValue": 1, - "maxValue": 128, - "metadata": { - "description": "Optional. The minimum number of the CPU cores recommended for this image." + "description": "Optional. The privacy statement uri." } }, - "maxRecommendedvCPUs": { - "type": "int", - "defaultValue": 4, - "minValue": 1, - "maxValue": 128, + "purchasePlan": { + "$ref": "#/definitions/purchasePlanType", + "nullable": true, "metadata": { - "description": "Optional. The maximum number of the CPU cores recommended for this image." + "description": "Optional. Describes the gallery image definition purchase plan. This is used by marketplace images." } }, - "minRecommendedMemory": { - "type": "int", - "defaultValue": 4, - "minValue": 1, - "maxValue": 4000, + "vCPUs": { + "$ref": "#/definitions/resourceRangeType", + "defaultValue": { + "min": 1, + "max": 4 + }, "metadata": { - "description": "Optional. The minimum amount of RAM in GB recommended for this image." + "description": "Optional. Describes the resource range (1-128 CPU cores)." } }, - "maxRecommendedMemory": { - "type": "int", - "defaultValue": 16, - "minValue": 1, - "maxValue": 4000, + "memory": { + "$ref": "#/definitions/resourceRangeType", + "defaultValue": { + "min": 4, + "max": 16 + }, "metadata": { - "description": "Optional. The maximum amount of RAM in GB recommended for this image." + "description": "Optional. Describes the resource range (1-4000 GB RAM)." } }, - "hyperVGeneration": { + "releaseNoteUri": { "type": "string", "nullable": true, - "allowedValues": [ - "V1", - "V2" - ], "metadata": { - "description": "Optional. The hypervisor generation of the Virtual Machine.\n- If this value is not specified, then it is determined by the securityType parameter.\n- If the securityType parameter is specified, then the value of hyperVGeneration will be V2, else V1.\n" + "description": "Optional. The release note uri. Has to be a valid URL." } }, "securityType": { "type": "string", - "defaultValue": "Standard", "allowedValues": [ + "ConfidentialVM", + "ConfidentialVMSupported", "Standard", "TrustedLaunch", - "ConfidentialVM", - "ConfidentialVMSupported" + "TrustedLaunchAndConfidentialVmSupported", + "TrustedLaunchSupported" ], + "nullable": true, "metadata": { "description": "Optional. The security type of the image. Requires a hyperVGeneration V2." } }, - "isHibernateSupported": { + "isAcceleratedNetworkSupported": { "type": "bool", - "defaultValue": false, + "nullable": true, "metadata": { - "description": "Optional. Specifiy if the image supports hibernation." + "description": "Optional. Specify if the image supports accelerated networking." } }, - "isAcceleratedNetworkSupported": { + "isHibernateSupported": { "type": "bool", - "defaultValue": true, + "nullable": true, "metadata": { - "description": "Optional. Specify if the image supports accelerated networking.\nAccelerated networking enables single root I/O virtualization (SR-IOV) to a VM, greatly improving its networking performance.\nThis high-performance path bypasses the host from the data path, which reduces latency, jitter, and CPU utilization for the most demanding network workloads on supported VM types.\n" + "description": "Optional. Specifiy if the image supports hibernation." } }, - "description": { - "type": "string", + "allowUpdateImage": { + "type": "bool", "nullable": true, "metadata": { - "description": "Optional. The description of this gallery Image Definition resource. This property is updatable." + "description": "Optional. Must be set to true if the gallery image features are being updated." } }, - "eula": { + "architecture": { "type": "string", + "allowedValues": [ + "Arm64", + "x64" + ], "nullable": true, "metadata": { - "description": "Optional. The Eula agreement for the gallery Image Definition. Has to be a valid URL." + "description": "Optional. The architecture of the image. Applicable to OS disks only." } }, - "privacyStatementUri": { + "description": { "type": "string", "nullable": true, "metadata": { - "description": "Optional. The privacy statement uri. Has to be a valid URL." + "description": "Optional. The description of this gallery image definition resource. This property is updatable." } }, - "releaseNoteUri": { - "type": "string", + "disallowed": { + "$ref": "#/definitions/disallowedType", "nullable": true, "metadata": { - "description": "Optional. The release note uri. Has to be a valid URL." + "description": "Optional. Describes the disallowed disk types." } }, - "productName": { + "endOfLifeDate": { "type": "string", "nullable": true, "metadata": { - "description": "Optional. The product ID." + "description": "Optional. The end of life date of the gallery image definition. This property can be used for decommissioning purposes. This property is updatable." } }, - "planName": { + "eula": { "type": "string", "nullable": true, "metadata": { - "description": "Optional. The plan ID." + "description": "Optional. The Eula agreement for the gallery image definition." } }, - "planPublisherName": { + "hyperVGeneration": { "type": "string", + "allowedValues": [ + "V1", + "V2" + ], "nullable": true, "metadata": { - "description": "Optional. The publisher ID." + "description": "Optional. The hypervisor generation of the Virtual Machine. If this value is not specified, then it is determined by the securityType parameter. If the securityType parameter is specified, then the value of hyperVGeneration will be V2, else V1." } }, - "endOfLife": { + "diskControllerType": { "type": "string", - "defaultValue": "", - "metadata": { - "description": "Optional. The end of life date of the gallery Image Definition. This property can be used for decommissioning purposes. This property is updatable. Allowed format: 2020-01-10T23:00:00.000Z." - } - }, - "excludedDiskTypes": { - "type": "array", - "defaultValue": [], + "allowedValues": [ + "NVMe, SCSI", + "SCSI", + "SCSI, NVMe" + ], + "nullable": true, "metadata": { - "description": "Optional. List of the excluded disk types (e.g., Standard_LRS)." + "description": "Optional. The disk controllers that an OS disk supports." } }, "roleAssignments": { @@ -3217,17 +4467,25 @@ "type": "object", "nullable": true, "metadata": { - "description": "Optional. Tags for all resources." + "example": "{\r\n key1: 'value1'\r\n key2: 'value2'\r\n}\r\n", + "description": "Optional. Tags for all the image." } } }, "variables": { + "copy": [ + { + "name": "formattedRoleAssignments", + "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]", + "input": "[union(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')], createObject('roleDefinitionId', coalesce(tryGet(variables('builtInRoleNames'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName), if(contains(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName)))))]" + } + ], "builtInRoleNames": { "Compute Gallery Sharing Admin": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '1ef6a3be-d0ac-425d-8c01-acb62866290b')]", "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", - "Role Based Access Control Administrator (Preview)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168')]", + "Role Based Access Control Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168')]", "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]" } }, @@ -3235,67 +4493,58 @@ "gallery": { "existing": true, "type": "Microsoft.Compute/galleries", - "apiVersion": "2022-03-03", + "apiVersion": "2024-03-03", "name": "[parameters('galleryName')]" }, "image": { "type": "Microsoft.Compute/galleries/images", - "apiVersion": "2022-03-03", + "apiVersion": "2024-03-03", "name": "[format('{0}/{1}', parameters('galleryName'), parameters('name'))]", "location": "[parameters('location')]", "tags": "[parameters('tags')]", "properties": { - "osType": "[parameters('osType')]", - "osState": "[parameters('osState')]", - "identifier": { - "publisher": "[parameters('publisher')]", - "offer": "[parameters('offer')]", - "sku": "[parameters('sku')]" - }, - "recommended": { - "vCPUs": { - "min": "[parameters('minRecommendedvCPUs')]", - "max": "[parameters('maxRecommendedvCPUs')]" - }, - "memory": { - "min": "[parameters('minRecommendedMemory')]", - "max": "[parameters('maxRecommendedMemory')]" - } - }, - "hyperVGeneration": "[coalesce(parameters('hyperVGeneration'), if(not(empty(parameters('securityType'))), 'V2', 'V1'))]", - "features": "[union(createArray(createObject('name', 'IsAcceleratedNetworkSupported', 'value', format('{0}', parameters('isAcceleratedNetworkSupported'))), createObject('name', 'IsHibernateSupported', 'value', format('{0}', parameters('isHibernateSupported')))), if(not(equals(parameters('securityType'), 'Standard')), createArray(createObject('name', 'SecurityType', 'value', parameters('securityType'))), createArray()))]", + "allowUpdateImage": "[if(not(equals(parameters('allowUpdateImage'), null())), parameters('allowUpdateImage'), null())]", + "architecture": "[parameters('architecture')]", "description": "[parameters('description')]", + "disallowed": { + "diskTypes": "[coalesce(tryGet(parameters('disallowed'), 'diskTypes'), createArray())]" + }, + "endOfLifeDate": "[parameters('endOfLifeDate')]", "eula": "[parameters('eula')]", + "features": "[union(if(not(equals(parameters('isAcceleratedNetworkSupported'), null())), createArray(createObject('name', 'IsAcceleratedNetworkSupported', 'value', format('{0}', parameters('isAcceleratedNetworkSupported')))), createArray()), if(and(not(equals(parameters('securityType'), null())), not(equals(parameters('securityType'), 'Standard'))), createArray(createObject('name', 'SecurityType', 'value', format('{0}', parameters('securityType')))), createArray()), if(not(equals(parameters('isHibernateSupported'), null())), createArray(createObject('name', 'IsHibernateSupported', 'value', format('{0}', parameters('isHibernateSupported')))), createArray()), if(not(equals(parameters('diskControllerType'), null())), createArray(createObject('name', 'DiskControllerTypes', 'value', format('{0}', parameters('diskControllerType')))), createArray()))]", + "hyperVGeneration": "[coalesce(parameters('hyperVGeneration'), if(not(empty(coalesce(parameters('securityType'), ''))), 'V2', 'V1'))]", + "identifier": { + "publisher": "[parameters('identifier').publisher]", + "offer": "[parameters('identifier').offer]", + "sku": "[parameters('identifier').sku]" + }, + "osState": "[parameters('osState')]", + "osType": "[parameters('osType')]", "privacyStatementUri": "[parameters('privacyStatementUri')]", - "releaseNoteUri": "[parameters('releaseNoteUri')]", - "purchasePlan": { - "product": "[parameters('productName')]", - "name": "[parameters('planName')]", - "publisher": "[parameters('planPublisherName')]" + "recommended": { + "vCPUs": "[parameters('vCPUs')]", + "memory": "[parameters('memory')]" }, - "endOfLifeDate": "[parameters('endOfLife')]", - "disallowed": { - "diskTypes": "[parameters('excludedDiskTypes')]" - } + "releaseNoteUri": "[parameters('releaseNoteUri')]" } }, "image_roleAssignments": { "copy": { "name": "image_roleAssignments", - "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]" + "count": "[length(coalesce(variables('formattedRoleAssignments'), createArray()))]" }, "type": "Microsoft.Authorization/roleAssignments", "apiVersion": "2022-04-01", "scope": "[format('Microsoft.Compute/galleries/{0}/images/{1}', parameters('galleryName'), parameters('name'))]", - "name": "[guid(resourceId('Microsoft.Compute/galleries/images', parameters('galleryName'), parameters('name')), coalesce(parameters('roleAssignments'), createArray())[copyIndex()].principalId, coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName)]", + "name": "[coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'name'), guid(resourceId('Microsoft.Compute/galleries/images', parameters('galleryName'), parameters('name')), coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId, coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId))]", "properties": { - "roleDefinitionId": "[if(contains(variables('builtInRoleNames'), coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName), variables('builtInRoleNames')[coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName], if(contains(coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/'), coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName)))]", - "principalId": "[coalesce(parameters('roleAssignments'), createArray())[copyIndex()].principalId]", - "description": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'description')]", - "principalType": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'principalType')]", - "condition": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'condition')]", - "conditionVersion": "[if(not(empty(tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'condition'))), coalesce(tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'conditionVersion'), '2.0'), null())]", - "delegatedManagedIdentityResourceId": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'delegatedManagedIdentityResourceId')]" + "roleDefinitionId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId]", + "principalId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId]", + "description": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'description')]", + "principalType": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'principalType')]", + "condition": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition')]", + "conditionVersion": "[if(not(empty(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition'))), coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'conditionVersion'), '2.0'), null())]", + "delegatedManagedIdentityResourceId": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'delegatedManagedIdentityResourceId')]" }, "dependsOn": [ "image" @@ -3329,7 +4578,7 @@ "metadata": { "description": "The location the resource was deployed into." }, - "value": "[reference('image', '2022-03-03', 'full').location]" + "value": "[reference('image', '2024-03-03', 'full').location]" } } } @@ -3384,10 +4633,10 @@ "imageSource": { "value": { "type": "PlatformImage", - "publisher": "[variables('varOperatingSystemImageDefinitions')[parameters('operatingSystemImage')].publisher]", - "offer": "[variables('varOperatingSystemImageDefinitions')[parameters('operatingSystemImage')].offer]", - "sku": "[variables('varOperatingSystemImageDefinitions')[parameters('operatingSystemImage')].sku]", - "version": "[variables('varOperatingSystemImageDefinitions')[parameters('operatingSystemImage')].version]" + "publisher": "[parameters('mpImagePublisher')]", + "offer": "[parameters('mpImageOffer')]", + "sku": "[parameters('mpImageSku')]", + "version": "[parameters('mpImageVersion')]" } }, "tags": "[if(parameters('enableResourceTags'), createObject('value', variables('varCommonResourceTags')), createObject('value', createObject()))]" @@ -3400,172 +4649,69 @@ "_generator": { "name": "bicep", "version": "0.34.44.8038", - "templateHash": "2323289411287396743" + "templateHash": "17973083359124118530" }, "name": "Virtual Machine Image Templates", - "description": "This module deploys a Virtual Machine Image Template that can be consumed by Azure Image Builder (AIB).", - "owner": "Azure/module-maintainers" + "description": "This module deploys a Virtual Machine Image Template that can be consumed by Azure Image Builder (AIB)." }, "definitions": { - "lockType": { + "distributionType": { + "type": "object", + "discriminator": { + "propertyName": "type", + "mapping": { + "SharedImage": { + "$ref": "#/definitions/sharedImageDistributionType" + }, + "ManagedImage": { + "$ref": "#/definitions/managedImageDistributionType" + }, + "VHD": { + "$ref": "#/definitions/unManagedDistributionType" + } + } + }, + "metadata": { + "__bicep_export!": true + } + }, + "sharedImageDistributionType": { "type": "object", "properties": { - "name": { + "runOutputName": { "type": "string", "nullable": true, "metadata": { - "description": "Optional. Specify the name of lock." + "description": "Optional. The name to be used for the associated RunOutput. If not provided, a name will be calculated." } }, - "kind": { + "artifactTags": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Tags that will be applied to the artifact once it has been created/updated by the distributor. If not provided will set tags based on the provided image source." + } + }, + "type": { "type": "string", "allowedValues": [ - "CanNotDelete", - "None", - "ReadOnly" + "SharedImage" ], + "metadata": { + "description": "Required. The type of distribution." + } + }, + "sharedImageGalleryImageDefinitionResourceId": { + "type": "string", + "metadata": { + "description": "Conditional. Resource ID of Compute Gallery Image Definition to distribute image to, e.g.: /subscriptions//resourceGroups//providers/Microsoft.Compute/galleries//images/." + } + }, + "sharedImageGalleryImageDefinitionTargetVersion": { + "type": "string", "nullable": true, "metadata": { - "description": "Optional. Specify the type of lock." - } - } - }, - "nullable": true - }, - "roleAssignmentType": { - "type": "array", - "items": { - "type": "object", - "properties": { - "roleDefinitionIdOrName": { - "type": "string", - "metadata": { - "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, or its fully qualified ID in the following format: '/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11'." - } - }, - "principalId": { - "type": "string", - "metadata": { - "description": "Required. The principal ID of the principal (user/group/identity) to assign the role to." - } - }, - "principalType": { - "type": "string", - "allowedValues": [ - "Device", - "ForeignGroup", - "Group", - "ServicePrincipal", - "User" - ], - "nullable": true, - "metadata": { - "description": "Optional. The principal type of the assigned principal ID." - } - }, - "description": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The description of the role assignment." - } - }, - "condition": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." - } - }, - "conditionVersion": { - "type": "string", - "allowedValues": [ - "2.0" - ], - "nullable": true, - "metadata": { - "description": "Optional. Version of the condition." - } - }, - "delegatedManagedIdentityResourceId": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The Resource Id of the delegated managed identity resource." - } - } - } - }, - "nullable": true - }, - "managedIdentitiesType": { - "type": "object", - "properties": { - "userAssignedResourceIds": { - "type": "array", - "items": { - "type": "string" - }, - "metadata": { - "description": "Optional. The resource ID(s) to assign to the resource. Required if a user assigned identity is used for encryption." - } - } - } - }, - "distributionType": { - "type": "object", - "discriminator": { - "propertyName": "type", - "mapping": { - "SharedImage": { - "$ref": "#/definitions/sharedImageDistributionType" - }, - "ManagedImage": { - "$ref": "#/definitions/managedImageDistributionType" - }, - "VHD": { - "$ref": "#/definitions/unManagedDistributionType" - } - } - } - }, - "sharedImageDistributionType": { - "type": "object", - "properties": { - "runOutputName": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The name to be used for the associated RunOutput. If not provided, a name will be calculated." - } - }, - "artifactTags": { - "type": "object", - "nullable": true, - "metadata": { - "description": "Optional. Tags that will be applied to the artifact once it has been created/updated by the distributor. If not provided will set tags based on the provided image source." - } - }, - "type": { - "type": "string", - "allowedValues": [ - "SharedImage" - ], - "metadata": { - "description": "Required. The type of distribution." - } - }, - "sharedImageGalleryImageDefinitionResourceId": { - "type": "string", - "metadata": { - "description": "Conditional. Resource ID of Compute Gallery Image Definition to distribute image to, e.g.: /subscriptions//resourceGroups//providers/Microsoft.Compute/galleries//images/." - } - }, - "sharedImageGalleryImageDefinitionTargetVersion": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. Version of the Compute Gallery Image. Supports the following Version Syntax: Major.Minor.Build (i.e., '1.1.1' or '10.1.2'). If not provided, a version will be calculated." + "description": "Optional. Version of the Compute Gallery Image. Supports the following Version Syntax: Major.Minor.Build (i.e., '1.1.1' or '10.1.2'). If not provided, a version will be calculated." } }, "excludeFromLatest": { @@ -3596,6 +4742,9 @@ "description": "Optional. The storage account type of the image. Defaults to [Standard_LRS]." } } + }, + "metadata": { + "__bicep_export!": true } }, "unManagedDistributionType": { @@ -3630,6 +4779,9 @@ "description": "Conditional. Name of the managed or unmanaged image that will be created." } } + }, + "metadata": { + "__bicep_export!": true } }, "managedImageDistributionType": { @@ -3678,6 +4830,9 @@ "description": "Conditional. Name of the managed or unmanaged image that will be created." } } + }, + "metadata": { + "__bicep_export!": true } }, "validationProcessType": { @@ -3790,7 +4945,135 @@ } } }, - "nullable": true + "metadata": { + "__bicep_export!": true + } + }, + "lockType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Specify the name of lock." + } + }, + "kind": { + "type": "string", + "allowedValues": [ + "CanNotDelete", + "None", + "ReadOnly" + ], + "nullable": true, + "metadata": { + "description": "Optional. Specify the type of lock." + } + } + }, + "metadata": { + "description": "An AVM-aligned type for a lock.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.5.1" + } + } + }, + "managedIdentityOnlyUserAssignedType": { + "type": "object", + "properties": { + "userAssignedResourceIds": { + "type": "array", + "items": { + "type": "string" + }, + "nullable": true, + "metadata": { + "description": "Optional. The resource ID(s) to assign to the resource. Required if a user assigned identity is used for encryption." + } + } + }, + "metadata": { + "description": "An AVM-aligned type for a managed identity configuration. To be used if only user-assigned identities are supported by the resource provider.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.5.1" + } + } + }, + "roleAssignmentType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." + } + }, + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, or its fully qualified ID in the following format: '/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11'." + } + }, + "principalId": { + "type": "string", + "metadata": { + "description": "Required. The principal ID of the principal (user/group/identity) to assign the role to." + } + }, + "principalType": { + "type": "string", + "allowedValues": [ + "Device", + "ForeignGroup", + "Group", + "ServicePrincipal", + "User" + ], + "nullable": true, + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The description of the role assignment." + } + }, + "condition": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." + } + }, + "conditionVersion": { + "type": "string", + "allowedValues": [ + "2.0" + ], + "nullable": true, + "metadata": { + "description": "Optional. Version of the condition." + } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Resource Id of the delegated managed identity resource." + } + } + }, + "metadata": { + "description": "An AVM-aligned type for a role assignment.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.5.1" + } + } } }, "parameters": { @@ -3845,11 +5128,12 @@ }, "customizationSteps": { "type": "array", + "nullable": true, "metadata": { - "description": "Required. Customization steps to be run when building the VM image." + "description": "Optional. Customization steps to be run when building the VM image." } }, - "stagingResourceGroup": { + "stagingResourceGroupResourceId": { "type": "string", "nullable": true, "metadata": { @@ -3858,6 +5142,7 @@ }, "lock": { "$ref": "#/definitions/lockType", + "nullable": true, "metadata": { "description": "Optional. The lock settings of the service." } @@ -3873,7 +5158,7 @@ "type": "string", "defaultValue": "[utcNow('yyyy-MM-dd-HH-mm-ss')]", "metadata": { - "description": "Generated. Do not provide a value! This date value is used to generate a unique image template name." + "description": "Generated. Do not provide a value! This date is used to generate a unique image template name." } }, "enableTelemetry": { @@ -3884,7 +5169,11 @@ } }, "roleAssignments": { - "$ref": "#/definitions/roleAssignmentType", + "type": "array", + "items": { + "$ref": "#/definitions/roleAssignmentType" + }, + "nullable": true, "metadata": { "description": "Optional. Array of role assignments to create." } @@ -3906,13 +5195,14 @@ } }, "managedIdentities": { - "$ref": "#/definitions/managedIdentitiesType", + "$ref": "#/definitions/managedIdentityOnlyUserAssignedType", "metadata": { "description": "Required. The managed identity definition for this resource." } }, "validationProcess": { "$ref": "#/definitions/validationProcessType", + "nullable": true, "metadata": { "description": "Optional. Configuration options and list of validations to be performed on the resulting image." } @@ -3927,9 +5217,56 @@ "metadata": { "description": "Optional. The optimize property can be enabled while creating a VM image and allows VM optimization to improve image creation time." } + }, + "autoRunState": { + "type": "string", + "defaultValue": "Disabled", + "allowedValues": [ + "Enabled", + "Disabled" + ], + "metadata": { + "description": "Optional. Indicates whether or not to automatically run the image template build on template creation or update." + } + }, + "errorHandlingOnCustomizerError": { + "type": "string", + "defaultValue": "cleanup", + "allowedValues": [ + "cleanup", + "abort" + ], + "metadata": { + "description": "Optional. If there is a customizer error and this field is set to 'cleanup', the build VM and associated network resources will be cleaned up. This is the default behavior. If there is a customizer error and this field is set to 'abort', the build VM will be preserved." + } + }, + "errorHandlingOnValidationError": { + "type": "string", + "defaultValue": "cleanup", + "allowedValues": [ + "cleanup", + "abort" + ], + "metadata": { + "description": "Optional. If there is a validation error and this field is set to 'cleanup', the build VM and associated network resources will be cleaned up. If there is a validation error and this field is set to 'abort', the build VM will be preserved. This is the default behavior." + } + }, + "managedResourceTags": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Tags that will be applied to the resource group and/or resources created by the service." + } } }, "variables": { + "copy": [ + { + "name": "formattedRoleAssignments", + "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]", + "input": "[union(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')], createObject('roleDefinitionId', coalesce(tryGet(variables('builtInRoleNames'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName), if(contains(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName)))))]" + } + ], "identity": { "type": "UserAssigned", "userAssignedIdentities": "[reduce(map(coalesce(tryGet(parameters('managedIdentities'), 'userAssignedResourceIds'), createArray()), lambda('id', createObject(format('{0}', lambdaVariables('id')), createObject()))), createObject(), lambda('cur', 'next', union(lambdaVariables('cur'), lambdaVariables('next'))))]" @@ -3938,7 +5275,7 @@ "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", - "Role Based Access Control Administrator (Preview)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168')]", + "Role Based Access Control Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168')]", "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]" } }, @@ -3946,7 +5283,7 @@ "avmTelemetry": { "condition": "[parameters('enableTelemetry')]", "type": "Microsoft.Resources/deployments", - "apiVersion": "2023-07-01", + "apiVersion": "2024-03-01", "name": "[format('46d3xbcp.res.virtualmachineimages-imagetemplate.{0}.{1}', replace('-..--..-', '.', '-'), substring(uniqueString(deployment().name, parameters('location')), 0, 4))]", "properties": { "mode": "Incremental", @@ -3965,32 +5302,12 @@ }, "imageTemplate": { "type": "Microsoft.VirtualMachineImages/imageTemplates", - "apiVersion": "2023-07-01", + "apiVersion": "2024-02-01", "name": "[format('{0}-{1}', parameters('name'), parameters('baseTime'))]", "location": "[parameters('location')]", "tags": "[parameters('tags')]", "identity": "[variables('identity')]", - "properties": { - "copy": [ - { - "name": "distribute", - "count": "[length(parameters('distributions'))]", - "input": "[union(createObject('type', parameters('distributions')[copyIndex('distribute')].type, 'artifactTags', coalesce(tryGet(parameters('distributions')[copyIndex('distribute')], 'artifactTags'), createObject('sourceType', parameters('imageSource').type, 'sourcePublisher', tryGet(parameters('imageSource'), 'publisher'), 'sourceOffer', tryGet(parameters('imageSource'), 'offer'), 'sourceSku', tryGet(parameters('imageSource'), 'sku'), 'sourceVersion', tryGet(parameters('imageSource'), 'version'), 'sourceImageId', tryGet(parameters('imageSource'), 'imageId'), 'sourceImageVersionID', tryGet(parameters('imageSource'), 'imageVersionID'), 'creationTime', parameters('baseTime')))), if(equals(parameters('distributions')[copyIndex('distribute')].type, 'ManagedImage'), createObject('runOutputName', coalesce(tryGet(parameters('distributions')[copyIndex('distribute')], 'runOutputName'), format('{0}-{1}-ManagedImage', parameters('distributions')[copyIndex('distribute')].imageName, parameters('baseTime'))), 'location', coalesce(tryGet(parameters('distributions')[copyIndex('distribute')], 'location'), parameters('location')), 'imageId', coalesce(tryGet(parameters('distributions')[copyIndex('distribute')], 'imageResourceId'), format('{0}/resourceGroups/{1}/providers/Microsoft.Compute/images/{2}-{3}', subscription().id, resourceGroup().name, parameters('distributions')[copyIndex('distribute')].imageName, parameters('baseTime')))), createObject()), if(equals(parameters('distributions')[copyIndex('distribute')].type, 'SharedImage'), createObject('runOutputName', coalesce(tryGet(parameters('distributions')[copyIndex('distribute')], 'runOutputName'), if(not(empty(tryGet(parameters('distributions')[copyIndex('distribute')], 'sharedImageGalleryImageDefinitionResourceId'))), format('{0}-SharedImage', last(split(coalesce(parameters('distributions')[copyIndex('distribute')].sharedImageGalleryImageDefinitionResourceId, '/'), '/'))), 'SharedImage')), 'galleryImageId', if(not(empty(tryGet(parameters('distributions')[copyIndex('distribute')], 'sharedImageGalleryImageDefinitionTargetVersion'))), format('{0}/versions/{1}', parameters('distributions')[copyIndex('distribute')].sharedImageGalleryImageDefinitionResourceId, parameters('distributions')[copyIndex('distribute')].sharedImageGalleryImageDefinitionTargetVersion), parameters('distributions')[copyIndex('distribute')].sharedImageGalleryImageDefinitionResourceId), 'excludeFromLatest', coalesce(tryGet(parameters('distributions')[copyIndex('distribute')], 'excludeFromLatest'), false()), 'replicationRegions', coalesce(tryGet(parameters('distributions')[copyIndex('distribute')], 'replicationRegions'), createArray(parameters('location'))), 'storageAccountType', coalesce(tryGet(parameters('distributions')[copyIndex('distribute')], 'storageAccountType'), 'Standard_LRS')), createObject()), if(equals(parameters('distributions')[copyIndex('distribute')].type, 'VHD'), createObject('runOutputName', coalesce(tryGet(parameters('distributions')[copyIndex('distribute')], 'runOutputName'), format('{0}-VHD', parameters('distributions')[copyIndex('distribute')].imageName))), createObject()))]" - } - ], - "buildTimeoutInMinutes": "[parameters('buildTimeoutInMinutes')]", - "vmProfile": { - "vmSize": "[parameters('vmSize')]", - "osDiskSizeGB": "[parameters('osDiskSizeGB')]", - "userAssignedIdentities": "[parameters('vmUserAssignedIdentities')]", - "vnetConfig": "[if(not(empty(parameters('subnetResourceId'))), createObject('subnetId', parameters('subnetResourceId')), null())]" - }, - "source": "[parameters('imageSource')]", - "customize": "[parameters('customizationSteps')]", - "stagingResourceGroup": "[parameters('stagingResourceGroup')]", - "validate": "[parameters('validationProcess')]", - "optimize": "[if(not(equals(parameters('optimizeVmBoot'), null())), createObject('vmBoot', createObject('state', parameters('optimizeVmBoot'))), null())]" - } + "properties": "[shallowMerge(createArray(createObject('buildTimeoutInMinutes', parameters('buildTimeoutInMinutes'), 'vmProfile', createObject('vmSize', parameters('vmSize'), 'osDiskSizeGB', parameters('osDiskSizeGB'), 'userAssignedIdentities', parameters('vmUserAssignedIdentities'), 'vnetConfig', if(not(empty(parameters('subnetResourceId'))), createObject('subnetId', parameters('subnetResourceId')), null())), 'source', parameters('imageSource')), if(not(empty(parameters('customizationSteps'))), createObject('customize', parameters('customizationSteps')), createObject()), createObject('stagingResourceGroup', parameters('stagingResourceGroupResourceId'), 'distribute', map(parameters('distributions'), lambda('distribution', shallowMerge(createArray(createObject('type', lambdaVariables('distribution').type, 'artifactTags', coalesce(tryGet(lambdaVariables('distribution'), 'artifactTags'), createObject('sourceType', parameters('imageSource').type, 'sourcePublisher', tryGet(parameters('imageSource'), 'publisher'), 'sourceOffer', tryGet(parameters('imageSource'), 'offer'), 'sourceSku', tryGet(parameters('imageSource'), 'sku'), 'sourceVersion', tryGet(parameters('imageSource'), 'version'), 'sourceImageId', tryGet(parameters('imageSource'), 'imageId'), 'sourceImageVersionID', tryGet(parameters('imageSource'), 'imageVersionID'), 'creationTime', parameters('baseTime')))), if(equals(lambdaVariables('distribution').type, 'ManagedImage'), createObject('runOutputName', coalesce(tryGet(lambdaVariables('distribution'), 'runOutputName'), format('{0}-{1}-ManagedImage', lambdaVariables('distribution').imageName, parameters('baseTime'))), 'location', coalesce(tryGet(lambdaVariables('distribution'), 'location'), parameters('location')), 'imageId', coalesce(tryGet(lambdaVariables('distribution'), 'imageResourceId'), format('{0}/resourceGroups/{1}/providers/Microsoft.Compute/images/{2}-{3}', subscription().id, resourceGroup().name, lambdaVariables('distribution').imageName, parameters('baseTime')))), createObject()), if(equals(lambdaVariables('distribution').type, 'SharedImage'), createObject('runOutputName', coalesce(tryGet(lambdaVariables('distribution'), 'runOutputName'), if(not(empty(tryGet(lambdaVariables('distribution'), 'sharedImageGalleryImageDefinitionResourceId'))), format('{0}-SharedImage', last(split(coalesce(lambdaVariables('distribution').sharedImageGalleryImageDefinitionResourceId, '/'), '/'))), 'SharedImage')), 'galleryImageId', if(not(empty(tryGet(lambdaVariables('distribution'), 'sharedImageGalleryImageDefinitionTargetVersion'))), format('{0}/versions/{1}', lambdaVariables('distribution').sharedImageGalleryImageDefinitionResourceId, lambdaVariables('distribution').sharedImageGalleryImageDefinitionTargetVersion), lambdaVariables('distribution').sharedImageGalleryImageDefinitionResourceId), 'excludeFromLatest', coalesce(tryGet(lambdaVariables('distribution'), 'excludeFromLatest'), false()), 'replicationRegions', coalesce(tryGet(lambdaVariables('distribution'), 'replicationRegions'), createArray(parameters('location'))), 'storageAccountType', coalesce(tryGet(lambdaVariables('distribution'), 'storageAccountType'), 'Standard_LRS')), createObject()), if(equals(lambdaVariables('distribution').type, 'VHD'), createObject('runOutputName', coalesce(tryGet(lambdaVariables('distribution'), 'runOutputName'), format('{0}-VHD', lambdaVariables('distribution').imageName))), createObject()))))), 'validate', parameters('validationProcess'), 'optimize', if(not(equals(parameters('optimizeVmBoot'), null())), createObject('vmBoot', createObject('state', parameters('optimizeVmBoot'))), null()), 'autoRun', createObject('state', parameters('autoRunState')), 'errorHandling', createObject('onCustomizerError', parameters('errorHandlingOnCustomizerError'), 'onValidationError', parameters('errorHandlingOnValidationError')), 'managedResourceTags', parameters('managedResourceTags'))))]" }, "imageTemplate_lock": { "condition": "[and(not(empty(coalesce(parameters('lock'), createObject()))), not(equals(tryGet(parameters('lock'), 'kind'), 'None')))]", @@ -4009,20 +5326,20 @@ "imageTemplate_roleAssignments": { "copy": { "name": "imageTemplate_roleAssignments", - "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]" + "count": "[length(coalesce(variables('formattedRoleAssignments'), createArray()))]" }, "type": "Microsoft.Authorization/roleAssignments", "apiVersion": "2022-04-01", "scope": "[format('Microsoft.VirtualMachineImages/imageTemplates/{0}', format('{0}-{1}', parameters('name'), parameters('baseTime')))]", - "name": "[guid(resourceId('Microsoft.VirtualMachineImages/imageTemplates', format('{0}-{1}', parameters('name'), parameters('baseTime'))), coalesce(parameters('roleAssignments'), createArray())[copyIndex()].principalId, coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName)]", + "name": "[coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'name'), guid(resourceId('Microsoft.VirtualMachineImages/imageTemplates', format('{0}-{1}', parameters('name'), parameters('baseTime'))), coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId, coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId))]", "properties": { - "roleDefinitionId": "[if(contains(variables('builtInRoleNames'), coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName), variables('builtInRoleNames')[coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName], if(contains(coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/'), coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName)))]", - "principalId": "[coalesce(parameters('roleAssignments'), createArray())[copyIndex()].principalId]", - "description": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'description')]", - "principalType": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'principalType')]", - "condition": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'condition')]", - "conditionVersion": "[if(not(empty(tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'condition'))), coalesce(tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'conditionVersion'), '2.0'), null())]", - "delegatedManagedIdentityResourceId": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'delegatedManagedIdentityResourceId')]" + "roleDefinitionId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId]", + "principalId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId]", + "description": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'description')]", + "principalType": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'principalType')]", + "condition": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition')]", + "conditionVersion": "[if(not(empty(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition'))), coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'conditionVersion'), '2.0'), null())]", + "delegatedManagedIdentityResourceId": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'delegatedManagedIdentityResourceId')]" }, "dependsOn": [ "imageTemplate" @@ -4070,7 +5387,7 @@ "metadata": { "description": "The location the resource was deployed into." }, - "value": "[reference('imageTemplate', '2023-07-01', 'full').location]" + "value": "[reference('imageTemplate', '2024-02-01', 'full').location]" } } } @@ -4105,8 +5422,10 @@ "dataRetention": { "value": "[parameters('logAnalyticsWorkspaceDataRetention')]" }, - "useResourcePermissions": { - "value": true + "features": { + "value": { + "enableLogAccessUsingOnlyResourcePermissions": true + } }, "tags": "[if(parameters('enableResourceTags'), createObject('value', variables('varCommonResourceTags')), createObject('value', createObject()))]" }, @@ -4118,982 +5437,3710 @@ "_generator": { "name": "bicep", "version": "0.34.44.8038", - "templateHash": "8971404674064738552" + "templateHash": "13170081599813815725" }, "name": "Log Analytics Workspaces", - "description": "This module deploys a Log Analytics Workspace.", - "owner": "Azure/module-maintainers" + "description": "This module deploys a Log Analytics Workspace." }, "definitions": { - "managedIdentitiesType": { + "diagnosticSettingType": { "type": "object", "properties": { - "systemAssigned": { - "type": "bool", + "name": { + "type": "string", "nullable": true, "metadata": { - "description": "Optional. Enables system assigned managed identity on the resource." + "description": "Optional. The name of diagnostic setting." } }, - "userAssignedResourceIds": { + "logCategoriesAndGroups": { "type": "array", "items": { - "type": "string" + "type": "object", + "properties": { + "category": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Name of a Diagnostic Log category for a resource type this setting is applied to. Set the specific logs to collect here." + } + }, + "categoryGroup": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Name of a Diagnostic Log category group for a resource type this setting is applied to. Set to `allLogs` to collect all logs." + } + }, + "enabled": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Enable or disable the category explicitly. Default is `true`." + } + } + } + }, + "nullable": true, + "metadata": { + "description": "Optional. The name of logs that will be streamed. \"allLogs\" includes all possible logs for the resource. Set to `[]` to disable log collection." + } + }, + "metricCategories": { + "type": "array", + "items": { + "type": "object", + "properties": { + "category": { + "type": "string", + "metadata": { + "description": "Required. Name of a Diagnostic Metric category for a resource type this setting is applied to. Set to `AllMetrics` to collect all metrics." + } + }, + "enabled": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Enable or disable the category explicitly. Default is `true`." + } + } + } }, "nullable": true, "metadata": { - "description": "Optional. The resource ID(s) to assign to the resource." + "description": "Optional. The name of metrics that will be streamed. \"allMetrics\" includes all possible metrics for the resource. Set to `[]` to disable metric collection." + } + }, + "logAnalyticsDestinationType": { + "type": "string", + "allowedValues": [ + "AzureDiagnostics", + "Dedicated" + ], + "nullable": true, + "metadata": { + "description": "Optional. A string indicating whether the export to Log Analytics should use the default destination type, i.e. AzureDiagnostics, or use a destination type." + } + }, + "useThisWorkspace": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Instead of using an external reference, use the deployed instance as the target for its diagnostic settings. If set to `true`, the `workspaceResourceId` property is ignored." + } + }, + "workspaceResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Resource ID of the diagnostic log analytics workspace. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub." + } + }, + "storageAccountResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Resource ID of the diagnostic storage account. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub." + } + }, + "eventHubAuthorizationRuleResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to." + } + }, + "eventHubName": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub." + } + }, + "marketplacePartnerResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The full ARM resource ID of the Marketplace resource to which you would like to send Diagnostic Logs." } } - }, - "nullable": true - } - }, - "parameters": { - "name": { - "type": "string", - "metadata": { - "description": "Required. Name of the Log Analytics workspace." } }, - "location": { - "type": "string", - "defaultValue": "[resourceGroup().location]", + "gallerySolutionType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. Name of the solution.\nFor solutions authored by Microsoft, the name must be in the pattern: `SolutionType(WorkspaceName)`, for example: `AntiMalware(contoso-Logs)`.\nFor solutions authored by third parties, the name should be in the pattern: `SolutionType[WorkspaceName]`, for example `MySolution[contoso-Logs]`.\nThe solution type is case-sensitive." + } + }, + "plan": { + "$ref": "#/definitions/solutionPlanType", + "metadata": { + "description": "Required. Plan for solution object supported by the OperationsManagement resource provider." + } + } + }, "metadata": { - "description": "Optional. Location for all resources." + "__bicep_export!": true, + "description": "Properties of the gallery solutions to be created in the log analytics workspace." } }, - "skuName": { - "type": "string", - "defaultValue": "PerGB2018", - "allowedValues": [ - "CapacityReservation", - "Free", - "LACluster", - "PerGB2018", - "PerNode", - "Premium", - "Standalone", - "Standard" - ], + "storageInsightsConfigType": { + "type": "object", + "properties": { + "storageAccountResourceId": { + "type": "string", + "metadata": { + "description": "Required. Resource ID of the storage account to be linked." + } + }, + "containers": { + "type": "array", + "items": { + "type": "string" + }, + "nullable": true, + "metadata": { + "description": "Optional. The names of the blob containers that the workspace should read." + } + }, + "tables": { + "type": "array", + "items": { + "type": "string" + }, + "nullable": true, + "metadata": { + "description": "Optional. List of tables to be read by the workspace." + } + } + }, "metadata": { - "description": "Optional. The name of the SKU." + "__bicep_export!": true, + "description": "Properties of the storage insights configuration." } }, - "skuCapacityReservationLevel": { - "type": "int", - "defaultValue": 100, - "minValue": 100, - "maxValue": 5000, + "linkedServiceType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. Name of the linked service." + } + }, + "resourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The resource id of the resource that will be linked to the workspace. This should be used for linking resources which require read access." + } + }, + "writeAccessResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The resource id of the resource that will be linked to the workspace. This should be used for linking resources which require write access." + } + } + }, "metadata": { - "description": "Optional. The capacity reservation level in GB for this workspace, when CapacityReservation sku is selected. Must be in increments of 100 between 100 and 5000." + "__bicep_export!": true, + "description": "Properties of the linked service." } }, - "storageInsightsConfigs": { - "type": "array", - "defaultValue": [], + "linkedStorageAccountType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. Name of the link." + } + }, + "storageAccountIds": { + "type": "array", + "items": { + "type": "string" + }, + "minLength": 1, + "metadata": { + "description": "Required. Linked storage accounts resources Ids." + } + } + }, "metadata": { - "description": "Optional. List of storage accounts to be read by the workspace." + "__bicep_export!": true, + "description": "Properties of the linked storage account." } }, - "dataRetention": { - "type": "int", - "defaultValue": 365, - "minValue": 0, - "maxValue": 730, + "savedSearchType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. Name of the saved search." + } + }, + "etag": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The ETag of the saved search. To override an existing saved search, use \"*\" or specify the current Etag." + } + }, + "category": { + "type": "string", + "metadata": { + "description": "Required. The category of the saved search. This helps the user to find a saved search faster." + } + }, + "displayName": { + "type": "string", + "metadata": { + "description": "Required. Display name for the search." + } + }, + "functionAlias": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The function alias if query serves as a function." + } + }, + "functionParameters": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The optional function parameters if query serves as a function. Value should be in the following format: 'param-name1:type1 = default_value1, param-name2:type2 = default_value2'. For more examples and proper syntax please refer to /azure/kusto/query/functions/user-defined-functions." + } + }, + "query": { + "type": "string", + "metadata": { + "description": "Required. The query expression for the saved search." + } + }, + "tags": { + "type": "array", + "nullable": true, + "metadata": { + "description": "Optional. The tags attached to the saved search." + } + }, + "version": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. The version number of the query language. The current version is 2 and is the default." + } + } + }, "metadata": { - "description": "Optional. Number of days data will be retained for." + "__bicep_export!": true, + "description": "Properties of the saved search." } }, - "dailyQuotaGb": { - "type": "int", - "defaultValue": -1, - "minValue": -1, - "metadata": { - "description": "Optional. The workspace daily quota for ingestion." - } - }, - "publicNetworkAccessForIngestion": { - "type": "string", - "defaultValue": "Enabled", - "allowedValues": [ - "Enabled", - "Disabled" - ], - "metadata": { - "description": "Optional. The network access type for accessing Log Analytics ingestion." - } - }, - "publicNetworkAccessForQuery": { - "type": "string", - "defaultValue": "Enabled", - "allowedValues": [ - "Enabled", - "Disabled" - ], - "metadata": { - "description": "Optional. The network access type for accessing Log Analytics query." - } - }, - "managedIdentities": { - "$ref": "#/definitions/managedIdentitiesType", - "metadata": { - "description": "Optional. The managed identity definition for this resource. Only one type of identity is supported: system-assigned or user-assigned, but not both." - } - }, - "useResourcePermissions": { - "type": "bool", - "defaultValue": false, - "metadata": { - "description": "Optional. Set to 'true' to use resource or workspace permissions and 'false' (or leave empty) to require workspace permissions." - } - }, - "forceCmkForQuery": { - "type": "bool", - "defaultValue": true, - "metadata": { - "description": "Optional. Indicates whether customer managed storage is mandatory for query management." - } - }, - "tags": { + "dataExportType": { "type": "object", - "nullable": true, + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. Name of the data export." + } + }, + "destination": { + "$ref": "#/definitions/destinationType", + "nullable": true, + "metadata": { + "description": "Optional. The destination of the data export." + } + }, + "enable": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Enable or disable the data export." + } + }, + "tableNames": { + "type": "array", + "items": { + "type": "string" + }, + "metadata": { + "description": "Required. The list of table names to export." + } + } + }, "metadata": { - "description": "Optional. Tags of the resource." + "__bicep_export!": true, + "description": "Properties of the data export." } }, - "enableTelemetry": { - "type": "bool", - "defaultValue": true, - "metadata": { - "description": "Optional. Enable/Disable usage telemetry for module." - } - } - }, - "variables": { - "formattedUserAssignedIdentities": "[reduce(map(coalesce(tryGet(parameters('managedIdentities'), 'userAssignedResourceIds'), createArray()), lambda('id', createObject(format('{0}', lambdaVariables('id')), createObject()))), createObject(), lambda('cur', 'next', union(lambdaVariables('cur'), lambdaVariables('next'))))]", - "identity": "[if(not(empty(parameters('managedIdentities'))), createObject('type', if(coalesce(tryGet(parameters('managedIdentities'), 'systemAssigned'), false()), 'SystemAssigned', if(not(empty(coalesce(tryGet(parameters('managedIdentities'), 'userAssignedResourceIds'), createObject()))), 'UserAssigned', 'None')), 'userAssignedIdentities', if(not(empty(variables('formattedUserAssignedIdentities'))), variables('formattedUserAssignedIdentities'), null())), null())]" - }, - "resources": { - "avmTelemetry": { - "condition": "[parameters('enableTelemetry')]", - "type": "Microsoft.Resources/deployments", - "apiVersion": "2023-07-01", - "name": "[format('46d3xbcp.res.operationalinsights-workspace.{0}.{1}', replace('-..--..-', '.', '-'), substring(uniqueString(deployment().name, parameters('location')), 0, 4))]", + "dataSourceType": { + "type": "object", "properties": { - "mode": "Incremental", - "template": { - "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", - "contentVersion": "1.0.0.0", - "resources": [], - "outputs": { - "telemetry": { - "type": "String", - "value": "For more information, see https://aka.ms/avm/TelemetryInfo" - } + "name": { + "type": "string", + "metadata": { + "description": "Required. Name of the data source." + } + }, + "kind": { + "type": "string", + "metadata": { + "description": "Required. The kind of data source." + } + }, + "linkedResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The resource id of the resource that will be linked to the workspace." + } + }, + "eventLogName": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of the event log to configure when kind is WindowsEvent." + } + }, + "eventTypes": { + "type": "array", + "nullable": true, + "metadata": { + "description": "Optional. The event types to configure when kind is WindowsEvent." + } + }, + "objectName": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Name of the object to configure when kind is WindowsPerformanceCounter or LinuxPerformanceObject." + } + }, + "instanceName": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Name of the instance to configure when kind is WindowsPerformanceCounter or LinuxPerformanceObject." + } + }, + "intervalSeconds": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. Interval in seconds to configure when kind is WindowsPerformanceCounter or LinuxPerformanceObject." + } + }, + "performanceCounters": { + "type": "array", + "nullable": true, + "metadata": { + "description": "Optional. List of counters to configure when the kind is LinuxPerformanceObject." + } + }, + "counterName": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Counter name to configure when kind is WindowsPerformanceCounter." + } + }, + "state": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. State to configure when kind is IISLogs or LinuxSyslogCollection or LinuxPerformanceCollection." + } + }, + "syslogName": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. System log to configure when kind is LinuxSyslog." + } + }, + "syslogSeverities": { + "type": "array", + "nullable": true, + "metadata": { + "description": "Optional. Severities to configure when kind is LinuxSyslog." + } + }, + "tags": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Tags to configure in the resource." } } + }, + "metadata": { + "__bicep_export!": true, + "description": "Properties of the data source." } }, - "logAnalyticsWorkspace": { - "type": "Microsoft.OperationalInsights/workspaces", - "apiVersion": "2022-10-01", - "name": "[parameters('name')]", - "location": "[parameters('location')]", - "tags": "[parameters('tags')]", + "tableType": { + "type": "object", "properties": { - "features": { - "searchVersion": 1, - "enableLogAccessUsingOnlyResourcePermissions": "[parameters('useResourcePermissions')]" + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the table." + } }, - "sku": { - "name": "[parameters('skuName')]", - "capacityReservationLevel": "[if(equals(parameters('skuName'), 'CapacityReservation'), parameters('skuCapacityReservationLevel'), null())]" + "plan": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The plan for the table." + } }, - "retentionInDays": "[parameters('dataRetention')]", - "workspaceCapping": { - "dailyQuotaGb": "[parameters('dailyQuotaGb')]" + "restoredLogs": { + "$ref": "#/definitions/restoredLogsType", + "nullable": true, + "metadata": { + "description": "Optional. The restored logs for the table." + } }, - "publicNetworkAccessForIngestion": "[parameters('publicNetworkAccessForIngestion')]", - "publicNetworkAccessForQuery": "[parameters('publicNetworkAccessForQuery')]", - "forceCmkForQuery": "[parameters('forceCmkForQuery')]" + "schema": { + "$ref": "#/definitions/schemaType", + "nullable": true, + "metadata": { + "description": "Optional. The schema for the table." + } + }, + "searchResults": { + "$ref": "#/definitions/searchResultsType", + "nullable": true, + "metadata": { + "description": "Optional. The search results for the table." + } + }, + "retentionInDays": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. The retention in days for the table." + } + }, + "totalRetentionInDays": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. The total retention in days for the table." + } + }, + "roleAssignments": { + "type": "array", + "items": { + "$ref": "#/definitions/roleAssignmentType" + }, + "nullable": true, + "metadata": { + "description": "Optional. The role assignments for the table." + } + } }, - "identity": "[variables('identity')]" + "metadata": { + "__bicep_export!": true, + "description": "Properties of the custom table." + } }, - "logAnalyticsWorkspace_storageInsightConfigs": { - "copy": { - "name": "logAnalyticsWorkspace_storageInsightConfigs", - "count": "[length(parameters('storageInsightsConfigs'))]" - }, - "type": "Microsoft.Resources/deployments", - "apiVersion": "2022-09-01", - "name": "[format('{0}-LAW-StorageInsightsConfig-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "workspaceFeaturesType": { + "type": "object", "properties": { - "expressionEvaluationOptions": { - "scope": "inner" + "disableLocalAuth": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Disable Non-EntraID based Auth. Default is true." + } }, - "mode": "Incremental", - "parameters": { - "logAnalyticsWorkspaceName": { - "value": "[parameters('name')]" - }, - "containers": "[if(contains(parameters('storageInsightsConfigs')[copyIndex()], 'containers'), createObject('value', parameters('storageInsightsConfigs')[copyIndex()].containers), createObject('value', createArray()))]", - "tables": "[if(contains(parameters('storageInsightsConfigs')[copyIndex()], 'tables'), createObject('value', parameters('storageInsightsConfigs')[copyIndex()].tables), createObject('value', createArray()))]", - "storageAccountResourceId": { - "value": "[parameters('storageInsightsConfigs')[copyIndex()].storageAccountResourceId]" + "enableDataExport": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Flag that indicate if data should be exported." } }, - "template": { - "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", - "languageVersion": "2.0", - "contentVersion": "1.0.0.0", + "enableLogAccessUsingOnlyResourcePermissions": { + "type": "bool", + "nullable": true, "metadata": { - "_generator": { - "name": "bicep", - "version": "0.34.44.8038", - "templateHash": "4384156253703622371" - }, - "name": "Log Analytics Workspace Storage Insight Configs", - "description": "This module deploys a Log Analytics Workspace Storage Insight Config.", - "owner": "Azure/module-maintainers" - }, - "parameters": { - "logAnalyticsWorkspaceName": { - "type": "string", - "metadata": { - "description": "Conditional. The name of the parent Log Analytics workspace. Required if the template is used in a standalone deployment." - } - }, - "name": { - "type": "string", - "defaultValue": "[format('{0}-stinsconfig', last(split(parameters('storageAccountResourceId'), '/')))]", - "metadata": { - "description": "Optional. The name of the storage insights config." - } - }, - "storageAccountResourceId": { - "type": "string", - "metadata": { - "description": "Required. The Azure Resource Manager ID of the storage account resource." - } - }, - "containers": { - "type": "array", - "defaultValue": [], - "metadata": { - "description": "Optional. The names of the blob containers that the workspace should read." - } - }, - "tables": { - "type": "array", - "defaultValue": [], - "metadata": { - "description": "Optional. The names of the Azure tables that the workspace should read." - } - }, - "tags": { - "type": "object", - "nullable": true, - "metadata": { - "description": "Optional. Tags to configure in the resource." - } - } - }, - "resources": { - "storageAccount": { - "existing": true, - "type": "Microsoft.Storage/storageAccounts", - "apiVersion": "2022-09-01", - "name": "[last(split(parameters('storageAccountResourceId'), '/'))]" - }, - "workspace": { - "existing": true, - "type": "Microsoft.OperationalInsights/workspaces", - "apiVersion": "2022-10-01", - "name": "[parameters('logAnalyticsWorkspaceName')]" - }, - "storageinsightconfig": { - "type": "Microsoft.OperationalInsights/workspaces/storageInsightConfigs", - "apiVersion": "2020-08-01", - "name": "[format('{0}/{1}', parameters('logAnalyticsWorkspaceName'), parameters('name'))]", - "tags": "[parameters('tags')]", - "properties": { - "containers": "[parameters('containers')]", - "tables": "[parameters('tables')]", - "storageAccount": { - "id": "[parameters('storageAccountResourceId')]", - "key": "[listKeys(resourceId('Microsoft.Storage/storageAccounts', last(split(parameters('storageAccountResourceId'), '/'))), '2022-09-01').keys[0].value]" - } - } - } - }, - "outputs": { - "resourceId": { - "type": "string", - "metadata": { - "description": "The resource ID of the deployed storage insights configuration." - }, - "value": "[resourceId('Microsoft.OperationalInsights/workspaces/storageInsightConfigs', parameters('logAnalyticsWorkspaceName'), parameters('name'))]" - }, - "resourceGroupName": { - "type": "string", - "metadata": { - "description": "The resource group where the storage insight configuration is deployed." - }, - "value": "[resourceGroup().name]" - }, - "name": { - "type": "string", - "metadata": { - "description": "The name of the storage insights configuration." - }, - "value": "[parameters('name')]" - } + "description": "Optional. Enable log access using only resource permissions. Default is false." } - } - }, - "dependsOn": [ - "logAnalyticsWorkspace" - ] - } - }, - "outputs": { - "resourceId": { - "type": "string", - "metadata": { - "description": "The resource ID of the deployed log analytics workspace." - }, - "value": "[resourceId('Microsoft.OperationalInsights/workspaces', parameters('name'))]" - }, - "resourceGroupName": { - "type": "string", - "metadata": { - "description": "The resource group of the deployed log analytics workspace." - }, - "value": "[resourceGroup().name]" - }, - "name": { - "type": "string", - "metadata": { - "description": "The name of the deployed log analytics workspace." - }, - "value": "[parameters('name')]" - }, - "logAnalyticsWorkspaceId": { - "type": "string", - "metadata": { - "description": "The ID associated with the workspace." - }, - "value": "[reference('logAnalyticsWorkspace').customerId]" - }, - "location": { - "type": "string", - "metadata": { - "description": "The location the resource was deployed into." - }, - "value": "[reference('logAnalyticsWorkspace', '2022-10-01', 'full').location]" - }, - "systemAssignedMIPrincipalId": { - "type": "string", - "metadata": { - "description": "The principal ID of the system assigned identity." - }, - "value": "[coalesce(tryGet(tryGet(reference('logAnalyticsWorkspace', '2022-10-01', 'full'), 'identity'), 'principalId'), '')]" - } - } - } - }, - "dependsOn": [ - "[subscriptionResourceId(parameters('sharedServicesSubId'), 'Microsoft.Resources/deployments', format('RG-{0}', parameters('time')))]" - ] - }, - { - "type": "Microsoft.Resources/deployments", - "apiVersion": "2022-09-01", - "name": "[format('Automation-Account-{0}', parameters('time'))]", - "subscriptionId": "[parameters('sharedServicesSubId')]", - "resourceGroup": "[variables('varResourceGroupName')]", - "properties": { - "expressionEvaluationOptions": { - "scope": "inner" - }, - "mode": "Incremental", - "parameters": { - "diagnosticSettings": "[if(parameters('enableMonitoringAlerts'), createObject('value', createArray(createObject('workspaceResourceId', if(empty(parameters('alertsDistributionGroup')), '', if(empty(parameters('existingLogAnalyticsWorkspaceResourceId')), reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('sharedServicesSubId'), variables('varResourceGroupName')), 'Microsoft.Resources/deployments', format('Log-Analytics-Workspace-{0}', parameters('time'))), '2022-09-01').outputs.resourceId.value, parameters('existingLogAnalyticsWorkspaceResourceId')))))), createObject('value', createArray()))]", - "name": { - "value": "[variables('varAutomationAccountName')]" - }, - "jobSchedules": { - "value": [ - { - "parameters": { - "ClientId": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('sharedServicesSubId'), variables('varResourceGroupName')), 'Microsoft.Resources/deployments', format('User-Assigned-Managed-Identity-{0}', parameters('time'))), '2022-09-01').outputs.clientId.value]", - "EnvironmentName": "[variables('varAzureCloudName')]", - "ImageOffer": "[variables('varOperatingSystemImageDefinitions')[parameters('operatingSystemImage')].offer]", - "ImagePublisher": "[variables('varOperatingSystemImageDefinitions')[parameters('operatingSystemImage')].publisher]", - "ImageSku": "[variables('varOperatingSystemImageDefinitions')[parameters('operatingSystemImage')].sku]", - "Location": "[parameters('deploymentLocation')]", - "SubscriptionId": "[parameters('sharedServicesSubId')]", - "TemplateName": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('sharedServicesSubId'), variables('varResourceGroupName')), 'Microsoft.Resources/deployments', format('Image-Template-{0}', parameters('time'))), '2022-09-01').outputs.name.value]", - "TemplateResourceGroupName": "[variables('varResourceGroupName')]", - "TenantId": "[subscription().tenantId]" }, - "runbookName": "aib-build-automation", - "scheduleName": "[variables('varImageTemplateName')]" - } - ] - }, - "location": { - "value": "[parameters('deploymentLocation')]" - }, - "runbooks": { - "value": [ - { - "name": "aib-build-automation", - "description": "When this runbook is triggered, last build date is checked on the AIB image template. If a new marketplace image has been released since that date, a new build is initiated. If a build has never been initiated then it will be start one.", - "type": "PowerShell", - "uri": "https://raw.githubusercontent.com/Azure/avdaccelerator/main/workload/scripts/New-AzureImageBuilderBuild.ps1", - "version": "1.0.0.0" - } - ] - }, - "schedules": { - "value": [ - { - "name": "[variables('varImageTemplateName')]", - "frequency": "[if(equals(parameters('buildSchedule'), 'OneTime'), 'OneTime', 'Day')]", - "interval": "[if(equals(parameters('buildSchedule'), 'OneTime'), 0, 1)]", - "starttime": "[dateTimeAdd(parameters('time'), 'PT15M')]", - "varTimeZone": "[variables('varTimeZone')]", - "advancedSchedule": {} - } - ] - }, - "skuName": { - "value": "Free" - }, - "tags": "[if(parameters('enableResourceTags'), createObject('value', variables('varCommonResourceTags')), createObject('value', createObject()))]", - "managedIdentities": { - "value": { - "systemAssigned": false, - "userAssignedResourceIds": [ - "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('sharedServicesSubId'), variables('varResourceGroupName')), 'Microsoft.Resources/deployments', format('User-Assigned-Managed-Identity-{0}', parameters('time'))), '2022-09-01').outputs.resourceId.value]" - ] - } - } - }, - "template": { - "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", - "languageVersion": "2.0", - "contentVersion": "1.0.0.0", - "metadata": { - "_generator": { - "name": "bicep", - "version": "0.34.44.8038", - "templateHash": "13651865514986653890" - }, - "name": "Automation Accounts", - "description": "This module deploys an Azure Automation Account.", - "owner": "Azure/module-maintainers" - }, - "definitions": { - "managedIdentitiesType": { - "type": "object", - "properties": { - "systemAssigned": { + "immediatePurgeDataOn30Days": { "type": "bool", "nullable": true, "metadata": { - "description": "Optional. Enables system assigned managed identity on the resource." - } - }, - "userAssignedResourceIds": { - "type": "array", - "items": { - "type": "string" - }, - "nullable": true, - "metadata": { - "description": "Optional. The resource ID(s) to assign to the resource." + "description": "Optional. Flag that describes if we want to remove the data after 30 days." } } }, - "nullable": true + "metadata": { + "__bicep_export!": true, + "description": "Features of the workspace." + } }, - "lockType": { + "_1.columnType": { "type": "object", "properties": { "name": { "type": "string", - "nullable": true, "metadata": { - "description": "Optional. Specify the name of lock." + "description": "Required. The column name." } }, - "kind": { + "type": { "type": "string", "allowedValues": [ - "CanNotDelete", - "None", - "ReadOnly" + "boolean", + "dateTime", + "dynamic", + "guid", + "int", + "long", + "real", + "string" ], - "nullable": true, "metadata": { - "description": "Optional. Specify the type of lock." + "description": "Required. The column type." } - } - }, - "nullable": true - }, - "roleAssignmentType": { - "type": "array", - "items": { - "type": "object", - "properties": { - "roleDefinitionIdOrName": { - "type": "string", - "metadata": { - "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, or its fully qualified ID in the following format: '/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11'." - } - }, - "principalId": { - "type": "string", - "metadata": { - "description": "Required. The principal ID of the principal (user/group/identity) to assign the role to." - } - }, - "principalType": { - "type": "string", - "allowedValues": [ - "Device", - "ForeignGroup", - "Group", - "ServicePrincipal", - "User" - ], - "nullable": true, - "metadata": { - "description": "Optional. The principal type of the assigned principal ID." - } - }, - "description": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The description of the role assignment." - } - }, - "condition": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." - } - }, - "conditionVersion": { - "type": "string", - "allowedValues": [ - "2.0" - ], - "nullable": true, - "metadata": { - "description": "Optional. Version of the condition." - } - }, - "delegatedManagedIdentityResourceId": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The Resource Id of the delegated managed identity resource." - } + }, + "dataTypeHint": { + "type": "string", + "allowedValues": [ + "armPath", + "guid", + "ip", + "uri" + ], + "nullable": true, + "metadata": { + "description": "Optional. The column data type logical hint." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The column description." + } + }, + "displayName": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Column display name." } } }, - "nullable": true + "metadata": { + "description": "The parameters of the table column.", + "__bicep_imported_from!": { + "sourceTemplate": "table/main.bicep" + } + } }, - "privateEndpointType": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The name of the private endpoint." - } - }, - "location": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The location to deploy the private endpoint to." - } - }, - "privateLinkServiceConnectionName": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The name of the private link connection to create." - } - }, - "service": { - "type": "string", - "metadata": { - "description": "Required. The subresource to deploy the private endpoint for. For example \"blob\", \"table\", \"queue\" or \"file\"." - } - }, - "subnetResourceId": { - "type": "string", - "metadata": { - "description": "Required. Resource ID of the subnet where the endpoint needs to be created." - } - }, - "privateDnsZoneGroupName": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The name of the private DNS zone group to create if privateDnsZoneResourceIds were provided." - } - }, - "privateDnsZoneResourceIds": { - "type": "array", - "items": { - "type": "string" - }, - "nullable": true, - "metadata": { - "description": "Optional. The private DNS zone groups to associate the private endpoint with. A DNS zone group can support up to 5 DNS zones." - } - }, - "isManualConnection": { - "type": "bool", - "nullable": true, - "metadata": { - "description": "Optional. If Manual Private Link Connection is required." - } - }, - "manualConnectionRequestMessage": { - "type": "string", - "nullable": true, - "maxLength": 140, - "metadata": { - "description": "Optional. A message passed to the owner of the remote resource with the manual connection request." - } - }, - "customDnsConfigs": { - "type": "array", - "items": { - "type": "object", - "properties": { - "fqdn": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Required. Fqdn that resolves to private endpoint ip address." - } - }, - "ipAddresses": { - "type": "array", - "items": { - "type": "string" - }, - "metadata": { - "description": "Required. A list of private ip addresses of the private endpoint." - } - } - } - }, - "nullable": true, - "metadata": { - "description": "Optional. Custom DNS configurations." - } - }, - "ipConfigurations": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string", - "metadata": { - "description": "Required. The name of the resource that is unique within a resource group." - } - }, - "properties": { - "type": "object", - "properties": { - "groupId": { - "type": "string", - "metadata": { - "description": "Required. The ID of a group obtained from the remote resource that this private endpoint should connect to." - } - }, - "memberName": { - "type": "string", - "metadata": { - "description": "Required. The member name of a group obtained from the remote resource that this private endpoint should connect to." - } - }, - "privateIPAddress": { - "type": "string", - "metadata": { - "description": "Required. A private ip address obtained from the private endpoint's subnet." - } - } - }, - "metadata": { - "description": "Required. Properties of private endpoint IP configurations." - } - } + "destinationType": { + "type": "object", + "properties": { + "resourceId": { + "type": "string", + "metadata": { + "description": "Required. The destination resource ID." + } + }, + "metaData": { + "type": "object", + "properties": { + "eventHubName": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Allows to define an Event Hub name. Not applicable when destination is Storage Account." } - }, - "nullable": true, - "metadata": { - "description": "Optional. A list of IP configurations of the private endpoint. This will be used to map to the First Party Service endpoints." - } - }, - "applicationSecurityGroupResourceIds": { - "type": "array", - "items": { - "type": "string" - }, - "nullable": true, - "metadata": { - "description": "Optional. Application security groups in which the private endpoint IP configuration is included." - } - }, - "customNetworkInterfaceName": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The custom name of the network interface attached to the private endpoint." - } - }, - "lock": { - "$ref": "#/definitions/lockType", - "metadata": { - "description": "Optional. Specify the type of lock." - } - }, - "roleAssignments": { - "$ref": "#/definitions/roleAssignmentType", - "metadata": { - "description": "Optional. Array of role assignments to create." } }, - "tags": { - "type": "object", - "nullable": true, - "metadata": { - "description": "Optional. Tags to be applied on all resources/resource groups in this deployment." - } - }, - "enableTelemetry": { - "type": "bool", - "nullable": true, - "metadata": { - "description": "Optional. Enable/Disable usage telemetry for module." - } - }, - "resourceGroupName": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. Specify if you want to deploy the Private Endpoint into a different resource group than the main resource." - } + "nullable": true, + "metadata": { + "description": "Optional. The destination metadata." } } }, - "nullable": true + "metadata": { + "description": "The data export destination properties.", + "__bicep_imported_from!": { + "sourceTemplate": "data-export/main.bicep" + } + } }, - "diagnosticSettingType": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The name of diagnostic setting." - } + "lockType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Specify the name of lock." + } + }, + "kind": { + "type": "string", + "allowedValues": [ + "CanNotDelete", + "None", + "ReadOnly" + ], + "nullable": true, + "metadata": { + "description": "Optional. Specify the type of lock." + } + } + }, + "metadata": { + "description": "An AVM-aligned type for a lock.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } + } + }, + "managedIdentityAllType": { + "type": "object", + "properties": { + "systemAssigned": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Enables system assigned managed identity on the resource." + } + }, + "userAssignedResourceIds": { + "type": "array", + "items": { + "type": "string" + }, + "nullable": true, + "metadata": { + "description": "Optional. The resource ID(s) to assign to the resource. Required if a user assigned identity is used for encryption." + } + } + }, + "metadata": { + "description": "An AVM-aligned type for a managed identity configuration. To be used if both a system-assigned & user-assigned identities are supported by the resource provider.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } + } + }, + "restoredLogsType": { + "type": "object", + "properties": { + "sourceTable": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The table to restore data from." + } + }, + "startRestoreTime": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The timestamp to start the restore from (UTC)." + } + }, + "endRestoreTime": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The timestamp to end the restore by (UTC)." + } + } + }, + "metadata": { + "description": "The parameters of the restore operation that initiated the table.", + "__bicep_imported_from!": { + "sourceTemplate": "table/main.bicep" + } + } + }, + "roleAssignmentType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." + } + }, + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, or its fully qualified ID in the following format: '/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11'." + } + }, + "principalId": { + "type": "string", + "metadata": { + "description": "Required. The principal ID of the principal (user/group/identity) to assign the role to." + } + }, + "principalType": { + "type": "string", + "allowedValues": [ + "Device", + "ForeignGroup", + "Group", + "ServicePrincipal", + "User" + ], + "nullable": true, + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The description of the role assignment." + } + }, + "condition": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." + } + }, + "conditionVersion": { + "type": "string", + "allowedValues": [ + "2.0" + ], + "nullable": true, + "metadata": { + "description": "Optional. Version of the condition." + } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Resource Id of the delegated managed identity resource." + } + } + }, + "metadata": { + "description": "An AVM-aligned type for a role assignment.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } + } + }, + "schemaType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The table name." + } + }, + "columns": { + "type": "array", + "items": { + "$ref": "#/definitions/_1.columnType" + }, + "metadata": { + "description": "Required. A list of table custom columns." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The table description." + } + }, + "displayName": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The table display name." + } + } + }, + "metadata": { + "description": "The table schema.", + "__bicep_imported_from!": { + "sourceTemplate": "table/main.bicep" + } + } + }, + "searchResultsType": { + "type": "object", + "properties": { + "query": { + "type": "string", + "metadata": { + "description": "Required. The search job query." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The search description." + } + }, + "limit": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. Limit the search job to return up to specified number of rows." + } + }, + "startSearchTime": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The timestamp to start the search from (UTC)." + } + }, + "endSearchTime": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The timestamp to end the search by (UTC)." + } + } + }, + "metadata": { + "description": "The parameters of the search job that initiated the table.", + "__bicep_imported_from!": { + "sourceTemplate": "table/main.bicep" + } + } + }, + "solutionPlanType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Name of the solution to be created.\nFor solutions authored by Microsoft, the name must be in the pattern: `SolutionType(WorkspaceName)`, for example: `AntiMalware(contoso-Logs)`.\nFor solutions authored by third parties, it can be anything.\nThe solution type is case-sensitive.\nIf not provided, the value of the `name` parameter will be used." + } + }, + "product": { + "type": "string", + "metadata": { + "description": "Required. The product name of the deployed solution.\nFor Microsoft published gallery solution it should be `OMSGallery/{solutionType}`, for example `OMSGallery/AntiMalware`.\nFor a third party solution, it can be anything.\nThis is case sensitive." + } + }, + "publisher": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The publisher name of the deployed solution. For Microsoft published gallery solution, it is `Microsoft`, which is the default value." + } + } + }, + "metadata": { + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/res/operations-management/solution:0.3.0" + } + } + } + }, + "parameters": { + "name": { + "type": "string", + "metadata": { + "description": "Required. Name of the Log Analytics workspace." + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. Location for all resources." + } + }, + "skuName": { + "type": "string", + "defaultValue": "PerGB2018", + "allowedValues": [ + "CapacityReservation", + "Free", + "LACluster", + "PerGB2018", + "PerNode", + "Premium", + "Standalone", + "Standard" + ], + "metadata": { + "description": "Optional. The name of the SKU." + } + }, + "skuCapacityReservationLevel": { + "type": "int", + "defaultValue": 100, + "minValue": 100, + "maxValue": 5000, + "metadata": { + "description": "Optional. The capacity reservation level in GB for this workspace, when CapacityReservation sku is selected. Must be in increments of 100 between 100 and 5000." + } + }, + "storageInsightsConfigs": { + "type": "array", + "items": { + "$ref": "#/definitions/storageInsightsConfigType" + }, + "nullable": true, + "metadata": { + "description": "Optional. List of storage accounts to be read by the workspace." + } + }, + "linkedServices": { + "type": "array", + "items": { + "$ref": "#/definitions/linkedServiceType" + }, + "nullable": true, + "metadata": { + "description": "Optional. List of services to be linked." + } + }, + "linkedStorageAccounts": { + "type": "array", + "items": { + "$ref": "#/definitions/linkedStorageAccountType" + }, + "nullable": true, + "metadata": { + "description": "Conditional. List of Storage Accounts to be linked. Required if 'forceCmkForQuery' is set to 'true' and 'savedSearches' is not empty." + } + }, + "savedSearches": { + "type": "array", + "items": { + "$ref": "#/definitions/savedSearchType" + }, + "nullable": true, + "metadata": { + "description": "Optional. Kusto Query Language searches to save." + } + }, + "dataExports": { + "type": "array", + "items": { + "$ref": "#/definitions/dataExportType" + }, + "nullable": true, + "metadata": { + "description": "Optional. LAW data export instances to be deployed." + } + }, + "dataSources": { + "type": "array", + "items": { + "$ref": "#/definitions/dataSourceType" + }, + "nullable": true, + "metadata": { + "description": "Optional. LAW data sources to configure." + } + }, + "tables": { + "type": "array", + "items": { + "$ref": "#/definitions/tableType" + }, + "nullable": true, + "metadata": { + "description": "Optional. LAW custom tables to be deployed." + } + }, + "gallerySolutions": { + "type": "array", + "items": { + "$ref": "#/definitions/gallerySolutionType" + }, + "nullable": true, + "metadata": { + "description": "Optional. List of gallerySolutions to be created in the log analytics workspace." + } + }, + "onboardWorkspaceToSentinel": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Onboard the Log Analytics Workspace to Sentinel. Requires 'SecurityInsights' solution to be in gallerySolutions." + } + }, + "dataRetention": { + "type": "int", + "defaultValue": 365, + "minValue": 0, + "maxValue": 730, + "metadata": { + "description": "Optional. Number of days data will be retained for." + } + }, + "dailyQuotaGb": { + "type": "int", + "defaultValue": -1, + "minValue": -1, + "metadata": { + "description": "Optional. The workspace daily quota for ingestion." + } + }, + "publicNetworkAccessForIngestion": { + "type": "string", + "defaultValue": "Enabled", + "allowedValues": [ + "Enabled", + "Disabled" + ], + "metadata": { + "description": "Optional. The network access type for accessing Log Analytics ingestion." + } + }, + "publicNetworkAccessForQuery": { + "type": "string", + "defaultValue": "Enabled", + "allowedValues": [ + "Enabled", + "Disabled" + ], + "metadata": { + "description": "Optional. The network access type for accessing Log Analytics query." + } + }, + "managedIdentities": { + "$ref": "#/definitions/managedIdentityAllType", + "nullable": true, + "metadata": { + "description": "Optional. The managed identity definition for this resource. Only one type of identity is supported: system-assigned or user-assigned, but not both." + } + }, + "features": { + "$ref": "#/definitions/workspaceFeaturesType", + "nullable": true, + "metadata": { + "description": "Optional. The workspace features." + } + }, + "diagnosticSettings": { + "type": "array", + "items": { + "$ref": "#/definitions/diagnosticSettingType" + }, + "nullable": true, + "metadata": { + "description": "Optional. The diagnostic settings of the service." + } + }, + "forceCmkForQuery": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Indicates whether customer managed storage is mandatory for query management." + } + }, + "lock": { + "$ref": "#/definitions/lockType", + "nullable": true, + "metadata": { + "description": "Optional. The lock settings of the service." + } + }, + "roleAssignments": { + "type": "array", + "items": { + "$ref": "#/definitions/roleAssignmentType" + }, + "nullable": true, + "metadata": { + "description": "Optional. Array of role assignments to create." + } + }, + "tags": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Tags of the resource." + } + }, + "enableTelemetry": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Enable/Disable usage telemetry for module." + } + } + }, + "variables": { + "copy": [ + { + "name": "formattedRoleAssignments", + "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]", + "input": "[union(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')], createObject('roleDefinitionId', coalesce(tryGet(variables('builtInRoleNames'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName), if(contains(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName)))))]" + } + ], + "formattedUserAssignedIdentities": "[reduce(map(coalesce(tryGet(parameters('managedIdentities'), 'userAssignedResourceIds'), createArray()), lambda('id', createObject(format('{0}', lambdaVariables('id')), createObject()))), createObject(), lambda('cur', 'next', union(lambdaVariables('cur'), lambdaVariables('next'))))]", + "identity": "[if(not(empty(parameters('managedIdentities'))), createObject('type', if(coalesce(tryGet(parameters('managedIdentities'), 'systemAssigned'), false()), 'SystemAssigned', if(not(empty(coalesce(tryGet(parameters('managedIdentities'), 'userAssignedResourceIds'), createObject()))), 'UserAssigned', 'None')), 'userAssignedIdentities', if(not(empty(variables('formattedUserAssignedIdentities'))), variables('formattedUserAssignedIdentities'), null())), null())]", + "builtInRoleNames": { + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Log Analytics Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293')]", + "Log Analytics Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893')]", + "Monitoring Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa')]", + "Monitoring Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05')]", + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Role Based Access Control Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168')]", + "Security Admin": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'fb1c8493-542b-48eb-b624-b4c8fea62acd')]", + "Security Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '39bc4728-0917-49c7-9d2c-d95423bc2eb4')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]" + } + }, + "resources": { + "avmTelemetry": { + "condition": "[parameters('enableTelemetry')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2024-03-01", + "name": "[format('46d3xbcp.res.operationalinsights-workspace.{0}.{1}', replace('-..--..-', '.', '-'), substring(uniqueString(deployment().name, parameters('location')), 0, 4))]", + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [], + "outputs": { + "telemetry": { + "type": "String", + "value": "For more information, see https://aka.ms/avm/TelemetryInfo" + } + } + } + } + }, + "logAnalyticsWorkspace": { + "type": "Microsoft.OperationalInsights/workspaces", + "apiVersion": "2023-09-01", + "name": "[parameters('name')]", + "location": "[parameters('location')]", + "tags": "[parameters('tags')]", + "properties": { + "features": { + "searchVersion": 1, + "enableLogAccessUsingOnlyResourcePermissions": "[coalesce(tryGet(parameters('features'), 'enableLogAccessUsingOnlyResourcePermissions'), false())]", + "disableLocalAuth": "[coalesce(tryGet(parameters('features'), 'disableLocalAuth'), true())]", + "enableDataExport": "[tryGet(parameters('features'), 'enableDataExport')]", + "immediatePurgeDataOn30Days": "[tryGet(parameters('features'), 'immediatePurgeDataOn30Days')]" + }, + "sku": { + "name": "[parameters('skuName')]", + "capacityReservationLevel": "[if(equals(parameters('skuName'), 'CapacityReservation'), parameters('skuCapacityReservationLevel'), null())]" + }, + "retentionInDays": "[parameters('dataRetention')]", + "workspaceCapping": { + "dailyQuotaGb": "[parameters('dailyQuotaGb')]" + }, + "publicNetworkAccessForIngestion": "[parameters('publicNetworkAccessForIngestion')]", + "publicNetworkAccessForQuery": "[parameters('publicNetworkAccessForQuery')]", + "forceCmkForQuery": "[parameters('forceCmkForQuery')]" + }, + "identity": "[variables('identity')]" + }, + "logAnalyticsWorkspace_diagnosticSettings": { + "copy": { + "name": "logAnalyticsWorkspace_diagnosticSettings", + "count": "[length(coalesce(parameters('diagnosticSettings'), createArray()))]" + }, + "type": "Microsoft.Insights/diagnosticSettings", + "apiVersion": "2021-05-01-preview", + "scope": "[format('Microsoft.OperationalInsights/workspaces/{0}', parameters('name'))]", + "name": "[coalesce(tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'name'), format('{0}-diagnosticSettings', parameters('name')))]", + "properties": { + "copy": [ + { + "name": "metrics", + "count": "[length(coalesce(tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'metricCategories'), createArray(createObject('category', 'AllMetrics'))))]", + "input": { + "category": "[coalesce(tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'metricCategories'), createArray(createObject('category', 'AllMetrics')))[copyIndex('metrics')].category]", + "enabled": "[coalesce(tryGet(coalesce(tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'metricCategories'), createArray(createObject('category', 'AllMetrics')))[copyIndex('metrics')], 'enabled'), true())]", + "timeGrain": null + } + }, + { + "name": "logs", + "count": "[length(coalesce(tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'logCategoriesAndGroups'), createArray(createObject('categoryGroup', 'allLogs'))))]", + "input": { + "categoryGroup": "[tryGet(coalesce(tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'logCategoriesAndGroups'), createArray(createObject('categoryGroup', 'allLogs')))[copyIndex('logs')], 'categoryGroup')]", + "category": "[tryGet(coalesce(tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'logCategoriesAndGroups'), createArray(createObject('categoryGroup', 'allLogs')))[copyIndex('logs')], 'category')]", + "enabled": "[coalesce(tryGet(coalesce(tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'logCategoriesAndGroups'), createArray(createObject('categoryGroup', 'allLogs')))[copyIndex('logs')], 'enabled'), true())]" + } + } + ], + "storageAccountId": "[tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'storageAccountResourceId')]", + "workspaceId": "[if(coalesce(tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'useThisWorkspace'), false()), resourceId('Microsoft.OperationalInsights/workspaces', parameters('name')), tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'workspaceResourceId'))]", + "eventHubAuthorizationRuleId": "[tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'eventHubAuthorizationRuleResourceId')]", + "eventHubName": "[tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'eventHubName')]", + "marketplacePartnerId": "[tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'marketplacePartnerResourceId')]", + "logAnalyticsDestinationType": "[tryGet(coalesce(parameters('diagnosticSettings'), createArray())[copyIndex()], 'logAnalyticsDestinationType')]" + }, + "dependsOn": [ + "logAnalyticsWorkspace" + ] + }, + "logAnalyticsWorkspace_sentinelOnboarding": { + "condition": "[and(not(empty(filter(coalesce(parameters('gallerySolutions'), createArray()), lambda('item', startsWith(lambdaVariables('item').name, 'SecurityInsights'))))), parameters('onboardWorkspaceToSentinel'))]", + "type": "Microsoft.SecurityInsights/onboardingStates", + "apiVersion": "2024-03-01", + "scope": "[format('Microsoft.OperationalInsights/workspaces/{0}', parameters('name'))]", + "name": "default", + "properties": {}, + "dependsOn": [ + "logAnalyticsWorkspace" + ] + }, + "logAnalyticsWorkspace_lock": { + "condition": "[and(not(empty(coalesce(parameters('lock'), createObject()))), not(equals(tryGet(parameters('lock'), 'kind'), 'None')))]", + "type": "Microsoft.Authorization/locks", + "apiVersion": "2020-05-01", + "scope": "[format('Microsoft.OperationalInsights/workspaces/{0}', parameters('name'))]", + "name": "[coalesce(tryGet(parameters('lock'), 'name'), format('lock-{0}', parameters('name')))]", + "properties": { + "level": "[coalesce(tryGet(parameters('lock'), 'kind'), '')]", + "notes": "[if(equals(tryGet(parameters('lock'), 'kind'), 'CanNotDelete'), 'Cannot delete resource or child resources.', 'Cannot delete or modify the resource or child resources.')]" + }, + "dependsOn": [ + "logAnalyticsWorkspace" + ] + }, + "logAnalyticsWorkspace_roleAssignments": { + "copy": { + "name": "logAnalyticsWorkspace_roleAssignments", + "count": "[length(coalesce(variables('formattedRoleAssignments'), createArray()))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2022-04-01", + "scope": "[format('Microsoft.OperationalInsights/workspaces/{0}', parameters('name'))]", + "name": "[coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'name'), guid(resourceId('Microsoft.OperationalInsights/workspaces', parameters('name')), coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId, coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId))]", + "properties": { + "roleDefinitionId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId]", + "principalId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId]", + "description": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'description')]", + "principalType": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'principalType')]", + "condition": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition')]", + "conditionVersion": "[if(not(empty(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition'))), coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'conditionVersion'), '2.0'), null())]", + "delegatedManagedIdentityResourceId": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'delegatedManagedIdentityResourceId')]" + }, + "dependsOn": [ + "logAnalyticsWorkspace" + ] + }, + "logAnalyticsWorkspace_storageInsightConfigs": { + "copy": { + "name": "logAnalyticsWorkspace_storageInsightConfigs", + "count": "[length(coalesce(parameters('storageInsightsConfigs'), createArray()))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-LAW-StorageInsightsConfig-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "logAnalyticsWorkspaceName": { + "value": "[parameters('name')]" + }, + "containers": { + "value": "[tryGet(coalesce(parameters('storageInsightsConfigs'), createArray())[copyIndex()], 'containers')]" + }, + "tables": { + "value": "[tryGet(coalesce(parameters('storageInsightsConfigs'), createArray())[copyIndex()], 'tables')]" + }, + "storageAccountResourceId": { + "value": "[coalesce(parameters('storageInsightsConfigs'), createArray())[copyIndex()].storageAccountResourceId]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.34.44.8038", + "templateHash": "9051499270642810789" + }, + "name": "Log Analytics Workspace Storage Insight Configs", + "description": "This module deploys a Log Analytics Workspace Storage Insight Config." + }, + "parameters": { + "logAnalyticsWorkspaceName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent Log Analytics workspace. Required if the template is used in a standalone deployment." + } + }, + "name": { + "type": "string", + "defaultValue": "[format('{0}-stinsconfig', last(split(parameters('storageAccountResourceId'), '/')))]", + "metadata": { + "description": "Optional. The name of the storage insights config." + } + }, + "storageAccountResourceId": { + "type": "string", + "metadata": { + "description": "Required. The Azure Resource Manager ID of the storage account resource." + } + }, + "containers": { + "type": "array", + "items": { + "type": "string" + }, + "nullable": true, + "metadata": { + "description": "Optional. The names of the blob containers that the workspace should read." + } + }, + "tables": { + "type": "array", + "items": { + "type": "string" + }, + "nullable": true, + "metadata": { + "description": "Optional. The names of the Azure tables that the workspace should read." + } + }, + "tags": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Tags to configure in the resource." + } + } + }, + "resources": { + "storageAccount": { + "existing": true, + "type": "Microsoft.Storage/storageAccounts", + "apiVersion": "2022-09-01", + "name": "[last(split(parameters('storageAccountResourceId'), '/'))]" + }, + "workspace": { + "existing": true, + "type": "Microsoft.OperationalInsights/workspaces", + "apiVersion": "2023-09-01", + "name": "[parameters('logAnalyticsWorkspaceName')]" + }, + "storageinsightconfig": { + "type": "Microsoft.OperationalInsights/workspaces/storageInsightConfigs", + "apiVersion": "2023-09-01", + "name": "[format('{0}/{1}', parameters('logAnalyticsWorkspaceName'), parameters('name'))]", + "tags": "[parameters('tags')]", + "properties": { + "containers": "[parameters('containers')]", + "tables": "[parameters('tables')]", + "storageAccount": { + "id": "[parameters('storageAccountResourceId')]", + "key": "[listKeys(resourceId('Microsoft.Storage/storageAccounts', last(split(parameters('storageAccountResourceId'), '/'))), '2022-09-01').keys[0].value]" + } + } + } + }, + "outputs": { + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the deployed storage insights configuration." + }, + "value": "[resourceId('Microsoft.OperationalInsights/workspaces/storageInsightConfigs', parameters('logAnalyticsWorkspaceName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The resource group where the storage insight configuration is deployed." + }, + "value": "[resourceGroup().name]" + }, + "name": { + "type": "string", + "metadata": { + "description": "The name of the storage insights configuration." + }, + "value": "[parameters('name')]" + } + } + } + }, + "dependsOn": [ + "logAnalyticsWorkspace" + ] + }, + "logAnalyticsWorkspace_linkedServices": { + "copy": { + "name": "logAnalyticsWorkspace_linkedServices", + "count": "[length(coalesce(parameters('linkedServices'), createArray()))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-LAW-LinkedService-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "logAnalyticsWorkspaceName": { + "value": "[parameters('name')]" + }, + "name": { + "value": "[coalesce(parameters('linkedServices'), createArray())[copyIndex()].name]" + }, + "resourceId": { + "value": "[tryGet(coalesce(parameters('linkedServices'), createArray())[copyIndex()], 'resourceId')]" + }, + "writeAccessResourceId": { + "value": "[tryGet(coalesce(parameters('linkedServices'), createArray())[copyIndex()], 'writeAccessResourceId')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.34.44.8038", + "templateHash": "3446289766074720900" + }, + "name": "Log Analytics Workspace Linked Services", + "description": "This module deploys a Log Analytics Workspace Linked Service." + }, + "parameters": { + "logAnalyticsWorkspaceName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent Log Analytics workspace. Required if the template is used in a standalone deployment." + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. Name of the link." + } + }, + "resourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The resource ID of the resource that will be linked to the workspace. This should be used for linking resources which require read access." + } + }, + "writeAccessResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The resource ID of the resource that will be linked to the workspace. This should be used for linking resources which require write access." + } + }, + "tags": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Tags to configure in the resource." + } + } + }, + "resources": { + "workspace": { + "existing": true, + "type": "Microsoft.OperationalInsights/workspaces", + "apiVersion": "2023-09-01", + "name": "[parameters('logAnalyticsWorkspaceName')]" + }, + "linkedService": { + "type": "Microsoft.OperationalInsights/workspaces/linkedServices", + "apiVersion": "2023-09-01", + "name": "[format('{0}/{1}', parameters('logAnalyticsWorkspaceName'), parameters('name'))]", + "tags": "[parameters('tags')]", + "properties": { + "resourceId": "[parameters('resourceId')]", + "writeAccessResourceId": "[parameters('writeAccessResourceId')]" + } + } + }, + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the deployed linked service." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the deployed linked service." + }, + "value": "[resourceId('Microsoft.OperationalInsights/workspaces/linkedServices', parameters('logAnalyticsWorkspaceName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The resource group where the linked service is deployed." + }, + "value": "[resourceGroup().name]" + } + } + } + }, + "dependsOn": [ + "logAnalyticsWorkspace" + ] + }, + "logAnalyticsWorkspace_linkedStorageAccounts": { + "copy": { + "name": "logAnalyticsWorkspace_linkedStorageAccounts", + "count": "[length(coalesce(parameters('linkedStorageAccounts'), createArray()))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-LAW-LinkedStorageAccount-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "logAnalyticsWorkspaceName": { + "value": "[parameters('name')]" + }, + "name": { + "value": "[coalesce(parameters('linkedStorageAccounts'), createArray())[copyIndex()].name]" + }, + "storageAccountIds": { + "value": "[coalesce(parameters('linkedStorageAccounts'), createArray())[copyIndex()].storageAccountIds]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.34.44.8038", + "templateHash": "2851368446344033310" + }, + "name": "Log Analytics Workspace Linked Storage Accounts", + "description": "This module deploys a Log Analytics Workspace Linked Storage Account." + }, + "parameters": { + "logAnalyticsWorkspaceName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent Log Analytics workspace. Required if the template is used in a standalone deployment." + } + }, + "name": { + "type": "string", + "allowedValues": [ + "Query", + "Alerts", + "CustomLogs", + "AzureWatson" + ], + "metadata": { + "description": "Required. Name of the link." + } + }, + "storageAccountIds": { + "type": "array", + "items": { + "type": "string" + }, + "minLength": 1, + "metadata": { + "description": "Required. Linked storage accounts resources Ids." + } + } + }, + "resources": { + "workspace": { + "existing": true, + "type": "Microsoft.OperationalInsights/workspaces", + "apiVersion": "2023-09-01", + "name": "[parameters('logAnalyticsWorkspaceName')]" + }, + "linkedStorageAccount": { + "type": "Microsoft.OperationalInsights/workspaces/linkedStorageAccounts", + "apiVersion": "2023-09-01", + "name": "[format('{0}/{1}', parameters('logAnalyticsWorkspaceName'), parameters('name'))]", + "properties": { + "storageAccountIds": "[parameters('storageAccountIds')]" + } + } + }, + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the deployed linked storage account." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the deployed linked storage account." + }, + "value": "[resourceId('Microsoft.OperationalInsights/workspaces/linkedStorageAccounts', parameters('logAnalyticsWorkspaceName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The resource group where the linked storage account is deployed." + }, + "value": "[resourceGroup().name]" + } + } + } + }, + "dependsOn": [ + "logAnalyticsWorkspace" + ] + }, + "logAnalyticsWorkspace_savedSearches": { + "copy": { + "name": "logAnalyticsWorkspace_savedSearches", + "count": "[length(coalesce(parameters('savedSearches'), createArray()))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-LAW-SavedSearch-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "logAnalyticsWorkspaceName": { + "value": "[parameters('name')]" + }, + "name": { + "value": "[format('{0}{1}', coalesce(parameters('savedSearches'), createArray())[copyIndex()].name, uniqueString(deployment().name))]" + }, + "etag": { + "value": "[tryGet(coalesce(parameters('savedSearches'), createArray())[copyIndex()], 'etag')]" + }, + "displayName": { + "value": "[coalesce(parameters('savedSearches'), createArray())[copyIndex()].displayName]" + }, + "category": { + "value": "[coalesce(parameters('savedSearches'), createArray())[copyIndex()].category]" + }, + "query": { + "value": "[coalesce(parameters('savedSearches'), createArray())[copyIndex()].query]" + }, + "functionAlias": { + "value": "[tryGet(coalesce(parameters('savedSearches'), createArray())[copyIndex()], 'functionAlias')]" + }, + "functionParameters": { + "value": "[tryGet(coalesce(parameters('savedSearches'), createArray())[copyIndex()], 'functionParameters')]" + }, + "tags": { + "value": "[tryGet(coalesce(parameters('savedSearches'), createArray())[copyIndex()], 'tags')]" + }, + "version": { + "value": "[tryGet(coalesce(parameters('savedSearches'), createArray())[copyIndex()], 'version')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.34.44.8038", + "templateHash": "17136566179979595265" + }, + "name": "Log Analytics Workspace Saved Searches", + "description": "This module deploys a Log Analytics Workspace Saved Search." + }, + "parameters": { + "logAnalyticsWorkspaceName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent Log Analytics workspace. Required if the template is used in a standalone deployment." + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. Name of the saved search." + } + }, + "displayName": { + "type": "string", + "metadata": { + "description": "Required. Display name for the search." + } + }, + "category": { + "type": "string", + "metadata": { + "description": "Required. Query category." + } + }, + "query": { + "type": "string", + "metadata": { + "description": "Required. Kusto Query to be stored." + } + }, + "tags": { + "type": "array", + "nullable": true, + "metadata": { + "description": "Optional. Tags to configure in the resource." + } + }, + "functionAlias": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. The function alias if query serves as a function." + } + }, + "functionParameters": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. The optional function parameters if query serves as a function. Value should be in the following format: \"param-name1:type1 = default_value1, param-name2:type2 = default_value2\". For more examples and proper syntax please refer to /azure/kusto/query/functions/user-defined-functions." + } + }, + "version": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. The version number of the query language." + } + }, + "etag": { + "type": "string", + "defaultValue": "*", + "metadata": { + "description": "Optional. The ETag of the saved search. To override an existing saved search, use \"*\" or specify the current Etag." + } + } + }, + "resources": { + "workspace": { + "existing": true, + "type": "Microsoft.OperationalInsights/workspaces", + "apiVersion": "2023-09-01", + "name": "[parameters('logAnalyticsWorkspaceName')]" + }, + "savedSearch": { + "type": "Microsoft.OperationalInsights/workspaces/savedSearches", + "apiVersion": "2023-09-01", + "name": "[format('{0}/{1}', parameters('logAnalyticsWorkspaceName'), parameters('name'))]", + "properties": { + "etag": "[parameters('etag')]", + "tags": "[coalesce(parameters('tags'), createArray())]", + "displayName": "[parameters('displayName')]", + "category": "[parameters('category')]", + "query": "[parameters('query')]", + "functionAlias": "[parameters('functionAlias')]", + "functionParameters": "[parameters('functionParameters')]", + "version": "[parameters('version')]" + } + } + }, + "outputs": { + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the deployed saved search." + }, + "value": "[resourceId('Microsoft.OperationalInsights/workspaces/savedSearches', parameters('logAnalyticsWorkspaceName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The resource group where the saved search is deployed." + }, + "value": "[resourceGroup().name]" + }, + "name": { + "type": "string", + "metadata": { + "description": "The name of the deployed saved search." + }, + "value": "[parameters('name')]" + } + } + } + }, + "dependsOn": [ + "logAnalyticsWorkspace", + "logAnalyticsWorkspace_linkedStorageAccounts" + ] + }, + "logAnalyticsWorkspace_dataExports": { + "copy": { + "name": "logAnalyticsWorkspace_dataExports", + "count": "[length(coalesce(parameters('dataExports'), createArray()))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-LAW-DataExport-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "workspaceName": { + "value": "[parameters('name')]" + }, + "name": { + "value": "[coalesce(parameters('dataExports'), createArray())[copyIndex()].name]" + }, + "destination": { + "value": "[tryGet(coalesce(parameters('dataExports'), createArray())[copyIndex()], 'destination')]" + }, + "enable": { + "value": "[tryGet(coalesce(parameters('dataExports'), createArray())[copyIndex()], 'enable')]" + }, + "tableNames": { + "value": "[tryGet(coalesce(parameters('dataExports'), createArray())[copyIndex()], 'tableNames')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.34.44.8038", + "templateHash": "13455168024740429315" + }, + "name": "Log Analytics Workspace Data Exports", + "description": "This module deploys a Log Analytics Workspace Data Export." + }, + "definitions": { + "destinationType": { + "type": "object", + "properties": { + "resourceId": { + "type": "string", + "metadata": { + "description": "Required. The destination resource ID." + } + }, + "metaData": { + "type": "object", + "properties": { + "eventHubName": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Allows to define an Event Hub name. Not applicable when destination is Storage Account." + } + } + }, + "nullable": true, + "metadata": { + "description": "Optional. The destination metadata." + } + } + }, + "metadata": { + "__bicep_export!": true, + "description": "The data export destination properties." + } + } + }, + "parameters": { + "name": { + "type": "string", + "minLength": 4, + "maxLength": 63, + "metadata": { + "description": "Required. The data export rule name." + } + }, + "workspaceName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent workspaces. Required if the template is used in a standalone deployment." + } + }, + "destination": { + "$ref": "#/definitions/destinationType", + "nullable": true, + "metadata": { + "description": "Optional. Destination properties." + } + }, + "enable": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Optional. Active when enabled." + } + }, + "tableNames": { + "type": "array", + "items": { + "type": "string" + }, + "minLength": 1, + "metadata": { + "description": "Required. An array of tables to export, for example: ['Heartbeat', 'SecurityEvent']." + } + } + }, + "resources": { + "workspace": { + "existing": true, + "type": "Microsoft.OperationalInsights/workspaces", + "apiVersion": "2023-09-01", + "name": "[parameters('workspaceName')]" + }, + "dataExport": { + "type": "Microsoft.OperationalInsights/workspaces/dataExports", + "apiVersion": "2023-09-01", + "name": "[format('{0}/{1}', parameters('workspaceName'), parameters('name'))]", + "properties": { + "destination": "[parameters('destination')]", + "enable": "[parameters('enable')]", + "tableNames": "[parameters('tableNames')]" + } + } + }, + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the data export." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the data export." + }, + "value": "[resourceId('Microsoft.OperationalInsights/workspaces/dataExports', parameters('workspaceName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The name of the resource group the data export was created in." + }, + "value": "[resourceGroup().name]" + } + } + } + }, + "dependsOn": [ + "logAnalyticsWorkspace" + ] + }, + "logAnalyticsWorkspace_dataSources": { + "copy": { + "name": "logAnalyticsWorkspace_dataSources", + "count": "[length(coalesce(parameters('dataSources'), createArray()))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-LAW-DataSource-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "logAnalyticsWorkspaceName": { + "value": "[parameters('name')]" + }, + "name": { + "value": "[coalesce(parameters('dataSources'), createArray())[copyIndex()].name]" + }, + "kind": { + "value": "[coalesce(parameters('dataSources'), createArray())[copyIndex()].kind]" + }, + "linkedResourceId": { + "value": "[tryGet(coalesce(parameters('dataSources'), createArray())[copyIndex()], 'linkedResourceId')]" + }, + "eventLogName": { + "value": "[tryGet(coalesce(parameters('dataSources'), createArray())[copyIndex()], 'eventLogName')]" + }, + "eventTypes": { + "value": "[tryGet(coalesce(parameters('dataSources'), createArray())[copyIndex()], 'eventTypes')]" + }, + "objectName": { + "value": "[tryGet(coalesce(parameters('dataSources'), createArray())[copyIndex()], 'objectName')]" + }, + "instanceName": { + "value": "[tryGet(coalesce(parameters('dataSources'), createArray())[copyIndex()], 'instanceName')]" + }, + "intervalSeconds": { + "value": "[tryGet(coalesce(parameters('dataSources'), createArray())[copyIndex()], 'intervalSeconds')]" + }, + "counterName": { + "value": "[tryGet(coalesce(parameters('dataSources'), createArray())[copyIndex()], 'counterName')]" + }, + "state": { + "value": "[tryGet(coalesce(parameters('dataSources'), createArray())[copyIndex()], 'state')]" + }, + "syslogName": { + "value": "[tryGet(coalesce(parameters('dataSources'), createArray())[copyIndex()], 'syslogName')]" + }, + "syslogSeverities": { + "value": "[tryGet(coalesce(parameters('dataSources'), createArray())[copyIndex()], 'syslogSeverities')]" + }, + "performanceCounters": { + "value": "[tryGet(coalesce(parameters('dataSources'), createArray())[copyIndex()], 'performanceCounters')]" + }, + "tags": { + "value": "[tryGet(coalesce(parameters('dataSources'), createArray())[copyIndex()], 'tags')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.34.44.8038", + "templateHash": "18361444309880126206" + }, + "name": "Log Analytics Workspace Datasources", + "description": "This module deploys a Log Analytics Workspace Data Source." + }, + "parameters": { + "logAnalyticsWorkspaceName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent Log Analytics workspace. Required if the template is used in a standalone deployment." + } + }, + "name": { + "type": "string", + "metadata": { + "description": "Required. Name of the data source." + } + }, + "kind": { + "type": "string", + "defaultValue": "AzureActivityLog", + "allowedValues": [ + "AzureActivityLog", + "WindowsEvent", + "WindowsPerformanceCounter", + "IISLogs", + "LinuxSyslog", + "LinuxSyslogCollection", + "LinuxPerformanceObject", + "LinuxPerformanceCollection" + ], + "metadata": { + "description": "Optional. The kind of the data source." + } + }, + "tags": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Tags to configure in the resource." + } + }, + "linkedResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Resource ID of the resource to be linked." + } + }, + "eventLogName": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Windows event log name to configure when kind is WindowsEvent." + } + }, + "eventTypes": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Windows event types to configure when kind is WindowsEvent." + } + }, + "objectName": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Name of the object to configure when kind is WindowsPerformanceCounter or LinuxPerformanceObject." + } + }, + "instanceName": { + "type": "string", + "defaultValue": "*", + "metadata": { + "description": "Optional. Name of the instance to configure when kind is WindowsPerformanceCounter or LinuxPerformanceObject." + } + }, + "intervalSeconds": { + "type": "int", + "defaultValue": 60, + "metadata": { + "description": "Optional. Interval in seconds to configure when kind is WindowsPerformanceCounter or LinuxPerformanceObject." + } + }, + "performanceCounters": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. List of counters to configure when the kind is LinuxPerformanceObject." + } + }, + "counterName": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Counter name to configure when kind is WindowsPerformanceCounter." + } + }, + "state": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. State to configure when kind is IISLogs or LinuxSyslogCollection or LinuxPerformanceCollection." + } + }, + "syslogName": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. System log to configure when kind is LinuxSyslog." + } + }, + "syslogSeverities": { + "type": "array", + "defaultValue": [], + "metadata": { + "description": "Optional. Severities to configure when kind is LinuxSyslog." + } + } + }, + "resources": { + "workspace": { + "existing": true, + "type": "Microsoft.OperationalInsights/workspaces", + "apiVersion": "2023-09-01", + "name": "[parameters('logAnalyticsWorkspaceName')]" + }, + "dataSource": { + "type": "Microsoft.OperationalInsights/workspaces/dataSources", + "apiVersion": "2023-09-01", + "name": "[format('{0}/{1}', parameters('logAnalyticsWorkspaceName'), parameters('name'))]", + "kind": "[parameters('kind')]", + "tags": "[parameters('tags')]", + "properties": { + "linkedResourceId": "[if(and(not(empty(parameters('kind'))), equals(parameters('kind'), 'AzureActivityLog')), parameters('linkedResourceId'), null())]", + "eventLogName": "[if(and(not(empty(parameters('kind'))), equals(parameters('kind'), 'WindowsEvent')), parameters('eventLogName'), null())]", + "eventTypes": "[if(and(not(empty(parameters('kind'))), equals(parameters('kind'), 'WindowsEvent')), parameters('eventTypes'), null())]", + "objectName": "[if(and(not(empty(parameters('kind'))), or(equals(parameters('kind'), 'WindowsPerformanceCounter'), equals(parameters('kind'), 'LinuxPerformanceObject'))), parameters('objectName'), null())]", + "instanceName": "[if(and(not(empty(parameters('kind'))), or(equals(parameters('kind'), 'WindowsPerformanceCounter'), equals(parameters('kind'), 'LinuxPerformanceObject'))), parameters('instanceName'), null())]", + "intervalSeconds": "[if(and(not(empty(parameters('kind'))), or(equals(parameters('kind'), 'WindowsPerformanceCounter'), equals(parameters('kind'), 'LinuxPerformanceObject'))), parameters('intervalSeconds'), null())]", + "counterName": "[if(and(not(empty(parameters('kind'))), equals(parameters('kind'), 'WindowsPerformanceCounter')), parameters('counterName'), null())]", + "state": "[if(and(not(empty(parameters('kind'))), or(or(equals(parameters('kind'), 'IISLogs'), equals(parameters('kind'), 'LinuxSyslogCollection')), equals(parameters('kind'), 'LinuxPerformanceCollection'))), parameters('state'), null())]", + "syslogName": "[if(and(not(empty(parameters('kind'))), equals(parameters('kind'), 'LinuxSyslog')), parameters('syslogName'), null())]", + "syslogSeverities": "[if(and(not(empty(parameters('kind'))), or(equals(parameters('kind'), 'LinuxSyslog'), equals(parameters('kind'), 'LinuxPerformanceObject'))), parameters('syslogSeverities'), null())]", + "performanceCounters": "[if(and(not(empty(parameters('kind'))), equals(parameters('kind'), 'LinuxPerformanceObject')), parameters('performanceCounters'), null())]" + } + } + }, + "outputs": { + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the deployed data source." + }, + "value": "[resourceId('Microsoft.OperationalInsights/workspaces/dataSources', parameters('logAnalyticsWorkspaceName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The resource group where the data source is deployed." + }, + "value": "[resourceGroup().name]" + }, + "name": { + "type": "string", + "metadata": { + "description": "The name of the deployed data source." + }, + "value": "[parameters('name')]" + } + } + } + }, + "dependsOn": [ + "logAnalyticsWorkspace" + ] + }, + "logAnalyticsWorkspace_tables": { + "copy": { + "name": "logAnalyticsWorkspace_tables", + "count": "[length(coalesce(parameters('tables'), createArray()))]" + }, + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-LAW-Table-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "workspaceName": { + "value": "[parameters('name')]" + }, + "name": { + "value": "[coalesce(parameters('tables'), createArray())[copyIndex()].name]" + }, + "plan": { + "value": "[tryGet(coalesce(parameters('tables'), createArray())[copyIndex()], 'plan')]" + }, + "schema": { + "value": "[tryGet(coalesce(parameters('tables'), createArray())[copyIndex()], 'schema')]" + }, + "retentionInDays": { + "value": "[tryGet(coalesce(parameters('tables'), createArray())[copyIndex()], 'retentionInDays')]" + }, + "totalRetentionInDays": { + "value": "[tryGet(coalesce(parameters('tables'), createArray())[copyIndex()], 'totalRetentionInDays')]" + }, + "restoredLogs": { + "value": "[tryGet(coalesce(parameters('tables'), createArray())[copyIndex()], 'restoredLogs')]" + }, + "searchResults": { + "value": "[tryGet(coalesce(parameters('tables'), createArray())[copyIndex()], 'searchResults')]" + }, + "roleAssignments": { + "value": "[tryGet(coalesce(parameters('tables'), createArray())[copyIndex()], 'roleAssignments')]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.34.44.8038", + "templateHash": "14889477996869149215" + }, + "name": "Log Analytics Workspace Tables", + "description": "This module deploys a Log Analytics Workspace Table." + }, + "definitions": { + "restoredLogsType": { + "type": "object", + "properties": { + "sourceTable": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The table to restore data from." + } + }, + "startRestoreTime": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The timestamp to start the restore from (UTC)." + } + }, + "endRestoreTime": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The timestamp to end the restore by (UTC)." + } + } + }, + "metadata": { + "__bicep_export!": true, + "description": "The parameters of the restore operation that initiated the table." + } + }, + "schemaType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The table name." + } + }, + "columns": { + "type": "array", + "items": { + "$ref": "#/definitions/columnType" + }, + "metadata": { + "description": "Required. A list of table custom columns." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The table description." + } + }, + "displayName": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The table display name." + } + } + }, + "metadata": { + "__bicep_export!": true, + "description": "The table schema." + } + }, + "columnType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The column name." + } + }, + "type": { + "type": "string", + "allowedValues": [ + "boolean", + "dateTime", + "dynamic", + "guid", + "int", + "long", + "real", + "string" + ], + "metadata": { + "description": "Required. The column type." + } + }, + "dataTypeHint": { + "type": "string", + "allowedValues": [ + "armPath", + "guid", + "ip", + "uri" + ], + "nullable": true, + "metadata": { + "description": "Optional. The column data type logical hint." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The column description." + } + }, + "displayName": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Column display name." + } + } + }, + "metadata": { + "__bicep_export!": true, + "description": "The parameters of the table column." + } + }, + "searchResultsType": { + "type": "object", + "properties": { + "query": { + "type": "string", + "metadata": { + "description": "Required. The search job query." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The search description." + } + }, + "limit": { + "type": "int", + "nullable": true, + "metadata": { + "description": "Optional. Limit the search job to return up to specified number of rows." + } + }, + "startSearchTime": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The timestamp to start the search from (UTC)." + } + }, + "endSearchTime": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The timestamp to end the search by (UTC)." + } + } + }, + "metadata": { + "__bicep_export!": true, + "description": "The parameters of the search job that initiated the table." + } + }, + "roleAssignmentType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." + } + }, + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, or its fully qualified ID in the following format: '/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11'." + } + }, + "principalId": { + "type": "string", + "metadata": { + "description": "Required. The principal ID of the principal (user/group/identity) to assign the role to." + } + }, + "principalType": { + "type": "string", + "allowedValues": [ + "Device", + "ForeignGroup", + "Group", + "ServicePrincipal", + "User" + ], + "nullable": true, + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The description of the role assignment." + } + }, + "condition": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." + } + }, + "conditionVersion": { + "type": "string", + "allowedValues": [ + "2.0" + ], + "nullable": true, + "metadata": { + "description": "Optional. Version of the condition." + } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Resource Id of the delegated managed identity resource." + } + } + }, + "metadata": { + "description": "An AVM-aligned type for a role assignment.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.2.1" + } + } + } + }, + "parameters": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the table." + } + }, + "workspaceName": { + "type": "string", + "metadata": { + "description": "Conditional. The name of the parent workspaces. Required if the template is used in a standalone deployment." + } + }, + "plan": { + "type": "string", + "defaultValue": "Analytics", + "allowedValues": [ + "Basic", + "Analytics" + ], + "metadata": { + "description": "Optional. Instruct the system how to handle and charge the logs ingested to this table." + } + }, + "restoredLogs": { + "$ref": "#/definitions/restoredLogsType", + "nullable": true, + "metadata": { + "description": "Optional. Restore parameters." + } + }, + "retentionInDays": { + "type": "int", + "defaultValue": -1, + "minValue": -1, + "maxValue": 730, + "metadata": { + "description": "Optional. The table retention in days, between 4 and 730. Setting this property to -1 will default to the workspace retention." + } + }, + "schema": { + "$ref": "#/definitions/schemaType", + "nullable": true, + "metadata": { + "description": "Optional. Table's schema." + } + }, + "searchResults": { + "$ref": "#/definitions/searchResultsType", + "nullable": true, + "metadata": { + "description": "Optional. Parameters of the search job that initiated this table." + } + }, + "totalRetentionInDays": { + "type": "int", + "defaultValue": -1, + "minValue": -1, + "maxValue": 2555, + "metadata": { + "description": "Optional. The table total retention in days, between 4 and 2555. Setting this property to -1 will default to table retention." + } + }, + "roleAssignments": { + "type": "array", + "items": { + "$ref": "#/definitions/roleAssignmentType" + }, + "nullable": true, + "metadata": { + "description": "Optional. Array of role assignments to create." + } + } + }, + "variables": { + "copy": [ + { + "name": "formattedRoleAssignments", + "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]", + "input": "[union(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')], createObject('roleDefinitionId', coalesce(tryGet(variables('builtInRoleNames'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName), if(contains(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName)))))]" + } + ], + "builtInRoleNames": { + "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", + "Log Analytics Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293')]", + "Log Analytics Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893')]", + "Monitoring Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa')]", + "Monitoring Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05')]", + "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", + "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", + "Role Based Access Control Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168')]", + "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]" + } + }, + "resources": { + "workspace": { + "existing": true, + "type": "Microsoft.OperationalInsights/workspaces", + "apiVersion": "2023-09-01", + "name": "[parameters('workspaceName')]" + }, + "table": { + "type": "Microsoft.OperationalInsights/workspaces/tables", + "apiVersion": "2023-09-01", + "name": "[format('{0}/{1}', parameters('workspaceName'), parameters('name'))]", + "properties": { + "plan": "[parameters('plan')]", + "restoredLogs": "[parameters('restoredLogs')]", + "retentionInDays": "[parameters('retentionInDays')]", + "schema": "[parameters('schema')]", + "searchResults": "[parameters('searchResults')]", + "totalRetentionInDays": "[parameters('totalRetentionInDays')]" + } + }, + "table_roleAssignments": { + "copy": { + "name": "table_roleAssignments", + "count": "[length(coalesce(variables('formattedRoleAssignments'), createArray()))]" + }, + "type": "Microsoft.Authorization/roleAssignments", + "apiVersion": "2022-04-01", + "scope": "[format('Microsoft.OperationalInsights/workspaces/{0}/tables/{1}', parameters('workspaceName'), parameters('name'))]", + "name": "[coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'name'), guid(resourceId('Microsoft.OperationalInsights/workspaces/tables', parameters('workspaceName'), parameters('name')), coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId, coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId))]", + "properties": { + "roleDefinitionId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId]", + "principalId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId]", + "description": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'description')]", + "principalType": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'principalType')]", + "condition": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition')]", + "conditionVersion": "[if(not(empty(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition'))), coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'conditionVersion'), '2.0'), null())]", + "delegatedManagedIdentityResourceId": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'delegatedManagedIdentityResourceId')]" + }, + "dependsOn": [ + "table" + ] + } + }, + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the table." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the table." + }, + "value": "[resourceId('Microsoft.OperationalInsights/workspaces/tables', parameters('workspaceName'), parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The name of the resource group the table was created in." + }, + "value": "[resourceGroup().name]" + } + } + } + }, + "dependsOn": [ + "logAnalyticsWorkspace" + ] + }, + "logAnalyticsWorkspace_solutions": { + "copy": { + "name": "logAnalyticsWorkspace_solutions", + "count": "[length(coalesce(parameters('gallerySolutions'), createArray()))]" + }, + "condition": "[not(empty(parameters('gallerySolutions')))]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('{0}-LAW-Solution-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "name": { + "value": "[coalesce(parameters('gallerySolutions'), createArray())[copyIndex()].name]" + }, + "location": { + "value": "[parameters('location')]" + }, + "logAnalyticsWorkspaceName": { + "value": "[parameters('name')]" + }, + "plan": { + "value": "[coalesce(parameters('gallerySolutions'), createArray())[copyIndex()].plan]" + }, + "enableTelemetry": { + "value": "[coalesce(tryGet(coalesce(parameters('gallerySolutions'), createArray())[copyIndex()], 'enableTelemetry'), parameters('enableTelemetry'))]" + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.30.23.60470", + "templateHash": "1867653058254938383" + }, + "name": "Operations Management Solutions", + "description": "This module deploys an Operations Management Solution.", + "owner": "Azure/module-maintainers" + }, + "definitions": { + "solutionPlanType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Name of the solution to be created.\nFor solutions authored by Microsoft, the name must be in the pattern: `SolutionType(WorkspaceName)`, for example: `AntiMalware(contoso-Logs)`.\nFor solutions authored by third parties, it can be anything.\nThe solution type is case-sensitive.\nIf not provided, the value of the `name` parameter will be used." + } + }, + "product": { + "type": "string", + "metadata": { + "description": "Required. The product name of the deployed solution.\nFor Microsoft published gallery solution it should be `OMSGallery/{solutionType}`, for example `OMSGallery/AntiMalware`.\nFor a third party solution, it can be anything.\nThis is case sensitive." + } + }, + "publisher": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The publisher name of the deployed solution. For Microsoft published gallery solution, it is `Microsoft`, which is the default value." + } + } + }, + "metadata": { + "__bicep_export!": true + } + } + }, + "parameters": { + "name": { + "type": "string", + "metadata": { + "description": "Required. Name of the solution.\nFor solutions authored by Microsoft, the name must be in the pattern: `SolutionType(WorkspaceName)`, for example: `AntiMalware(contoso-Logs)`.\nFor solutions authored by third parties, the name should be in the pattern: `SolutionType[WorkspaceName]`, for example `MySolution[contoso-Logs]`.\nThe solution type is case-sensitive." + } + }, + "plan": { + "$ref": "#/definitions/solutionPlanType", + "metadata": { + "description": "Required. Plan for solution object supported by the OperationsManagement resource provider." + } + }, + "logAnalyticsWorkspaceName": { + "type": "string", + "metadata": { + "description": "Required. Name of the Log Analytics workspace where the solution will be deployed/enabled." + } + }, + "location": { + "type": "string", + "defaultValue": "[resourceGroup().location]", + "metadata": { + "description": "Optional. Location for all resources." + } + }, + "enableTelemetry": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Optional. Enable/Disable usage telemetry for module." + } + } + }, + "resources": { + "avmTelemetry": { + "condition": "[parameters('enableTelemetry')]", + "type": "Microsoft.Resources/deployments", + "apiVersion": "2024-03-01", + "name": "[format('46d3xbcp.res.operationsmanagement-solution.{0}.{1}', replace('0.3.0', '.', '-'), substring(uniqueString(deployment().name, parameters('location')), 0, 4))]", + "properties": { + "mode": "Incremental", + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [], + "outputs": { + "telemetry": { + "type": "String", + "value": "For more information, see https://aka.ms/avm/TelemetryInfo" + } + } + } + } + }, + "logAnalyticsWorkspace": { + "existing": true, + "type": "Microsoft.OperationalInsights/workspaces", + "apiVersion": "2021-06-01", + "name": "[parameters('logAnalyticsWorkspaceName')]" + }, + "solution": { + "type": "Microsoft.OperationsManagement/solutions", + "apiVersion": "2015-11-01-preview", + "name": "[parameters('name')]", + "location": "[parameters('location')]", + "properties": { + "workspaceResourceId": "[resourceId('Microsoft.OperationalInsights/workspaces', parameters('logAnalyticsWorkspaceName'))]" + }, + "plan": { + "name": "[coalesce(tryGet(parameters('plan'), 'name'), parameters('name'))]", + "promotionCode": "", + "product": "[parameters('plan').product]", + "publisher": "[coalesce(tryGet(parameters('plan'), 'publisher'), 'Microsoft')]" + }, + "dependsOn": [ + "logAnalyticsWorkspace" + ] + } + }, + "outputs": { + "name": { + "type": "string", + "metadata": { + "description": "The name of the deployed solution." + }, + "value": "[parameters('name')]" + }, + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the deployed solution." + }, + "value": "[resourceId('Microsoft.OperationsManagement/solutions', parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The resource group where the solution is deployed." + }, + "value": "[resourceGroup().name]" + }, + "location": { + "type": "string", + "metadata": { + "description": "The location the resource was deployed into." + }, + "value": "[reference('solution', '2015-11-01-preview', 'full').location]" + } + } + } + }, + "dependsOn": [ + "logAnalyticsWorkspace" + ] + } + }, + "outputs": { + "resourceId": { + "type": "string", + "metadata": { + "description": "The resource ID of the deployed log analytics workspace." + }, + "value": "[resourceId('Microsoft.OperationalInsights/workspaces', parameters('name'))]" + }, + "resourceGroupName": { + "type": "string", + "metadata": { + "description": "The resource group of the deployed log analytics workspace." + }, + "value": "[resourceGroup().name]" + }, + "name": { + "type": "string", + "metadata": { + "description": "The name of the deployed log analytics workspace." + }, + "value": "[parameters('name')]" + }, + "logAnalyticsWorkspaceId": { + "type": "string", + "metadata": { + "description": "The ID associated with the workspace." + }, + "value": "[reference('logAnalyticsWorkspace').customerId]" + }, + "location": { + "type": "string", + "metadata": { + "description": "The location the resource was deployed into." + }, + "value": "[reference('logAnalyticsWorkspace', '2023-09-01', 'full').location]" + }, + "systemAssignedMIPrincipalId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "The principal ID of the system assigned identity." + }, + "value": "[tryGet(tryGet(reference('logAnalyticsWorkspace', '2023-09-01', 'full'), 'identity'), 'principalId')]" + } + } + } + }, + "dependsOn": [ + "[subscriptionResourceId(parameters('sharedServicesSubId'), 'Microsoft.Resources/deployments', format('RG-{0}', parameters('time')))]" + ] + }, + { + "type": "Microsoft.Resources/deployments", + "apiVersion": "2022-09-01", + "name": "[format('Automation-Account-{0}', parameters('time'))]", + "subscriptionId": "[parameters('sharedServicesSubId')]", + "resourceGroup": "[variables('varResourceGroupName')]", + "properties": { + "expressionEvaluationOptions": { + "scope": "inner" + }, + "mode": "Incremental", + "parameters": { + "diagnosticSettings": "[if(parameters('enableMonitoringAlerts'), createObject('value', createArray(createObject('workspaceResourceId', if(empty(parameters('alertsDistributionGroup')), '', if(empty(parameters('existingLogAnalyticsWorkspaceResourceId')), reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('sharedServicesSubId'), variables('varResourceGroupName')), 'Microsoft.Resources/deployments', format('Log-Analytics-Workspace-{0}', parameters('time'))), '2022-09-01').outputs.resourceId.value, parameters('existingLogAnalyticsWorkspaceResourceId')))))), createObject('value', createArray()))]", + "name": { + "value": "[variables('varAutomationAccountName')]" + }, + "jobSchedules": { + "value": [ + { + "parameters": { + "ClientId": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('sharedServicesSubId'), variables('varResourceGroupName')), 'Microsoft.Resources/deployments', format('User-Assigned-Managed-Identity-{0}', parameters('time'))), '2022-09-01').outputs.clientId.value]", + "EnvironmentName": "[variables('varAzureCloudName')]", + "ImageOffer": "[parameters('mpImageOffer')]", + "ImagePublisher": "[parameters('mpImagePublisher')]", + "ImageSku": "[parameters('mpImageSku')]", + "Location": "[parameters('deploymentLocation')]", + "SubscriptionId": "[parameters('sharedServicesSubId')]", + "TemplateName": "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('sharedServicesSubId'), variables('varResourceGroupName')), 'Microsoft.Resources/deployments', format('Image-Template-{0}', parameters('time'))), '2022-09-01').outputs.name.value]", + "TemplateResourceGroupName": "[variables('varResourceGroupName')]", + "TenantId": "[subscription().tenantId]" + }, + "runbookName": "aib-build-automation", + "scheduleName": "[variables('varImageTemplateName')]" + } + ] + }, + "location": { + "value": "[parameters('deploymentLocation')]" + }, + "runbooks": { + "value": [ + { + "name": "aib-build-automation", + "description": "When this runbook is triggered, last build date is checked on the AIB image template. If a new marketplace image has been released since that date, a new build is initiated. If a build has never been initiated then it will be start one.", + "type": "PowerShell", + "uri": "https://raw.githubusercontent.com/Azure/avdaccelerator/main/workload/scripts/New-AzureImageBuilderBuild.ps1", + "version": "1.0.0.0" + } + ] + }, + "schedules": { + "value": [ + { + "name": "[variables('varImageTemplateName')]", + "frequency": "[if(equals(parameters('buildSchedule'), 'OneTime'), 'OneTime', 'Day')]", + "interval": "[if(equals(parameters('buildSchedule'), 'OneTime'), 0, 1)]", + "starttime": "[dateTimeAdd(parameters('time'), 'PT15M')]", + "varTimeZone": "[variables('varTimeZone')]", + "advancedSchedule": {} + } + ] + }, + "skuName": { + "value": "Free" + }, + "tags": "[if(parameters('enableResourceTags'), createObject('value', variables('varCommonResourceTags')), createObject('value', createObject()))]", + "managedIdentities": { + "value": { + "systemAssigned": false, + "userAssignedResourceIds": [ + "[reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', parameters('sharedServicesSubId'), variables('varResourceGroupName')), 'Microsoft.Resources/deployments', format('User-Assigned-Managed-Identity-{0}', parameters('time'))), '2022-09-01').outputs.resourceId.value]" + ] + } + } + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "metadata": { + "_generator": { + "name": "bicep", + "version": "0.34.44.8038", + "templateHash": "9449404362838709909" + }, + "name": "Automation Accounts", + "description": "This module deploys an Azure Automation Account." + }, + "definitions": { + "credentialType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. Name of the Automation Account credential." + } + }, + "userName": { + "type": "string", + "metadata": { + "description": "Required. The user name associated to the credential." + } + }, + "password": { + "type": "securestring", + "metadata": { + "description": "Required. Password of the credential." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Description of the credential." + } + } + }, + "metadata": { + "__bicep_export!": true + } + }, + "gallerySolutionType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. Name of the solution.\nFor solutions authored by Microsoft, the name must be in the pattern: `SolutionType(WorkspaceName)`, for example: `AntiMalware(contoso-Logs)`.\nFor solutions authored by third parties, the name should be in the pattern: `SolutionType[WorkspaceName]`, for example `MySolution[contoso-Logs]`.\nThe solution type is case-sensitive." + } + }, + "plan": { + "$ref": "#/definitions/solutionPlanType", + "metadata": { + "description": "Required. Plan for solution object supported by the OperationsManagement resource provider." + } + } + }, + "metadata": { + "__bicep_export!": true + } + }, + "_1.privateEndpointCustomDnsConfigType": { + "type": "object", + "properties": { + "fqdn": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. FQDN that resolves to private endpoint IP address." + } + }, + "ipAddresses": { + "type": "array", + "items": { + "type": "string" }, - "logCategoriesAndGroups": { - "type": "array", - "items": { - "type": "object", - "properties": { - "category": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. Name of a Diagnostic Log category for a resource type this setting is applied to. Set the specific logs to collect here." - } - }, - "categoryGroup": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. Name of a Diagnostic Log category group for a resource type this setting is applied to. Set to `allLogs` to collect all logs." - } - }, - "enabled": { - "type": "bool", - "nullable": true, - "metadata": { - "description": "Optional. Enable or disable the category explicitly. Default is `true`." - } - } + "metadata": { + "description": "Required. A list of private IP addresses of the private endpoint." + } + } + }, + "metadata": { + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.4.0" + } + } + }, + "_1.privateEndpointIpConfigurationType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "metadata": { + "description": "Required. The name of the resource that is unique within a resource group." + } + }, + "properties": { + "type": "object", + "properties": { + "groupId": { + "type": "string", + "metadata": { + "description": "Required. The ID of a group obtained from the remote resource that this private endpoint should connect to." } }, - "nullable": true, - "metadata": { - "description": "Optional. The name of logs that will be streamed. \"allLogs\" includes all possible logs for the resource. Set to `[]` to disable log collection." + "memberName": { + "type": "string", + "metadata": { + "description": "Required. The member name of a group obtained from the remote resource that this private endpoint should connect to." + } + }, + "privateIPAddress": { + "type": "string", + "metadata": { + "description": "Required. A private IP address obtained from the private endpoint's subnet." + } } }, - "metricCategories": { - "type": "array", - "items": { - "type": "object", - "properties": { - "category": { - "type": "string", - "metadata": { - "description": "Required. Name of a Diagnostic Metric category for a resource type this setting is applied to. Set to `AllMetrics` to collect all metrics." - } - }, - "enabled": { - "type": "bool", - "nullable": true, - "metadata": { - "description": "Optional. Enable or disable the category explicitly. Default is `true`." - } + "metadata": { + "description": "Required. Properties of private endpoint IP configurations." + } + } + }, + "metadata": { + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.4.0" + } + } + }, + "_1.privateEndpointPrivateDnsZoneGroupType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of the Private DNS Zone Group." + } + }, + "privateDnsZoneGroupConfigs": { + "type": "array", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of the private DNS Zone Group config." + } + }, + "privateDnsZoneResourceId": { + "type": "string", + "metadata": { + "description": "Required. The resource id of the private DNS zone." } } - }, - "nullable": true, - "metadata": { - "description": "Optional. The name of metrics that will be streamed. \"allMetrics\" includes all possible metrics for the resource. Set to `[]` to disable metric collection." } }, - "logAnalyticsDestinationType": { - "type": "string", - "allowedValues": [ - "AzureDiagnostics", - "Dedicated" - ], - "nullable": true, - "metadata": { - "description": "Optional. A string indicating whether the export to Log Analytics should use the default destination type, i.e. AzureDiagnostics, or use a destination type." + "metadata": { + "description": "Required. The private DNS Zone Groups to associate the Private Endpoint. A DNS Zone Group can support up to 5 DNS zones." + } + } + }, + "metadata": { + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.4.0" + } + } + }, + "customerManagedKeyType": { + "type": "object", + "properties": { + "keyVaultResourceId": { + "type": "string", + "metadata": { + "description": "Required. The resource ID of a key vault to reference a customer managed key for encryption from." + } + }, + "keyName": { + "type": "string", + "metadata": { + "description": "Required. The name of the customer managed key to use for encryption." + } + }, + "keyVersion": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The version of the customer managed key to reference for encryption. If not provided, the deployment will use the latest version available at deployment time." + } + }, + "userAssignedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. User assigned identity to use when fetching the customer managed key. Required if no system assigned identity is available for use." + } + } + }, + "metadata": { + "description": "An AVM-aligned type for a customer-managed key. To be used if the resource type does not support auto-rotation of the customer-managed key.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.4.0" + } + } + }, + "diagnosticSettingFullType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of the diagnostic setting." + } + }, + "logCategoriesAndGroups": { + "type": "array", + "items": { + "type": "object", + "properties": { + "category": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Name of a Diagnostic Log category for a resource type this setting is applied to. Set the specific logs to collect here." + } + }, + "categoryGroup": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Name of a Diagnostic Log category group for a resource type this setting is applied to. Set to `allLogs` to collect all logs." + } + }, + "enabled": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Enable or disable the category explicitly. Default is `true`." + } + } + } + }, + "nullable": true, + "metadata": { + "description": "Optional. The name of logs that will be streamed. \"allLogs\" includes all possible logs for the resource. Set to `[]` to disable log collection." + } + }, + "metricCategories": { + "type": "array", + "items": { + "type": "object", + "properties": { + "category": { + "type": "string", + "metadata": { + "description": "Required. Name of a Diagnostic Metric category for a resource type this setting is applied to. Set to `AllMetrics` to collect all metrics." + } + }, + "enabled": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Enable or disable the category explicitly. Default is `true`." + } + } } }, - "workspaceResourceId": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. Resource ID of the diagnostic log analytics workspace. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub." - } + "nullable": true, + "metadata": { + "description": "Optional. The name of metrics that will be streamed. \"allMetrics\" includes all possible metrics for the resource. Set to `[]` to disable metric collection." + } + }, + "logAnalyticsDestinationType": { + "type": "string", + "allowedValues": [ + "AzureDiagnostics", + "Dedicated" + ], + "nullable": true, + "metadata": { + "description": "Optional. A string indicating whether the export to Log Analytics should use the default destination type, i.e. AzureDiagnostics, or use a destination type." + } + }, + "workspaceResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Resource ID of the diagnostic log analytics workspace. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub." + } + }, + "storageAccountResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Resource ID of the diagnostic storage account. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub." + } + }, + "eventHubAuthorizationRuleResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to." + } + }, + "eventHubName": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub." + } + }, + "marketplacePartnerResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The full ARM resource ID of the Marketplace resource to which you would like to send Diagnostic Logs." + } + } + }, + "metadata": { + "description": "An AVM-aligned type for a diagnostic setting. To be used if both logs & metrics are supported by the resource provider.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.4.0" + } + } + }, + "lockType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Specify the name of lock." + } + }, + "kind": { + "type": "string", + "allowedValues": [ + "CanNotDelete", + "None", + "ReadOnly" + ], + "nullable": true, + "metadata": { + "description": "Optional. Specify the type of lock." + } + } + }, + "metadata": { + "description": "An AVM-aligned type for a lock.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.4.0" + } + } + }, + "managedIdentityAllType": { + "type": "object", + "properties": { + "systemAssigned": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Enables system assigned managed identity on the resource." + } + }, + "userAssignedResourceIds": { + "type": "array", + "items": { + "type": "string" }, - "storageAccountResourceId": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. Resource ID of the diagnostic storage account. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub." - } + "nullable": true, + "metadata": { + "description": "Optional. The resource ID(s) to assign to the resource. Required if a user assigned identity is used for encryption." + } + } + }, + "metadata": { + "description": "An AVM-aligned type for a managed identity configuration. To be used if both a system-assigned & user-assigned identities are supported by the resource provider.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.4.0" + } + } + }, + "privateEndpointMultiServiceType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of the private endpoint." + } + }, + "location": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The location to deploy the private endpoint to." + } + }, + "privateLinkServiceConnectionName": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of the private link connection to create." + } + }, + "service": { + "type": "string", + "metadata": { + "description": "Required. The subresource to deploy the private endpoint for. For example \"blob\", \"table\", \"queue\" or \"file\" for a Storage Account's Private Endpoints." + } + }, + "subnetResourceId": { + "type": "string", + "metadata": { + "description": "Required. Resource ID of the subnet where the endpoint needs to be created." + } + }, + "privateDnsZoneGroup": { + "$ref": "#/definitions/_1.privateEndpointPrivateDnsZoneGroupType", + "nullable": true, + "metadata": { + "description": "Optional. The private DNS zone group to configure for the private endpoint." + } + }, + "isManualConnection": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. If Manual Private Link Connection is required." + } + }, + "manualConnectionRequestMessage": { + "type": "string", + "nullable": true, + "maxLength": 140, + "metadata": { + "description": "Optional. A message passed to the owner of the remote resource with the manual connection request." + } + }, + "customDnsConfigs": { + "type": "array", + "items": { + "$ref": "#/definitions/_1.privateEndpointCustomDnsConfigType" }, - "eventHubAuthorizationRuleResourceId": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to." - } + "nullable": true, + "metadata": { + "description": "Optional. Custom DNS configurations." + } + }, + "ipConfigurations": { + "type": "array", + "items": { + "$ref": "#/definitions/_1.privateEndpointIpConfigurationType" }, - "eventHubName": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub." - } + "nullable": true, + "metadata": { + "description": "Optional. A list of IP configurations of the private endpoint. This will be used to map to the First Party Service endpoints." + } + }, + "applicationSecurityGroupResourceIds": { + "type": "array", + "items": { + "type": "string" }, - "marketplacePartnerResourceId": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The full ARM resource ID of the Marketplace resource to which you would like to send Diagnostic Logs." - } + "nullable": true, + "metadata": { + "description": "Optional. Application security groups in which the private endpoint IP configuration is included." + } + }, + "customNetworkInterfaceName": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The custom name of the network interface attached to the private endpoint." + } + }, + "lock": { + "$ref": "#/definitions/lockType", + "nullable": true, + "metadata": { + "description": "Optional. Specify the type of lock." + } + }, + "roleAssignments": { + "type": "array", + "items": { + "$ref": "#/definitions/roleAssignmentType" + }, + "nullable": true, + "metadata": { + "description": "Optional. Array of role assignments to create." + } + }, + "tags": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Tags to be applied on all resources/resource groups in this deployment." + } + }, + "enableTelemetry": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Enable/Disable usage telemetry for module." + } + }, + "resourceGroupName": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Specify if you want to deploy the Private Endpoint into a different resource group than the main resource." + } + } + }, + "metadata": { + "description": "An AVM-aligned type for a private endpoint. To be used if the private endpoint's default service / groupId can NOT be assumed (i.e., for services that have more than one subresource, like Storage Account with Blob (blob, table, queue, file, ...).", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.4.0" + } + } + }, + "roleAssignmentType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." + } + }, + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, or its fully qualified ID in the following format: '/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11'." + } + }, + "principalId": { + "type": "string", + "metadata": { + "description": "Required. The principal ID of the principal (user/group/identity) to assign the role to." + } + }, + "principalType": { + "type": "string", + "allowedValues": [ + "Device", + "ForeignGroup", + "Group", + "ServicePrincipal", + "User" + ], + "nullable": true, + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The description of the role assignment." + } + }, + "condition": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." + } + }, + "conditionVersion": { + "type": "string", + "allowedValues": [ + "2.0" + ], + "nullable": true, + "metadata": { + "description": "Optional. Version of the condition." + } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Resource Id of the delegated managed identity resource." } } }, - "nullable": true + "metadata": { + "description": "An AVM-aligned type for a role assignment.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.4.0" + } + } }, - "customerManagedKeyType": { + "solutionPlanType": { "type": "object", "properties": { - "keyVaultResourceId": { - "type": "string", - "metadata": { - "description": "Required. The resource ID of a key vault to reference a customer managed key for encryption from." - } - }, - "keyName": { + "name": { "type": "string", + "nullable": true, "metadata": { - "description": "Required. The name of the customer managed key to use for encryption." + "description": "Optional. Name of the solution to be created.\nFor solutions authored by Microsoft, the name must be in the pattern: `SolutionType(WorkspaceName)`, for example: `AntiMalware(contoso-Logs)`.\nFor solutions authored by third parties, it can be anything.\nThe solution type is case-sensitive.\nIf not provided, the value of the `name` parameter will be used." } }, - "keyVersion": { + "product": { "type": "string", - "nullable": true, "metadata": { - "description": "Optional. The version of the customer managed key to reference for encryption. If not provided, using 'latest'." + "description": "Required. The product name of the deployed solution.\nFor Microsoft published gallery solution it should be `OMSGallery/{solutionType}`, for example `OMSGallery/AntiMalware`.\nFor a third party solution, it can be anything.\nThis is case sensitive." } }, - "userAssignedIdentityResourceId": { + "publisher": { "type": "string", "nullable": true, "metadata": { - "description": "Optional. User assigned identity to use when fetching the customer managed key. Required if no system assigned identity is available for use." - } - } - }, - "nullable": true - }, - "credentialType": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string", - "metadata": { - "description": "Required. Name of the Automation Account credential." - } - }, - "userName": { - "type": "string", - "metadata": { - "description": "Required. The user name associated to the credential." - } - }, - "password": { - "type": "securestring", - "metadata": { - "description": "Required. Password of the credential." - } - }, - "description": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. Description of the credential." - } + "description": "Optional. The publisher name of the deployed solution. For Microsoft published gallery solution, it is `Microsoft`, which is the default value." } } }, "metadata": { "__bicep_imported_from!": { - "sourceTemplate": "credential/main.bicep" + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/res/operations-management/solution:0.3.0" } } } @@ -5125,13 +9172,17 @@ }, "customerManagedKey": { "$ref": "#/definitions/customerManagedKeyType", + "nullable": true, "metadata": { "description": "Optional. The customer managed key definition." } }, "credentials": { - "$ref": "#/definitions/credentialType", - "defaultValue": [], + "type": "array", + "items": { + "$ref": "#/definitions/credentialType" + }, + "nullable": true, "metadata": { "description": "Optional. List of credentials to be created in the automation account." } @@ -5180,7 +9231,10 @@ }, "gallerySolutions": { "type": "array", - "defaultValue": [], + "items": { + "$ref": "#/definitions/gallerySolutionType" + }, + "nullable": true, "metadata": { "description": "Optional. List of gallerySolutions to be created in the linked log analytics workspace." } @@ -5212,31 +9266,45 @@ } }, "privateEndpoints": { - "$ref": "#/definitions/privateEndpointType", + "type": "array", + "items": { + "$ref": "#/definitions/privateEndpointMultiServiceType" + }, + "nullable": true, "metadata": { "description": "Optional. Configuration details for private endpoints. For security reasons, it is recommended to use private endpoints whenever possible." } }, "diagnosticSettings": { - "$ref": "#/definitions/diagnosticSettingType", + "type": "array", + "items": { + "$ref": "#/definitions/diagnosticSettingFullType" + }, + "nullable": true, "metadata": { "description": "Optional. The diagnostic settings of the service." } }, "managedIdentities": { - "$ref": "#/definitions/managedIdentitiesType", + "$ref": "#/definitions/managedIdentityAllType", + "nullable": true, "metadata": { "description": "Optional. The managed identity definition for this resource." } }, "lock": { "$ref": "#/definitions/lockType", + "nullable": true, "metadata": { "description": "Optional. The lock settings of the service." } }, "roleAssignments": { - "$ref": "#/definitions/roleAssignmentType", + "type": "array", + "items": { + "$ref": "#/definitions/roleAssignmentType" + }, + "nullable": true, "metadata": { "description": "Optional. Array of role assignments to create." } @@ -5257,6 +9325,13 @@ } }, "variables": { + "copy": [ + { + "name": "formattedRoleAssignments", + "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]", + "input": "[union(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')], createObject('roleDefinitionId', coalesce(tryGet(variables('builtInRoleNames'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName), if(contains(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName)))))]" + } + ], "formattedUserAssignedIdentities": "[reduce(map(coalesce(tryGet(parameters('managedIdentities'), 'userAssignedResourceIds'), createArray()), lambda('id', createObject(format('{0}', lambdaVariables('id')), createObject()))), createObject(), lambda('cur', 'next', union(lambdaVariables('cur'), lambdaVariables('next'))))]", "identity": "[if(not(empty(parameters('managedIdentities'))), createObject('type', if(coalesce(tryGet(parameters('managedIdentities'), 'systemAssigned'), false()), if(not(empty(coalesce(tryGet(parameters('managedIdentities'), 'userAssignedResourceIds'), createObject()))), 'SystemAssigned, UserAssigned', 'SystemAssigned'), if(not(empty(coalesce(tryGet(parameters('managedIdentities'), 'userAssignedResourceIds'), createObject()))), 'UserAssigned', 'None')), 'userAssignedIdentities', if(not(empty(variables('formattedUserAssignedIdentities'))), variables('formattedUserAssignedIdentities'), null())), null())]", "builtInRoleNames": { @@ -5267,7 +9342,7 @@ "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", - "Role Based Access Control Administrator (Preview)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168')]", + "Role Based Access Control Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168')]", "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]" } }, @@ -5284,7 +9359,7 @@ "avmTelemetry": { "condition": "[parameters('enableTelemetry')]", "type": "Microsoft.Resources/deployments", - "apiVersion": "2023-07-01", + "apiVersion": "2024-03-01", "name": "[format('46d3xbcp.res.automation-automationaccount.{0}.{1}', replace('-..--..-', '.', '-'), substring(uniqueString(deployment().name, parameters('location')), 0, 4))]", "properties": { "mode": "Incremental", @@ -5397,30 +9472,33 @@ "automationAccount_roleAssignments": { "copy": { "name": "automationAccount_roleAssignments", - "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]" + "count": "[length(coalesce(variables('formattedRoleAssignments'), createArray()))]" }, "type": "Microsoft.Authorization/roleAssignments", "apiVersion": "2022-04-01", "scope": "[format('Microsoft.Automation/automationAccounts/{0}', parameters('name'))]", - "name": "[guid(resourceId('Microsoft.Automation/automationAccounts', parameters('name')), coalesce(parameters('roleAssignments'), createArray())[copyIndex()].principalId, coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName)]", + "name": "[coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'name'), guid(resourceId('Microsoft.Automation/automationAccounts', parameters('name')), coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId, coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId))]", "properties": { - "roleDefinitionId": "[if(contains(variables('builtInRoleNames'), coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName), variables('builtInRoleNames')[coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName], if(contains(coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/'), coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName)))]", - "principalId": "[coalesce(parameters('roleAssignments'), createArray())[copyIndex()].principalId]", - "description": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'description')]", - "principalType": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'principalType')]", - "condition": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'condition')]", - "conditionVersion": "[if(not(empty(tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'condition'))), coalesce(tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'conditionVersion'), '2.0'), null())]", - "delegatedManagedIdentityResourceId": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'delegatedManagedIdentityResourceId')]" + "roleDefinitionId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId]", + "principalId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId]", + "description": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'description')]", + "principalType": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'principalType')]", + "condition": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition')]", + "conditionVersion": "[if(not(empty(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition'))), coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'conditionVersion'), '2.0'), null())]", + "delegatedManagedIdentityResourceId": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'delegatedManagedIdentityResourceId')]" }, "dependsOn": [ "automationAccount" ] }, "automationAccount_credentials": { - "condition": "[not(empty(parameters('credentials')))]", + "copy": { + "name": "automationAccount_credentials", + "count": "[length(coalesce(parameters('credentials'), createArray()))]" + }, "type": "Microsoft.Resources/deployments", "apiVersion": "2022-09-01", - "name": "[format('{0}-AutomationAccount-Credentials', uniqueString(deployment().name, parameters('location')))]", + "name": "[format('{0}-AutomationAccount-Credential-{1}', uniqueString(deployment().name, parameters('location')), copyIndex())]", "properties": { "expressionEvaluationOptions": { "scope": "inner" @@ -5430,8 +9508,17 @@ "automationAccountName": { "value": "[parameters('name')]" }, - "credentials": { - "value": "[parameters('credentials')]" + "name": { + "value": "[coalesce(parameters('credentials'), createArray())[copyIndex()].name]" + }, + "password": { + "value": "[coalesce(parameters('credentials'), createArray())[copyIndex()].password]" + }, + "userName": { + "value": "[coalesce(parameters('credentials'), createArray())[copyIndex()].userName]" + }, + "description": { + "value": "[tryGet(coalesce(parameters('credentials'), createArray())[copyIndex()], 'description')]" } }, "template": { @@ -5442,49 +9529,10 @@ "_generator": { "name": "bicep", "version": "0.34.44.8038", - "templateHash": "3658522857864678576" + "templateHash": "16031055399857988118" }, "name": "Automation Account Credential", - "description": "This module deploys Azure Automation Account Credential.", - "owner": "Azure/module-maintainers" - }, - "definitions": { - "credentialType": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string", - "metadata": { - "description": "Required. Name of the Automation Account credential." - } - }, - "userName": { - "type": "string", - "metadata": { - "description": "Required. The user name associated to the credential." - } - }, - "password": { - "type": "securestring", - "metadata": { - "description": "Required. Password of the credential." - } - }, - "description": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. Description of the credential." - } - } - } - }, - "metadata": { - "__bicep_export!": true - } - } + "description": "This module deploys Azure Automation Account Credential." }, "parameters": { "automationAccountName": { @@ -5493,10 +9541,29 @@ "description": "Conditional. The name of the parent Automation Account. Required if the template is used in a standalone deployment." } }, - "credentials": { - "$ref": "#/definitions/credentialType", + "name": { + "type": "string", + "metadata": { + "description": "Required. Name of the Automation Account credential." + } + }, + "userName": { + "type": "string", + "metadata": { + "description": "Required. The user name associated to the credential." + } + }, + "password": { + "type": "securestring", + "metadata": { + "description": "Required. Password of the credential." + } + }, + "description": { + "type": "string", + "nullable": true, "metadata": { - "description": "Required. The credential definition." + "description": "Optional. Description of the credential." } } }, @@ -5507,41 +9574,31 @@ "apiVersion": "2022-08-08", "name": "[parameters('automationAccountName')]" }, - "automationAccount_credential": { - "copy": { - "name": "automationAccount_credential", - "count": "[length(parameters('credentials'))]" - }, + "credential": { "type": "Microsoft.Automation/automationAccounts/credentials", "apiVersion": "2023-11-01", - "name": "[format('{0}/{1}', parameters('automationAccountName'), parameters('credentials')[copyIndex()].name)]", + "name": "[format('{0}/{1}', parameters('automationAccountName'), parameters('name'))]", "properties": { - "password": "[parameters('credentials')[copyIndex()].password]", - "userName": "[parameters('credentials')[copyIndex()].userName]", - "description": "[coalesce(tryGet(parameters('credentials')[copyIndex()], 'description'), '')]" + "password": "[parameters('password')]", + "userName": "[parameters('userName')]", + "description": "[coalesce(parameters('description'), '')]" } } }, "outputs": { "resourceId": { - "type": "array", + "type": "string", "metadata": { - "description": "The resource IDs of the credentials associated to the automation account." + "description": "The resource Id of the credential associated to the automation account." }, - "copy": { - "count": "[length(range(0, length(parameters('credentials'))))]", - "input": "[resourceId('Microsoft.Automation/automationAccounts/credentials', parameters('automationAccountName'), parameters('credentials')[range(0, length(parameters('credentials')))[copyIndex()]].name)]" - } + "value": "[resourceId('Microsoft.Automation/automationAccounts/credentials', parameters('automationAccountName'), parameters('name'))]" }, "name": { - "type": "array", + "type": "string", "metadata": { - "description": "The names of the credentials associated to the automation account." + "description": "The name of the credential associated to the automation account." }, - "copy": { - "count": "[length(range(0, length(parameters('credentials'))))]", - "input": "[parameters('credentials')[range(0, length(parameters('credentials')))[copyIndex()]].name]" - } + "value": "[parameters('name')]" }, "resourceGroupName": { "type": "string", @@ -5598,11 +9655,10 @@ "_generator": { "name": "bicep", "version": "0.34.44.8038", - "templateHash": "8188890335834665181" + "templateHash": "12845441251190142050" }, "name": "Automation Account Modules", - "description": "This module deploys an Azure Automation Account Module.", - "owner": "Azure/module-maintainers" + "description": "This module deploys an Azure Automation Account Module." }, "parameters": { "name": { @@ -5722,13 +9778,27 @@ "automationAccountName": { "value": "[parameters('name')]" }, - "advancedSchedule": "[if(contains(parameters('schedules')[copyIndex()], 'advancedSchedule'), createObject('value', parameters('schedules')[copyIndex()].advancedSchedule), createObject('value', null()))]", - "description": "[if(contains(parameters('schedules')[copyIndex()], 'description'), createObject('value', parameters('schedules')[copyIndex()].description), createObject('value', ''))]", - "expiryTime": "[if(contains(parameters('schedules')[copyIndex()], 'expiryTime'), createObject('value', parameters('schedules')[copyIndex()].expiryTime), createObject('value', ''))]", - "frequency": "[if(contains(parameters('schedules')[copyIndex()], 'frequency'), createObject('value', parameters('schedules')[copyIndex()].frequency), createObject('value', 'OneTime'))]", - "interval": "[if(contains(parameters('schedules')[copyIndex()], 'interval'), createObject('value', parameters('schedules')[copyIndex()].interval), createObject('value', 0))]", - "startTime": "[if(contains(parameters('schedules')[copyIndex()], 'startTime'), createObject('value', parameters('schedules')[copyIndex()].startTime), createObject('value', ''))]", - "timeZone": "[if(contains(parameters('schedules')[copyIndex()], 'timeZone'), createObject('value', parameters('schedules')[copyIndex()].timeZone), createObject('value', ''))]" + "advancedSchedule": { + "value": "[tryGet(parameters('schedules')[copyIndex()], 'advancedSchedule')]" + }, + "description": { + "value": "[tryGet(parameters('schedules')[copyIndex()], 'description')]" + }, + "expiryTime": { + "value": "[tryGet(parameters('schedules')[copyIndex()], 'expiryTime')]" + }, + "frequency": { + "value": "[tryGet(parameters('schedules')[copyIndex()], 'frequency')]" + }, + "interval": { + "value": "[tryGet(parameters('schedules')[copyIndex()], 'interval')]" + }, + "startTime": { + "value": "[tryGet(parameters('schedules')[copyIndex()], 'startTime')]" + }, + "timeZone": { + "value": "[tryGet(parameters('schedules')[copyIndex()], 'timeZone')]" + } }, "template": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", @@ -5737,11 +9807,10 @@ "_generator": { "name": "bicep", "version": "0.34.44.8038", - "templateHash": "18138414380263278543" + "templateHash": "16852093821055316937" }, "name": "Automation Account Schedules", - "description": "This module deploys an Azure Automation Account Schedule.", - "owner": "Azure/module-maintainers" + "description": "This module deploys an Azure Automation Account Schedule." }, "parameters": { "name": { @@ -5892,9 +9961,15 @@ "type": { "value": "[parameters('runbooks')[copyIndex()].type]" }, - "description": "[if(contains(parameters('runbooks')[copyIndex()], 'description'), createObject('value', parameters('runbooks')[copyIndex()].description), createObject('value', ''))]", - "uri": "[if(contains(parameters('runbooks')[copyIndex()], 'uri'), createObject('value', parameters('runbooks')[copyIndex()].uri), createObject('value', ''))]", - "version": "[if(contains(parameters('runbooks')[copyIndex()], 'version'), createObject('value', parameters('runbooks')[copyIndex()].version), createObject('value', ''))]", + "description": { + "value": "[tryGet(parameters('runbooks')[copyIndex()], 'description')]" + }, + "uri": { + "value": "[tryGet(parameters('runbooks')[copyIndex()], 'uri')]" + }, + "version": { + "value": "[tryGet(parameters('runbooks')[copyIndex()], 'version')]" + }, "sasTokenValidityLength": { "value": "[tryGet(parameters('runbooks')[copyIndex()], 'sasTokenValidityLength')]" }, @@ -5916,11 +9991,10 @@ "_generator": { "name": "bicep", "version": "0.34.44.8038", - "templateHash": "15224946706292447671" + "templateHash": "4395796056327018779" }, "name": "Automation Account Runbooks", - "description": "This module deploys an Azure Automation Account Runbook.", - "owner": "Azure/module-maintainers" + "description": "This module deploys an Azure Automation Account Runbook." }, "parameters": { "name": { @@ -6106,8 +10180,12 @@ "scheduleName": { "value": "[parameters('jobSchedules')[copyIndex()].scheduleName]" }, - "parameters": "[if(contains(parameters('jobSchedules')[copyIndex()], 'parameters'), createObject('value', parameters('jobSchedules')[copyIndex()].parameters), createObject('value', createObject()))]", - "runOn": "[if(contains(parameters('jobSchedules')[copyIndex()], 'runOn'), createObject('value', parameters('jobSchedules')[copyIndex()].runOn), createObject('value', ''))]" + "parameters": { + "value": "[tryGet(parameters('jobSchedules')[copyIndex()], 'parameters')]" + }, + "runOn": { + "value": "[tryGet(parameters('jobSchedules')[copyIndex()], 'runOn')]" + } }, "template": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", @@ -6116,11 +10194,10 @@ "_generator": { "name": "bicep", "version": "0.34.44.8038", - "templateHash": "5403126960771484558" + "templateHash": "5190210010905570418" }, "name": "Automation Account Job Schedules", - "description": "This module deploys an Azure Automation Account Job Schedule.", - "owner": "Azure/module-maintainers" + "description": "This module deploys an Azure Automation Account Job Schedule." }, "parameters": { "name": { @@ -6231,11 +10308,15 @@ "name": { "value": "[parameters('variables')[copyIndex()].name]" }, - "description": "[if(contains(parameters('variables')[copyIndex()], 'description'), createObject('value', parameters('variables')[copyIndex()].description), createObject('value', ''))]", + "description": { + "value": "[tryGet(parameters('variables')[copyIndex()], 'description')]" + }, "value": { "value": "[parameters('variables')[copyIndex()].value]" }, - "isEncrypted": "[if(contains(parameters('variables')[copyIndex()], 'isEncrypted'), createObject('value', parameters('variables')[copyIndex()].isEncrypted), createObject('value', true()))]" + "isEncrypted": { + "value": "[tryGet(parameters('variables')[copyIndex()], 'isEncrypted')]" + } }, "template": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", @@ -6244,11 +10325,10 @@ "_generator": { "name": "bicep", "version": "0.34.44.8038", - "templateHash": "8098174796941643834" + "templateHash": "17675848897504900269" }, "name": "Automation Account Variables", - "description": "This module deploys an Azure Automation Account Variable.", - "owner": "Azure/module-maintainers" + "description": "This module deploys an Azure Automation Account Variable." }, "parameters": { "automationAccountName": { @@ -6359,11 +10439,10 @@ "_generator": { "name": "bicep", "version": "0.34.44.8038", - "templateHash": "3438664015858123192" + "templateHash": "17309250222261416192" }, "name": "Log Analytics Workspace Linked Services", - "description": "This module deploys a Log Analytics Workspace Linked Service.", - "owner": "Azure/module-maintainers" + "description": "This module deploys a Log Analytics Workspace Linked Service." }, "parameters": { "logAnalyticsWorkspaceName": { @@ -6450,7 +10529,7 @@ "automationAccount_solutions": { "copy": { "name": "automationAccount_solutions", - "count": "[length(parameters('gallerySolutions'))]" + "count": "[length(coalesce(parameters('gallerySolutions'), createArray()))]" }, "condition": "[not(empty(parameters('linkedWorkspaceResourceId')))]", "type": "Microsoft.Resources/deployments", @@ -6465,7 +10544,7 @@ "mode": "Incremental", "parameters": { "name": { - "value": "[parameters('gallerySolutions')[copyIndex()].name]" + "value": "[coalesce(parameters('gallerySolutions'), createArray())[copyIndex()].name]" }, "location": { "value": "[parameters('location')]" @@ -6473,30 +10552,68 @@ "logAnalyticsWorkspaceName": { "value": "[last(split(parameters('linkedWorkspaceResourceId'), '/'))]" }, - "product": "[if(contains(parameters('gallerySolutions')[copyIndex()], 'product'), createObject('value', parameters('gallerySolutions')[copyIndex()].product), createObject('value', 'OMSGallery'))]", - "publisher": "[if(contains(parameters('gallerySolutions')[copyIndex()], 'publisher'), createObject('value', parameters('gallerySolutions')[copyIndex()].publisher), createObject('value', 'Microsoft'))]", + "plan": { + "value": "[coalesce(parameters('gallerySolutions'), createArray())[copyIndex()].plan]" + }, "enableTelemetry": { "value": "[parameters('enableTelemetry')]" } }, "template": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", "contentVersion": "1.0.0.0", "metadata": { "_generator": { "name": "bicep", - "version": "0.23.1.45101", - "templateHash": "18444780972506374592" + "version": "0.30.23.60470", + "templateHash": "1867653058254938383" }, "name": "Operations Management Solutions", "description": "This module deploys an Operations Management Solution.", "owner": "Azure/module-maintainers" }, + "definitions": { + "solutionPlanType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. Name of the solution to be created.\nFor solutions authored by Microsoft, the name must be in the pattern: `SolutionType(WorkspaceName)`, for example: `AntiMalware(contoso-Logs)`.\nFor solutions authored by third parties, it can be anything.\nThe solution type is case-sensitive.\nIf not provided, the value of the `name` parameter will be used." + } + }, + "product": { + "type": "string", + "metadata": { + "description": "Required. The product name of the deployed solution.\nFor Microsoft published gallery solution it should be `OMSGallery/{solutionType}`, for example `OMSGallery/AntiMalware`.\nFor a third party solution, it can be anything.\nThis is case sensitive." + } + }, + "publisher": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The publisher name of the deployed solution. For Microsoft published gallery solution, it is `Microsoft`, which is the default value." + } + } + }, + "metadata": { + "__bicep_export!": true + } + } + }, "parameters": { "name": { "type": "string", "metadata": { - "description": "Required. Name of the solution. For Microsoft published gallery solution the target solution resource name will be composed as `{name}({logAnalyticsWorkspaceName})`." + "description": "Required. Name of the solution.\nFor solutions authored by Microsoft, the name must be in the pattern: `SolutionType(WorkspaceName)`, for example: `AntiMalware(contoso-Logs)`.\nFor solutions authored by third parties, the name should be in the pattern: `SolutionType[WorkspaceName]`, for example `MySolution[contoso-Logs]`.\nThe solution type is case-sensitive." + } + }, + "plan": { + "$ref": "#/definitions/solutionPlanType", + "metadata": { + "description": "Required. Plan for solution object supported by the OperationsManagement resource provider." } }, "logAnalyticsWorkspaceName": { @@ -6512,20 +10629,6 @@ "description": "Optional. Location for all resources." } }, - "product": { - "type": "string", - "defaultValue": "OMSGallery", - "metadata": { - "description": "Optional. The product of the deployed solution. For Microsoft published gallery solution it should be `OMSGallery` and the target solution resource product will be composed as `OMSGallery/{name}`. For third party solution, it can be anything. This is case sensitive." - } - }, - "publisher": { - "type": "string", - "defaultValue": "Microsoft", - "metadata": { - "description": "Optional. The publisher name of the deployed solution. For Microsoft published gallery solution, it is `Microsoft`." - } - }, "enableTelemetry": { "type": "bool", "defaultValue": true, @@ -6534,16 +10637,12 @@ } } }, - "variables": { - "solutionName": "[if(equals(parameters('publisher'), 'Microsoft'), format('{0}({1})', parameters('name'), parameters('logAnalyticsWorkspaceName')), parameters('name'))]", - "solutionProduct": "[if(equals(parameters('publisher'), 'Microsoft'), format('OMSGallery/{0}', parameters('name')), parameters('product'))]" - }, - "resources": [ - { + "resources": { + "avmTelemetry": { "condition": "[parameters('enableTelemetry')]", "type": "Microsoft.Resources/deployments", - "apiVersion": "2023-07-01", - "name": "[format('46d3xbcp.res.operationsmanagement-solution.{0}.{1}', replace('0.1.0', '.', '-'), substring(uniqueString(deployment().name, parameters('location')), 0, 4))]", + "apiVersion": "2024-03-01", + "name": "[format('46d3xbcp.res.operationsmanagement-solution.{0}.{1}', replace('0.3.0', '.', '-'), substring(uniqueString(deployment().name, parameters('location')), 0, 4))]", "properties": { "mode": "Incremental", "template": { @@ -6559,36 +10658,45 @@ } } }, - { + "logAnalyticsWorkspace": { + "existing": true, + "type": "Microsoft.OperationalInsights/workspaces", + "apiVersion": "2021-06-01", + "name": "[parameters('logAnalyticsWorkspaceName')]" + }, + "solution": { "type": "Microsoft.OperationsManagement/solutions", "apiVersion": "2015-11-01-preview", - "name": "[variables('solutionName')]", + "name": "[parameters('name')]", "location": "[parameters('location')]", "properties": { "workspaceResourceId": "[resourceId('Microsoft.OperationalInsights/workspaces', parameters('logAnalyticsWorkspaceName'))]" }, "plan": { - "name": "[variables('solutionName')]", + "name": "[coalesce(tryGet(parameters('plan'), 'name'), parameters('name'))]", "promotionCode": "", - "product": "[variables('solutionProduct')]", - "publisher": "[parameters('publisher')]" - } + "product": "[parameters('plan').product]", + "publisher": "[coalesce(tryGet(parameters('plan'), 'publisher'), 'Microsoft')]" + }, + "dependsOn": [ + "logAnalyticsWorkspace" + ] } - ], + }, "outputs": { "name": { "type": "string", "metadata": { "description": "The name of the deployed solution." }, - "value": "[variables('solutionName')]" + "value": "[parameters('name')]" }, "resourceId": { "type": "string", "metadata": { "description": "The resource ID of the deployed solution." }, - "value": "[resourceId('Microsoft.OperationsManagement/solutions', variables('solutionName'))]" + "value": "[resourceId('Microsoft.OperationsManagement/solutions', parameters('name'))]" }, "resourceGroupName": { "type": "string", @@ -6602,7 +10710,7 @@ "metadata": { "description": "The location the resource was deployed into." }, - "value": "[reference(resourceId('Microsoft.OperationsManagement/solutions', variables('solutionName')), '2015-11-01-preview', 'full').location]" + "value": "[reference('solution', '2015-11-01-preview', 'full').location]" } } } @@ -6640,46 +10748,100 @@ "rebootSetting": { "value": "[parameters('softwareUpdateConfigurations')[copyIndex()].rebootSetting]" }, - "azureVirtualMachines": "[if(contains(parameters('softwareUpdateConfigurations')[copyIndex()], 'azureVirtualMachines'), createObject('value', parameters('softwareUpdateConfigurations')[copyIndex()].azureVirtualMachines), createObject('value', createArray()))]", - "excludeUpdates": "[if(contains(parameters('softwareUpdateConfigurations')[copyIndex()], 'excludeUpdates'), createObject('value', parameters('softwareUpdateConfigurations')[copyIndex()].excludeUpdates), createObject('value', createArray()))]", - "expiryTime": "[if(contains(parameters('softwareUpdateConfigurations')[copyIndex()], 'expiryTime'), createObject('value', parameters('softwareUpdateConfigurations')[copyIndex()].expiryTime), createObject('value', ''))]", - "expiryTimeOffsetMinutes": "[if(contains(parameters('softwareUpdateConfigurations')[copyIndex()], 'expiryTimeOffsetMinutes'), createObject('value', parameters('softwareUpdateConfigurations')[copyIndex()].expiryTimeOffsetMinute), createObject('value', 0))]", - "includeUpdates": "[if(contains(parameters('softwareUpdateConfigurations')[copyIndex()], 'includeUpdates'), createObject('value', parameters('softwareUpdateConfigurations')[copyIndex()].includeUpdates), createObject('value', createArray()))]", - "interval": "[if(contains(parameters('softwareUpdateConfigurations')[copyIndex()], 'interval'), createObject('value', parameters('softwareUpdateConfigurations')[copyIndex()].interval), createObject('value', 1))]", - "isEnabled": "[if(contains(parameters('softwareUpdateConfigurations')[copyIndex()], 'isEnabled'), createObject('value', parameters('softwareUpdateConfigurations')[copyIndex()].isEnabled), createObject('value', true()))]", - "maintenanceWindow": "[if(contains(parameters('softwareUpdateConfigurations')[copyIndex()], 'maintenanceWindow'), createObject('value', parameters('softwareUpdateConfigurations')[copyIndex()].maintenanceWindow), createObject('value', 'PT2H'))]", - "monthDays": "[if(contains(parameters('softwareUpdateConfigurations')[copyIndex()], 'monthDays'), createObject('value', parameters('softwareUpdateConfigurations')[copyIndex()].monthDays), createObject('value', createArray()))]", - "monthlyOccurrences": "[if(contains(parameters('softwareUpdateConfigurations')[copyIndex()], 'monthlyOccurrences'), createObject('value', parameters('softwareUpdateConfigurations')[copyIndex()].monthlyOccurrences), createObject('value', createArray()))]", - "nextRun": "[if(contains(parameters('softwareUpdateConfigurations')[copyIndex()], 'nextRun'), createObject('value', parameters('softwareUpdateConfigurations')[copyIndex()].nextRun), createObject('value', ''))]", - "nextRunOffsetMinutes": "[if(contains(parameters('softwareUpdateConfigurations')[copyIndex()], 'nextRunOffsetMinutes'), createObject('value', parameters('softwareUpdateConfigurations')[copyIndex()].nextRunOffsetMinutes), createObject('value', 0))]", - "nonAzureComputerNames": "[if(contains(parameters('softwareUpdateConfigurations')[copyIndex()], 'nonAzureComputerNames'), createObject('value', parameters('softwareUpdateConfigurations')[copyIndex()].nonAzureComputerNames), createObject('value', createArray()))]", - "nonAzureQueries": "[if(contains(parameters('softwareUpdateConfigurations')[copyIndex()], 'nonAzureQueries'), createObject('value', parameters('softwareUpdateConfigurations')[copyIndex()].nonAzureQueries), createObject('value', createArray()))]", - "postTaskParameters": "[if(contains(parameters('softwareUpdateConfigurations')[copyIndex()], 'postTaskParameters'), createObject('value', parameters('softwareUpdateConfigurations')[copyIndex()].postTaskParameters), createObject('value', createObject()))]", - "postTaskSource": "[if(contains(parameters('softwareUpdateConfigurations')[copyIndex()], 'postTaskSource'), createObject('value', parameters('softwareUpdateConfigurations')[copyIndex()].postTaskSource), createObject('value', ''))]", - "preTaskParameters": "[if(contains(parameters('softwareUpdateConfigurations')[copyIndex()], 'preTaskParameters'), createObject('value', parameters('softwareUpdateConfigurations')[copyIndex()].preTaskParameters), createObject('value', createObject()))]", - "preTaskSource": "[if(contains(parameters('softwareUpdateConfigurations')[copyIndex()], 'preTaskSource'), createObject('value', parameters('softwareUpdateConfigurations')[copyIndex()].preTaskSource), createObject('value', ''))]", - "scheduleDescription": "[if(contains(parameters('softwareUpdateConfigurations')[copyIndex()], 'scheduleDescription'), createObject('value', parameters('softwareUpdateConfigurations')[copyIndex()].scheduleDescription), createObject('value', ''))]", - "scopeByLocations": "[if(contains(parameters('softwareUpdateConfigurations')[copyIndex()], 'scopeByLocations'), createObject('value', parameters('softwareUpdateConfigurations')[copyIndex()].scopeByLocations), createObject('value', createArray()))]", - "scopeByResources": "[if(contains(parameters('softwareUpdateConfigurations')[copyIndex()], 'scopeByResources'), createObject('value', parameters('softwareUpdateConfigurations')[copyIndex()].scopeByResources), createObject('value', createArray(subscription().id)))]", - "scopeByTags": "[if(contains(parameters('softwareUpdateConfigurations')[copyIndex()], 'scopeByTags'), createObject('value', parameters('softwareUpdateConfigurations')[copyIndex()].scopeByTags), createObject('value', createObject()))]", - "scopeByTagsOperation": "[if(contains(parameters('softwareUpdateConfigurations')[copyIndex()], 'scopeByTagsOperation'), createObject('value', parameters('softwareUpdateConfigurations')[copyIndex()].scopeByTagsOperation), createObject('value', 'All'))]", - "startTime": "[if(contains(parameters('softwareUpdateConfigurations')[copyIndex()], 'startTime'), createObject('value', parameters('softwareUpdateConfigurations')[copyIndex()].startTime), createObject('value', ''))]", - "timeZone": "[if(contains(parameters('softwareUpdateConfigurations')[copyIndex()], 'timeZone'), createObject('value', parameters('softwareUpdateConfigurations')[copyIndex()].timeZone), createObject('value', 'UTC'))]", - "updateClassifications": "[if(contains(parameters('softwareUpdateConfigurations')[copyIndex()], 'updateClassifications'), createObject('value', parameters('softwareUpdateConfigurations')[copyIndex()].updateClassifications), createObject('value', createArray('Critical', 'Security')))]", - "weekDays": "[if(contains(parameters('softwareUpdateConfigurations')[copyIndex()], 'weekDays'), createObject('value', parameters('softwareUpdateConfigurations')[copyIndex()].weekDays), createObject('value', createArray()))]" + "azureVirtualMachines": { + "value": "[tryGet(parameters('softwareUpdateConfigurations')[copyIndex()], 'azureVirtualMachines')]" + }, + "excludeUpdates": { + "value": "[tryGet(parameters('softwareUpdateConfigurations')[copyIndex()], 'excludeUpdates')]" + }, + "expiryTime": { + "value": "[tryGet(parameters('softwareUpdateConfigurations')[copyIndex()], 'expiryTime')]" + }, + "expiryTimeOffsetMinutes": { + "value": "[tryGet(parameters('softwareUpdateConfigurations')[copyIndex()], 'expiryTimeOffsetMinute')]" + }, + "includeUpdates": { + "value": "[tryGet(parameters('softwareUpdateConfigurations')[copyIndex()], 'includeUpdates')]" + }, + "interval": { + "value": "[tryGet(parameters('softwareUpdateConfigurations')[copyIndex()], 'interval')]" + }, + "isEnabled": { + "value": "[tryGet(parameters('softwareUpdateConfigurations')[copyIndex()], 'isEnabled')]" + }, + "maintenanceWindow": { + "value": "[tryGet(parameters('softwareUpdateConfigurations')[copyIndex()], 'maintenanceWindow')]" + }, + "monthDays": { + "value": "[tryGet(parameters('softwareUpdateConfigurations')[copyIndex()], 'monthDays')]" + }, + "monthlyOccurrences": { + "value": "[tryGet(parameters('softwareUpdateConfigurations')[copyIndex()], 'monthlyOccurrences')]" + }, + "nextRun": { + "value": "[tryGet(parameters('softwareUpdateConfigurations')[copyIndex()], 'nextRun')]" + }, + "nextRunOffsetMinutes": { + "value": "[tryGet(parameters('softwareUpdateConfigurations')[copyIndex()], 'nextRunOffsetMinutes')]" + }, + "nonAzureComputerNames": { + "value": "[tryGet(parameters('softwareUpdateConfigurations')[copyIndex()], 'nonAzureComputerNames')]" + }, + "nonAzureQueries": { + "value": "[tryGet(parameters('softwareUpdateConfigurations')[copyIndex()], 'nonAzureQueries')]" + }, + "postTaskParameters": { + "value": "[tryGet(parameters('softwareUpdateConfigurations')[copyIndex()], 'postTaskParameters')]" + }, + "postTaskSource": { + "value": "[tryGet(parameters('softwareUpdateConfigurations')[copyIndex()], 'postTaskSource')]" + }, + "preTaskParameters": { + "value": "[tryGet(parameters('softwareUpdateConfigurations')[copyIndex()], 'preTaskParameters')]" + }, + "preTaskSource": { + "value": "[tryGet(parameters('softwareUpdateConfigurations')[copyIndex()], 'preTaskSource')]" + }, + "scheduleDescription": { + "value": "[tryGet(parameters('softwareUpdateConfigurations')[copyIndex()], 'scheduleDescription')]" + }, + "scopeByLocations": { + "value": "[tryGet(parameters('softwareUpdateConfigurations')[copyIndex()], 'scopeByLocations')]" + }, + "scopeByResources": { + "value": "[tryGet(parameters('softwareUpdateConfigurations')[copyIndex()], 'scopeByResources')]" + }, + "scopeByTags": { + "value": "[tryGet(parameters('softwareUpdateConfigurations')[copyIndex()], 'scopeByTags')]" + }, + "scopeByTagsOperation": { + "value": "[tryGet(parameters('softwareUpdateConfigurations')[copyIndex()], 'scopeByTagsOperation')]" + }, + "startTime": { + "value": "[tryGet(parameters('softwareUpdateConfigurations')[copyIndex()], 'startTime')]" + }, + "timeZone": { + "value": "[tryGet(parameters('softwareUpdateConfigurations')[copyIndex()], 'timeZone')]" + }, + "updateClassifications": { + "value": "[tryGet(parameters('softwareUpdateConfigurations')[copyIndex()], 'updateClassifications')]" + }, + "weekDays": { + "value": "[tryGet(parameters('softwareUpdateConfigurations')[copyIndex()], 'weekDays')]" + } }, "template": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", "contentVersion": "1.0.0.0", "metadata": { "_generator": { "name": "bicep", "version": "0.34.44.8038", - "templateHash": "4244185494071451980" + "templateHash": "9164057096760743873" }, "name": "Automation Account Software Update Configurations", - "description": "This module deploys an Azure Automation Account Software Update Configuration.", - "owner": "Azure/module-maintainers" + "description": "This module deploys an Azure Automation Account Software Update Configuration." }, "parameters": { "name": { @@ -6807,28 +10969,28 @@ }, "preTaskParameters": { "type": "object", - "defaultValue": {}, + "nullable": true, "metadata": { "description": "Optional. Parameters provided to the task running before the deployment schedule." } }, "preTaskSource": { "type": "string", - "defaultValue": "", + "nullable": true, "metadata": { "description": "Optional. The source of the task running before the deployment schedule." } }, "postTaskParameters": { "type": "object", - "defaultValue": {}, + "nullable": true, "metadata": { "description": "Optional. Parameters provided to the task running after the deployment schedule." } }, "postTaskSource": { "type": "string", - "defaultValue": "", + "nullable": true, "metadata": { "description": "Optional. The source of the task running after the deployment schedule." } @@ -6878,7 +11040,10 @@ }, "weekDays": { "type": "array", - "defaultValue": [], + "items": { + "type": "string" + }, + "nullable": true, "allowedValues": [ "Monday", "Tuesday", @@ -6894,7 +11059,10 @@ }, "monthDays": { "type": "array", - "defaultValue": [], + "items": { + "type": "int" + }, + "nullable": true, "allowedValues": [ 1, 2, @@ -6934,7 +11102,7 @@ }, "monthlyOccurrences": { "type": "array", - "defaultValue": [], + "nullable": true, "metadata": { "description": "Optional. Can be used with frequency 'Month'. Provides the pattern/cadence for running the deployment schedule in a month. Takes objects formed like this {occurance(int),day(string)}. Day is the name of the day to run the deployment schedule, the occurance specifies which occurance of that day to run the deployment schedule." } @@ -6992,8 +11160,14 @@ "variables": { "updateClassificationsVar": "[replace(replace(replace(replace(string(parameters('updateClassifications')), ',', ', '), '[', ''), ']', ''), '\"', '')]" }, - "resources": [ - { + "resources": { + "automationAccount": { + "existing": true, + "type": "Microsoft.Automation/automationAccounts", + "apiVersion": "2022-08-08", + "name": "[parameters('automationAccountName')]" + }, + "softwareUpdateConfiguration": { "type": "Microsoft.Automation/automationAccounts/softwareUpdateConfigurations", "apiVersion": "2019-06-01", "name": "[format('{0}/{1}', parameters('automationAccountName'), parameters('name'))]", @@ -7021,12 +11195,12 @@ }, "tasks": { "preTask": { - "parameters": "[if(empty(parameters('preTaskParameters')), null(), parameters('preTaskParameters'))]", - "source": "[if(empty(parameters('preTaskSource')), null(), parameters('preTaskSource'))]" + "parameters": "[parameters('preTaskParameters')]", + "source": "[parameters('preTaskSource')]" }, "postTask": { - "parameters": "[if(empty(parameters('postTaskParameters')), null(), parameters('postTaskParameters'))]", - "source": "[if(empty(parameters('postTaskSource')), null(), parameters('postTaskSource'))]" + "parameters": "[parameters('postTaskParameters')]", + "source": "[parameters('postTaskSource')]" } }, "scheduleInfo": { @@ -7035,9 +11209,9 @@ "isEnabled": "[parameters('isEnabled')]", "timeZone": "[parameters('timeZone')]", "advancedSchedule": { - "weekDays": "[if(empty(parameters('weekDays')), null(), parameters('weekDays'))]", - "monthDays": "[if(empty(parameters('monthDays')), null(), parameters('monthDays'))]", - "monthlyOccurrences": "[if(empty(parameters('monthlyOccurrences')), null(), parameters('monthlyOccurrences'))]" + "weekDays": "[parameters('weekDays')]", + "monthDays": "[parameters('monthDays')]", + "monthlyOccurrences": "[parameters('monthlyOccurrences')]" }, "startTime": "[if(empty(parameters('startTime')), dateTimeAdd(parameters('baseTime'), 'PT10M'), parameters('startTime'))]", "expiryTime": "[parameters('expiryTime')]", @@ -7048,7 +11222,7 @@ } } } - ], + }, "outputs": { "name": { "type": "string", @@ -7106,16 +11280,13 @@ "value": "[coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'enableTelemetry'), parameters('enableTelemetry'))]" }, "location": { - "value": "[coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'location'), reference(split(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()].subnetResourceId, '/subnets/')[0], '2024-06-01', 'Full').location)]" + "value": "[coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'location'), reference(split(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()].subnetResourceId, '/subnets/')[0], '2020-06-01', 'Full').location)]" }, "lock": { "value": "[coalesce(tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'lock'), parameters('lock'))]" }, - "privateDnsZoneGroupName": { - "value": "[tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'privateDnsZoneGroupName')]" - }, - "privateDnsZoneResourceIds": { - "value": "[tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'privateDnsZoneResourceIds')]" + "privateDnsZoneGroup": { + "value": "[tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'privateDnsZoneGroup')]" }, "roleAssignments": { "value": "[tryGet(coalesce(parameters('privateEndpoints'), createArray())[copyIndex()], 'roleAssignments')]" @@ -7143,19 +11314,47 @@ "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "4120048060064073955" + "version": "0.29.47.4906", + "templateHash": "1277254088602407590" }, "name": "Private Endpoints", "description": "This module deploys a Private Endpoint.", "owner": "Azure/module-maintainers" }, "definitions": { + "privateDnsZoneGroupType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of the Private DNS Zone Group." + } + }, + "privateDnsZoneGroupConfigs": { + "type": "array", + "items": { + "$ref": "#/definitions/privateDnsZoneGroupConfigType" + }, + "metadata": { + "description": "Required. The private DNS zone groups to associate the private endpoint. A DNS zone group can support up to 5 DNS zones." + } + } + } + }, "roleAssignmentType": { "type": "array", "items": { "type": "object", "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." + } + }, "roleDefinitionIdOrName": { "type": "string", "metadata": { @@ -7259,13 +11458,13 @@ "groupId": { "type": "string", "metadata": { - "description": "Required. The ID of a group obtained from the remote resource that this private endpoint should connect to." + "description": "Required. The ID of a group obtained from the remote resource that this private endpoint should connect to. If used with private link service connection, this property must be defined as empty string." } }, "memberName": { "type": "string", "metadata": { - "description": "Required. The member name of a group obtained from the remote resource that this private endpoint should connect to." + "description": "Required. The member name of a group obtained from the remote resource that this private endpoint should connect to. If used with private link service connection, this property must be defined as empty string." } }, "privateIPAddress": { @@ -7299,8 +11498,11 @@ "properties": { "groupIds": { "type": "array", + "items": { + "type": "string" + }, "metadata": { - "description": "Required. The ID of a group obtained from the remote resource that this private endpoint should connect to." + "description": "Required. The ID of a group obtained from the remote resource that this private endpoint should connect to. If used with private link service connection, this property must be defined as empty string array `[]`." } }, "privateLinkServiceId": { @@ -7340,8 +11542,11 @@ "properties": { "groupIds": { "type": "array", + "items": { + "type": "string" + }, "metadata": { - "description": "Required. The ID of a group obtained from the remote resource that this private endpoint should connect to." + "description": "Required. The ID of a group obtained from the remote resource that this private endpoint should connect to. If used with private link service connection, this property must be defined as empty string array `[]`." } }, "privateLinkServiceId": { @@ -7389,6 +11594,29 @@ } }, "nullable": true + }, + "privateDnsZoneGroupConfigType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of the private DNS zone group config." + } + }, + "privateDnsZoneResourceId": { + "type": "string", + "metadata": { + "description": "Required. The resource id of the private DNS zone." + } + } + }, + "metadata": { + "__bicep_imported_from!": { + "sourceTemplate": "private-dns-zone-group/main.bicep" + } + } } }, "parameters": { @@ -7424,18 +11652,11 @@ "description": "Optional. A list of IP configurations of the private endpoint. This will be used to map to the First Party Service endpoints." } }, - "privateDnsZoneGroupName": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The name of the private DNS zone group to create if `privateDnsZoneResourceIds` were provided." - } - }, - "privateDnsZoneResourceIds": { - "type": "array", + "privateDnsZoneGroup": { + "$ref": "#/definitions/privateDnsZoneGroupType", "nullable": true, "metadata": { - "description": "Optional. The private DNS zone groups to associate the private endpoint. A DNS zone group can support up to 5 DNS zones." + "description": "Optional. The private DNS zone group to configure for the private endpoint." } }, "location": { @@ -7491,6 +11712,13 @@ } }, "variables": { + "copy": [ + { + "name": "formattedRoleAssignments", + "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]", + "input": "[union(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')], createObject('roleDefinitionId', coalesce(tryGet(variables('builtInRoleNames'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName), if(contains(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName)))))]" + } + ], "builtInRoleNames": { "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", "DNS Resolver Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '0f2ebee7-ffd4-4fc0-b3b7-664099fdad5d')]", @@ -7508,8 +11736,8 @@ "avmTelemetry": { "condition": "[parameters('enableTelemetry')]", "type": "Microsoft.Resources/deployments", - "apiVersion": "2023-07-01", - "name": "[format('46d3xbcp.res.network-privateendpoint.{0}.{1}', replace('0.4.1', '.', '-'), substring(uniqueString(deployment().name, parameters('location')), 0, 4))]", + "apiVersion": "2024-03-01", + "name": "[format('46d3xbcp.res.network-privateendpoint.{0}.{1}', replace('0.7.1', '.', '-'), substring(uniqueString(deployment().name, parameters('location')), 0, 4))]", "properties": { "mode": "Incremental", "template": { @@ -7527,7 +11755,7 @@ }, "privateEndpoint": { "type": "Microsoft.Network/privateEndpoints", - "apiVersion": "2023-04-01", + "apiVersion": "2023-11-01", "name": "[parameters('name')]", "location": "[parameters('location')]", "tags": "[parameters('tags')]", @@ -7568,27 +11796,27 @@ "privateEndpoint_roleAssignments": { "copy": { "name": "privateEndpoint_roleAssignments", - "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]" + "count": "[length(coalesce(variables('formattedRoleAssignments'), createArray()))]" }, "type": "Microsoft.Authorization/roleAssignments", "apiVersion": "2022-04-01", "scope": "[format('Microsoft.Network/privateEndpoints/{0}', parameters('name'))]", - "name": "[guid(resourceId('Microsoft.Network/privateEndpoints', parameters('name')), coalesce(parameters('roleAssignments'), createArray())[copyIndex()].principalId, coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName)]", + "name": "[coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'name'), guid(resourceId('Microsoft.Network/privateEndpoints', parameters('name')), coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId, coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId))]", "properties": { - "roleDefinitionId": "[if(contains(variables('builtInRoleNames'), coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName), variables('builtInRoleNames')[coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName], if(contains(coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/'), coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName)))]", - "principalId": "[coalesce(parameters('roleAssignments'), createArray())[copyIndex()].principalId]", - "description": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'description')]", - "principalType": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'principalType')]", - "condition": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'condition')]", - "conditionVersion": "[if(not(empty(tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'condition'))), coalesce(tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'conditionVersion'), '2.0'), null())]", - "delegatedManagedIdentityResourceId": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'delegatedManagedIdentityResourceId')]" + "roleDefinitionId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId]", + "principalId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId]", + "description": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'description')]", + "principalType": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'principalType')]", + "condition": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition')]", + "conditionVersion": "[if(not(empty(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition'))), coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'conditionVersion'), '2.0'), null())]", + "delegatedManagedIdentityResourceId": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'delegatedManagedIdentityResourceId')]" }, "dependsOn": [ "privateEndpoint" ] }, "privateEndpoint_privateDnsZoneGroup": { - "condition": "[not(empty(parameters('privateDnsZoneResourceIds')))]", + "condition": "[not(empty(parameters('privateDnsZoneGroup')))]", "type": "Microsoft.Resources/deployments", "apiVersion": "2022-09-01", "name": "[format('{0}-PrivateEndpoint-PrivateDnsZoneGroup', uniqueString(deployment().name))]", @@ -7599,28 +11827,52 @@ "mode": "Incremental", "parameters": { "name": { - "value": "[coalesce(parameters('privateDnsZoneGroupName'), 'default')]" - }, - "privateDNSResourceIds": { - "value": "[coalesce(parameters('privateDnsZoneResourceIds'), createArray())]" + "value": "[tryGet(parameters('privateDnsZoneGroup'), 'name')]" }, "privateEndpointName": { "value": "[parameters('name')]" + }, + "privateDnsZoneConfigs": { + "value": "[parameters('privateDnsZoneGroup').privateDnsZoneGroupConfigs]" } }, "template": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", "contentVersion": "1.0.0.0", "metadata": { "_generator": { "name": "bicep", - "version": "0.25.53.49325", - "templateHash": "11244630631275470040" + "version": "0.29.47.4906", + "templateHash": "5805178546717255803" }, "name": "Private Endpoint Private DNS Zone Groups", "description": "This module deploys a Private Endpoint Private DNS Zone Group.", "owner": "Azure/module-maintainers" }, + "definitions": { + "privateDnsZoneGroupConfigType": { + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name of the private DNS zone group config." + } + }, + "privateDnsZoneResourceId": { + "type": "string", + "metadata": { + "description": "Required. The resource id of the private DNS zone." + } + } + }, + "metadata": { + "__bicep_export!": true + } + } + }, "parameters": { "privateEndpointName": { "type": "string", @@ -7628,12 +11880,15 @@ "description": "Conditional. The name of the parent private endpoint. Required if the template is used in a standalone deployment." } }, - "privateDNSResourceIds": { + "privateDnsZoneConfigs": { "type": "array", + "items": { + "$ref": "#/definitions/privateDnsZoneGroupConfigType" + }, "minLength": 1, "maxLength": 5, "metadata": { - "description": "Required. Array of private DNS zone resource IDs. A DNS zone group can support up to 5 DNS zones." + "description": "Required. Array of private DNS zone configurations of the private DNS zone group. A DNS zone group can support up to 5 DNS zones." } }, "name": { @@ -7647,27 +11902,36 @@ "variables": { "copy": [ { - "name": "privateDnsZoneConfigs", - "count": "[length(parameters('privateDNSResourceIds'))]", + "name": "privateDnsZoneConfigsVar", + "count": "[length(parameters('privateDnsZoneConfigs'))]", "input": { - "name": "[last(split(parameters('privateDNSResourceIds')[copyIndex('privateDnsZoneConfigs')], '/'))]", + "name": "[coalesce(tryGet(parameters('privateDnsZoneConfigs')[copyIndex('privateDnsZoneConfigsVar')], 'name'), last(split(parameters('privateDnsZoneConfigs')[copyIndex('privateDnsZoneConfigsVar')].privateDnsZoneResourceId, '/')))]", "properties": { - "privateDnsZoneId": "[parameters('privateDNSResourceIds')[copyIndex('privateDnsZoneConfigs')]]" + "privateDnsZoneId": "[parameters('privateDnsZoneConfigs')[copyIndex('privateDnsZoneConfigsVar')].privateDnsZoneResourceId]" } } } ] }, - "resources": [ - { + "resources": { + "privateEndpoint": { + "existing": true, + "type": "Microsoft.Network/privateEndpoints", + "apiVersion": "2023-11-01", + "name": "[parameters('privateEndpointName')]" + }, + "privateDnsZoneGroup": { "type": "Microsoft.Network/privateEndpoints/privateDnsZoneGroups", - "apiVersion": "2023-04-01", + "apiVersion": "2023-11-01", "name": "[format('{0}/{1}', parameters('privateEndpointName'), parameters('name'))]", "properties": { - "privateDnsZoneConfigs": "[variables('privateDnsZoneConfigs')]" - } + "privateDnsZoneConfigs": "[variables('privateDnsZoneConfigsVar')]" + }, + "dependsOn": [ + "privateEndpoint" + ] } - ], + }, "outputs": { "name": { "type": "string", @@ -7725,14 +11989,28 @@ "metadata": { "description": "The location the resource was deployed into." }, - "value": "[reference('privateEndpoint', '2023-04-01', 'full').location]" + "value": "[reference('privateEndpoint', '2023-11-01', 'full').location]" + }, + "customDnsConfig": { + "$ref": "#/definitions/customDnsConfigType", + "metadata": { + "description": "The custom DNS configurations of the private endpoint." + }, + "value": "[reference('privateEndpoint').customDnsConfigs]" + }, + "networkInterfaceIds": { + "type": "array", + "metadata": { + "description": "The IDs of the network interfaces associated with the private endpoint." + }, + "value": "[reference('privateEndpoint').networkInterfaces]" }, "groupId": { "type": "string", "metadata": { "description": "The group Id for the private endpoint Group." }, - "value": "[if(not(empty(reference('privateEndpoint').manualPrivateLinkServiceConnections)), reference('privateEndpoint').manualPrivateLinkServiceConnections[0].properties.groupIds[0], reference('privateEndpoint').privateLinkServiceConnections[0].properties.groupIds[0])]" + "value": "[if(and(not(empty(reference('privateEndpoint').manualPrivateLinkServiceConnections)), greater(length(tryGet(reference('privateEndpoint').manualPrivateLinkServiceConnections[0].properties, 'groupIds')), 0)), coalesce(tryGet(reference('privateEndpoint').manualPrivateLinkServiceConnections[0].properties, 'groupIds', 0), ''), if(and(not(empty(reference('privateEndpoint').privateLinkServiceConnections)), greater(length(tryGet(reference('privateEndpoint').privateLinkServiceConnections[0].properties, 'groupIds')), 0)), coalesce(tryGet(reference('privateEndpoint').privateLinkServiceConnections[0].properties, 'groupIds', 0), ''), ''))]" } } } @@ -7766,10 +12044,11 @@ }, "systemAssignedMIPrincipalId": { "type": "string", + "nullable": true, "metadata": { "description": "The principal ID of the system assigned identity." }, - "value": "[coalesce(tryGet(tryGet(reference('automationAccount', '2022-08-08', 'full'), 'identity'), 'principalId'), '')]" + "value": "[tryGet(tryGet(reference('automationAccount', '2022-08-08', 'full'), 'identity'), 'principalId')]" }, "location": { "type": "string", @@ -7777,6 +12056,22 @@ "description": "The location the resource was deployed into." }, "value": "[reference('automationAccount', '2022-08-08', 'full').location]" + }, + "privateEndpoints": { + "type": "array", + "metadata": { + "description": "The private endpoints of the automation account." + }, + "copy": { + "count": "[length(if(not(empty(parameters('privateEndpoints'))), array(parameters('privateEndpoints')), createArray()))]", + "input": { + "name": "[reference(format('automationAccount_privateEndpoints[{0}]', copyIndex())).outputs.name.value]", + "resourceId": "[reference(format('automationAccount_privateEndpoints[{0}]', copyIndex())).outputs.resourceId.value]", + "groupId": "[reference(format('automationAccount_privateEndpoints[{0}]', copyIndex())).outputs.groupId.value]", + "customDnsConfig": "[reference(format('automationAccount_privateEndpoints[{0}]', copyIndex())).outputs.customDnsConfig.value]", + "networkInterfaceIds": "[reference(format('automationAccount_privateEndpoints[{0}]', copyIndex())).outputs.networkInterfaceIds.value]" + } + } } } } @@ -7829,11 +12124,10 @@ "_generator": { "name": "bicep", "version": "0.34.44.8038", - "templateHash": "8188890335834665181" + "templateHash": "12845441251190142050" }, "name": "Automation Account Modules", - "description": "This module deploys an Azure Automation Account Module.", - "owner": "Azure/module-maintainers" + "description": "This module deploys an Azure Automation Account Module." }, "parameters": { "name": { @@ -7977,78 +12271,86 @@ "_generator": { "name": "bicep", "version": "0.34.44.8038", - "templateHash": "5995579594382776904" + "templateHash": "10506784974698889272" }, "name": "Action Groups", - "description": "This module deploys an Action Group.", - "owner": "Azure/module-maintainers" + "description": "This module deploys an Action Group." }, "definitions": { "roleAssignmentType": { - "type": "array", - "items": { - "type": "object", - "properties": { - "roleDefinitionIdOrName": { - "type": "string", - "metadata": { - "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, or its fully qualified ID in the following format: '/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11'." - } - }, - "principalId": { - "type": "string", - "metadata": { - "description": "Required. The principal ID of the principal (user/group/identity) to assign the role to." - } - }, - "principalType": { - "type": "string", - "allowedValues": [ - "Device", - "ForeignGroup", - "Group", - "ServicePrincipal", - "User" - ], - "nullable": true, - "metadata": { - "description": "Optional. The principal type of the assigned principal ID." - } - }, - "description": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The description of the role assignment." - } - }, - "condition": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." - } - }, - "conditionVersion": { - "type": "string", - "allowedValues": [ - "2.0" - ], - "nullable": true, - "metadata": { - "description": "Optional. Version of the condition." - } - }, - "delegatedManagedIdentityResourceId": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The Resource Id of the delegated managed identity resource." - } + "type": "object", + "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." + } + }, + "roleDefinitionIdOrName": { + "type": "string", + "metadata": { + "description": "Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, or its fully qualified ID in the following format: '/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11'." + } + }, + "principalId": { + "type": "string", + "metadata": { + "description": "Required. The principal ID of the principal (user/group/identity) to assign the role to." + } + }, + "principalType": { + "type": "string", + "allowedValues": [ + "Device", + "ForeignGroup", + "Group", + "ServicePrincipal", + "User" + ], + "nullable": true, + "metadata": { + "description": "Optional. The principal type of the assigned principal ID." + } + }, + "description": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The description of the role assignment." + } + }, + "condition": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase \"foo_storage_container\"." + } + }, + "conditionVersion": { + "type": "string", + "allowedValues": [ + "2.0" + ], + "nullable": true, + "metadata": { + "description": "Optional. Version of the condition." + } + }, + "delegatedManagedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The Resource Id of the delegated managed identity resource." } } }, - "nullable": true + "metadata": { + "description": "An AVM-aligned type for a role assignment.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.5.1" + } + } } }, "parameters": { @@ -8072,7 +12374,11 @@ } }, "roleAssignments": { - "$ref": "#/definitions/roleAssignmentType", + "type": "array", + "items": { + "$ref": "#/definitions/roleAssignmentType" + }, + "nullable": true, "metadata": { "description": "Optional. Array of role assignments to create." } @@ -8170,11 +12476,18 @@ } }, "variables": { + "copy": [ + { + "name": "formattedRoleAssignments", + "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]", + "input": "[union(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')], createObject('roleDefinitionId', coalesce(tryGet(variables('builtInRoleNames'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName), if(contains(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName)))))]" + } + ], "builtInRoleNames": { "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", - "Role Based Access Control Administrator (Preview)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168')]", + "Role Based Access Control Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168')]", "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]" } }, @@ -8182,7 +12495,7 @@ "avmTelemetry": { "condition": "[parameters('enableTelemetry')]", "type": "Microsoft.Resources/deployments", - "apiVersion": "2023-07-01", + "apiVersion": "2024-03-01", "name": "[format('46d3xbcp.res.insights-actiongroup.{0}.{1}', replace('-..--..-', '.', '-'), substring(uniqueString(deployment().name, parameters('location')), 0, 4))]", "properties": { "mode": "Incremental", @@ -8223,20 +12536,20 @@ "actionGroup_roleAssignments": { "copy": { "name": "actionGroup_roleAssignments", - "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]" + "count": "[length(coalesce(variables('formattedRoleAssignments'), createArray()))]" }, "type": "Microsoft.Authorization/roleAssignments", "apiVersion": "2022-04-01", "scope": "[format('Microsoft.Insights/actionGroups/{0}', parameters('name'))]", - "name": "[guid(resourceId('Microsoft.Insights/actionGroups', parameters('name')), coalesce(parameters('roleAssignments'), createArray())[copyIndex()].principalId, coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName)]", + "name": "[coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'name'), guid(resourceId('Microsoft.Insights/actionGroups', parameters('name')), coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId, coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId))]", "properties": { - "roleDefinitionId": "[if(contains(variables('builtInRoleNames'), coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName), variables('builtInRoleNames')[coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName], if(contains(coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/'), coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName)))]", - "principalId": "[coalesce(parameters('roleAssignments'), createArray())[copyIndex()].principalId]", - "description": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'description')]", - "principalType": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'principalType')]", - "condition": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'condition')]", - "conditionVersion": "[if(not(empty(tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'condition'))), coalesce(tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'conditionVersion'), '2.0'), null())]", - "delegatedManagedIdentityResourceId": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'delegatedManagedIdentityResourceId')]" + "roleDefinitionId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId]", + "principalId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId]", + "description": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'description')]", + "principalType": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'principalType')]", + "condition": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition')]", + "conditionVersion": "[if(not(empty(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition'))), coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'conditionVersion'), '2.0'), null())]", + "delegatedManagedIdentityResourceId": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'delegatedManagedIdentityResourceId')]" }, "dependsOn": [ "actionGroup" @@ -8347,11 +12660,10 @@ "_generator": { "name": "bicep", "version": "0.34.44.8038", - "templateHash": "202898675797449665" + "templateHash": "10158611710193848674" }, "name": "Scheduled Query Rules", - "description": "This module deploys a Scheduled Query Rule.", - "owner": "Azure/module-maintainers" + "description": "This module deploys a Scheduled Query Rule." }, "definitions": { "roleAssignmentType": { @@ -8359,6 +12671,13 @@ "items": { "type": "object", "properties": { + "name": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The name (as GUID) of the role assignment. If not provided, a GUID will be generated." + } + }, "roleDefinitionIdOrName": { "type": "string", "metadata": { @@ -8442,6 +12761,13 @@ "description": "Optional. The description of the scheduled query rule." } }, + "alertDisplayName": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The display name of the scheduled query rule." + } + }, "enabled": { "type": "bool", "defaultValue": true, @@ -8494,6 +12820,13 @@ "description": "Optional. Array of role assignments to create." } }, + "ruleResolveConfiguration": { + "type": "object", + "nullable": true, + "metadata": { + "description": "Optional. Defines the configuration for resolving fired alerts. Relevant only for rules of the kind LogAlert." + } + }, "scopes": { "type": "array", "metadata": { @@ -8564,11 +12897,18 @@ } }, "variables": { + "copy": [ + { + "name": "formattedRoleAssignments", + "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]", + "input": "[union(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')], createObject('roleDefinitionId', coalesce(tryGet(variables('builtInRoleNames'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName), if(contains(coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/'), coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', coalesce(parameters('roleAssignments'), createArray())[copyIndex('formattedRoleAssignments')].roleDefinitionIdOrName)))))]" + } + ], "builtInRoleNames": { "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", "Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]", "Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]", - "Role Based Access Control Administrator (Preview)": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168')]", + "Role Based Access Control Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168')]", "User Access Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9')]" } }, @@ -8576,7 +12916,7 @@ "avmTelemetry": { "condition": "[parameters('enableTelemetry')]", "type": "Microsoft.Resources/deployments", - "apiVersion": "2023-07-01", + "apiVersion": "2024-03-01", "name": "[format('46d3xbcp.res.insights-scheduledqueryrule.{0}.{1}', replace('-..--..-', '.', '-'), substring(uniqueString(deployment().name, parameters('location')), 0, 4))]", "properties": { "mode": "Incremental", @@ -8595,7 +12935,7 @@ }, "queryRule": { "type": "Microsoft.Insights/scheduledQueryRules", - "apiVersion": "2021-02-01-preview", + "apiVersion": "2023-03-15-preview", "name": "[parameters('name')]", "location": "[parameters('location')]", "tags": "[parameters('tags')]", @@ -8608,11 +12948,12 @@ "autoMitigate": "[if(equals(parameters('kind'), 'LogAlert'), parameters('autoMitigate'), null())]", "criteria": "[parameters('criterias')]", "description": "[parameters('alertDescription')]", - "displayName": "[parameters('name')]", + "displayName": "[coalesce(parameters('alertDisplayName'), parameters('name'))]", "enabled": "[parameters('enabled')]", "evaluationFrequency": "[if(and(equals(parameters('kind'), 'LogAlert'), not(empty(parameters('evaluationFrequency')))), parameters('evaluationFrequency'), null())]", "muteActionsDuration": "[if(and(equals(parameters('kind'), 'LogAlert'), not(empty(parameters('suppressForMinutes')))), parameters('suppressForMinutes'), null())]", "overrideQueryTimeRange": "[if(and(equals(parameters('kind'), 'LogAlert'), not(empty(parameters('queryTimeRange')))), parameters('queryTimeRange'), null())]", + "ruleResolveConfiguration": "[if(and(equals(parameters('kind'), 'LogAlert'), not(empty(parameters('ruleResolveConfiguration')))), parameters('ruleResolveConfiguration'), null())]", "scopes": "[parameters('scopes')]", "severity": "[if(equals(parameters('kind'), 'LogAlert'), parameters('severity'), null())]", "skipQueryValidation": "[if(equals(parameters('kind'), 'LogAlert'), parameters('skipQueryValidation'), null())]", @@ -8623,20 +12964,20 @@ "queryRule_roleAssignments": { "copy": { "name": "queryRule_roleAssignments", - "count": "[length(coalesce(parameters('roleAssignments'), createArray()))]" + "count": "[length(coalesce(variables('formattedRoleAssignments'), createArray()))]" }, "type": "Microsoft.Authorization/roleAssignments", "apiVersion": "2022-04-01", "scope": "[format('Microsoft.Insights/scheduledQueryRules/{0}', parameters('name'))]", - "name": "[guid(resourceId('Microsoft.Insights/scheduledQueryRules', parameters('name')), coalesce(parameters('roleAssignments'), createArray())[copyIndex()].principalId, coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName)]", + "name": "[coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'name'), guid(resourceId('Microsoft.Insights/scheduledQueryRules', parameters('name')), coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId, coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId))]", "properties": { - "roleDefinitionId": "[if(contains(variables('builtInRoleNames'), coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName), variables('builtInRoleNames')[coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName], if(contains(coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName, '/providers/Microsoft.Authorization/roleDefinitions/'), coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', coalesce(parameters('roleAssignments'), createArray())[copyIndex()].roleDefinitionIdOrName)))]", - "principalId": "[coalesce(parameters('roleAssignments'), createArray())[copyIndex()].principalId]", - "description": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'description')]", - "principalType": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'principalType')]", - "condition": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'condition')]", - "conditionVersion": "[if(not(empty(tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'condition'))), coalesce(tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'conditionVersion'), '2.0'), null())]", - "delegatedManagedIdentityResourceId": "[tryGet(coalesce(parameters('roleAssignments'), createArray())[copyIndex()], 'delegatedManagedIdentityResourceId')]" + "roleDefinitionId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].roleDefinitionId]", + "principalId": "[coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()].principalId]", + "description": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'description')]", + "principalType": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'principalType')]", + "condition": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition')]", + "conditionVersion": "[if(not(empty(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'condition'))), coalesce(tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'conditionVersion'), '2.0'), null())]", + "delegatedManagedIdentityResourceId": "[tryGet(coalesce(variables('formattedRoleAssignments'), createArray())[copyIndex()], 'delegatedManagedIdentityResourceId')]" }, "dependsOn": [ "queryRule" @@ -8670,7 +13011,7 @@ "metadata": { "description": "The location the resource was deployed into." }, - "value": "[reference('queryRule', '2021-02-01-preview', 'full').location]" + "value": "[reference('queryRule', '2023-03-15-preview', 'full').location]" } } } diff --git a/workload/bicep/deploy-custom-image.bicep b/workload/bicep/deploy-custom-image.bicep index 478f2953d..37f55dc4f 100644 --- a/workload/bicep/deploy-custom-image.bicep +++ b/workload/bicep/deploy-custom-image.bicep @@ -30,8 +30,8 @@ param automationAccountCustomName string = 'aa-avd' // param avdContainerCustomName string = 'avd-artifacts' @allowed([ - 'OneTime' - 'Recurring' + 'OneTime' + 'Recurring' ]) @sys.description('Determine whether to build the image template one time or check daily for a new marketplace image and auto build when found. (Default: Recurring)') param buildSchedule string = 'Recurring' @@ -43,11 +43,11 @@ param costCenterTag string = 'Contoso-CC' param criticalityCustomTag string = 'Contoso-Critical' @allowed([ - 'Low' - 'Medium' - 'High' - 'Mission-critical' - 'Custom' + 'Low' + 'Medium' + 'High' + 'Mission-critical' + 'Custom' ]) @sys.description('criticality of each workload. (Default: Low)') param criticalityTag string = 'Low' @@ -56,11 +56,11 @@ param criticalityTag string = 'Low' param customNaming bool = false @allowed([ - 'Non-business' - 'Public' - 'General' - 'Confidential' - 'Highly Confidential' + 'Non-business' + 'Public' + 'General' + 'Confidential' + 'Highly Confidential' ]) @sys.description('Sensitivity of data hosted (Default: Non-business)') param dataClassificationTag string = 'Non-business' @@ -69,40 +69,40 @@ param dataClassificationTag string = 'Non-business' param departmentTag string = 'Contoso-AVD' @allowed([ - 'australiaeast' - 'australiasoutheast' - 'brazilsouth' - 'canadacentral' - 'centralindia' - 'centralus' - 'eastasia' - 'eastus' - 'eastus2' - 'francecentral' - 'germanywestcentral' - 'japaneast' - 'jioindiawest' - 'koreacentral' - 'northcentralus' - 'northeurope' - 'norwayeast' - 'qatarcentral' - 'southafricanorth' - 'southcentralus' - 'southeastasia' - 'switzerlandnorth' - 'uaenorth' - 'uksouth' - 'ukwest' - 'usgovarizona' - 'usgoviowa' - 'usgovtexas' - 'usgovvirginia' - 'westcentralus' - 'westeurope' - 'westus' - 'westus2' - 'westus3' + 'australiaeast' + 'australiasoutheast' + 'brazilsouth' + 'canadacentral' + 'centralindia' + 'centralus' + 'eastasia' + 'eastus' + 'eastus2' + 'francecentral' + 'germanywestcentral' + 'japaneast' + 'jioindiawest' + 'koreacentral' + 'northcentralus' + 'northeurope' + 'norwayeast' + 'qatarcentral' + 'southafricanorth' + 'southcentralus' + 'southeastasia' + 'switzerlandnorth' + 'uaenorth' + 'uksouth' + 'ukwest' + 'usgovarizona' + 'usgoviowa' + 'usgovtexas' + 'usgovvirginia' + 'westcentralus' + 'westeurope' + 'westus' + 'westus2' + 'westus3' ]) @sys.description('Location to deploy the resources in this solution, except the image template. (Default: eastus)') param deploymentLocation string = 'eastus' @@ -117,9 +117,9 @@ param enableResourceTags bool = false param enableTelemetry bool = true @allowed([ - 'Prod' - 'Dev' - 'Staging' + 'Prod' + 'Dev' + 'Staging' ]) @sys.description('Deployment environment of the application, workload. (Default: Dev)') param environmentTag string = 'Dev' @@ -151,10 +151,10 @@ param imageDefinitionAcceleratedNetworkSupported bool = true param imageDefinitionHibernateSupported bool = false @allowed([ - 'Standard' - 'TrustedLaunch' - 'ConfidentialVM' - 'ConfidentialVMSupported' + 'Standard' + 'TrustedLaunch' + 'ConfidentialVM' + 'ConfidentialVMSupported' ]) @sys.description('Choose the Security Type of the Image Definition. (Default: Standard)') param imageDefinitionSecurityType string = 'Standard' @@ -174,9 +174,9 @@ param imageVersionDisasterRecoveryLocation string = '' param imageVersionPrimaryLocation string @allowed([ - //'Premium_LRS' supported by Image Versions but not Image Templates yet - 'Standard_LRS' - 'Standard_ZRS' + //'Premium_LRS' supported by Image Versions but not Image Templates yet + 'Standard_LRS' + 'Standard_ZRS' ]) @sys.description('Determine the Storage Account Type for the Image Version distributed by the Image Template. (Default: Standard_LRS)') param imageVersionStorageAccountType string = 'Standard_LRS' @@ -189,18 +189,17 @@ param logAnalyticsWorkspaceCustomName string = 'log-avd' @sys.description('Set the data retention in the number of days for the Log Analytics Workspace. (Default: 30)') param logAnalyticsWorkspaceDataRetention int = 30 -@allowed([ - 'win10_22h2_g2' - 'win10_22h2_office_g2' - 'win11_22h2' - 'win11_22h2_office' - 'win11_23h2' - 'win11_23h2_office' - 'win11_24h2' - 'win11_24h2_office' -]) -@sys.description('AVD OS image source. (Default: win11_23h2)') -param operatingSystemImage string = 'win11_23h2' +@sys.description('Market place AVD OS image offer. (Default: Office-365)') +param mpImageOffer string = 'Office-365' + +@sys.description('Market place AVD OS image SKU. (Default: win11-24h2-avd-m365)') +param mpImageSku string = 'win11-24h2-avd-m365' + +@sys.description('Market place AVD OS image publisher.') +param mpImagePublisher string = 'MicrosoftWindowsDesktop' + +@sys.description('Market place AVD OS image version.') +param mpImageVersion string = 'latest' @sys.description('Team accountable for day-to-day operations. (Contoso-Ops)') param operationsTeamTag string = 'workload-admins@Contoso.com' @@ -254,274 +253,209 @@ param workloadNameTag string = 'Contoso-Workload' var varActionGroupName = customNaming ? alertsActionGroupCustomName : 'ag-avd-${varNamingStandard}' // Placeholder for future feature // var varAibContainerName = customNaming ? aibContainerCustomName : 'aib-artifacts' -var varAlerts = enableMonitoringAlerts ? [ - { +var varAlerts = enableMonitoringAlerts + ? [ + { name: 'Azure Image Builder - Build Failure' description: 'Sends an error alert when a build fails on an image template for Azure Image Builder.' severity: 0 evaluationFrequency: 'PT5M' windowSize: 'PT5M' criterias: { - allOf: [ + allOf: [ + { + query: 'AzureDiagnostics\n| where ResourceProvider == "MICROSOFT.AUTOMATION"\n| where Category == "JobStreams"\n| where ResultDescription has "Image Template build failed"' + timeAggregation: 'Count' + dimensions: [ { - query: 'AzureDiagnostics\n| where ResourceProvider == "MICROSOFT.AUTOMATION"\n| where Category == "JobStreams"\n| where ResultDescription has "Image Template build failed"' - timeAggregation: 'Count' - dimensions: [ - { - name: 'ResultDescription' - operator: 'Include' - values: [ - '*' - ] - } - ] - operator: 'GreaterThanOrEqual' - threshold: 1 - failingPeriods: { - numberOfEvaluationPeriods: 1 - minFailingPeriodsToAlert: 1 - } + name: 'ResultDescription' + operator: 'Include' + values: [ + '*' + ] } - ] + ] + operator: 'GreaterThanOrEqual' + threshold: 1 + failingPeriods: { + numberOfEvaluationPeriods: 1 + minFailingPeriodsToAlert: 1 + } + } + ] } - } - { + } + { name: 'Azure Image Builder - Build Success' description: 'Sends an informational alert when a build succeeds on an image template for Azure Image Builder.' severity: 3 evaluationFrequency: 'PT5M' windowSize: 'PT5M' criterias: { - allOf: [ + allOf: [ + { + query: 'AzureDiagnostics\n| where ResourceProvider == "MICROSOFT.AUTOMATION"\n| where Category == "JobStreams"\n| where ResultDescription has "Image Template build succeeded"' + timeAggregation: 'Count' + dimensions: [ { - query: 'AzureDiagnostics\n| where ResourceProvider == "MICROSOFT.AUTOMATION"\n| where Category == "JobStreams"\n| where ResultDescription has "Image Template build succeeded"' - timeAggregation: 'Count' - dimensions: [ - { - name: 'ResultDescription' - operator: 'Include' - values: [ - '*' - ] - } - ] - operator: 'GreaterThanOrEqual' - threshold: 1 - failingPeriods: { - numberOfEvaluationPeriods: 1 - minFailingPeriodsToAlert: 1 - } + name: 'ResultDescription' + operator: 'Include' + values: [ + '*' + ] } - ] + ] + operator: 'GreaterThanOrEqual' + threshold: 1 + failingPeriods: { + numberOfEvaluationPeriods: 1 + minFailingPeriodsToAlert: 1 + } + } + ] } - } -] : [] + } + ] + : [] var varAutomationAccountName = customNaming ? automationAccountCustomName : 'aa-avd-${varNamingStandard}' // Placeholder for future feature // var varAvdContainerName = customNaming ? avdContainerCustomName : 'avd-artifacts' var varAzureCloudName = environment().name var varBaseScriptUri = 'https://raw.githubusercontent.com/Azure/avdaccelerator/main/workload/' -var varCommonResourceTags = enableResourceTags ? { - ImageBuildName: imageBuildNameTag - WorkloadName: workloadNameTag - DataClassification: dataClassificationTag - Department: departmentTag - Criticality: (criticalityTag == 'Custom') ? criticalityCustomTag : criticalityTag - ApplicationName: applicationNameTag - OpsTeam: operationsTeamTag - Owner: ownerTag - CostCenter: costCenterTag - Environment: environmentTag - -} : {} +var varCommonResourceTags = enableResourceTags + ? { + ImageBuildName: imageBuildNameTag + WorkloadName: workloadNameTag + DataClassification: dataClassificationTag + Department: departmentTag + Criticality: (criticalityTag == 'Custom') ? criticalityCustomTag : criticalityTag + ApplicationName: applicationNameTag + OpsTeam: operationsTeamTag + Owner: ownerTag + CostCenter: costCenterTag + Environment: environmentTag + } + : {} var varCustomizationSteps = union(varScriptCustomizers, varRemainingCustomizers) -var varImageDefinitionName = customNaming ? imageDefinitionCustomName : 'avd-${operatingSystemImage}' +var varImageDefinitionName = customNaming ? imageDefinitionCustomName : 'avd-${mpImageOffer}-${mpImageSku}' var varImageGalleryName = customNaming ? imageGalleryCustomName : 'gal_avd_${varNamingStandard}' -var varImageReplicationRegions = empty(imageVersionDisasterRecoveryLocation) ? [ - imageVersionPrimaryLocation -] : [ - imageVersionPrimaryLocation - imageVersionDisasterRecoveryLocation -] +var varImageReplicationRegions = empty(imageVersionDisasterRecoveryLocation) + ? [ + imageVersionPrimaryLocation + ] + : [ + imageVersionPrimaryLocation + imageVersionDisasterRecoveryLocation + ] // Image template permissions are currently (1/6/23) not supported in Azure US Government var varImageTemplateBuildAutomationName = 'Image Template Build Automation' -var varImageTemplateBuildAutomation = varAzureCloudName == 'AzureCloud' ? [ - { +var varImageTemplateBuildAutomation = varAzureCloudName == 'AzureCloud' + ? [ + { resourceGroup: varResourceGroupName name: varImageTemplateBuildAutomationName description: 'Allow Image Template build automation using a Managed Identity on an Automation Account.' actions: [ - 'Microsoft.VirtualMachineImages/imageTemplates/run/action' - 'Microsoft.VirtualMachineImages/imageTemplates/read' - 'Microsoft.Compute/locations/publishers/artifacttypes/offers/skus/versions/read' - 'Microsoft.Compute/locations/publishers/artifacttypes/offers/skus/read' - 'Microsoft.Compute/locations/publishers/artifacttypes/offers/read' - 'Microsoft.Compute/locations/publishers/read' + 'Microsoft.VirtualMachineImages/imageTemplates/run/action' + 'Microsoft.VirtualMachineImages/imageTemplates/read' + 'Microsoft.Compute/locations/publishers/artifacttypes/offers/skus/versions/read' + 'Microsoft.Compute/locations/publishers/artifacttypes/offers/skus/read' + 'Microsoft.Compute/locations/publishers/artifacttypes/offers/read' + 'Microsoft.Compute/locations/publishers/read' ] - } -] : [] + } + ] + : [] var varImageTemplateContributorRoleName = 'Image Template Contributor' var varImageTemplateContributorRole = [ - { - resourceGroup: varResourceGroupName - name: varImageTemplateContributorRoleName - description: 'Allow the creation and management of images' - actions: [ - 'Microsoft.Compute/galleries/read' - 'Microsoft.Compute/galleries/images/read' - 'Microsoft.Compute/galleries/images/versions/read' - 'Microsoft.Compute/galleries/images/versions/write' - 'Microsoft.Compute/images/read' - 'Microsoft.Compute/images/write' - 'Microsoft.Compute/images/delete' - ] - } + { + resourceGroup: varResourceGroupName + name: varImageTemplateContributorRoleName + description: 'Allow the creation and management of images' + actions: [ + 'Microsoft.Compute/galleries/read' + 'Microsoft.Compute/galleries/images/read' + 'Microsoft.Compute/galleries/images/versions/read' + 'Microsoft.Compute/galleries/images/versions/write' + 'Microsoft.Compute/images/read' + 'Microsoft.Compute/images/write' + 'Microsoft.Compute/images/delete' + ] + } ] -var varImageTemplateName = customNaming ? imageTemplateCustomName : 'it-avd-${operatingSystemImage}' +var varImageTemplateName = customNaming ? imageTemplateCustomName : 'it-avd-${mpImageOffer}' var varLocationAcronym = varLocations[varLocation].acronym var varLocation = toLower(replace(deploymentLocation, ' ', '')) var varLocations = loadJsonContent('../variables/locations.json') var varLogAnalyticsWorkspaceName = customNaming ? logAnalyticsWorkspaceCustomName : 'log-avd-${varNamingStandard}' var varModules = [ - { - name: 'Az.Accounts' - uri: 'https://www.powershellgallery.com/api/v2/package' - version: '2.12.1' - } - { - name: 'Az.ImageBuilder' - uri: 'https://www.powershellgallery.com/api/v2/package' - version: '0.3.0' - } + { + name: 'Az.Accounts' + uri: 'https://www.powershellgallery.com/api/v2/package' + version: '4.0.2' + } + { + name: 'Az.ImageBuilder' + uri: 'https://www.powershellgallery.com/api/v2/package' + version: '0.4.1' + } ] var varNamingStandard = '${varLocationAcronym}' -var varOperatingSystemImageDefinitions = { - win10_22h2_g2: { - osType: 'Windows' - osState: 'Generalized' - offer: 'windows-10' - publisher: 'MicrosoftWindowsDesktop' - sku: 'win10-22h2-avd-g2' - hyperVGeneration: 'V2' - version: 'latest' - } - win10_22h2_office_g2: { - osType: 'Windows' - osState: 'Generalized' - offer: 'office-365' - publisher: 'MicrosoftWindowsDesktop' - sku: 'win10-22h2-avd-m365-g2' - hyperVGeneration: 'V2' - version: 'latest' - } - win11_22h2: { - osType: 'Windows' - osState: 'Generalized' - offer: 'windows-11' - publisher: 'MicrosoftWindowsDesktop' - sku: 'win11-22h2-avd' - hyperVGeneration: 'V2' - version: 'latest' - } - win11_22h2_office: { - osType: 'Windows' - osState: 'Generalized' - offer: 'office-365' - publisher: 'MicrosoftWindowsDesktop' - sku: 'win11-22h2-avd-m365' - hyperVGeneration: 'V2' - version: 'latest' - } - win11_23h2: { - osType: 'Windows' - osState: 'Generalized' - offer: 'windows-11' - publisher: 'MicrosoftWindowsDesktop' - sku: 'win11-23h2-avd' - hyperVGeneration: 'V2' - version: 'latest' - } - win11_23h2_office: { - osType: 'Windows' - osState: 'Generalized' - offer: 'office-365' - publisher: 'MicrosoftWindowsDesktop' - sku: 'win11-23h2-avd-m365' - hyperVGeneration: 'V2' - version: 'latest' - } - win11_24h2: { - osType: 'Windows' - osState: 'Generalized' - offer: 'windows-11' - publisher: 'MicrosoftWindowsDesktop' - sku: 'win11-24h2-avd' - hyperVGeneration: 'V2' - version: 'latest' - } - win11_24h2_office: { - osType: 'Windows' - osState: 'Generalized' - offer: 'office-365' - publisher: 'MicrosoftWindowsDesktop' - sku: 'win11-24h2-avd-m365' - hyperVGeneration: 'V2' - version: 'latest' - } -} -var varRdpShortPathCustomizer = rdpShortPathManagedNetworks ? [ - { +var varRdpShortPathCustomizer = rdpShortPathManagedNetworks + ? [ + { type: 'PowerShell' name: 'rdpShortPath' runElevated: true runAsSystem: true scriptUri: '${varBaseScriptUri}scripts/Set-RdpShortpath.ps1' - } -] : [] + } + ] + : [] var varRemainingCustomizers = [ - { - type: 'WindowsRestart' - restartCheckCommand: 'Write-Host "Restarting post script customizers"' - restarttimeout: '10m' - } - { - type: 'WindowsUpdate' - searchCriteria: 'IsInstalled=0' - filters: [ - 'exclude:$_.Title -like \'*Preview*\'' - 'include:$true' - ] - updateLimit: 40 - } - { - type: 'PowerShell' - name: 'Sleep for 5 minutes' - runElevated: true - runAsSystem: true - inline: [ - 'Write-Host "Sleep for 5 min"' - 'Start-Sleep -Seconds 300' - ] - } - { - type: 'WindowsRestart' - restartCheckCommand: 'Write-Host "restarting post Windows updates"' - restarttimeout: '10m' - } - { - type: 'PowerShell' - name: 'Sleep for a min' - runElevated: true - runAsSystem: true - inline: [ - 'Write-Host "Sleep for a min"' - 'Start-Sleep -Seconds 60' - ] - } - { - type: 'WindowsRestart' - restarttimeout: '10m' - } + { + type: 'WindowsRestart' + restartCheckCommand: 'Write-Host "Restarting post script customizers"' + restartTimeout: '10m' + } + { + type: 'WindowsUpdate' + searchCriteria: 'IsInstalled=0' + filters: [ + 'exclude:$_.Title -like \'*Preview*\'' + 'include:$true' + ] + updateLimit: 40 + } + { + type: 'PowerShell' + name: 'Sleep for 5 minutes' + runElevated: true + runAsSystem: true + inline: [ + 'Write-Host "Sleep for 5 min"' + 'Start-Sleep -Seconds 300' + ] + } + { + type: 'WindowsRestart' + restartCheckCommand: 'Write-Host "restarting post Windows updates"' + restartTimeout: '10m' + } + { + type: 'PowerShell' + name: 'Sleep for a min' + runElevated: true + runAsSystem: true + inline: [ + 'Write-Host "Sleep for a min"' + 'Start-Sleep -Seconds 60' + ] + } + { + type: 'WindowsRestart' + restartTimeout: '10m' + } ] var varResourceGroupName = customNaming ? resourceGroupCustomName : 'rg-avd-${varNamingStandard}-shared-services' //var varRoles = union(varVirtualNetworkJoinRoleExistingRoleCheck, varRolesimageTemplateBuildAutomationExistingRoleCheck, varImageTemplateContributorRoleExistingRoleCheck) @@ -529,15 +463,17 @@ var varRoles = union(varVirtualNetworkJoinRole, varImageTemplateBuildAutomation, //var varRolesimageTemplateBuildAutomationExistingRoleCheck = empty(imageTemplateBuildAutomationExistingRoleCheck.id) ? varImageTemplateBuildAutomation : [] //var varImageTemplateContributorRoleExistingRoleCheck = empty(imageTemplateContributorExistingRoleCheck.id) ? varImageTemplateContributorRole : [] //var varVirtualNetworkJoinRoleExistingRoleCheck = empty(virtualNetworkJoinExistingRoleCheck.id) ? varVirtualNetworkJoinRole : [] -var varScreenCaptureProtectionCustomizer = screenCaptureProtection ? [ - { +var varScreenCaptureProtectionCustomizer = screenCaptureProtection + ? [ + { type: 'PowerShell' name: 'screenCaptureProtection' runElevated: true runAsSystem: true scriptUri: '${varBaseScriptUri}scripts/Set-ScreenCaptureProtection.ps1' - } -] : [] + } + ] + : [] var varScriptCustomizers = union(varRdpShortPathCustomizer, varScreenCaptureProtectionCustomizer) // Placeholder for future feature // var varStorageAccountName = customNaming ? storageAccountCustomName : 'stavd${varNamingStandard}${varUniqueStringSixChar}' @@ -546,20 +482,24 @@ var varTimeZone = varLocations[varLocation].timeZone // Placeholder for future feature // var varUniqueStringSixChar = take('${uniqueString(sharedServicesSubId, time)}', 6) -var varUserAssignedManagedIdentityName = customNaming ? userAssignedManagedIdentityCustomName : 'id-aib-${varNamingStandard}' +var varUserAssignedManagedIdentityName = customNaming + ? userAssignedManagedIdentityCustomName + : 'id-aib-${varNamingStandard}' var varVirtualNetworkJoinRoleName = 'Virtual Network Join' -var varVirtualNetworkJoinRole = useExistingVirtualNetwork ? [ - { +var varVirtualNetworkJoinRole = useExistingVirtualNetwork + ? [ + { resourceGroup: split(existingVirtualNetworkResourceId, '/')[4] name: varVirtualNetworkJoinRoleName description: 'Allow resources to join a subnet' actions: [ - 'Microsoft.Network/virtualNetworks/read' - 'Microsoft.Network/virtualNetworks/subnets/read' - 'Microsoft.Network/virtualNetworks/subnets/join/action' + 'Microsoft.Network/virtualNetworks/read' + 'Microsoft.Network/virtualNetworks/subnets/read' + 'Microsoft.Network/virtualNetworks/subnets/join/action' ] - } -] : [] + } + ] + : [] var varVmSize = 'Standard_D4s_v3' // =========== // @@ -568,27 +508,27 @@ var varVmSize = 'Standard_D4s_v3' // Telemetry Deployment. resource telemetryDeployment 'Microsoft.Resources/deployments@2021-04-01' = if (enableTelemetry) { - name: varTelemetryId - location: deploymentLocation - properties: { - mode: 'Incremental' - template: { - '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' - contentVersion: '1.0.0.0' - resources: [] - } - } + name: varTelemetryId + location: deploymentLocation + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } } // AVD Shared Services Resource Group. -module avdSharedResourcesRg '../../avm/1.0.0/res/resources/resource-group/main.bicep' = { - scope: subscription(sharedServicesSubId) - name: 'RG-${time}' - params: { - name: varResourceGroupName - location: deploymentLocation - tags: enableResourceTags ? varCommonResourceTags : {} - } +module avdSharedResourcesRg '../../avm/1.1.0/res/resources/resource-group/main.bicep' = { + scope: subscription(sharedServicesSubId) + name: 'RG-${time}' + params: { + name: varResourceGroupName + location: deploymentLocation + tags: enableResourceTags ? varCommonResourceTags : {} + } } /* // Role definition check Image Template Build Automation. @@ -608,289 +548,311 @@ resource virtualNetworkJoinExistingRoleCheck 'Microsoft.Authorization/roleDefini */ // Role definition deployment. -module roleDefinitions './modules/rbacRoles/roleDefinitionsSubscriptions.bicep' = [for i in range(0, length(varRoles)): { +module roleDefinitions './modules/rbacRoles/roleDefinitionsSubscriptions.bicep' = [ + for i in range(0, length(varRoles)): { scope: subscription(sharedServicesSubId) name: 'Role-Definition-${i}-${time}' params: { - subscriptionId: sharedServicesSubId - description: varRoles[i].description - roleName: varRoles[i].name - actions: varRoles[i].actions - assignableScopes: [ - '/subscriptions/${sharedServicesSubId}' - ] - } -}] + subscriptionId: sharedServicesSubId + description: varRoles[i].description + roleName: varRoles[i].name + actions: varRoles[i].actions + assignableScopes: [ + '/subscriptions/${sharedServicesSubId}' + ] + } + } +] // Managed identity. -module userAssignedManagedIdentity '../../avm/1.0.0/res/managed-identity/user-assigned-identity/main.bicep' = { - scope: resourceGroup(sharedServicesSubId, varResourceGroupName) - name: 'User-Assigned-Managed-Identity-${time}' - params: { - name: varUserAssignedManagedIdentityName - location: deploymentLocation - tags: enableResourceTags ? varCommonResourceTags : {} - } - dependsOn: [ - avdSharedResourcesRg - ] +module userAssignedManagedIdentity '../../avm/1.1.0/res/managed-identity/user-assigned-identity/main.bicep' = { + scope: resourceGroup(sharedServicesSubId, varResourceGroupName) + name: 'User-Assigned-Managed-Identity-${time}' + params: { + name: varUserAssignedManagedIdentityName + location: deploymentLocation + tags: enableResourceTags ? varCommonResourceTags : {} + } + dependsOn: [ + avdSharedResourcesRg + ] } // Role assignments. -module roleAssignments '../../avm/1.0.0/ptn/authorization/role-assignment/modules/resource-group.bicep' = [for i in range(0, length(varRoles)): { +module roleAssignments '../../avm/1.0.0/ptn/authorization/role-assignment/modules/resource-group.bicep' = [ + for i in range(0, length(varRoles)): { name: 'Role-Assignment-${i}-${time}' scope: resourceGroup(sharedServicesSubId, varRoles[i].resourceGroup) params: { - roleDefinitionIdOrName: roleDefinitions[i].outputs.resourceId - principalId: userAssignedManagedIdentity.outputs.principalId - principalType: 'ServicePrincipal' + roleDefinitionIdOrName: roleDefinitions[i].outputs.resourceId + principalId: userAssignedManagedIdentity.outputs.principalId + principalType: 'ServicePrincipal' } -}] + } +] //// Unique role assignment for Azure US Government since it does not support image template permissions -module roleAssignment_AzureUSGovernment '../../avm/1.0.0/ptn/authorization/role-assignment/modules/resource-group.bicep' = if (varAzureCloudName != 'AzureCloud') { - name: 'Role-Assignment-MAG-${time}' - scope: resourceGroup(sharedServicesSubId, varResourceGroupName) - params: { - roleDefinitionIdOrName: 'Contributor' - principalId: userAssignedManagedIdentity.outputs.principalId - principalType: 'ServicePrincipal' - } +module roleAssignment_AzureUSGovernment '../../avm/1.1.0/ptn/authorization/role-assignment/modules/resource-group.bicep' = if (varAzureCloudName != 'AzureCloud') { + name: 'Role-Assignment-MAG-${time}' + scope: resourceGroup(sharedServicesSubId, varResourceGroupName) + params: { + roleDefinitionIdOrName: 'Contributor' + principalId: userAssignedManagedIdentity.outputs.principalId + principalType: 'ServicePrincipal' + } } // Compute Gallery. -module gallery '../../avm/1.0.0/res/compute/gallery/main.bicep' = { - scope: resourceGroup(sharedServicesSubId, varResourceGroupName) - name: 'Compute-Gallery-${time}' - params: { - name: varImageGalleryName - location: imageVersionPrimaryLocation - description: 'Azure Virtual Desktops Images' - tags: enableResourceTags ? varCommonResourceTags : {} - } - dependsOn: [ - avdSharedResourcesRg - ] +module gallery '../../avm/1.1.0/res/compute/gallery/main.bicep' = { + scope: resourceGroup(sharedServicesSubId, varResourceGroupName) + name: 'Compute-Gallery-${time}' + params: { + name: varImageGalleryName + location: imageVersionPrimaryLocation + description: 'Azure Virtual Desktops Images' + tags: enableResourceTags ? varCommonResourceTags : {} + } + dependsOn: [ + avdSharedResourcesRg + ] } // Image Definition. -module image '../../avm/1.0.0/res/compute/gallery/image/main.bicep' = { - scope: resourceGroup(sharedServicesSubId, varResourceGroupName) - name: 'Image-Definition-${time}' - params: { - galleryName: varImageGalleryName - name: varImageDefinitionName - osState: varOperatingSystemImageDefinitions[operatingSystemImage].osState - osType: varOperatingSystemImageDefinitions[operatingSystemImage].osType - publisher: varOperatingSystemImageDefinitions[operatingSystemImage].publisher - offer: varOperatingSystemImageDefinitions[operatingSystemImage].offer - sku: varOperatingSystemImageDefinitions[operatingSystemImage].sku - location: imageVersionPrimaryLocation - hyperVGeneration: varOperatingSystemImageDefinitions[operatingSystemImage].hyperVGeneration - isAcceleratedNetworkSupported: imageDefinitionAcceleratedNetworkSupported - isHibernateSupported: imageDefinitionHibernateSupported - securityType: imageDefinitionSecurityType - //productName: operatingSystemImage - //planName: varOperatingSystemImageDefinitions[operatingSystemImage].offer - //planPublisherName: varOperatingSystemImageDefinitions[operatingSystemImage].publisher - tags: enableResourceTags ? varCommonResourceTags : {} - } - dependsOn: [ - gallery - avdSharedResourcesRg - ] +module image '../../avm/1.1.0/res/compute/gallery/image/main.bicep' = { + scope: resourceGroup(sharedServicesSubId, varResourceGroupName) + name: 'Image-Definition-${time}' + params: { + galleryName: varImageGalleryName + name: varImageDefinitionName + osState: 'Generalized' + osType: 'Windows' + identifier: { + publisher: mpImagePublisher + offer: mpImageOffer + sku: mpImageSku + } + location: imageVersionPrimaryLocation + hyperVGeneration: 'V2' + isAcceleratedNetworkSupported: imageDefinitionAcceleratedNetworkSupported + isHibernateSupported: imageDefinitionHibernateSupported + securityType: imageDefinitionSecurityType + tags: enableResourceTags ? varCommonResourceTags : {} + } + dependsOn: [ + gallery + avdSharedResourcesRg + ] } - - // Image template. -module imageTemplate '../../avm/1.0.0/res/virtual-machine-images/image-template/main.bicep' = { - scope: resourceGroup(sharedServicesSubId, varResourceGroupName) - name: 'Image-Template-${time}' - params: { - name: varImageTemplateName - subnetResourceId: !empty(existingVirtualNetworkResourceId) && !empty(existingSubnetName) ? '${existingVirtualNetworkResourceId}/subnets/${existingSubnetName}' : '' - managedIdentities: { - userAssignedResourceIds: [ - userAssignedManagedIdentity.outputs.resourceId - ] - } - location: deploymentLocation - distributions: [ - { - type: 'SharedImage' - replicationRegions: varImageReplicationRegions - storageAccountType: imageVersionStorageAccountType - sharedImageGalleryImageDefinitionResourceId: image.outputs.resourceId - } - ] - vmSize: varVmSize - customizationSteps: varCustomizationSteps - imageSource: { - type: 'PlatformImage' - publisher: varOperatingSystemImageDefinitions[operatingSystemImage].publisher - offer: varOperatingSystemImageDefinitions[operatingSystemImage].offer - sku: varOperatingSystemImageDefinitions[operatingSystemImage].sku - version: varOperatingSystemImageDefinitions[operatingSystemImage].version - } - tags: enableResourceTags ? varCommonResourceTags : {} +module imageTemplate '../../avm/1.1.0/res/virtual-machine-images/image-template/main.bicep' = { + scope: resourceGroup(sharedServicesSubId, varResourceGroupName) + name: 'Image-Template-${time}' + params: { + name: varImageTemplateName + subnetResourceId: !empty(existingVirtualNetworkResourceId) && !empty(existingSubnetName) + ? '${existingVirtualNetworkResourceId}/subnets/${existingSubnetName}' + : '' + managedIdentities: { + userAssignedResourceIds: [ + userAssignedManagedIdentity.outputs.resourceId + ] } - dependsOn: [ - image - gallery - avdSharedResourcesRg - roleAssignments + location: deploymentLocation + distributions: [ + { + type: 'SharedImage' + replicationRegions: varImageReplicationRegions + storageAccountType: imageVersionStorageAccountType + sharedImageGalleryImageDefinitionResourceId: image.outputs.resourceId + } ] + vmSize: varVmSize + customizationSteps: varCustomizationSteps + imageSource: { + type: 'PlatformImage' + publisher: mpImagePublisher + offer: mpImageOffer + sku: mpImageSku + version: mpImageVersion + } + tags: enableResourceTags ? varCommonResourceTags : {} + } + dependsOn: [ + gallery + avdSharedResourcesRg + roleAssignments + ] } // Log Analytics Workspace. -module workspace '../../avm/1.0.0/res/operational-insights/workspace/main.bicep' = if (enableMonitoringAlerts && empty(existingLogAnalyticsWorkspaceResourceId)) { - scope: resourceGroup(sharedServicesSubId, varResourceGroupName) - name: 'Log-Analytics-Workspace-${time}' - params: { - location: deploymentLocation - name: varLogAnalyticsWorkspaceName - dataRetention: logAnalyticsWorkspaceDataRetention - useResourcePermissions: true - tags: enableResourceTags ? varCommonResourceTags : {} - } - dependsOn: [ - avdSharedResourcesRg - ] +module workspace '../../avm/1.1.0/res/operational-insights/workspace/main.bicep' = if (enableMonitoringAlerts && empty(existingLogAnalyticsWorkspaceResourceId)) { + scope: resourceGroup(sharedServicesSubId, varResourceGroupName) + name: 'Log-Analytics-Workspace-${time}' + params: { + location: deploymentLocation + name: varLogAnalyticsWorkspaceName + dataRetention: logAnalyticsWorkspaceDataRetention + features: { + enableLogAccessUsingOnlyResourcePermissions: true + } + tags: enableResourceTags ? varCommonResourceTags : {} + } + dependsOn: [ + avdSharedResourcesRg + ] } // Automation account. -module automationAccount '../../avm/1.0.0/res/automation/automation-account/main.bicep' = { - scope: resourceGroup(sharedServicesSubId, varResourceGroupName) - name: 'Automation-Account-${time}' - params: { - diagnosticSettings: enableMonitoringAlerts ? [ - { - workspaceResourceId: empty(alertsDistributionGroup) ? '' : empty(existingLogAnalyticsWorkspaceResourceId) ? workspace.outputs.resourceId : existingLogAnalyticsWorkspaceResourceId - } - ] : [ - +module automationAccount '../../avm/1.1.0/res/automation/automation-account/main.bicep' = { + scope: resourceGroup(sharedServicesSubId, varResourceGroupName) + name: 'Automation-Account-${time}' + params: { + diagnosticSettings: enableMonitoringAlerts + ? [ + { + workspaceResourceId: empty(alertsDistributionGroup) + ? '' + : empty(existingLogAnalyticsWorkspaceResourceId) + ? workspace.outputs.resourceId + : existingLogAnalyticsWorkspaceResourceId + } ] - name: varAutomationAccountName - jobSchedules: [ - { - parameters: { - ClientId: userAssignedManagedIdentity.outputs.clientId - EnvironmentName: varAzureCloudName - ImageOffer: varOperatingSystemImageDefinitions[operatingSystemImage].offer - ImagePublisher: varOperatingSystemImageDefinitions[operatingSystemImage].publisher - ImageSku: varOperatingSystemImageDefinitions[operatingSystemImage].sku - Location: deploymentLocation - SubscriptionId: sharedServicesSubId - TemplateName: imageTemplate.outputs.name - TemplateResourceGroupName: varResourceGroupName - TenantId: subscription().tenantId - } - runbookName: 'aib-build-automation' - scheduleName: varImageTemplateName - } - ] - location: deploymentLocation - runbooks: [ - { - name: 'aib-build-automation' - description: 'When this runbook is triggered, last build date is checked on the AIB image template. If a new marketplace image has been released since that date, a new build is initiated. If a build has never been initiated then it will be start one.' - type: 'PowerShell' - // ToDo: Update URL before PR merge - uri: 'https://raw.githubusercontent.com/Azure/avdaccelerator/main/workload/scripts/New-AzureImageBuilderBuild.ps1' - version: '1.0.0.0' - } - ] - schedules: [ - { - name: varImageTemplateName - frequency: buildSchedule == 'OneTime' ? 'OneTime' : 'Day' - interval: buildSchedule == 'OneTime' ? 0 : 1 - starttime: dateTimeAdd(time, 'PT15M') - varTimeZone: varTimeZone - advancedSchedule: {} // required to prevent deployment failure - } - ] - skuName: 'Free' - tags: enableResourceTags ? varCommonResourceTags : {} - managedIdentities: { - systemAssigned: false - userAssignedResourceIds: [ - userAssignedManagedIdentity.outputs.resourceId - ] + : [] + name: varAutomationAccountName + jobSchedules: [ + { + parameters: { + ClientId: userAssignedManagedIdentity.outputs.clientId + EnvironmentName: varAzureCloudName + ImageOffer: mpImageOffer + ImagePublisher: mpImagePublisher + ImageSku: mpImageSku + Location: deploymentLocation + SubscriptionId: sharedServicesSubId + TemplateName: imageTemplate.outputs.name + TemplateResourceGroupName: varResourceGroupName + TenantId: subscription().tenantId } - } - dependsOn: empty(existingLogAnalyticsWorkspaceResourceId) ? [ + runbookName: 'aib-build-automation' + scheduleName: varImageTemplateName + } + ] + location: deploymentLocation + runbooks: [ + { + name: 'aib-build-automation' + description: 'When this runbook is triggered, last build date is checked on the AIB image template. If a new marketplace image has been released since that date, a new build is initiated. If a build has never been initiated then it will be start one.' + type: 'PowerShell' + // ToDo: Update URL before PR merge + uri: 'https://raw.githubusercontent.com/Azure/avdaccelerator/main/workload/scripts/New-AzureImageBuilderBuild.ps1' + version: '1.0.0.0' + } + ] + schedules: [ + { + name: varImageTemplateName + frequency: buildSchedule == 'OneTime' ? 'OneTime' : 'Day' + interval: buildSchedule == 'OneTime' ? 0 : 1 + starttime: dateTimeAdd(time, 'PT15M') + varTimeZone: varTimeZone + advancedSchedule: {} // required to prevent deployment failure + } + ] + skuName: 'Free' + tags: enableResourceTags ? varCommonResourceTags : {} + managedIdentities: { + systemAssigned: false + userAssignedResourceIds: [ + userAssignedManagedIdentity.outputs.resourceId + ] + } + } + dependsOn: empty(existingLogAnalyticsWorkspaceResourceId) + ? [ workspace - ] : [] + ] + : [] } // Automation accounts. @batchSize(1) -module modules '../../avm/1.0.0/res/automation/automation-account/module/main.bicep' = [for i in range(0, length(varModules)): { +module modules '../../avm/1.1.0/res/automation/automation-account/module/main.bicep' = [ + for i in range(0, length(varModules)): { scope: resourceGroup(sharedServicesSubId, varResourceGroupName) name: 'AA-Module-${i}-${time}' params: { - name: varModules[i].name - location: deploymentLocation - automationAccountName: automationAccount.outputs.name - uri: varModules[i].uri - version: varModules[i].version + name: varModules[i].name + location: deploymentLocation + automationAccountName: automationAccount.outputs.name + uri: varModules[i].uri + version: varModules[i].version } -}] + } +] // Action groups. -module actionGroup '../../avm/1.0.0/res/insights/action-group/main.bicep' = if (enableMonitoringAlerts) { - scope: resourceGroup(sharedServicesSubId, varResourceGroupName) - name: 'Action-Group-${time}' - params: { - location: 'global' - groupShortName: 'aib-email' - name: varActionGroupName - enabled: true - emailReceivers: [ - { - name: alertsDistributionGroup - emailAddress: alertsDistributionGroup - useCommonvarAlertschema: true - } - ] - tags: enableResourceTags ? varCommonResourceTags : {} - } - dependsOn: [ - avdSharedResourcesRg +module actionGroup '../../avm/1.1.0/res/insights/action-group/main.bicep' = if (enableMonitoringAlerts) { + scope: resourceGroup(sharedServicesSubId, varResourceGroupName) + name: 'Action-Group-${time}' + params: { + location: 'global' + groupShortName: 'aib-email' + name: varActionGroupName + enabled: true + emailReceivers: [ + { + name: alertsDistributionGroup + emailAddress: alertsDistributionGroup + useCommonvarAlertschema: true + } ] + tags: enableResourceTags ? varCommonResourceTags : {} + } + dependsOn: [ + avdSharedResourcesRg + ] } // Schedules. -module scheduledQueryRules '../../avm/1.0.0/res/insights/scheduled-query-rule/main.bicep' = [for i in range(0, length(varAlerts)): if (enableMonitoringAlerts) { +module scheduledQueryRules '../../avm/1.1.0/res/insights/scheduled-query-rule/main.bicep' = [ + for i in range(0, length(varAlerts)): if (enableMonitoringAlerts) { scope: resourceGroup(sharedServicesSubId, varResourceGroupName) name: 'Scheduled-Query-Rule-${i}-${time}' params: { - location: deploymentLocation - name: varAlerts[i].name - alertDescription: varAlerts[i].description - enabled: true - kind: 'LogAlert' - autoMitigate: false - skipQueryValidation: false - targetResourceTypes: [] - roleAssignments: [] - scopes: empty(alertsDistributionGroup) ? [] : empty(existingLogAnalyticsWorkspaceResourceId) ? [ - workspace.outputs.resourceId - ] : [ - existingLogAnalyticsWorkspaceResourceId - ] - severity: varAlerts[i].severity - evaluationFrequency: varAlerts[i].evaluationFrequency - windowSize: varAlerts[i].windowSize - actions: !empty(alertsDistributionGroup) ? [ + location: deploymentLocation + name: varAlerts[i].name + alertDescription: varAlerts[i].description + enabled: true + kind: 'LogAlert' + autoMitigate: false + skipQueryValidation: false + targetResourceTypes: [] + roleAssignments: [] + scopes: empty(alertsDistributionGroup) + ? [] + : empty(existingLogAnalyticsWorkspaceResourceId) + ? [ + workspace.outputs.resourceId + ] + : [ + existingLogAnalyticsWorkspaceResourceId + ] + severity: varAlerts[i].severity + evaluationFrequency: varAlerts[i].evaluationFrequency + windowSize: varAlerts[i].windowSize + actions: !empty(alertsDistributionGroup) + ? [ actionGroup.outputs.resourceId - ] : [] - criterias: varAlerts[i].criterias - tags: enableResourceTags ? varCommonResourceTags : {} - } - dependsOn: empty(existingLogAnalyticsWorkspaceResourceId) ? [ - workspace - ] : [] -}] + ] + : [] + criterias: varAlerts[i].criterias + tags: enableResourceTags ? varCommonResourceTags : {} + } + dependsOn: empty(existingLogAnalyticsWorkspaceResourceId) + ? [ + workspace + ] + : [] + } +] diff --git a/workload/portal-ui/portal-ui-custom-image.json b/workload/portal-ui/portal-ui-custom-image.json index ae506b40b..bda716a53 100644 --- a/workload/portal-ui/portal-ui-custom-image.json +++ b/workload/portal-ui/portal-ui-custom-image.json @@ -29,9 +29,9 @@ "name": "deploymentInfo", "type": "Microsoft.Common.InfoBox", "options": { - "style": "Info", + "style": "Info", "text": "The subscription and region selected below will be used for most of the resources deployed in this solution. The replication regions for the image version will be the only exception and those regions will be defined in the next step. The regions listed in the menu below are the only regions that support Azure Image Builder image templates. Please ensure to select the appropriate options for your environment.", - "uri": "https://learn.microsoft.com/azure/virtual-machines/image-builder-overview?tabs=azure-powershell#regions" + "uri": "https://learn.microsoft.com/azure/virtual-machines/image-builder-overview?tabs=azure-powershell#regions" } } ] @@ -170,55 +170,55 @@ ] }, { - "name": "operatingSystem", + "name": "imageOsSection", "type": "Microsoft.Common.Section", "visible": true, - "label": "Operating system", + "label": "Market place OS selection", "elements": [ { - "name": "versionSelection", + "name": "offer", "type": "Microsoft.Common.DropDown", - "label": "Version", - "filter": true, - "defaultValue": "Windows 11 23H2", - "toolTip": "Select the operating system version for the source image.", + "label": "Offer", + "defaultValue": "Office-365", + "toolTip": "Select the desired marketplace image offer.", "constraints": { - "required": true, "allowedValues": [ { - "label": "Windows 10 22H2 (Gen2)", - "value": "win10_22h2_g2" - }, - { - "label": "Windows 10 22H2 - Office 365 (Gen2)", - "value": "win10_22h2_office_g2" - }, - { - "label": "Windows 11 22H2", - "value": "win11_22h2" - }, - { - "label": "Windows 11 22H2 - Office 365", - "value": "win11_22h2_office" - }, - { - "label": "Windows 11 23H2", - "value": "win11_23h2" + "label": "Office-365", + "value": "office-365" }, { - "label": "Windows 11 23H2 - Office 365", - "value": "win11_23h2_office" + "label": "Windows-10", + "value": "Windows-10" }, { - "label": "Windows 11 24H2", - "value": "win11_24h2" - }, - { - "label": "Windows 11 24H2 - Office 365", - "value": "win11_24h2_office" + "label": "Windows-11", + "value": "windows-11" } - ] + ], + "required": true } + }, + { + "name": "skusApi", + "type": "Microsoft.Solutions.ArmApiControl", + "condition": "", + "request": { + "method": "GET", + "path": "[concat(steps('basics').resourceScope.subscription.id, '/providers/Microsoft.Compute/locations/', steps('basics').resourceScope.location.name, '/publishers/MicrosoftWindowsDesktop/artifacttypes/vmimage/offers/', steps('imageManagement').imageOsSection.offer, '/skus?api-version=2022-08-01')]" + } + }, + { + "name": "sku", + "type": "Microsoft.Common.DropDown", + "label": "SKU", + "defaultValue": "win11-24h2-avd-m365", + "toolTip": "Select the desired marketplace image SKU.", + "constraints": { + "allowedValues": "[map(filter(steps('imageManagement').imageOsSection.skusApi, (sku) => and(startsWith(sku.name, 'win'), not(contains(sku.name, 'ent')), or(contains(sku.name, 'ent'), contains(sku.name, 'avd')))), (sku) => parse(concat('{\"label\":\"', sku.name, '\",\"value\":\"', sku.name, '\"}')))]", + "required": true + }, + "visible": true } ] }, @@ -247,9 +247,9 @@ { "name": "securityType", "type": "Microsoft.Common.DropDown", - "visible": "[or(contains(steps('imageManagement').operatingSystem.versionSelection, 'g2'), contains(steps('imageManagement').operatingSystem.versionSelection, 'win11'))]", + "visible": true, "label": "Security type", - "defaultValue": "Standard", + "defaultValue": "Trusted Launch", "toolTip": "Security type refers to the different security features available for a virtual machine. Security features like Trusted launch and Confidential Virtual Machines help to improve the security of Azure generation 2 virtual machines. However, additional security features have some limitations, which include not supporting back up, managed disks, and ephemeral OS disks. Learn more about Trusted launch virtual machines at https://learn.microsoft.com/en-us/azure/virtual-machines/trusted-launch and Confidential virtual machines at https://learn.microsoft.com/en-us/azure/confidential-computing/confidential-vm-overview.", "constraints": { "required": true, @@ -286,13 +286,13 @@ "type": "Microsoft.Common.TextBlock", "visible": true, "options": { - "text": "The AIB service allows the use of scripts and customizers to automatically create images on demand. This solution will deploy a managed identity and custom RBAC roles to enable AIB.", - "link": { - "label": "Learn more", - "uri": "https://learn.microsoft.com/azure/virtual-machines/image-builder-overview?tabs=azure-powershell" - } + "text": "The AIB service allows the use of scripts and customizers to automatically create images on demand. This solution will deploy a managed identity and custom RBAC roles to enable AIB.", + "link": { + "label": "Learn more", + "uri": "https://learn.microsoft.com/azure/virtual-machines/image-builder-overview?tabs=azure-powershell" + } } - }, + }, { "name": "buildSchedule", "type": "Microsoft.Common.OptionsGroup", @@ -871,7 +871,8 @@ "imageVersionPrimaryLocation": "[steps('imageManagement').imageVersion.primaryLocation]", "imageVersionStorageAccountType": "[steps('imageManagement').imageVersion.storageAccountType]", "logAnalyticsWorkspaceCustomName": "[if(equals(steps('naming').customNamingSelection, true), steps('naming').customNaming.logAnalyticsWorkspace, 'none')]", - "operatingSystemImage": "[steps('imageManagement').operatingSystem.versionSelection]", + "mpImageOffer": "[steps('imageManagement').imageOsSection.offer]", + "mpImageSku": "[steps('imageManagement').imageOsSection.sku]", "operationsTeamTag": "[if(equals(steps('tags').selection, true), steps('tags').customTags.operationsTeam, 'none')]", "ownerTag": "[if(equals(steps('tags').selection, true), steps('tags').customTags.owner, 'none')]", "rdpShortPathManagedNetworks": "[steps('aib').customizers.rdpShortPathSelection]",