GCP Workload Identity Federation의 OpenID Connect 구성


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

경고:
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 간의 ID 페더레이션을 위해 OpenID Connect (OIDC)를 구성합니다.
GitLab에서 OIDC를 사용하는 자세한 정보는 클라우드 서비스에 연결을 참조하십시오.

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

참고:
이 튜토리얼을 따르려면 이 튜토리얼 대신 테라폼 모듈과 CI/CD 템플릿을 사용하고 싶다면 Google Cloud와 GitLab CI/CD 파이프라인의 인증을 간소화할 수 있는 OIDC 모듈 소개을 참조하십시오.

이 튜토리얼을 완료하려면:

  1. Google Cloud Workload Identity Pool 생성.
  2. 워크로드 신원 공급자 생성.
  3. 서비스 계정 표현에 대한 권한 부여.
  4. 임시 자격 증명 검색.

Google Cloud Workload Identity Pool 생성

다음 옵션으로 새 Google Cloud Workload Identity Pool 생성:

  • 이름: Workload Identity Pool의 사람 친화적인 이름(예: GitLab).
  • 풀 ID: Workload Identity Pool의 Google Cloud 프로젝트 내 고유 ID(예: gitlab). 이 값은 풀을 참조하거나 URL에 표시됩니다.
  • 설명: 선택 사항. 풀에 대한 설명.
  • 풀 활성화: 이 옵션이 true로 설정되어 있는지 확인합니다.

한 Google Cloud 프로젝트 당 GitLab 설치 당 단일 생성을 권장합니다.
동일한 GitLab 인스턴스의 여러 GitLab 저장소 및 CI/CD 작업이 동일한 을 대상으로 다른 공급자를 사용하여 인증할 수 있습니다.

워크로드 신원 공급자 생성

이전 단계에서 생성한 Workload Identity Pool 내에 새 Google Cloud Workload Identity Provider 생성하고 다음 옵션을 사용합니다:

  • 공급자 유형: OpenID Connect (OIDC).
  • 공급자 이름: Workload Identity Provider의 사람 친화적인 이름(예: gitlab/gitlab).
  • 공급자 ID: 공급자의 풀에서 사용하는 고유 ID(예: gitlab-gitlab). 이 값은 공급자를 참조하거나 URL에 표시됩니다.
  • 발행자 (URL): GitLab 인스턴스의 주소(예: https://gitlab.com/ 또는 https://gitlab.example.com/).
    • 주소는 https:// 프로토콜을 사용해야 합니다.
    • 주소는 trailing slash로 끝나야 합니다.
  • 수강청취자(Audiences): 허용된 수강청취자 목록을 수동으로 GitLab 인스턴스의 주소(예: https://gitlab.com 또는 https://gitlab.example.com)로 설정합니다.
    • 주소는 https:// 프로토콜을 사용해야 합니다.
    • 주소는 trailing slash로 끝나서는 안 됩니다.
  • 공급자 속성 매핑: 다음 매핑을 만듭니다. 여기서 attribute.X는 Google의 클레임에 존재해야 하는 속성의 이름이고 assertion.XGitLab 클레임에서 추출할 값입니다:

    Google의 속성 GitLab의 Assertion
    google.subject assertion.sub
    attribute.X assertion.X

    또한 Common Expression Language (CEL)을 사용하여 복잡한 속성을 작성할 수 있습니다.

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

서비스 계정 표현에 대한 권한 부여

Workload Identity Pool 및 Workload Identity Provider 생성은 Google Cloud에서의 인증을 정의합니다.
이 시점에서 GitLab CI/CD 작업에서 Google Cloud로 인증할 수 있습니다.
그러나 Google Cloud의 권한(authorization)을 갖지는 못합니다.

GitLab CI/CD 작업에 Google Cloud에서의 권한을 부여하려면 다음을 수행해야 합니다:

  1. Google Cloud 서비스 계정 생성. 원하는 이름과 ID를 사용할 수 있습니다.
  2. Google Cloud 리소스에 대한 IAM 권한 부여. 이러한 권한은 사용 사례에 따라 크게 다를 수 있습니다. 일반적으로 이 서비스 계정에는 GitLab CI/CD 작업에서 사용하려는 Google Cloud 프로젝트 및 리소스에 대한 권한을 부여합니다. 예를 들어 GitLab CI/CD 작업에서 Google Cloud Storage 버킷에 파일을 업로드해야 하는 경우 Cloud Storage 버킷에 roles/storage.objectCreator 권한을 부여합니다.
  3. 외부 신원에 권한 부여하여 해당 서비스 계정을 의도한 작업을 대신할 수 있도록 합니다. 이 단계에서는 GitLab CI/CD 작업이 서비스 계정의 신원을 나타내도록 허용하는 IAM 권한을 서비스 계정 자체에 부여합니다.

이 단계 또한 원하는 구성에 크게 의존합니다.
예를 들어, GitLab CI/CD 작업이 chris라는 사용자가 시작한 경우 my-service-account라는 서비스 계정을 표현하는 데 사용자 chris에게 roles/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입니다.

이 구성은 이전 섹션에서 클레임에서 매핑된 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 및 서비스에 대해 bearer 토큰으로 인증할 수 있습니다. 또한 이 값을 환경 변수 CLOUDSDK_AUTH_ACCESS_TOKEN으로 설정하여 gcloud CLI에 전달할 수 있습니다.

작동 예시

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

문제 해결

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

  • Workload Identity Federation의 문제 해결에 대한 Google Cloud 문서를 확인하세요.