从 Azure 管道任务访问 Microsoft.Azure.WebSites 资源提供程序(Microsoft Azure 应用服务)的服务主体

Access service principal for Microsoft.Azure.WebSites Resource Provider (Microsoft Azure App Service) from Azure pipeline task

我想创建一个密钥保管库来存储 TLS 证书。需要可以从 Azure 管道任务访问此密钥保管库,这些任务将检索所述证书并将其绑定到其应用程序。 Microsoft mentions:

By default, 'Microsoft.Azure.WebSites' Resource Provider (RP) doesn't have access to the Key Vault specified in the template hence you need to authorize it by executing the following PowerShell commands before deploying the template:

Login-AzureRmAccount
Set-AzureRmContext -SubscriptionId AZURE_SUBSCRIPTION_ID
Set-AzureRmKeyVaultAccessPolicy -VaultName KEY_VAULT_NAME -ServicePrincipalName abfa0a7c-a6b6-4736-8310-5855508787cd -PermissionsToSecrets get

当我手动执行时,这适用于我的密钥保管库。但是,我想将其自动化作为我的主管道的一部分。我试过定义这个任务:

- task: AzurePowerShell@5
  displayName: 'Set key vault policy'
  inputs:
    azureSubscription: …
    azurePowerShellVersion: 'LatestVersion'
    ScriptType: 'InlineScript'
    Inline: |
      Set-AzKeyVaultAccessPolicy -VaultName … -ServicePrincipalName abfa0a7c-a6b6-4736-8310-5855508787cd -PermissionsToSecrets get

但是失败了:

##[error]Operation returned an invalid status code 'Forbidden'

我还注意到“Microsoft Azure App Service”的这个服务主体甚至对我的任务不可用;以下打印出空白:

 $azureAppServicePrincipal = Get-AzADServicePrincipal -ServicePrincipalName abfa0a7c-a6b6-4736-8310-5855508787cd
 Write-Output "azureAppServicePrincipalId = $($azureAppServicePrincipal.Id)"

有没有办法让我的管道可以访问此服务主体?

当我使用参数 Set-AzKeyVaultAccessPolicy -ServicePrincipalName other-service-principal 进行测试时。我得到同样的错误。

您可以使用 ObjectId 并在 Set-AzKeyVaultAccessPolicy 命令中添加 -BypassObjectIdValidation 参数作为解决方法。请参阅 this document.

上的注释

When using a service principal to grant access policy permissions, you must use the -BypassObjectIdValidation parameter.

Set-AzKeyVaultAccessPolicy -VaultName myvault -ObjectId "ObjectId" -PermissionsToSecrets get -BypassObjectIdValidation 

Object id 是驻留在Managed application in local directory

中的ObjectId

您还可以在 Azure CLI 任务中使用以下 Az cli 命令

az keyvault set-policy -n levikeyv --secret-permissions get --object-id "object-id"

因为命令 Get-AzADServicePrincipal 没有返回任何结果。大概是 与您的 ARM 连接服务关联的服务主体在 Microsoft Grap

中没有 Read Directory Data 权限

您可以尝试转到服务主体应用程序的 Api 权限并添加适当的权限。它可能需要您的管理员同意。有关信息,请参阅 this thread and this

Levi Lu 的回答让我走上了正确的轨道,但我添加了我自己的答案来阐明确切的要求。

为了能够访问“Microsoft Azure 应用服务”(abfa0a7c-a6b6-4736-8310-5855508787cd) 的服务主体,您需要做两件事:

  1. 您的订阅必须注册“Microsoft.Web”资源提供者。这通常会在创建新订阅时自动注册,但有时不会。


  1. 与您的 ARM 服务连接(您的管道在其下运行)关联的服务主体必须具有来自 Azure Active Directory Graph 的“Directory.Read.All”权限。打开您的 Azure DevOps 项目设置,单击“服务连接”,打开您的服务连接,然后单击“管理服务主体”。然后转到“API 权限”,单击“添加权限”,向下滚动并单击“Azure Active Directory Graph”、“应用程序权限”,然后添加“Directory.Read.All”。单击“授予管理员同意”。如果此按钮显示为灰色,您需要让 AAD 管理员为您执行此步骤。






重要的是,尽管如此 API 被标记为遗留和弃用路径。从 Microsoft Graph 选择上述权限 将不起作用 。也就是说,添加来自两个 API 的权限并不是一个坏主意,以防需求最终从一个切换到另一个。我发现的另一件奇怪的事情是,一旦授予并使用了权限,即使在它被撤销后仍然有效。为了让任务再次失败(为了测试),我需要创建一个新租户 (Azure Active Directory)。

有了这两个,您可以通过此任务(相应地替换 $env:keyVaultName)向您的密钥保管库授予“Microsoft Azure App Service”服务主体的权限:

- task: AzurePowerShell@5
  displayName: 'Grant key vault access to service principal'
  inputs:
    azureSubscription: '${{ parameters.armConnection }}'
    azurePowerShellVersion: 'LatestVersion'
    ScriptType: 'InlineScript'
    Inline: |              
    if (!(Get-AzADServicePrincipal -ServicePrincipalName abfa0a7c-a6b6-4736-8310-5855508787cd)) {
        throw "Current account cannot retrieve service principal `"abfa0a7c-a6b6-4736-8310-5855508787cd`" (Microsoft Azure App Service)."
    }
    Write-Host "Granting access to service principal `"abfa0a7c-a6b6-4736-8310-5855508787cd`" (Microsoft Azure App Service) on vault `"$($env:keyVaultName)`"..."
    Set-AzKeyVaultAccessPolicy -VaultName $env:keyVaultName -ServicePrincipalName abfa0a7c-a6b6-4736-8310-5855508787cd -PermissionsToSecrets Get,List -PermissionsToCertificates Get,List

2022 年 5 月更新

Microsoft 似乎已经解决了这个问题。 Azure Active Directory 图 API 变灰了,尽管 Set-AzKeyVaultAccessPolicy 仍在使用它。

Microsoft CLI 团队正在处理 migrating from the Azure Active Directory Graph API to the Microsoft Graph API. Until that is released, the best workaround seems to be to give Application administrator permissions to the service principal, as explained in