New Relicでは、インシデント対応やインフラストラクチャ管理の自動化をする Workflow Automation という機能を提供しています。この Workflow Automation の中には、JSON Web Token(JWT)を生成するための アクション が用意されています。
外部サービスの中には、APIを呼び出す前にJWTによる認証を求めるものがあります。GitHub App もそのひとつで、APIを利用するにはまずJWTを生成し、それを使って一時的なアクセストークンを取得する、という手順を踏む必要があります。
本記事では、この Auth JWT actions の Create a JSON Web Token を使って、GitHub App による Issue の作成を実際に行っていきます。それでは、順番にみていきましょう。
事前準備1: GitHub Appの作成とインストール
まず、Issueを作成するためのGitHub Appを用意します。下記のドキュメントを参考に、Issue の Read/Write 権限を持ったGitHub Appを作成します。
作成後、そのGitHub Appを任意のOrganizationまたはユーザーにインストールし、対象のリポジトリに対してIssueを作成できる状態にしておきます。 この後の手順で、以下の3つの値を利用しますので、あわせて控えておきます。
- App ID(GitHub Appの設定画面で確認できます)
- 秘密鍵(GitHub Appの設定画面から生成・ダウンロードします)
- Installation ID(Appをインストールした際のURL、またはGitHubのAPIから取得できます)
事前準備2: 秘密鍵をNew Relicのシークレットに登録
次に、JWT認証で必要となる秘密鍵をNew RelicのSecrets Management Serviceに登録します。
シークレットの登録に、今回はNerdGraphのsecretsManagementCreateSecretを使用します。
詳細については、下記のドキュメントを参照してください。
- NerdGraphによるシークレット管理: https://docs.newrelic.com/docs/apis/nerdgraph/examples/nerdgraph-api-secret-management-service/
また、秘密鍵は1行の文字列としてシークレットに保存する必要があります。ダウンロードした秘密鍵ファイルには改行が含まれているため、改行を \n に置き換えて1行の文字列に整形してから保存します。
登録したシークレットは、ワークフロー内から ${{ :secrets:ネームスペース:キー名 }} の形式で参照します。
ワークフローの作成
事前準備が整ったら、ワークフローを作成していきます。今回は次の3つのアクションを順番につなげます。
- Auth JWT アクションでJWTを生成する
- HTTPアクションで、JWTから一時的なアクセストークンを発行する
- HTTPアクションで、そのトークンを使ってIssueを作成する
では、実際に1つずつ設定していきます。
1. JWTの生成(Auth JWT アクション)
まず、Auth JWT アクションでJWTを生成します。GitHub AppのJWTを生成する際に要求されるパラメータは、下記のドキュメントにあるとおり、alg(アルゴリズム)、iat(発行時刻)、exp(有効期限)、iss(発行者)です。
- GitHub AppのJWTの生成: https://docs.github.com/ja/apps/creating-github-apps/authenticating-with-a-github-app/generating-a-json-web-token-jwt-for-a-github-app
Workflow Automation の Auth JWT アクションでは、これらをUI上でそれぞれ指定できます。今回は次のように設定します。
algorithm:RS256を指定します。GitHub App は RS256 での署名を要求します。privateKey: 事前準備2で登録した秘密鍵を指定します。- 例。
${{:secrets:github:nhashigithubappsecret}}
- 例。
includeIssuedAt:trueを指定します。これによりiat(発行時刻)が自動で付与されます。expirationTimeMinutes: exp(有効期限)を分単位で指定します。GitHub App のJWTは最大10分までのため、ここでは5としています。Claims:issに App ID を指定します。これがJWTの発行者を表します。
このアクションが成功すると、出力として jwt に生成されたJWT文字列が格納されます。次のアクションでこの値を参照します。
2. アクセストークンの発行(HTTPアクション)
次に、生成したJWTを元に一時的なアクセストークンを発行します。GitHub App では、JWTそのものでIssueを作成するのではなく、JWTを使ってインストールアクセストークンを取得し、そのトークンでAPIを呼び出す流れになります。
- インストールアクセストークンの生成: https://docs.github.com/ja/apps/creating-github-apps/authenticating-with-a-github-app/generating-an-installation-access-token-for-a-github-app
ここでは Workflow AutomationのHTTPアクション(POST)を使います。設定内容は次のとおりです。
- リクエスト先URL:
https://api.github.com/app/installations/{Installation ID}/access_tokens - ヘッダー
Authorization:Bearerに続けて、前のアクションで生成したJWTを参照します。- 例。
Bearer ${{ .steps.auth_jwt_create_1.outputs.jwt }}
- 例。
- ヘッダー
Accept:application/vnd.github+jsonを指定します。
レスポンスのボディには発行されたトークンが含まれます。そのままでは後続で扱いにくいため、セレクター(selectors)を使って必要な値だけを抽出します。ここではレスポンスボディをJSONとして解釈し、token フィールドを取り出して、次のアクションから参照できる名前を付けておきます。
3. Issueの作成(HTTPアクション)
その後、抽出したアクセストークンを元にIssueの発行を行います。ここでもう一度 HTTPアクション(POST)を使い、GitHubのREST APIを呼び出します。
設定内容は次のとおりです。
- リクエスト先URL:
https://api.github.com/repos/{owner}/{repo}/issues - ヘッダー
Authorization:Bearerに続けて、前のアクションで抽出したトークンを参照します。- 例。
Bearer ${{ .steps.http_post_2.outputs.token }}
- 例。
- ヘッダー
Accept:application/vnd.github+jsonを指定します。 - ボディ: 作成したいIssueの
titleとbodyをJSONで指定します。
ここまで設定できたら、ワークフローを実行します。指定したリポジトリに、設定したタイトルと本文でIssueが作成されていれば成功です。
まとめ
GitHub Appを用いたissueの作成を例に、Workflow Automation 上でJWT認証を使用する方法を紹介しました。
今回は例として、GitHub Appを取り上げましたが、JWT認証を求める外部サービスは他にもあります。Auth JWT アクションでJWTを生成し、HTTPアクションでAPIを呼び出すという同じ考え方で、さまざまな連携に応用できます。Workflow Automation から外部サービスとの認証連携を検討する際の参考にしてみてください。
本ブログに掲載されている見解は著者に所属するものであり、必ずしも New Relic 株式会社の公式見解であるわけではありません。また、本ブログには、外部サイトにアクセスするリンクが含まれる場合があります。それらリンク先の内容について、New Relic がいかなる保証も提供することはありません。