---
title: GitHubのOpen ID Connectを使ってGitHub ActionsからHashiCorp Vaultに安全にアクセスするメモ
tags: ["Vault", "OIDC", "GitHub Actions"]
categories: ["Dev", "SecretManagement", "Vault"]
date: 2023-01-09T07:00:13Z
updated: 2023-01-11T03:04:32Z
---

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

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

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

* https://docs.github.com/en/actions/deployment/security-hardening-your-deployments/configuring-openid-connect-in-hashicorp-vault
* (日本語版) https://docs.github.com/ja/actions/deployment/security-hardening-your-deployments/configuring-openid-connect-in-hashicorp-vault
* https://github.com/hashicorp/vault-action


前提として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](https://developer.hashicorp.com/vault/docs/auth/jwt)を有効にし、トークンの検証方式として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/*"
    ]
  },
  "bound_audiences": [
    "https://github.com/making",
    "https://github.com/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に保存しました。機密情報というより、ハードコードしたくなかっただけです。

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

```yaml
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 です。

<img width="1024" alt="image" src="https://user-images.githubusercontent.com/106908/211255041-33676b9f-318f-4dae-841e-a32223de2855.png">

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