教程:使用 Azure PowerShell 添加角色分配条件以限制对 Blob 的访问

在大多数情况下,角色分配将授予访问 Azure 资源所需的权限。 但在某些情况下,你可能希望通过添加角色分配条件来提供更精细的访问控制。

在本教程中,你将了解如何执行以下操作:

  • 将条件添加到角色分配
  • 基于 blob 索引标记限制对 blob 的访问

重要

Azure 基于属性的访问控制 (Azure ABAC) 已正式发布 (GA),用于使用标准和高级存储帐户性能层中的 requestresourceenvironmentprincipal 属性控制对 Azure Blob 存储、Azure Data Lake Storage Gen2 和 Azure 队列的访问。 目前,“容器元数据”资源属性和“列出 Blob 操作的所含内容”请求属性处于预览状态。 有关 Azure 存储 ABAC 的完整功能状态信息,请参阅 Azure 存储中条件功能的状态

有关 beta 版本、预览版或尚未正式发布的版本的 Azure 功能所适用的法律条款,请参阅 Azure 预览版的补充使用条款

先决条件

有关添加或编辑角色分配条件的先决条件的信息,请参阅有关条件的先决条件

条件

在本教程中,你将使用特定的标记来限制对 blob 的访问。 例如,将条件添加到角色分配,使 Chandra 只能读取带有 Project=Cascade 标记的文件。

带条件的角色分配的关系图。

如果 Chandra 尝试读取不带 Project=Cascade 标记的 Blob,则访问将被拒绝。

显示对带有 Project=Cascade 标记的 blob 进行读取访问的示意图。

下面是条件在代码中的呈现效果:

(
    (
        !(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'
    )
)

步骤 1:安装必备组件

  1. 打开 PowerShell 窗口。

  2. 使用 Get-InstalledModule 检查已安装模块的版本。

    Get-InstalledModule -Name Az
    Get-InstalledModule -Name Az.Resources
    Get-InstalledModule -Name Az.Storage
    
  3. 如果需要,请使用 Install-Module 安装所需版本的 AzAz.ResourcesAz.Storage 模块。

    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. 关闭再重新打开 PowerShell 以刷新会话。

步骤 2:登录到 Azure

  1. 使用 Connect-AzAccount 命令,并按照显示的说明以用户访问管理员所有者身份登录到你的目录。

    Connect-AzAccount -Environment AzureChinaCloud
    
  2. 使用 Get-AzSubscription 列出你的所有订阅。

    Get-AzSubscription
    
  3. 确定订阅 ID 并初始化变量。

    $subscriptionId = "<subscriptionId>"
    
  4. 将订阅设置为活动订阅。

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

步骤 3:创建用户

  1. 使用 New-MgUser 创建用户,或查找现有用户。 本教程使用 Chandra 作为示例。

  2. 初始化用户对象 ID 的变量。

    $userObjectId = "<userObjectId>"
    

步骤 4:设置存储

  1. 使用 New-AzStorageAccount 创建与 Blob 索引功能兼容的存储帐户。 有关详细信息,请查看使用 Blob 索引标记管理和查找 Azure Blob 数据

  2. 使用 New-AzStorageContainer 在存储帐户中创建新的 Blob 容器,并将“匿名访问级别”设置为“专用 (不允许匿名访问)”。

  3. 使用 Set-AzStorageBlobContent 将文本文件上传到该容器。

  4. 将以下 Blob 索引标记添加到文本文件。 有关详细信息,请参阅使用 blob 索引标记管理和查找 Azure Blob 存储中的数据

    注意

    Blob 还能够存储任意用户定义的键值元数据。 尽管元数据与 Blob 索引标记类似,但你也必须将 Blob 索引标记与条件配合使用。

    密钥
    Project Cascade
  5. 将第二个文本文件上传到容器。

  6. 将以下 Blob 索引标记添加到第二个文本文件。

    密钥
    Project Baker
  7. 使用你所用的名称初始化以下变量。

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

步骤 5:分配带条件的角色

  1. 初始化存储 Blob 数据读取者角色变量。

    $roleDefinitionName = "Storage Blob Data Reader"
    $roleDefinitionId = "2a2b9908-6ea1-4ae2-8e65-a410df84e7d1"
    
  2. 初始化资源组的范围。

    $scope = "/subscriptions/$subscriptionId/resourceGroups/$resourceGroup"
    
  3. 初始化条件。

    $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'))"
    

    在 PowerShell 中,如果条件包含美元符号 ($),则必须使用反撇号 (`) 作为其前缀。 例如,此条件使用美元符号来描述标记键名称。

  4. 初始化条件版本和说明。

    $conditionVersion = "2.0"
    $description = "Read access to blobs with the tag Project=Cascade"
    
  5. 使用 New-AzRoleAssignment 将带条件的存储 Blob 数据读取者角色分配到资源组范围的用户。

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

    这是一个输出示例:

    RoleAssignmentId   : /subscriptions/<subscriptionId>/resourceGroups/<resourceGroup>/providers/Microso
                         ft.Authorization/roleAssignments/<roleAssignmentId>
    Scope              : /subscriptions/<subscriptionId>/resourceGroups/<resourceGroup>
    DisplayName        : Chandra
    SignInName         : chandra@contoso.com
    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'))
    

步骤 6:(可选)在 Azure 门户中查看条件

  1. 在 Azure 门户中打开资源组。

  2. 选择“访问控制 (IAM)”。

  3. 在“角色分配”选项卡上找到角色分配。

  4. 在“条件”列中,选择“查看/编辑”以查看条件。

Azure 门户中“添加角色分配条件”的屏幕截图。

步骤 7:测试条件

  1. 打开一个新的 PowerShell 窗口。

  2. 使用 Connect-AzAccount 以 Chandra 的身份登录。

    Connect-AzAccount -Environment AzureChinaCloud
    
  3. 使用你所用的名称初始化以下变量。

    $storageAccountName = "<storageAccountName>"
    $containerName = "<containerName>"
    $blobNameBaker = "<blobNameBaker>"
    $blobNameCascade = "<blobNameCascade>"
    
  4. 使用 New-AzStorageContext 创建特定的上下文,以便更轻松地访问你的存储帐户。

    $bearerCtx = New-AzStorageContext -StorageAccountName $storageAccountName
    
  5. 使用 Get-AzStorageBlob 尝试读取 Baker 项目的文件。

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

    下面是一个输出示例。 请注意,由于添加了上述条件,因此无法读取该文件。

    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. 读取 Cascade 项目的文件。

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

    下面是一个输出示例。 你会发现,由于该项目带有 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
    

步骤 8:(可选)编辑条件

  1. 在另一个 PowerShell 窗口中,使用 Get-AzRoleAssignment 获取添加的角色分配。

    $testRa = Get-AzRoleAssignment -Scope $scope -RoleDefinitionName $roleDefinitionName -ObjectId $userObjectId
    
  2. 编辑条件。

    $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. 初始化条件和说明。

    $testRa.Condition = $condition
    $testRa.Description = "Read access to blobs with the tag Project=Cascade or Project=Baker"
    
  4. 使用 Set-AzRoleAssignment 更新角色分配的条件。

    Set-AzRoleAssignment -InputObject $testRa -PassThru
    

    这是一个输出示例:

    RoleAssignmentId   : /subscriptions/<subscriptionId>/resourceGroups/<resourceGroup>/providers/Microso
                         ft.Authorization/roleAssignments/<roleAssignmentId>
    Scope              : /subscriptions/<subscriptionId>/resourceGroups/<resourceGroup>
    DisplayName        : Chandra
    SignInName         : chandra@contoso.com
    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'))
    

步骤 9:清理资源

  1. 使用 Remove-AzRoleAssignment 删除添加的角色分配和条件。

    Remove-AzRoleAssignment -ObjectId $userObjectId -RoleDefinitionName $roleDefinitionName -ResourceGroupName $resourceGroup
    
  2. 删除创建的存储帐户。

  3. 删除创建的用户。

后续步骤