在 CI 中使用外部 secret

  • 引入于极狐GitLab 13.4 版本和 GitLab Runner 13.4 版本。
  • file 设置引入于极狐GitLab 14.1 版本和 GitLab Runner 14.1 版本。
  • VAULT_NAMESPACE 设置引入于极狐GitLab 14.9 版本和 GitLab Runner 14.9。

Secret 代表完成您的 CI 作业所需的敏感信息。此敏感信息可以是 API 令牌、数据库凭据或私钥等项目。 Secret 来自您的 secrets provider。

与始终呈现给作业的 CI/CD 变量不同,作业必须明确要求 secret。阅读 GitLab CI/CD 流水线配置参考 以获取有关语法的更多信息。

GitLab 选择了 Vault by HashiCorp 作为第一个支持的提供者,以及 KV-V2 作为第一个支持的 secret engine。

GitLab 使用 Vault 的 JSON Web Token (JWT) 身份验证方法 进行身份验证,使用 JSON Web Token (CI_JOB_JWT) 于 12.10 版本引入。

您必须配置您的 Vault 服务器,然后才能在 CI 作业中使用 Vault secret

下图总结了使用 GitLab 和 HashiCorp Vault 的流程:

Flow between GitLab and HashiCorp

  1. 配置您的 vault 和 secret。
  2. 生成您的 JWT 并将其提供给您的 CI 作业。
  3. Runner 联系 HashiCorp Vault 并使用 JWT 进行身份验证。
  4. HashiCorp Vault 验证 JWT。
  5. HashiCorp Vault 检查 bounded claims 并附加策略。
  6. HashiCorp Vault 返回令牌。
  7. Runner 从 HashiCorp Vault 读取 secrets。

配置您的 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 -(可选)用于读取 secret 和身份验证的 Vault Enterprise 命名空间。 如果没有指定命名空间,Vault 使用 root (“/”) 命名空间。 Vault Open Source 忽略该设置。

在 CI 作业中使用 Vault secret

引入于 13.4 版本和 GitLab Runner 13.4。

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

secrets:
  DATABASE_PASSWORD:
    vault: production/db/password@ops  # translates to secret `ops/data/production/db`, field `password`

在这个例子中:

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

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

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

secrets:
  DATABASE_PASSWORD:
    vault: production/db/password@ops
    file: false

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

有关支持的语法的更多信息,请阅读 .gitlab-ci.yml 参考

配置 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 的创建角色文档 中找到。