Personal Access Token の管理

library(gh)

gh は通常、PAT (Personal Access Token) をリクエストとともに送信します。 GitHub APIの一部のエンドポイントは、認証なしでアクセスできます。 しかし、APIを頻繁に利用するようになると、レート制限の問題を防ぎ、可能な限りのエンドポイントにアクセスするために PAT が必要になります。

この記事では、PAT を保存して gh が (ほとんどの場合、自動的に) それを見つけられるようにする方法について説明します。ghがこのために使用する関数は、gh_token()です。

PATの管理に関するその他のリソース

PATとホスト

gh::gh()では、.tokenという引数で PAT を指定したり、.api_url` という引数で “github.com” 以外のホストを指定することができます。 (企業や大学によっては、独自にGitHub Enterpriseのインスタンスを運用しているところもあります。)

gh(endpoint, ..., .token = NULL, ..., .api_url = NULL, ...)

しかし、常にPATやホストを提供するのは煩わしいですし、PATがRコードに明示的に表示されるのは安全ではありません。 ユーザーがPATやAPIのURLを直接指定できるようにすることは重要ですが、それが必要になることはほとんどないはずです。 gh::gh() は、より安全で、より面倒でない方法で目的のものを表現できるように設計されています。

ユーザーが .api_url.token を提供しなかった場合、どのようにしてそれらを決定するのですか?

  1. .api_url のデフォルトは環境変数 GITHUB_API_URL の値です。 環境変数の値をデフォルトとし、それが設定されていない場合は、"https://api.github.com"にフォールバックします。 これはPATを気にする前に常に行われます。
  2. PATは、gh_token(.api_url) の呼び出しによって得られます。つまり、トークン はホストに基づいて検索されます。

gitcreds パッケージ

gh は gitcreds パッケージを使って Git のクレデンシャルストアと連携するようになりました。

gh は URL を指定して gitcreds::gitcreds_get() を呼び出し、一致する PAT を探そうとします。 gitcreds::gitcreds_get()は、セッションの環境変数をチェックし、次にローカルのGitクレデンシャル・ストアをチェックします。 そのため、コマンドラインのGitなどで以前にPATを使用したことがある場合には、ghがそのPATを取得して再利用することができます。 特定の URL に対して何が見つかったかを確認したい場合には、自分で直接gitcreds::gitcreds_get()` を呼び出すことができます。

gitcreds::gitcreds_get()

If you see something like this:

#> <gitcreds>
#>   protocol: https
#>   host    : github.com
#>   username: PersonalAccessToken
#>   password: <-- hidden -->

ということは、gitcreds は Git のクレデンシャルストアから PAT を取得できるということです。 実際のPATを見るには、gitcreds_get()$passwordを呼び出します。

一致するPATが見つからない場合は、gitcreds::gitcreds_get()のエラーになります。

環境変数でのPAT

Gitをインストールしていない場合や、Gitをインストールしてもクレデンシャルストアが動作しない場合は、PATを環境変数で指定することができます。 github.com」の場合は、「GITHUB_PAT_GITHUB_COM」または「GITHUB_PAT」という変数を設定します。 GitHub のホストが異なる場合は、API の URL を指定して gitcreds::gitcreds_cache_envvar() をコールすると、設定する必要のある環境変数がわかります。 たとえば、以下のようになります。:

gitcreds::gitcreds_cache_envvar("https://github.acme.com")
#> [1] "GITHUB_PAT_GITHUB_ACME_COM"

推奨事項

インタラクティブな開発に使用するマシンでは、以下を推奨します。

CI/CDプラットフォームのようなヘッドレスシステムでは、セキュアな環境変数を介して必要なPATを提供します。 通常の環境変数は、APIホストのような機密性の低い設定に使用できます。 すべての環境変数をログファイルにダンプするような愚かなことをして、PATを公開してはいけません。

なお、GitHub Actionsでは、個人のアクセストークンがGITHUB_TOKENというシークレットとしてワークフローで自動的に利用可能になっています。 これが、Rコミュニティの多くのワークフローにこのスニペットが含まれている理由です。:

env:
  GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }}

これにより、自動PATが環境変数GITHUB_PATとして利用できるようになります。 そのPATが適切なパーミッションを持っていない場合は、パーミッションを持つPATを明示的に用意する必要があります(詳細は上記リンクを参照)。

失敗

必要なPATがない場合、gh::gh()はトークンのないリクエストを送信します。 (内部的には、PAT が空文字列 "" であることが判明した場合には Authorization ヘッダが省略されます)

PAT関連の失敗はどのようなものか?

PATが送信されず、エンドポイントが認証を必要としない場合、リクエストはおそらく成功します。 少なくとも、レートの制限にぶつかるまでは。 エンドポイントが認証を必要とする場合は、HTTPエラーが発生します。:

GitHub API error (401): 401 Unauthorized
Message: Requires authentication

環境変数の中にPATが最初に発見された場合、それは額面通りに受け取られます。 ここで最も一般的な方法は、.Renviron によるPATの指定と、GitHub ActionsのようなCI/CDプラットフォームのシークレットとしてのPATです。 PATが無効な場合、影響を受ける最初のリクエストはおそらく次のように失敗します。:

GitHub API error (401): 401 Unauthorized
Message: Bad credentials

これは、無効なPATが .token を介して直接提供された場合にも起こります。

有効なPATであっても、特定のリクエストに対するスコープが不十分であれば、下流工程でエラーになる可能性があります。