Help us learn about your current experience with the documentation. Take the survey.

在 AWS 中配置 OpenID Connect 以获取临时凭证

  • Tier: Free, Premium, Ultimate
  • Offering: GitLab.com, GitLab Self-Managed, GitLab Dedicated

CI_JOB_JWT_V2GitLab 15.9 中已被弃用 并计划在 GitLab 17.0 中移除。请改用 ID tokens

在本教程中,我们将向您展示如何使用带有 JSON Web Token (JWT) 的 GitLab CI/CD 作业从 AWS 获取临时凭证,而无需存储密钥。 为此,您必须在 GitLab 和 AWS 之间配置 OpenID Connect (OIDC) 进行身份联合。有关使用 OIDC 集成 GitLab 的背景和要求,请参阅 连接到云服务

完成本教程需要:

  1. 添加身份提供者
  2. 配置角色和信任关系
  3. 获取临时凭证

添加身份提供者

按照这些 说明 在 AWS 中创建 GitLab 作为 IAM OIDC 提供者。

包含以下信息:

  • 提供者 URL:您的 GitLab 实例地址,例如 https://gitlab.comhttp://gitlab.example.com。 此地址必须可公开访问。如果不可公开访问,请参阅如何 配置非公开的 GitLab 实例
  • 受众:您的 GitLab 实例地址,例如 https://gitlab.comhttp://gitlab.example.com
    • 地址必须包含 https://
    • 不要包含尾部斜杠。

配置角色和信任关系

创建身份提供者后,配置一个带有条件的 Web 身份角色,以限制对 GitLab 资源的访问。临时凭证是使用 AWS Security Token Service 获取的,因此将 Action 设置为 sts:AssumeRoleWithWebIdentity

您可以创建一个 自定义信任策略 来限制对特定组、项目、分支或标签的授权。 有关支持的过滤类型的完整列表,请参阅 连接到云服务

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Federated": "arn:aws:iam::AWS_ACCOUNT:oidc-provider/gitlab.example.com"
      },
      "Action": "sts:AssumeRoleWithWebIdentity",
      "Condition": {
        "StringEquals": {
          "gitlab.example.com:sub": "project_path:mygroup/myproject:ref_type:branch:ref:main"
        }
      }
    }
  ]
}

创建角色后,将定义权限的策略附加到 AWS 服务(S3、EC2、Secrets Manager)。

获取临时凭证

配置 OIDC 和角色后,GitLab CI/CD 作业可以从 AWS Security Token Service (STS) 获取临时凭证。

assume role:
  id_tokens:
    GITLAB_OIDC_TOKEN:
      aud: https://gitlab.example.com
  script:
    # this is split out for correct exit code handling
    - >
      aws_sts_output=$(aws sts assume-role-with-web-identity
      --role-arn ${ROLE_ARN}
      --role-session-name "GitLabRunner-${CI_PROJECT_ID}-${CI_PIPELINE_ID}"
      --web-identity-token ${GITLAB_OIDC_TOKEN}
      --duration-seconds 3600
      --query 'Credentials.[AccessKeyId,SecretAccessKey,SessionToken]'
      --output text)
    - export $(printf "AWS_ACCESS_KEY_ID=%s AWS_SECRET_ACCESS_KEY=%s AWS_SESSION_TOKEN=%s" $aws_sts_output)
    - aws sts get-caller-identity
  • ROLE_ARN:在此 步骤 中定义的角色 ARN。
  • GITLAB_OIDC_TOKEN:一个 OIDC ID token

工作示例

配置非公开的 GitLab 实例

  • Tier: Free, Premium, Ultimate
  • Offering: GitLab Self-Managed

此解决方法是一个高级配置选项,需要理解安全注意事项。 您必须小心地将 OpenID 配置和来自您的私有 GitLab Self-Managed 实例的公钥同步到公开可用的位置,例如 S3 存储桶。 您还必须确保 S3 存储桶和其中的文件得到适当保护。 未能正确保护 S3 存储桶可能导致与此 OpenID Connect 身份关联的任何云账户被接管。

如果您的 GitLab 实例不可公开访问,默认情况下无法在 AWS 中配置 OpenID Connect。您可以使用解决方法使某些特定配置公开可用,从而为实例启用 OpenID Connect 配置:

  1. 将您的 GitLab 实例的身份验证详细信息存储在公开可用的位置, 例如在 S3 文件中:

    • 在 S3 文件中托管您实例的 OpenID 配置。配置可在 /.well-known/openid-configuration 获取,如 http://gitlab.example.com/.well-known/openid-configuration。 更新配置文件中的 issuer:jwks_uri: 值,使其指向公开可用的位置。
    • 在 S3 文件中托管您实例 URL 的公钥。密钥可在 /oauth/discovery/keys 获取, 如 http://gitlab.example.com/oauth/discovery/keys

    例如:

    • OpenID 配置文件:https://example-oidc-configuration-s3-bucket.s3.eu-north-1.amazonaws.com/.well-known/openid-configuration
    • JWKS (JSON Web Key Sets):https://example-oidc-configuration-s3-bucket.s3.eu-north-1.amazonaws.com/oauth/discovery/keys
    • ID Token 中的发行者声明 iss: 和 OpenID 配置中的 issuer: 值将是: https://example-oidc-configuration-s3-bucket.s3.eu-north-1.amazonaws.com
  2. 可选。使用 OpenID 配置验证器(如 OpenID Configuration Endpoint Validator) 验证您公开可用的 OpenID 配置。

  3. 为您的 ID token 配置自定义发行者声明。默认情况下,GitLab ID token 的发行者声明 iss: 设置为您的 GitLab 实例地址,例如:http://gitlab.example.com

  4. 更新发行者 URL:

    1. 编辑 /etc/gitlab/gitlab.rb

      gitlab_rails['ci_id_tokens_issuer_url'] = 'public_url_with_openid_configuration_and_keys'
    2. 保存文件并 重新配置 GitLab 以使更改生效。

    1. 导出 Helm 值:

      helm get values gitlab > gitlab_values.yaml
    2. 编辑 gitlab_values.yaml

      global:
        appConfig:
          ciIdTokens:
            issuerUrl: 'public_url_with_openid_configuration_and_keys'
    3. 保存文件并应用新值:

      helm upgrade -f gitlab_values.yaml gitlab gitlab/gitlab
    1. 编辑 docker-compose.yml

      version: "3.6"
      services:
        gitlab:
          environment:
            GITLAB_OMNIBUS_CONFIG: |
              gitlab_rails['ci_id_tokens_issuer_url'] = 'public_url_with_openid_configuration_and_keys'
    2. 保存文件并重启 GitLab:

      docker compose up -d
    1. 编辑 /home/git/gitlab/config/gitlab.yml

       production: &base
         ci_id_tokens:
           issuer_url: 'public_url_with_openid_configuration_and_keys'
    2. 保存文件并 重新配置 GitLab 以使更改生效。

  5. 运行 ci:validate_id_token_configuration Rake 任务 以验证 CI/CD ID token 配置。

故障排除

错误:Not authorized to perform sts:AssumeRoleWithWebIdentity

如果您看到此错误:

An error occurred (AccessDenied) when calling the AssumeRoleWithWebIdentity operation:
Not authorized to perform sts:AssumeRoleWithWebIdentity

可能的原因有多个:

  • 云管理员尚未将项目配置为使用 GitLab 的 OIDC。
  • 角色被限制在分支或标签上运行。请参阅 配置条件角色
  • 使用通配符条件时使用了 StringEquals 而不是 StringLike。请参阅 相关问题

Could not connect to openid configuration of provider 错误

在 AWS IAM 中添加身份提供者后,您可能会收到以下错误:

Your request has a problem. Please see the following details.
  - Could not connect to openid configuration of provider: `https://gitlab.example.com`

当 OIDC 身份提供者的发行者呈现的证书链顺序错误,或包含重复或额外的证书时,会发生此错误。

验证您的 GitLab 实例的证书链。链必须从域名或发行者 URL 开始,然后是中间证书,最后是根证书。使用以下命令检查证书链,将 gitlab.example.com 替换为您的 GitLab 主机名:

echo | /opt/gitlab/embedded/bin/openssl s_client -connect gitlab.example.com:443

Couldn't retrieve verification key from your identity provider 错误

您可能会收到类似以下的错误:

  • An error occurred (InvalidIdentityToken) when calling the AssumeRoleWithWebIdentity operation: Couldn't retrieve verification key from your identity provider, please reference AssumeRoleWithWebIdentity documentation for requirements

此错误可能是因为:

  • 身份提供者 (IdP) 的 .well_known URL 和 jwks_uri 无法从公共互联网访问。
  • 自定义防火墙阻止了请求。
  • 从 IdP 到 AWS STS 端点的 API 请求延迟超过 5 秒。
  • STS 对您的 .well_known URL 或 IdP 的 jwks_uri 发送了太多请求。

此错误的 AWS 知识中心文章 中所述, 您的 GitLab 实例需要可公开访问,以便 .well_known URL 和 jwks_uri 可以被解析。 如果这不可能,例如您的 GitLab 实例处于离线环境, 请参阅如何 配置非公开的 GitLab 实例