日曜日, 9月 14, 2025
日曜日, 9月 14, 2025
- Advertisment -
ホームニューステックニュースghtkn でローカル開発用に GitHub Access Token をセキュアに生成して PAT から卒業する

ghtkn でローカル開発用に GitHub Access Token をセキュアに生成して PAT から卒業する



ローカル開発のために GitHub App からセキュアに User Access Token を生成する CLI である ghtkn を紹介します。

https://github.com/suzuki-shunsuke/ghtkn

https://github.com/suzuki-shunsuke/ghtkn-go-sdk

まとめ

  • ghtkn は Device Flow を用いて GitHub App から User Access Token を生成する CLI
  • セキュアなローカル開発を実現
    • No More Personal Access Token
    • Personal Access Token と違い短命 (8時間) な access token
    • GitHub App とユーザー両方が持ってる権限しか持たず、両方がアクセスできるリポジトリにしかアクセスできない
    • Secret manager を用いて access token を管理
      • プレインテキストや shell の環境変数に access token を露出しないため、流出リスクが低い
  • 複数の GitHub App を使い分けることが可能
  • Git Credential Helper としても利用可能
  • Go SDK によって Go Application にも組み込み可能

ghtkn とは

ghtkn は Device Flow を用いて GitHub App から User Access Token を生成する CLI です。

User Access Token では Installation Access Token と違い、 access token がユーザーに帰属するため、ユーザーとして操作を行うことができます。
ユーザーは ghtkn で生成した access token を用いて任意の処理を行うことができます。
ghtkn によって設定ファイルを用いて複数の GitHub App を管理したり、 Windows Credential Manager や macOS KeyChain, GNOME Keyring のような secret manager を用いて access token を管理することができます。

なぜ ghtkn が必要か

ghtkn を使うことで、ローカル開発における access token の流出リスクを最小化し、セキュリティを高めることができます。
GitHub CLI の OAuth App や Personal Access Token のような有効期限の長い access token を ローカルに保持していると流出時のリスクが大きいです。
ghatkn では Personal Access Token や GitHub App の Private Key や Client Secret のような機密性の高い secret は必要ありません。
必要なのは GitHub App の Client ID だけですし User Access Token の有効期限も 8 時間だけなので相対的に見て安全です。

Getting Started

  1. ghtkn をインストール
  2. GitHub App を作成
  • Enable Device Flow にチェックをつける
  • Webhook のチェックは外す
  • Homepage URL: https://github.com/suzuki-shunsuke/ghtkn (なんでもよい)
  • Only on this account
  • Permissions: なし (デフォルトのまま)
  • Repositories: なし (デフォルトのまま)
  1. ghtkn init で設定ファイルを生成し、修正
  • Windows: %APPDATA%\ghtkn\ghtkn.yaml
  • macOS, Linux: ${XDG_CONFIG_HOME:-${HOME}/.config}/ghtkn/ghtkn.yaml

ghtkn.yaml

apps:
  - name: suzuki-shunsuke/none 
    client_id: xxx 

この状態で ghtkn get を実行して access token を生成します。

するとブラウザで https://github.com/login/device が開くので、ターミナルに表示されたコードを入力し、承認します。
すると ghu_ で始まる access token が標準出力されます。
開いたタブは閉じて大丈夫です。

このようにブラウザを介した認可フローが必要なため、 CI のようなインタラクティブでない環境では ghtkn は使えません。
ghtkn は主にローカルでの開発を想定しています。

もう一度実行すると今度は認可フロー無しで直ぐに出力されます。
これは ghtkn が secret manager に access token を保存して再利用しているからです。

この access token を使ってあなたが管理する適当な public repository に gh issue create を実行してみましょう。

REPO=suzuki-shunsuke/ghtkn 
env GH_TOKEN=$(ghtkn get) gh issue create -R "$REPO" --title "Hello, ghtkn" --body "This is created by ghtkn"

すると権限不足で失敗します。

GraphQL: Resource not accessible by integration (createIssue)

GitHub App に issues:write 権限を付与して再び実行しましょう。また失敗するはずです。
GitHub App を対象のリポジトリに install して再び実行すると今度は成功するはずです。
Issue の作成者は App ではなくあなたになります。

User Access Token の権限 (Permissions と Repositories) は認可したユーザー (つまりあなた) と GitHub App が両方持つ権限になります。
そのため、上記のように GitHub App が許可されてない操作は出来ませんし、逆にユーザーが権限のない操作も出来ません。

ghtkn を使って任意のコマンドをラップする

ghtkn を使って access token を必要とする任意のコマンドの簡単なラッパー (シェル関数) を書けます。

gh コマンドのラッパー

gh() {
    env GH_TOKEN=$(ghtkn get) command gh "$@" 
}

こうして普通に gh コマンドを実行すれば、 access token が勝手に gh コマンドに渡されるようになります。

シェル関数の代わりにシェルスクリプトでも良いでしょう。
PATH 配下にコマンドと同じ名前でスクリプトを作って実行権限を付与します。

gh コマンドのラッパースクリプト

#!/usr/bin/env bash

set -eu

GH_TOKEN="$(ghtkn get)" 
export GH_TOKEN
exec /opt/homebrew/bin/gh "$@" 

aqua でインストールしている場合、絶対パスの代わりに aqua exec でも良いでしょう。

exec aqua exec -- gh "$@"

Git Credential Helper の設定

ghtkn を使って Git Credential Helper を定義します。
こうすると git push や pull の際に ghtkn の access token で認証するようになります。

  1. ghtkn helper を使用するように Git を設定
git config --global credential.helper '!ghtkn git-credential'

GitHub リポジトリに応じて GitHub App を切り替えたい場合:

  1. 設定ファイルで git_owner を設定

例えば以下のような設定をすると、 suzuki-shunsuke のリポジトリに push/pull する際に suzuki-shunsuke/write の GitHub App が使用されるようになります。

apps:
  - name: suzuki-shunsuke/write
    client_id: xxx
    git_owner: suzuki-shunsuke 

これは GHTKN_APP の設定より優先されます。
ただし、 git_owner は Git Credential Helper のための設定であり、 ghtkn get コマンドはこれを無視します。
git_owner はユニークでなければなりません。

  1. Git を設定

Git Credential Helper にリポジトリの情報が渡るようにこの設定をします。

git config credential.useHttpPath true

GitHub App を使い分ける

設定ファイルの apps に複数の GitHub App を設定し、 App の Owner (Organization や User) や権限ごとに App を作成して使い分けることができます。
デフォルトでは apps の最初の App が使われます。

コマンドの引数で App を指定できます。

ghtkn get suzuki-shunsuke/write

指定するのは設定ファイルで定義した App の name です。
name は自由に定義できますが、個人的には / というふうにすると分かりやすくて良いのではないかと思っています。

代わりに環境変数 GHTKN_APP でも指定できます。
例えば direnv を使って directory ごとに GHTKN_APP を切り替えると便利です。
自分の場合、 ~/repos/src/github.com/suzuki-shunsuke という directory 配下に https://github.com/suzuki-shunsuke のリポジトリを checkout してあるので、 ~/repos/src/github.com/suzuki-shunsuke に .envrc を配置します。

source_up

export GHTKN_APP=suzuki-shunsuke/write

同様に ~/repos/src/github.com/aquaproj にも .envrc を配置します。

source_up

export GHTKN_APP=aquaproj/write

デフォルトでは何の権限も持たない App が使われるようにしておきます。
何の権限も持たない access token に意味はないと思う人もいるかもしれませんが、 public repository を read するのには使えますし、 access token なしの場合と比べて API rate limit に引っかかりにくくなるので十分意味はあります。

apps:
  - name: suzuki-shunsuke/none
    client_id: xxx

これで作業ディレクトリによって access token を透過的に切り替えられます。
.envrc に書くのは access token ではなく GHTKN_APP であり、これは secret でもなんでもないので安全です。

Access Token の再生成

ghtkn は生成した access token とその有効期限を secret manager に保存します。
ghtkn get はこれらを取得し、有効期限が切れている場合 access token を Device Flow によって生成し直します。
access token の有効期限は 8 時間です。

デフォルトでは access token の期限が切れていない場合それを返しますが、その場合短命な access token が返ってくる可能性があります。
-min-expiration (-m) を指定すると、 access token の有効期限が指定した有効期限より短い場合に access token を再生成します。

有効期限が 1 時間より短かったら再生成

ghtkn get -m 1h

2h, 30m, 30s なども有効です。単位は必要です。

環境変数でも設定できます。

export GHTKN_MIN_EXPIRATION=10m

GitHub CLI で API を叩くだけなら基本一瞬で終わるので設定はほぼ不要だと思いますが、例えば 30 分くらいかかるスクリプトに access token を渡したい場合は 50m とか設定しておくとスクリプトの途中で expire しないですみます。

ちなみに 8h 以上を指定すれば ghtkn が access token を再生成する挙動を再現できます。
ghtkn の挙動を検証したい際には使えるかもしれません。

会社の Organization で ghtkn を使いたい場合

ghtkn では GitHub App が必要ですが、会社の GitHub Organization にユーザーごとに GitHub App を作るのは一定以上の規模の開発組織では非現実的です。
そこで共有の GitHub App を作り、 Client ID を社内で共有することになると思います。
User Access Token はそのユーザーが持っている権限以上の access token は生成できず、また他人になりすますことも出来ません。
API の rate limit もユーザーごとです。
そのため、社内という限られた空間で共有してもリスクは低いのではないかと思っています。

企業からすると企業の Organization にアクセス可能な開発者の PAT や GitHub CLI の OAuth App の access token が流出するのを防ぐことができます。
万が一 Client ID が社外に流出しても企業の Organization に直接アクセスできるわけではないですし、 access token が流出しても有効期限が短いのでリスクを最小限にできます。

SDK による Go Application への組み込み

ghtkn の Go SDK を使うことで Access Token を必要とする Application で ghtkn を用いて access token を取得できるようになります。
SDK なので ghtkn CLI には依存しませんが、 secret manager や GitHub App, ghtkn の設定ファイルは当然必要です。
oauth2.TokenSource の実装も提供しているので、非常に簡単に組み込めます。
aqua への組み込みも既にやってますが非常に簡単でした。

aqua の場合、環境変数 AQUA_GHTKN_ENABLED=true を設定するだけです。
ただし、環境変数 GITHUB_TOKENAQUA_GITHUB_TOKEN AQUA_KEYRING_ENABLED などが設定されている場合はそちらが優先されます。

export AQUA_GHTKN_ENABLED=true

ghtkn の不便な点

自分が管理していない User や Organization に対して write できない

GitHub App の User Access Token の欠点として App がインストールされていないリポジトリに対して write が出来ません。
そのため、自分の GitHub App がインストールされていない他人の OSS に gh pr create で PR の作成をしたりすることができません。
gh pr create では --web でブラウザを開くまでにしておけば、スクリプトでまとめて PR を作成するとかでなければなんとかなります。
このように多少制約があります。

さいごに

以上、ローカル開発のために GitHub App からセキュアに User Access Token を生成する CLI である ghtkn を紹介しました。

https://github.com/suzuki-shunsuke/ghtkn

https://github.com/suzuki-shunsuke/ghtkn-go-sdk

ghtkn を使って、流出時のリスクが高い PAT や GitHub CLI の OAuth access token の利用、煩雑な PAT の管理をやめてみませんか?



Source link

Views: 0

RELATED ARTICLES

返事を書く

あなたのコメントを入力してください。
ここにあなたの名前を入力してください

- Advertisment -