Tutorial: Add a role assignment condition to restrict access to blobs using Azure PowerShell

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

In this tutorial, you learn how to:

  • Add a condition to a role assignment
  • Restrict access to blobs based on a blob index tag

Important

Azure attribute-based access control (Azure ABAC) is generally available (GA) for controlling access to Azure Blob Storage, Azure Data Lake Storage Gen2, and Azure Queues using request, resource, environment, and principal attributes in both the standard and premium storage account performance tiers. Currently, the container metadata resource attribute and the list blob include request attribute are in PREVIEW. For complete feature status information of ABAC for Azure Storage, see Status of condition features in Azure Storage.

See the Supplemental Terms of Use for Microsoft Azure Previews for legal terms that apply to Azure features that are in beta, preview, or otherwise not yet released into general availability.

Prerequisites

For information about the prerequisites to add or edit role assignment conditions, see Conditions prerequisites.

Condition

In this tutorial, you restrict access to blobs with a specific tag. For example, you add a condition to a role assignment so that Chandra can only read files with the tag Project=Cascade.

Diagram of role assignment with a condition.

If Chandra tries to read a blob without the tag Project=Cascade, access isn't allowed.

Diagram showing read access to blobs with Project=Cascade tag.

Here's what the condition looks like in code:

(
    (
        !(ActionMatches{'Microsoft.Storage/storageAccounts/blobServices/containers/blobs/read'}
        AND NOT
        SubOperationMatches{'Blob.List'})
    )
    OR
    (
        @Resource[Microsoft.Storage/storageAccounts/blobServices/containers/blobs/tags:Project<$key_case_sensitive$>] StringEquals 'Cascade'
    )
)

Step 1: Install prerequisites

  1. Open a PowerShell window.

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

    Get-InstalledModule -Name Az
    Get-InstalledModule -Name Az.Resources
    Get-InstalledModule -Name Az.Storage
    
  3. If necessary, use Install-Module to install the required versions for the Az, Az.Resources, and Az.Storage modules.

    Install-Module -Name Az -RequiredVersion 5.5.0
    Install-Module -Name Az.Resources -RequiredVersion 3.2.1
    Install-Module -Name Az.Storage -RequiredVersion 2.5.2-preview -AllowPrerelease
    
  4. Close and reopen PowerShell to refresh session.

Step 2: Sign in to Azure

  1. Use the Connect-AzAccount command and follow the instructions that appear to sign in to your directory as User Access Administrator or Owner.

    Connect-AzAccount
    
  2. Use Get-AzSubscription to list all of your subscriptions.

    Get-AzSubscription
    
  3. Determine the subscription ID and initialize the variable.

    $subscriptionId = "<subscriptionId>"
    
  4. Set the subscription as the active subscription.

    $context = Get-AzSubscription -SubscriptionId $subscriptionId
    Set-AzContext $context
    

Step 3: Create a user

  1. Use New-MgUser to create a user or find an existing user. This tutorial uses Chandra as the example.

  2. Initialize the variable for the object ID of the user.

    $userObjectId = "<userObjectId>"
    

Step 4: Set up storage

  1. Use New-AzStorageAccount to create a storage account that is compatible with the blob index feature. For more information, see Manage and find Azure Blob data with blob index tags.

  2. Use New-AzStorageContainer to create a new blob container within the storage account and set the anonymous access level to Private (no anonymous access).

  3. Use Set-AzStorageBlobContent to upload a text file to the container.

  4. Add the following blob index tag to the text file. For more information, see Use blob index tags to manage and find data on Azure Blob Storage.

    Note

    Blobs also support the ability to store arbitrary user-defined key-value metadata. Although metadata is similar to blob index tags, you must use blob index tags with conditions.

    Key Value
    Project Cascade
  5. Upload a second text file to the container.

  6. Add the following blob index tag to the second text file.

    Key Value
    Project Baker
  7. Initialize the following variables with the names you used.

    $resourceGroup = "<resourceGroup>"
    $storageAccountName = "<storageAccountName>"
    $containerName = "<containerName>"
    $blobNameCascade = "<blobNameCascade>"
    $blobNameBaker = "<blobNameBaker>"
    

Step 5: Assign a role with a condition

  1. Initialize the Storage Blob Data Reader role variables.

    $roleDefinitionName = "Storage Blob Data Reader"
    $roleDefinitionId = "2a2b9908-6ea1-4ae2-8e65-a410df84e7d1"
    
  2. Initialize the scope for the resource group.

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

    $condition = "((!(ActionMatches{'Microsoft.Storage/storageAccounts/blobServices/containers/blobs/read'} AND NOT SubOperationMatches{'Blob.List'})) OR (@Resource[Microsoft.Storage/storageAccounts/blobServices/containers/blobs/tags:Project<`$key_case_sensitive`$>] StringEquals 'Cascade'))"
    

    In PowerShell, if your condition includes a dollar sign ($), you must prefix it with a backtick (`). For example, this condition uses dollar signs to delineate the tag key name.

  4. Initialize the condition version and description.

    $conditionVersion = "2.0"
    $description = "Read access to blobs with the tag Project=Cascade"
    
  5. Use New-AzRoleAssignment to assign the Storage Blob Data Reader role with a condition to the user at a resource group scope.

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

    Here's an example of the output:

    RoleAssignmentId   : /subscriptions/<subscriptionId>/resourceGroups/<resourceGroup>/providers/Microso
                         ft.Authorization/roleAssignments/<roleAssignmentId>
    Scope              : /subscriptions/<subscriptionId>/resourceGroups/<resourceGroup>
    DisplayName        : Chandra
    SignInName         : [email protected]
    RoleDefinitionName : Storage Blob Data Reader
    RoleDefinitionId   : 2a2b9908-6ea1-4ae2-8e65-a410df84e7d1
    ObjectId           : <userObjectId>
    ObjectType         : User
    CanDelegate        : False
    Description        : Read access to blobs with the tag Project=Cascade
    ConditionVersion   : 2.0
    Condition          : ((!(ActionMatches{'Microsoft.Storage/storageAccounts/blobServices/containers/blobs/read'} AND NOT
                         SubOperationMatches{'Blob.List'})) OR
                         (@Resource[Microsoft.Storage/storageAccounts/blobServices/co
                         ntainers/blobs/tags:Project<$key_case_sensitive$>] StringEquals 'Cascade'))
    

Step 6: (Optional) View the condition in the Azure portal

  1. In the Azure portal, open the resource group.

  2. Select Access control (IAM).

  3. On the Role assignments tab, find the role assignment.

  4. In the Condition column, select View/Edit to view the condition.

Screenshot of Add role assignment condition in the Azure portal.

Step 7: Test the condition

  1. Open a new PowerShell window.

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

    Connect-AzAccount
    
  3. Initialize the following variables with the names you used.

    $storageAccountName = "<storageAccountName>"
    $containerName = "<containerName>"
    $blobNameBaker = "<blobNameBaker>"
    $blobNameCascade = "<blobNameCascade>"
    
  4. Use New-AzStorageContext to create a specific context to access your storage account more easily.

    $bearerCtx = New-AzStorageContext -StorageAccountName $storageAccountName
    
  5. Use Get-AzStorageBlob to try to read the file for the Baker project.

    Get-AzStorageBlob -Container $containerName -Blob $blobNameBaker -Context $bearerCtx 
    

    Here's an example of the output. Notice that you can't read the file because of the condition you added.

    Get-AzStorageBlob : This request is not authorized to perform this operation using this permission. HTTP Status Code:
    403 - HTTP Error Message: This request is not authorized to perform this operation using this permission.
    ErrorCode: AuthorizationPermissionMismatch
    ErrorMessage: This request is not authorized to perform this operation using this permission.
    RequestId: <requestId>
    Time: Sat, 24 Apr 2021 13:26:25 GMT
    At line:1 char:1
    + Get-AzStorageBlob -Container $containerName -Blob $blobNameBaker -Con ...
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        + CategoryInfo          : CloseError: (:) [Get-AzStorageBlob], StorageException
        + FullyQualifiedErrorId : StorageException,Microsoft.WindowsAzure.Commands.Storage.Blob.Cmdlet.GetAzureStorageBlob
       Command
    
  6. Read the file for the Cascade project.

    Get-AzStorageBlob -Container $containerName -Blob $blobNameCascade -Context $bearerCtx 
    

    Here's an example of the output. Notice that you can read the file because it has the tag Project=Cascade.

       AccountName: <storageAccountName>, ContainerName: <containerName>
    
    Name                 BlobType  Length          ContentType                    LastModified         AccessTier SnapshotT
                                                                                                                  ime
    ----                 --------  ------          -----------                    ------------         ---------- ---------
    CascadeFile.txt      BlockBlob 7               text/plain                     2021-04-24 05:35:24Z Hot
    

Step 8: (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
    
  2. Edit the condition.

    $condition = "((!(ActionMatches{'Microsoft.Storage/storageAccounts/blobServices/containers/blobs/read'} AND NOT SubOperationMatches{'Blob.List'})) OR (@Resource[Microsoft.Storage/storageAccounts/blobServices/containers/blobs/tags:Project<`$key_case_sensitive`$>] StringEquals 'Cascade' OR @Resource[Microsoft.Storage/storageAccounts/blobServices/containers/blobs/tags:Project<`$key_case_sensitive`$>] StringEquals 'Baker'))"
    
  3. Initialize the condition and description.

    $testRa.Condition = $condition
    $testRa.Description = "Read access to blobs with the tag Project=Cascade or Project=Baker"
    
  4. Use Set-AzRoleAssignment to update the condition for the role assignment.

    Set-AzRoleAssignment -InputObject $testRa -PassThru
    

    Here's an example of the output:

    RoleAssignmentId   : /subscriptions/<subscriptionId>/resourceGroups/<resourceGroup>/providers/Microso
                         ft.Authorization/roleAssignments/<roleAssignmentId>
    Scope              : /subscriptions/<subscriptionId>/resourceGroups/<resourceGroup>
    DisplayName        : Chandra
    SignInName         : [email protected]
    RoleDefinitionName : Storage Blob Data Reader
    RoleDefinitionId   : 2a2b9908-6ea1-4ae2-8e65-a410df84e7d1
    ObjectId           : <userObjectId>
    ObjectType         : User
    CanDelegate        : False
    Description        : Read access to blobs with the tag Project=Cascade or Project=Baker
    ConditionVersion   : 2.0
    Condition          : ((!(ActionMatches{'Microsoft.Storage/storageAccounts/blobServices/containers/blobs/read'} AND NOT
                         SubOperationMatches{'Blob.List'})) OR
                         (@Resource[Microsoft.Storage/storageAccounts/blobServices/co
                         ntainers/blobs/tags:Project<$key_case_sensitive$>] StringEquals 'Cascade' OR @Resource[Microsoft.S
                         torage/storageAccounts/blobServices/containers/blobs/tags:Project<$key_case_sensitive$>]
                         StringEquals 'Baker'))
    

Step 9: Clean up resources

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

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

  3. Delete the user you created.

Next steps