diff --git a/arm/Microsoft.Compute/diskEncryptionSets/.bicep/nested_kvAccessPolicy.bicep b/arm/Microsoft.Compute/diskEncryptionSets/.bicep/nested_kvAccessPolicy.bicep new file mode 100644 index 0000000000..3f8c479dc1 --- /dev/null +++ b/arm/Microsoft.Compute/diskEncryptionSets/.bicep/nested_kvAccessPolicy.bicep @@ -0,0 +1,36 @@ +@description('Required. The name of the key vault') +param keyVaultName string + +@description('Optional. An array of 0 to 16 identities that have access to the key vault. All identities in the array must use the same tenant ID as the key vault\'s tenant ID.') +param accessPolicies array = [] + +@description('Optional. The access policy name') +param name string = 'add' + +var formattedAccessPolicies = [for accessPolicy in accessPolicies: { + applicationId: contains(accessPolicy, 'applicationId') ? accessPolicy.applicationId : '' + objectId: contains(accessPolicy, 'objectId') ? accessPolicy.objectId : '' + permissions: accessPolicy.permissions + tenantId: contains(accessPolicy, 'tenantId') ? accessPolicy.tenantId : tenant().tenantId +}] + +resource keyVault 'Microsoft.KeyVault/vaults@2021-06-01-preview' existing = { + name: keyVaultName +} + +resource policies 'Microsoft.KeyVault/vaults/accessPolicies@2021-06-01-preview' = { + name: name + parent: keyVault + properties: { + accessPolicies: formattedAccessPolicies + } +} + +@description('The name of the resource group the access policies assignment was created in.') +output accessPolicyResourceGroup string = resourceGroup().name + +@description('The name of the access policies assignment') +output accessPolicyName string = policies.name + +@description('The resource ID of the access policies assignment') +output accessPolicyResourceId string = policies.id diff --git a/arm/Microsoft.Compute/diskEncryptionSets/deploy.bicep b/arm/Microsoft.Compute/diskEncryptionSets/deploy.bicep index 332fd6cae3..6039850e71 100644 --- a/arm/Microsoft.Compute/diskEncryptionSets/deploy.bicep +++ b/arm/Microsoft.Compute/diskEncryptionSets/deploy.bicep @@ -10,10 +10,20 @@ param keyVaultId string @description('Required. Key URL (with version) pointing to a key or secret in KeyVault.') param keyUrl string +@description('Optional. The type of key used to encrypt the data of the disk.') +@allowed([ + 'EncryptionAtRestWithCustomerKey' + 'EncryptionAtRestWithPlatformAndCustomerKeys' +]) +param encryptionType string = 'EncryptionAtRestWithCustomerKey' + +@description('Optional. Set this flag to true to enable auto-updating of this disk encryption set to the latest key version.') +param rotationToLatestKeyVersionEnabled bool = false + @description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, you can provide either the display name of the role definition, or its fully qualified ID in the following format: \'/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11\'') param roleAssignments array = [] -@description('Optional. Tags of the Automation Account resource.') +@description('Optional. Tags of the disk encryption resource.') param tags object = {} @description('Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered') @@ -24,13 +34,33 @@ module pid_cuaId '.bicep/nested_cuaId.bicep' = if (!empty(cuaId)) { params: {} } -resource keyVaultAccessPolicies 'Microsoft.KeyVault/vaults/accessPolicies@2019-09-01' = { - name: '${last(split(keyVaultId, '/'))}/add' +resource diskEncryptionSet 'Microsoft.Compute/diskEncryptionSets@2021-04-01' = { + name: name + location: location + tags: tags + identity: { + type: 'SystemAssigned' + } properties: { + activeKey: { + sourceVault: { + id: keyVaultId + } + keyUrl: keyUrl + } + encryptionType: encryptionType + rotationToLatestKeyVersionEnabled: rotationToLatestKeyVersionEnabled + } +} + +module keyVaultAccessPolicies '.bicep/nested_kvAccessPolicy.bicep' = { + name: '${uniqueString(deployment().name, location)}-DiskEncrSet-KVAccessPolicies' + params: { + keyVaultName: last(split(keyVaultId, '/')) accessPolicies: [ { tenantId: subscription().tenantId - objectId: reference('Microsoft.Compute/diskEncryptionSets/${diskEncryptionSet.name}', '2020-12-01', 'Full').identity.principalId + objectId: diskEncryptionSet.identity.principalId permissions: { keys: [ 'get' @@ -43,23 +73,8 @@ resource keyVaultAccessPolicies 'Microsoft.KeyVault/vaults/accessPolicies@2019-0 } ] } -} - -resource diskEncryptionSet 'Microsoft.Compute/diskEncryptionSets@2020-12-01' = { - name: name - location: location - tags: tags - identity: { - type: 'SystemAssigned' - } - properties: { - activeKey: { - sourceVault: { - id: keyVaultId - } - keyUrl: keyUrl - } - } + // This is to support access policies to KV in different subscription and resource group than the disk encryption set. + scope: resourceGroup(split(keyVaultId, '/')[2], split(keyVaultId, '/')[4]) } module diskEncryptionSet_rbac '.bicep/nested_rbac.bicep' = [for (roleAssignment, index) in roleAssignments: { diff --git a/arm/Microsoft.Compute/diskEncryptionSets/readme.md b/arm/Microsoft.Compute/diskEncryptionSets/readme.md index 72127509c1..e656a38f7a 100644 --- a/arm/Microsoft.Compute/diskEncryptionSets/readme.md +++ b/arm/Microsoft.Compute/diskEncryptionSets/readme.md @@ -7,20 +7,22 @@ This template deploys a disk encryption set. | Resource Type | API Version | | :-- | :-- | | `Microsoft.Authorization/roleAssignments` | 2020-04-01-preview | -| `Microsoft.Compute/diskEncryptionSets` | 2020-12-01 | -| `Microsoft.KeyVault/vaults/accessPolicies` | 2019-09-01 | +| `Microsoft.Compute/diskEncryptionSets` | 2021-04-01 | +| `Microsoft.KeyVault/vaults/accessPolicies` | 2021-06-01-preview | ## Parameters | Parameter Name | Type | Default Value | Possible Values | Description | | :-- | :-- | :-- | :-- | :-- | | `cuaId` | string | | | Optional. Customer Usage Attribution ID (GUID). This GUID must be previously registered | +| `encryptionType` | string | `EncryptionAtRestWithCustomerKey` | `[EncryptionAtRestWithCustomerKey, EncryptionAtRestWithPlatformAndCustomerKeys]` | Optional. The type of key used to encrypt the data of the disk. | | `keyUrl` | string | | | Required. Key URL (with version) pointing to a key or secret in KeyVault. | | `keyVaultId` | string | | | Required. Resource ID of the KeyVault containing the key or secret. | | `location` | string | `[resourceGroup().location]` | | Optional. Resource location. | | `name` | string | | | Required. The name of the disk encryption set that is being created. | | `roleAssignments` | array | `[]` | | Optional. Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, you can provide either the display name of the role definition, or its fully qualified ID in the following format: '/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11' | -| `tags` | object | `{object}` | | Optional. Tags of the Automation Account resource. | +| `rotationToLatestKeyVersionEnabled` | bool | | | Optional. Set this flag to true to enable auto-updating of this disk encryption set to the latest key version. | +| `tags` | object | `{object}` | | Optional. Tags of the disk encryption resource. | ### Parameter Usage: `roleAssignments` @@ -73,6 +75,6 @@ Tag names and tag values can be provided as needed. A tag can be left without a ## Template references +- [Diskencryptionsets](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Compute/2021-04-01/diskEncryptionSets) - [Roleassignments](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2020-04-01-preview/roleAssignments) -- [Diskencryptionsets](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Compute/2020-12-01/diskEncryptionSets) -- [Vaults/Accesspolicies](https://docs.microsoft.com/en-us/azure/templates/Microsoft.KeyVault/2019-09-01/vaults/accessPolicies) +- [Vaults/Accesspolicies](https://docs.microsoft.com/en-us/azure/templates/Microsoft.KeyVault/2021-06-01-preview/vaults/accessPolicies) diff --git a/utilities/pipelines/resourceRemoval/helper/Invoke-ResourceRemoval.ps1 b/utilities/pipelines/resourceRemoval/helper/Invoke-ResourceRemoval.ps1 index 14f9891773..1fd2854397 100644 --- a/utilities/pipelines/resourceRemoval/helper/Invoke-ResourceRemoval.ps1 +++ b/utilities/pipelines/resourceRemoval/helper/Invoke-ResourceRemoval.ps1 @@ -27,6 +27,9 @@ function Invoke-ResourceRemoval { [string] $Type ) + Write-Verbose ('Resource ID [{0}]' -f $resourceId) -Verbose + Write-Verbose ('Resource Type [{0}]' -f $type) -Verbose + switch ($type) { 'Microsoft.Insights/diagnosticSettings' { $parentResourceId = $resourceId.Split('/providers/{0}' -f $type)[0] @@ -36,6 +39,33 @@ function Invoke-ResourceRemoval { } break } + 'Microsoft.KeyVault/vaults/accessPolicies' { + Write-Verbose ('Skip resource removal for type [{0}]. Reason: handled by different logic.' -f $type) -Verbose + break + } + 'Microsoft.Compute/diskEncryptionSets' { + # Pre-Removal + # ----------- + # Remove access policies on key vault + $resourceGroupName = $resourceId.Split('/')[4] + $resourceName = Split-Path $resourceId -Leaf + + $diskEncryptionSet = Get-AzDiskEncryptionSet -Name $resourceName -ResourceGroupName $resourceGroupName + $keyVaultResourceId = $diskEncryptionSet.ActiveKey.SourceVault.Id + $keyVaultName = Split-Path $keyVaultResourceId -Leaf + $objectId = $diskEncryptionSet.Identity.PrincipalId + + Write-Verbose ('keyVaultResourceId [{0}]' -f $keyVaultResourceId) -Verbose + Write-Verbose ('objectId [{0}]' -f $objectId) -Verbose + if ($PSCmdlet.ShouldProcess(('Access policy [{0}] from key vault [{1}]' -f $objectId, $keyVaultName), 'Remove')) { + $null = Remove-AzKeyVaultAccessPolicy -VaultName $keyVaultName -ObjectId $objectId + } + + # Actual removal + # -------------- + $null = Remove-AzResource -ResourceId $resourceId -Force -ErrorAction 'Stop' + break + } 'Microsoft.RecoveryServices/vaults' { # Pre-Removal # ----------- diff --git a/utilities/pipelines/sharedScripts/Set-EnvironmentOnAgent.ps1 b/utilities/pipelines/sharedScripts/Set-EnvironmentOnAgent.ps1 index 72149ff01a..da2aa354f5 100644 --- a/utilities/pipelines/sharedScripts/Set-EnvironmentOnAgent.ps1 +++ b/utilities/pipelines/sharedScripts/Set-EnvironmentOnAgent.ps1 @@ -97,6 +97,7 @@ function Set-EnvironmentOnAgent { [Parameter(Mandatory = $false)] [Hashtable[]] $Modules = @( @{ Name = 'Az.Accounts' }, + @{ Name = 'Az.Compute' }, @{ Name = 'Az.Resources' }, @{ Name = 'Az.NetAppFiles' }, @{ Name = 'Az.Network' },