개요
OIDC(OpenID Connect)를 사용하면 GitHub Actions 워크플로가 HashiCorp 자격 증명 모음으로 인증하여 비밀을 검색할 수 있습니다.
이 가이드에서는 GitHub의 OIDC를 페더레이션 ID로 신뢰하도록 HashiCorp Vault를 구성하는 방법에 대한 개요를 제공하고 hashicorp/vault-action 작업에서 이 구성을 사용하여 HashiCorp Vault에서 비밀을 검색하는 방법을 보여줍니다.
필수 조건
-
GitHub가 OIDC(OpenID Connect)를 사용하는 방법과 아키텍처 및 이점에 대한 기본 개념을 알아보려면 “OpenID Connect를 사용한 보안 강화 정보”를 참조하세요.
-
계속하기 전에 액세스 토큰이 예측 가능한 방식으로만 할당되도록 보안 전략을 계획해야 합니다. 클라우드 공급자가 액세스 토큰을 발급하는 방법을 제어하려면 신뢰할 수 없는 리포지토리가 클라우드 리소스에 대한 액세스 토큰을 요청할 수 없도록 하나 이상의 조건을 정의해야 합니다. 자세한 내용은 "OpenID Connect를 사용한 보안 강화 정보"을(를) 참조하세요.
-
GHE.com에서 이 가이드를 따르는 경우 다음 문서의 특정 값을 대체해야 한다는 점을 알아 두세요. "OpenID Connect를 사용한 보안 강화 정보" 항목을 참조하세요.
HashiCorp 자격 증명 모음에 ID 공급자 추가
HashiCorp Vault에서 OIDC를 사용하려면 GitHub OIDC 공급자에 대한 신뢰 구성을 추가해야 합니다. 자세한 내용은 HashiCorp Vault 설명서를 참조하세요.
인증을 위해 JWT(JSON Web Tokens)를 수락하도록 Vault 서버를 구성하려면 다음을 수행합니다.
-
JWT
auth
메서드를 사용하도록 설정하고write
를 사용하여 자격 증명 모음에 구성을 적용합니다.oidc_discovery_url
및bound_issuer
매개 변수의 경우https://token.actions.githubusercontent.com
을(를) 사용합니다. 이러한 매개 변수를 통해 Vault 서버는 인증 프로세스 중에 수신된 JWT(JSON Web Token)를 확인할 수 있습니다.Shell vault auth enable jwt
vault auth enable jwt
Shell vault write auth/jwt/config \ bound_issuer="https://token.actions.githubusercontent.com" \ oidc_discovery_url="https://token.actions.githubusercontent.com"
vault write auth/jwt/config \ bound_issuer="https://token.actions.githubusercontent.com" \ oidc_discovery_url="https://token.actions.githubusercontent.com"
Note
REST API("OpenID Connect를 사용한 보안 강화 정보"에 설명된 대로)를 사용하여 엔터프라이즈에 대한 고유한 발급자 URL을 설정한 경우
bound_issuer
및oidc_discover_url
값이 해당 고유 URL과 일치해야 합니다. 예를 들어 고유한 발급자 URL을 사용하는octocat
엔터프라이즈의 경우bound_issuer
및oidc_discovery_url
을https://token.actions.githubusercontent.com/octocat
로 설정해야 합니다. -
워크플로에서 비밀을 검색하는 데 사용할 특정 경로에 대한 액세스 권한만 부여하는 정책을 구성합니다. 고급 정책은 HashiCorp Vault 정책 설명서를 참조하세요.
Shell vault policy write myproject-production - <<EOF # Read-only permission on 'secret/data/production/*' path path "secret/data/production/*" { capabilities = [ "read" ] } EOF
vault policy write myproject-production - <<EOF # Read-only permission on 'secret/data/production/*' path path "secret/data/production/*" { capabilities = [ "read" ] } EOF
-
서로 다른 정책을 함께 그룹화하는 역할을 구성합니다. 인증에 성공하면 이러한 정책이 결과 자격 증명 모음 액세스 토큰에 연결됩니다.
Shell vault write auth/jwt/role/myproject-production -<<EOF { "role_type": "jwt", "user_claim": "actor", "bound_claims": { "repository": "user-or-org-name/repo-name" }, "policies": ["myproject-production"], "ttl": "10m" } EOF
vault write auth/jwt/role/myproject-production -<<EOF { "role_type": "jwt", "user_claim": "actor", "bound_claims": { "repository": "user-or-org-name/repo-name" }, "policies": ["myproject-production"], "ttl": "10m" } EOF
ttl
은 결과 액세스 토큰의 유효성을 정의합니다.bound_claims
매개 변수가 보안 요구 사항에 대해 정의되고 하나 이상의 조건이 있는지 확인합니다. 필요에 따라bound_audiences
매개 변수뿐만bound_subject
를 설정할 수도 있습니다.- 수신된 JWT 페이로드에서 임의의 클레임을 확인하기 위해
bound_claims
매개 변수에는 클레임 집합과 해당 필수 값이 포함됩니다. 위의 예제에서 역할은user-or-org-name
계정이 소유한repo-name
리포지토리에서 들어오는 인증 요청을 수락합니다. - GitHub의 OIDC 공급자가 지원하는 사용 가능한 모든 클레임을 보려면 "OpenID Connect를 사용한 보안 강화 정보"을 참조하세요.
자세한 내용은 HashiCorp Vault 설명서를 참조하세요.
GitHub Actions 워크플로 업데이트
OIDC에 대한 워크플로를 업데이트하려면 YAML에 두 가지를 변경해야 합니다.
- 토큰에 대한 사용 권한 설정을 추가합니다.
hashicorp/vault-action
작업을 사용하여 클라우드 액세스 토큰에 대한 OIDC 토큰(JWT)을 교환합니다.
참고: 워크플로 또는 OIDC 정책에서 환경을 사용하는 경우 추가 보안을 위해 환경에 보호 규칙을 추가하는 것이 좋습니다. 예를 들어 환경에 배포할 수 있는 분기 및 태그를 제한하거나 환경 비밀에 액세스하도록 환경에 대한 배포 규칙을 구성할 수 있습니다. 자세한 내용은 "배포 환경 관리"을(를) 참조하세요.
자격 증명 모음의 비밀에 액세스할 수 있도록 하는 워크플로에 OIDC 통합을 추가하려면 다음 코드 변경 내용을 추가해야 합니다.
- GitHub OIDC 공급자에서 토큰을 가져올 수 있는 권한을 부여합니다.
- 워크플로에는
id-token
값이write
로 설정된permissions:
설정이 필요합니다. 이렇게 하면 워크플로의 모든 작업에서 OIDC 토큰을 가져올 수 있습니다.
- 워크플로에는
- GitHub OIDC 공급자에서 JWT를 요청하고 HashiCorp Vault에 제출하여 액세스 토큰을 받습니다.
hashicorp/vault-action
작업을 사용하여 JWT를 가져오고 자격 증명 모음에서 액세스 토큰을 받거나 작업 도구 키트를 사용하여 작업에 대한 토큰을 가져올 수 있습니다.
이 예제에서는 공식 작업과 함께 OIDC를 사용하여 HashiCorp Vault에서 비밀을 요청하는 방법을 보여줍니다.
사용 권한 설정 추가
작업 또는 워크플로 실행에는 GitHub의 OIDC 공급자가 모든 실행에 대한 JSON 웹 토큰을 만들 수 있는 id-token: write
가 있는 permissions
설정이 필요합니다. id-token
에 대한 permissions
가 write
로 설정되지 않으면 OIDC JWT ID 토큰을 요청할 수 없습니다. 그러나 이 값은 리소스에 대한 쓰기 액세스 권한을 부여하는 것을 의미하지 않으며, 수명이 짧은 액세스 토큰으로 인증할 수 있도록 작업 또는 단계에 대한 OIDC 토큰을 페치하고 설정할 수만 있습니다. 실제 신뢰 설정은 OIDC 클레임을 사용하여 정의됩니다. 자세한 내용은 "OpenID Connect를 사용한 보안 강화 정보"을(를) 참조하세요.
이 id-token: write
설정을 통해 다음 방법 중 하나를 사용하여 GitHub의 OIDC 공급자에서 JWT를 요청할 수 있습니다.
- 실행기(
ACTIONS_ID_TOKEN_REQUEST_URL
및ACTIONS_ID_TOKEN_REQUEST_TOKEN
)에서 환경 변수 사용 - Actions 도구 키트에서
getIDToken()
사용
워크플로에 대한 OIDC 토큰을 페치해야 하는 경우 워크플로 수준에서 사용 권한을 설정할 수 있습니다. 예시:
permissions: id-token: write # This is required for requesting the JWT contents: read # This is required for actions/checkout
permissions:
id-token: write # This is required for requesting the JWT
contents: read # This is required for actions/checkout
단일 작업에 대한 OIDC 토큰을 가져오기만 하면 되는 경우 해당 작업 내에서 이 권한을 설정할 수 있습니다. 예시:
permissions: id-token: write # This is required for requesting the JWT
permissions:
id-token: write # This is required for requesting the JWT
워크플로의 요구 사항에 따라 여기에서 추가 권한을 지정해야 할 수 있습니다.
호출자 워크플로와 동일한 사용자, 조직 또는 엔터프라이즈가 소유한 재사용 가능한 워크플로의 경우, 호출자의 컨텍스트에서 재사용 가능한 워크플로에서 생성된 OIDC 토큰에 액세스할 수 있습니다.
엔터프라이즈 또는 조직 외부에서 재사용 가능한 워크플로의 경우, 호출자 워크플로 수준 또는 재사용 가능한 워크플로를 호출하는 특정 작업에서 write
에 id-token
의 permissions
설정을 명시적으로 설정해야 합니다.
이렇게 설정하면 재사용 가능한 워크플로에서 생성된 OIDC 토큰이 의도한 경우에만 호출자 워크플로에서 사용할 수 있게 됩니다.
자세한 내용은 "워크플로 다시 사용"을(를) 참조하세요.
Note
permissions
키를 사용하는 경우 항상 읽기 액세스 권한을 가져오는 메타데이터 범위를 제외하고 지정되지 않은 모든 권한은 _액세스 권한 없음_으로 설정됩니다. 따라서 다른 권한(예: contents: read
)을 추가해야 할 수 있습니다. 자세한 내용은 "자동 토큰 인증"을 참조하세요.
액세스 토큰 요청
hashicorp/vault-action
작업은 GitHub OIDC 공급자로부터 JWT를 받은 다음 HashiCorp Vault 인스턴스에서 액세스 토큰을 요청하여 비밀을 검색합니다. 자세한 내용은 HashiCorp Vault GitHub Action 설명서를 참조하세요.
이 예제에서는 HashiCorp Vault에서 비밀을 요청하는 작업을 만드는 방법을 보여줍니다.
VAULT-URL
: HashiCorp Vault의 URL로 바꿉니다.VAULT-NAMESPACE
: HashiCorp Vault에서 설정한 네임스페이스로 바꿉니다. 예:admin
ROLE-NAME
: HashiCorp Vault 트러스트 관계에서 설정한 역할로 바꿉니다.SECRET-PATH
: HashiCorp Vault에서 검색하는 비밀의 경로로 바꿉니다. 예:secret/data/production/ci npmToken
jobs: retrieve-secret: runs-on: ubuntu-latest permissions: id-token: write contents: read steps: - name: Retrieve secret from Vault uses: hashicorp/vault-action@9a8b7c6d5e4f3a2b1c0d9e8f7a6b5c4d3e2f1a0b with: method: jwt url: VAULT-URL namespace: VAULT-NAMESPACE # HCP Vault and Vault Enterprise only role: ROLE-NAME secrets: SECRET-PATH - name: Use secret from Vault run: | # This step has access to the secret retrieved above; see hashicorp/vault-action for more details.
jobs:
retrieve-secret:
runs-on: ubuntu-latest
permissions:
id-token: write
contents: read
steps:
- name: Retrieve secret from Vault
uses: hashicorp/vault-action@9a8b7c6d5e4f3a2b1c0d9e8f7a6b5c4d3e2f1a0b
with:
method: jwt
url: VAULT-URL
namespace: VAULT-NAMESPACE # HCP Vault and Vault Enterprise only
role: ROLE-NAME
secrets: SECRET-PATH
- name: Use secret from Vault
run: |
# This step has access to the secret retrieved above; see hashicorp/vault-action for more details.
Note
- 공용 네트워크에서 Vault 서버에 액세스할 수 없는 경우 사용 가능한 다른 자격 증명 모음 인증 방법과 함께 자체 호스트형 실행기를 사용하는 것이 좋습니다. 자세한 내용은 "자체 호스트형 실행기 정보"을 참조하세요.
VAULT-NAMESPACE
는 Vault Enterprise(HCP Vault 포함) 배포에 대해 설정해야 합니다. 자세한 내용은 Vault 네임스페이스를 참조하세요.
액세스 토큰 해지
기본적으로 Vault 서버는 TTL이 만료되면 액세스 토큰을 자동으로 철회하므로 액세스 토큰을 수동으로 철회할 필요가 없습니다. 그러나 작업이 완료되거나 실패한 직후에 액세스 토큰을 철회하려는 경우 Vault API를 사용하여 발급된 토큰을 수동으로 철회할 수 있습니다.
exportToken
옵션을true
로 설정합니다(기본값:false
). 그러면 발급된 자격 증명 모음 액세스 토큰을 환경 변수VAULT_TOKEN
으로 내보냅니다.- 액세스 토큰을 철회하려면 토큰 철회(자체) Vault API를 호출하는 단계를 추가합니다.
jobs: retrieve-secret: runs-on: ubuntu-latest permissions: id-token: write contents: read steps: - name: Retrieve secret from Vault uses: hashicorp/vault-action@9a8b7c6d5e4f3a2b1c0d9e8f7a6b5c4d3e2f1a0b with: exportToken: true method: jwt url: VAULT-URL role: ROLE-NAME secrets: SECRET-PATH - name: Use secret from Vault run: | # This step has access to the secret retrieved above; see hashicorp/vault-action for more details. - name: Revoke token # This step always runs at the end regardless of the previous steps result if: always() run: | curl -X POST -sv -H "X-Vault-Token: ${{ env.VAULT_TOKEN }}" \ VAULT-URL/v1/auth/token/revoke-self
jobs:
retrieve-secret:
runs-on: ubuntu-latest
permissions:
id-token: write
contents: read
steps:
- name: Retrieve secret from Vault
uses: hashicorp/vault-action@9a8b7c6d5e4f3a2b1c0d9e8f7a6b5c4d3e2f1a0b
with:
exportToken: true
method: jwt
url: VAULT-URL
role: ROLE-NAME
secrets: SECRET-PATH
- name: Use secret from Vault
run: |
# This step has access to the secret retrieved above; see hashicorp/vault-action for more details.
- name: Revoke token
# This step always runs at the end regardless of the previous steps result
if: always()
run: |
curl -X POST -sv -H "X-Vault-Token: ${{ env.VAULT_TOKEN }}" \
VAULT-URL/v1/auth/token/revoke-self