GitHub ActionsワークロードでOpenPubkeyを使用する方法

この記事は、 BastionZero の CTO である Ethan Heilman 氏の寄稿によるものです。

OpenPubkey は、OpenID Connect (OIDC) を使用する ID プロバイダーとの標準的なシングル サインオン (SSO) 対話に公開キーを追加するための Web の新しいテクノロジです。 OpenPubkeyは、基本的にIDプロバイダーを認証局(CA)に変えることで機能し、認証局(CA)は、IDを暗号化公開鍵に暗号的にバインドする証明書を発行する信頼できるエンティティです。 OpenPubkeyを使用すると、OIDCを話すIDプロバイダーは、現在公開鍵をIDにバインドできます。

OpenPubkeyは、 BastionZero、Docker、Linux Foundationのコラボレーションにより、新たにオープンソース化されました。 ぜひお試しいただき、貢献していただき、独自のユースケースを構築していただきたいと思います。 GitHub の OpenPubkey リポジトリを確認できます。

この記事では、OpenPubkey を使用して公開キーをワークロード ID にバインドする方法を紹介します。 GitHub Actionsのワークロードは、OpenPubkeyオープンソースプロジェクトで現在サポートされているものであるため、ここでは集中的に説明します。 また、DockerがGitHub ActionsでOpenPubkeyを使用して、Docker公式イメージにサインインして 認証を行い、サプライチェーンのセキュリティを向上させる方法についても簡単に説明します。 

水色の背景に濃い青のテキストが docker ロゴ付きの openpubkey を読み取っています

IDトークンとは?

始める前に、OpenID Connect プロトコルを確認しましょう。 OIDC を話す ID プロバイダーは、通常 OpenID プロバイダーと呼ばれますが、この記事では単に OP と呼びます。 

OIDC には、ID トークンと呼ばれる重要な成果物があります。 ユーザーは、OP へのシングル・サインオンの完了後に ID トークンを取得します。 その後、ID トークンをサード・パーティー・サービスに提示して、OP によって適切に認証されたことを証明できます。  

ID トークンには、ユーザーの ID (E メール・アドレスなど) が含まれ、OP によって暗号で署名されます。 サード・パーティー・サービスは、OPのJSON Web Key Set (JWKS)エンドポイントを問い合せ、OPの公開鍵を取得してから、OPの公開鍵を使用してIDトークンの署名を検証することで、IDトークンを検証できます。 OPの公開鍵は、OPによってホストされているJWKSエンドポイントを問い合せることによって使用できます。 

GitHub ActionsはどのようにしてIDトークンを取得しますか? 

ここまでは、人間のアイデンティティ(メールアドレスなど)と、それらがIDトークンでどのように使用されるかについて説明してきました。 ただし、この記事ではワークロード ID に焦点を当てています。 Actionsには、GitHub ActionsにIDトークンを割り当てるための優れた方法があることがわかりました。   

その仕組みはこうです。 GitHub は OpenID プロバイダーを実行します。 新しいGitHub Actionがスピンアップされると、GitHubはまず新しいAPIキーとシークレットを割り当てます。 その後、GitHub アクションは、その API キーとシークレットを使用して、GitHub の OP に対して認証できます。 GitHub の OP は、この API キーとシークレットを検証し (新しい GitHub Action に割り当てられたことがわかっているため)、GitHub Action に OIDC ID トークンを提供できます。 このGitHub Actionは、このIDトークンを使用して、サードパーティサービスに対して自身を識別できるようになりました。

GitHub の OP を操作するとき、Docker は ID トークン内の要求を job_workflow_ref ワークフローの "ID" として使用します。 このクレームは、GitHub Actionがビルドされたファイルの場所を識別するため、検証者はワークフローを生成したファイルを識別し、ワークフロー自体の有効性を理解して確認することもできます。 要求の設定方法の例を次に示します。

job_workflow_ref = octo-org/octo-automation/.github/workflows/oidc.yml@refs/heads/main

GitHub の OP によって発行された ID トークン内の他の要求は、他のユース ケースで役立つ場合があります。 たとえば、 または ActorIDというActorフィールドがあり、これは GitHub Action を開始した人の ID です。これは、ワークロードが特定のユーザーによって開始されたことを確認するのに役立ちます。 (ワークロードが自動化されたプロセスによって開始された場合はあまり役に立ちません)。

GitHub の OP は、ID トークンの他の多くの便利なフィールドをサポートしています。 詳細については、 GitHub OIDC のドキュメントを参照してください。

ワークロードの PK トークンの作成

GitHub の OP を使用してワークロードを識別する方法を確認したので、OpenPubkey を使用してそのワークロード ID を公開キーにバインドする方法を見ていきます。 OpenPubKeyは、PKトークンと呼ばれる暗号化オブジェクトを使用してこれを行います。 

このプロセスがどのように機能するかを理解するために、GitHub の OP が OIDC プロトコルをどのように実装しているかを見てみましょう。 GitHub の OP によって生成された ID トークンには、 というaudienceフィールドがあります重要なのは、ワークロード ID のユーザー ID とは異なり、この audience フィールドは ID トークンを要求する OIDC クライアントによって選択されることです。 GitHub の OP が ID トークンを作成するとき、OP が ID トークンを作成するときに署名する他のフィールド ( job_workflow_refactorなど) とともに が含まれますaudience

そのため、OpenPubkey では、GitHub Action ワークロードは、最初に新しい公開鍵と秘密鍵のペアを生成する OpenPubkey クライアントを実行します。 次に、ワークロードが OIDC を使用して GitHub の OP に対して認証を行うと、ワークロードの公開キーの暗号化ハッシュとランダムなノイズと等しいフィールドが設定 audience されます。 

これで、ID トークンには、ワークロードの ID ( job_workflow_ref フィールドとその他の関連フィールド) とワークロードの公開キーのハッシュに関する GitHub OP の署名が含まれるようになりました。 これは、GitHubのOPにワークロードのIDと公開鍵をバインドさせるために必要なものの大部分です。

実際、PK トークンは JSON Web 署名 (JWS) であり、大まかに次の要素で構成されます。

  • ワークロードの公開キーのハッシュを含むフィールドを含む audience ID トークン。
  • ワークロードの公開キー。
  • ワークロードの公開キーのハッシュを計算するために使用されるランダムノイズ。
  • ワークロードの公開キーの下にある、PK トークン内のすべての情報の署名。 (この署名は、PK トークンで証明されたユーザー所有の秘密署名キーにユーザーがアクセスできるという暗号証明として機能します。

その後、PK トークンは、OIDC を使用して JWKS 側から GitHub OP の公開キーを取得する任意の OpenPubkey 検証者に提示できます。 次に、検証者は GitHub OP 公開キーを使用して ID トークンを検証し、ワークロードの公開キーを使用して PK トークン内の他のフィールドを検証します。 これで、検証者はワークロードの公開キー (ID トークン内のフィールドまたは他のフィールド job_workflow_ref によって識別される) を認識し、この公開キーを任意の暗号化に使用できます。

OpenPubkeyでエフェメラルキーを使用できますか?

はい! エフェメラルキーは、短期間だけ使用されるキーです。 エフェメラルキーは、秘密キーを長期間管理する必要がないため便利です。不要になったら削除できるため、セキュリティが向上し、運用上のオーバーヘッドが削減されます。

OpenPubkeyでこれを行う方法は次のとおりです。 公開鍵と秘密鍵のペアを選択し、OP に対して認証して公開鍵の PK トークンを取得し、秘密鍵を使用してオブジェクトに署名し、最後に秘密鍵を破棄します。   

1 回限りの PK トークン 

これをさらに一歩進めて、PK トークンが 1 つの署名付きオブジェクトにのみ関連付けられるようにすることができます。 その仕組みはこうです。 まず、署名するオブジェクトのハッシュを取得します。 次に、ワークロードが GitHub の OP に対して認証されるときに、要求を audience 次の項目の暗号化ハッシュと等しくなるように設定します。

  • 公開鍵 
  • 署名するオブジェクトのハッシュ
  • ランダムなノイズ

最後に、OpenPubkey 検証ツールは、署名されたオブジェクトとその 1 回限りの PK トークンを取得し、署名されたオブジェクトのハッシュが要求に含まれていることをさらに確認して PK トークンを検証します audience 。 これで、1 回限りの PK トークンができました。 OpenPubkey のこの機能の詳細については、リポジトリを参照してください

DockerはOpenPubkeyを使用してDocker公式イメージに署名する方法を教えてください。

Dockerは、GitHub ActionsワークロードでOpenPubkeyを使用して、Docker公式イメージの認証にサインイン します 。 Docker公式イメージは、GitHub Actionワークロードを使用して作成されます。 ワークロードは、新しいエフェメラルの公開キーと秘密キーのペアを作成し、OpenPubkey を介して公開キーの PK トークンを取得し、最後に秘密キーを使用してイメージの構成証明に署名します。  

その後、秘密キーが削除され、イメージ、その署名、および PK トークンが Docker Hub コンテナー レジストリで使用できるようになります。 このアプローチは、署名者が秘密鍵を維持または保存する必要がないため、優れています。

Dockerのコンテナ署名のユースケースは、別のLinux Foundationのオープンソースプロジェクトである The Update Framework(TUF)にも大きく依存しています。 その仕組みの詳細については、「OpenPubkeyを使用してDocker公式イメージに署名する」をお読みください。

OpenPubkeyとGitHub Actionsのワークロードで他に何ができますか?

OpenPubkeyとGitHub Actionsをうまく活用する方法について、次のアイデアを確認してください。

ワンタイムキーを使用したプライベート成果物への署名 

プライベートリポジトリに保存される成果物に署名することを検討してください。 OpenPubkeyは、GitHub Actionに1回限りのキーを使ってアーティファクトに暗号署名させたい場合に使えます。 このアプローチの良いところは、パブリックリポジトリや透明性ログで情報を公開する必要がないことです。 代わりに、アーティファクト、その署名、およびその PK トークンをプライベート リポジトリに投稿する必要があります。 この機能は、プライベート コード リポジトリや内部ビルド システムで、何が、誰によって、いつ、どのくらいの頻度でビルドされているかを世界に公開したくない場合に役立ちます。 

関連する場合は、and actor-ID 要求を使用してactor、特定の成果物を構築する人間を署名された成果物自体にバインドすることも検討できます。 

ワークロード間の通信の認証

あるワークロード (Bob と呼ぶ) で、別のワークロード (Alice と呼ぶ) によって作成されたアーティファクトを処理するとします。 Alice ワークロードが GitHub Action の場合、Alice ワークロードが作成するアーティファクトは OpenPubkey を使用して署名され、Bob ワークロードに渡され、Bob ワークロードは OpenPubkey ベリファイアを使用して GitHub OP の公開キー (GitHub OP の JWKS URL から取得) を使用して検証します。 このアプローチは、複数ステージの CI/CD プロセスで役立つ場合があります。

そして、他のものも! 

これらは単なるストローマンのアイデアです。 この記事の要点は、OpenPubkeyを試し、貢献し、独自のユースケースを構築することです。

その他、技術的な課題も考慮する必要があります

まとめる前に、いくつかの技術的な質問について話し合う必要があります。

IDトークンは非公開のままであるべきではありませんか?

OpenPubkeyのアプリケーションでは、IDトークンがPKトークン内で広く公開されているので心配かもしれません。 たとえば、Docker 公式イメージ署名のユースケースでは、PK トークンは Docker Hub コンテナー レジストリで一般に公開されます。 IDトークンが広く公開されると、IDトークンが再生され、他のサービスへの不正アクセスに使用されるリスクがあります。  

このため、PK トークンが一般に広く公開されているアプリケーション用に、わずかに異なる PK トークンがあります。 

これらのアプリケーションの場合、OpenPubkey は PK トークンをインクルードする前に ID トークンから OP の署名を取り除きます。 OPの署名は、RSA署名(「GQ署名」とも呼ばれる)のGuillou-Quisquater(GQ)非対話型知識証明に置き換えられます。 現在、OPの署名が削除されているため、IDトークンを他のサービスに対して再生することはできませんが、OPのRSA署名のセキュリティはGQ署名によって維持されます。   

そのため、PK トークンを広く一般に公開する必要があるアプリケーションでは、PK トークンは JSON Web 署名であり、次の要素で構成されます。

  • OPの署名 を除いた IDトークン
  • ID トークンの GQ 署名
  • ユーザーの公開鍵
  • ユーザーの公開鍵のハッシュを計算するために使用されるランダムノイズ
  • ユーザーの公開鍵の下で、PK トークン内のすべての情報の署名 

GQ署名により、クライアントは、OPの署名を明らかにすることなく、IDトークンがOPによって有効に署名されたことを証明できます。 OpenPubkeyクライアントは、クライアントがIDトークン上のOPの署名を知っていることを暗号的に証明するためにGQ署名を生成しますが、OPの署名は秘密に保ちます。 GQ 署名は RSA でのみ機能しますが、 すべての OpenID Connect プロバイダーが RSA をサポートする必要があるため、これは問題ありません。

GQ 署名は通常の署名よりも大きく、低速であるため、PK トークンを広く一般に公開する必要があるユースケースでのみ使用することをお勧めします。 BastionZeroインフラストラクチャアクセスのユースケース では、PKトークンを公開する必要がないため、GQ署名を使用しません。 代わりに、ユーザーはアクセスするターゲット (サーバー、コンテナー、クラスター、データベースなど) にのみ PK トークンを公開します。これは、ID トークンが通常 OpenID Connect で公開されるのと同じ方法です。   

GQ 署名は、ワークロード間の通信を認証するときには必要ない場合があります。Alice ワークロードが署名付きアーティファクトとその PK トークンを Bob ワークロードのみに渡す場合、PK トークンは一般に広く公開されているため、問題はあまりありません。

OPがOpenID Connectキーをローテーションするとどうなりますか? 

OP には、時間の経過とともに (たとえば、2 週間ごとに) 変更される OpenID Connect 署名キーがあります。 OP が PK トークンに署名した OpenID Connect キーをローテーションした後、PK トークンを使用する必要がある場合はどうなりますか? 

一部のユースケースでは、通常、PKトークンの有効期間が短くなります。 たとえば、 BastionZeroのインフラストラクチャアクセスのユースケースでは、PKトークンは24時間以上使用されません。 このユースケースでは、(1)ユーザーがIdPに対して再認証を行い、IdPがキーをローテーションするたびに新しいPKトークンを作成し、(2)IDトークンの有効期限が切れるたびに、クライアントがPKトークンとともに有効なOIDC更新トークンを持っていることをOpenPubkey検証ツールがチェックすることで、これらのタイミングの問題が解決されます。

一部のユースケースでは、PKトークンの寿命が長いため、OPがOpenID Connectキーをローテーションすることを心配する必要があります。 Dockerの構成証明署名のユースケースでは、この問題は、TUFにOPの署名キーの履歴ログを追加で保存することで解決されます。OP公開鍵のヒストリカル・ログは、有効期限が切れた後に使用するために、誰でも保持できます。 実際、OPがこの履歴ログを自分で保持する未来を思い描いています。 

今回はここまでです。 GitHub の OpenPubkey リポジトリを確認できます。ぜひプロジェクトに参加して、貢献し、OpenPubkeyが役立つ可能性のある他のユースケースを特定してください。

さらに詳しく