diff --git a/.azuredevops/modulePipelines/ms.cognitiveservices.accounts.yml b/.azuredevops/modulePipelines/ms.cognitiveservices.accounts.yml index 56654ea7da..2630458041 100644 --- a/.azuredevops/modulePipelines/ms.cognitiveservices.accounts.yml +++ b/.azuredevops/modulePipelines/ms.cognitiveservices.accounts.yml @@ -47,6 +47,8 @@ stages: deploymentBlocks: - path: $(modulePath)/.parameters/parameters.json - path: $(modulePath)/.parameters/speech.parameters.json + - path: $(modulePath)/.parameters/encr.parameters.json + - path: $(modulePath)/.parameters/min.parameters.json - stage: Publishing displayName: Publishing diff --git a/arm/Microsoft.CognitiveServices/accounts/.parameters/encr.parameters.json b/arm/Microsoft.CognitiveServices/accounts/.parameters/encr.parameters.json new file mode 100644 index 0000000000..082120732a --- /dev/null +++ b/arm/Microsoft.CognitiveServices/accounts/.parameters/encr.parameters.json @@ -0,0 +1,34 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-cgs-encr-001" + }, + "kind": { + "value": "SpeechServices" + }, + "sku": { + "value": "S0" + }, + "userAssignedIdentities": { + "value": { + "/subscriptions/<>/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-<>-az-msi-x-001": {} + } + }, + "publicNetworkAccess": { + "value": "Enabled" + }, + "encryption": { + "value": { + "keySource": "Microsoft.KeyVault", + "keyVaultProperties": { + "identityClientId": "c907a696-36f4-49fe-b926-39e3aabba814", // ID must be updated for new identity + "keyVaultUri": "https://adp-<>-az-kv-nopr-002.vault.azure.net/", + "keyName": "keyEncryptionKey", + "keyversion": "4570a207ec394a0bbbe4fc9adc663a51" // Version must be updated for new keys + } + } + } + } +} diff --git a/arm/Microsoft.CognitiveServices/accounts/.parameters/min.parameters.json b/arm/Microsoft.CognitiveServices/accounts/.parameters/min.parameters.json new file mode 100644 index 0000000000..0f4f624c48 --- /dev/null +++ b/arm/Microsoft.CognitiveServices/accounts/.parameters/min.parameters.json @@ -0,0 +1,12 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-cgs-min-001" + }, + "kind": { + "value": "SpeechServices" + } + } +} diff --git a/arm/Microsoft.CognitiveServices/accounts/.parameters/parameters.json b/arm/Microsoft.CognitiveServices/accounts/.parameters/parameters.json index 9b8a8a07da..c12f36aac5 100644 --- a/arm/Microsoft.CognitiveServices/accounts/.parameters/parameters.json +++ b/arm/Microsoft.CognitiveServices/accounts/.parameters/parameters.json @@ -12,7 +12,7 @@ "value": "Face" }, "sku": { - "value": "F0" + "value": "S0" }, "roleAssignments": { "value": [ @@ -24,6 +24,20 @@ } ] }, + "networkAcls": { + "value": { + "defaultAction": "deny", + "virtualNetworkRules": [ + { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/adp-<>-az-vnet-x-001/subnets/<>-az-subnet-x-001", + "action": "Allow" + } + ] + } + }, + "customSubDomainName": { + "value": "<>xdomain" + }, "systemAssignedIdentity": { "value": true }, diff --git a/arm/Microsoft.CognitiveServices/accounts/.parameters/speech.parameters.json b/arm/Microsoft.CognitiveServices/accounts/.parameters/speech.parameters.json index 489b409bac..7903268ccd 100644 --- a/arm/Microsoft.CognitiveServices/accounts/.parameters/speech.parameters.json +++ b/arm/Microsoft.CognitiveServices/accounts/.parameters/speech.parameters.json @@ -9,7 +9,7 @@ "value": "SpeechServices" }, "sku": { - "value": "F0" + "value": "S0" }, "systemAssignedIdentity": { "value": true @@ -20,7 +20,7 @@ } }, "customSubDomainName": { - "value": "<>domain" + "value": "<>speechdomain" }, "privateEndpoints": { "value": [ diff --git a/arm/Microsoft.CognitiveServices/accounts/deploy.bicep b/arm/Microsoft.CognitiveServices/accounts/deploy.bicep index 17c346d42f..a8dc05ffa1 100644 --- a/arm/Microsoft.CognitiveServices/accounts/deploy.bicep +++ b/arm/Microsoft.CognitiveServices/accounts/deploy.bicep @@ -1,7 +1,7 @@ @description('Required. The name of Cognitive Services account.') param name string -@description('Required. Kind of the Cognitive Services. Use \'Get-AzCognitiveServicesAccountSku\' to determine a valid combinations of \'kind\' and \'sku\' for your Azure region.') +@description('Required. Kind of the Cognitive Services. Use \'Get-AzCognitiveServicesAccountSku\' to determine a valid combinations of \'kind\' and \'SKU\' for your Azure region.') @allowed([ 'AnomalyDetector' 'Bing.Autosuggest.v7' @@ -28,7 +28,7 @@ param name string ]) param kind string -@description('Optional. SKU of the Cognitive Services resource. Use \'Get-AzCognitiveServicesAccountSku\' to determine a valid combinations of \'kind\' and \'sku\' for your Azure region.') +@description('Optional. SKU of the Cognitive Services resource. Use \'Get-AzCognitiveServicesAccountSku\' to determine a valid combinations of \'kind\' and \'SKU\' for your Azure region.') @allowed([ 'C2' 'C3' @@ -70,15 +70,16 @@ param diagnosticEventHubAuthorizationRuleId string = '' @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.') param diagnosticEventHubName string = '' -@description('Conditional. Subdomain name used for token-based authentication. Required if \'networkAcls\' are set.') +@description('Conditional. Subdomain name used for token-based authentication. Required if \'networkAcls\' or \'privateEndpoints\' are set.') param customSubDomainName string = '' @description('Optional. Whether or not public endpoint access is allowed for this account.') @allowed([ + '' 'Enabled' 'Disabled' ]) -param publicNetworkAccess string = 'Enabled' +param publicNetworkAccess string = '' @description('Optional. Service endpoint object information.') param networkAcls object = {} @@ -86,7 +87,7 @@ param networkAcls object = {} @description('Optional. Enables system assigned managed identity on the resource.') param systemAssignedIdentity bool = false -@description('Optional. The ID(s) to assign to the resource.') +@description('Conditional. The ID(s) to assign to the resource. Required if a user assigned identity is used for encryption.') param userAssignedIdentities object = {} @allowed([ @@ -112,8 +113,8 @@ param allowedFqdnList array = [] @description('Optional. The API properties for special APIs.') param apiProperties object = {} -@description('Optional. Allow only Azure AD authentication.') -param disableLocalAuth bool = false +@description('Optional. Allow only Azure AD authentication. Should be enabled for security reasons.') +param disableLocalAuth bool = true @description('Optional. Properties to configure encryption.') param encryption object = {} @@ -182,12 +183,6 @@ var identity = identityType != 'None' ? { userAssignedIdentities: !empty(userAssignedIdentities) ? userAssignedIdentities : null } : null -var networkAcls_var = { - defaultAction: !empty(networkAcls) ? networkAcls.defaultAction : null - virtualNetworkRules: !empty(networkAcls) ? ((length(networkAcls.virtualNetworkRules) == 0) ? [] : networkAcls.virtualNetworkRules) : null - ipRules: !empty(networkAcls) ? ((length(networkAcls.ipRules) == 0) ? [] : networkAcls.ipRules) : null -} - resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' properties: { @@ -211,8 +206,8 @@ resource cognitiveServices 'Microsoft.CognitiveServices/accounts@2021-10-01' = { } properties: { customSubDomainName: !empty(customSubDomainName) ? customSubDomainName : null - networkAcls: !empty(networkAcls) ? networkAcls_var : null - publicNetworkAccess: publicNetworkAccess + networkAcls: networkAcls + publicNetworkAccess: !empty(publicNetworkAccess) ? any(publicNetworkAccess) : (!empty(privateEndpoints) ? 'Disabled' : null) allowedFqdnList: allowedFqdnList apiProperties: apiProperties disableLocalAuth: disableLocalAuth diff --git a/arm/Microsoft.CognitiveServices/accounts/readme.md b/arm/Microsoft.CognitiveServices/accounts/readme.md index 800db10ae6..d6856965e2 100644 --- a/arm/Microsoft.CognitiveServices/accounts/readme.md +++ b/arm/Microsoft.CognitiveServices/accounts/readme.md @@ -26,13 +26,14 @@ This module deploys different kinds of cognitive services resources **Required parameters** | Parameter Name | Type | Allowed Values | Description | | :-- | :-- | :-- | :-- | -| `kind` | string | `[AnomalyDetector, Bing.Autosuggest.v7, Bing.CustomSearch, Bing.EntitySearch, Bing.Search.v7, Bing.SpellCheck.v7, CognitiveServices, ComputerVision, ContentModerator, CustomVision.Prediction, CustomVision.Training, Face, FormRecognizer, ImmersiveReader, Internal.AllInOne, LUIS, LUIS.Authoring, Personalizer, QnAMaker, SpeechServices, TextAnalytics, TextTranslation]` | Kind of the Cognitive Services. Use 'Get-AzCognitiveServicesAccountSku' to determine a valid combinations of 'kind' and 'sku' for your Azure region. | +| `kind` | string | `[AnomalyDetector, Bing.Autosuggest.v7, Bing.CustomSearch, Bing.EntitySearch, Bing.Search.v7, Bing.SpellCheck.v7, CognitiveServices, ComputerVision, ContentModerator, CustomVision.Prediction, CustomVision.Training, Face, FormRecognizer, ImmersiveReader, Internal.AllInOne, LUIS, LUIS.Authoring, Personalizer, QnAMaker, SpeechServices, TextAnalytics, TextTranslation]` | Kind of the Cognitive Services. Use 'Get-AzCognitiveServicesAccountSku' to determine a valid combinations of 'kind' and 'SKU' for your Azure region. | | `name` | string | | The name of Cognitive Services account. | **Conditional parameters** | Parameter Name | Type | Default Value | Description | | :-- | :-- | :-- | :-- | -| `customSubDomainName` | string | `''` | Subdomain name used for token-based authentication. Required if 'networkAcls' are set. | +| `customSubDomainName` | string | `''` | Subdomain name used for token-based authentication. Required if 'networkAcls' or 'privateEndpoints' are set. | +| `userAssignedIdentities` | object | `{object}` | The ID(s) to assign to the resource. Required if a user assigned identity is used for encryption. | **Optional parameters** | Parameter Name | Type | Default Value | Allowed Values | Description | @@ -47,7 +48,7 @@ This module deploys different kinds of cognitive services resources | `diagnosticSettingsName` | string | `[format('{0}-diagnosticSettings', parameters('name'))]` | | The name of the diagnostic setting, if deployed. | | `diagnosticStorageAccountId` | string | `''` | | Resource ID of the diagnostic storage account. | | `diagnosticWorkspaceId` | string | `''` | | Resource ID of the diagnostic log analytics workspace. | -| `disableLocalAuth` | bool | `False` | | Allow only Azure AD authentication. | +| `disableLocalAuth` | bool | `True` | | Allow only Azure AD authentication. Should be enabled for security reasons. | | `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | | `encryption` | object | `{object}` | | Properties to configure encryption. | | `location` | string | `[resourceGroup().location]` | | Location for all Resources. | @@ -55,14 +56,13 @@ This module deploys different kinds of cognitive services resources | `migrationToken` | string | `''` | | Resource migration token. | | `networkAcls` | object | `{object}` | | Service endpoint object information. | | `privateEndpoints` | array | `[]` | | Configuration Details for private endpoints. | -| `publicNetworkAccess` | string | `'Enabled'` | `[Enabled, Disabled]` | Whether or not public endpoint access is allowed for this account. | +| `publicNetworkAccess` | string | `''` | `[, Enabled, Disabled]` | Whether or not public endpoint access is allowed for this account. | | `restore` | bool | `False` | | Restore a soft-deleted cognitive service at deployment time. Will fail if no such soft-deleted resource exists. | | `restrictOutboundNetworkAccess` | bool | `True` | | Restrict outbound network access. | | `roleAssignments` | array | `[]` | | Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, you can provide either the display name of the role definition, or its fully qualified ID in the following format: '/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11'. | -| `sku` | string | `'S0'` | `[C2, C3, C4, F0, F1, S, S0, S1, S10, S2, S3, S4, S5, S6, S7, S8, S9]` | SKU of the Cognitive Services resource. Use 'Get-AzCognitiveServicesAccountSku' to determine a valid combinations of 'kind' and 'sku' for your Azure region. | +| `sku` | string | `'S0'` | `[C2, C3, C4, F0, F1, S, S0, S1, S10, S2, S3, S4, S5, S6, S7, S8, S9]` | SKU of the Cognitive Services resource. Use 'Get-AzCognitiveServicesAccountSku' to determine a valid combinations of 'kind' and 'SKU' for your Azure region. | | `systemAssignedIdentity` | bool | `False` | | Enables system assigned managed identity on the resource. | | `tags` | object | `{object}` | | Tags of the resource. | -| `userAssignedIdentities` | object | `{object}` | | The ID(s) to assign to the resource. | | `userOwnedStorage` | array | `[]` | | The storage accounts for this resource. | @@ -143,6 +143,58 @@ privateEndpoints: [

+### Parameter Usage: `encryption` + +

+ +Parameter JSON format + +```json +// With customer-managed key +"encryption": { + "value": { + "keySource": "Microsoft.KeyVault", + "keyVaultProperties": { + "identityClientId": "c907a696-36f4-49fe-b926-39e3aabba814", // ID must be updated for new identity + "keyVaultUri": "https://adp-<>-az-kv-nopr-002.vault.azure.net/", + "keyName": "keyEncryptionKey", + "keyversion": "4570a207ec394a0bbbe4fc9adc663a51" // ID must be updated for new keys + } + } +} +// With service-managed key +"encryption": { + "value": { + "keySource": "Microsoft.CognitiveServices" + } +} +``` + +
+ +
+ +Bicep format + +```bicep +// With customer managed key +encryption: { + keySource: 'Microsoft.KeyVault' + keyVaultProperties: { + identityClientId: 'c907a696-36f4-49fe-b926-39e3aabba814' // ID must be updated for new identity + keyVaultUri: 'https://adp-<>-az-kv-nopr-002.vault.azure.net/' + keyName: 'keyEncryptionKey' + keyversion: '4570a207ec394a0bbbe4fc9adc663a51' // Version must be updated for new keys + } +} +// With service-managed key +encryption: { + keySource: 'Microsoft.CognitiveServices' +} +``` + +
+

### Parameter Usage: `roleAssignments` Create a role assignment for the given resource. If you want to assign a service principal / managed identity that is created in the same deployment, make sure to also specify the `'principalType'` parameter and set it to `'ServicePrincipal'`. This will ensure the role assignment waits for the principal's propagation in Azure. @@ -347,7 +399,7 @@ userAssignedIdentities: { ## Considerations -- Not all combinations of parameters `kind` and `sku` are valid and they may vary in different Azure Regions. Please use PowerShell CmdLet `Get-AzCognitiveServicesAccountSku` or another methods to determine valid values in your region. +- Not all combinations of parameters `kind` and `SKU` are valid and they may vary in different Azure Regions. Please use PowerShell cmdlet `Get-AzCognitiveServicesAccountSku` or another methods to determine valid values in your region. - Not all kinds of Cognitive Services support virtual networks. Please visit the link below to determine supported services. ## Deployment examples @@ -358,6 +410,122 @@ userAssignedIdentities: {

via JSON Parameter file +```json +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-cgs-encr-001" + }, + "kind": { + "value": "SpeechServices" + }, + "sku": { + "value": "S0" + }, + "userAssignedIdentities": { + "value": { + "/subscriptions/<>/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-<>-az-msi-x-001": {} + } + }, + "publicNetworkAccess": { + "value": "Enabled" + }, + "encryption": { + "value": { + "keySource": "Microsoft.KeyVault", + "keyVaultProperties": { + "identityClientId": "c907a696-36f4-49fe-b926-39e3aabba814", // ID must be updated for new identity + "keyVaultUri": "https://adp-<>-az-kv-nopr-002.vault.azure.net/", + "keyName": "keyEncryptionKey", + "keyversion": "4570a207ec394a0bbbe4fc9adc663a51" // Version must be updated for new keys + } + } + } + } +} + +``` + + + +
+ +via Bicep module + +```bicep +module accounts './Microsoft.CognitiveServices/accounts/deploy.bicep' = { + name: '${uniqueString(deployment().name)}-accounts' + params: { + name: '<>-az-cgs-encr-001' + kind: 'SpeechServices' + sku: 'S0' + userAssignedIdentities: { + '/subscriptions/<>/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-<>-az-msi-x-001': {} + } + publicNetworkAccess: 'Enabled' + encryption: { + keySource: 'Microsoft.KeyVault' + keyVaultProperties: { + identityClientId: 'c907a696-36f4-49fe-b926-39e3aabba814' + keyVaultUri: 'https://adp-<>-az-kv-nopr-002.vault.azure.net/' + keyName: 'keyEncryptionKey' + keyversion: '4570a207ec394a0bbbe4fc9adc663a51' + } + } + } +``` + +
+

+ +

Example 2

+ +
+ +via JSON Parameter file + +```json +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "name": { + "value": "<>-az-cgs-min-001" + }, + "kind": { + "value": "SpeechServices" + } + } +} + +``` + +
+ +
+ +via Bicep module + +```bicep +module accounts './Microsoft.CognitiveServices/accounts/deploy.bicep' = { + name: '${uniqueString(deployment().name)}-accounts' + params: { + name: '<>-az-cgs-min-001' + kind: 'SpeechServices' + } +``` + +
+

+ +

Example 3

+ +
+ +via JSON Parameter file + ```json { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", @@ -373,7 +541,7 @@ userAssignedIdentities: { "value": "Face" }, "sku": { - "value": "F0" + "value": "S0" }, "roleAssignments": { "value": [ @@ -385,6 +553,20 @@ userAssignedIdentities: { } ] }, + "networkAcls": { + "value": { + "defaultAction": "deny", + "virtualNetworkRules": [ + { + "id": "/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/adp-<>-az-vnet-x-001/subnets/<>-az-subnet-x-001", + "action": "Allow" + } + ] + } + }, + "customSubDomainName": { + "value": "<>xdomain" + }, "systemAssignedIdentity": { "value": true }, @@ -426,7 +608,7 @@ module accounts './Microsoft.CognitiveServices/accounts/deploy.bicep' = { name: '<>-az-cgs-x-001' lock: 'CanNotDelete' kind: 'Face' - sku: 'F0' + sku: 'S0' roleAssignments: [ { roleDefinitionIdOrName: 'Reader' @@ -435,6 +617,16 @@ module accounts './Microsoft.CognitiveServices/accounts/deploy.bicep' = { ] } ] + networkAcls: { + defaultAction: 'deny' + virtualNetworkRules: [ + { + id: '/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/adp-<>-az-vnet-x-001/subnets/<>-az-subnet-x-001' + action: 'Allow' + } + ] + } + customSubDomainName: '<>xdomain' systemAssignedIdentity: true userAssignedIdentities: { '/subscriptions/<>/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-<>-az-msi-x-001': {} @@ -450,7 +642,7 @@ module accounts './Microsoft.CognitiveServices/accounts/deploy.bicep' = {

-

Example 2

+

Example 4

@@ -468,7 +660,7 @@ module accounts './Microsoft.CognitiveServices/accounts/deploy.bicep' = { "value": "SpeechServices" }, "sku": { - "value": "F0" + "value": "S0" }, "systemAssignedIdentity": { "value": true @@ -479,7 +671,7 @@ module accounts './Microsoft.CognitiveServices/accounts/deploy.bicep' = { } }, "customSubDomainName": { - "value": "<>domain" + "value": "<>speechdomain" }, "privateEndpoints": { "value": [ @@ -506,12 +698,12 @@ module accounts './Microsoft.CognitiveServices/accounts/deploy.bicep' = { params: { name: '<>-az-cgs-speech-001' kind: 'SpeechServices' - sku: 'F0' + sku: 'S0' systemAssignedIdentity: true userAssignedIdentities: { '/subscriptions/<>/resourcegroups/validation-rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/adp-<>-az-msi-x-001': {} } - customSubDomainName: '<>domain' + customSubDomainName: '<>speechdomain' privateEndpoints: [ { subnetResourceId: '/subscriptions/<>/resourceGroups/validation-rg/providers/Microsoft.Network/virtualNetworks/adp-<>-az-vnet-x-001/subnets/<>-az-subnet-x-005-privateEndpoints' diff --git a/utilities/pipelines/dependencies/Microsoft.Network/virtualNetworks/parameters/parameters.json b/utilities/pipelines/dependencies/Microsoft.Network/virtualNetworks/parameters/parameters.json index d455744dc2..89adeb108c 100644 --- a/utilities/pipelines/dependencies/Microsoft.Network/virtualNetworks/parameters/parameters.json +++ b/utilities/pipelines/dependencies/Microsoft.Network/virtualNetworks/parameters/parameters.json @@ -32,6 +32,9 @@ }, { "service": "Microsoft.KeyVault" + }, + { + "service": "Microsoft.CognitiveServices" } ] },