修正对 blob 数据的匿名读取访问(Azure 资源管理器部署)

Azure Blob 存储支持对容器和 blob 进行可选的匿名读取访问。 但是,匿名访问可能会带来安全风险。 建议禁用匿名访问,以获得最佳安全性。 禁止匿名访问有助于防止意外匿名访问导致的数据泄露。

默认情况下,始终会禁止对 blob 数据的匿名访问。 Azure 资源管理器存储帐户的默认配置禁止用户配置对存储帐户中的容器和 blob 的匿名访问。 此默认配置不允许所有对 Azure 资源管理器存储帐户的匿名访问,无视单个容器的访问设置。

不允许对存储帐户进行匿名访问时,Azure 存储会拒绝针对 blob 数据的所有匿名读取请求。 用户以后无法为该帐户中的容器配置匿名访问。 已配置匿名访问的所有容器将不再接受匿名请求。

警告

为容器配置了匿名访问时,任何客户端都可以读取该容器中的数据。 匿名访问会带来潜在的安全风险,因此,如果你的方案不需要匿名访问,建议禁止对存储帐户进行匿名访问。

Azure 资源管理器与经典存储帐户的修正

本文介绍如何使用 DRAG(检测-修正-审核-治理)框架持续管理使用 Azure 资源管理器部署模型的存储帐户的匿名访问。 所有常规用途 v2 存储帐户、高级块 Blob 存储帐户、高级文件共享帐户和 Blob 存储帐户都使用 Azure 资源管理器部署模型。 某些较旧的常规用途 v1 帐户和高级页 Blob 帐户可能使用经典部署模型。

如果存储帐户使用经典部署模型,建议尽快迁移到 Azure 资源管理器部署模型。 使用经典部署模型的 Azure 存储帐户将于 2024 年 8 月 31 日停用。 有关详细信息,请参阅 Azure 经典存储帐户将于 2024 年 8 月 31 日停用

如果目前无法迁移经典存储帐户,则应立即修正对这些帐户的匿名访问。 若要了解如何修正经典存储帐户的匿名访问,请参阅修正对 blob 数据的匿名读取访问(经典部署)。 有关 Azure 部署模型的详细信息,请参阅资源管理器和经典部署

关于匿名读取访问

默认情况下,系统始终禁止对数据进行匿名访问。 有两个单独的设置会影响匿名访问:

  1. 存储帐户的匿名访问设置。 Azure 资源管理器存储帐户提供了一个设置,用于允许或禁止对该帐户进行匿名访问。 Azure 建议禁止对存储帐户进行匿名访问,确保安全性最高。

    当在帐户级别允许匿名访问时,无法对 blob 数据进行匿名读取访问,除非用户采取额外步骤显式配置了容器的匿名访问设置。

  2. 配置容器的匿名访问设置。 默认情况下,容器的匿名访问设置被禁用,这意味着对容器或其数据的每个请求都需要授权。 仅当允许了对存储帐户进行匿名访问时,具有适当权限的用户才能修改容器的匿名访问设置以启用匿名访问。

下表总结了这两个设置如何共同影响对容器的匿名访问。

容器的匿名访问级别设置为“专用”(默认设置) 容器的匿名访问级别设置为“容器” 容器的匿名访问级别设置为“Blob”
禁止对存储帐户进行匿名访问 无法对存储帐户中的任何容器进行匿名访问。 无法对存储帐户中的任何容器进行匿名访问。 存储帐户设置替代容器设置。 无法对存储帐户中的任何容器进行匿名访问。 存储帐户设置替代容器设置。
允许对存储帐户进行匿名访问 无法对此容器进行匿名访问(默认配置)。 可以对此容器及其 blob 进行匿名访问。 可以对此容器中的 blob 进行匿名访问,但无法对容器本身进行匿名访问。

当允许存储帐户匿名访问并为特定容器配置匿名访问时,服务将接受读取该容器中 Blob 的请求,但不使用 Authorization 标头传递该请求,并在响应中返回 Blob 的数据。 但是,如果使用 Authorization 标头传递该请求,则会忽略存储帐户上的匿名访问,并且根据提供的凭据对请求进行授权。

检测来自客户端应用程序的匿名请求

如果你禁止对存储帐户的匿名读取访问,系统可能会拒绝对当前配置了匿名访问的容器和 blob 的请求。 禁止对存储帐户的匿名访问这一设置将替代该存储帐户中各个容器的访问设置。 禁止对存储帐户的匿名访问后,将来对该帐户的任何匿名请求都会失败。

为了了解禁止匿名访问对客户端应用程序造成的影响,建议你为该帐户启用日志记录和指标,并分析一段时间间隔内的匿名请求的模式。 使用指标来确定对存储帐户的匿名请求数,并使用日志来确定匿名访问了哪些容器。

使用指标资源管理器监视匿名请求

若要跟踪对存储帐户的匿名请求,请在 Azure 门户中使用 Azure 指标资源管理器。 若要详细了解指标资源管理器,请参阅使用 Azure Monitor 指标资源管理器分析指标

按照以下步骤创建跟踪匿名请求的指标:

  1. 导航到 Azure 门户中的存储帐户。 在“监视”部分下,选择“指标” 。

  2. 选择添加指标。 在“指标”对话框中,指定以下值:

    1. 将“作用域”字段设置为存储帐户的名称。
    2. 将“指标命名空间”设置为“Blob”。 此指标仅报告对 Blob 存储的请求。
    3. 将“指标”字段设置为“事务”。
    4. 将“聚合”字段设置为“求和”。

    新指标显示给定时间间隔内针对 Blob 存储的事务数之和。 生成的指标如下图所示:

    屏幕截图显示了如何将指标配置为对 blob 事务数求和

  3. 接下来,选择“添加筛选器”按钮,为匿名请求创建基于指标的筛选器。

  4. 在“筛选器”对话框中,指定以下值:

    1. 将属性值设置为“身份验证”。
    2. 将“运算符”字段设置为等号 (=)。
    3. 通过从下拉列表中选择或输入将“值”字段设置为“匿名”。
  5. 在右上角,选择要查看指标的时间间隔。 还可以通过指定从 1 分钟到 1 个月的时间间隔,来指示请求聚合粒度。

配置指标后,匿名请求将开始显示在图形上。 下图显示了在过去 30 分钟内聚合的匿名请求。

屏幕截图显示了对 Blob 存储的聚合匿名请求

你还可以配置警报规则,让系统在针对你的存储帐户发出的匿名请求达到一定数量时通知你。 有关详细信息,请参阅使用 Azure Monitor 创建、查看和管理指标警报

分析日志以识别接收匿名请求的容器

Azure 存储日志会捕获有关针对存储帐户发出的请求的详细信息,包括请求的授权方式。 可以分析这些日志,以确定接收匿名请求的容器。

若要记录针对 Azure 存储帐户发出的请求以评估匿名请求,可以使用 Azure Monitor 中的 Azure 存储日志记录。 有关详细信息,请参阅监视 Azure 存储

Azure Monitor 中的 Azure 存储日志记录支持使用日志查询来分析日志数据。 若要查询日志,可以使用 Azure Log Analytics 工作区。 若要详细了解日志查询,请参阅教程:Log Analytics 查询入门

在 Azure 门户中创建诊断设置

若要使用 Azure Monitor 记录 Azure 存储数据并使用 Azure Log Analytics 对其进行分析,必须先创建一项诊断设置,用于指示要记录其数据的请求类型和存储服务。 配置存储帐户的日志记录后,日志将在 Log Analytics 工作区中提供。 若要创建工作区,请参阅在 Azure 门户中创建 Log Analytics 工作区

若要了解如何在 Azure 入口中创建诊断设置,请参阅在 Azure Monitor 中创建诊断设置

有关 Azure Monitor 的 Azure 存储日志中可用字段的参考,请参阅资源日志

查询匿名请求的日志

Azure Monitor 中的 Azure 存储日志包括用于对存储帐户发出请求的授权类型。 在日志查询中,根据 AuthenticationType 属性筛选以查看匿名请求。

若要检索过去 7 天针对 Blob 存储发出的匿名请求的日志,请打开你的 Log Analytics 工作区。 接下来,将以下查询粘贴到新的日志查询中并运行该查询:

StorageBlobLogs
| where TimeGenerated > ago(7d) and AuthenticationType == "Anonymous"
| project TimeGenerated, AccountName, AuthenticationType, Uri

还可以基于此查询配置警报规则,以接收有关匿名请求的通知。 有关详细信息,请参阅使用 Azure Monitor 创建、查看和管理日志警报

对匿名请求的响应

当 Blob 存储收到匿名请求时,如果满足以下所有条件,该请求将成功:

  • 允许对存储帐户进行匿名访问。
  • 目标容器配置为允许匿名访问。
  • 请求用于读取访问。

如果上述任一条件不为 true,则请求会失败。 失败时的响应代码取决于是否使用支持持有者质询的服务版本发出匿名请求。 服务版本 2019-12-12 及更新版本支持持有者质询:

  • 如果使用支持持有者质询的服务版本发出匿名请求,服务会返回错误代码 401(未授权)。
  • 如果使用不支持持有者质询的服务版本发出匿名请求,并且不允许对存储帐户进行匿名访问,服务会返回错误代码 409(冲突)。
  • 如果使用不支持持有者质询的服务版本发出匿名请求,并且允许对存储帐户进行匿名访问,服务会返回错误代码 404(未找到)。

有关持有者质询的详细信息,请参阅持有者质询

修正存储帐户的匿名访问

评估对存储帐户中容器和 Blob 的匿名请求后,可以通过将帐户的 AllowBlobPublicAccess 属性设置为 False 来采取措施修正整个帐户的匿名访问。

存储帐户的匿名访问设置会替代该帐户中容器的单个设置。 如果禁止对存储帐户的匿名访问,则任何配置为允许匿名访问的容器将不再可匿名访问。 如果禁止对帐户进行匿名访问,则不需要再禁用对单个容器的匿名访问。

如果你的方案要求某些容器可供匿名访问,则应将这些容器及其 blob 移到为匿名访问保留的单独存储帐户中。 然后,你可以禁止对任何其他存储帐户的匿名访问。

修正匿名访问需要 Azure 存储资源提供程序的 2019-04-01 或更高版本。 有关详细信息,请参阅 Azure 存储资源提供程序 REST API

禁止匿名访问的权限

若要为存储帐户设置 AllowBlobPublicAccess 属性,用户必须有权创建和管理存储帐户。 提供这些权限的 Azure 基于角色的访问控制 (Azure RBAC) 角色包含 Microsoft.Storage/storageAccounts/write 操作。 具有此操作的内置角色包括:

角色分配的范围必须设定为存储帐户级别或更高级别,以禁止对存储帐户进行匿名访问。 有关角色范围的详细信息,请参阅了解 Azure RBAC 的范围

注意,请仅向需要创建存储帐户或更新其属性的权限的那些管理用户分配这些角色。 使用最小特权原则确保用户拥有完成任务所需的最少权限。 有关使用 Azure RBAC 管理访问权限的详细信息,请参阅 Azure RBAC 最佳做法

这些角色未提供通过 Microsoft Entra ID 访问存储帐户中数据的访问权限。 但是,它们包含 Microsoft.Storage/storageAccounts/listkeys/action,可以授予对帐户访问密钥的访问权限。 借助此权限,用户可以使用帐户访问密钥访问存储帐户中的所有数据。

Microsoft.Storage/storageAccounts/listkeys/action 本身通过帐户密钥授予数据访问权限,但不授予用户更改存储帐户的 AllowBlobPublicAccess 属性的能力。 对于需要访问你的存储帐户中的数据但不能更改该存储帐户配置的用户,请考虑分配存储 Blob 数据参与者存储 Blob 数据读取者读取者和数据访问等角色。

注意

经典订阅管理员角色“服务管理员”和“共同管理员”具有 Azure 资源管理器所有者角色的等效权限。 “所有者”角色包含所有操作,因此具有这些管理角色之一的用户也可以创建存储帐户和管理帐户配置。 有关详细信息,请参阅 Azure 角色、Azure AD 角色和经典订阅管理员角色

将存储帐户的 AllowBlobPublicAccess 属性设置为 False

若要禁止对存储帐户的匿名访问,请将帐户的 AllowBlobPublicAccess 属性设为 False

重要

禁止对存储帐户的匿名访问这一设置会替代该存储帐户中所有容器的访问设置。 禁止对存储帐户的匿名访问后,将来对该帐户的任何匿名请求都会失败。 在更改此设置之前,请务必按照检测来自客户端应用程序的匿名请求中所述的步骤,了解可能对匿名访问存储帐户中数据的客户端应用程序的影响。

若要在 Azure 门户中禁止对存储帐户的匿名访问,请执行以下步骤:

  1. 导航到 Azure 门户中的存储帐户。

  2. 在“设置”下找到“配置”设置。

  3. 将“允许 Blob 匿名访问”设置为“禁用”。

    显示如何禁止对帐户的匿名访问的屏幕截图

注意

禁止对存储帐户的匿名访问不会影响该存储帐户中承载的任何静态网站。 $web 容器始终可供公共访问。

更新存储帐户的匿名访问设置后,可能需要长达 30 秒的时间才能完全传播所做的更改。

批量修正的示例脚本

以下示例 PowerShell 脚本针对订阅中的所有 Azure 资源管理器存储帐户运行,并将这些帐户的 AllowBlobPublicAccess 设置设为 False。

<#
.SYNOPSIS
Finds storage accounts in a subscription where AllowBlobPublicAccess is True or null.

.DESCRIPTION
This script runs against all Azure Resource Manager storage accounts in a subscription
and sets the "AllowBlobPublicAccess" property to False.

Standard operation will enumerate all accounts where the setting is enabled and allow the 
user to decide whether or not to disable the setting.  

Classic storage accounts will require individual adjustment of containers to remove public
access, and will not be affected by this script.

Run with BypassConfirmation=$true if you wish to disallow public access on all Azure Resource Manager 
storage accounts without individual confirmation.

You will need access to the subscription to run the script.

.PARAMETER BypassConformation
Set this to $true to skip confirmation of changes. Not recommended.

.PARAMETER SubscriptionId
The subscription ID of the subscription to check.

.PARAMETER ReadOnly
Set this parameter so that the script makes no changes to any subscriptions and only reports affect accounts.

.PARAMETER NoSignin
Set this parameter so that no sign-in occurs -- you must sign in first. Use this if you're invoking this script repeatedly for multiple subscriptions and want to avoid being prompted to sign-in for each subscription.

.OUTPUTS
This command produces only STDOUT output (not standard PowerShell) with information about affect accounts.
#>
param(
    [boolean]$BypassConfirmation = $false,
    [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = 'SubscriptionId')]
    [String] $SubscriptionId,
    [switch] $ReadOnly, # Use this if you don't want to make changes, but want to get information about affected accounts
    [switch] $NoSignin # Use this if you are already signed in and don't want to be prompted again
)

begin {
    if ( ! $NoSignin.IsPresent ) {
        Login-AzAccount -Environment AzureChinaCloud | Out-Null
    }
}

process {
    try {
        Select-AzSubscription -SubscriptionId $SubscriptionId -ErrorAction Stop | Out-Null
    }
    catch {
        Write-Error "Unable to access select subscription '$SubscriptionId' as the signed in user -- ensure that you have access to this subscription." -ErrorAction Stop
    }

    foreach ($account in Get-AzStorageAccount) {
        if ($null -eq $account.AllowBlobPublicAccess -or $account.AllowBlobPublicAccess -eq $true) {
            Write-host "Account:" $account.StorageAccountName " isn't disallowing public access."

            if ( ! $ReadOnly.IsPresent ) {
                if (!$BypassConfirmation) {
                    $confirmation = Read-Host "Do you wish to disallow public access? [y/n]"
                }
                if ($BypassConfirmation -or $confirmation -eq 'y') {
                    try {
                        Set-AzStorageAccount -Name $account.StorageAccountName -ResourceGroupName $account.ResourceGroupName -AllowBlobPublicAccess $false
                        Write-Host "Success!"
                    }
                    catch {
                        Write-Output $_
                    }
                }
            }
        }
        elseif ($account.AllowBlobPublicAccess -eq $false) {
            Write-Host "Account:" $account.StorageAccountName "has public access disabled, no action required."
        }
        else {
            Write-Host "Account:" $account.StorageAccountName ". Error, please manually investigate."
        }
    }
}

end {
    Write-Host "Script complete"
}

检查多个帐户的匿名访问设置

若要检查具有最佳性能的一组存储帐户的匿名访问设置,可以使用 Azure 门户中的 Azure Resource Graph 浏览器。 若要详细了解如何使用 Resource Graph 资源管理器,请参阅快速入门:使用 Azure Resource Graph 资源管理器运行你的第一个 Resource Graph 查询

在 Resource Graph 浏览器中运行以下查询会返回存储帐户的列表,并显示每个帐户的匿名访问设置:

resources
| where type =~ 'Microsoft.Storage/storageAccounts'
| extend allowBlobPublicAccess = parse_json(properties).allowBlobPublicAccess
| project subscriptionId, resourceGroup, name, allowBlobPublicAccess

下图显示了整个订阅中的查询结果。 对于已显式设置了 AllowBlobPublicAccess 属性的存储帐户,它在结果中显示为 true 或 false。 如果尚未为存储帐户设置 AllowBlobPublicAccess 属性,则它在查询结果中显示为空白(或 null)。

屏幕截图显示各个存储帐户中针对匿名访问设置的查询结果

使用 Azure Policy 审核合规性

如果你有大量存储帐户,则可能需要执行审核,以确保将这些帐户配置为阻止匿名访问。 若要审核一组存储帐户的合规性,请使用 Azure Policy。 Azure Policy 是一项服务,可用于创建、分配和管理将规则应用于 Azure 资源的策略。 Azure Policy 可帮助你确保这些资源始终符合公司标准和服务级别协议。 有关详细信息,请参阅 Azure Policy 概述

创建具有 Audit 效果的策略

Azure Policy 支持的效果决定了针对资源评估某个策略规则时会发生什么情况。 当资源不合规时,审核效果会创建一个警告,但不会停止请求。 有关效果的详细信息,请参阅了解 Azure Policy 效果

若要通过 Azure 门户为存储帐户的匿名访问设置创建具有“审核”效果的策略,请执行以下步骤:

  1. 在 Azure 门户中,导航到 Azure Policy 服务。

  2. 在“创作”部分下,选择“定义”。

  3. 选择“添加策略定义”以创建新的策略定义。

  4. 对于“定义位置”字段,选择“更多”按钮以指定审核策略资源所在的位置。

  5. 指定策略的名称。 还可以指定说明和类别。

  6. 在“策略规则”下,将以下策略定义添加到“policyRule”部分。

    {
      "if": {
        "allOf": [
          {
            "field": "type",
            "equals": "Microsoft.Storage/storageAccounts"
          },
          {
            "not": {
              "field":"Microsoft.Storage/storageAccounts/allowBlobPublicAccess",
              "equals": "false"
            }
          }
        ]
      },
      "then": {
        "effect": "audit"
      }
    }
    
  7. 保存策略。

分配策略

接下来,将策略分配给资源。 策略的作用域对应于该资源及其下的所有资源。 有关策略分配的详细信息,请参阅 Azure Policy 分配结构

若要在 Azure 门户中分配策略,请执行下列步骤:

  1. 在 Azure 门户中,导航到 Azure Policy 服务。
  2. 在“创作”部分下,选择“分配”。
  3. 选择“分配策略”以创建新的策略分配。
  4. 对于“作用域”字段,请选择策略分配的作用域。
  5. 对于“策略定义”字段,请选择“更多”按钮,然后从列表中选择你在上一部分定义的策略。
  6. 提供策略分配的名称。 说明是可选的。
  7. 让“策略强制实施”设置为“启用”状态。 此设置对审核策略没有影响。
  8. 选择“查看 + 创建”以创建分配。

查看合规性报告

分配策略后,你可以查看合规性报告。 审核策略的合规性报告会指出哪些存储帐户不符合策略。 有关详细信息,请参阅获取策略合规性数据

创建策略分配后,合规性报告可能需要几分钟时间才会变得可用。

若要在 Azure 门户中查看合规性报告,请执行以下步骤:

  1. 在 Azure 门户中,导航到 Azure Policy 服务。

  2. 选择“合规性”。

  3. 筛选你在上一步创建的策略分配名称的结果。 该报告显示有多少资源不符合策略。

  4. 你可以在报告中向下钻取以获取更多详细信息,包括不合规的存储帐户的列表。

    屏幕截图显示针对匿名访问的审核策略的合规性报告

使用 Azure Policy 强制实施授权访问

Azure Policy 可以确保 Azure 资源符合要求和标准,从而为云治理提供支持。 若要确保组织中的存储帐户仅允许经授权的请求,可以创建一个策略,用以阻止创建其匿名访问设置允许匿名请求的新存储帐户。 如果现有帐户的匿名访问设置不符合策略,则此策略还会阻止对该帐户进行的所有配置更改。

此强制实施策略会使用“拒绝”效果来阻止将创建或修改存储帐户以允许匿名访问的请求。 有关效果的详细信息,请参阅了解 Azure Policy 效果

若要为允许匿名请求的匿名访问设置创建具有“拒绝”效果的策略,请执行使用 Azure Policy 审核合规性中所述的步骤,但要在策略定义的“policyRule”部分提供以下 JSON:

{
  "if": {
    "allOf": [
      {
        "field": "type",
        "equals": "Microsoft.Storage/storageAccounts"
      },
      {
        "not": {
          "field":"Microsoft.Storage/storageAccounts/allowBlobPublicAccess",
          "equals": "false"
        }
      }
    ]
  },
  "then": {
    "effect": "deny"
  }
}

在你创建具有“拒绝”效果的策略并将其分配给作用域后,用户无法创建允许匿名访问的存储帐户。 用户也不能对当前允许匿名访问的现有存储帐户进行任何配置更改。 如果尝试这样做,将会导致错误。 必须将存储帐户的匿名访问设置设为 false,然后才能继续创建或配置帐户。

下图显示了在以下情况下发生的错误:当具有“拒绝”效果的策略要求禁止匿名访问时,你尝试创建允许匿名访问的存储帐户。

屏幕截图显示了在违反策略的情况下创建存储帐户时出现的错误

后续步骤