Skip to content

Commit

Permalink
fix: Add key vault to cognitive service - avm/res/cognitive-services/…
Browse files Browse the repository at this point in the history
…account (Azure#3222)

## Description

Follow-up to: Azure#1932
cc: @Agazoth 

| Pipeline |
| -------- |

[![avm.res.cognitive-services.account](https://github.com/Azure/bicep-registry-modules/actions/workflows/avm.res.cognitive-services.account.yml/badge.svg?branch=users%2Falsehr%2FAgazoth%2FAddKVToCognitiveService&event=workflow_dispatch)](https://github.com/Azure/bicep-registry-modules/actions/workflows/avm.res.cognitive-services.account.yml)

## Type of Change

<!-- Use the check-boxes [x] on the options that are relevant. -->

- [ ] Update to CI Environment or utlities (Non-module effecting
changes)
- [x] Azure Verified Module updates:
- [x] Bugfix containing backwards compatible bug fixes, and I have NOT
bumped the MAJOR or MINOR version in `version.json`:
- [ ] Someone has opened a bug report issue, and I have included "Closes
#{bug_report_issue_number}" in the PR description.
- [ ] The bug was found by the module author, and no one has opened an
issue to report it yet.
- [ ] Feature update backwards compatible feature updates, and I have
bumped the MINOR version in `version.json`.
- [ ] Breaking changes and I have bumped the MAJOR version in
`version.json`.
  - [ ] Update to documentation

## Checklist

- [x] I'm sure there are no other open Pull Requests for the same
update/change
- [x] I have run `Set-AVMModule` locally to generate the supporting
module files.
- [x] My corresponding pipelines / checks run clean and green without
any errors or warnings

<!-- Please keep up to day with the contribution guide at
https://aka.ms/avm/contribute/bicep -->

---------

Co-authored-by: Axel B. Andersen <[email protected]>
Co-authored-by: Javier Cevallos <[email protected]>
  • Loading branch information
3 people authored Sep 18, 2024
1 parent f21032a commit 7876f36
Show file tree
Hide file tree
Showing 6 changed files with 530 additions and 15 deletions.
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 @@ -2142,6 +2209,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 @@ -2192,6 +2300,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

0 comments on commit 7876f36

Please sign in to comment.