使用 Infisical 管理 Azure DevOps 密钥

  • infisical
  • 发布于 2026-03-06 19:52
  • 阅读 5

文章系统介绍了如何用 Infisical 统一管理 Azure DevOps 中分散的密钥,指出原生变量组、YAML 与 Key Vault 在大规模场景下存在轮换困难、权限粗粒度、跨项目不可见和多云适配差等问题。

使用 Infisical 进行 Azure DevOps Secrets 管理

Blog image

Azure DevOps pipelines 依赖 secrets(数据库凭据、API tokens、云提供商 keys 和 TLS certificates)来构建、测试和部署软件。问题不在于 Azure DevOps 缺少 secret 存储能力,而在于原生机制无法扩展:secrets 分散积累在 pipeline variable groups、YAML 定义、Key Vault instances 和 repository 历史中,却没有统一的 inventory、一致的 access controls 或自动 rotation。

对于管理数十或数百条 pipeline 的平台团队来说,这种分散是持续的运维负担,并带来真实的安全后果。

将开源且云无关的 secrets 平台 Infisical 与 Azure DevOps pipelines 集成,可以通过基于 OIDC 的身份验证、Terraform 和 OpenTofu workflows,以及使用原生 Infisical operator 的 Kubernetes deployments,实现生产级配置。

原生 Azure DevOps Secrets 管理为何不足

Pipeline Variables 和 Variable Groups

在 YAML 中或通过 Azure DevOps 门户定义的 variables 可以标记为 secret,这会在日志中隐藏它们,并将其加密存储于静态状态。Variable groups 通过在多个 pipeline 之间共享值进一步扩展了这一点。实际上,这种方法在规模化时会失效:

  • 无法自动 rotation。 存储在 variable groups 中的 secrets 是静态的。轮换数据库密码意味着要手动更新引用它的每个 variable group。
  • 访问控制粗粒度。 权限只作用于 project 或 variable group 级别。group 内的单个 secret 无法按 team 或 role 进行限制。
  • 缺少跨 project 可见性。 每个 Azure DevOps project 都独立管理自己的 variables,无法集中了解有哪些 secrets、在哪里被使用、以及它们上次 rotation 的时间。
  • 误暴露风险。 在 YAML 文件中内联定义的 variables 可能被提交到 version control。即使是 secrets,如果 pipeline tasks 不正确地回显它们,也可能泄漏到日志中。

Azure Key Vault 集成

Azure Key Vault 是一个有意义的改进。Secrets 在 pipeline runtime 时检索,而不是存储在 pipeline definitions 中,并且 Key Vault 提供自己的 access policies、audit logging 和 rotation capabilities。然而,Key Vault 也带来了自身的限制:

  • 仅限 Azure 范围。 Key Vault 与 Azure 的 IAM 紧密耦合。部署到 AWS、GCP 或本地基础设施的 pipelines 需要额外工具来管理这些环境中的 secrets。
  • 每个 subscription 一个 vault 的模型。 拥有多个 Azure subscriptions 的组织通常最终会拥有多个 Key Vault instances,在更高层抽象下重现了 sprawl 问题。
  • 没有内置 workflows。 Key Vault 可以存储和检索 secrets,但默认并不提供 approval workflows、change management 或 environment-aware 的 secret scoping。
  • 运维开销。 管理 service connections、access policies 和 Key Vault networking(private endpoints 和 firewalls)会增加基础设施复杂度,并随着 project 和 environment 数量的增加而增长。

集成指南:Infisical + Azure DevOps

Infisical 可通过多种方式与 Azure DevOps 集成:通过 Infisical dashboard 的原生 sync、在 pipeline runtime 通过 CLI 注入、基于 OIDC 的 Workload Identity Federation、Terraform 和 OpenTofu workflow 支持、基于 Kubernetes operator 的 sync,以及用于自定义 workflows 的 API 和 SDK 访问。

前提条件

  • 一个 Infisical account(cloud 或 self-hosted),并已配置至少一个 project 和 environment。
  • 一个具有 project-level admin access 的 Azure DevOps organization。
  • 在 Infisical 中创建的一个 Machine Identity。有关设置说明,请参阅 Infisical Machine Identity 文档

方案 1:原生 Azure DevOps Sync

Infisical 可以直接将 secrets 同步到 Azure DevOps variable groups。由 Infisical 管理的 secrets 会自动推送到 ADO,pipeline 可像使用标准 variable group 引用一样消费它们。无需安装 CLI 或修改 pipeline。

此集成通过 Infisical 的 Secret Syncs system 使用 App Connection 进行配置,而不是旧的 Integrations 页面。App Connections 支持三种连接 Azure DevOps 的身份验证方式:OAuth、Personal Access Token (PAT) 或 Client Secret。请选择适合你组织 access control policy 的方式。

步骤 1:在 Infisical 中创建一个 App Connection

在 Infisical dashboard 中,进入 Organization Settings,然后进入 App Connections,并创建一个新的 Azure DevOps connection。选择你偏好的身份验证方式:

  • OAuth: 推荐用于交互式设置。Infisical 将重定向到 Azure DevOps 完成授权。
  • Personal Access Token: 在 Azure DevOps 的 User Settings 下创建 PAT,然后进入 Personal Access Tokens。授予以下 scopes:Variable Groups(Read, Create and Manage)以及 Project and Team(Read)。根据你组织的 policy 设置过期时间。
  • Client Secret: 注册一个可访问你 ADO organization 的 Entra ID 应用,并提供 client ID 和 secret。

步骤 2:创建一个 Secret Sync

进入你的 Infisical project,然后进入 Secret Syncs,创建一个新的 Azure DevOps sync。选择上面创建的 App Connection,然后配置 sync mapping:

  • Source: Infisical project、environment(例如 production)以及 secret path(例如 /backend/api)。
  • Destination: Azure DevOps organization、project,以及目标 variable group 名称。
  • Sync behavior: 在 manual 或 automatic sync 之间选择。Automatic sync 会在 secret 被创建、更新或删除时,将变更从 Infisical 传播到 ADO。

配置完成后,pipeline 像往常一样通过 variable group 引用 secrets。Infisical 成为单一事实来源,ADO 消费同步后的值。

方案 2:在运行时基于 CLI 注入 Secret

对于希望在 pipeline 执行时直接注入 secrets,而不将其持久化到 ADO variable groups 的团队,Infisical CLI 提供了一个干净的解决方案。Secrets 从 Infisical 中获取,并在 pipeline step 的持续时间内作为 environment variables 注入。它们不会接触 Azure DevOps 存储,只存在于 pipeline agent 的 runtime memory 中。

正确的模式是一个两步流程:首先使用 infisical login 将 Machine Identity 凭据交换为短期 Infisical token,然后通过 --token 标志将该 token 直接传递给每次 infisical run 调用。infisical run 命令不直接接受 --client-id--client-secret。使用 Machine Identity token 认证时,还必须提供 --projectId 标志。

Pipeline 示例:使用 Infisical CLI 进行 Node.js 部署

## azure-pipelines.yml
trigger:
- main

pool:
  vmImage: 'ubuntu-latest'

steps:
  - script: |
      set -euo pipefail
      curl -1sLf \
        'https://dl.cloudsmith.io/public/infisical/infisical-cli/setup.deb.sh' \
        | sudo -E bash
      sudo apt-get update && sudo apt-get install -y infisical
    displayName: 'Install Infisical CLI'

  - script: |
      set -euo pipefail
      # 将 Machine Identity 凭据交换为短期 token。
      # --silent 会抑制 login 提示;--plain 只输出 token。
      INFISICAL_TOKEN=$(infisical login \
        --method=universal-auth \
        --client-id="$(INFISICAL_CLIENT_ID)" \
        --client-secret="$(INFISICAL_CLIENT_SECRET)" \
        --silent --plain)
      echo "##vso[task.setvariable variable=INFISICAL_TOKEN;issecret=true]$INFISICAL_TOKEN"
    displayName: 'Authenticate with Infisical'

  - script: |
      set -euo pipefail
      infisical run \
        --token="$(INFISICAL_TOKEN)" \
        --projectId="$(INFISICAL_PROJECT_ID)" \
        --env=prod \
        --path=/backend/api \
        -- npm ci
      infisical run \
        --token="$(INFISICAL_TOKEN)" \
        --projectId="$(INFISICAL_PROJECT_ID)" \
        --env=prod \
        --path=/backend/api \
        -- npm run build
    displayName: 'Build with secrets'

  - script: |
      set -euo pipefail
      infisical run \
        --token="$(INFISICAL_TOKEN)" \
        --projectId="$(INFISICAL_PROJECT_ID)" \
        --env=prod \
        --path=/backend/api \
        -- npm run deploy
    displayName: 'Deploy'

关于此模式的说明:

  • INFISICAL_CLIENT_IDINFISICAL_CLIENT_SECRETINFISICAL_PROJECT_ID 存储在 ADO 中作为 secret pipeline variables。这些是唯一需要保存在 Azure DevOps 中的凭据。
  • login 步骤使用 --silent --plain 仅输出原始 token 字符串,然后将其设置为 secret pipeline variable 供后续步骤使用。
  • 每次 infisical run 调用都通过 --token 接收 token,并将获取范围限定到特定的 project、environment 和 path。Secrets 只存在于 step 的执行上下文中,不会写入磁盘。

针对特定环境

--env--path 标志可以精确限定 secrets 的范围。常见的环境隔离模式:

## Staging deployment
infisical run \
  --token="$(INFISICAL_TOKEN)" \
  --projectId="$(INFISICAL_PROJECT_ID)" \
  --env=staging \
  --path=/backend/api \
  -- npm run deploy

## Production deployment
infisical run \
  --token="$(INFISICAL_TOKEN)" \
  --projectId="$(INFISICAL_PROJECT_ID)" \
  --env=prod \
  --path=/backend/api \
  -- npm run deploy

每个 path 都映射到 Infisical 中的一个文件夹,因此团队可以按 service、tier 或任何符合其架构的结构来组织 secrets。

方案 3:OIDC / Workload Identity Federation

在 pipeline variables 中使用长期有效的 client secrets 会带来不必要的凭据管理开销。基于 OIDC 的 Workload Identity Federation 是 2026 年 CI/CD systems 的首选身份验证标准。这里描述的方法使用 AzureCLI@2 task 的 federated identity 能力,它从 Microsoft Entra ID 签发一个短期 token。Infisical 的 JWT Auth 方法会验证该 token,然后返回一个短期 Infisical access token。Azure DevOps 中不会存储任何静态 Infisical 凭据。

工作原理

启用 addSpnToEnvironment: trueAzureCLI@2 task 会暴露由 Microsoft Entra ID 为 Azure DevOps service connection 背后的 service principal 签发的 OIDC token。该 token 会通过 jwt-auth 方法传递给 infisical login。Infisical 会针对 Entra ID JWKS endpoint 验证 token 签名,并在签发 session token 之前检查已配置的 claim bindings。

步骤 1:在 Infisical Machine Identity 上配置 JWT Auth

在 Infisical dashboard 中,进入你的 Machine Identity 并选择 JWT Auth 作为身份验证方法。配置以下字段:

  • JWKS URL: 你租户的 Microsoft Entra ID JWKS endpoint:https://login.microsoftonline.com/{tenantId}/discovery/v2.0/keys。这是真正的 public key endpoint,而不是 OIDC discovery document URL。
  • Bound issuer: https://login.microsoftonline.com/{tenantId}/v2.0
  • Bound subject: 你的 Entra ID service principal token 的 subject claim。通常是支撑 Azure DevOps service connection 的 service principal 或 app registration 的 Object ID。请通过解码 pipeline 中的示例 token 来验证准确值。
  • Bound audiences: api://AzureADTokenExchange(Azure federated identity tokens 的标准 audience)。

有关完整的可配置 claim bindings 以及如何将 identities 限定到特定 projects 和 environments,请参阅 Infisical JWT Auth 文档

步骤 2:将 OIDC Token 交换为 Infisical Session Token

## azure-pipelines.yml
trigger:
- main

pool:
  vmImage: 'ubuntu-latest'

steps:
  - script: |
      set -euo pipefail
      curl -1sLf \
        'https://dl.cloudsmith.io/public/infisical/infisical-cli/setup.deb.sh' \
        | sudo -E bash
      sudo apt-get update && sudo apt-get install -y infisical
    displayName: 'Install Infisical CLI'

  - task: AzureCLI@2
    inputs:
      azureSubscription: '$(SERVICE_CONNECTION_NAME)'
      scriptType: 'bash'
      addSpnToEnvironment: true
      scriptLocation: 'inlineScript'
      inlineScript: |
        set -euo pipefail
        # $idToken 是 addSpnToEnvironment 暴露的 Entra ID OIDC token。
        # --method=jwt-auth 是正确的标志;必须提供 --machine-identity-id。
        # --silent --plain 只输出原始 Infisical session token。
        INFISICAL_TOKEN=$(infisical login \
          --method=jwt-auth \
          --machine-identity-id="$(INFISICAL_MACHINE_IDENTITY_ID)" \
          --jwt="$idToken" \
          --silent --plain)
        echo "##vso[task.setvariable variable=INFISICAL_TOKEN;issecret=true]$INFISICAL_TOKEN"
    displayName: 'Authenticate with Infisical via OIDC'

  - script: |
      set -euo pipefail
      infisical run \
        --token="$(INFISICAL_TOKEN)" \
        --projectId="$(INFISICAL_PROJECT_ID)" \
        --env=prod \
        --path=/backend/api \
        -- npm run deploy
    displayName: 'Deploy with secrets'

使用此模式时,Azure DevOps 中不会存储任何静态 Infisical 凭据。只需将 INFISICAL_MACHINE_IDENTITY_IDINFISICAL_PROJECT_ID 设为 pipeline variables 即可(两者都不敏感,尽管标记为 secret 也无妨)。Entra ID OIDC token 是短暂的,并且仅作用于该 pipeline run。

方案 4:Terraform 和 OpenTofu Workflow 集成

Terraform 和 OpenTofu pipelines 有不同的 secrets 需求:provider 身份验证凭据、variable inputs 和 state backend 访问都需要仔细管理。Infisical CLI 可在 ADO-based IaC pipelines 中将其无缝集成到这三类场景。这里同样适用方案 2 中的先 login 再 run 的 token 交换模式。

注入 Provider 凭据

Cloud provider 凭据绝不应存储在 .tfvars 文件或 pipeline variable groups 中。先获取一个 Infisical session token,然后用 infisical run 包裹 Terraform commands,在运行时注入它们。Terraform providers 会自动从注入的 environment 中读取它们期望的 environment variable 名称(例如 AzureRM provider 的 ARM_CLIENT_ID):

steps:
  - script: |
      set -euo pipefail
      INFISICAL_TOKEN=$(infisical login \
        --method=universal-auth \
        --client-id="$(INFISICAL_CLIENT_ID)" \
        --client-secret="$(INFISICAL_CLIENT_SECRET)" \
        --silent --plain)
      echo "##vso[task.setvariable variable=INFISICAL_TOKEN;issecret=true]$INFISICAL_TOKEN"
    displayName: 'Authenticate with Infisical'

  - script: |
      set -euo pipefail
      # ARM_CLIENT_ID、ARM_CLIENT_SECRET、ARM_TENANT_ID 和
      # ARM_SUBSCRIPTION_ID 存储在 Infisical 的 /infra/azure 中,
      # 并自动注入给 AzureRM provider。
      infisical run \
        --token="$(INFISICAL_TOKEN)" \
        --projectId="$(INFISICAL_PROJECT_ID)" \
        --env=prod \
        --path=/infra/azure \
        -- bash -c '
          terraform init
          terraform plan -out=tfplan
          terraform apply tfplan
        '
    displayName: 'Terraform Apply'

注入 Terraform Input Variables

Terraform 从以 TF_VAR_ 为前缀的 environment variables 中读取输入 variables。由于 Infisical CLI 不支持自动前缀重映射,正确的模式是在调用 Terraform 之前显式导出每个 secret。这样映射保持透明且可审计:

## main.tf
variable "database_url" {
  type      = string
  sensitive = true
}

variable "api_key" {
  type      = string
  sensitive = true
}
## azure-pipelines.yml
  - script: |
      set -euo pipefail
      # 先将 secrets 作为 JSON 导出,然后在运行 Terraform 之前
      # 将每一个映射为 TF_VAR_ environment variable。
      eval "$(infisical export \
        --token="$(INFISICAL_TOKEN)" \
        --projectId="$(INFISICAL_PROJECT_ID)" \
        --env=prod \
        --path=/infra/shared \
        --format=dotenv | sed 's/^/export TF_VAR_/')"
      terraform apply
    displayName: 'Terraform Apply with Input Variables'

注:请根据你的 CLI 版本验证 infisical export 的输出格式。如果 dotenv 输出包含引号或注释,请在 eval 之前应用额外过滤。始终先在非生产环境中测试 variable 注入。

管理 State Backend 凭据

对于存储在 Azure Blob Storage 或 S3-compatible backends 中的 Terraform state,以相同方式注入 backend 凭据。Backend config 值可在 init 时通过 -backend-config 标志传入:

  - script: |
      set -euo pipefail
      infisical run \
        --token="$(INFISICAL_TOKEN)" \
        --projectId="$(INFISICAL_PROJECT_ID)" \
        --env=prod \
        --path=/infra/state \
        -- bash -c '
          terraform init \
            -backend-config="storage_account_name=$STORAGE_ACCOUNT_NAME" \
            -backend-config="container_name=$CONTAINER_NAME" \
            -backend-config="access_key=$STORAGE_ACCESS_KEY"
        '
    displayName: 'Terraform Init with Backend Credentials'

方案 5:使用 Infisical Operator 的 Kubernetes

对于部署到 AKS 或任何 Kubernetes cluster 的团队,Infisical 提供了一个原生 Kubernetes operator,可将 Infisical 中的 secrets 直接同步到 Kubernetes Secret resources。这是基于 Kubernetes 的 workloads 的推荐模式,并且无需对应用代码做任何改动。

该 operator 支持 Kubernetes native authentication,这是 in-cluster workloads 的推荐方式。与其在 cluster 内保存静态 client secret,不如让 Kubernetes Auth 使用 Kubernetes 原生签发的 projected ServiceAccount token 向 Infisical 进行身份识别。Infisical 会针对 cluster 的 API server 验证 token,确认 ServiceAccount 名称和 namespace 与绑定的 identity 匹配,然后返回一个短期 Infisical access token。不会有任何长期凭据进入 cluster。

Operator 的工作原理

Infisical Secrets Operator 部署到你的 cluster 中,并监听 InfisicalSecret custom resources。当 resource 被创建或更新时,operator 会将其 ServiceAccount token 提交给 Infisical 的 Kubernetes Auth endpoint。验证成功后,Infisical 返回一个 access token,operator 使用该 token 拉取指定 secrets,并将其协调为目标 namespace 中的 Kubernetes Secret。应用通过标准 Kubernetes 方式,将这些 secrets 作为 environment variables 或挂载 volumes 使用。

步骤 1:在 Infisical Machine Identity 上配置 Kubernetes Auth

在安装 operator 之前,请在 Infisical 中创建一个 Machine Identity,并启用 Kubernetes Auth 作为身份验证方法。你需要提供:

  • Kubernetes host: 你 cluster 的 API server URL(例如,https://your-aks-cluster.hcp.eastus.azmk8s.io)。
  • Token reviewer JWT: 具有调用 Kubernetes TokenReview API 权限的 ServiceAccount token。这使 Infisical 能够验证传入 tokens。创建一个专用的 reviewer ServiceAccount(见下文)。
  • CA certificate: 你 cluster 的 CA certificate,Infisical 用它在 token review 期间验证 Kubernetes API server 的真实性。
  • Bound service account names and namespaces: operator 将使用的特定 ServiceAccount 名称和 namespace。Infisical 会拒绝来自不在此列表中的任何 ServiceAccount 的 tokens。

完整配置步骤可在 Infisical Kubernetes Auth 文档 中查看。

步骤 2:创建 Reviewer 和 Operator 的 ServiceAccounts

需要两个 ServiceAccounts:一个用于 TokenReview delegation(reviewer),另一个用于 operator 自身向 Infisical 进行身份验证。

## reviewer-sa.yaml
## 此 ServiceAccount 供 Infisical 使用,
## 通过 Kubernetes TokenReview API 验证 operator tokens。
apiVersion: v1
kind: ServiceAccount
metadata:
  name: infisical-token-reviewer
  namespace: infisical-operator
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: infisical-token-reviewer
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: system:auth-delegator
subjects:
  - kind: ServiceAccount
    name: infisical-token-reviewer
    namespace: infisical-operator
---
## operator-sa.yaml
## 这是 operator 向 Infisical 出示的身份。
## 其名称和 namespace 必须与
## 在 Infisical Machine Identity 上配置的绑定值匹配。
apiVersion: v1
kind: ServiceAccount
metadata:
  name: infisical-operator
  namespace: infisical-operator

步骤 3:安装 Operator

helm repo add infisical-helm-charts \
  'https://dl.cloudsmith.io/public/infisical/helm-charts/helm/charts/'
helm repo update
helm install infisical-operator infisical-helm-charts/secrets-operator \
  --namespace infisical-operator \
  --create-namespace \
  --set serviceAccount.name=infisical-operator

步骤 4:使用 Kubernetes Auth 定义一个 Secret Sync

在 operator 运行并且 Machine Identity 已配置后,创建一个 InfisicalSecret resource。kubernetesAuth block 引用 Machine Identity ID 和 operator 运行所使用的 ServiceAccount。secret scope(即要从哪个 project、environment 和 path 拉取)定义在 kubernetesAuth block 下的 secretsScope 中。注意,hostAPI 需要带上 /api path suffix,且 resyncIntervalsyncConfig 下的 duration string。

apiVersion: secrets.infisical.com/v1alpha1
kind: InfisicalSecret
metadata:
  name: backend-api-secrets
  namespace: production
spec:
  hostAPI: https://app.infisical.com/api
  syncConfig:
    resyncInterval: "60s"
  authentication:
    kubernetesAuth:
      identityId: <your-infisical-machine-identity-id>
      serviceAccountRef:
        name: infisical-operator
        namespace: infisical-operator
      secretsScope:
        projectSlug: my-project
        envSlug: prod
        secretsPath: /backend/api
  managedKubeSecretReferences:
    - secretName: backend-api-secrets
      secretNamespace: production

identityId 字段是你在 Infisical 中创建并启用了 Kubernetes Auth 的 Machine Identity 的 UUID。serviceAccountRef 必须与你绑定到该 identity 的 ServiceAccount 名称和 namespace 匹配。secretsScope 使用 slugs 而不是 display names 定义要同步的 Infisical project、environment 和 path。此配置中不会创建或引用任何包含 client secret 的 Kubernetes Secret。

operator 会持续协调 managedKubeSecretReferences 中的每个条目。当某个值在 Infisical 中被 rotation 时,对应的 Kubernetes Secret 会在下一个 resync interval 内自动更新。

有关包括 secret templating 和在 secret 变化时自动重载 Deployments 在内的高级配置,请参阅 Infisical Kubernetes operator 文档

步骤 5:在 Deployment 中消费已同步的 Secret

应用使用标准 envFrom 或 volume mounts 来引用受管理的 Kubernetes Secret。用于 Kubernetes Auth 的 ServiceAccount 是 operator 自身的身份,与 application pods 完全独立,后者无需任何特殊配置。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: backend-api
  namespace: production
spec:
  template:
    spec:
      containers:
        - name: api
          image: my-backend:latest
          envFrom:
            - secretRef:
                name: backend-api-secrets

deployment manifest 中不会硬编码任何 secrets,cluster 中也不会存储任何凭据。operator 使用其原生 Kubernetes ServiceAccount token 向 Infisical 进行身份验证,拉取 secrets,并自动保持 Kubernetes Secret 的协调一致。

方案 6:API 和 SDK 集成

对于高级自动化、自定义工具,或在应用代码或脚本中需要程序化访问 secrets 的场景,Infisical 提供 REST APIs 以及 Node.js、Python、Go、Ruby 和 PHP 的官方 SDKs。

示例:使用 Node.js SDK 获取 Secret

// fetch-and-use-secret.js
const { InfisicalSDK } = require('@infisical/sdk');

async function connectToDatabase() {
  const client = new InfisicalSDK({
    siteUrl: 'https://app.infisical.com', // 或你的 self-hosted URL
  });

  await client.auth().universalAuth.login({
    clientId: process.env.INFISICAL_CLIENT_ID,
    clientSecret: process.env.INFISICAL_CLIENT_SECRET,
  });

  const secret = await client.secrets().getSecret({
    environment: 'prod',
    projectId: process.env.INFISICAL_PROJECT_ID,
    secretName: 'DATABASE_URL',
    secretPath: '/backend/api',
  });

  // 将该值直接传递给需要它的函数。
  // 永远不要记录或打印 secret 值。
  const db = await createConnection(secret.secretValue);
  return db;
}

这种方式适用于基础设施脚本、自定义部署工具,或需要在启动时解析 secrets 而不是依赖 environment variable 注入的应用。

方案 7:同步到 Azure Key Vault

已有 Azure Key Vault workflows 的组织可以采用 Infisical 作为集中管理层,同时继续将 secrets 同步到 Key Vault instances。Infisical 以集中、可审计、跨云的事实来源替代手动 Key Vault 管理,而使用 AzureKeyVault@2 task 的 pipelines 可以无需修改继续运行。

设置

与 Azure DevOps variable group sync 类似,Azure Key Vault sync 通过 Infisical 的 Secret Syncs system 使用 App Connection 进行配置。在 Infisical dashboard 中,进入 Organization Settings,然后进入 App Connections,并使用 Microsoft Entra ID service principal 或 managed identity 创建一个 Azure connection。该 connection 必须被授予你 vault 的 Key Vault Secrets Officer 权限。然后进入项目的 Secret Syncs,创建一个新的 Azure Key Vault sync,并配置:

配置完成后,Infisical 会按照你定义的 sync schedule 将 secrets 推送到 Key Vault。Continuous sync 可确保轮换后的值自动传播。引用 Key Vault secrets 的现有 ADO pipelines 无需更改。这是一条实用的迁移路径:采用 Infisical 进行集中管理和 rotation,同时保持现有 pipeline 集成不变。

动态 Secrets:消除长期凭据

静态 secrets(创建一次并使用到有人轮换为止的凭据)是持续存在的攻击面。Infisical 支持 dynamic secrets,可按需生成短期凭据,并在可配置的 TTL 之后自动吊销。

在 Azure DevOps pipeline 场景中,deploy step 可以请求一个有效期 60 分钟的新数据库凭据,在部署期间使用它,并让其自动过期。无需 cleanup scripts,也不会有过时凭据留在 variable groups 中。

Infisical 支持为 PostgreSQL、MySQL、MongoDB、AWS IAM、Microsoft Entra ID、GCP service accounts 以及其他 backends 生成 dynamic secrets。配置在 Infisical dashboard 的项目 Dynamic Secrets section 中完成。

生产使用的最佳实践

使用 Machine Identities,而不是个人 tokens

使用 Infisical Machine Identities 对 pipelines 进行身份验证。Machine Identities 可以限定到特定 projects 和 environments,提供便于审计的身份轨迹,并且不会因员工离职而过期。对于非交互式 pipeline 身份验证,应避免使用个人 API tokens。

优先使用 OIDC,而不是长期凭据

在可能的情况下,使用基于 OIDC 的 Workload Identity Federation(方案 3)来替代 client secret 对。OIDC tokens 短期有效,并且仅作用于特定的 pipeline run,从而消除了因 pipeline variables 被攻破而导致的凭据窃取风险。

强制环境隔离

将 dev、staging 和 production secrets 放在不同的 Infisical environments 中。限定 Machine Identity permissions,使 staging pipeline identity 无法读取 production secrets。这可以在事故中限制 blast radius,并防止凭据交叉污染。

为敏感更改启用审批 workflows

对于 production environments,配置 Infisical 的 approval policies,要求在修改 secret values 之前进行 review。这样可以为关键更改增加一个人工检查点,而无需引入单独的 change management process。审批可直接在 Infisical UI 中处理,或通过 Slack 和 email 通知处理。

自动轮换凭据

为无法通过 dynamic secrets 替代的静态 secrets 配置 rotation policies。Infisical 支持对数据库凭据、cloud provider keys 和其他常见 secret types 的自动 rotation。结合对 ADO variable groups 或 Key Vault 的 continuous sync,轮换后的值可在无需人工干预的情况下自动传播。

审计并监控访问

Infisical 会记录每一次 secret read、write 和 permission change。将这些 audit logs 输入你的 SIEM 或 monitoring stack,以检测异常 access patterns。对于 SOC 2、ISO 27001 或 HIPAA 等 compliance frameworks,这些日志可提供审计所需的证据链。

将 Secrets Scanning 作为 pipeline gate

将 secrets management 与 secrets scanning 配对使用。Infisical 的扫描能力可以在 credentials 到达 production 之前检测仓库中的泄漏。将其作为 pipeline gate 可在源头捕获误暴露,并自然集成到你现有的 pull request workflow 中。

尽量减少存储在 Azure DevOps 中的 secrets

使用 CLI 方案时,Azure DevOps 中唯一需要存在的 secrets 是 Machine Identity 的 client ID 和 client secret。使用基于 OIDC 的身份验证(方案 3)时,甚至这些都不需要。这会显著减少 ADO 本身的攻击面。

选择合适的方案

这七种集成模式分别适用于不同团队需求。请使用下表为你的组织确定合适的起点:

方案 最适合
原生 ADO Sync(方案 1) 希望即插即用且无需修改 pipeline 的团队
CLI 注入(方案 2) 希望仅在运行时注入且不在 ADO 存储 secrets 的团队
OIDC Auth(方案 3) 注重安全、希望从 ADO 中移除所有长期凭据的团队
Terraform(方案 4) 管理 provider 凭据和输入 variables 的 IaC 团队
Kubernetes Operator(方案 5) 部署到 AKS 或任何 Kubernetes cluster 的团队
SDK / API(方案 6) 自定义工具和应用级 secret 解析
Key Vault Sync(方案 7) 具有现有 Key Vault pipelines、正在迁移到集中管理的团队

Azure DevOps 原生的 secret 处理方式适用于简单场景。运行多云基础设施、跨多个 projects 管理 secrets,或需要符合审计级合规要求的组织将会超出其能力范围。Infisical 提供了填补这一空白的集中控制平面,而且无需彻底重构 pipeline。

要开始使用,请查阅 Infisical Azure DevOps 集成文档GitHub 上的开源仓库

Mathew Pregasen avatar

Mathew Pregasen

Technical Writer, Infisical

  • 原文链接: infisical.com/blog/azure...
  • 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
点赞 0
收藏 0
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

0 条评论

请先 登录 后评论
infisical
infisical
江湖只有他的大名,没有他的介绍。