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 토큰을 사용하세요.

이 자습서는 GitLab CI/CD 작업에서 JSON 웹 토큰(JWT) 및 Workload Identity Federation을 사용하여 Google Cloud에 인증하는 방법을 보여줍니다. 이 구성은 보안 정보를 저장하지 않고도 온디맨드로 짧은 수명의 자격증명을 생성합니다.

시작하려면 GitLab과 Google Cloud 사이에서 ID 연동을 위해 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의 사용하기 쉬운 이름
  • 풀 ID: gitlab과 같은 Google Cloud 프로젝트의 Workload Identity Pool을 위한 고유 ID. 이 값은 풀을 참조하는 데 사용되며 URL에 표시됩니다.
  • 설명: 선택 사항. 풀에 대한 설명
  • 활성화된 풀: 이 옵션이 true로 설정되어 있는지 확인하세요.

하나의 GitLab 설치 당 Google Cloud 프로젝트당 단일 _풀_을 생성하는 것을 권장합니다. 같은 GitLab 인스턴스에서 여러 개의 GitLab 저장소 및 CI/CD 작업이 있는 경우 서로 다른 _공급자_를 사용하여 같은 _풀_에 대해 인증할 수 있습니다.

Workload Identity Provider 생성

이전 단계에서 생성된 Workload Identity Pool 내에서 새로운 Google Cloud Workload Identity Provider 생성 using the following options:

  • 공급자 유형: 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:// 프로토콜을 사용해야 합니다.
    • 주소는 끝에 슬래시를 반드시 포함해야 합니다.
  • 청중: 귀하의 GitLab 인스턴스 주소에 대한 허용된 청중 목록을 수동으로 설정하세요, 예: https://gitlab.com 또는 https://gitlab.example.com.
    • 주소는 https:// 프로토콜을 사용해야 합니다.
    • 주소는 끝에 슬래시를 포함해서는 안 됩니다.
  • 공급자 속성 매핑: 다음 매핑을 생성하세요. 여기서 attribute.X는 Google의 클레임에 나타나길 원하는 속성의 이름이고, assertion.XGitLab 클레임에서 추출할 값을 나타냅니다:

    Google의 속성 GitLab에서 추출한 값
    google.subject assertion.sub
    attribute.X assertion.X

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

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

Service Account 타당성 부여 권한

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 버킷에 파일을 업로드해야 하는 경우, 해당 서비스 계정에게 Cloud Storage 버킷에 대한 roles/storage.objectCreator 역할을 부여해야 합니다.
  3. 해당 서비스 계정을 가장하도록 외부 ID에게 권한을 부여하세요. 이 단계는 GitLab CI/CD 작업이 서비스 계정을 가장하여 Google Cloud에 _인가_할 수 있도록 하는 단계입니다. 이 단계는 외부 ID가 해당 서비스 계정으로 작동할 수 있도록 해당 서비스 계정 자체에 대한 IAM 권한을 부여합니다. 외부 ID는 principalSet:// 프로토콜을 사용하여 표현됩니다.

이전 단계와 마찬가지로, 이 단계는 원하는 구성에 크게 의존합니다. 예를 들어, GitLab CI/CD 작업이 시작된 시점에서 GitLab 사용자 이름이 chris인 경우, my-service-account라는 서비스 계정을 가장할 수 있도록 chris 사용자에게 roles/iam.workloadIdentityUser IAM 역할을 부여해야 합니다. 외부 ID는 다음 형식을 취합니다.

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 Security Token Service (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에 전달할 수도 있습니다.

작동하는 예시

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

문제 해결

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

  • 구글 클라우드의 문서를 검토하세요. 워크로드 ID 연합의 문제 해결.