Skip to content

Commit

Permalink
fix: Add key vault to search service - avm/res/search/search-service (
Browse files Browse the repository at this point in the history
#1950)

Add option for outputting admin keys to search service

<!--
>Thank you for your contribution !
> Please include a summary of the change and which issue is fixed.
> Please also include the context.
> List any dependencies that are required for this change.

Fixes #123
Fixes #456
Closes #123
Closes #456
-->

## Pipeline Reference

<!-- Insert your Pipeline Status Badge below -->

| Pipeline |
| -------- |
|
[![avm.res.search.search-service](https://github.com/mortenvpschmidt/bicep-registry-modules/actions/workflows/avm.res.search.search-service.yml/badge.svg?branch=Aisearch_w_keyvault)](https://github.com/mortenvpschmidt/bicep-registry-modules/actions/workflows/avm.res.search.search-service.yml)
|

## Type of Change

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

- [ ] Update to CI Environment or utilities (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: Morten Schmidt <[email protected]>
Co-authored-by: Axel Bøg Andersen <[email protected]>
Co-authored-by: Erika Gressi <[email protected]>
  • Loading branch information
4 people authored Oct 1, 2024
1 parent 3073a74 commit 7d6600c
Show file tree
Hide file tree
Showing 7 changed files with 535 additions and 37 deletions.
138 changes: 129 additions & 9 deletions avm/res/search/search-service/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ This module deploys a Search Service.
| `Microsoft.Authorization/locks` | [2020-05-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2020-05-01/locks) |
| `Microsoft.Authorization/roleAssignments` | [2022-04-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2022-04-01/roleAssignments) |
| `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) |
| `Microsoft.Search/searchServices` | [2024-03-01-preview](https://learn.microsoft.com/en-us/azure/templates/Microsoft.Search/2024-03-01-preview/searchServices) |
Expand All @@ -32,9 +33,10 @@ The following section provides usage examples for the module, which were used to
>**Note**: To reference the module, please use the following syntax `br/public:avm/res/search/search-service:<version>`.
- [Using only defaults](#example-1-using-only-defaults)
- [Using large parameter set](#example-2-using-large-parameter-set)
- [Private endpoint-enabled deployment](#example-3-private-endpoint-enabled-deployment)
- [WAF-aligned](#example-4-waf-aligned)
- [Deploying with a key vault reference to save secrets](#example-2-deploying-with-a-key-vault-reference-to-save-secrets)
- [Using large parameter set](#example-3-using-large-parameter-set)
- [Private endpoint-enabled deployment](#example-4-private-endpoint-enabled-deployment)
- [WAF-aligned](#example-5-waf-aligned)

### Example 1: _Using only defaults_

Expand Down Expand Up @@ -84,7 +86,83 @@ module searchService 'br/public:avm/res/search/search-service:<version>' = {
</details>
<p>

### Example 2: _Using large parameter set_
### Example 2: _Deploying with a key vault reference to save secrets_

This instance deploys the module saving admin key secrets in a key vault.


<details>

<summary>via Bicep module</summary>

```bicep
module searchService 'br/public:avm/res/search/search-service:<version>' = {
name: 'searchServiceDeployment'
params: {
// Required parameters
name: 'kv-ref'
// Non-required parameters
authOptions: {
aadOrApiKey: {
aadAuthFailureMode: 'http401WithBearerChallenge'
}
}
disableLocalAuth: false
location: '<location>'
secretsExportConfiguration: {
keyVaultResourceId: '<keyVaultResourceId>'
primaryAdminKeyName: 'Primary-Admin-Key'
secondaryAdminKeyName: 'Secondary-Admin-Key'
}
}
}
```

</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
"name": {
"value": "kv-ref"
},
// Non-required parameters
"authOptions": {
"value": {
"aadOrApiKey": {
"aadAuthFailureMode": "http401WithBearerChallenge"
}
}
},
"disableLocalAuth": {
"value": false
},
"location": {
"value": "<location>"
},
"secretsExportConfiguration": {
"value": {
"keyVaultResourceId": "<keyVaultResourceId>",
"primaryAdminKeyName": "Primary-Admin-Key",
"secondaryAdminKeyName": "Secondary-Admin-Key"
}
}
}
}
```

</details>
<p>

### Example 3: _Using large parameter set_

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

Expand Down Expand Up @@ -300,7 +378,7 @@ module searchService 'br/public:avm/res/search/search-service:<version>' = {
</details>
<p>

### Example 3: _Private endpoint-enabled deployment_
### Example 4: _Private endpoint-enabled deployment_

This instance deploys the module with private endpoints.

Expand All @@ -314,7 +392,7 @@ module searchService 'br/public:avm/res/search/search-service:<version>' = {
name: 'searchServiceDeployment'
params: {
// Required parameters
name: 'ssspe001'
name: 'ssspr001'
// Non-required parameters
location: '<location>'
privateEndpoints: [
Expand Down Expand Up @@ -383,7 +461,7 @@ module searchService 'br/public:avm/res/search/search-service:<version>' = {
"parameters": {
// Required parameters
"name": {
"value": "ssspe001"
"value": "ssspr001"
},
// Non-required parameters
"location": {
Expand Down Expand Up @@ -452,7 +530,7 @@ module searchService 'br/public:avm/res/search/search-service:<version>' = {
</details>
<p>

### Example 4: _WAF-aligned_
### Example 5: _WAF-aligned_

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

Expand Down Expand Up @@ -645,6 +723,7 @@ module searchService 'br/public:avm/res/search/search-service:<version>' = {
| [`publicNetworkAccess`](#parameter-publicnetworkaccess) | string | This value can be set to 'Enabled' to avoid breaking changes on existing customer resources and templates. If set to 'Disabled', traffic over public interface is not allowed, and private endpoint connections would be the exclusive access method. |
| [`replicaCount`](#parameter-replicacount) | int | The number of replicas in the search service. If specified, it must be a value between 1 and 12 inclusive for standard SKUs or between 1 and 3 inclusive for basic SKU. |
| [`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. |
| [`semanticSearch`](#parameter-semanticsearch) | string | Sets options that control the availability of semantic search. This configuration is only possible for certain search SKUs in certain locations. |
| [`sharedPrivateLinkResources`](#parameter-sharedprivatelinkresources) | array | The sharedPrivateLinkResources to create as part of the search Service. |
| [`sku`](#parameter-sku) | string | Defines the SKU of an Azure Cognitive Search Service, which determines price tier and capacity limits. |
Expand Down Expand Up @@ -1481,6 +1560,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 API Admin keys generated by the modules. |

**Optional parameters**

| Parameter | Type | Description |
| :-- | :-- | :-- |
| [`primaryAdminKeyName`](#parameter-secretsexportconfigurationprimaryadminkeyname) | string | The primaryAdminKey secret name to create. |
| [`secondaryAdminKeyName`](#parameter-secretsexportconfigurationsecondaryadminkeyname) | string | The secondaryAdminKey secret name to create. |

### Parameter: `secretsExportConfiguration.keyVaultResourceId`

The key vault name where to store the API Admin keys generated by the modules.

- Required: Yes
- Type: string

### Parameter: `secretsExportConfiguration.primaryAdminKeyName`

The primaryAdminKey secret name to create.

- Required: No
- Type: string

### Parameter: `secretsExportConfiguration.secondaryAdminKeyName`

The secondaryAdminKey secret name to create.

- Required: No
- Type: string

### Parameter: `semanticSearch`

Sets options that control the availability of semantic search. This configuration is only possible for certain search SKUs in certain locations.
Expand Down Expand Up @@ -1535,9 +1655,9 @@ Tags to help categorize the resource in the Azure portal.

| Output | Type | Description |
| :-- | :-- | :-- |
| `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 search service. |
| `privateEndpoints` | array | The private endpoints of the search service. |
| `resourceGroupName` | string | The name of the resource group the search service was created in. |
| `resourceId` | string | The resource ID of the search service. |
| `systemAssignedMIPrincipalId` | string | The principal ID of the system assigned identity. |
Expand Down
64 changes: 54 additions & 10 deletions avm/res/search/search-service/main.bicep
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,9 @@ param sharedPrivateLinkResources array = []
])
param publicNetworkAccess string = 'Enabled'

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

@description('Optional. The number of replicas in the search service. If specified, it must be a value between 1 and 12 inclusive for standard SKUs or between 1 and 3 inclusive for basic SKU.')
@minValue(1)
@maxValue(12)
Expand Down Expand Up @@ -324,6 +327,36 @@ module searchService_sharedPrivateLinkResources 'shared-private-link-resource/ma
}
]

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!, 'primaryAdminKeyName')
? [
{
name: secretsExportConfiguration!.primaryAdminKeyName
value: searchService.listAdminKeys().primaryKey
}
]
: [],
contains(secretsExportConfiguration!, 'secondaryAdminKeyName')
? [
{
name: secretsExportConfiguration!.secondaryAdminKeyName
value: searchService.listAdminKeys().secondaryKey
}
]
: []
)
}
}

// =========== //
// Outputs //
// =========== //
Expand All @@ -343,16 +376,10 @@ output systemAssignedMIPrincipalId string = searchService.?identity.?principalId
@description('The location the resource was deployed into.')
output location string = searchService.location

@description('The private endpoints of the search service.')
output privateEndpoints array = [
for (pe, i) in (!empty(privateEndpoints) ? array(privateEndpoints) : []): {
name: searchService_privateEndpoints[i].outputs.name
resourceId: searchService_privateEndpoints[i].outputs.resourceId
groupId: searchService_privateEndpoints[i].outputs.groupId
customDnsConfig: searchService_privateEndpoints[i].outputs.customDnsConfig
networkInterfaceIds: searchService_privateEndpoints[i].outputs.networkInterfaceIds
}
]
@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 @@ -530,3 +557,20 @@ type diagnosticSettingType = {
@description('Optional. The full ARM resource ID of the Marketplace resource to which you would like to send Diagnostic Logs.')
marketplacePartnerResourceId: string?
}[]?

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

@description('Optional. The primaryAdminKey secret name to create.')
primaryAdminKeyName: string?

@description('Optional. The secondaryAdminKey secret name to create.')
secondaryAdminKeyName: string?
}

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

0 comments on commit 7d6600c

Please sign in to comment.