npm公開鍵を置かない、OIDC移行後にトークンも止める

|著者: QUASA編集チーム|2 分で読めます
npm公開鍵を置かない、OIDC移行後にトークンも止める

npmパッケージをGitHub Actionsから長期の公開トークンなしでリリースするには、npmに公開元のワークフローを登録し、公開ジョブにOIDC権限を与える。npmのTrusted Publishing手順に沿って旧トークンを渡さず初回公開を成功させ、その後に従来のトークン公開を禁止する。

信頼設定を保存しただけでは、既存の公開トークンは使える状態にある。一方、OIDCでの公開を試す前にトークンを遮断すると、設定の食い違いが見つかったときにリリースを止めてしまう。非公開依存関係がある場合は、インストール用の読み取り認証を公開用の認証から分ける。

対象パッケージと実行環境を確認する

以下は、既存のnpmパッケージをGitHub ActionsのGitHubホストランナーから直接公開する手順だ。npmが対応を案内しているのは、このランナーのほか、GitLab.comの共有ランナーとCircleCI cloudであり、セルフホストランナーは対象外となる。公開ジョブが実際にどのランナーで動くかを、設定を始める前に確かめる。

OIDC公開にはnpm CLI 11.5.1以上とNode.js 22.14.0以上が必要だ。公開元をコマンドで登録する場合は条件が別にあり、npm trustの仕様はnpm 11.15.0以上、対象パッケージへの書き込み権限、アカウントの二要素認証、レジストリに存在するパッケージを必要条件としている。手元で登録に使うCLIと、CIで公開に使うCLIの両方を確認する。

まだnpmレジストリに存在しないパッケージは、通常の認証で初版を公開してから信頼設定を追加する。移行対象が既存パッケージなら、次の未公開バージョンをOIDCの初回確認に使える。どちらの場合も、package.jsonのパッケージ名と公開先を先に確定させておくと、認証エラーとパッケージ設定の問題を切り分けやすい。

npmに公開元のワークフローを登録する

npmパッケージに、GitHub Actionsの特定の公開ワークフローを信頼できる公開元として登録する関係

対象パッケージのnpm設定でTrusted Publisherを開き、GitHub Actionsを選ぶ。GitHubのユーザー名または組織名、リポジトリ名、公開用ワークフローのファイル名を入力する。ワークフローが.github/workflows/publish.ymlなら、入力するのはpublish.ymlだけだ。拡張子を含め、実際のファイル名と一致させる。

GitHub Environmentで承認を設けている場合は、その環境名も登録する。今回のようにCIからnpm publishを直接実行するなら、許可する操作にnpm publishを含める。段階的な公開を選ぶ設定とは権限が異なるため、公開元を登録しただけで直接公開まで許可されたと考えず、操作の選択も確認する。

CLIから登録するなら、仮のパッケージ名とリポジトリを使った例は「npm trust github @scope/pkg --file publish.yml --repo owner/repo --allow-publish」となる。@scope/pkg、publish.yml、owner/repoを実際の値に置き換える。登録内容は「npm trust list @scope/pkg」で確認できるが、npmは保存時点ではGitHub上のワークフローとの一致を検証しない。設定後の公開で初めて分かる誤記がある。

公開ジョブにOIDC権限を与え、認証を分ける

GitHub Actionsで依存関係をインストールした後、公開用の長期トークンを渡さずnpmパッケージを公開する流れ

GitHub Actionsの公開ジョブには「permissions:」で「id-token: write」と「contents: read」を指定し、GitHubホストランナーで実行する。前者はGitHub ActionsがOIDCトークンを発行するための権限だ。actions/setup-nodeでnpmレジストリと対応するNode.jsを設定し、依存関係のインストール、必要なビルドとテストを経てnpm publishを実行する。

公開ステップには、以前の公開用シークレットをNODE_AUTH_TOKENとして渡さない。npm CLIは対応するOIDC環境を検出すると、その認証を使って公開するが、従来のトークン認証へ戻る経路もある。移行の成否を確かめるリリースで旧トークンをジョブ全体に渡したままだと、公開が成功してもOIDCで成功したとは判断しにくい。

非公開のnpmパッケージを依存関係として取得するなら、読み取り専用のGranular Access Tokenを用意し、npm ciのステップだけにNODE_AUTH_TOKENとして渡す。npm publishのステップにはその環境変数を渡さない。OIDCが置き換えるのは公開時の認証であり、非公開パッケージをインストールするための権限ではない。

読み取り用トークンの対象は、インストールに必要なパッケージやスコープに絞り、公開権限を付けない。npm ciが認証エラーになる場合は、Trusted Publisherの登録を変更する前に、このトークンが対象の依存関係を読めるかを見る。逆にnpm ciが通ってnpm publishだけ失敗するなら、公開元の一致とOIDC権限を調べる。

旧トークンなしの初回公開を通す

新しいTrusted Publisher設定は、作成から2日以内に最初の公開を成功させる必要がある。成功すると設定が検証され、リポジトリの変更されない識別情報に結び付く。期限までに成功しなかった設定は失効するため、削除して作り直してから公開をやり直す。

ワークフローを実行し、公開用の旧トークンを渡していない状態で新しいバージョンが公開されたことを確認する。認証エラーなら、登録したリポジトリ、ワークフロー名の大文字小文字と拡張子、ジョブのid-token: write、ランナーの種類を照合する。package.jsonのrepository.urlも、公開元として使うGitHubリポジトリと正確に一致している必要がある。

再利用可能なワークフローを呼び出して公開する構成では、npmが呼び出し元のワークフロー名を照合する場合がある。親子両方のワークフローにid-token: writeが必要になる点も、単一の公開ジョブとの違いだ。なお、npm whoamiはTrusted Publishingの公開権限を調べる操作ではないため、判定には実際の公開結果を使う。

従来のトークン公開を禁止し、不要なトークンを失効させる

npmパッケージで従来のトークン公開を禁止し、GitHub ActionsからのOIDC公開を続ける状態

OIDCでの初回公開が成功したら、対象パッケージのSettingsからPublishing accessを開き、「Require two-factor authentication and disallow tokens」を選んで保存する。この設定は従来のトークンによる公開を禁止する一方、Trusted PublisherからのOIDC公開は引き続き利用できる。公開元の登録だけで残っていた旧経路を、ここで閉じる。

次に、GitHubのリポジトリや組織のSecretsから、不要になった公開用シークレットへの参照を取り除く。参照の削除だけではトークン自体は失効しない。npmのトークン失効手順に従い、WebのAccess Tokens画面で削除するか、npm token listで完全なIDを確認してnpm token deleteで削除する。失効後は再び一覧を見て、対象のトークンが残っていないことを確かめる。

非公開依存関係の取得に使う読み取り専用トークンは、旧公開トークンと取り違えて削除しないよう、用途とアクセス範囲を確認する。公開ステップからはトークンを外し、インストールのステップにだけ必要な読み取り認証を残すことで、次のリリースでも同じ認証経路を使える。

関連記事:

共有:

ニュースレターを購読

Web3、AI、暗号資産の最新ニュースを受信箱にお届けします。

0