GCP Secret Manager을 GitLab CI/CD에서 사용하기

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

당신은 GitLab CI/CD 파이프라인에서 Google Cloud (GCP) Secret Manager에 저장된 비밀을 사용할 수 있습니다.

GitLab과 GCP Secret Manager를 사용하는 흐름은 다음과 같습니다:

  1. GitLab은 CI/CD 작업에게 ID 토큰을 발급합니다.
  2. Runner는 ID 토큰을 사용하여 GCP에 인증합니다.
  3. GCP는 ID 토큰을 GitLab로 확인합니다.
  4. GCP는 단기간의 액세스 토큰을 발급합니다.
  5. Runner는 액세스 토큰을 사용하여 비밀 데이터에 액세스합니다.
  6. GCP는 액세스 토큰의 프린시펄에 대한 IAM 권한을 확인합니다.
  7. GCP는 비밀 데이터를 Runner에게 반환합니다.

GCP Secret Manager를 사용하려면 GitLab에서 다음을 준수해야 합니다:

GCP IAM Workload Identity Federation (WIF) 구성

GCP IAM WIF는 GitLab에서 발급된 ID 토큰을 인식하고 이에 적절한 프린시펄을 할당하도록 구성되어야 합니다. 프린시펄은 Secret Manager 리소스에 대한 액세스 권한을 인가하는 데 사용됩니다:

  1. GCP 콘솔에서 IAM & Admin > Workload Identity Federation로 이동합니다.
  2. 풀 생성을 선택하여 고유한 이름(예: gitlab-pool)으로 새 ID 풀을 만듭니다.
  3. 제공자 추가를 선택하여 고유한 이름(예: gitlab-provider)으로 새 OIDC 제공자를 ID 풀에 추가합니다.
    1. 발행자 (URL)를 GitLab URL(예: https://gitlab.com)로 설정합니다.
    2. 기본 수강청취자를 선택하거나 사용자 정의 수강청취자에 대해 허용된 수강청취자를 선택합니다. 이는 GitLab CI/CD ID 토큰의 aud에 사용됩니다.
  4. 속성 매핑에서 다음과 같은 매핑을 생성합니다.

    • attribute.X: Google 클레임에 존재해야 하는 속성의 이름입니다.
    • assertion.X: GitLab 클레임에서 추출할 값을 나타냅니다.
    Google에서의 속성 GitLab에서의 assertion
    google.subject assertion.sub
    attribute.gitlab_project_id assertion.project_id

GCP IAM 프린시펄에 액세스 권한 부여

WIF를 설정한 후에는 WIF 제공자를 통해 생성된 프린시펄에 Secret Manager의 비밀에 액세스 권한을 부여해야 합니다.

  1. GCP 콘솔에서 IAM & Admin > IAM으로 이동합니다.
  2. 액세스를 부여할 프린시펄 설정을 위해 액세스 부여를 선택합니다. 외부 식별 형식은 다음과 같습니다:

    principalSet://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/POOL_ID/attribute.gitlab_project_id/GITLAB_PROJECT_ID
    

    여기서:

    • PROJECT_NUMBER: 프로젝트 대시보드에서 찾을 수 있는 Google Cloud 프로젝트 번호(아이디가 아님)입니다.
    • POOL_ID: 첫 번째 섹션에서 생성한 Workload Identity Pool의 ID(이름이 아님)로, 예를 들어 gitlab-pool입니다.
    • GITLAB_PROJECT_ID: 프로젝트 개요 페이지에서 찾을 수 있는 GitLab 프로젝트 ID입니다.
  3. Secret Manager Secret Accessor 역할을 할당합니다.
  4. (선택 사항) IAM 조건(선택 사항)을 추가하려면 IAM 조건 (Optional)를 선택합니다. 조건 빌더 아래에서 조건을 추가할 수 있습니다. 예를 들어, 두 개의 AND 조건을 추가할 수 있습니다:
    • 첫 번째 조건:
      • 조건 유형: 유형
      • 연산자: 일치함
      • 리소스 유형: secretmanager.googleapis.com/SecretVersion
    • 두 번째 조건:
      • 조건 유형: 이름
      • 연산자: 다음으로 시작함
      • : 액세스를 부여하려는 비밀의 패턴

비밀 이름으로 시작하는 비밀에 대한 액세스 제어를 포함한 세밀한 액세스 제어를 위해 추가 IAM 조건을 추가할 수 있습니다.

GCP Secret Manager 비밀을 사용하도록 GitLab CI/CD 구성

GCP Secret Manager에 대한 세부 정보를 제공하기 위해 다음 CI/CD 변수들을 추가해야 합니다:

  • GCP_PROJECT_NUMBER: 프로젝트 번호입니다.
  • GCP_WORKLOAD_IDENTITY_FEDERATION_POOL_ID: WIF 풀 ID로, 예를 들어 gitlab-pool입니다.
  • GCP_WORKLOAD_IDENTITY_FEDERATION_PROVIDER_ID: WIF 제공자 ID로, 예를 들어 gitlab-provider입니다.

그런 다음 gcp_secret_manager 키워드를 사용하여 CI/CD 작업에서 GCP Secret Manager에 저장된 비밀을 정의하여 사용할 수 있습니다:

job_using_gcp_sm:
  id_tokens:
    GCP_ID_TOKEN:
      # `aud`는 WIF ID 풀에서 정의된 수강청취자와 일치해야 합니다.
      aud: https://iam.googleapis.com/projects/${GCP_PROJECT_NUMBER}/locations/global/workloadIdentityPools/${GCP_WORKLOAD_IDENTITY_FEDERATION_POOL_ID}/providers/${GCP_WORKLOAD_IDENTITY_FEDERATION_PROVIDER_ID}
  secrets:
    DATABASE_PASSWORD:
      gcp_secret_manager:
        name: my-project-secret  # GCP Secret Manager에 정의된 비밀 이름입니다
        version: 1               # 선택 사항: 기본값은 `latest`입니다.
      token: $GCP_ID_TOKEN

다른 GCP 프로젝트에서 비밀 사용하기

GCP에서 비밀 이름은 프로젝트마다 다릅니다. gcp_secret_manager:name에 지정된 프로젝트와는 다른 프로젝트에서 비밀을 읽으려면 projects/<project-number>/secrets/<secret-name> 형식으로 완전히 지정된 비밀 이름을 사용해야 합니다.

예를 들어, my-project-secret이 GCP 프로젝트 번호인 123456789에 있는 경우 다음과 같이 비밀에 액세스할 수 있습니다:

job_using_gcp_sm:
  # ... 앞에서 설정한대로 구성 ...
  secrets:
    DATABASE_PASSWORD:
      gcp_secret_manager:
        name: projects/123456789/secrets/my-project-secret  # GCP Secret Manager에 정의된 비밀의 완전한 이름
        version: 1                                          # 선택 사항: 기본값은 `latest`입니다.
      token: $GCP_ID_TOKEN

문제 해결

The size of mapped attribute google.subject exceeds the 127 bytes limit 오류

긴 Merge Request 브랜치 이름은 the assertion.sub attribute이 127자를 초과하면 작업이 다음과 같은 오류로 실패할 수 있습니다:

ERROR: Job failed (system failure): resolving secrets: failed to exchange sts token: googleapi: got HTTP response code 400 with body:
{"error":"invalid_request","error_description":"The size of mapped attribute google.subject exceeds the 127 bytes limit.
Either modify your attribute mapping or the incoming assertion to produce a mapped attribute that is less than 127 bytes."}

예를 들어, gitlab-org/gitlab 브랜치의 경우 페이로드는 project_path:gitlab-org/gitlab:ref_type:branch:ref:{branch_name}이므로 브랜치 이름은 76자 이하여야 합니다.

WARNING: Not resolved: no resolver that can handle the secret 경고

Google Cloud Secret Manager 통합은 GitLab 16.8 및 GitLab Runner 16.8 이상이 필요합니다. 이 경고는 작업이 16.8 이전 버전을 사용하는 러너에 의해 실행될 때 나타납니다.

GitLab.com에서는 알려진 문제로 인해 SaaS 러너가 이전 버전을 실행하는 문제가 발생합니다. 이 문제가 해결될 때까지의 임시 방편으로 버전 16.8 이상의 자체 GitLab 러너를 등록할 수 있습니다.