作为管理员,你可以锁定 Azure 订阅、资源组或资源,以防止用户意外删除和修改它们。 锁会替代任何用户权限。
可以设置锁来防止删除或修改。 在门户中,这些锁称为“删除”和“只读”。 在命令行中,这些锁称为 CanNotDelete 和 ReadOnly。
- CanNotDelete 表示已获授权的用户可以读取和修改某个资源,但不能删除该资源。
- ReadOnly 表示已获授权的用户可以读取某个资源,但不能删除或更新该资源。 应用此锁类似于将所有已获授权的用户限制于使用“读取者”角色提供的权限。
与基于角色的访问控制(RBAC)不同,可以使用管理锁跨所有用户和角色应用限制。 若要了解如何为用户和角色设置权限,请参阅 Azure RBAC。
锁继承
在父范围应用锁时,该范围内所有资源都会继承相同的锁。 即使是以后添加的资源也会继承同一父锁。 继承链中限制性最大的锁优先。
扩展资源 会继承它们所应用的目标资源的锁定。 例如,Microsoft.Insights/diagnosticSettings 是扩展资源类型。 如果将诊断设置应用到存储 Blob 并锁定存储帐户,则无法删除诊断设置。 此继承是合理的,因为诊断设置的完整资源 ID 为:
/subscriptions/{sub-id}/resourceGroups/{rg-name}/providers/Microsoft.Storage/storageAccounts/{storage-name}/blobServices/default/providers/microsoft.insights/diagnosticSettings/{setting-name}"
锁定资源的资源 ID 必须与以下格式匹配:
/subscriptions/{sub-id}/resourceGroups/{rg-name}/providers/Microsoft.Storage/storageAccounts/{storage-name}
如果你对某个资源拥有“删除”锁并尝试删除其资源组,该功能会阻止整个删除操作。 即使资源组或资源组中的其他资源已解锁,也不会发生删除操作。 无法进行部分删除。
- 资源锁不会阻止取消该订阅。
- Azure 通过停用资源而不是立即删除它们来保留资源。
- Azure 只会在等待期过后才永久删除资源。
了解锁的作用域
注意
锁仅适用于控制平面 Azure 操作,而不适用于数据平面操作。
Azure 控制平面操作转到 https://management.chinacloudapi.cn。 Azure 数据平面操作转到服务实例,例如 https://myaccount.blob.core.chinacloudapi.cn/。 有关详细信息,请参阅 Azure 控制平面和数据平面 。 要了解哪些操作使用控制平面 URL,请参阅 Azure REST API。
这种差别意味着,锁可以防止资源遭到更改,但不限制资源执行其功能的方式。 例如,SQL 数据库逻辑服务器上的 ReadOnly 锁可防止删除或修改。 它允许在服务器数据库中创建、更新或删除数据。 数据平面操作允许数据事务。 这些请求不会转到 https://management.chinacloudapi.cn。
应用锁之前的注意事项
应用锁可能会导致意外结果。 某些看似没有修改资源的操作需要被阻止的操作。 锁定可防止 POST 方法将数据发送到 Azure 资源管理器 API。 阻止的操作的一些常见示例包括:
- 存储帐户上的只读锁阻止用户列出帐户密钥。 POST 请求处理 Azure 存储列出密钥操作,以保护对帐户密钥的访问。 帐户密钥提供对存储帐户中数据的完整访问权限。 如果为存储帐户配置了只读锁,则没有帐户密钥的用户需要使用 Microsoft Entra 凭据才能访问 blob 或队列数据。 只读锁还阻止分配存储帐户或数据容器(blob 容器或队列)范围内的 Azure RBAC 角色。 
- 存储帐户上的只读锁可以防止范围限定为存储帐户或数据容器(blob 容器或队列)的 RBAC 分配。 
- 存储帐户上的只读锁会阻止创建 Blob 容器。 
- 存储帐户上的只读锁会阻止创建 Blob 容器。 但是,可以通过控制平面和数据平面在存储帐户上创建操作。 只读锁仅阻止控制平面创建请求,但用户仍可以通过数据平面对资源执行有效的创建操作。 
- 存储帐户上的只读锁或无法删除锁不会保护其数据不被删除或修改。 它也不能保护 Blob、队列、表或文件中的数据。 
- 存储帐户 API 会公开数据平面和控制平面操作。 如果请求使用数据平面操作,那么存储帐户上的锁不会保护该存储帐户中的 Blob、队列、表或文件数据。 但是,如果请求使用 控制平面 操作,锁将保护这些资源。 - 例如,如果请求使用 文件共享 - 删除,一种控制平面操作,则删除将失败。 如果请求使用Delete Share,作为数据平面操作,删除操作将成功完成。 我们建议使用控制平面操作。 
- 在网络安全组(NSG)上的只读锁可防止创建相应的 NSG 流日志。 NSG 上的无法删除锁不会阻止创建或修改相应的 NSG 流日志。 
- 应用服务资源上的只读锁将阻止 Visual Studio 服务器资源管理器显示资源的文件,因为该交互需要写入访问权限。 
- 包含应用服务计划的资源组上的 read-only 锁会阻止你纵向或横向扩展计划。 
- 包含虚拟机的资源组上的 read-only 锁将阻止所有用户启动或重启该虚拟机。 这些操作需要 POST 方法请求。 
- 资源组上的只读锁可防止将现有资源移入或移出资源组。 但是,可以将具有只读锁 的资源 移到另一个资源组。 
- 包含自动化帐户的资源组上的只读锁会阻止所有 Runbook 启动。 这些操作需要 POST 方法请求。 
- 资源或资源组上的“无法删除”锁会阻止删除 Azure RBAC 分配。 
- 资源组上的无法删除锁可防止 Resource Manager 自动删除历史记录中的已部署项目。 如果历史记录中达到 800 个部署,则部署会失败。 
- 当 Azure 备份服务创建的资源组上存在无法删除的锁定时,备份会失败。 该服务最多支持 18 个还原点。 锁定后,备份服务无法清理还原点。 有关详细信息,请参阅常见问题解答 - 备份 Azure VM。 
- 包含 Azure 机器学习工作区的资源组上的无法删除锁可防止自动缩放 Azure 机器学习计算群集正常工作。 使用该锁,自动缩放功能将无法删除未使用的节点。 解决方案使用的资源多于工作负载所需的资源。 
- Log Analytics 工作区上的只读锁会阻止启用“用户和实体行为分析(UEBA)”。 
- Log Analytics 工作区上的“不可删除”锁不会阻止数据清除操作, 而是从用户中删除 数据清除器 角色。 
- 订阅上的只读锁会导致 Azure 顾问无法正常运行。 顾问无法存储其查询的结果。 
- 应用程序网关上的只读锁将阻止获取应用程序网关的后端运行状况。 该操作使用 POST 方法 - 一个 read-only 锁阻止方法。 
- Azure Kubernetes 服务 (AKS) 群集上的只读锁可以限制如何通过门户访问群集资源。 只读锁可以防止使用 Azure 门户中的 AKS 群集 Kubernetes 资源部分来选择群集资源。 这些操作需要通过 POST 方法请求进行身份验证。 
- 在受Site Recovery保护的虚拟机上设置的无法删除锁可以防止您在移除保护或禁用复制时删除与 Site Recovery 相关的某些资源链接。 如果以后计划再次保护虚拟机,请先删除锁定,然后再禁用保护。 如果不删除锁,则需要执行某些步骤来清理过时的链接,然后才能保护虚拟机。 有关详细信息,请参阅 排查 Azure 到 Azure VM 复制错误。 
- 对于 PostgreSQL,虚拟网络不应在虚拟网络或子网级别设置任何资源锁,因为锁可能会干扰网络和域名系统作。 在虚拟网络中创建服务器之前,请确保从虚拟网络和所有子网中移除任何删除或只读锁。 创建服务器后,可以重新应用锁。 
谁可以创建或删除锁
若要创建或删除管理锁,你需要有权访问 Microsoft.Authorization/* 或 Microsoft.Authorization/locks/* 操作。 分配给“所有者”和“用户访问管理员”角色的用户具有所需的访问权限。 某些专用内置角色也授予此访问权限。 可以创建拥有所需权限的自定义角色。
托管应用程序和锁
某些 Azure 服务使用 托管应用程序 来实现该服务;一个示例中的 Azure Databricks。 在这种情况下,该服务将创建两个资源组。 其中一个资源组是包含服务概述的已解锁资源组。 另一个是包含服务基础结构的已锁定资源组。
如果尝试删除基础结构资源组,将会收到一条错误消息,指出资源组已锁定。 如果你尝试删除基础结构资源组的锁,将会收到一条错误消息,指出无法删除该锁,因为它由系统应用程序拥有。
应该删除服务,这样也会删除基础结构资源组。
对于托管应用程序,请选择你部署的服务。
              
               
              
              
            
请注意,服务包含托管资源组的链接。 该资源组包含基础结构且已锁定。 只能间接删除它。
              
               
              
              
            
若要删除服务的所有内容(包括锁定的基础结构资源组),请选择该服务对应的“删除”。
              
               
              
              
            
配置锁定
Azure 门户
在左侧导航面板中,订阅锁定功能的名称为“资源锁”,而资源组锁定功能的名称为“锁”。
- 在要锁定的资源、资源组或订阅的“设置”边栏选项卡中,选择“锁定”。   
- 要添加锁,请选择“添加”。 如果要在父级别创建锁,请选择父级。 当前选定的资源将从父级继承锁。 例如,可以锁定资源组,以便向其所有资源应用锁。   
- 为该锁提供名称和锁级别。 (可选)可以添加注释来描述该锁。   
- 要删除锁,请选择“删除”按钮。   
模板
使用资源管理器模板(ARM 模板)或 Bicep 文件部署锁时,需要了解部署范围和锁范围如何协同工作。 若要在部署范围内应用锁定,例如锁定资源组或订阅时,请不要设置 scope 属性。 锁定部署范围内的资源时,请在锁定对象上设置 scope 属性。
以下模板会将锁应用于资源组。 请注意,锁资源没有 scope 属性,因为锁范围与部署范围匹配。 在资源组级别部署此模板。
{
  "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {
  },
  "resources": [
    {
      "type": "Microsoft.Authorization/locks",
      "apiVersion": "2016-09-01",
      "name": "rgLock",
      "properties": {
        "level": "CanNotDelete",
        "notes": "Resource group should not be deleted."
      }
    }
  ]
}
若要创建资源组并将其锁定,请在订阅级别部署上述模板。
{
  "$schema": "https://schema.management.azure.com/schemas/2018-05-01/subscriptionDeploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {
    "rgName": {
      "type": "string"
    },
    "rgLocation": {
      "type": "string"
    }
  },
  "variables": {},
  "resources": [
    {
      "type": "Microsoft.Resources/resourceGroups",
      "apiVersion": "2021-04-01",
      "name": "[parameters('rgName')]",
      "location": "[parameters('rgLocation')]",
      "properties": {}
    },
    {
      "type": "Microsoft.Resources/deployments",
      "apiVersion": "2021-04-01",
      "name": "lockDeployment",
      "resourceGroup": "[parameters('rgName')]",
      "dependsOn": [
        "[resourceId('Microsoft.Resources/resourceGroups/', parameters('rgName'))]"
      ],
      "properties": {
        "mode": "Incremental",
        "template": {
          "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
          "contentVersion": "1.0.0.0",
          "parameters": {},
          "variables": {},
          "resources": [
            {
              "type": "Microsoft.Authorization/locks",
              "apiVersion": "2016-09-01",
              "name": "rgLock",
              "properties": {
                "level": "CanNotDelete",
                "notes": "Resource group and its resources should not be deleted."
              }
            }
          ],
          "outputs": {}
        }
      }
    }
  ],
  "outputs": {}
}
对资源组中的资源应用锁时,请添加 scope 属性。 将 scope 设置为要锁定的资源的名称。
以下示例演示可创建应用服务计划、网站和网站上的锁的模板。 锁的范围设置为网站。
{
  "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {
    "hostingPlanName": {
      "type": "string"
    },
    "location": {
      "type": "string",
      "defaultValue": "[resourceGroup().location]"
    }
  },
  "variables": {
    "siteName": "[concat('ExampleSite', uniqueString(resourceGroup().id))]"
  },
  "resources": [
    {
      "type": "Microsoft.Web/serverfarms",
      "apiVersion": "2020-12-01",
      "name": "[parameters('hostingPlanName')]",
      "location": "[parameters('location')]",
      "sku": {
        "tier": "Free",
        "name": "f1",
        "capacity": 0
      },
      "properties": {
        "targetWorkerCount": 1
      }
    },
    {
      "type": "Microsoft.Web/sites",
      "apiVersion": "2020-12-01",
      "name": "[variables('siteName')]",
      "location": "[parameters('location')]",
      "dependsOn": [
        "[resourceId('Microsoft.Web/serverfarms', parameters('hostingPlanName'))]"
      ],
      "properties": {
        "serverFarmId": "[parameters('hostingPlanName')]"
      }
    },
    {
      "type": "Microsoft.Authorization/locks",
      "apiVersion": "2016-09-01",
      "name": "siteLock",
      "scope": "[concat('Microsoft.Web/sites/', variables('siteName'))]",
      "dependsOn": [
        "[resourceId('Microsoft.Web/sites', variables('siteName'))]"
      ],
      "properties": {
        "level": "CanNotDelete",
        "notes": "Site should not be deleted."
      }
    }
  ]
}
Azure PowerShell
使用 Azure PowerShell 通过 New-AzResourceLock 命令锁定已部署的资源。
若要锁定资源,请提供资源的名称、资源类型和资源组名称。
New-AzResourceLock -LockLevel CanNotDelete -LockName LockSite -ResourceName examplesite -ResourceType Microsoft.Web/sites -ResourceGroupName exampleresourcegroup
若要锁定资源组,请提供资源组名称。
New-AzResourceLock -LockName LockGroup -LockLevel CanNotDelete -ResourceGroupName exampleresourcegroup
若要获取有关某个锁的信息,请使用 Get-AzResourceLock。 若要获取订阅中的所有锁,请使用:
Get-AzResourceLock
若要获取某个资源的所有锁,请使用:
Get-AzResourceLock -ResourceName examplesite -ResourceType Microsoft.Web/sites -ResourceGroupName exampleresourcegroup
若要获取某个资源组的所有锁,请使用:
Get-AzResourceLock -ResourceGroupName exampleresourcegroup
若要删除某个资源的锁,请使用:
$lockId = (Get-AzResourceLock -ResourceGroupName exampleresourcegroup -ResourceName examplesite -ResourceType Microsoft.Web/sites).LockId
Remove-AzResourceLock -LockId $lockId
若要删除某个资源组的锁,请使用:
$lockId = (Get-AzResourceLock -ResourceGroupName exampleresourcegroup).LockId
Remove-AzResourceLock -LockId $lockId
Azure CLI
若要使用 Azure CLI 锁定已部署的资源,请使用 az lock create 命令。
若要锁定资源,请提供资源名称、资源类型和资源组名称。
az lock create --name LockSite --lock-type CanNotDelete --resource-group exampleresourcegroup --resource-name examplesite --resource-type Microsoft.Web/sites
若要锁定资源组,请提供资源组名称。
az lock create --name LockGroup --lock-type CanNotDelete --resource-group exampleresourcegroup
若要获取有关某个锁的信息,请使用 az lock list。 若要获取订阅中的所有锁,请使用:
az lock list
若要获取某个资源的所有锁,请使用:
az lock list --resource-group exampleresourcegroup --resource-name examplesite --namespace Microsoft.Web --resource-type sites --parent ""
若要获取某个资源组的所有锁,请使用:
az lock list --resource-group exampleresourcegroup
若要删除某个资源的锁,请使用:
lockid=$(az lock show --name LockSite --resource-group exampleresourcegroup --resource-type Microsoft.Web/sites --resource-name examplesite --output tsv --query id)
az lock delete --ids $lockid
若要删除某个资源组的锁,请使用:
lockid=$(az lock show --name LockSite --resource-group exampleresourcegroup  --output tsv --query id)
az lock delete --ids $lockid
Python
若要使用 Python 锁定已部署的资源,请使用 ManagementLockClient.management_locks.create_or_update_at_resource_group_level 命令。
若要锁定资源,请提供资源名称、资源类型和资源组名称。
import os
from azure.identity import AzureCliCredential
from azure.mgmt.resource import ManagementLockClient
credential = AzureCliCredential()
subscription_id = os.environ["AZURE_SUBSCRIPTION_ID"]
lock_client = ManagementLockClient(credential, subscription_id)
lock_result = lock_client.management_locks.create_or_update_at_resource_level(
    "exampleGroup",
    "Microsoft.Web",
    "",
    "sites",
    "examplesite",
    "lockSite",
    {
        "level": "CanNotDelete"
    }
)
若要锁定某个资源组,请提供该资源组的名称。
import os
from azure.identity import AzureCliCredential
from azure.mgmt.resource import ManagementLockClient
credential = AzureCliCredential()
subscription_id = os.environ["AZURE_SUBSCRIPTION_ID"]
lock_client = ManagementLockClient(credential, subscription_id)
lock_result = lock_client.management_locks.create_or_update_at_resource_group_level(
    "exampleGroup",
    "lockGroup",
    {
        "level": "CanNotDelete"
    }
)
若要获取有关订阅中所有锁的信息,请使用 ManagementLockClient.management_locks.get。
若要获取订阅中的所有锁,请使用:
import os
from azure.identity import AzureCliCredential
from azure.mgmt.resource import ManagementLockClient
credential = AzureCliCredential()
subscription_id = os.environ["AZURE_SUBSCRIPTION_ID"]
lock_client = ManagementLockClient(credential, subscription_id)
lock_result = lock_client.management_locks.list_at_subscription_level()
for lock in lock_result:
    print(f"Lock name: {lock.name}")
    print(f"Lock level: {lock.level}")
    print(f"Lock notes: {lock.notes}")
若要获取某个资源的锁,请使用:
import os
from azure.identity import AzureCliCredential
from azure.mgmt.resource import ManagementLockClient
credential = AzureCliCredential()
subscription_id = os.environ["AZURE_SUBSCRIPTION_ID"]
lock_client = ManagementLockClient(credential, subscription_id)
lock_result = lock_client.management_locks.get_at_resource_level(
    "exampleGroup",
    "Microsoft.Web",
    "",
    "sites",
    "examplesite",
    "lockSite"
)
print(f"Lock ID: {lock_result.id}")
print(f"Lock Name: {lock_result.name}")
print(f"Lock Level: {lock_result.level}")
若要获取资源组的锁,请使用以下代码:
import os
from azure.identity import AzureCliCredential
from azure.mgmt.resource import ManagementLockClient
credential = AzureCliCredential()
subscription_id = os.environ["AZURE_SUBSCRIPTION_ID"]
lock_client = ManagementLockClient(credential, subscription_id)
lock_result = lock_client.management_locks.get_at_resource_group_level(
    "exampleGroup",
    "lockGroup"
)
print(f"Lock ID: {lock_result.id}")
print(f"Lock Level: {lock_result.level}")
若要删除某个资源的锁,请使用:
import os
from azure.identity import AzureCliCredential
from azure.mgmt.resource import ManagementLockClient
credential = AzureCliCredential()
subscription_id = os.environ["AZURE_SUBSCRIPTION_ID"]
lock_client = ManagementLockClient(credential, subscription_id)
lock_client.management_locks.delete_at_resource_level(
    "exampleGroup",
    "Microsoft.Web",
    "",
    "sites",
    "examplesite",
    "lockSite"
)
若要删除某个资源组的锁,请使用:
import os
from azure.identity import AzureCliCredential
from azure.mgmt.resource import ManagementLockClient
credential = AzureCliCredential()
subscription_id = os.environ["AZURE_SUBSCRIPTION_ID"]
lock_client = ManagementLockClient(credential, subscription_id)
lock_client.management_locks.delete_at_resource_group_level("exampleGroup", "lockGroup")
REST API
可以使用 管理锁的 REST API锁定已部署的资源。 可以使用 REST API 创建和删除锁,以及检索有关现有锁的信息。
若要创建一个锁,请运行:
PUT https://management.chinacloudapi.cn/{scope}/providers/Microsoft.Authorization/locks/{lock-name}?api-version={api-version}
范围可以是订阅、资源组或资源。 锁名称可以是想要使用的任意名称。 对于 API 版本,请使用 2016-09-01。
在请求中,请包含用于指定锁属性的 JSON 对象。
{
  "properties": {
  "level": "CanNotDelete",
  "notes": "Optional text notes."
  }
}
后续步骤
- 若要了解如何以逻辑方式组织资源,请参阅 使用标记来组织 Azure 资源和管理层次结构。
- 可以使用自定义策略对订阅应用限制和约定。 有关详细信息,请参阅什么是 Azure Policy?。