【问题标题】:Azure DevOps Build Pipeline can't get secrets from Key Vault when secured with vnet and firewallAzure DevOps Build Pipeline 在使用 vnet 和防火墙保护时无法从 Key Vault 获取机密
【发布时间】:2020-01-16 07:12:04
【问题描述】:

使用 vnet 和防火墙保护后,无法从 Key Vault 获取机密。

我想使用 DevOps Build Pipeline 任务中存储在密钥库中的机密,并且我想遵循安全最佳实践和深度防御。作为安全最佳实践,我希望可以从选定的虚拟网络、选定的 Azure 服务和受信任的 Internet ip 访问密钥库。当然,我会使用服务主体和适当的权限(列表/获取)。

很遗憾,Azure DevOps 不是受信任的服务之一。因此,我的替代方案是将 DevOps IP 列入白名单。我发现我的 DevOps 位于美国东部 2 区域,我下载了 Azure 数据中心 IP(使用美国东部 2 过滤)。美国东部 2 大约有 285 个 IP。Key Vault 防火墙对您可以添加的防火墙规则数量有限制,它是 127!所以,我运气不好!

目前,只有在我允许所有网络的情况下,我才能在构建管道中从密钥库中获取机密!是的,我仍然需要进行身份验证才能获取秘密,但我在深度防御上失败了。我真的需要将密钥库锁定到受信任的网络,但我不能。为什么?我不能添加超过 127 条防火墙规则(以覆盖该区域),并且 DevOps 不是受信任的 Azure 服务之一!

【问题讨论】:

  • 不同的Azure服务,相同的基本问题,相同的基本解决方案。
  • @Daniel Mann- 感谢您的想法,它也应该适用于我的场景。我厌倦了看到构建管道的随机 IP 地址。获取客户端 IP 并将其添加到防火墙规则就可以了。只需要保证删除ip即可。一旦我测试它会更新这篇文章。理想情况下,Microsoft 应该自动支持此功能,但我可以接受临时解决方法。请记住,服务主体需要提升权限才能更改基础架构。非常感谢你的想法。 ??????????
  • @Prodip,既然您已经解决了您的问题,您可以将您的评论转换为答案,这样可以帮助遇到相同问题的其他社区成员,我们可以存档此线程,谢谢。
  • 我更喜欢的另一种方法是在私有 VNet 中运行代理:无需调整安全组或防火墙规则

标签: azure-devops firewall azure-keyvault


【解决方案1】:

我想我会在 Prodip 提供的解决方案上做一些改动。这依赖于这样一个事实,即当您请求秘密时,az 客户端会很好地告诉您您的客户端 IP 地址是什么,即:

az keyvault secret show -n "a-known-client-secret" --vault-name "$keyVaultName"

Attempting to get value for known secret from key vault: '******'
ERROR: Client address is not authorized and caller is not a trusted service.
Client address: 1.1.1.1
Caller: appid=***;oid=****;iss=https://sts.windows.net/***/
Vault: ******;location=******

这是我的 bash 脚本(whitelist-agent-for-key-vault.sh):

#!/usr/bin/env bash

## By default the Azure DevOps IP addresses are NOT whitelisted for key vault access. So even if the service principal has access, you won't get past the firewall.
## The solution is to temporarily add the build agent IP address to the key vault firewall, and remove it when the pipeline is complete. 

if [[ $(uname -s) == "Linux" ]]; then
    azcmd="az"
else
    # If we're in a bash shell on Windows, az commands don't work, but we can call the az.cmd batch file directly from git Bash if we can find it...
    azcmd=$(where az.cmd)
fi

# Are we removing rather than setting?
if [[ $1 == "-r" ]]; then
    if [[ -z "$3" ]]; then
        echo "Build agent IP address is empty, no whitelist entry to remove from key vault: '$2'"
    else
        echo "Removing key vault '$2' network rule for DevOps build agent IP address: '$3'"

        # Remember to specify CIDR /32 for removal
        "$azcmd" keyvault network-rule remove -n $2 --ip-address $3/32
    fi
    exit 0
fi

keyVaultName=$1

########################################################################
##### This is the known secret which we request from the key vault #####
########################################################################

knownSecret="<My known secret>"

echo "Attempting to get value for known secret from key vault: '$keyVaultName'"

# Attempt to show secret - if it doesn't work, we are echoed our IP address on stderror, so capture it
secretOutput=$("$azcmd" keyvault secret show -n "$knownSecret" --vault-name "$keyVaultName" 2>&1)
buildAgentIpAddress=$(echo $secretOutput | grep -oE "\b([0-9]{1,3}\.){3}[0-9]{1,3}\b")

set -euo pipefail

if [[ ! -z "$buildAgentIpAddress" ]]; then
    # Temporarily whitelist Azure DevOps IP for key vault access.
    # Note use of /32 for CIDR = 1 IP address. If we omit this Azure adds it anyway and fails to match on the IP when attempting removal.
    echo "Azure DevOps IP address '$buildAgentIpAddress' is blocked. Attempting to whitelist..."
    "$azcmd" keyvault network-rule add -n $keyVaultName --ip-address $buildAgentIpAddress/32

    # Capture the IP address as an ADO variable, so that this can be undone in a later step
    echo "##vso[task.setvariable variable=buildAgentIpAddress]$buildAgentIpAddress"
else
    # We didn't find the IP address - are we already whitelisted?
    secretValue=$(echo $secretOutput | grep -o "value")

    if [[ -z "$secretValue" ]]; then
        echo "Unexpected response from key vault whitelist request, json attribute 'value' not found. Unable to whitelist build agent - response was: '$secretOutput'"
        exit 1
    fi
fi

以下是我将 IP 添加到白名单的方法:

  # Add agent IP to key vault white list
  - task: AzureCLI@2
    displayName: Add Azure DevOps build agent IP to key vault white list
    inputs:
      azureSubscription: ${{ parameters.azureSubscription }}
      scriptType: bash
      scriptLocation: scriptPath
      scriptPath: $(Pipeline.Workspace)/server-build-tools/drop/build-scripts/whitelist-agent-for-key-vault.sh
      arguments: '$(keyVaultName)'

这是我从白名单中删除 IP 的方法

      - task: AzureCLI@2
        displayName: Remove Azure DevOps build agent IP from key vault white list
        condition: always()
        inputs:
          azureSubscription: ${{ parameters.azureSubscription }}
          scriptType: bash
          scriptLocation: scriptPath
          scriptPath: $(Pipeline.Workspace)/server-build-tools/drop/build-scripts/whitelist-agent-for-key-vault.sh
          arguments: '-r "$(keyVaultName)" "$(buildAgentIpAddress)"'

注意事项:

  • 这依赖于 Azure DevOps 服务主体已被授予对密钥保管库机密的读取访问权限
  • knownSecret 值替换为您已知机密的名称

奖励:

这可以使用 Azure CLI 运行,并且已经在 Azure DevOps for Linux 和 Windows 构建代理上进行了测试,后者在 Git bash 下运行。通常,如果您尝试在 Git Bash 中运行“az”命令,您只会得到“找不到命令”。我想要一个适用于两者的解决方案,因为由于 Linux / Windows 构建要求,我需要共享代码。

【讨论】:

    【解决方案2】:

    您可以在构建定义中添加一个步骤以将代理 IP 地址列入白名单,然后在构建结束时将其从白名单中删除。在 Azure 产品团队将 Azure DevOps 添加为受信任的服务之前,这不是一种解决方案,而是一种解决方法。感谢@DanielMann 提供的想法。

    解决方案很简单,但我不会信任 ipify.org 作为 REST API 端点来获取我的构建代理的 IP 地址。相反,我在 Azure Function-GetClientIP 创建了我自己的(和受信任的)服务。 DevOps 不是我的日常工作,我很难弄清楚如何分配和使用用户定义的变量并将它们传递给管道中的下一步/任务/阶段!微软关于变量使用的文档对我的帮助不够,但经过多次不成功的运行后我发现了!

    在我的博客上查看完整的解决方案-Azure DevOps Build Pipeline- use keys and secrets from Key Vault

    【讨论】:

      【解决方案3】:

      唯一的解决方案是使用self-hosted agent

      您可以创建一个虚拟机并在其中安装代理客户端。然后您可以在 DevOps 代理池中添加它的新代理并使用它。

      由于自我代理在您的 Azure VM 中运行,它肯定位于虚拟网络中。通过这种方式,您可以将虚拟网络添加到您的密钥保管库防火墙白名单中。


      事实上,我认为你不需要这样做。因为,没有访问策略,任何人都无法访问您的密钥保管库。因此,从理论上讲,它是足够安全的。

      但是,如果您必须使用防火墙和网络规则保护您的密钥保管库,您可以使用自托管代理。

      【讨论】:

      • 感谢替代方案,但自托管代理不是 SaaS Azure DevOps 的答案!
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-02-24
      • 2020-05-07
      • 2020-03-30
      • 2022-07-22
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多