概要
OpenID Connect (OIDC) を使うと、GitHub Actions ワークフローが HashiCorp Vault で認証し、シークレットを取得できます。
このガイドでは、HashiCorp Vault が GitHub の OIDC をフェデレーション ID として信頼するように構成する方法の概要について説明します。また、この構成を hashicorp/vault-action アクションで使って HashiCorp Vault からシークレットを取得する方法を示します。
前提条件
- 
GitHub が OpenID Connect (OIDC) を使用する方法の基本的な概念とそのアーキテクチャと利点については、「OpenID Connect」を参照してください。 
- 
先に進む前に、アクセス トークンが予測可能な方法でのみ割り当てられるようにセキュリティ戦略を計画する必要があります。 クラウド プロバイダーがアクセス トークンを発行する方法を制御するには、少なくとも 1 つの条件を定義し、信頼できないリポジトリがクラウド リソースにアクセス トークンを要求できないようにする必要があります。 詳しくは、「OpenID Connect」をご覧ください。 
- 
GHE.com に関するこのガイドに従っている場合は、次のドキュメントの特定の値を置き換える必要があることを理解してください。 「OpenID Connect」を参照してください。 
HashiCorp Vault への ID プロバイダーの追加
HashiCorp Vault と共に OIDC を使うには、GitHub OIDC プロバイダーの信頼構成を追加する必要があります。 詳細については、HashiCorp Vault のドキュメントを参照してください。
認証に JSON Web トークン (JWT) を受け入れるように Vault サーバーを構成します。
- 
JWT authメソッドを有効にし、writeを使用して Vault に構成を適用します。oidc_discovery_urlおよびbound_issuerパラメーターの場合は、https://token.actions.githubusercontent.comを使います。 これらのパラメーターを使用すると、Vault サーバーは認証プロセス中に受信した JSON Web トークン (JWT) を確認できます。Shell vault auth enable jwt vault auth enable jwtShell 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"メモ Enterprise に対して一意の発行者 URL が REST API を使って設定されていた場合 (「OpenID Connect」で説明されています)、 bound_issuerとoidc_discover_urlの値はその URL と一致している必要があります。 たとえば、その一意の issuer URL が使われているoctocatという名前の Enterprise の場合、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" ] } EOFvault policy write myproject-production - <<EOF # Read-only permission on 'secret/data/production/*' path path "secret/data/production/*" { capabilities = [ "read" ] } EOF
- 
異なるポリシーをグループ化するようにロールを構成します。 認証が成功した場合、これらのポリシーは結果の Vault アクセス トークンにアタッチされます。 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" } EOFvault 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パラメーターがセキュリティ要件に対して定義されており、少なくとも 1 つの条件があることを確認します。 必要に応じて、- bound_subjectだけでなく、- bound_audiencesパラメーターも設定できます。
- 受信した JWT ペイロード内の任意の要求を確認するために、bound_claimsパラメーターには一連の要求とその必須の値が含まれています。 上記の例では、ロールは、user-or-org-nameアカウントによって所有されるrepo-nameリポジトリからの受信認証要求を受け取ります。
- GitHub の OIDC プロバイダーでサポートされているすべての可能な要求を確認するには、「OpenID Connect」を参照してください。
詳細については、HashiCorp Vault のドキュメントを参照してください。
GitHub Actions ワークフローを更新する
OIDC のワークフローを更新するには、YAML に 2 つの変更を行う必要があります。
- トークンのアクセス許可設定を追加します。
- この hashicorp/vault-actionアクションを使って、OIDC トークン (JWT) をクラウド アクセス トークンと交換します。
独自のカスタム保護規則を有効にして、サードパーティ サービスを使ったデプロイを制御できます。 たとえば、Datadog、Honeycomb、ServiceNow などのサービスを使用し、GitHub への展開に対して自動承認を提供できます。
Vault のシークレットにアクセスできるようにワークフローに OIDC 統合を追加するには、次のコード変更を追加する必要があります。
- GitHub OIDC プロバイダーからトークンをフェッチするアクセス許可を付与します。
- ワークフローには、id-tokenの値がwriteに設定されたpermissions:設定が必要です。 これにより、ワークフロー内のすべてのジョブから OIDC トークンをフェッチすることができます。
 
- ワークフローには、
- GitHub OIDC プロバイダーに JWT を要求し、それを HashiCorp Vault に提示してアクセス トークンを受け取ります。
- hashicorp/vault-actionアクションを使って、JWT をフェッチし、Vault からアクセス トークンを受け取ることができます。または、Actions ツールキットを使ってジョブのトークンをフェッチすることもできます。
 
この例は、HashiCorp Vault からシークレットを要求するために、公式のアクションと共に OIDC を使う方法を示しています。
アクセス許可設定の追加
GitHub の OIDC プロバイダーが実行ごとに JSON Web Token を作成できるよう、ジョブまたはワークフローの実行には id-token: write を含む permissions の設定が必要です。
メモ
 ワークフローのアクセス許可で id-token: write を設定しても、リソースへの変更または書き込みを行うアクセス許可はワークフローに付与されません。 そうではなく、ワークフローは、アクションまたはステップのための OIDC トークンを要求 (フェッチ) して使用 (設定) することのみが許可されます。 その後、このトークンは、有効期間の短いアクセス トークンを使って外部サービスで認証を行うために使われます。
必要なアクセス許可、構成例、高度なシナリオについて詳しくは、「OpenID Connect リファレンス」をご覧ください。
メモ
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.
メモ
- Vault サーバーにパブリック ネットワークからアクセスできない場合は、他の使用可能な Vault の認証方法でセルフホステッド ランナーを使用することを検討してください。 詳しくは、「セルフホステッド ランナー」をご覧ください。
- VAULT-NAMESPACEは、Vault Enterprise (HCP Vault を含む) デプロイに対して設定する必要があります。 詳しくは、Vault 名前空間に関するページを参照してください。
アクセス トークンの取り消し
既定で、Vault サーバーでは TTL の有効期限が切れたときにアクセス トークンを自動的に取り消します。そのため、アクセス トークンを手動で取り消す必要はありません。 ただし、ジョブが完了または失敗した直後にアクセス トークンを取り消す場合は、Vault API を使用して発行されたトークンを手動で取り消すことができます。
- exportTokenオプションを- true(既定値:- false) に設定します。 これにより、発行された Vault アクセス トークンが環境変数としてエクスポートされます:- 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