在 CI 中使用外部 secret

密钥代表了需要完成您 CI 作业的敏感信息。这些敏感信息可能是 API 令牌、数据库凭据或私钥。密钥存储在您的密钥提供器中。

和 CI/CD 变量不一样,密钥必须由作业明确要求。关于语法的更对详情,可阅读极狐GitLab CI/CD 流水线配置参考以获取更多信息。

极狐GitLab 支持一下密钥管理提供商:

  1. Vault by HashiCorp
  2. Google Cloud Secret Manager
  3. Azure Key Vault

极狐GitLab 已经选择 Hashicorp Valut 作为第一个支持提供商,KV-V2是第一个支持的密钥引擎。

使用 ID 令牌使用 ID 令牌进行身份验证使用 Hashicorp Vault 进行身份验证和读取机密教程中有关使用 ID 令牌进行身份验证的更多详细信息。

在您可以在 CI 作业中使用 Vault 密钥之前,您必须配置您的 Vault 服务器

以下是极狐GitLab 和 Vault 集成的示意图:

Flow between GitLab and HashiCorp

  1. 配置您的 vault 和密钥。
  2. 生成您的 JWT 并将其提供给您的 CI 作业。
  3. Runner 联系 HashiCorp Vault 并使用 JWT 进行身份验证。
  4. HashiCorp Vault 验证 JWT。
  5. HashiCorp Vault 检查绑定的声明并附加策略。
  6. HashiCorp Vault 返回令牌。
  7. Runner 从 HashiCorp Vault 中读取密钥。
note 阅读使用 Hashicorp Vault 进行身份验证和读取机密教程以查看此功能的某个版本。所有订阅级别都可使用此功能,支持从 Vault 写、读取和删除机密,并支持多个机密引擎。

您必须将下面的 vault.example.com URL 替换为您的 Vault 服务器,并将 gitlab.example.com 替换为您的极狐GitLab 实例 URL。

Vault 密钥引擎

  • generic 选项引入于极狐GitLab Runner 16.11。

极狐GitLab Runner 支持的 Vault 密钥引擎有:

密钥引擎 secrets:engine:name Runner 版本 详情
KV secrets engine - version 2 kv-v2 13.4 当没有显式指定引擎类型时,极狐GitLab 默认使用 kv-v2
KV secrets engine - version 1 kv-v1generic 13.4 对于 generic 关键字的支持引入于极狐GitLab 15.11。
The AWS secrets engine generic 16.11  
Hashicorp Vault Artifactory Secrets Plugin generic 16.11 此密钥后端和 JFrog Artifactory server (5.0.0 及以后) 进行通信并动态创建具有特定范围的访问令牌。

配置您的 Vault 服务器

要配置您的 Vault 服务器:

  1. 确保您的 Vault 服务器在 1.2.0 或更高版本上运行。
  2. 通过运行这些命令启用身份验证方法。他们为您的实例提供 JSON Web 密钥集 (JWKS) 端点,以便认证时, Vault 可以获取公共签名密钥并验证 JSON Web 令牌 (JWT) :

    $ vault auth enable jwt
    
    $ vault write auth/jwt/config \
      jwks_url="https://gitlab.example.com/-/jwks" \
      bound_issuer="gitlab.example.com"
    
  3. 在您的 Vault 服务器上配置策略,授予或禁止对某些路径和操作的访问。此示例授予对生产环境所需的一组 secret 的读取访问权限:

    vault policy write myproject-production - <<EOF
    # Read-only permission on 'ops/data/production/*' path
    
    path "ops/data/production/*" {
      capabilities = [ "read" ]
    }
    EOF
    
  4. 在您的 Vault 服务器上配置角色,将角色限制为项目或命名空间,如本页 配置 Vault 服务器角色 中所述。
  5. 创建以下 CI/CD 变量,提供有关您的 Vault 服务器的详细信息:
    • VAULT_SERVER_URL - Vault 服务器的 URL,例如 https://vault.example.com:8200。必需。
    • VAULT_AUTH_ROLE -(可选)尝试进行身份验证时使用的角色。如果未指定角色,Vault 将使用配置身份验证方法时指定的默认角色
    • VAULT_AUTH_PATH -(可选)挂载认证方法的路径,默认为 jwt
    • VAULT_NAMESPACE - 可选。 Vault 企业命名空间用来读取密钥和进行验证。使用:
      • Vault,当没有指定命名空间时使用 root (“/”) 命名空间。
      • Vault Open source,忽略该设置。
      • HashiCorp Cloud Platform (HCP) Vault,需要一个命名空间。默认情况下 HCP Vault 使用 admin 命名空间作为 root 命名空间。比如,VAULT_NAMESPACE=admin

在 CI 作业中使用 Vault secret

配置您的 Vault 服务器后,您可以通过使用 vault 关键字,定义存储在 Vault 中的 secret,然后使用它们:

job_using_vault:
  id_tokens:
    VAULT_ID_TOKEN:
      aud: https://vault.example.com
  secrets:
    DATABASE_PASSWORD:
      vault: production/db/password@ops  # translates to secret `ops/data/production/db`, field `password`
      token: $VAULT_ID_TOKEN

在这个例子中:

  • production/db - secret。
  • password - 字段。
  • ops - 安装 secret engine 的路径。

极狐GitLab 从 Vault 获取 secret 后,该值将保存在一个临时文件中。此文件的路径存储在名为 DATABASE_PASSWORD 的 CI/CD 变量中

要覆盖默认,请显式设置 file 选项:

secrets:
  id_tokens:
    VAULT_ID_TOKEN:
      aud: https://vault.example.com
  DATABASE_PASSWORD:
    vault: production/db/password@ops
    file: false
    token: $VAULT_ID_TOKEN

在这个例子中,secret 值直接放在 DATABASE_PASSWORD 变量中,而不是指向保存它的文件。

使用不同的密钥引擎

默认情况下使用 kv-v2 密钥引擎。要使用其他引擎,请在配置中将 engine 部分添加到 vault 下。

比如,要为 Artifactory 设置密钥引擎和路径:

job_using_vault:
  id_tokens:
    VAULT_ID_TOKEN:
      aud: https://vault.example.com
  secrets:
    JFROG_TOKEN:
      vault:
        engine:
          name: generic
          path: artifactory
        path: production/jfrog
        field: access_token
      file: false

在此示例中,secret 值从 artifactory/production/jfrog 获取,字段为 access_tokengeneric 密钥引擎可用于 kv-v1、AWS、Artifactory 和其他类似 vault 密钥引擎

配置 Vault 服务器角色

当 CI 作业尝试进行身份验证时,它会指定一个角色。您可以使用角色将不同的策略组合在一起。如果身份验证成功,这些策略将附加到生成的 Vault 令牌。

绑定声明 是与 JWT 声明匹配的预定义值。使用 bounded claims,您可以为特定 Git 引用,限制对特定极狐GitLab 用户、特定项目甚至运行的作业的访问。您可以拥有所需数量的 bounded claims,但它们必须全部匹配才能成功进行身份验证。

将 bounded claims 与用户角色和受保护分支等功能相结合,您可以定制这些规则来适合您的特定用例。在此示例中,仅允许为受保护标签运行的作业进行身份验证,其名称与用于生产版本的 pattern 相匹配:

$ vault write auth/jwt/role/myproject-production - <<EOF
{
  "role_type": "jwt",
  "policies": ["myproject-production"],
  "token_explicit_max_ttl": 60,
  "user_claim": "user_email",
  "bound_claims_type": "glob",
  "bound_claims": {
    "project_id": "42",
    "ref_protected": "true",
    "ref_type": "tag",
    "ref": "auto-deploy-*"
  }
}
EOF
caution 始终使用提供的声明之一(如 project_idnamespace_id)将您的角色限制在项目或命名空间。在没有这些限制的情况下,可以允许此实例生成的任何 JWT 使用此角色进行身份验证。

您还可以为生成的 Vault 令牌指定一些属性,例如生存时间、IP 地址范围和使用次数。JSON 网络令牌方法的完整选项列表可在 Vault 的创建角色文档 中找到。

使用自签名的 Vault 服务器

当 Vault 服务器使用自签名证书时,您可以在作业日志中看到如下错误:

ERROR: Job failed (system failure): resolving secrets: initializing Vault service: preparing authenticated client: checking Vault server health: Get https://vault.example.com:8000/v1/sys/health?drsecondarycode=299&performancestandbycode=299&sealedcode=299&standbycode=299&uninitcode=299: x509: certificate signed by unknown authority

您有两种方法来解决此错误:

  • 将自签名证书添加到极狐GitLab Runner 服务器的 CA sotre 中。如果您使用的是Helm chart部署的 runner,您需要创建您自己的极狐GitLab Runner 镜像。
  • 使用 VAULT_CACERT 环境变量来配置极狐GitLab Runner 以信任证书:
    • If you are using systemd to manage GitLab Runner, see how to add an environment variable for GitLab Runner.
    • 如果您正在使用 systemd 来管理极狐GitLab Runner,请参阅如何为极狐GitLab Runner 添加环境变量
    • 如果您使用的是Helm chart部署的极狐GitLab Runner:
      1. 提供一个能访问极狐GitLab 的自定义证书,并确保添加 Vault 服务器的证书而不是极狐GitLab 的证书。如果您的极狐GitLab 实例也使用自签名证书,您可以将两个证书添加到同一个 Secret 中。
      2. 在您的 values.yaml 文件中添加以下行:

        ## Replace both the <SECRET_NAME> and the <VAULT_CERTIFICATE>
        ## with the actual values you used to create the secret
        
        certsSecretName: <SECRET_NAME>
        
        envVars:
          - name: VAULT_CACERT
            value: "/home/gitlab-runner/.gitlab-runner/certs/<VAULT_CERTIFICATE>"
        

故障排查

resolving secrets: secret not found: MY_SECRET 错误

当极狐GitLab 在 vault 中无法找到密钥时,就会报如下错误:

ERROR: Job failed (system failure): resolving secrets: secret not found: MY_SECRET

检查以确保 vault 的值在 CI/CD 作业中配置正确

您可以使用 kv 命令与 Vault CLI来检查是否可以从 vault 中检索到密钥,以帮助确定 CI/CD 配置中 vault 值的语法。例如,要检索密钥:

$ vault kv get -field=password -namespace=admin -mount=ops "production/db"
this-is-a-password