OpenID Connect (OIDC) Authentication Using ID Tokens

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

GitLab CI/CD의 ID 토큰을 사용하여 제3자 서비스로 인증할 수 있습니다.

ID 토큰

ID 토큰은 GitLab CI/CD 작업에 추가할 수 있는 JSON 웹 토큰(JWT)입니다. 이들은 제3자 서비스와의 OIDC 인증에 사용되며, secrets 키워드를 사용하여 HashiCorp Vault로의 인증에 사용됩니다.

ID 토큰은 .gitlab-ci.yml에서 구성됩니다. 예를 들어:

job_with_id_tokens:
  id_tokens:
    FIRST_ID_TOKEN:
      aud: https://first.service.com
    SECOND_ID_TOKEN:
      aud: https://second.service.com
  script:
    - first-service-authentication-script.sh $FIRST_ID_TOKEN
    - second-service-authentication-script.sh $SECOND_ID_TOKEN

이 예에서 두 토큰은 다른 aud 클레임을 갖고 있습니다. 제3자 서비스는 자신의 바인딩된 대상 청중과 일치하지 않는 토큰을 거부하도록 구성할 수 있습니다. 이 기능을 사용하여 토큰이 인증할 수 있는 서비스의 수를 줄일 수 있습니다. 이를 통해 토큰이 Compromised되는 심각도를 줄일 수 있습니다.

토큰 페이로드

각 ID 토큰에는 다음 표준 클레임이 포함됩니다:

필드 설명
iss 토큰의 발급자, 기본적으로 GitLab 인스턴스의 도메인입니다 (“issuer” 클레임).
sub project_path:{group}/{project}:ref_type:{type}:ref:{branch_name} (“subject” 클레임).
aud 토큰의 의도된 청중, 기본적으로 GitLab 인스턴스의 도메인입니다. ID 토큰의 구성에서 지정됩니다.
exp 만료 시간 (“expiration time” 클레임).
nbf 토큰이 유효해지는 시간 (“not before” 클레임).
iat JWT가 발급된 시간 (“issued at” 클레임).
jti 토큰의 고유 식별자 (“JWT ID” 클레임).

토큰에는 GitLab에서 제공하는 사용자 정의 클레임도 포함됩니다: … (중략)

매뉴얼 ID 토큰 인증

서드 파티 서비스와 OIDC 인증에 ID 토큰을 사용할 수 있습니다. 예를 들어:

manual_authentication:
  variables:
    VAULT_ADDR: http://vault.example.com:8200
  image: vault:latest
  id_tokens:
    VAULT_ID_TOKEN:
      aud: http://vault.example.com:8200
  script:
    - export VAULT_TOKEN="$(vault write -field=token auth/jwt/login role=myproject-example jwt=$VAULT_ID_TOKEN)"
    - export PASSWORD="$(vault kv get -field=password secret/myproject/example/db)"
    - my-authentication-script.sh $VAULT_TOKEN $PASSWORD

HashiCorp Vault를 이용한 자동 ID 토큰 인증

Tier: Premium, Ultimate
Offering: GitLab.com, Self-managed, GitLab Dedicated

secrets 키워드를 사용하여 HashiCorp Vault에서 시크릿을 자동으로 가져오려면 ID 토큰을 사용할 수 있습니다.

만약 이전에 CI_JOB_JWT를 사용하여 Vault에서 시크릿을 가져오셨다면 HashiCorp Vault 구성을 ID 토큰 사용으로 변경 튜토리얼을 통해 변경하는 방법을 알아보세요.

자동 ID 토큰 인증 구성

한 개의 ID 토큰이 정의된 경우, secrets 키워드는 자동으로 해당 토큰을 사용하여 Vault와 인증합니다. 예를 들어:

job_with_secrets:
  id_tokens:
    VAULT_ID_TOKEN:
      aud: https://example.vault.com
  secrets:
    PROD_DB_PASSWORD:
      vault: example/db/password # $VAULT_ID_TOKEN을 사용하여 인증
  script:
    - access-prod-db.sh --token $PROD_DB_PASSWORD

여러 개의 ID 토큰이 정의된 경우, token 키워드를 사용하여 어떤 토큰을 사용해야 하는지 지정합니다. 예를 들어:

job_with_secrets:
  id_tokens:
    FIRST_ID_TOKEN:
      aud: https://first.service.com
    SECOND_ID_TOKEN:
      aud: https://second.service.com
  secrets:
    FIRST_DB_PASSWORD:
      vault: first/db/password
      token: $FIRST_ID_TOKEN
    SECOND_DB_PASSWORD:
      vault: second/db/password
      token: $SECOND_ID_TOKEN
  script:
    - access-first-db.sh --token $FIRST_DB_PASSWORD
    - access-second-db.sh --token $SECOND_DB_PASSWORD

문제 해결

400: missing token 상태 코드

이 오류는 ID 토큰에 필요한 하나 이상의 기본 컴포넌트가 누락되었거나 예상대로 구성되지 않았음을 나타냅니다.

문제를 찾으려면 관리자는 인스턴스의 exceptions_json.log에서 실패한 특정 메서드에 대한 자세한 내용을 찾을 수 있습니다.

GitLab::Ci::Jwt::NoSigningKeyError

exceptions_json.log 파일의 이 오류는 데이터베이스에서 서명 키가 누락되어 토큰을 생성할 수 없기 때문입니다. 이 문제를 확인하려면 인스턴스의 PostgreSQL 터미널에서 다음 쿼리를 실행하세요:

SELECT encrypted_ci_jwt_signing_key FROM application_settings;

반환된 값이 비어 있다면, Rails 스니펫을 사용하여 새로운 키를 생성하고 내부적으로 교체하세요:

  key = OpenSSL::PKey::RSA.new(2048).to_pem
  
  ApplicationSetting.find_each do |application_setting|
    application_setting.update(ci_jwt_signing_key: key)
  end