通过Azure管道任务访问Microsoft.Azure.WebSites资源提供程序Microsoft Azure App Service的服务主体

问题描述

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

认情况下,“ Microsoft.Azure.WebSites”资源提供者(RP)无权访问模板中指定的Key Vault,因此您需要在部署模板之前通过执行以下PowerShell命令对其进行授权:>

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并在-BypassObjectIdValidation命令中添加Set-AzKeyVaultAccessPolicy参数作为解决方法。请参阅关于t {his document的注释。

使用服务主体授予访问策略权限时,必须使用-BypassObjectIdValidation参数。

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

对象ID是位于Managed application in local directory的对象ID

enter image description here

您还可以在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 threadthis

enter image description here

,

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

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

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

Microsoft.Web


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

Manage Service Principal


Add permission


Directory.Read.All


Grant consent


Granted consent


重要的是,尽管此API被标记为旧版且已弃用,但您必须 Azure Active Directory图中选择“ Directory.Read.All”权限。而是从Microsoft Graph中选择上述权限将不起作用。话虽如此,添加两个API的许可并不是一个坏主意,以防需求最终从一个切换到另一个。我发现奇怪的是,该许可一旦被授予和使用,即使被撤销,它仍继续有效。为了使任务再次失败(出于测试目的),我需要创建一个新的租户(Azure Active Directory)。

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

- 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