You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Deploying blob storage with CMK and rbac-enabled keyVault fails due to a race condition. It seems that role assignments are applied inside storage managed identity only after a small delay. An explicit wait (using a deployment script) works around the issue (but is, of course, fragile).
To Reproduce
Deploy an rbac-enabled keyVault containing a CMK
give an MI permissions (rbac) to the keyVault
create a key
deploy blob storage using the key and with the MI as identity
The deployment will fail with the error message
[{"code":"KeyVaultAuthenticationFailure","message":"The operation failed because of authentication issue on the keyvault.
Additional context
the issue does not occur if access policies are used instead of rbac on the keyVault
the deployment is successful if the deployment is retried
This code does not work:
@description('Specifies the name of the environment.')
paramenvironmentstring
@description('Specifies the name of the deployment.')
@minLength(1)
@maxLength(10)
paramcustomerAssetstring
@description('Set soft delete retention in days for key vault')
paramsoftDeleteRetentionInDaysint
@description('We only use 2 letters as a unique suffix so that we adhere to the Naming Rules and Character Restrictions, see https://learn.microsoft.com/en-us/azure/azure-resource-manager/management/resource-name-rules')
varuniqueSuffix = substring(uniqueString(resourceGroup().id), 0, 2)
varregion = 'gwc'varstorageAccountName = 'st${customerAsset}${environment}${region}${uniqueSuffix}'varstorageIdentityName = 'id-${customerAsset}-${environment}-${region}-storage${uniqueSuffix}'varstorageAccountKeyName = 'key-${customerAsset}-${environment}-${region}-storage${uniqueSuffix}'varkeyVaultName = 'kv-${customerAsset}-${environment}-${region}${uniqueSuffix}'resourcestorageIdentity'Microsoft.ManagedIdentity/userAssignedIdentities@2022-01-31-preview' = {
name: storageIdentityNamelocation: resourceGroup().locationtags: resourceGroup().tags
}
resourcekeyVault'Microsoft.KeyVault/vaults@2023-07-01' = {
name: keyVaultNamelocation: resourceGroup().locationtags: resourceGroup().tagsproperties: {
tenantId: subscription().tenantIdsku: {
name: 'standard'family: 'A'
}
enablePurgeProtection: trueenableSoftDelete: truesoftDeleteRetentionInDays: softDeleteRetentionInDaysenableRbacAuthorization: true
}
}
@description('This is the built-in Key Vault Crypto Service Encryption User role ')
resourcekeyVaultCryptoServiceEncryptionUserRole'Microsoft.Authorization/roleDefinitions@2022-04-01'existing = {
name: 'e147488a-f6f5-4113-8e2d-b22465e65bf6'
}
resourcekeyVaultCryptoServiceEncryptionUserAssignment'Microsoft.Authorization/roleAssignments@2022-04-01' = {
name: guid(keyVaultCryptoServiceEncryptionUserRole.id, storageIdentity.id, keyVault.id)
scope: keyVaultproperties: {
description: 'Allow access to perform cryptographic operations using keys.'roleDefinitionId: keyVaultCryptoServiceEncryptionUserRole.idprincipalId: storageIdentity.properties.principalIdprincipalType: 'ServicePrincipal'
}
}
@description('This is the built-in Key Vault Reader role. See https://docs.microsoft.com/azure/role-based-access-control/built-in-roles/security#key-vault-reader')
resourcekeyVaultReaderRole'Microsoft.Authorization/roleDefinitions@2022-04-01'existing = {
name: '21090545-7ca7-4776-b22c-e363652d74d2'
}
resourcekeyVaultReaderRoleAssignment'Microsoft.Authorization/roleAssignments@2022-04-01' = {
name: guid(keyVaultReaderRole.id, storageIdentity.id, keyVault.id)
scope: keyVaultproperties: {
description: 'Read metadata of key vaults and its certificates, keys, and secrets.'roleDefinitionId: keyVaultReaderRole.idprincipalId: storageIdentity.properties.principalIdprincipalType: 'ServicePrincipal'
}
}
resourcestorageAccountKey'Microsoft.KeyVault/vaults/keys@2023-07-01' = {
parent: keyVaultname: storageAccountKeyNametags: resourceGroup().tagsproperties: {
kty: 'RSA'keySize: 4096rotationPolicy: {
lifetimeActions: [
{
trigger: {
timeAfterCreate: 'P1Y'
}
action: {
type: 'rotate'
}
}
{
trigger: {
timeBeforeExpiry: 'P30D'
}
action: {
type: 'notify'
}
}
]
}
attributes: {
enabled: true
}
}
}
resourcestorageAccount'Microsoft.Storage/storageAccounts@2023-05-01' = {
name: storageAccountNamelocation: resourceGroup().locationtags: resourceGroup().tagssku: {
name: 'Standard_LRS'
}
identity: {
type: 'UserAssigned'userAssignedIdentities: { '${storageIdentity.id}': {} }
}
kind: 'StorageV2'properties: {
accessTier: 'Hot'supportsHttpsTrafficOnly: trueminimumTlsVersion: 'TLS1_2'encryption: {
services: {
blob: {
enabled: truekeyType: 'Account'
}
file: {
enabled: truekeyType: 'Account'
}
queue: {
enabled: truekeyType: 'Account'
}
table: {
enabled: truekeyType: 'Account'
}
}
keySource: 'Microsoft.Keyvault'identity: {
userAssignedIdentity: storageIdentity.id
}
keyvaultproperties: {
keyname: storageAccountKey.namekeyvaulturi: keyVault.properties.vaultUri
}
}
}
dependsOn: [
keyVaultReaderRoleAssignmentkeyVaultCryptoServiceEncryptionUserAssignment
]
}
This is working code:
@description('Specifies the name of the environment.')
paramenvironmentstring
@description('Specifies the name of the deployment.')
@minLength(1)
@maxLength(10)
paramcustomerAssetstring
@description('Set soft delete retention in days for key vault')
paramsoftDeleteRetentionInDaysint
@description('We only use 2 letters as a unique suffix so that we adhere to the Naming Rules and Character Restrictions, see https://learn.microsoft.com/en-us/azure/azure-resource-manager/management/resource-name-rules')
varuniqueSuffix = substring(uniqueString(resourceGroup().id), 0, 2)
varregion = 'gwc'varstorageAccountName = 'st${customerAsset}${environment}${region}${uniqueSuffix}'varstorageIdentityName = 'id-${customerAsset}-${environment}-${region}-storage${uniqueSuffix}'varstorageAccountKeyName = 'key-${customerAsset}-${environment}-${region}-storage${uniqueSuffix}'varkeyVaultName = 'kv-${customerAsset}-${environment}-${region}${uniqueSuffix}'resourcestorageIdentity'Microsoft.ManagedIdentity/userAssignedIdentities@2022-01-31-preview' = {
name: storageIdentityNamelocation: resourceGroup().locationtags: resourceGroup().tags
}
resourcekeyVault'Microsoft.KeyVault/vaults@2023-07-01' = {
name: keyVaultNamelocation: resourceGroup().locationtags: resourceGroup().tagsproperties: {
tenantId: subscription().tenantIdsku: {
name: 'standard'family: 'A'
}
/* networkAcls: networkAcls */enablePurgeProtection: trueenableSoftDelete: truesoftDeleteRetentionInDays: softDeleteRetentionInDaysenableRbacAuthorization: true
}
}
@description('This is the built-in Key Vault Crypto Service Encryption User role ')
resourcekeyVaultCryptoServiceEncryptionUserRole'Microsoft.Authorization/roleDefinitions@2022-04-01'existing = {
name: 'e147488a-f6f5-4113-8e2d-b22465e65bf6'
}
resourcekeyVaultCryptoServiceEncryptionUserAssignment'Microsoft.Authorization/roleAssignments@2022-04-01' = {
name: guid(keyVaultCryptoServiceEncryptionUserRole.id, storageIdentity.id, keyVault.id)
scope: keyVaultproperties: {
description: 'Allow access to perform cryptographic operations using keys.'roleDefinitionId: keyVaultCryptoServiceEncryptionUserRole.idprincipalId: storageIdentity.properties.principalIdprincipalType: 'ServicePrincipal'
}
}
@description('This is the built-in Key Vault Reader role. See https://docs.microsoft.com/azure/role-based-access-control/built-in-roles/security#key-vault-reader')
resourcekeyVaultReaderRole'Microsoft.Authorization/roleDefinitions@2022-04-01'existing = {
name: '21090545-7ca7-4776-b22c-e363652d74d2'
}
resourcekeyVaultReaderRoleAssignment'Microsoft.Authorization/roleAssignments@2022-04-01' = {
name: guid(keyVaultReaderRole.id, storageIdentity.id, keyVault.id)
scope: keyVaultproperties: {
description: 'Read metadata of key vaults and its certificates, keys, and secrets.'roleDefinitionId: keyVaultReaderRole.idprincipalId: storageIdentity.properties.principalIdprincipalType: 'ServicePrincipal'
}
}
resourcestorageAccountKey'Microsoft.KeyVault/vaults/keys@2023-07-01' = {
parent: keyVaultname: storageAccountKeyNametags: resourceGroup().tagsproperties: {
kty: 'RSA'keySize: 4096rotationPolicy: {
lifetimeActions: [
{
trigger: {
timeAfterCreate: 'P1Y'
}
action: {
type: 'rotate'
}
}
{
trigger: {
timeBeforeExpiry: 'P30D'
}
action: {
type: 'notify'
}
}
]
}
attributes: {
enabled: true
}
}
}
resourcedeploymentScript'Microsoft.Resources/deploymentScripts@2023-08-01' = {
name: 'inlineCLI'location: resourceGroup().locationkind: 'AzureCLI'properties: {
azCliVersion: '2.52.0'scriptContent: ''' sleep 10s '''retentionInterval: 'PT1H'
}
dependsOn: [
keyVaultReaderRoleAssignmentkeyVaultCryptoServiceEncryptionUserAssignment
]
}
resourcestorageAccount'Microsoft.Storage/storageAccounts@2023-05-01' = {
name: storageAccountNamelocation: resourceGroup().locationtags: resourceGroup().tagssku: {
name: 'Standard_LRS'
}
identity: {
type: 'UserAssigned'userAssignedIdentities: { '${storageIdentity.id}': {} }
}
kind: 'StorageV2'properties: {
accessTier: 'Hot'supportsHttpsTrafficOnly: trueminimumTlsVersion: 'TLS1_2'encryption: {
services: {
blob: {
enabled: truekeyType: 'Account'
}
file: {
enabled: truekeyType: 'Account'
}
queue: {
enabled: truekeyType: 'Account'
}
table: {
enabled: truekeyType: 'Account'
}
}
keySource: 'Microsoft.Keyvault'identity: {
userAssignedIdentity: storageIdentity.id
}
keyvaultproperties: {
keyname: storageAccountKey.namekeyvaulturi: keyVault.properties.vaultUri
}
}
}
dependsOn: [
deploymentScript
]
}
The text was updated successfully, but these errors were encountered:
Bicep version
Bicep CLI version 0.33.93 (7a77c7f)
Describe the bug
Deploying blob storage with CMK and rbac-enabled keyVault fails due to a race condition. It seems that role assignments are applied inside storage managed identity only after a small delay. An explicit wait (using a deployment script) works around the issue (but is, of course, fragile).
To Reproduce
The deployment will fail with the error message
[{"code":"KeyVaultAuthenticationFailure","message":"The operation failed because of authentication issue on the keyvault.
Additional context
This code does not work:
This is working code:
The text was updated successfully, but these errors were encountered: