{ "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", "contentVersion": "1.0.0.0", "metadata": { "_generator": { "name": "bicep", "version": "0.27.1.19265", "templateHash": "5135073006996650384" } }, "parameters": { "workspaceName": { "type": "string", "metadata": { "description": "Specifies the name of the Azure Machine Learning workspace." } }, "location": { "type": "string", "metadata": { "description": "Specifies the location for workspace." } }, "identityType": { "type": "string", "defaultValue": "systemAssigned", "allowedValues": [ "systemAssigned", "userAssigned", "systemAssigned,userAssigned" ], "metadata": { "description": "Specifies the identity type of the Azure Machine Learning workspace." } }, "primaryUserAssignedIdentityResourceGroup": { "type": "string", "defaultValue": "[resourceGroup().name]", "metadata": { "description": "Specifies the resource group of user assigned identity that represents the Azure Machine Learing workspace." } }, "primaryUserAssignedIdentityName": { "type": "string", "defaultValue": "", "metadata": { "description": "Specifies the name of user assigned identity that represents the Azure Machine Learing workspace." } }, "cmkUserAssignedIdentityResourceGroup": { "type": "string", "defaultValue": "[resourceGroup().name]", "metadata": { "description": "Specifies the resource group of user assigned identity that needs to be used to access the key for encryption." } }, "cmkUserAssignedIdentityName": { "type": "string", "defaultValue": "", "metadata": { "description": "Specifies the name of user assigned identity that needs to be used to access the key for encryption." } }, "tagValues": { "type": "object", "defaultValue": {}, "metadata": { "description": "Tags for workspace, will also be populated if provisioning new dependent resources." } }, "storageAccountOption": { "type": "string", "defaultValue": "new", "allowedValues": [ "new", "existing" ], "metadata": { "description": "Determines whether or not a new storage should be provisioned." } }, "storageAccountName": { "type": "string", "defaultValue": "[format('sa{0}', uniqueString(resourceGroup().id, parameters('workspaceName')))]", "metadata": { "description": "Name of the storage account." } }, "storageAccountType": { "type": "string", "defaultValue": "Standard_LRS", "allowedValues": [ "Standard_LRS", "Standard_GRS", "Standard_RAGRS", "Standard_ZRS", "Standard_GZRS", "Standard_RAGZRS" ] }, "storageAccountBehindVNet": { "type": "string", "defaultValue": "false", "allowedValues": [ "true", "false" ], "metadata": { "description": "Determines whether or not to put the storage account behind VNet" } }, "storageAccountResourceGroupName": { "type": "string", "defaultValue": "[resourceGroup().name]", "metadata": { "description": "Resource group name of the storage account if using existing one" } }, "keyVaultOption": { "type": "string", "defaultValue": "new", "allowedValues": [ "new", "existing" ], "metadata": { "description": "Determines whether or not a new key vault should be provisioned." } }, "keyVaultName": { "type": "string", "defaultValue": "[format('kv{0}', uniqueString(resourceGroup().id, parameters('workspaceName')))]", "metadata": { "description": "Name of the key vault." } }, "keyVaultBehindVNet": { "type": "string", "defaultValue": "false", "allowedValues": [ "true", "false" ], "metadata": { "description": "Determines whether or not to put the storage account behind VNet" } }, "keyVaultResourceGroupName": { "type": "string", "defaultValue": "[resourceGroup().name]", "metadata": { "description": "Resource group name of the key vault if using existing one" } }, "applicationInsightsOption": { "type": "string", "defaultValue": "new", "allowedValues": [ "new", "existing" ], "metadata": { "description": "Determines whether or not new ApplicationInsights should be provisioned." } }, "applicationInsightsName": { "type": "string", "defaultValue": "[format('ai{0}', uniqueString(resourceGroup().id, parameters('workspaceName')))]", "metadata": { "description": "Name of ApplicationInsights." } }, "applicationInsightsResourceGroupName": { "type": "string", "defaultValue": "[resourceGroup().name]", "metadata": { "description": "Resource group name of the application insights if using existing one." } }, "containerRegistryOption": { "type": "string", "defaultValue": "none", "allowedValues": [ "new", "existing", "none" ], "metadata": { "description": "Determines whether or not a new container registry should be provisioned." } }, "containerRegistryName": { "type": "string", "defaultValue": "[format('cr{0}', uniqueString(resourceGroup().id, parameters('workspaceName')))]", "metadata": { "description": "The container registry bind to the workspace." } }, "containerRegistrySku": { "type": "string", "defaultValue": "Standard", "allowedValues": [ "Basic", "Standard", "Premium" ] }, "containerRegistryResourceGroupName": { "type": "string", "defaultValue": "[resourceGroup().name]", "metadata": { "description": "Resource group name of the container registry if using existing one." } }, "containerRegistryBehindVNet": { "type": "string", "defaultValue": "false", "allowedValues": [ "true", "false" ], "metadata": { "description": "Determines whether or not to put container registry behind VNet." } }, "vnetOption": { "type": "string", "defaultValue": "[if(equals(parameters('privateEndpointType'), 'none'), 'none', 'new')]", "allowedValues": [ "new", "existing", "none" ], "metadata": { "description": "Determines whether or not a new VNet should be provisioned." } }, "vnetName": { "type": "string", "defaultValue": "[format('vn{0}', uniqueString(resourceGroup().id, parameters('workspaceName')))]", "metadata": { "description": "Name of the VNet" } }, "vnetResourceGroupName": { "type": "string", "defaultValue": "[resourceGroup().name]", "metadata": { "description": "Resource group name of the VNET if using existing one." } }, "vnetLocation": { "type": "string", "defaultValue": "[parameters('location')]", "metadata": { "description": "Required if existing VNET location differs from workspace location" } }, "addressPrefixes": { "type": "array", "defaultValue": [ "10.0.0.0/16" ], "metadata": { "description": "Address prefix of the virtual network" } }, "subnetOption": { "type": "string", "defaultValue": "[if(or(not(equals(parameters('privateEndpointType'), 'none')), equals(parameters('vnetOption'), 'new')), 'new', 'none')]", "allowedValues": [ "new", "existing", "none" ], "metadata": { "description": "Determines whether or not a new subnet should be provisioned." } }, "subnetName": { "type": "string", "defaultValue": "[format('sn{0}', uniqueString(resourceGroup().id, parameters('workspaceName')))]", "metadata": { "description": "Name of the subnet" } }, "subnetPrefix": { "type": "string", "defaultValue": "10.0.0.0/24", "metadata": { "description": "Subnet prefix of the virtual network" } }, "adbWorkspaceId": { "type": "string", "defaultValue": "", "metadata": { "description": "Azure Databrick workspace to be linked to the workspace" } }, "confidential_data": { "type": "bool", "defaultValue": false, "allowedValues": [ false, true ], "metadata": { "description": "Specifies that the Azure Machine Learning workspace holds highly confidential data." } }, "encryption_status": { "type": "string", "defaultValue": "Disabled", "allowedValues": [ "Enabled", "Disabled" ], "metadata": { "description": "Specifies if the Azure Machine Learning workspace should be encrypted with customer managed key." } }, "cmk_keyvault": { "type": "string", "defaultValue": "", "metadata": { "description": "Specifies the customer managed keyVault arm id. Required when encryption is enabled" } }, "resource_cmk_uri": { "type": "string", "defaultValue": "", "metadata": { "description": "Specifies if the customer managed keyvault key uri. Required when encryption is enabled" } }, "privateEndpointType": { "type": "string", "defaultValue": "none", "allowedValues": [ "AutoApproval", "ManualApproval", "none" ] } }, "variables": { "tenantId": "[subscription().tenantId]", "storageAccountId": "[resourceId(parameters('storageAccountResourceGroupName'), 'Microsoft.Storage/storageAccounts', parameters('storageAccountName'))]", "keyVaultId": "[resourceId(parameters('keyVaultResourceGroupName'), 'Microsoft.KeyVault/vaults', parameters('keyVaultName'))]", "containerRegistryId": "[resourceId(parameters('containerRegistryResourceGroupName'), 'Microsoft.ContainerRegistry/registries', parameters('containerRegistryName'))]", "applicationInsightId": "[resourceId(parameters('applicationInsightsResourceGroupName'), 'Microsoft.Insights/components', parameters('applicationInsightsName'))]", "vnetId": "[resourceId(parameters('vnetResourceGroupName'), 'Microsoft.Network/virtualNetworks', parameters('vnetName'))]", "subnetId": "[resourceId(parameters('vnetResourceGroupName'), 'Microsoft.Network/virtualNetworks/subnets', parameters('vnetName'), parameters('subnetName'))]", "privateDnsZoneName": { "azureusgovernment": "privatelink.api.ml.azure.us", "azurechinacloud": "privatelink.api.ml.azure.cn", "azurecloud": "privatelink.api.azureml.ms" }, "privateAznbDnsZoneName": { "azureusgovernment": "privatelink.notebooks.usgovcloudapi.net", "azurecloud": "privatelink.notebooks.azure.net", "azurechinacloud": "privatelink.notebooks.chinacloudapi.cn" }, "enablePE": "[not(equals(parameters('privateEndpointType'), 'none'))]", "networkRuleSetBehindVNet": { "defaultAction": "deny", "virtualNetworkRules": [ { "action": "Allow", "id": "[variables('subnetId')]" } ] }, "serviceEndpointsAll": [ { "service": "Microsoft.Storage" }, { "service": "Microsoft.KeyVault" }, { "service": "Microsoft.ContainerRegistry" } ], "serviceEndpointsAzureChinaCloud": [ { "service": "Microsoft.Storage" }, { "service": "Microsoft.KeyVault" } ], "privateEndpointSettings": { "name": "[format('{0}-PrivateEndpoint', parameters('workspaceName'))]", "properties": { "privateLinkServiceId": "[resourceId('Microsoft.MachineLearningServices/workspaces', parameters('workspaceName'))]", "groupIds": [ "amlworkspace" ] } }, "defaultPEConnections": "[array(variables('privateEndpointSettings'))]", "userAssignedIdentities": "[union(variables('userAssignedIdentitiesPrimary'), variables('userAssignedIdentitiesCmk'))]", "userAssignedIdentityPrimary": { "[format('{0}', variables('primaryUserAssignedIdentity'))]": {} }, "userAssignedIdentitiesPrimary": "[if(not(equals(parameters('primaryUserAssignedIdentityName'), '')), variables('userAssignedIdentityPrimary'), json('{}'))]", "primaryUserAssignedIdentity": "[resourceId(parameters('primaryUserAssignedIdentityResourceGroup'), 'Microsoft.ManagedIdentity/userAssignedIdentities', parameters('primaryUserAssignedIdentityName'))]", "userAssignedIdentityCmk": { "[format('{0}', variables('cmkUserAssignedIdentity'))]": {} }, "userAssignedIdentitiesCmk": "[if(not(equals(parameters('cmkUserAssignedIdentityName'), '')), variables('userAssignedIdentityCmk'), json('{}'))]", "cmkUserAssignedIdentity": "[resourceId(parameters('cmkUserAssignedIdentityResourceGroup'), 'Microsoft.ManagedIdentity/userAssignedIdentities', parameters('cmkUserAssignedIdentityName'))]", "encryptionUserAssignedIdentity": { "userAssignedIdentity": "[variables('cmkUserAssignedIdentity')]" }, "encryptionIdentity": "[if(not(equals(parameters('cmkUserAssignedIdentityName'), '')), variables('encryptionUserAssignedIdentity'), json('{}'))]", "appInsightsLocation": "[if(or(or(or(equals(parameters('location'), 'westcentralus'), equals(parameters('location'), 'eastus2euap')), equals(parameters('location'), 'centraluseuap')), equals(parameters('location'), 'westus3')), 'southcentralus', if(equals(parameters('location'), 'canadaeast'), 'canadacentral', if(equals(parameters('location'), 'qatarcentral'), 'uaenorth', if(equals(parameters('location'), 'spaincentral'), 'francecentral', parameters('location')))))]" }, "resources": [ { "condition": "[equals(parameters('vnetOption'), 'new')]", "type": "Microsoft.Network/virtualNetworks", "apiVersion": "2022-05-01", "name": "[parameters('vnetName')]", "location": "[parameters('location')]", "tags": "[parameters('tagValues')]", "properties": { "addressSpace": { "addressPrefixes": "[parameters('addressPrefixes')]" }, "enableDdosProtection": false, "enableVmProtection": false } }, { "condition": "[equals(parameters('subnetOption'), 'new')]", "type": "Microsoft.Network/virtualNetworks/subnets", "apiVersion": "2022-05-01", "name": "[format('{0}/{1}', parameters('vnetName'), parameters('subnetName'))]", "properties": { "addressPrefix": "[parameters('subnetPrefix')]", "privateLinkServiceNetworkPolicies": "Enabled", "serviceEndpoints": "[if(equals(toLower(environment().name), 'azurechinacloud'), variables('serviceEndpointsAzureChinaCloud'), variables('serviceEndpointsAll'))]" }, "dependsOn": [ "[resourceId('Microsoft.Network/virtualNetworks', parameters('vnetName'))]" ] }, { "condition": "[equals(parameters('storageAccountOption'), 'new')]", "type": "Microsoft.Storage/storageAccounts", "apiVersion": "2022-05-01", "name": "[parameters('storageAccountName')]", "location": "[parameters('location')]", "sku": { "name": "[parameters('storageAccountType')]" }, "kind": "StorageV2", "tags": "[parameters('tagValues')]", "properties": { "encryption": { "services": { "blob": { "enabled": true }, "file": { "enabled": true } }, "keySource": "Microsoft.Storage" }, "supportsHttpsTrafficOnly": true, "minimumTlsVersion": "TLS1_2", "allowBlobPublicAccess": false, "networkAcls": "[if(equals(parameters('storageAccountBehindVNet'), 'true'), variables('networkRuleSetBehindVNet'), json('null'))]" }, "dependsOn": [ "[resourceId('Microsoft.Network/virtualNetworks/subnets', parameters('vnetName'), parameters('subnetName'))]" ] }, { "condition": "[equals(parameters('keyVaultOption'), 'new')]", "type": "Microsoft.KeyVault/vaults", "apiVersion": "2022-07-01", "name": "[parameters('keyVaultName')]", "location": "[parameters('location')]", "tags": "[parameters('tagValues')]", "properties": { "tenantId": "[variables('tenantId')]", "sku": { "name": "standard", "family": "A" }, "accessPolicies": [], "networkAcls": "[if(equals(parameters('keyVaultBehindVNet'), 'true'), variables('networkRuleSetBehindVNet'), json('null'))]" }, "dependsOn": [ "[resourceId('Microsoft.Network/virtualNetworks/subnets', parameters('vnetName'), parameters('subnetName'))]" ] }, { "condition": "[equals(parameters('containerRegistryOption'), 'new')]", "type": "Microsoft.ContainerRegistry/registries", "apiVersion": "2022-02-01-preview", "name": "[parameters('containerRegistryName')]", "location": "[parameters('location')]", "sku": { "name": "[parameters('containerRegistrySku')]" }, "tags": "[parameters('tagValues')]", "properties": { "adminUserEnabled": true, "networkRuleSet": "[if(equals(parameters('containerRegistryBehindVNet'), 'true'), variables('networkRuleSetBehindVNet'), json('null'))]" }, "dependsOn": [ "[resourceId('Microsoft.Network/virtualNetworks/subnets', parameters('vnetName'), parameters('subnetName'))]" ] }, { "condition": "[equals(parameters('applicationInsightsOption'), 'new')]", "type": "Microsoft.Insights/components", "apiVersion": "2020-02-02", "name": "[parameters('applicationInsightsName')]", "location": "[variables('appInsightsLocation')]", "kind": "web", "tags": "[parameters('tagValues')]", "properties": { "Application_Type": "web" } }, { "type": "Microsoft.MachineLearningServices/workspaces", "apiVersion": "2022-10-01", "name": "[parameters('workspaceName')]", "location": "[parameters('location')]", "identity": { "type": "[parameters('identityType')]", "userAssignedIdentities": "[if(or(equals(parameters('identityType'), 'userAssigned'), equals(parameters('identityType'), 'systemAssigned,userAssigned')), variables('userAssignedIdentities'), json('null'))]" }, "tags": "[parameters('tagValues')]", "properties": { "friendlyName": "[parameters('workspaceName')]", "storageAccount": "[variables('storageAccountId')]", "keyVault": "[variables('keyVaultId')]", "applicationInsights": "[variables('applicationInsightId')]", "containerRegistry": "[if(not(equals(parameters('containerRegistryOption'), 'none')), variables('containerRegistryId'), json('null'))]", "adbWorkspace": "[if(equals(parameters('adbWorkspaceId'), ''), json('null'), parameters('adbWorkspaceId'))]", "primaryUserAssignedIdentity": "[if(equals(parameters('identityType'), 'userAssigned'), variables('primaryUserAssignedIdentity'), json('null'))]", "encryption": { "status": "[parameters('encryption_status')]", "identity": "[variables('encryptionIdentity')]", "keyVaultProperties": { "keyVaultArmId": "[parameters('cmk_keyvault')]", "keyIdentifier": "[parameters('resource_cmk_uri')]" } }, "hbiWorkspace": "[parameters('confidential_data')]", "publicNetworkAccess": "Disabled" }, "dependsOn": [ "[resourceId('Microsoft.Insights/components', parameters('applicationInsightsName'))]", "[resourceId('Microsoft.ContainerRegistry/registries', parameters('containerRegistryName'))]", "[resourceId('Microsoft.Storage/storageAccounts', parameters('storageAccountName'))]", "[resourceId('Microsoft.KeyVault/vaults', parameters('keyVaultName'))]" ] }, { "type": "Microsoft.Resources/deployments", "apiVersion": "2022-09-01", "name": "DeployPrivateEndpoints", "resourceGroup": "[parameters('vnetResourceGroupName')]", "properties": { "expressionEvaluationOptions": { "scope": "inner" }, "mode": "Incremental", "parameters": { "enablePE": { "value": "[variables('enablePE')]" }, "defaultPEConnections": { "value": "[variables('defaultPEConnections')]" }, "subnetId": { "value": "[variables('subnetId')]" }, "privateDnsZoneName": { "value": "[variables('privateDnsZoneName')]" }, "privateAznbDnsZoneName": { "value": "[variables('privateAznbDnsZoneName')]" }, "vnetId": { "value": "[variables('vnetId')]" }, "workspaceName": { "value": "[parameters('workspaceName')]" }, "vnetLocation": { "value": "[parameters('vnetLocation')]" }, "tagValues": { "value": "[parameters('tagValues')]" }, "privateEndpointType": { "value": "[parameters('privateEndpointType')]" } }, "template": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", "contentVersion": "1.0.0.0", "metadata": { "_generator": { "name": "bicep", "version": "0.27.1.19265", "templateHash": "9570492630025719683" } }, "parameters": { "enablePE": { "type": "bool" }, "defaultPEConnections": { "type": "array" }, "subnetId": { "type": "string" }, "privateDnsZoneName": { "type": "object" }, "privateAznbDnsZoneName": { "type": "object" }, "vnetId": { "type": "string" }, "workspaceName": { "type": "string", "metadata": { "description": "Specifies the name of the Azure Machine Learning workspace." } }, "vnetLocation": { "type": "string", "metadata": { "description": "Required if existing VNET location differs from workspace location" } }, "tagValues": { "type": "object", "metadata": { "description": "Tags for workspace, will also be populated if provisioning new dependent resources." } }, "privateEndpointType": { "type": "string", "allowedValues": [ "AutoApproval", "ManualApproval", "none" ] } }, "resources": [ { "condition": "[parameters('enablePE')]", "type": "Microsoft.Network/privateEndpoints", "apiVersion": "2022-05-01", "name": "[format('{0}-PrivateEndpoint', parameters('workspaceName'))]", "location": "[parameters('vnetLocation')]", "tags": "[parameters('tagValues')]", "properties": { "privateLinkServiceConnections": "[if(equals(parameters('privateEndpointType'), 'AutoApproval'), parameters('defaultPEConnections'), json('null'))]", "manualPrivateLinkServiceConnections": "[if(equals(parameters('privateEndpointType'), 'ManualApproval'), parameters('defaultPEConnections'), json('null'))]", "subnet": { "id": "[parameters('subnetId')]" } } }, { "condition": "[equals(parameters('privateEndpointType'), 'AutoApproval')]", "type": "Microsoft.Network/privateDnsZones", "apiVersion": "2020-06-01", "name": "[parameters('privateDnsZoneName')[toLower(environment().name)]]", "location": "global", "tags": "[parameters('tagValues')]", "properties": {}, "dependsOn": [ "[resourceId('Microsoft.Network/privateEndpoints', format('{0}-PrivateEndpoint', parameters('workspaceName')))]" ] }, { "condition": "[equals(parameters('privateEndpointType'), 'AutoApproval')]", "type": "Microsoft.Network/privateDnsZones", "apiVersion": "2020-06-01", "name": "[parameters('privateAznbDnsZoneName')[toLower(environment().name)]]", "location": "global", "tags": "[parameters('tagValues')]", "properties": {}, "dependsOn": [ "[resourceId('Microsoft.Network/privateEndpoints', format('{0}-PrivateEndpoint', parameters('workspaceName')))]" ] }, { "condition": "[equals(parameters('privateEndpointType'), 'AutoApproval')]", "type": "Microsoft.Network/privateDnsZones/virtualNetworkLinks", "apiVersion": "2020-06-01", "name": "[format('{0}/{1}', parameters('privateDnsZoneName')[toLower(environment().name)], uniqueString(parameters('vnetId')))]", "location": "global", "tags": "[parameters('tagValues')]", "properties": { "virtualNetwork": { "id": "[parameters('vnetId')]" }, "registrationEnabled": false }, "dependsOn": [ "[resourceId('Microsoft.Network/privateDnsZones', parameters('privateDnsZoneName')[toLower(environment().name)])]", "[resourceId('Microsoft.Network/privateEndpoints', format('{0}-PrivateEndpoint', parameters('workspaceName')))]" ] }, { "condition": "[equals(parameters('privateEndpointType'), 'AutoApproval')]", "type": "Microsoft.Network/privateDnsZones/virtualNetworkLinks", "apiVersion": "2020-06-01", "name": "[format('{0}/{1}', parameters('privateAznbDnsZoneName')[toLower(environment().name)], uniqueString(parameters('vnetId')))]", "location": "global", "tags": "[parameters('tagValues')]", "properties": { "virtualNetwork": { "id": "[parameters('vnetId')]" }, "registrationEnabled": false }, "dependsOn": [ "[resourceId('Microsoft.Network/privateDnsZones', parameters('privateAznbDnsZoneName')[toLower(environment().name)])]", "[resourceId('Microsoft.Network/privateEndpoints', format('{0}-PrivateEndpoint', parameters('workspaceName')))]" ] }, { "condition": "[equals(parameters('privateEndpointType'), 'AutoApproval')]", "type": "Microsoft.Network/privateEndpoints/privateDnsZoneGroups", "apiVersion": "2022-05-01", "name": "[format('{0}/{1}', format('{0}-PrivateEndpoint', parameters('workspaceName')), 'default')]", "properties": { "privateDnsZoneConfigs": [ { "name": "privatelink-api-azureml-ms", "properties": { "privateDnsZoneId": "[resourceId('Microsoft.Network/privateDnsZones', parameters('privateDnsZoneName')[toLower(environment().name)])]" } }, { "name": "privatelink-notebooks-azure-net", "properties": { "privateDnsZoneId": "[resourceId('Microsoft.Network/privateDnsZones', parameters('privateAznbDnsZoneName')[toLower(environment().name)])]" } } ] }, "dependsOn": [ "[resourceId('Microsoft.Network/privateDnsZones', parameters('privateAznbDnsZoneName')[toLower(environment().name)])]", "[resourceId('Microsoft.Network/privateDnsZones', parameters('privateDnsZoneName')[toLower(environment().name)])]", "[resourceId('Microsoft.Network/privateEndpoints', format('{0}-PrivateEndpoint', parameters('workspaceName')))]" ] } ] } }, "dependsOn": [ "[resourceId('Microsoft.MachineLearningServices/workspaces', parameters('workspaceName'))]" ] } ] }