튜토리얼: HashiCorp Vault 구성 업데이트하여 ID 토큰 사용

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

이 튜토리얼은 기존 CI/CD 비밀 구성을 ID 토큰 사용하도록 변환하는 방법을 보여줍니다.

CI_JOB_JWT 변수는 사용 중지되었지만, ID 토큰으로 업데이트하려면 Vault와 함께 사용하기 위한 중요한 구성 변경이 필요합니다. 수십 개 이상의 작업이 있는 경우, 한꺼번에 모든 것을 변환하는 것은 어려운 작업입니다.

ID 토큰으로 이관하는 표준 방법은 없으므로, 이 튜토리얼에는 기존 CI/CD 비밀을 변환하는 두 가지 방법이 포함되어 있습니다. 귀하의 사용 사례에 가장 적합한 방법을 선택하세요:

  1. Vault 구성 업데이트:
  2. CI/CD 작업 업데이트

전제 조건

이 튜토리얼은 GitLab CI/CD 및 Vault에 익숙한 것으로 가정합니다.

따라오기 위해서는 다음이 있어야 합니다:

  • GitLab 16.0 이상을 실행 중인 인스턴스 또는 GitLab.com에 있는 계정.
  • 이미 사용 중인 Vault 서버.
  • CI_JOB_JWT로부터 시크릿을 검색하는 CI/CD 작업.

아래의 예제에서 다음을 교체하세요:

  • vault.example.com: 귀하의 Vault 서버의 URL.
  • gitlab.example.com: 귀하의 GitLab 인스턴스의 URL.
  • jwt 또는 jwt_v2: 귀하의 인증 방법 이름으로 교체하세요.

방법 A: JWT 역할을 새 Vault 인증 방법으로 마이그레이션

이 방법은 기존 사용 중인 것과 병렬로 두 번째 JWT 인증 방법을 생성합니다. 그 후 GitLab 통합에 사용되는 모든 Vault 역할은이 새로운 인증 방법에 다시 생성됩니다.

Vault에서 두 번째 JWT 인증 경로 생성

CI_JOB_JWT에서 ID 토큰으로의 전환 일환으로 bound_issuerhttps://를 포함하여 업데이트해야 합니다:

$ vault write auth/jwt/config \
    oidc_discovery_url="https://gitlab.example.com" \
    bound_issuer="https://gitlab.example.com"

이 변경을 수행한 후에 CI_JOB_JWT를 사용하는 작업이 실패하기 시작합니다.

Vault에서 여러 인증 경로를 생성할 수 있으므로 중단 없이 프로젝트별로 ID 토큰으로 이동할 수 있게 합니다.

  1. 다음 명령을 실행하여 새로운 인증 경로를 구성합니다(jwt_v2로 이름을 선택할 수 있지만, 아래 예제는 jwt_v2를 사용한다고 가정하므로 필요에 따라 예제를 업데이트하세요):

    vault auth enable -path jwt_v2 jwt
    
  2. 인스턴스에 새로운 인증 경로를 구성하세요:

    $ vault write auth/jwt_v2/config \
        oidc_discovery_url="https://gitlab.example.com" \
        bound_issuer="https://gitlab.example.com"
    

새로운 인증 경로를 사용하도록 역할 재생성

역할은 특정 인증 경로에 바인딩되므로 각 작업에 대해 새로운 역할을 추가해야 합니다.

  1. myproject-staging이름으로 스테이징 역할을 재생성합니다:

    $ vault write auth/jwt_v2/role/myproject-staging - <<EOF
    {
      "role_type": "jwt",
      "policies": ["myproject-staging"],
      "token_explicit_max_ttl": 60,
      "user_claim": "user_email",
      "bound_claims": {
        "project_id": "22",
        "ref": "master",
        "ref_type": "branch"
      }
    }
    EOF
    
  2. myproject-production이름으로 프로덕션 역할을 재생성합니다:

    $ vault write auth/jwt_v2/role/myproject-production - <<EOF
    {
      "role_type": "jwt",
      "policies": ["myproject-production"],
      "token_explicit_max_ttl": 60,
      "user_claim": "user_email",
      "bound_claims_type": "glob",
      "bound_claims": {
        "project_id": "22",
        "ref_protected": "true",
        "ref_type": "branch",
        "ref": "auto-deploy-*"
      }
    }
    EOF
    

vault 명령에서 jwtjwt_v2로 업데이트하면 되며, 역할 안의 role_type는 변경하지 말아주시기 바랍니다.

메소드 B: iss 클레임을 이관 창으로 이동

이 방법은 Vault 관리자가 두 번째 JWT 인증 방법을 만들고 GitLab 관련 역할을 모두 재생성할 필요가 없습니다.

각 역할에 bound_issuers 클레임 맵 추가

Vault는 JWT 인증 방법 레벨에서 여러 iss 클레임을 허용하지 않습니다. 왜냐하면 이 레벨의 bound_issuer 지시문은 단일 값을 받기 때문입니다. 그러나 여러 클레임은 bound_claims 맵 구성 지시문을 사용하여 역할 레벨에서 구성할 수 있습니다.

이 방법을 사용하면 Vault에 iss 클레임 유효성 검사를 위한 여러 옵션을 제공할 수 있습니다. 이는 id_tokens와 함께 제공되는 https://로 시작하는 GitLab 인스턴스 호스트명 클레임과 이전의 접두사가 없는 클레임을 지원합니다.

필요한 역할에 bound_claims 구성을 추가하려면 다음을 실행하세요:

$ vault write auth/jwt/role/myproject-staging - <<EOF
{
  "role_type": "jwt",
  "policies": ["myproject-staging"],
  "token_explicit_max_ttl": 60,
  "user_claim": "user_email",
  "bound_claims": {
    "iss": [
      "https://gitlab.example.com",
      "gitlab.example.com"
    ],
    "project_id": "22",
    "ref": "master",
    "ref_type": "branch"
  }
}
EOF

bound_claims 섹션 외에는 기존 역할 구성을 수정할 필요가 없습니다. 위에 표시된대로 iss 구성을 추가하여 Vault가 이 역할에 대해 접두사가 있는 것과 없는 iss 클레임을 모두 수락하도록 하세요.

다음 단계로 진행하기 전에 GitLab 통합에 사용되는 모든 JWT 역할에이 변경을 적용해야 합니다.

모든 프로젝트가 마이그레이션되고 CI_JOB_JWT와 ID 토큰에 대한 병렬 지원이 더 이상 필요하지 않은 경우 원하는 경우 iss 클레임 유효성 검사의 마이그레이션을 역할로 다시 되돌릴 수 있습니다.

bound_issuers 클레임을 인증 방법에서 제거

모든 역할이 bound_claims.iss 클레임으로 업데이트된 후에 이 유효성 검사에 대한 인증 방법 레벨 구성을 제거할 수 있습니다.

$ vault write auth/jwt/config \
    oidc_discovery_url="https://gitlab.example.com" \
    bound_issuer=""

bound_issuer 지시문을 빈 문자열로 설정하면 인증 방법 레벨에서 발행자 유효성 검사가 제거됩니다. 그러나 이 유효성 검사는 역할 레벨로 이동되었으므로이 구성은 여전히 안전합니다.

CI/CD 작업 업데이트

Vault에는 두 가지 다른 KV Secrets Engines가 있으며 사용 중인 버전에 따라 CI/CD에서 보안 정보를 어떻게 정의하는지가 영향을 미칩니다.

Vault 서버를 확인하려면 HashiCorp 지원 포털의 내 Vault KV 마운트는 어떤 버전입니까? 문서를 확인하세요.

또한 필요한 경우 CI/CD 문서를 확인할 수 있습니다:

다음 예시에서는 secret/myproject/staging/dbpassword 필드에 작성된 스테이징 데이터베이스 암호를 얻는 방법을 보여줍니다.

VAULT_AUTH_PATH 변수의 값은 사용한 마이그레이션 방법에 따라 달라집니다.

  • 방법 A (JWT 역할을 새로운 Vault 인증 방법으로 마이그레이션): jwt_v2 사용
  • 방법 B (iss 클레임을 역할로 이동하여 마이그레이션 창 생성): jwt 사용

KV Secrets Engine v1

secrets:vault 키워드는 KV Mount의 v2를 기본값으로 사용하므로 작업을 명시적으로 v1 엔진을 사용하도록 구성해야 합니다:

job:
  variables:
    VAULT_SERVER_URL: https://vault.example.com
    VAULT_AUTH_PATH: jwt_v2  # 또는 방법 B를 사용한 경우 "jwt"
    VAULT_AUTH_ROLE: myproject-staging
  id_tokens:
    VAULT_ID_TOKEN:
      aud: https://gitlab.example.com
  secrets:
    PASSWORD:
      vault:
        engine:
          name: kv-v1
          path: secret
        field: password
        path: myproject/staging/db
      file: false

VAULT_SERVER_URLVAULT_AUTH_PATH프로젝트 또는 그룹 CI/CD 변수로 정의할 수 있습니다.

우리는 기본적으로 ID 토큰이 기본적으로 파일에 비밀을 넣기 때문에 secrets:file:false를 사용합니다만, 우리는 그것을 예전 동작과 일치시키기 위해 보통 변수로 동작하도록 만들어야 합니다.

KV Secrets Engine v2

v2 엔진에 사용할 수 있는 두 가지 형식이 있습니다.

긴 형식:

job:
  variables:
    VAULT_SERVER_URL: https://vault.example.com
    VAULT_AUTH_PATH: jwt_v2  # 또는 "jwt", 메소드 B를 사용한 경우
    VAULT_AUTH_ROLE: myproject-staging
  id_tokens:
    VAULT_ID_TOKEN:
      aud: https://gitlab.example.com
  secrets:
    PASSWORD:
      vault:
        engine:
          name: kv-v2
          path: secret
        field: password
        path: myproject/staging/db
      file: false

이 예제는 v1 엔진을 사용하는 예제와 동일하지만, secrets:vault:engine:name:kv-v2로 설정되어 엔진과 일치하도록 되어 있습니다.

또한 짧은 형식을 사용할 수도 있습니다:

job:
  variables:
    VAULT_SERVER_URL: https://vault.example.com
    VAULT_AUTH_PATH: jwt_v2  # 또는 "jwt", 메소드 B를 사용한 경우
    VAULT_AUTH_ROLE: myproject-staging
  id_tokens:
    VAULT_ID_TOKEN:
      aud: https://gitlab.example.com
  secrets:
      PASSWORD:
        vault: myproject/staging/db/password@secret
        file: false

업데이트한 CI/CD 구성을 커밋한 후에는 작업이 ID 토큰을 사용하여 비밀을 가져올 것입니다. 축하합니다!

모든 프로젝트를 ID 토큰을 사용하여 비밀을 가져오도록 마이그레이션한 경우, 마이그레이션에 메소드 B를 사용했다면 원하는 경우 iss 클레임 검증을 다시 인증 메소드 구성으로 이동할 수 있습니다.