diff --git a/avm/res/recovery-services/vault/README.md b/avm/res/recovery-services/vault/README.md index 44d7d1c90c..3d9347b878 100644 --- a/avm/res/recovery-services/vault/README.md +++ b/avm/res/recovery-services/vault/README.md @@ -2711,9 +2711,9 @@ param tags = { | [`backupConfig`](#parameter-backupconfig) | object | The backup configuration. | | [`backupPolicies`](#parameter-backuppolicies) | array | List of all backup policies. | | [`backupStorageConfig`](#parameter-backupstorageconfig) | object | The storage configuration for the Azure Recovery Service Vault. | +| [`customerManagedKey`](#parameter-customermanagedkey) | object | The customer managed key definition. | | [`diagnosticSettings`](#parameter-diagnosticsettings) | array | The diagnostic settings of the service. | | [`enableTelemetry`](#parameter-enabletelemetry) | bool | Enable/Disable usage telemetry for module. | -| [`encryption`](#parameter-encryption) | object | The encryption settings for the vault. | | [`location`](#parameter-location) | string | Location for all resources. | | [`lock`](#parameter-lock) | object | The lock settings of the service. | | [`managedIdentities`](#parameter-managedidentities) | object | The managed identity definition for this resource. | @@ -2761,6 +2761,63 @@ The storage configuration for the Azure Recovery Service Vault. - Type: object - Default: `{}` +### Parameter: `customerManagedKey` + +The customer managed key definition. + +- Required: No +- Type: object + +**Required parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`keyName`](#parameter-customermanagedkeykeyname) | string | The name of the customer managed key to use for encryption. | +| [`keyVaultResourceId`](#parameter-customermanagedkeykeyvaultresourceid) | string | The resource ID of a key vault to reference a customer managed key for encryption from. | + +**Optional parameters** + +| Parameter | Type | Description | +| :-- | :-- | :-- | +| [`autoRotationEnabled`](#parameter-customermanagedkeyautorotationenabled) | bool | Enable or disable auto-rotating to the latest key version. Default is `true`. If set to `false`, the latest key version at the time of the deployment is used. | +| [`keyVersion`](#parameter-customermanagedkeykeyversion) | string | The version of the customer managed key to reference for encryption. If not provided, using version as per 'autoRotationEnabled' setting. | +| [`userAssignedIdentityResourceId`](#parameter-customermanagedkeyuserassignedidentityresourceid) | string | User assigned identity to use when fetching the customer managed key. Required if no system assigned identity is available for use. | + +### Parameter: `customerManagedKey.keyName` + +The name of the customer managed key to use for encryption. + +- Required: Yes +- Type: string + +### Parameter: `customerManagedKey.keyVaultResourceId` + +The resource ID of a key vault to reference a customer managed key for encryption from. + +- Required: Yes +- Type: string + +### Parameter: `customerManagedKey.autoRotationEnabled` + +Enable or disable auto-rotating to the latest key version. Default is `true`. If set to `false`, the latest key version at the time of the deployment is used. + +- Required: No +- Type: bool + +### Parameter: `customerManagedKey.keyVersion` + +The version of the customer managed key to reference for encryption. If not provided, using version as per 'autoRotationEnabled' setting. + +- Required: No +- Type: string + +### Parameter: `customerManagedKey.userAssignedIdentityResourceId` + +User assigned identity to use when fetching the customer managed key. Required if no system assigned identity is available for use. + +- Required: No +- Type: string + ### Parameter: `diagnosticSettings` The diagnostic settings of the service. @@ -2915,76 +2972,6 @@ Enable/Disable usage telemetry for module. - Type: bool - Default: `True` -### Parameter: `encryption` - -The encryption settings for the vault. - -- Required: No -- Type: object - -**Optional parameters** - -| Parameter | Type | Description | -| :-- | :-- | :-- | -| [`infrastructureEncryption`](#parameter-encryptioninfrastructureencryption) | string | The encryption settings for the vault. | -| [`kekIdentity`](#parameter-encryptionkekidentity) | object | The user assigned identity to be used. | -| [`keyVaultProperties`](#parameter-encryptionkeyvaultproperties) | object | The key vault URI. | - -### Parameter: `encryption.infrastructureEncryption` - -The encryption settings for the vault. - -- Required: No -- Type: string - -### Parameter: `encryption.kekIdentity` - -The user assigned identity to be used. - -- Required: Yes -- Type: object - -**Optional parameters** - -| Parameter | Type | Description | -| :-- | :-- | :-- | -| [`userAssignedIdentity`](#parameter-encryptionkekidentityuserassignedidentity) | string | The user assigned identity to be used. | -| [`useSystemAssignedIdentity`](#parameter-encryptionkekidentityusesystemassignedidentity) | bool | Indicate that system assigned identity should be used. | - -### Parameter: `encryption.kekIdentity.userAssignedIdentity` - -The user assigned identity to be used. - -- Required: No -- Type: string - -### Parameter: `encryption.kekIdentity.useSystemAssignedIdentity` - -Indicate that system assigned identity should be used. - -- Required: No -- Type: bool - -### Parameter: `encryption.keyVaultProperties` - -The key vault URI. - -- Required: Yes -- Type: object - -**Optional parameters** - -| Parameter | Type | Description | -| :-- | :-- | :-- | -| [`keyUri`](#parameter-encryptionkeyvaultpropertieskeyuri) | string | The key vault URI. | - -### Parameter: `encryption.keyVaultProperties.keyUri` - -The key vault URI. - -- Required: No -- Type: string - ### Parameter: `location` Location for all resources. @@ -3726,6 +3713,7 @@ This section gives you an overview of all local-referenced module files (i.e., o | Reference | Type | | :-- | :-- | | `br/public:avm/res/network/private-endpoint:0.7.1` | Remote reference | +| `br/public:avm/utl/types/avm-common-types:0.4.0` | Remote reference | ## Data Collection diff --git a/avm/res/recovery-services/vault/main.bicep b/avm/res/recovery-services/vault/main.bicep index 73e63c4220..ffb28e6063 100644 --- a/avm/res/recovery-services/vault/main.bicep +++ b/avm/res/recovery-services/vault/main.bicep @@ -63,14 +63,15 @@ param securitySettings object = {} ]) param publicNetworkAccess string = 'Disabled' -@description('Optional. The encryption settings for the vault.') -param encryption encryptionType - @description('Optional. The redundancy settings of the vault.') -param redundancySettings redundancySettingsType +param redundancySettings redundancySettingsType? @description('Optional. The restore settings of the vault.') -param restoreSettings restoreSettingsType +param restoreSettings restoreSettingsType? + +import { customerManagedKeyWithAutoRotateType } from 'br/public:avm/utl/types/avm-common-types:0.4.0' +@description('Optional. The customer managed key definition.') +param customerManagedKey customerManagedKeyWithAutoRotateType? var formattedUserAssignedIdentities = reduce( map((managedIdentities.?userAssignedResourceIds ?? []), (id) => { '${id}': {} }), @@ -155,6 +156,26 @@ resource avmTelemetry 'Microsoft.Resources/deployments@2024-03-01' = if (enableT } } +resource cMKKeyVault 'Microsoft.KeyVault/vaults@2023-02-01' existing = if (!empty(customerManagedKey.?keyVaultResourceId)) { + name: last(split((customerManagedKey.?keyVaultResourceId ?? 'dummyVault'), '/')) + scope: resourceGroup( + split((customerManagedKey.?keyVaultResourceId ?? '//'), '/')[2], + split((customerManagedKey.?keyVaultResourceId ?? '////'), '/')[4] + ) + + resource cMKKey 'keys@2023-02-01' existing = if (!empty(customerManagedKey.?keyVaultResourceId) && !empty(customerManagedKey.?keyName)) { + name: customerManagedKey.?keyName ?? 'dummyKey' + } +} + +resource cMKUserAssignedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31' existing = if (!empty(customerManagedKey.?userAssignedIdentityResourceId)) { + name: last(split(customerManagedKey.?userAssignedIdentityResourceId ?? 'dummyMsi', '/')) + scope: resourceGroup( + split((customerManagedKey.?userAssignedIdentityResourceId ?? '//'), '/')[2], + split((customerManagedKey.?userAssignedIdentityResourceId ?? '////'), '/')[4] + ) +} + resource rsv 'Microsoft.RecoveryServices/vaults@2024-04-01' = { name: name location: location @@ -168,9 +189,23 @@ resource rsv 'Microsoft.RecoveryServices/vaults@2024-04-01' = { monitoringSettings: !empty(monitoringSettings) ? monitoringSettings : null securitySettings: !empty(securitySettings) ? securitySettings : null publicNetworkAccess: publicNetworkAccess - encryption: !empty(encryption) ? encryption : null redundancySettings: !empty(redundancySettings) ? redundancySettings : null restoreSettings: !empty(restoreSettings) ? restoreSettings : null + encryption: !empty(customerManagedKey) + ? { + infrastructureEncryption: 'Enabled' + kekIdentity: !empty(customerManagedKey.?userAssignedIdentityResourceId) + ? { + userAssignedIdentity: cMKUserAssignedIdentity.id + } + : { + useSystemAssignedIdentity: empty(customerManagedKey.?userAssignedIdentityResourceId) + } + keyVaultProperties: { + keyUri: cMKKeyVault.properties.vaultUri + } + } + : null } } @@ -403,25 +438,19 @@ output privateEndpoints array = [ // Definitions // // =============== // -type encryptionType = { - @description('Optional. The encryption settings for the vault.') - infrastructureEncryption: string? +type customerManagedKeyType = { + @description('Required. The resource ID of a key vault to reference a customer managed key for encryption from.') + keyVaultResourceId: string - @description('Optional. The user assigned identity to be used.') - kekIdentity: { - @description('Optional. The user assigned identity to be used.') - userAssignedIdentity: string? + @description('Required. The name of the customer managed key to use for encryption.') + keyName: string - @description('Optional. Indicate that system assigned identity should be used.') - useSystemAssignedIdentity: bool? - } - @description('Optional. The key vault URI.') - keyVaultProperties: { - @description('Optional. The key vault URI.') - keyUri: string? - } -}? + @description('Optional. The version of the customer managed key to reference for encryption. If not provided, using \'latest\'.') + keyVersion: string? + @description('Optional. User assigned identity to use when fetching the customer managed key. Required if no system assigned identity is available for use.') + userAssignedIdentityResourceId: string? +}? type redundancySettingsType = { @description('Optional. Flag to show if Cross Region Restore is enabled on the Vault or not.') crossRegionRestore: string? diff --git a/avm/res/recovery-services/vault/main.json b/avm/res/recovery-services/vault/main.json index 40b45b5a10..447979e2c4 100644 --- a/avm/res/recovery-services/vault/main.json +++ b/avm/res/recovery-services/vault/main.json @@ -6,58 +6,40 @@ "_generator": { "name": "bicep", "version": "0.31.92.45157", - "templateHash": "14800957207343530226" + "templateHash": "5096948249327950906" }, "name": "Recovery Services Vaults", "description": "This module deploys a Recovery Services Vault.", "owner": "Azure/module-maintainers" }, "definitions": { - "encryptionType": { + "customerManagedKeyType": { "type": "object", "properties": { - "infrastructureEncryption": { + "keyVaultResourceId": { "type": "string", - "nullable": true, "metadata": { - "description": "Optional. The encryption settings for the vault." + "description": "Required. The resource ID of a key vault to reference a customer managed key for encryption from." } }, - "kekIdentity": { - "type": "object", - "properties": { - "userAssignedIdentity": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The user assigned identity to be used." - } - }, - "useSystemAssignedIdentity": { - "type": "bool", - "nullable": true, - "metadata": { - "description": "Optional. Indicate that system assigned identity should be used." - } - } - }, + "keyName": { + "type": "string", "metadata": { - "description": "Optional. The user assigned identity to be used." + "description": "Required. The name of the customer managed key to use for encryption." } }, - "keyVaultProperties": { - "type": "object", - "properties": { - "keyUri": { - "type": "string", - "nullable": true, - "metadata": { - "description": "Optional. The key vault URI." - } - } - }, + "keyVersion": { + "type": "string", + "nullable": true, "metadata": { - "description": "Optional. The key vault URI." + "description": "Optional. The version of the customer managed key to reference for encryption. If not provided, using 'latest'." + } + }, + "userAssignedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. User assigned identity to use when fetching the customer managed key. Required if no system assigned identity is available for use." } } }, @@ -80,8 +62,7 @@ "description": "Optional. The storage redundancy setting of a vault." } } - }, - "nullable": true + } }, "restoreSettingsType": { "type": "object", @@ -101,8 +82,7 @@ "description": "Optional. The restore settings of the vault." } } - }, - "nullable": true + } }, "managedIdentitiesType": { "type": "object", @@ -564,6 +544,50 @@ } }, "nullable": true + }, + "customerManagedKeyWithAutoRotateType": { + "type": "object", + "properties": { + "keyVaultResourceId": { + "type": "string", + "metadata": { + "description": "Required. The resource ID of a key vault to reference a customer managed key for encryption from." + } + }, + "keyName": { + "type": "string", + "metadata": { + "description": "Required. The name of the customer managed key to use for encryption." + } + }, + "keyVersion": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. The version of the customer managed key to reference for encryption. If not provided, using version as per 'autoRotationEnabled' setting." + } + }, + "autoRotationEnabled": { + "type": "bool", + "nullable": true, + "metadata": { + "description": "Optional. Enable or disable auto-rotating to the latest key version. Default is `true`. If set to `false`, the latest key version at the time of the deployment is used." + } + }, + "userAssignedIdentityResourceId": { + "type": "string", + "nullable": true, + "metadata": { + "description": "Optional. User assigned identity to use when fetching the customer managed key. Required if no system assigned identity is available for use." + } + } + }, + "metadata": { + "description": "An AVM-aligned type for a customer-managed key. To be used if the resource type supports auto-rotation of the customer-managed key.", + "__bicep_imported_from!": { + "sourceTemplate": "br:mcr.microsoft.com/bicep/avm/utl/types/avm-common-types:0.4.0" + } + } } }, "parameters": { @@ -698,23 +722,26 @@ "description": "Optional. Whether or not public network access is allowed for this resource. For security reasons it should be disabled." } }, - "encryption": { - "$ref": "#/definitions/encryptionType", - "metadata": { - "description": "Optional. The encryption settings for the vault." - } - }, "redundancySettings": { "$ref": "#/definitions/redundancySettingsType", + "nullable": true, "metadata": { "description": "Optional. The redundancy settings of the vault." } }, "restoreSettings": { "$ref": "#/definitions/restoreSettingsType", + "nullable": true, "metadata": { "description": "Optional. The restore settings of the vault." } + }, + "customerManagedKey": { + "$ref": "#/definitions/customerManagedKeyWithAutoRotateType", + "nullable": true, + "metadata": { + "description": "Optional. The customer managed key definition." + } } }, "variables": { @@ -742,6 +769,18 @@ } }, "resources": { + "cMKKeyVault::cMKKey": { + "condition": "[and(not(empty(tryGet(parameters('customerManagedKey'), 'keyVaultResourceId'))), and(not(empty(tryGet(parameters('customerManagedKey'), 'keyVaultResourceId'))), not(empty(tryGet(parameters('customerManagedKey'), 'keyName')))))]", + "existing": true, + "type": "Microsoft.KeyVault/vaults/keys", + "apiVersion": "2023-02-01", + "subscriptionId": "[split(coalesce(tryGet(parameters('customerManagedKey'), 'keyVaultResourceId'), '//'), '/')[2]]", + "resourceGroup": "[split(coalesce(tryGet(parameters('customerManagedKey'), 'keyVaultResourceId'), '////'), '/')[4]]", + "name": "[format('{0}/{1}', last(split(coalesce(tryGet(parameters('customerManagedKey'), 'keyVaultResourceId'), 'dummyVault'), '/')), coalesce(tryGet(parameters('customerManagedKey'), 'keyName'), 'dummyKey'))]", + "dependsOn": [ + "cMKKeyVault" + ] + }, "avmTelemetry": { "condition": "[parameters('enableTelemetry')]", "type": "Microsoft.Resources/deployments", @@ -762,6 +801,24 @@ } } }, + "cMKKeyVault": { + "condition": "[not(empty(tryGet(parameters('customerManagedKey'), 'keyVaultResourceId')))]", + "existing": true, + "type": "Microsoft.KeyVault/vaults", + "apiVersion": "2023-02-01", + "subscriptionId": "[split(coalesce(tryGet(parameters('customerManagedKey'), 'keyVaultResourceId'), '//'), '/')[2]]", + "resourceGroup": "[split(coalesce(tryGet(parameters('customerManagedKey'), 'keyVaultResourceId'), '////'), '/')[4]]", + "name": "[last(split(coalesce(tryGet(parameters('customerManagedKey'), 'keyVaultResourceId'), 'dummyVault'), '/'))]" + }, + "cMKUserAssignedIdentity": { + "condition": "[not(empty(tryGet(parameters('customerManagedKey'), 'userAssignedIdentityResourceId')))]", + "existing": true, + "type": "Microsoft.ManagedIdentity/userAssignedIdentities", + "apiVersion": "2023-01-31", + "subscriptionId": "[split(coalesce(tryGet(parameters('customerManagedKey'), 'userAssignedIdentityResourceId'), '//'), '/')[2]]", + "resourceGroup": "[split(coalesce(tryGet(parameters('customerManagedKey'), 'userAssignedIdentityResourceId'), '////'), '/')[4]]", + "name": "[last(split(coalesce(tryGet(parameters('customerManagedKey'), 'userAssignedIdentityResourceId'), 'dummyMsi'), '/'))]" + }, "rsv": { "type": "Microsoft.RecoveryServices/vaults", "apiVersion": "2024-04-01", @@ -777,10 +834,14 @@ "monitoringSettings": "[if(not(empty(parameters('monitoringSettings'))), parameters('monitoringSettings'), null())]", "securitySettings": "[if(not(empty(parameters('securitySettings'))), parameters('securitySettings'), null())]", "publicNetworkAccess": "[parameters('publicNetworkAccess')]", - "encryption": "[if(not(empty(parameters('encryption'))), parameters('encryption'), null())]", "redundancySettings": "[if(not(empty(parameters('redundancySettings'))), parameters('redundancySettings'), null())]", - "restoreSettings": "[if(not(empty(parameters('restoreSettings'))), parameters('restoreSettings'), null())]" - } + "restoreSettings": "[if(not(empty(parameters('restoreSettings'))), parameters('restoreSettings'), null())]", + "encryption": "[if(not(empty(parameters('customerManagedKey'))), createObject('infrastructureEncryption', 'Enabled', 'kekIdentity', if(not(empty(tryGet(parameters('customerManagedKey'), 'userAssignedIdentityResourceId'))), createObject('userAssignedIdentity', extensionResourceId(format('/subscriptions/{0}/resourceGroups/{1}', split(coalesce(tryGet(parameters('customerManagedKey'), 'userAssignedIdentityResourceId'), '//'), '/')[2], split(coalesce(tryGet(parameters('customerManagedKey'), 'userAssignedIdentityResourceId'), '////'), '/')[4]), 'Microsoft.ManagedIdentity/userAssignedIdentities', last(split(coalesce(tryGet(parameters('customerManagedKey'), 'userAssignedIdentityResourceId'), 'dummyMsi'), '/')))), createObject('useSystemAssignedIdentity', empty(tryGet(parameters('customerManagedKey'), 'userAssignedIdentityResourceId')))), 'keyVaultProperties', createObject('keyUri', reference('cMKKeyVault').vaultUri)), null())]" + }, + "dependsOn": [ + "cMKKeyVault", + "cMKUserAssignedIdentity" + ] }, "rsv_lock": { "condition": "[and(not(empty(coalesce(parameters('lock'), createObject()))), not(equals(tryGet(parameters('lock'), 'kind'), 'None')))]",