从管道访问私钥保管库

Azure 密钥保管库提供了一种安全的解决方案,用于管理密钥、机密和证书等凭据,并具有无缝的安全性。 使用 Azure Pipelines,可以简化访问和使用密钥保管库的过程,从而轻松存储和检索凭据。

在某些情况下,组织通过将密钥保管库的访问限制在指定的 Azure 虚拟网络来优先考虑安全性,以确保关键应用程序的最高安全级别。

在本教程中,您将学习如何执行以下操作:

  • 创建服务主体
  • 创建服务连接
  • 配置入站接入点
  • 从管道查询专用 Azure 密钥保管库

先决条件

访问私钥保管库

Azure Pipelines 使开发人员能够将 Azure 密钥保管库链接到变量组,并将选择性保管库机密映射到该组。 可以访问用作变量组的密钥保管库:

  1. 在变量组配置期间,来自 Azure DevOps。

  2. 在管道作业运行时期间,来自自托管代理。

显示用于访问私钥保管库的两个不同路径的关系图。

创建服务主体

首先创建新的服务主体,这样就可以访问 Azure 资源。 接下来,需要在 Azure DevOps 中创建新的 ARM 服务连接,然后在 Azure DevOps 中验证和保存服务连接之前,在 Azure 中为服务主体设置联合凭据。

  1. 导航到 Azure 门户

  2. 从菜单栏中打开 Cloud Shell,然后选择 Bash

  3. 运行以下命令以创建新服务主体:

    az ad sp create-for-rbac --name YOUR_SERVICE_PRINCIPAL_NAME
    
  4. 请确保复制输出,因为我们将在下一步使用它来创建服务连接。

创建服务连接

  1. 登录到 Azure DevOps 组织,并导航到你的项目。

  2. 选择项目设置>服务连接>新建服务连接

  3. 选择“Azure 资源管理器”,然后选择“下一步”。

  4. 对于 标识类型,请从下拉菜单中选择 “应用注册”(自动 )。

  5. 对于 凭据,请保留默认值: 工作负荷标识联合

  6. 对于 “范围”级别,请选择“订阅”,然后从下拉菜单中选择订阅。

  7. 如果要仅限制对指定资源组的访问,请选择资源组。

  8. 提供服务连接的名称,然后选择“ 授予对所有管道 的访问权限”复选框,以允许所有管道使用此服务连接。

  9. 完成时选择“保存”。

    显示如何为服务主体配置 ARM 服务连接的屏幕截图。

创建联合凭据

  1. 导航到Azure 门户,在搜索栏中输入服务主体的 ClientID,然后选择应用程序

  2. 在“管理”下,选择“证书和机密>联合凭据”。

  3. 选择“添加凭据”,然后选择“联合凭据方案”,选择“其他颁发者”。

  4. 对于 颁发者,粘贴以下 URL,将占位符替换为你的组织 GUID。 可以通过导航到“组织设置”>Microsoft Entra> 下载连接到目录的 Azure DevOps 组织列表来查找组织 ID。

    https://vstoken.dev.azure.com/<ORGANIZATION_ID>
    
  5. 对于 使用者标识符,粘贴以下 URL,将占位符替换为组织名称、项目名称和服务连接名称。

    sc://ORGANIZATION_NAME/PROJECT_NAME/SERVICE_CONNECTION_NAME
    
  6. 为联合凭据提供 名称 ,然后在完成后选择“ 添加 ”。

创建服务连接

  1. 登录到 Azure DevOps 组织,并导航到你的项目。

  2. 选择项目设置>服务连接>新建服务连接

  3. 选择 Azure 资源管理器、>下一步,然后选择服务主体(手动)>下一步

  4. 对于环境选择 Azure 云,对于范围级别选择订阅,然后输入订阅 ID订阅名称

  5. 输入服务主体信息,然后选择验证

  6. 验证成功后,输入你的服务连接名称,添加描述,然后选中授予对所有管道的访问权限复选框。 完成操作后,选择验证并保存

提示

如果无法验证服务主体连接,请授予服务主体对订阅的读取者访问权限。

创建服务连接

  1. 登录到 Azure DevOps 集合,然后导航到项目。

  2. 选择项目设置>服务连接>新建服务连接

  3. 选择 Azure 资源管理器,命名服务连接,然后为环境选择 Azure 云,为范围级别选择订阅

  4. 输入订阅 ID订阅名称

  5. 输入服务主体信息,然后选择验证连接

  6. 选中允许所有管道使用此连接复选框,然后在完成后选择确定

提示

如果无法验证服务主体连接,请授予服务主体对订阅的读取者访问权限。

从 Azure Devops 访问私钥保管库

在本节中,我们将探讨从 Azure DevOps 访问私钥保管库的两种方法。 首先,我们将使用变量组链接和映射密钥保管库中的机密,然后通过允许静态 IP 范围设置入站访问。 我们建立入站访问,因为 Azure Pipelines 从变量组查询 Azure 密钥保管库时使用已发布的 Azure DevOps 公共 IP。 因此,通过向 Azure 密钥保管库防火墙添加入站连接,可以成功连接到 Azure 密钥保管库。

对于第二种方法,我们将演示如何动态地将 Microsoft 托管代理 IP 地址添加到密钥保管库的防火墙分配列表中,查询密钥保管库,并在完成后删除 IP。 第二种方法用于演示目的,不是 Azure Pipelines 推荐的方法。

1 - 使用变量组映射密钥保管库机密

  1. 登录到 Azure DevOps 组织,并导航到你的项目。

  2. 选择管道>,然后选择 + 变量组

  3. 命名变量组,然后选择切换按钮,以启用链接 Azure Key Vault 中的机密作为变量按钮。

  4. 选择之前创建的服务连接,选择密钥保管库,然后选择“ 授权”。

  5. 在“变量”下,选择“添加”以添加机密,然后在完成后选择“保存”。

注意

确保服务连接具有“获取”和“列表”权限,并且为服务主体分配了私钥保管库中的密钥库机密用户角色。

1.1 设置服务连接权限

  1. 导航到 Azure 密钥保管库,然后选择“ 访问策略”。

  2. 选择“创建”,然后在“机密”权限添加“获取列表”权限,然后选择“下一步”。

  3. 在搜索栏中添加服务连接,选择它,然后选择“ 下一步”。

  4. 再次选择“下一步”,查看设置,然后在完成后选择“查看 + 创建”。

1.2 设置服务主体权限

  1. 导航到 Azure 密钥保管库,然后选择“访问控制”(IAM)。

  2. 选择“添加添加>角色分配>”,然后选择“角色”选项卡。

  3. 选择密钥库机密用户角色,然后选择“下一步”。

  4. 选择“选择成员>”,添加服务主体 >Select

  5. 完成后,选择“ 审阅 + 分配 ”。

  1. 登录到 Azure DevOps 组织,并导航到你的项目。

  2. 选择管道>,然后选择 + 变量组

  3. 命名变量组,然后选择切换按钮,以启用链接 Azure Key Vault 中的机密作为变量按钮。

  4. 从下拉菜单中选择之前创建的 Azure 服务连接,然后选择密钥保管库。

    一个屏幕截图,显示了如何将变量组链接到 Azure 密钥保管库,并显示一个错误,指示缺少获取和列表权限。

  5. 如果遇到错误消息:指定的 Azure 服务连接需要具有所选密钥保管库的 Get、List 密钥管理权限。,如上所示。 导航到 Azure 门户中的密钥保管库,选择访问控制 (IAM)>添加角色分配>密钥保管库机密用户>下一步,并添加服务主体,然后在完成后选择查看 + 分配

    显示如何将服务主体添加为 Azure 密钥保管库的机密用户的屏幕截图。

  6. 添加机密,然后在完成后选择保存

2 - 配置来自 Azure DevOps 的入站访问

若要启用从 Azure DevOps 访问密钥保管库,必须授予从特定静态 IP 范围访问的权限。 这些范围由 Azure DevOps 组织的地理位置确定。

  1. 登录到你的 Azure DevOps 组织。

  2. 选择 “组织设置”。

  3. 导航到概述,你将在页面底部找到列出的地理位置。

    显示如何查找 Azure DevOps 组织的地理位置的屏幕截图。

  4. 查找地理 IP V4 范围

  5. 配置密钥保管库,以允许从静态 IP 范围进行访问。

3 - 使用变量组查询私钥保管库

在此示例中,我们使用之前设置并由服务主体授权的变量组,只需使用链接的变量组即可从我们的专用 Azure 密钥保管库查询和复制机密。 Azure Pipelines 在从变量组查询 Azure 密钥保管库时使用已发布的公共 IP,因此请确保你配置了入站访问权限,以便正常工作:

variables:
-  group: mySecret-VG

steps:
- task: CmdLine@2
  inputs:
    script: 'echo $(mySecret) > secret.txt'

- task: CopyFiles@2
  inputs:
    Contents: secret.txt
    targetFolder: '$(Build.ArtifactStagingDirectory)'

- task: PublishBuildArtifacts@1
  inputs:
    PathtoPublish: '$(Build.ArtifactStagingDirectory)'
    ArtifactName: 'drop'
    publishLocation: 'Container'

替代方法 - 动态地允许 Microsoft 托管的代理 IP

在此第二种方法中,我们将从在管道开头查询 Microsoft 托管的代理的 IP 开始。 然后,我们将它添加到密钥保管库允许列表,继续完成剩余的任务;最后,从密钥保管库的防火墙允许列表中删除 IP。

注意

此方法仅用于演示目的,不是 Azure Pipelines 推荐的方法。

- task: AzurePowerShell@5
  displayName: 'Allow agent IP'
  inputs:
    azureSubscription: 'YOUR_SERVICE_CONNECTION_NAME'
    azurePowerShellVersion: LatestVersion
    ScriptType: InlineScript
    Inline: |
     $ip = (Invoke-WebRequest -uri "http://ifconfig.me/ip").Content
     Add-AzKeyVaultNetworkRule -VaultName "YOUR_KEY_VAULT_NAME" -ResourceGroupName "YOUR_RESOURCE_GROUP_NAME" -IpAddressRange $ip
     echo "##vso[task.setvariable variable=agentIP]ip"

- task: AzureKeyVault@2
  inputs:
    azureSubscription: 'YOUR_SERVICE_CONNECTION_NAME'
    KeyVaultName: 'YOUR_KEY_VAULT_NAME'
    SecretsFilter: '*'
    RunAsPreJob: false

- task: AzurePowerShell@5
  displayName: 'Remove agent IP'
  inputs:
    azureSubscription: 'YOUR_SERVICE_CONNECTION_NAME'
    azurePowerShellVersion: LatestVersion
    ScriptType: InlineScript
    Inline: |
     $ipRange = $env:agentIP + "/32"
     Remove-AzKeyVaultNetworkRule -VaultName "YOUR_KEY_VAULT_NAME" -IpAddressRange $ipRange
  condition: succeededOrFailed()

重要

确保用于从管道访问密钥保管库的服务主体在密钥保管库的访问控制 (IAM) 中保留密钥保管库参与者角色。

从自托管代理访问私钥保管库

若要能够从 Azure Pipelines 代理访问私钥保管库,需要使用自托管代理(WindowsLinuxMac)或规模集代理。 这是因为与其他通用计算服务一样,Microsoft 托管代理不包括在密钥保管库的受信任服务列表中。

若要与私钥保管库建立连接,必须通过为密钥保管库配置专用终结点来提供直通连接。 此终结点必须可路由,并且其专用 DNS 名称可以从自托管管道代理解析。

1 - 配置自托管代理的入站访问

  1. 按照提供的说明创建虚拟网络

  2. Azure 门户中,使用页面顶部的搜索栏查找 Azure 密钥保管库。

  3. 在搜索结果中找到密钥保管库后,选择它,然后导航到设置>网络

  4. 选择专用终结点连接,然后选择创建以创建新的专用终结点。

    显示如何为 Azure 密钥保管库创建新的专用终结点连接的屏幕截图。

  5. 选择托管你之前创建的虚拟网络的资源组。 为实例提供名称网络接口名称,并确保选择与前面创建的虚拟网络相同的区域。 完成后选择“下一步”。

    显示如何在为 Azure 密钥保管库创建新的专用终结点实例时配置“基本信息”选项卡的屏幕截图。

  6. 连接方法选择连接到我的目录中的 Azure 资源,然后从资源类型下拉菜单中选择 Microsoft.KeyVault/vaults。 从下拉菜单中选择你的资源目标子资源将自动用值填充:vault。 完成后选择“下一步”。

    显示如何在为 Azure 密钥保管库创建新的专用终结点实例时配置“资源”选项卡的屏幕截图。

  7. 虚拟网络选项卡下,选择之前创建的虚拟网络子网,并将其余字段保留为默认值。 完成后选择“下一步”。

  8. 继续浏览 DNS标记选项卡,接受默认设置。 在查看 + 创建选项卡下,完成后选择创建

  9. 部署资源后,导航到密钥保管库>设置>网络>专用终结点连接,专用终结点应列为连接状态 已批准。 如果链接到其他目录中的 Azure 资源,则需要等待资源所有者批准连接请求。

    显示已批准的专用终结点连接的屏幕截图

2 - 允许虚拟网络

  1. 导航到 Azure 门户,然后找到 Azure 密钥保管库。

  2. 选择设置>网络,并确保你位于防火墙和虚拟网络选项卡下。

  3. 选择添加虚拟网络>添加现有虚拟网络

  4. 从下拉菜单中选择订阅,然后选择之前创建的虚拟网络,再选择子网

  5. 完成后,选择添加,然后滚动到页面底部,然后选择应用以保存更改。

    显示如何将现有虚拟网络添加到 Azure 密钥保管库防火墙的屏幕截图。

3 - 从自托管代理查询私钥保管库

以下示例使用在虚拟网络的 VM 上设置的代理通过变量组查询私钥保管库:

pool: Self-hosted-pool

variables:
  group: mySecret-VG

steps:
- task: CmdLine@2
  inputs:
    script: 'echo $(mySecret) > secret.txt'

- task: CopyFiles@2
  inputs:
    Contents: secret.txt
    targetFolder: '$(Build.ArtifactStagingDirectory)'

- task: PublishBuildArtifacts@1
  inputs:
    PathtoPublish: '$(Build.ArtifactStagingDirectory)'
    ArtifactName: 'drop'
    publishLocation: 'Container'

如果不想授予 Azure DevOps 对私钥保管库的入站访问权限,则可以使用 AzureKeyVault 任务查询密钥保管库。 但是,必须确保在密钥保管库防火墙设置中允许托管代理的虚拟网络。

pool: Self-hosted-pool

steps:
- task: AzureKeyVault@2
  inputs:
    azureSubscription: '$(SERVICE_CONNECTION_NAME)'
    keyVaultName: $(KEY_VAULT_NAME)
    SecretsFilter: '*'

- task: CmdLine@2
  inputs:
    script: 'echo $(mySecret) > secret.txt'

- task: CopyFiles@2
  inputs:
    Contents: secret.txt
    targetFolder: '$(Build.ArtifactStagingDirectory)'

- task: PublishBuildArtifacts@1
  inputs:
    PathtoPublish: '$(Build.ArtifactStagingDirectory)'
    ArtifactName: 'drop'
    publishLocation: 'Container'

疑难解答

如果遇到以下错误,请按照本节中的步骤排查并解决问题:

  • Public network access is disabled and request is not from a trusted service nor via an approved private link.

这表示公共访问已被禁用,并且既没有设置专用终结点连接,也没有设置防火墙例外。 按照 [#configure-inbound-access-from-a-self--hosted-agent] 和配置来自 Azure DevOps 的入站访问下的步骤设置对私钥保管库的访问权限。

  • Request was not allowed by NSP rules and the client address is not authorized and caller was ignored because bypass is set to None Client address: <x.x.x.x>

此错误消息指示密钥保管库的公共访问已被禁用,并且未选中允许受信任的 Microsoft 服务绕过此防火墙选项,但客户端 IP 地址尚未添加到密钥保管库防火墙中。 导航到 Azure 门户中的密钥保管库,然后选择设置>网络,并将客户端 IP 添加到防火墙的允许列表。

  • Error: Client address is not authorized and caller is not a trusted service.

请确保将地理位置的 IPV4 范围添加到密钥保管库允许列表。 有关详细信息,请参阅配置来自 Azure DevOps 的入站访问。 或者,可以跳转到动态地允许 Microsoft 托管的代理 IP,了解如何在运行时将客户端 IP 添加到密钥保管库的防火墙。