Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: Add key vault to cognitive service - avm/res/cognitive-services/account #3222

Merged
merged 3 commits into from
Sep 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
137 changes: 123 additions & 14 deletions avm/res/cognitive-services/account/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ This module deploys a Cognitive Service.
| `Microsoft.CognitiveServices/accounts` | [2023-05-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.CognitiveServices/2023-05-01/accounts) |
| `Microsoft.CognitiveServices/accounts/deployments` | [2023-05-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.CognitiveServices/2023-05-01/accounts/deployments) |
| `Microsoft.Insights/diagnosticSettings` | [2021-05-01-preview](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Insights/2021-05-01-preview/diagnosticSettings) |
| `Microsoft.KeyVault/vaults/secrets` | [2023-07-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.KeyVault/2023-07-01/vaults/secrets) |
| `Microsoft.Network/privateEndpoints` | [2023-11-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Network/2023-11-01/privateEndpoints) |
| `Microsoft.Network/privateEndpoints/privateDnsZoneGroups` | [2023-11-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Network/2023-11-01/privateEndpoints/privateDnsZoneGroups) |

Expand All @@ -33,13 +34,14 @@ The following section provides usage examples for the module, which were used to

- [Using `AIServices` with `deployments` in parameter set and private endpoints](#example-1-using-aiservices-with-deployments-in-parameter-set-and-private-endpoints)
- [Using `AIServices` with `deployments` in parameter set](#example-2-using-aiservices-with-deployments-in-parameter-set)
- [Using only defaults](#example-3-using-only-defaults)
- [Using large parameter set](#example-4-using-large-parameter-set)
- [Using `OpenAI` and `deployments` in parameter set with private endpoint](#example-5-using-openai-and-deployments-in-parameter-set-with-private-endpoint)
- [As Speech Service](#example-6-as-speech-service)
- [Using Customer-Managed-Keys with System-Assigned identity](#example-7-using-customer-managed-keys-with-system-assigned-identity)
- [Using Customer-Managed-Keys with User-Assigned identity](#example-8-using-customer-managed-keys-with-user-assigned-identity)
- [WAF-aligned](#example-9-waf-aligned)
- [Storing keys of service in key vault](#example-3-storing-keys-of-service-in-key-vault)
- [Using only defaults](#example-4-using-only-defaults)
- [Using large parameter set](#example-5-using-large-parameter-set)
- [Using `OpenAI` and `deployments` in parameter set with private endpoint](#example-6-using-openai-and-deployments-in-parameter-set-with-private-endpoint)
- [As Speech Service](#example-7-as-speech-service)
- [Using Customer-Managed-Keys with System-Assigned identity](#example-8-using-customer-managed-keys-with-system-assigned-identity)
- [Using Customer-Managed-Keys with User-Assigned identity](#example-9-using-customer-managed-keys-with-user-assigned-identity)
- [WAF-aligned](#example-10-waf-aligned)

### Example 1: _Using `AIServices` with `deployments` in parameter set and private endpoints_

Expand Down Expand Up @@ -237,7 +239,71 @@ module account 'br/public:avm/res/cognitive-services/account:<version>' = {
</details>
<p>

### Example 3: _Using only defaults_
### Example 3: _Storing keys of service in key vault_

This instance deploys the module and stores its keys in a key vault.


<details>

<summary>via Bicep module</summary>

```bicep
module account 'br/public:avm/res/cognitive-services/account:<version>' = {
name: 'accountDeployment'
params: {
// Required parameters
kind: 'SpeechServices'
name: 'csakv001'
// Non-required parameters
location: '<location>'
secretsExportConfiguration: {
accessKey1Name: 'csakv001-accessKey1'
accessKey2Name: 'csakv001-accessKey2'
keyVaultResourceId: '<keyVaultResourceId>'
}
}
}
```

</details>
<p>

<details>

<summary>via JSON Parameter file</summary>

```json
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#",
"contentVersion": "1.0.0.0",
"parameters": {
// Required parameters
"kind": {
"value": "SpeechServices"
},
"name": {
"value": "csakv001"
},
// Non-required parameters
"location": {
"value": "<location>"
},
"secretsExportConfiguration": {
"value": {
"accessKey1Name": "csakv001-accessKey1",
"accessKey2Name": "csakv001-accessKey2",
"keyVaultResourceId": "<keyVaultResourceId>"
}
}
}
}
```

</details>
<p>

### Example 4: _Using only defaults_

This instance deploys the module with the minimum set of required parameters.

Expand Down Expand Up @@ -289,7 +355,7 @@ module account 'br/public:avm/res/cognitive-services/account:<version>' = {
</details>
<p>

### Example 4: _Using large parameter set_
### Example 5: _Using large parameter set_

This instance deploys the module with most of its features enabled.

Expand Down Expand Up @@ -581,7 +647,7 @@ module account 'br/public:avm/res/cognitive-services/account:<version>' = {
</details>
<p>

### Example 5: _Using `OpenAI` and `deployments` in parameter set with private endpoint_
### Example 6: _Using `OpenAI` and `deployments` in parameter set with private endpoint_

This instance deploys the module with the AI model deployment feature and private endpoint.

Expand Down Expand Up @@ -689,7 +755,7 @@ module account 'br/public:avm/res/cognitive-services/account:<version>' = {
</details>
<p>

### Example 6: _As Speech Service_
### Example 7: _As Speech Service_

This instance deploys the module as a Speech Service.

Expand Down Expand Up @@ -803,7 +869,7 @@ module account 'br/public:avm/res/cognitive-services/account:<version>' = {
</details>
<p>

### Example 7: _Using Customer-Managed-Keys with System-Assigned identity_
### Example 8: _Using Customer-Managed-Keys with System-Assigned identity_

This instance deploys the module using Customer-Managed-Keys using a System-Assigned Identity. This required the service to be deployed twice, once as a pre-requisite to create the System-Assigned Identity, and once to use it for accessing the Customer-Managed-Key secret.

Expand Down Expand Up @@ -885,7 +951,7 @@ module account 'br/public:avm/res/cognitive-services/account:<version>' = {
</details>
<p>

### Example 8: _Using Customer-Managed-Keys with User-Assigned identity_
### Example 9: _Using Customer-Managed-Keys with User-Assigned identity_

This instance deploys the module using Customer-Managed-Keys using a User-Assigned Identity to access the Customer-Managed-Key secret.

Expand Down Expand Up @@ -973,7 +1039,7 @@ module account 'br/public:avm/res/cognitive-services/account:<version>' = {
</details>
<p>

### Example 9: _WAF-aligned_
### Example 10: _WAF-aligned_

This instance deploys the module in alignment with the best-practices of the Azure Well-Architected Framework.

Expand Down Expand Up @@ -1146,6 +1212,7 @@ module account 'br/public:avm/res/cognitive-services/account:<version>' = {
| [`restore`](#parameter-restore) | bool | Restore a soft-deleted cognitive service at deployment time. Will fail if no such soft-deleted resource exists. |
| [`restrictOutboundNetworkAccess`](#parameter-restrictoutboundnetworkaccess) | bool | Restrict outbound network access. |
| [`roleAssignments`](#parameter-roleassignments) | array | Array of role assignments to create. |
| [`secretsExportConfiguration`](#parameter-secretsexportconfiguration) | object | Key vault reference and secret settings for the module's secrets export. |
| [`sku`](#parameter-sku) | string | SKU of the Cognitive Services resource. Use 'Get-AzCognitiveServicesAccountSku' to determine a valid combinations of 'kind' and 'SKU' for your Azure region. |
| [`tags`](#parameter-tags) | object | Tags of the resource. |
| [`userOwnedStorage`](#parameter-userownedstorage) | array | The storage accounts for this resource. |
Expand Down Expand Up @@ -2101,6 +2168,47 @@ The principal type of the assigned principal ID.
]
```

### Parameter: `secretsExportConfiguration`

Key vault reference and secret settings for the module's secrets export.

- Required: No
- Type: object

**Required parameters**

| Parameter | Type | Description |
| :-- | :-- | :-- |
| [`keyVaultResourceId`](#parameter-secretsexportconfigurationkeyvaultresourceid) | string | The key vault name where to store the keys and connection strings generated by the modules. |

**Optional parameters**

| Parameter | Type | Description |
| :-- | :-- | :-- |
| [`accessKey1Name`](#parameter-secretsexportconfigurationaccesskey1name) | string | The name for the accessKey1 secret to create. |
| [`accessKey2Name`](#parameter-secretsexportconfigurationaccesskey2name) | string | The name for the accessKey2 secret to create. |

### Parameter: `secretsExportConfiguration.keyVaultResourceId`

The key vault name where to store the keys and connection strings generated by the modules.

- Required: Yes
- Type: string

### Parameter: `secretsExportConfiguration.accessKey1Name`

The name for the accessKey1 secret to create.

- Required: No
- Type: string

### Parameter: `secretsExportConfiguration.accessKey2Name`

The name for the accessKey2 secret to create.

- Required: No
- Type: string

### Parameter: `sku`

SKU of the Cognitive Services resource. Use 'Get-AzCognitiveServicesAccountSku' to determine a valid combinations of 'kind' and 'SKU' for your Azure region.
Expand Down Expand Up @@ -2151,6 +2259,7 @@ The storage accounts for this resource.
| :-- | :-- | :-- |
| `endpoint` | string | The service endpoint of the cognitive services account. |
| `endpoints` | | All endpoints available for the cognitive services account, types depends on the cognitive service kind. |
| `exportedSecrets` | | A hashtable of references to the secrets exported to the provided Key Vault. The key of each reference is each secret's name. |
| `location` | string | The location the resource was deployed into. |
| `name` | string | The name of the cognitive services account. |
| `resourceGroupName` | string | The resource group the cognitive services account was deployed into. |
Expand Down
55 changes: 55 additions & 0 deletions avm/res/cognitive-services/account/main.bicep
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,9 @@ param enableTelemetry bool = true
@description('Optional. Array of deployments about cognitive service accounts to create.')
param deployments deploymentsType

@description('Optional. Key vault reference and secret settings for the module\'s secrets export.')
param secretsExportConfiguration secretsExportConfigurationType?

var formattedUserAssignedIdentities = reduce(
map((managedIdentities.?userAssignedResourceIds ?? []), (id) => { '${id}': {} }),
{},
Expand Down Expand Up @@ -468,6 +471,36 @@ resource cognitiveService_roleAssignments 'Microsoft.Authorization/roleAssignmen
}
]

module secretsExport 'modules/keyVaultExport.bicep' = if (secretsExportConfiguration != null) {
name: '${uniqueString(deployment().name, location)}-secrets-kv'
scope: resourceGroup(
split((secretsExportConfiguration.?keyVaultResourceId ?? '//'), '/')[2],
split((secretsExportConfiguration.?keyVaultResourceId ?? '////'), '/')[4]
)
params: {
keyVaultName: last(split(secretsExportConfiguration.?keyVaultResourceId ?? '//', '/'))
secretsToSet: union(
[],
contains(secretsExportConfiguration!, 'accessKey1Name')
? [
{
name: secretsExportConfiguration!.accessKey1Name
value: cognitiveService.listKeys().key1
}
]
: [],
contains(secretsExportConfiguration!, 'accessKey2Name')
? [
{
name: secretsExportConfiguration!.accessKey2Name
value: cognitiveService.listKeys().key2
}
]
: []
)
}
}

@description('The name of the cognitive services account.')
output name string = cognitiveService.name

Expand All @@ -489,6 +522,11 @@ output systemAssignedMIPrincipalId string = cognitiveService.?identity.?principa
@description('The location the resource was deployed into.')
output location string = cognitiveService.location

@description('A hashtable of references to the secrets exported to the provided Key Vault. The key of each reference is each secret\'s name.')
output exportedSecrets secretsOutputType = (secretsExportConfiguration != null)
? toObject(secretsExport.outputs.secretsSet, secret => last(split(secret.secretResourceId, '/')), secret => secret)
: {}

// ================ //
// Definitions //
// ================ //
Expand Down Expand Up @@ -706,3 +744,20 @@ type endpointsType = {
@description('The endpoint URI.')
endpoint: string?
}?

type secretsExportConfigurationType = {
@description('Required. The key vault name where to store the keys and connection strings generated by the modules.')
keyVaultResourceId: string

@description('Optional. The name for the accessKey1 secret to create.')
accessKey1Name: string?

@description('Optional. The name for the accessKey2 secret to create.')
accessKey2Name: string?
}

import { secretSetType } from 'modules/keyVaultExport.bicep'
type secretsOutputType = {
@description('An exported secret\'s references.')
*: secretSetType
}
Loading
Loading