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

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

Google Cloud(GCP) Secret Manager에 저장된 시크릿을 GitLab CI/CD 파이프라인에서 사용하는 방법을 설명하는 문서예요. Workload Identity Federation(WIF)을 이용한 인증 흐름과 IAM 권한 구성, CI/CD 변수 설정을 코드 예시와 함께 옆에서 설명해 주는 방식으로 정리했어요.

다른 GCP 프로젝트의 시크릿을 읽는 방법과 자주 겪는 문제 해결 방법도 함께 다루고 있어요.

출처: 문서

본문

Google Cloud(GCP) Secret Manager에 저장된 시크릿을 GitLab CI/CD 파이프라인에서 사용할 수 있어요.

GitLab을 GCP Secret Manager와 함께 사용하는 흐름은 다음과 같아요.

  1. GitLab이 CI/CD 작업에 ID 토큰을 발급해요.
  2. 러너가 ID 토큰으로 GCP에 인증해요.
  3. GCP가 ID 토큰을 GitLab으로 검증해요.
  4. GCP가 수명이 짧은 액세스 토큰을 발급해요.
  5. 러너가 액세스 토큰으로 시크릿 데이터에 접근해요.
  6. GCP가 액세스 토큰의 주체(principal)에 대한 IAM 시크릿 권한을 확인해요.
  7. GCP가 시크릿 데이터를 러너에 반환해요.

GitLab을 GCP Secret Manager와 함께 사용하려면 다음을 해야 해요.

GCP IAM Workload Identity Federation(WIF) 구성

GCP IAM WIF는 GitLab이 발급한 ID 토큰을 인식하고 적절한 주체를 할당하도록 구성되어야 해요. 주체는 Secret Manager 리소스에 대한 접근을 승인하는 데 사용돼요.

  1. GCP 콘솔에서 IAM & Admin > Workload Identity Federation으로 이동하세요.
  2. CREATE POOL을 선택하고 고유한 이름(예: gitlab-pool)으로 새 ID 풀을 만드세요.
  3. ADD PROVIDER를 선택해 ID 풀에 고유한 이름(예: gitlab-provider)의 새 OIDC 제공자를 추가하세요.
    1. **Issuer (URL)**을 GitLab URL(예: https://gitlab.com)로 설정하세요.
    2. Default audience를 선택하거나, GitLab CI/CD ID 토큰의 aud에 사용할 사용자 지정 오디언스를 위해 Allowed audiences를 선택하세요.
    3. Attribute Mapping 아래에서 다음 매핑을 만드세요. 여기서:
      • attribute.X는 Google 토큰에 클레임으로 포함할 속성 이름.
      • assertion.XGitLab 클레임에서 추출할 값. | 속성 (Google 쪽) | 어서션 (GitLab 쪽) | |---|---| | google.subject | assertion.sub | | attribute.gitlab_project_id | assertion.project_id |

GCP IAM 주체에 접근 권한 부여

WIF를 설정한 후에는 WIF 주체가 Secret Manager의 시크릿에 접근할 수 있도록 권한을 부여해야 해요.

  1. GCP 콘솔에서 Security > Secret Manager로 이동하세요.
  2. 접근 권한을 부여할 시크릿의 이름을 선택해 시크릿 세부 정보를 보세요.
  3. PERMISSIONS 탭에서 GRANT ACCESS를 선택해 WIF 제공자를 통해 생성된 주체 집합(principal set)에 접근 권한을 부여하세요. 외부 ID 형식은 다음과 같아요.
    principalSet://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/POOL_ID/attribute.gitlab_project_id/GITLAB_PROJECT_ID
    
    이 예시에서:
    • PROJECT_NUMBER: 프로젝트의 대시보드에서 찾을 수 있는 Google Cloud 프로젝트 번호(ID가 아님).
    • POOL_ID: 첫 번째 섹션에서 만든 워크로드 ID 풀의 ID(이름이 아님). 예: gitlab-pool.
    • GITLAB_PROJECT_ID: 프로젝트 개요 페이지에서 찾을 수 있는 GitLab 프로젝트 ID.
  4. Secret Manager Secret Accessor 역할을 할당하세요.

GCP Secret Manager 시크릿을 사용하도록 GitLab CI/CD 구성

GCP Secret Manager에 대한 정보를 제공하려면 이 CI/CD 변수들을 추가해야 해요.

  • GCP_PROJECT_NUMBER: GCP Project Number.
  • GCP_WORKLOAD_IDENTITY_FEDERATION_POOL_ID: WIF Pool ID. 예: gitlab-pool.
  • GCP_WORKLOAD_IDENTITY_FEDERATION_PROVIDER_ID: WIF Provider ID. 예: gitlab-provider.

그런 다음 gcp_secret_manager 키워드로 정의해 GCP Secret Manager에 저장된 시크릿을 CI/CD 작업에서 사용할 수 있어요.

job_using_gcp_sm:
  id_tokens:
    GCP_ID_TOKEN:
      # `aud` must match the audience defined in the WIF Identity Pool.
      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  # This is the name of the secret defined in GCP Secret Manager
        version: 1               # optional: default to `latest`.
      token: $GCP_ID_TOKEN

다른 GCP 프로젝트의 시크릿 사용하기

이력

GCP의 시크릿 이름은 프로젝트별로 고유해요. 기본적으로 gcp_secret_manager:name에 지정된 시크릿은 GCP_PROJECT_NUMBER에 지정된 프로젝트에서 읽혀요.

WIF 풀이 있는 프로젝트가 아닌 다른 프로젝트에서 시크릿을 읽으려면 projects/<project-number>/secrets/<secret-name> 형식의 완전한 시크릿 이름을 사용하세요.

예를 들어 my-project-secret이 GCP 프로젝트 번호 123456789에 있다면 다음으로 시크릿에 접근할 수 있어요.

job_using_gcp_sm:
  # ... as previously configured ...
  secrets:
    DATABASE_PASSWORD:
      gcp_secret_manager:
        name: projects/123456789/secrets/my-project-secret  # fully-qualified name of the secret defined in GCP Secret Manager
        version: 1                                          # optional: defaults to `latest`.
      token: $GCP_ID_TOKEN

문제 해결

오류: 매핑된 속성 google.subject의 크기가 127바이트 제한을 초과함

긴 브랜치 경로로 인해 작업이 이 오류로 실패할 수 있어요. assertion.sub 속성이 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}이에요. 문자열이 127자보다 짧게 유지되려면 브랜치 이름이 76자 이하여야 해요. 이 제한은 Google Cloud IAM이 부과하며, Google 이슈 #264362370에서 추적되고 있어요.

이 문제의 유일한 해결책은 브랜치와 저장소 이름을 더 짧게 사용하는 거예요.

The secrets provider can not be found. Check your CI/CD variables and try again. 메시지

GCP Secret Manager에 접근하도록 구성된 작업을 시작하려 할 때 이 오류를 받을 수 있어요.

The secrets provider can not be found. Check your CI/CD variables and try again.

필요한 변수 중 하나 이상이 정의되지 않아 작업을 만들 수 없어요.

  • GCP_PROJECT_NUMBER
  • GCP_WORKLOAD_IDENTITY_FEDERATION_POOL_ID
  • GCP_WORKLOAD_IDENTITY_FEDERATION_PROVIDER_ID

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

이 경고는 러너 버전이 Google Cloud Secret Manager 통합을 지원하지 않을 때 나타나요. 러너를 지원되는 버전으로 업그레이드하세요.

더 알아보기

GCP Secret Manager 통합 설정의 자세한 사항은 GCP용 OIDC 문서와 함께, 시크릿 인증의 기반이 되는 ID 토큰 인증 문서를 함께 읽어보시면 좋아요.