튜토리얼: HashiCorp Vault 설정을 업데이트하여 ID 토큰 사용하기

Tier: Premium, Ultimate Offering: GitLab.com, Self-managed, GitLab Dedicated
note
Vault 1.17부터, JWT 인증 로그인은 역할에 바운드된 청중을 요구합니다
JWT에 aud 클레임이 포함된 경우에 해당합니다. aud 클레임은 단일 문자열 또는 문자열 목록이 될 수 있습니다.

이 튜토리얼은 기존 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로 Vault에서 비밀을 검색하는 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 토큰으로 전환하는 과정의 일환으로, Vault의 bound_issuer를 업데이트하여 https://를 포함해야 합니다:

$ 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라는 이름으로 새로운 인증 경로를 구성합니다. 다음을 실행하세요:

    vault auth enable -path jwt_v2 jwt  
    

    다른 이름을 선택할 수 있지만, 이 예제는 jwt_v2를 사용한 것으로 가정하므로 필요한 경우 예제를 업데이트하세요.

  2. 인스턴스에 대해 새로운 인증 경로를 구성합니다:

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

새로운 인증 경로를 사용하기 위한 역할 다시 생성

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

JWT에 audience가 포함되어 있으면 역할의 bound_audiences 매개변수가 필수이며 JWT의 연관된 aud 클레임 중 최소 하나와 일치해야 합니다.

  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_audiences": ["https://vault.example.com"],
      "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_audiences": ["https://vault.example.com"],
      "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_audiences": ["https://vault.example.com"],
  "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 비밀 엔진이 있으며, 사용 중인 버전은 CI/CD에서 비밀을 정의하는 방식에 영향을 미칩니다.

HashiCorp 지원 포털의 내 Vault KV 마운트는 어떤 버전인가요? 기사를 확인하여 Vault 서버를 확인하세요.

또한 필요하다면 다음 CI/CD 문서를 검토할 수 있습니다:

다음 예시들은 secret/myproject/staging/dbpassword 필드에 기록된 스테이징 데이터베이스 비밀번호를 얻는 방법을 보여줍니다.

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

  • 방법 A (JWT 역할을 새 Vault 인증 방법으로 마이그레이션): jwt_v2 사용.
  • 방법 B (이전_window의 역할로 iss 클레임 이동): jwt 사용.

KV 비밀 엔진 v1

secrets:vault 키워드는 KV 마운트의 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://vault.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 변수로 정의될 수 있습니다, 필요에 따라.

우리는 secrets:file:false를 사용합니다. 이는 ID 토큰이 기본적으로 비밀을 파일에 저장하기 때문이며, 우리는 이전 동작과 일치하는 일반 변수로 작동해야 합니다.

KV 비밀 엔진 v2

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

긴 형식:

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://vault.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  # 또는 방법 B를 사용한 경우 "jwt"
    VAULT_AUTH_ROLE: myproject-staging
  id_tokens:
    VAULT_ID_TOKEN:
      aud: https://vault.example.com
  secrets:
      PASSWORD:
        vault: myproject/staging/db/password@secret
        file: false

업데이트된 CI/CD 구성을 커밋한 후, 귀하의 작업은 ID 토큰으로 비밀을 가져오기 시작할 것입니다. 축하합니다!

모든 프로젝트가 ID 토큰으로 비밀을 가져오기 위해 마이그레이션되었고 마이그레이션을 위해 방법 B를 사용한 경우, 원한다면 iss 클레임 검증을 다시 인증 방법 구성으로 이동할 수 있습니다.