Edit

Add role assignment conditions for Key Vault secrets by using Azure PowerShell (preview)

Note

Azure ABAC for Key Vault is in preview. Some aspects might change before general availability. For preview terms, see the supplemental terms of use.

In most cases, an Azure role assignment grants the permissions you need to Azure resources. In some cases, you might want more granular access control by adding a role assignment condition.

This article shows how to use Azure PowerShell to add an Azure attribute-based access control (Azure ABAC) condition to a Key Vault role assignment so that a principal can only read secrets whose names start with a specific prefix.

For the full set of supported actions and attributes, see Actions and attributes for Azure Key Vault ABAC conditions (preview).

Important

ABAC conditions only work when the key vault's permission model is set to Azure role-based access control. Legacy vault access policies don't support conditions.

Prerequisites

  • For information about the prerequisites to add or edit role assignment conditions, see Conditions prerequisites.
  • The target key vault must have its permission model set to Azure role-based access control.
  • Azure PowerShell installed locally, or use Azure Cloud Shell.

Condition

In this article, you restrict access to secrets whose names begin with test-app. If the user tries to read a secret without the test-app name prefix, access isn't allowed.

Here's what the condition looks like:

(
  (
    !(ActionMatches{'Microsoft.KeyVault/vaults/secrets/getSecret/action'})
  )
  OR
  (
    @Resource[Microsoft.KeyVault/vaults/secrets:name] StringStartsWith 'test-app'
  )
)

Step 1: Install prerequisites

  1. Open a PowerShell window.

  2. Use Get-InstalledModule to check the versions of installed modules.

    Get-InstalledModule -Name Az
    Get-InstalledModule -Name Az.Resources
    Get-InstalledModule -Name Az.KeyVault
    Get-InstalledModule -Name Microsoft.Graph.Users
    
  3. If necessary, use Install-Module to install the required versions of the Az, Az.Resources, and Az.KeyVault modules. You only need the Microsoft.Graph.Users module if you plan to create a new user with New-MgUser in Step 3; you can skip it if you reuse an existing user.

    Install-Module -Name Az
    Install-Module -Name Az.Resources
    Install-Module -Name Az.KeyVault
    Install-Module -Name Microsoft.Graph.Users
    
  4. Close and reopen PowerShell to refresh the session.

Step 2: Sign in to Azure

  1. Use Connect-AzAccount and follow the instructions to sign in as a User Access Administrator or Owner.

    Connect-AzAccount
    
  2. Use Get-AzSubscription to list your subscriptions. Format the output as a list so the full subscription IDs aren't truncated.

    Get-AzSubscription | Format-List Name, Id, TenantId
    

    Alternatively, display the results in a table with an untruncated Id column:

    Get-AzSubscription | Format-Table Name, Id, State -AutoSize
    
  3. Set your subscription as the active subscription.

    $subscriptionId = "<subscriptionId>"
    $context = Get-AzSubscription -SubscriptionId $subscriptionId
    Set-AzContext $context
    

Step 3: Create a user

Use New-MgUser to create a user, or find an existing user. This article uses User1 as the example.

Note

New-MgUser belongs to the Microsoft.Graph.Users module (installed in Step 1), not to the Az modules. It also requires a separate Microsoft Graph sign-in from Connect-AzAccount. Before you run it, connect with the User.ReadWrite.All scope:

Connect-MgGraph -Scopes "User.ReadWrite.All"

If you're reusing an existing user, you can skip both the Microsoft.Graph.Users module and Connect-MgGraph and supply that user's object ID.

Initialize a variable with the user's object ID.

$userObjectId = "<userObjectId>"

Step 4: Set up the key vault

  1. Use New-AzKeyVault to create a key vault that uses Azure RBAC as its permission model.

    New-AzKeyVault -Name "<keyVaultName>" -ResourceGroupName "<resourceGroup>" -Location "<location>"
    

    Note

    In Az.KeyVault 6.0.0 and later, Azure RBAC is the default permission model, so you don't need to specify an extra switch. The -EnableRbacAuthorization switch was removed in 6.0.0. If you include it, the command now fails with A parameter cannot be found that matches parameter name 'EnableRbacAuthorization'. Use -DisableRbacAuthorization only if you explicitly want the legacy vault access policy model instead.

    If you're running an older Az.KeyVault version (earlier than 6.0.0), RBAC isn't the default, so you must add the -EnableRbacAuthorization switch:

    New-AzKeyVault -Name "<keyVaultName>" -ResourceGroupName "<resourceGroup>" -Location "<location>" -EnableRbacAuthorization
    

    Check your installed version with Get-InstalledModule -Name Az.KeyVault.

  2. Grant yourself a Key Vault data-plane role so you can create secrets. When a vault uses Azure RBAC (the default), control-plane roles such as Owner or Contributor don't grant access to secret values. Without a data-plane role, Set-AzKeyVaultSecret fails with Operation returned an invalid status code 'Forbidden' and Assignment: (not found).

    # Object ID of the signed-in user (use -UserPrincipalName "you@tenant.com" if this returns nothing)
    $me = (Get-AzADUser -SignedIn).Id
    
    # Scope the assignment to the vault you just created
    $vaultScope = "/subscriptions/$subscriptionId/resourceGroups/<resourceGroup>/providers/Microsoft.KeyVault/vaults/<keyVaultName>"
    
    New-AzRoleAssignment -ObjectId $me `
      -RoleDefinitionName "Key Vault Secrets Officer" `
      -Scope $vaultScope
    

    Note

    Use Key Vault Secrets Officer to create and manage secret values, or Key Vault Administrator for full data-plane access. Key Vault Secrets User is read-only. After you assign a role, wait 1–5 minutes for propagation before you run the next command. A Forbidden error immediately after assignment usually means the role hasn't propagated yet.

  3. Use Set-AzKeyVaultSecret to create a secret named test-app-secret1.

    $secretValue = ConvertTo-SecureString "<secretValue>" -AsPlainText -Force
    Set-AzKeyVaultSecret -VaultName "<keyVaultName>" -Name "test-app-secret1" -SecretValue $secretValue
    

    Note

    The secret name is the resource attribute evaluated by the condition. Choose names that reflect the prefix you plan to restrict access to.

  4. Create a second secret named test-db-password.

    Set-AzKeyVaultSecret -VaultName "<keyVaultName>" -Name "test-db-password" -SecretValue $secretValue
    
  5. Initialize variables with the names you used.

    $resourceGroup = "<resourceGroup>"
    $keyVaultName = "<keyVaultName>"
    $secretNameAllowed = "test-app-secret1"
    $secretNameDenied = "test-db-password"
    

Step 5: Assign a role with a condition

  1. Initialize the Key Vault Secrets User role variables.

    $roleDefinitionName = "Key Vault Secrets User"
    $roleDefinitionId = "4633458b-17de-408a-b874-0445c86b69e6"
    
  2. Initialize the scope for the resource group. If you didn't set the $resourceGroup variable earlier in this session, set it to the name of the resource group that contains your key vault.

    $resourceGroup = "<resourceGroup>"
    $scope = "/subscriptions/$subscriptionId/resourceGroups/$resourceGroup"
    
  3. Initialize the condition.

    $condition = "((!(ActionMatches{'Microsoft.KeyVault/vaults/secrets/getSecret/action'})) OR (@Resource[Microsoft.KeyVault/vaults/secrets:name] StringStartsWith 'test-app'))"
    

    Important

    The condition must be a single-line string. Multi-line conditions are rejected. If you build the condition in a here-string or across multiple lines, flatten it first:

    $condition = $condition -replace '\s+', ' '
    

    In PowerShell, if your condition includes a dollar sign ($), prefix it with a backtick (`).

  4. Initialize the condition version and description.

    $conditionVersion = "2.0"
    $description = "Read access to secrets whose names start with test-app"
    
  5. Use New-AzRoleAssignment to assign the Key Vault Secrets User role with a condition to the user at resource group scope.

    New-AzRoleAssignment -ObjectId $userObjectId -Scope $scope -RoleDefinitionId $roleDefinitionId -Description $description -Condition $condition -ConditionVersion $conditionVersion
    

    Example output:

    RoleAssignmentId   : /subscriptions/<subscriptionId>/resourceGroups/<resourceGroup>/providers/Microsoft.Authorization/roleAssignments/<roleAssignmentId>
    Scope              : /subscriptions/<subscriptionId>/resourceGroups/<resourceGroup>
    DisplayName        : User1
    SignInName         : user1@contoso.com
    RoleDefinitionName : Key Vault Secrets User
    RoleDefinitionId   : 4633458b-17de-408a-b874-0445c86b69e6
    ObjectId           : <userObjectId>
    ObjectType         : User
    CanDelegate        : False
    Description        : Read access to secrets whose names start with test-app
    ConditionVersion   : 2.0
    Condition          : ((!(ActionMatches{'Microsoft.KeyVault/vaults/secrets/getSecret/action'})) OR (@Resource[Microsoft.KeyVault/vaults/secrets:name] StringStartsWith 'test-app'))
    

Step 6: Test the condition

  1. Open a new PowerShell window.

  2. Use Connect-AzAccount to sign in as User1.

    Connect-AzAccount
    
  3. Initialize the variables you used earlier.

    $keyVaultName = "<keyVaultName>"
    $secretNameAllowed = "test-app-secret1"
    $secretNameDenied = "test-db-password"
    
  4. Use Get-AzKeyVaultSecret to try to read the denied secret.

    Get-AzKeyVaultSecret -VaultName $keyVaultName -Name $secretNameDenied -AsPlainText
    

    Example output. Notice that the read fails because of the condition:

    Get-AzKeyVaultSecret : Operation returned an invalid status code 'Forbidden'
    Caller is not authorized to perform action on resource.
    If role assignments, deny assignments or role definitions changed
    recently, please observe propagation time.
    ...
    ForbiddenByRbac
    
  5. Read the secret whose name starts with test-app.

    Get-AzKeyVaultSecret -VaultName $keyVaultName -Name $secretNameAllowed -AsPlainText
    

    You can read this secret because its name starts with test-app.

Step 7: (Optional) Edit the condition

  1. In the other PowerShell window, use Get-AzRoleAssignment to get the role assignment you added.

    $testRa = Get-AzRoleAssignment -Scope $scope -RoleDefinitionName $roleDefinitionName -ObjectId $userObjectId | Where-Object { $_.Scope -eq $scope }
    

    Important

    Get-AzRoleAssignment also returns assignments inherited from higher scopes (for example, the same role assigned at the subscription level). If the principal holds this role at more than one scope, $testRa becomes an array, and the next step fails with The property 'Condition' cannot be found on this object. The Where-Object { $_.Scope -eq $scope } filter keeps only the assignment at your resource group scope so $testRa is a single object.

  2. Edit the condition to also allow secrets whose names start with api-.

    $condition = "((!(ActionMatches{'Microsoft.KeyVault/vaults/secrets/getSecret/action'})) OR (@Resource[Microsoft.KeyVault/vaults/secrets:name] StringStartsWith 'test-app' OR @Resource[Microsoft.KeyVault/vaults/secrets:name] StringStartsWith 'api-'))"
    

    For the Get secret action, this condition allows reading a secret only if its name starts with test-app or api-. All other actions pass through the condition normally.

  3. Update the condition and description on the assignment.

    $testRa.Condition = $condition
    $testRa.Description = "Read access to secrets whose names start with test-app or api-"
    
  4. Use Set-AzRoleAssignment to save the change.

    Set-AzRoleAssignment -InputObject $testRa -PassThru
    

Step 8: Clean up resources

  1. Use Remove-AzRoleAssignment to remove the role assignment and condition.

    Remove-AzRoleAssignment -ObjectId $userObjectId -RoleDefinitionName $roleDefinitionName -ResourceGroupName $resourceGroup
    
  2. Delete the key vault you created.

  3. Delete the user you created.