튜토리얼: 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를 사용하여 Vault에서 시크릿을 검색하는 CI/CD 작업

아래 예시에서 다음을 대체하세요:

  • vault.example.com은 Vault 서버의 URL로 대체합니다.
  • gitlab.example.com은 GitLab 인스턴스의 URL로 대체합니다.
  • jwt 또는 jwt_v2는 귀사의 인증 방법 이름으로 대체합니다.

방법 A: 기존 Vault 인증 방법에서 JWT 역할을 새로운 Vault 인증 방법으로 마이그레이션

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

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

CI_JOB_JWT에서 ID 토큰으로의 전환에 일환으로 Vault의 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라는 이름의 새 인증 경로를 구성하려면 다음을 실행합니다:

    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"
    

새 인증 경로에서 역할을 다시 생성

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

  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_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 토큰에 대한 병렬 지원이 더 이상 필요하지 않은 경우 bound_issuers 클레임 유효성 검사의 마이그레이션을 역할에서 인증 방법 수준으로 되돌릴 수 있습니다.

인증 방법에서 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 Mount는 어떤 버전입니까? 기사를 확인하세요.

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

다음 예시는 password 필드에 스테이징 데이터베이스 암호를 얻는 방법을 보여줍니다. 이 암호는 secret/myproject/staging/db에 있습니다.

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://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 변수로 정의할 수 있습니다.

기본적으로 ID 토큰은 비밀을 파일에 배치하지만, 이전 동작과 일치시키기 위해 우리는 secrets:file:false를 사용합니다.

KV Secrets Engine 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 클레임 유효성 검사를 다시 인증 방법 구성으로 이동할 수 있습니다.