问题描述
我想创建一个将存储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
您还可以在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和this。
,Levi Lu的答案使我走上了正确的轨道,但我要添加自己的答案以阐明确切的要求。
要访问“ Microsoft Azure应用程序服务”(abfa0a7c-a6b6-4736-8310-5855508787cd
)的服务主体,您需要做两件事:
- 您的订阅必须已注册“ Microsoft.Web”资源提供者。创建新订阅时,它通常会自动注册,但有时却不会。
- 与ARM服务连接(在其下运行管道)关联的服务主体必须具有Azure Active Directory图的“ Directory.Read.All”权限。打开您的Azure DevOps项目设置,单击“服务连接”,打开您的服务连接,然后单击“管理服务主体”。然后转到“ API权限”,单击“添加权限”,向下滚动并单击“ Azure Active Directory图”,“应用程序权限”,然后添加“ Directory.Read.All”。点击“授予管理员同意”。如果该按钮显示为灰色,则需要让AAD管理员为您执行此步骤。
重要的是,尽管此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