GCP Workload Identity Federation과 OpenID Connect 구성

Tier: Free, Premium, Ultimate Offering: GitLab.com, Self-Managed, GitLab Dedicated
caution
CI_JOB_JWT_V2GitLab 15.9에서 폐기되었으며 GitLab 17.0에서 제거될 예정입니다. ID 토큰을 대신 사용하십시오.

이 튜토리얼에서는 JSON Web Token (JWT) 토큰과 Workload Identity Federation을 사용하여 GitLab CI/CD 작업에서 Google Cloud에 인증하는 방법을 보여줍니다. 이 구성은 필요한 시점에 비밀을 저장하지 않고 즉석에서 짧은 수명의 자격 증명을 생성합니다.

시작하려면 GitLab과 Google Cloud 간의 식별페더레이션을 위해 OpenID Connect (OIDC)를 구성하십시오. GitLab에서 OIDC를 사용하는 자세한 내용은 클라우드 서비스에 연결을 참조하십시오.

이 튜토리얼은 Google Cloud 계정 및 Google Cloud 프로젝트가 있다고 가정합니다. 계정은 Google Cloud 프로젝트에서 적어도 Workload Identity Pool Admin 권한을 가져야 합니다.

note
이 튜토리얼 대신 Terraform 모듈과 CI/CD 템플릿을 사용하고 싶다면 OIDC를 통해 Google Cloud와 GitLab CI/CD 파이프라인의 인증을 간소화하는 방법을 참조하십시오.

이 튜토리얼 완료하려면:

  1. Google Cloud Workload Identity Pool 생성.
  2. Workload Identity Provider 생성.
  3. 서비스 계정 허가 권한 부여.
  4. 임시 자격 증명 검색.

Google Cloud Workload Identity Pool 생성

다음 옵션을 사용하여 새로운 Google Cloud Workload Identity Pool을 생성하십시오:

  • 이름: GitLab과 같은 Workload Identity Pool의 친숙한 이름.
  • Pool ID: gitlab과 같은 Google Cloud 프로젝트에 대한 Workload Identity Pool의 고유 ID. 이 값은 풀을 참조하는 데 사용되며 URL에 표시됩니다.
  • 설명: 선택 사항입니다. 풀에 대한 설명.
  • 풀 사용 설정: 이 옵션이 true로 설정되어 있는지 확인하십시오.

한 Google Cloud 프로젝트 당 GitLab 설치당 단일 _풀_을 생성하는 것이 좋습니다. 동일한 GitLab 인스턴스의 여러 GitLab 리포지터리 및 CI/CD 작업이 동일한 _풀_에 대해 다른 _공급자_를 사용하여 인증할 수 있습니다.

Workload Identity Provider 생성

이전 단계에서 생성된 Workload Identity Pool 내에 새로운 Google Cloud Workload Identity Provider을 다음 옵션을 사용하여 생성하십시오:

  • 공급자 유형: OpenID Connect (OIDC).
  • 공급자 이름: gitlab/gitlab과 같은 Workload Identity Provider의 친숙한 이름.
  • 공급자 ID: 풀 내에서의 Workload Identity Provider에 대한 고유 ID, gitlab-gitlab과 같습니다. 이 값은 공급자를 참조하는데 사용되며 URL에 표시됩니다.
  • 발급자 (URL): GitLab 인스턴스의 주소, https://gitlab.com/ 또는 https://gitlab.example.com/과 같은 것.
    • 주소는 https:// 프로토콜을 사용해야 합니다.
    • 주소는 슬래시로 끝나야 합니다.
  • 청중(Audiences): 허용된 청중 디렉터리을 매뉴얼으로 GitLab 인스턴스의 주소, https://gitlab.com 또는 https://gitlab.example.com과 같은 것으로 설정하십시오.
    • 주소는 https:// 프로토콜을 사용해야 합니다.
    • 주소는 슬래시로 끝나서는 안 됩니다.
  • Provider attributes mapping: 다음 매핑을 생성하십시오. attribute.X는 Google의 클레임에 존재해야 하는 속성의 이름이며 assertion.XGitLab 클레임에서 추출할 값입니다:

    Google의 속성(속성) GitLab의 assertion에서 가져온 값
    google.subject assertion.sub
    attribute.X assertion.X

    공통 표현 언어(CEL)를 사용하여 복잡한 속성을 만들 수도 있습니다.

    권한 부여에 사용하려면 모든 원하는 속성에 대한 매핑을 해야 합니다. 예를 들어, 다음 단계에서 사용자의 이메일 주소를 기반으로 권한을 매핑하려면 attribute.user_emailassertion.user_email에 매핑해야 합니다.

서비스 계정 위임을 위한 권한 부여

Workload Identity Pool과 Workload Identity Provider를 생성하면 Google Cloud로의 인증_을 정의합니다. 이 시점에서는 GitLab CI/CD 작업에서 Google Cloud로 인증할 수 있습니다. 그러나 Google Cloud에서 권한(_권한 부여)을 가지고 있지는 않습니다.

Google Cloud의 권한을 GitLab CI/CD 작업에 부여하려면:

  1. Google Cloud 서비스 계정 생성을 수행하십시오. 원하는 이름 및 ID를 사용할 수 있습니다.
  2. Google Cloud 리소스에 대한 IAM 권한 부여를 수행하십시오. 이러한 권한은 사용 사례에 따라 크게 달라집니다. 일반적으로 이 서비스 계정에는 GitLab CI/CD 작업에서 사용하려는 Google Cloud 프로젝트 및 리소스에 대한 권한을 부여해야 합니다. 예를 들어, GitLab CI/CD 작업에서 Google Cloud Storage 버킷에 파일을 업로드해야 하는 경우에는 이 서비스 계정에 roles/storage.objectCreator 역할을 부여해야 할 것입니다.
  3. 외부 신원에게 권한 부여를 수행하여 해당 서비스 계정을 위임할 수 있도록 합니다. 이 단계은 GitLab CI/CD 작업이 서비스 계정 위임을 허용하도록 만듭니다. 이 단계은 그 서비스 계정 자체에 대한 IAM 권한을 부여하여 외부 신원이 해당 서비스 계정으로 활동하도록 권한을 부여합니다. 외부 신원은 principalSet:// 프로토콜을 사용하여 표현됩니다.

이전 단계와 마찬가지로 이 단계도 원하는 구성에 많이 의존합니다. 예를 들어, GitLab CI/CD 작업이 chris라는 GitLab 사용자가 시작했을 때 my-service-account라는 서비스 계정을 위임할 수 있도록 하려면 외부 신원에게 my-service-accountroles/iam.workloadIdentityUser IAM 역할을 부여해야 합니다. 외부 신원의 형식은 다음과 같습니다:

principalSet://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/POOL_ID/attribute.user_login/chris

여기서 PROJECT_NUMBER는 Google Cloud 프로젝트 번호이고 POOL_ID는 첫 번째 섹션에서 생성한 Workload Identity Pool의 ID입니다.

이 구성은 또한 이전 섹션에서 assertion에서 매핑한 user_login을 추가했다고 가정합니다.

임시 자격 서칭

OIDC 및 역할을 구성한 후 GitLab CI/CD 작업은 Google Cloud 보안 토큰 서비스(STS)에서 임시 자격을 검색할 수 있습니다.

CI/CD 작업에 id_tokens를 추가하십시오.

job:
  id_tokens:
    GITLAB_OIDC_TOKEN:
      aud: https://gitlab.example.com

ID 토큰을 사용하여 임시 자격을 얻으십시오.

PAYLOAD="$(cat <<EOF
{
  "audience": "//iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/POOL_ID/providers/PROVIDER_ID",
  "grantType": "urn:ietf:params:oauth:grant-type:token-exchange",
  "requestedTokenType": "urn:ietf:params:oauth:token-type:access_token",
  "scope": "https://www.googleapis.com/auth/cloud-platform",
  "subjectTokenType": "urn:ietf:params:oauth:token-type:jwt",
  "subjectToken": "${GITLAB_OIDC_TOKEN}"
}
EOF
)"
FEDERATED_TOKEN="$(curl --fail "https://sts.googleapis.com/v1/token" \
  --header "Accept: application/json" \
  --header "Content-Type: application/json" \
  --data "${PAYLOAD}" \
  | jq -r '.access_token'
)"

여기서:

  • PROJECT_NUMBER는 Google Cloud 프로젝트 번호입니다(이름이 아닙니다).
  • POOL_ID는 첫 번째 섹션에서 생성한 Workload Identity Pool의 ID입니다.
  • PROVIDER_ID는 두 번째 섹션에서 생성한 Workload Identity Provider의 ID입니다.
  • GITLAB_OIDC_TOKEN은 OIDC ID 토큰입니다.

그런 다음 결과로 얻은 연합 토큰을 사용하여 이전 섹션에서 생성한 서비스 계정을 위임할 수 있습니다:

ACCESS_TOKEN="$(curl --fail "https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/SERVICE_ACCOUNT_EMAIL:generateAccessToken" \
  --header "Accept: application/json" \
  --header "Content-Type: application/json" \
  --header "Authorization: Bearer FEDERATED_TOKEN" \
  --data '{"scope": ["https://www.googleapis.com/auth/cloud-platform"]}' \
  | jq -r '.accessToken'
)"

여기서:

  • SERVICE_ACCOUNT_EMAIL은 이전 섹션에서 생성한 서비스 계정의 전체 이메일 주소입니다.
  • FEDERATED_TOKEN은 이전 단계에서 검색한 연합 토큰입니다.

결과는 Google Cloud OAuth 2.0 액세스 토큰이며, 이를 사용하여 대부분의 Google Cloud API 및 서비스에 인증할 수 있습니다(포즈 토큰으로 사용될 경우). 또한 이 값을 환경 변수 CLOUDSDK_AUTH_ACCESS_TOKEN으로 설정하여 gcloud CLI에 전달할 수도 있습니다.

작업 예시

GCP에서 Terraform을 사용하여 OIDC를 프로비저닝하고 일시적 자격 증명을 검색하는 샘플 스크립트를 사용하는 참조 프로젝트를 확인하세요.

문제 해결

  • curl 응답을 디버깅할 때 가장 최신 버전의 curl을 설치하세요. -f 대신 --fail-with-body를 사용하세요. 이 명령은 전체 본문을 인쇄하여 유용한 오류 메시지가 포함될 수 있습니다.

  • 작업 부하 식별을 위한 구글 클라우드 문서를 확인하세요.