diff --git a/modules/app-configuration/configuration-store/.bicep/nested_roleAssignments.bicep b/modules/app-configuration/configuration-store/.bicep/nested_roleAssignments.bicep index bd3923df33..065a1a3976 100644 --- a/modules/app-configuration/configuration-store/.bicep/nested_roleAssignments.bicep +++ b/modules/app-configuration/configuration-store/.bicep/nested_roleAssignments.bicep @@ -34,6 +34,8 @@ param conditionVersion string = '2.0' param delegatedManagedIdentityResourceId string = '' var builtInRoleNames = { + 'App Compliance Automation Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '0f37683f-2463-46b6-9ce7-9b788b988ba2') + 'App Compliance Automation Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ffc6bbe0-e443-4c3b-bf54-26581bb2f78e') 'App Configuration Data Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5ae67dd6-50cb-40e7-96ff-dc2bfa4b606b') 'App Configuration Data Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '516239f1-63e1-4d78-a4de-a74fb236a071') Contributor: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') @@ -51,7 +53,7 @@ var builtInRoleNames = { 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') } -resource appConfiguration 'Microsoft.AppConfiguration/configurationStores@2021-10-01-preview' existing = { +resource appConfiguration 'Microsoft.AppConfiguration/configurationStores@2023-03-01' existing = { name: last(split(resourceId, '/'))! } diff --git a/modules/app-configuration/configuration-store/.test/common/dependencies.bicep b/modules/app-configuration/configuration-store/.test/common/dependencies.bicep index 29b9641692..bd63a95634 100644 --- a/modules/app-configuration/configuration-store/.test/common/dependencies.bicep +++ b/modules/app-configuration/configuration-store/.test/common/dependencies.bicep @@ -11,3 +11,6 @@ resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2018- @description('The principal ID of the created managed identity.') output managedIdentityPrincipalId string = managedIdentity.properties.principalId + +@description('The resource ID of the created Managed Identity.') +output managedIdentityResourceId string = managedIdentity.id diff --git a/modules/app-configuration/configuration-store/.test/common/main.test.bicep b/modules/app-configuration/configuration-store/.test/common/main.test.bicep index 9c5e54e5f8..8eb3658b39 100644 --- a/modules/app-configuration/configuration-store/.test/common/main.test.bicep +++ b/modules/app-configuration/configuration-store/.test/common/main.test.bicep @@ -100,7 +100,10 @@ module testDeployment '../../main.bicep' = { } ] softDeleteRetentionInDays: 1 - systemAssignedIdentity: true + systemAssignedIdentity: false + userAssignedIdentities: { + '${nestedDependencies.outputs.managedIdentityResourceId}': {} + } tags: { 'hidden-title': 'This is visible in the resource name' Environment: 'Non-Prod' diff --git a/modules/app-configuration/configuration-store/.test/encr/dependencies.bicep b/modules/app-configuration/configuration-store/.test/encr/dependencies.bicep new file mode 100644 index 0000000000..bebad9a289 --- /dev/null +++ b/modules/app-configuration/configuration-store/.test/encr/dependencies.bicep @@ -0,0 +1,61 @@ +@description('Required. The name of the managed identity to create.') +param managedIdentityName string + +@description('Required. The name of the Key Vault to create.') +param keyVaultName string + +@description('Optional. The location to deploy resources to.') +param location string = resourceGroup().location + +resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2018-11-30' = { + name: managedIdentityName + location: location +} + +resource keyVault 'Microsoft.KeyVault/vaults@2023-02-01' = { + name: keyVaultName + location: location + properties: { + sku: { + family: 'A' + name: 'standard' + } + tenantId: tenant().tenantId + enablePurgeProtection: true + softDeleteRetentionInDays: 90 + enabledForTemplateDeployment: true + enabledForDiskEncryption: true + enabledForDeployment: true + enableRbacAuthorization: true + accessPolicies: [] + } + + resource key 'keys@2023-02-01' = { + name: 'keyEncryptionKey' + properties: { + kty: 'RSA' + } + } +} + +resource keyPermissions 'Microsoft.Authorization/roleAssignments@2022-04-01' = { + name: guid('msi-${keyVault::key.id}-${location}-${managedIdentity.id}-Key-Reader-RoleAssignment') + scope: keyVault::key + properties: { + principalId: managedIdentity.properties.principalId + roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '12338af0-0e69-4776-bea7-57ae8d297424') // Key Vault Crypto User + principalType: 'ServicePrincipal' + } +} + +@description('The principal ID of the created managed identity.') +output managedIdentityPrincipalId string = managedIdentity.properties.principalId + +@description('The resource ID of the created Managed Identity.') +output managedIdentityResourceId string = managedIdentity.id + +@description('The resource ID of the created Key Vault.') +output keyVaultResourceId string = keyVault.id + +@description('The name of the created encryption key.') +output keyName string = keyVault::key.name diff --git a/modules/app-configuration/configuration-store/.test/encr/main.test.bicep b/modules/app-configuration/configuration-store/.test/encr/main.test.bicep new file mode 100644 index 0000000000..01a2825ad0 --- /dev/null +++ b/modules/app-configuration/configuration-store/.test/encr/main.test.bicep @@ -0,0 +1,98 @@ +targetScope = 'subscription' + +// ========== // +// Parameters // +// ========== // + +@description('Optional. The name of the resource group to deploy for testing purposes.') +@maxLength(90) +param resourceGroupName string = 'dep-${namePrefix}-appconfiguration.configurationstores-${serviceShort}-rg' + +@description('Optional. The location to deploy resources to.') +param location string = deployment().location + +@description('Optional. A short identifier for the kind of deployment. Should be kept short to not run into resource-name length-constraints.') +param serviceShort string = 'accencr' + +@description('Optional. Enable telemetry via a Globally Unique Identifier (GUID).') +param enableDefaultTelemetry bool = true + +@description('Generated. Used as a basis for unique resource names.') +param baseTime string = utcNow('u') + +@description('Optional. A token to inject into the name of each resource.') +param namePrefix string = '[[namePrefix]]' + +// ============ // +// Dependencies // +// ============ // + +// General resources +// ================= +resource resourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = { + name: resourceGroupName + location: location +} + +module nestedDependencies 'dependencies.bicep' = { + scope: resourceGroup + name: '${uniqueString(deployment().name, location)}-nestedDependencies' + params: { + // Adding base time to make the name unique as purge protection must be enabled (but may not be longer than 24 characters total) + keyVaultName: 'dep-${namePrefix}-kv-${serviceShort}-${substring(uniqueString(baseTime), 0, 3)}' + managedIdentityName: 'dep-${namePrefix}-msi-${serviceShort}' + } +} + +// ============== // +// Test Execution // +// ============== // + +module testDeployment '../../main.bicep' = { + scope: resourceGroup + name: '${uniqueString(deployment().name, location)}-test-${serviceShort}' + params: { + enableDefaultTelemetry: enableDefaultTelemetry + name: '${namePrefix}${serviceShort}001' + createMode: 'Default' + disableLocalAuth: false + enablePurgeProtection: false + keyValues: [ + { + contentType: 'contentType' + name: 'keyName' + roleAssignments: [ + { + roleDefinitionIdOrName: 'Reader' + principalIds: [ + nestedDependencies.outputs.managedIdentityPrincipalId + ] + principalType: 'ServicePrincipal' + } + ] + value: 'valueName' + } + ] + roleAssignments: [ + { + roleDefinitionIdOrName: 'Reader' + principalIds: [ + nestedDependencies.outputs.managedIdentityPrincipalId + ] + principalType: 'ServicePrincipal' + } + ] + softDeleteRetentionInDays: 1 + userAssignedIdentities: { + '${nestedDependencies.outputs.managedIdentityResourceId}': {} + } + tags: { + 'hidden-title': 'This is visible in the resource name' + Environment: 'Non-Prod' + Role: 'DeploymentValidation' + } + cMKKeyVaultResourceId: nestedDependencies.outputs.keyVaultResourceId + cMKKeyName: nestedDependencies.outputs.keyName + cMKUserAssignedIdentityResourceId: nestedDependencies.outputs.managedIdentityResourceId + } +} diff --git a/modules/app-configuration/configuration-store/README.md b/modules/app-configuration/configuration-store/README.md index fbbd683f2b..bd34bd6772 100644 --- a/modules/app-configuration/configuration-store/README.md +++ b/modules/app-configuration/configuration-store/README.md @@ -14,8 +14,8 @@ This module deploys an App Configuration Store. | Resource Type | API Version | | :-- | :-- | -| `Microsoft.AppConfiguration/configurationStores` | [2021-10-01-preview](https://learn.microsoft.com/en-us/azure/templates/Microsoft.AppConfiguration/2021-10-01-preview/configurationStores) | -| `Microsoft.AppConfiguration/configurationStores/keyValues` | [2021-10-01-preview](https://learn.microsoft.com/en-us/azure/templates/Microsoft.AppConfiguration/2021-10-01-preview/configurationStores/keyValues) | +| `Microsoft.AppConfiguration/configurationStores` | [2023-03-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.AppConfiguration/2023-03-01/configurationStores) | +| `Microsoft.AppConfiguration/configurationStores/keyValues` | [2023-03-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.AppConfiguration/2023-03-01/configurationStores/keyValues) | | `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) | @@ -31,8 +31,9 @@ The following section provides usage examples for the module, which were used to >**Note**: To reference the module, please use the following syntax `br:bicep/modules/app-configuration.configuration-store:1.0.0`. - [Using large parameter set](#example-1-using-large-parameter-set) -- [Using only defaults](#example-2-using-only-defaults) -- [Pe](#example-3-pe) +- [Encr](#example-2-encr) +- [Using only defaults](#example-3-using-only-defaults) +- [Pe](#example-4-pe) ### Example 1: _Using large parameter set_ @@ -85,12 +86,15 @@ module configurationStore 'br:bicep/modules/app-configuration.configuration-stor } ] softDeleteRetentionInDays: 1 - systemAssignedIdentity: true + systemAssignedIdentity: false tags: { Environment: 'Non-Prod' 'hidden-title': 'This is visible in the resource name' Role: 'DeploymentValidation' } + userAssignedIdentities: { + '': {} + } } } ``` @@ -172,7 +176,7 @@ module configurationStore 'br:bicep/modules/app-configuration.configuration-stor "value": 1 }, "systemAssignedIdentity": { - "value": true + "value": false }, "tags": { "value": { @@ -180,6 +184,72 @@ module configurationStore 'br:bicep/modules/app-configuration.configuration-stor "hidden-title": "This is visible in the resource name", "Role": "DeploymentValidation" } + }, + "userAssignedIdentities": { + "value": { + "": {} + } + } + } +} +``` + + +

+ +### Example 2: _Encr_ + +

+ +via Bicep module + +```bicep +module configurationStore 'br:bicep/modules/app-configuration.configuration-store:1.0.0' = { + name: '${uniqueString(deployment().name, location)}-test-accencr' + params: { + // Required parameters + name: 'accencr001' + // Non-required parameters + cMKKeyName: '' + cMKKeyVaultResourceId: '' + cMKUserAssignedIdentityResourceId: '' + createMode: 'Default' + disableLocalAuth: false + enableDefaultTelemetry: '' + enablePurgeProtection: false + keyValues: [ + { + contentType: 'contentType' + name: 'keyName' + roleAssignments: [ + { + principalIds: [ + '' + ] + principalType: 'ServicePrincipal' + roleDefinitionIdOrName: 'Reader' + } + ] + value: 'valueName' + } + ] + roleAssignments: [ + { + principalIds: [ + '' + ] + principalType: 'ServicePrincipal' + roleDefinitionIdOrName: 'Reader' + } + ] + softDeleteRetentionInDays: 1 + tags: { + Environment: 'Non-Prod' + 'hidden-title': 'This is visible in the resource name' + Role: 'DeploymentValidation' + } + userAssignedIdentities: { + '': {} } } } @@ -188,7 +258,93 @@ module configurationStore 'br:bicep/modules/app-configuration.configuration-stor

-### Example 2: _Using only defaults_ +

+ +via JSON Parameter file + +```json +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", + "contentVersion": "1.0.0.0", + "parameters": { + // Required parameters + "name": { + "value": "accencr001" + }, + // Non-required parameters + "cMKKeyName": { + "value": "" + }, + "cMKKeyVaultResourceId": { + "value": "" + }, + "cMKUserAssignedIdentityResourceId": { + "value": "" + }, + "createMode": { + "value": "Default" + }, + "disableLocalAuth": { + "value": false + }, + "enableDefaultTelemetry": { + "value": "" + }, + "enablePurgeProtection": { + "value": false + }, + "keyValues": { + "value": [ + { + "contentType": "contentType", + "name": "keyName", + "roleAssignments": [ + { + "principalIds": [ + "" + ], + "principalType": "ServicePrincipal", + "roleDefinitionIdOrName": "Reader" + } + ], + "value": "valueName" + } + ] + }, + "roleAssignments": { + "value": [ + { + "principalIds": [ + "" + ], + "principalType": "ServicePrincipal", + "roleDefinitionIdOrName": "Reader" + } + ] + }, + "softDeleteRetentionInDays": { + "value": 1 + }, + "tags": { + "value": { + "Environment": "Non-Prod", + "hidden-title": "This is visible in the resource name", + "Role": "DeploymentValidation" + } + }, + "userAssignedIdentities": { + "value": { + "": {} + } + } + } +} +``` + +
+

+ +### Example 3: _Using only defaults_ This instance deploys the module with the minimum set of required parameters. @@ -236,7 +392,7 @@ module configurationStore 'br:bicep/modules/app-configuration.configuration-stor

-### Example 3: _Pe_ +### Example 4: _Pe_

@@ -352,10 +508,19 @@ module configurationStore 'br:bicep/modules/app-configuration.configuration-stor | :-- | :-- | :-- | | [`name`](#parameter-name) | string | Name of the Azure App Configuration. | +**Conditional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`cMKKeyVaultResourceId`](#parameter-cmkkeyvaultresourceid) | string | The resource ID of a key vault to reference a customer managed key for encryption from. Required if "cMKKeyName" is not empty. | +| [`cMKUserAssignedIdentityResourceId`](#parameter-cmkuserassignedidentityresourceid) | string | User assigned identity to use when fetching the customer managed key. The identity should have key usage permissions on the Key Vault Key. Required if "cMKKeyName" is not empty. | + **Optional parameters** | Parameter | Type | Description | | :-- | :-- | :-- | +| [`cMKKeyName`](#parameter-cmkkeyname) | string | The name of the customer managed key to use for encryption. | +| [`cMKKeyVersion`](#parameter-cmkkeyversion) | string | The version of the customer managed key to reference for encryption. If not provided, the latest key version is used. | | [`createMode`](#parameter-createmode) | string | Indicates whether the configuration store need to be recovered. | | [`diagnosticEventHubAuthorizationRuleId`](#parameter-diagnosticeventhubauthorizationruleid) | string | Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to. | | [`diagnosticEventHubName`](#parameter-diagnosticeventhubname) | string | 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. | @@ -367,7 +532,7 @@ module configurationStore 'br:bicep/modules/app-configuration.configuration-stor | [`disableLocalAuth`](#parameter-disablelocalauth) | bool | Disables all authentication methods other than AAD authentication. | | [`enableDefaultTelemetry`](#parameter-enabledefaulttelemetry) | bool | Enable telemetry via a Globally Unique Identifier (GUID). | | [`enablePurgeProtection`](#parameter-enablepurgeprotection) | bool | Property specifying whether protection against purge is enabled for this configuration store. | -| [`keyValues`](#parameter-keyvalues) | array | All Key / Values to create. | +| [`keyValues`](#parameter-keyvalues) | array | All Key / Values to create. Requires local authentication to be enabled. | | [`location`](#parameter-location) | string | Location for all Resources. | | [`lock`](#parameter-lock) | string | Specify the type of lock. | | [`privateEndpoints`](#parameter-privateendpoints) | array | Configuration details for private endpoints. For security reasons, it is recommended to use private endpoints whenever possible. | @@ -379,6 +544,34 @@ module configurationStore 'br:bicep/modules/app-configuration.configuration-stor | [`tags`](#parameter-tags) | object | Tags of the resource. | | [`userAssignedIdentities`](#parameter-userassignedidentities) | object | The ID(s) to assign to the resource. | +### Parameter: `cMKKeyName` + +The name of the customer managed key to use for encryption. +- Required: No +- Type: string +- Default: `''` + +### Parameter: `cMKKeyVaultResourceId` + +The resource ID of a key vault to reference a customer managed key for encryption from. Required if "cMKKeyName" is not empty. +- Required: No +- Type: string +- Default: `''` + +### Parameter: `cMKKeyVersion` + +The version of the customer managed key to reference for encryption. If not provided, the latest key version is used. +- Required: No +- Type: string +- Default: `''` + +### Parameter: `cMKUserAssignedIdentityResourceId` + +User assigned identity to use when fetching the customer managed key. The identity should have key usage permissions on the Key Vault Key. Required if "cMKKeyName" is not empty. +- Required: No +- Type: string +- Default: `''` + ### Parameter: `createMode` Indicates whether the configuration store need to be recovered. @@ -461,7 +654,7 @@ Property specifying whether protection against purge is enabled for this configu ### Parameter: `keyValues` -All Key / Values to create. +All Key / Values to create. Requires local authentication to be enabled. - Required: No - Type: array - Default: `[]` diff --git a/modules/app-configuration/configuration-store/key-value/.bicep/nested_roleAssignments.bicep b/modules/app-configuration/configuration-store/key-value/.bicep/nested_roleAssignments.bicep index bd3923df33..2b0b5813ba 100644 --- a/modules/app-configuration/configuration-store/key-value/.bicep/nested_roleAssignments.bicep +++ b/modules/app-configuration/configuration-store/key-value/.bicep/nested_roleAssignments.bicep @@ -51,7 +51,7 @@ var builtInRoleNames = { 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') } -resource appConfiguration 'Microsoft.AppConfiguration/configurationStores@2021-10-01-preview' existing = { +resource appConfiguration 'Microsoft.AppConfiguration/configurationStores@2023-03-01' existing = { name: last(split(resourceId, '/'))! } diff --git a/modules/app-configuration/configuration-store/key-value/README.md b/modules/app-configuration/configuration-store/key-value/README.md index 7aba86936e..3fb836e1b5 100644 --- a/modules/app-configuration/configuration-store/key-value/README.md +++ b/modules/app-configuration/configuration-store/key-value/README.md @@ -13,7 +13,7 @@ This module deploys an App Configuration Store Key Value. | Resource Type | API Version | | :-- | :-- | -| `Microsoft.AppConfiguration/configurationStores/keyValues` | [2021-10-01-preview](https://learn.microsoft.com/en-us/azure/templates/Microsoft.AppConfiguration/2021-10-01-preview/configurationStores/keyValues) | +| `Microsoft.AppConfiguration/configurationStores/keyValues` | [2023-03-01](https://learn.microsoft.com/en-us/azure/templates/Microsoft.AppConfiguration/2023-03-01/configurationStores/keyValues) | ## Parameters diff --git a/modules/app-configuration/configuration-store/key-value/main.bicep b/modules/app-configuration/configuration-store/key-value/main.bicep index 09c43a245e..199bad6726 100644 --- a/modules/app-configuration/configuration-store/key-value/main.bicep +++ b/modules/app-configuration/configuration-store/key-value/main.bicep @@ -32,11 +32,11 @@ resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (ena } } -resource appConfiguration 'Microsoft.AppConfiguration/configurationStores@2021-10-01-preview' existing = { +resource appConfiguration 'Microsoft.AppConfiguration/configurationStores@2023-03-01' existing = { name: appConfigurationName } -resource keyValues 'Microsoft.AppConfiguration/configurationStores/keyValues@2021-10-01-preview' = { +resource keyValues 'Microsoft.AppConfiguration/configurationStores/keyValues@2023-03-01' = { name: name parent: appConfiguration properties: { diff --git a/modules/app-configuration/configuration-store/key-value/main.json b/modules/app-configuration/configuration-store/key-value/main.json index bd6ba98307..7737b18021 100644 --- a/modules/app-configuration/configuration-store/key-value/main.json +++ b/modules/app-configuration/configuration-store/key-value/main.json @@ -5,7 +5,7 @@ "_generator": { "name": "bicep", "version": "0.22.6.54827", - "templateHash": "16698134952769248111" + "templateHash": "16264229277476024063" }, "name": "App Configuration Stores Key Values", "description": "This module deploys an App Configuration Store Key Value.", @@ -69,7 +69,7 @@ }, { "type": "Microsoft.AppConfiguration/configurationStores/keyValues", - "apiVersion": "2021-10-01-preview", + "apiVersion": "2023-03-01", "name": "[format('{0}/{1}', parameters('appConfigurationName'), parameters('name'))]", "properties": { "contentType": "[parameters('contentType')]", diff --git a/modules/app-configuration/configuration-store/main.bicep b/modules/app-configuration/configuration-store/main.bicep index 8572b9abc3..30ae719fe0 100644 --- a/modules/app-configuration/configuration-store/main.bicep +++ b/modules/app-configuration/configuration-store/main.bicep @@ -47,7 +47,19 @@ param publicNetworkAccess string = '' @maxValue(7) param softDeleteRetentionInDays int = 1 -@description('Optional. All Key / Values to create.') +@description('Conditional. The resource ID of a key vault to reference a customer managed key for encryption from. Required if "cMKKeyName" is not empty.') +param cMKKeyVaultResourceId string = '' + +@description('Optional. The name of the customer managed key to use for encryption.') +param cMKKeyName string = '' + +@description('Optional. The version of the customer managed key to reference for encryption. If not provided, the latest key version is used.') +param cMKKeyVersion string = '' + +@description('Conditional. User assigned identity to use when fetching the customer managed key. The identity should have key usage permissions on the Key Vault Key. Required if "cMKKeyName" is not empty.') +param cMKUserAssignedIdentityResourceId string = '' + +@description('Optional. All Key / Values to create. Requires local authentication to be enabled.') param keyValues array = [] @description('Optional. Resource ID of the diagnostic storage account.') @@ -143,7 +155,21 @@ resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (ena } } -resource configurationStore 'Microsoft.AppConfiguration/configurationStores@2021-10-01-preview' = { +resource cMKKeyVault 'Microsoft.KeyVault/vaults@2023-02-01' existing = if (!empty(cMKKeyVaultResourceId)) { + name: last(split(cMKKeyVaultResourceId, '/'))! + scope: resourceGroup(split(cMKKeyVaultResourceId, '/')[2], split(cMKKeyVaultResourceId, '/')[4]) + + resource cMKKey 'keys@2022-07-01' existing = if (!empty(cMKKeyName)) { + name: cMKKeyName + } +} + +resource cMKUserAssignedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31' existing = if (!empty(cMKUserAssignedIdentityResourceId)) { + name: last(split(cMKUserAssignedIdentityResourceId, '/'))! + scope: resourceGroup(split(cMKUserAssignedIdentityResourceId, '/')[2], split(cMKUserAssignedIdentityResourceId, '/')[4]) +} + +resource configurationStore 'Microsoft.AppConfiguration/configurationStores@2023-03-01' = { name: name location: location tags: tags @@ -155,6 +181,12 @@ resource configurationStore 'Microsoft.AppConfiguration/configurationStores@2021 createMode: createMode disableLocalAuth: disableLocalAuth enablePurgeProtection: sku == 'Free' ? false : enablePurgeProtection + encryption: !empty(cMKKeyName) ? { + keyVaultProperties: { + keyIdentifier: !empty(cMKKeyVersion) ? '${cMKKeyVault::cMKKey.properties.keyUri}/${cMKKeyVersion}' : cMKKeyVault::cMKKey.properties.keyUriWithVersion + identityClientId: cMKUserAssignedIdentity.properties.clientId + } + } : null publicNetworkAccess: !empty(publicNetworkAccess) ? any(publicNetworkAccess) : null softDeleteRetentionInDays: sku == 'Free' ? 0 : softDeleteRetentionInDays } diff --git a/modules/app-configuration/configuration-store/main.json b/modules/app-configuration/configuration-store/main.json index 9864464e86..d2673179c6 100644 --- a/modules/app-configuration/configuration-store/main.json +++ b/modules/app-configuration/configuration-store/main.json @@ -5,7 +5,7 @@ "_generator": { "name": "bicep", "version": "0.22.6.54827", - "templateHash": "10110269901043104603" + "templateHash": "9177345783229255097" }, "name": "App Configuration Stores", "description": "This module deploys an App Configuration Store.", @@ -96,11 +96,39 @@ "description": "Optional. The amount of time in days that the configuration store will be retained when it is soft deleted." } }, + "cMKKeyVaultResourceId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Conditional. The resource ID of a key vault to reference a customer managed key for encryption from. Required if \"cMKKeyName\" is not empty." + } + }, + "cMKKeyName": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. The name of the customer managed key to use for encryption." + } + }, + "cMKKeyVersion": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Optional. The version of the customer managed key to reference for encryption. If not provided, the latest key version is used." + } + }, + "cMKUserAssignedIdentityResourceId": { + "type": "string", + "defaultValue": "", + "metadata": { + "description": "Conditional. User assigned identity to use when fetching the customer managed key. The identity should have key usage permissions on the Key Vault Key. Required if \"cMKKeyName\" is not empty." + } + }, "keyValues": { "type": "array", "defaultValue": [], "metadata": { - "description": "Optional. All Key / Values to create." + "description": "Optional. All Key / Values to create. Requires local authentication to be enabled." } }, "diagnosticStorageAccountId": { @@ -251,7 +279,7 @@ }, { "type": "Microsoft.AppConfiguration/configurationStores", - "apiVersion": "2021-10-01-preview", + "apiVersion": "2023-03-01", "name": "[parameters('name')]", "location": "[parameters('location')]", "tags": "[parameters('tags')]", @@ -263,6 +291,7 @@ "createMode": "[parameters('createMode')]", "disableLocalAuth": "[parameters('disableLocalAuth')]", "enablePurgeProtection": "[if(equals(parameters('sku'), 'Free'), false(), parameters('enablePurgeProtection'))]", + "encryption": "[if(not(empty(parameters('cMKKeyName'))), createObject('keyVaultProperties', createObject('keyIdentifier', if(not(empty(parameters('cMKKeyVersion'))), format('{0}/{1}', reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', split(parameters('cMKKeyVaultResourceId'), '/')[2], split(parameters('cMKKeyVaultResourceId'), '/')[4]), 'Microsoft.KeyVault/vaults/keys', last(split(parameters('cMKKeyVaultResourceId'), '/')), parameters('cMKKeyName')), '2022-07-01').keyUri, parameters('cMKKeyVersion')), reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', split(parameters('cMKKeyVaultResourceId'), '/')[2], split(parameters('cMKKeyVaultResourceId'), '/')[4]), 'Microsoft.KeyVault/vaults/keys', last(split(parameters('cMKKeyVaultResourceId'), '/')), parameters('cMKKeyName')), '2022-07-01').keyUriWithVersion), 'identityClientId', reference(extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', split(parameters('cMKUserAssignedIdentityResourceId'), '/')[2], split(parameters('cMKUserAssignedIdentityResourceId'), '/')[4]), 'Microsoft.ManagedIdentity/userAssignedIdentities', last(split(parameters('cMKUserAssignedIdentityResourceId'), '/'))), '2023-01-31').clientId)), null())]", "publicNetworkAccess": "[if(not(empty(parameters('publicNetworkAccess'))), parameters('publicNetworkAccess'), null())]", "softDeleteRetentionInDays": "[if(equals(parameters('sku'), 'Free'), 0, parameters('softDeleteRetentionInDays'))]" } @@ -335,7 +364,7 @@ "_generator": { "name": "bicep", "version": "0.22.6.54827", - "templateHash": "16698134952769248111" + "templateHash": "16264229277476024063" }, "name": "App Configuration Stores Key Values", "description": "This module deploys an App Configuration Store Key Value.", @@ -399,7 +428,7 @@ }, { "type": "Microsoft.AppConfiguration/configurationStores/keyValues", - "apiVersion": "2021-10-01-preview", + "apiVersion": "2023-03-01", "name": "[format('{0}/{1}', parameters('appConfigurationName'), parameters('name'))]", "properties": { "contentType": "[parameters('contentType')]", @@ -472,7 +501,7 @@ "_generator": { "name": "bicep", "version": "0.22.6.54827", - "templateHash": "17212866457936326905" + "templateHash": "13848128808282670402" } }, "parameters": { @@ -543,6 +572,8 @@ }, "variables": { "builtInRoleNames": { + "App Compliance Automation Administrator": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '0f37683f-2463-46b6-9ce7-9b788b988ba2')]", + "App Compliance Automation Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ffc6bbe0-e443-4c3b-bf54-26581bb2f78e')]", "App Configuration Data Owner": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '5ae67dd6-50cb-40e7-96ff-dc2bfa4b606b')]", "App Configuration Data Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '516239f1-63e1-4d78-a4de-a74fb236a071')]", "Contributor": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]", @@ -1179,14 +1210,14 @@ "metadata": { "description": "The principal ID of the system assigned identity." }, - "value": "[if(and(parameters('systemAssignedIdentity'), contains(reference(resourceId('Microsoft.AppConfiguration/configurationStores', parameters('name')), '2021-10-01-preview', 'full').identity, 'principalId')), reference(resourceId('Microsoft.AppConfiguration/configurationStores', parameters('name')), '2021-10-01-preview', 'full').identity.principalId, '')]" + "value": "[if(and(parameters('systemAssignedIdentity'), contains(reference(resourceId('Microsoft.AppConfiguration/configurationStores', parameters('name')), '2023-03-01', 'full').identity, 'principalId')), reference(resourceId('Microsoft.AppConfiguration/configurationStores', parameters('name')), '2023-03-01', 'full').identity.principalId, '')]" }, "location": { "type": "string", "metadata": { "description": "The location the resource was deployed into." }, - "value": "[reference(resourceId('Microsoft.AppConfiguration/configurationStores', parameters('name')), '2021-10-01-preview', 'full').location]" + "value": "[reference(resourceId('Microsoft.AppConfiguration/configurationStores', parameters('name')), '2023-03-01', 'full').location]" } } } \ No newline at end of file