IK.AM

@making's tech note


GitHubのOpen ID Connectを使ってGitHub ActionsからHashiCorp Vaultに安全にアクセスするメモ

🗃 {Dev/SecretManagement/Vault}
🏷 Vault 🏷 OIDC 🏷 GitHub Actions 
🗓 Updated at 2023-01-11T03:04:32Z  🗓 Created at 2023-01-09T07:00:13Z   🌎 English Page

CIからクラウドプロバイダーにアクセスする際にAPI KeyなどのSecretsをCI側に置くと、CI側でセキュリティインシデントが発生した際にデータを守れません。
自分のデータは自分で守りましょう。

ということで、SecretsはSelf HostedなHashiCorp Vaultに置くとします。ではCIからHashiCorp Vaultへのアクセスはどうすれば良いでしょうか?VaultのトークンをCI側に置いてしまうと、意味がないですね。
GitHub ActionsではOpen ID Connectを使用して、GitHub側でJWTを発行し、Vault側でこのトークンを信頼し、Vaultのトークンをジョブごとに一時的に払い出すことができます。これを使うと、CI側にVaultのトークンを保存するよりも遥かに安全にVaultへアクセスすることができます。

このアクセス方法を試したのでメモします。以下のドキュメントを参考にしました。

前提としてGitHub Actionsからアクセス可能なVaultがあるとします。

動作確認したVaultのバージョンは以下です。

$ vault version
Vault v1.12.2 (415e1fe3118eebd5df6cb60d13defdc01aa17b03), built 2022-11-23T12:53:46Z

$ vault status
Key             Value
---             -----
Seal Type       shamir
Initialized     true
Sealed          false
Total Shares    5
Threshold       3
Version         1.12.2
Build Date      2022-11-23T12:53:46Z
Storage Type    s3
Cluster Name    vault-cluster-d5eb8945
Cluster ID      76979525-c584-407c-6b91-2671b591bf04
HA Enabled      false

JWT Auth Methodの設定

JWT Auth Methodを有効にし、トークンの検証方式としてOIDC Discoveryを設定します。 Discovery URLは https://token.actions.githubusercontent.com です。

vault auth enable jwt

vault write auth/jwt/config \
  bound_issuer="https://token.actions.githubusercontent.com" \
  oidc_discovery_url="https://token.actions.githubusercontent.com"

Policyの作成

kvというパスの下のcicd以下のみGitHub Actionsからのreadを許可します。

vault policy write cicd - <<EOF
path "kv/data/cicd/*" {
  capabilities = [ "read" ]
}
EOF

Roleの作成

JWT Auth Methodに対するRoleを作成します。このRoleは後にGitHub ActionsのWorkflowで指定します。

vault write auth/jwt/role/cicd -<<EOF
{
  "role_type": "jwt",
  "user_claim": "actor",
  "bound_claims_type": "glob",
  "bound_claims": {
    "sub": [
      "repo:making/*",
      "repo:categolj/*"
    ]
  },
  "policies": [
    "cicd"
  ],
  "ttl": "10m"
}
EOF

policiesに先ほど作成したPolicyを設定します。 bound_claimsにトークンを許可する条件を書きます。sub Claimに対してワイルドカードを指定することで、特定のGitHubのレポジトリからのみのアクセスを許可します。

Secretの作成

テスト用のSecretを作成します。

vault secrets enable -path=kv/ kv-v2
vault kv put kv/cicd/message text='Hello World!' user='\@making'

GitHub Actions Workflowの作成

以下のようなWorklowを定義します。ここではVaultのURLであるVAULT_ADDRだけ、GitHubのSecretに保存しました。機密情報というより、ハードコードしたくなかっただけです。

exportTokentrueにすると、Vaultから払い出されたトークンが環境変数VAULT_TOKENに入ります(デフォルト: false)。後にトークンをRevokeする際に使用します。exportEnvtrueにするとVaultから取得したSecretが環境変数に入ります(デフォルト: true)。

name: retrieve-secret
on:
- push
- workflow_dispatch
jobs:
  retrieve-secret:
    runs-on: ubuntu-latest
    permissions:
      id-token: write
      contents: read
    steps:
    - name: Import Secrets
      id: secrets
      uses: hashicorp/vault-action@v2.4.3
      with:
        exportToken: true
        exportEnv: true
        method: jwt
        url: ${{ secrets.VAULT_ADDR }}
        role: cicd
        secrets: |
          kv/data/cicd/message text | MESSAGE_TEXT ;
          kv/data/cicd/message user | MESSAGE_USER
    - name: Use Secrets
      run: |
        echo "MESSAGE_TEXT: ${MESSAGE_TEXT}"
        echo "MESSAGE_USER: ${MESSAGE_USER}"
    - name: Revoke token
      if: always()
      run: |
        curl -X POST -s -H "X-Vault-Token: ${VAULT_TOKEN}" ${{ secrets.VAULT_ADDR }}/v1/auth/token/revoke-self

実際に試したGitHub Repoは https://github.com/making/test-oidc です。

image

これでGitHub ActionsでVaultからSecretが安全に取得できました。


✒️️ Edit  ⏰ History  🗑 Delete