パブリックコードリポジトリでは一般的に,任意のユーザーがフォークを実行しプルリクエストを発行することが許可されています(この記事ではこれを”フォークされた公关”と呼びます)。これらのユーザーは組織外からアクセスしている可能性があるため,自動ビルドを実行する目的では,一般的に未信頼のユーザーと見なされます。このことは,継続的インテグレーション(CI)サービスを利用して,認証情報や機密データへのアクセスを伴うテストを実行する場合に問題となります。悪意ある開発者の提案したコードによって認証情報がCIログに開示されてしまう可能性があるためです。プライベートリポジトリの場合でも,組織内の一部のユーザーにはリポジトリの閲覧権限を提供して,シークレットを開示するビルドをトリガーする可能性をなくすことが必要な場合があります。

以前,「外部コントリビューターのプルリクエストがある场合のシークレットの管理」で,フォークされたPRから认证情报を非表示にして,认证情报を必要とするビルドをスキップする方法について说明しました。ただしこの记事では,认证情报を取得するビルドが,ビルドアーティファクトのステージングを目的としていることと,主へのマージにのみ本当に必要であることを前提としていました。このため,信頼済みジョブの出力を,マージ前の适切な変更レビューに使用する场合には,ジョブをスキップできません。必要とされているのは,フォークされたPRをチームの信頼済みメンバーがチェックし,シークレットを开示するような変更が追加されていないことを确认してから信頼済みのCIジョブを実行して,変更の整合性を确保する方法です。この记事の前半では,GIT中自体を使用してコードを信頼済みとしてマークすることで,このようなワークフローを有效化する方法について说明します。后半では,この概念を具体的なリポジトリホスト(GitHub的)とCIプロバイダー(CircleCI)に适用する方法を,详细なデモンストレーションを通じて解说します。

アップストリームにプッシュすることで,コードを信頼済みとしてマークする

プルリクエストをリポジトリにマージする行為は,部分的には,コードを有効で信頼できるものとしてマークする行為だと言えます。フォークは,ユーザーによる変更が検証されるまでの間,その変更を隔離する方法として捉えることができます。外部コントリビューターは通常,コードをメインリポジトリのどのブランチにもプッシュできません。プッシュできるのは自分のフォークに対してだけです。

GitHubなどのプロバイダーでは,セキュリティコントロールをセットアップすることで,このようなモデルをサポートできます。これは一般的には,特定の名前付きユーザーのグループだけがリポジトリにアクセスし,変更を加えられるというモデルです。同様にCIプロバイダーの多くが,このモデルを前提に権限をセットアップしています。一般的なCIシステムでは,メインリポジトリへのプッシュによりトリガーされたジョブだけに認証情報を開示するよう構成されています。

ビルド構成を直接リポジトリに置くすべてのシステムでは,ビルドが公关の作成時に自動的にトリガーされる場合,未信頼のコードを実行する危険性があります。しかしこのことは,アップストリームブランチにコードをプッシュする行為を信頼の表現として使用し,信頼済みジョブを実行できるということでもあります。フォークされた公关のコードをアップストリームブランチにプッシュすると,アップストリームブランチとフォークされたブランチのGitリファレンスは(“参考文献”),同じコミットを参照する同一のものになります。GitHubはこれらが同一のコードであることを認識します。GitHubの API エンドポイントの多くにとって重要なのは、参照が関連付けられているブランチではなく、コミットの参照だけです。CI ジョブの場合、GitHub はコミット単位でインデックスを作成するので、アップストリーム ブランチにコードをプッシュした結果として実行される信頼済みジョブは、同じコミットを参照するフォークされた PR にも関連付けられます。

信頼済みCIジョブをトリガーするワークフローを実装する

では,上記の理論を実践するサンプルプロジェクトを作成してみましょう。まず,フォークからのものを含むあらゆる公关を実行できる基本的な测试ジョブを1つ用意します。同時に,Amazon S3からプライベートデータを取得するためにAWSの認証情報を必要とする,より包括的なtest-with-dataジョブを用意します。後者のジョブについては,リポジトリのコミット権限を持つユーザーが公关をレビューして,認証情報が漏えいする可能性がないことを確認するまで,トリガーされないようにします。

プロジェクトを作成する

外部コントリビューターのプルリクエストがある场合のシークレットの管理“で作成したものと同じ,小さなJavaプロジェクトから開始します。ビルドツールにはApache Mavenを使用し,次のようにプロジェクトを生成します。

mvn原型:生成-DgroupId=com.my188bet娱乐官网company.app-DartifactId=managing-secrets-DarchetypeArtifactId=maven-archetype-quickstart-Dversion=1.3-DinteractiveMode=

次に,测试ジョブを1つ実行するシンプルなCircleCIワークフローを作成します。

版本:2.1职位:测试:码头工人:-图片:circleci / OpenJDK的:8u171,JDK步骤:-结帐-运行:MVN清洁测试工作流:版本:2建立:职位:-测试

これをGitHub的にコミットし,CircleCIのプロジェクトとして有效化すると,プッシュするたびにCircleCIで建立ワークフローの実行がトリガーされるようになります。メインリポジトリの任意のブランチから発行された公关には,测试ジョブのステータスが表示されます。

フォークされたプルリクエストのCIを有効にする

ここで,フォークされたリポジトリからのプルリクエストでも,同じワークフローを有効化したいと思います。これにより、コミット権限を持たないコントリビューターによる変更提案が可能になるだけでなく、個人のフォークからの作業を好むコミッターも作業がしやすくなります。

フォークされたプルリクエストのCIを有效にするには,CircleCIのプロジェクト设定ページに移动し,构建设置(ビルド设定)>高级设置(详细设定)を選択して,建立分叉的拉请求(フォークされたプルリクエストをビルド)]オプションを有效にします。

同じ画面で,このオプションの隣に[通过秘密建立分叉的拉请求(フォークされたプルリクエストからビルドにシークレットを渡す)]があります。このオプションは既定では無効になっていますが,これがまさに今回の目的に必要な状態です。次の手順では,AWSの認証情報をアップロードすると共に,組織外のユーザーに誤って開示されないようにします。

シークレットを追加する

AWSの认证情报を信頼済みビルドで利用できるようにするには,この认证情报をプロジェクト固有の環境変数として设定しますま。た,コンテキストを作成して複数のプロジェクトで共有する方法もあります。

次に,CircleCIプロジェクト設定ページの构建设置(ビルド设定)>环境变量(环境変数)セクションに移動して,変数AWS_ACCESS_KEY_IDおよびAWS_SECRET_ACCESS_KEYを追加します。プライベートテストデータをステージングした亚马逊S3の场所からの読み取りを许可された认证情报は,これらの変数に格纳されます。これらの変数は,コミット権限を持つユーザーが开始したメインリポジトリのブランチへのプッシュに対してのみ设定されます。フォークされたプルリクエストから开始されたCircleCIジョブに対しては设定されません。

フォークされたPRの场合には実行されない信頼済みジョブを追加する

この時点で,認証情報にアクセスし,プライベートデータに基づいてテストを実行する追加ジョブのセットアップ準備が整いました。更新された構成を確認してみましょう。

版本:2.1职位:测试:码头工人:-图片:circleci / OpenJDK的:8u171,JDK步骤:-结帐-运行:MVN清洁测试test-with-data:码头工人:-图片:circleci / OpenJDK的:8u171,JDK步骤:-结帐-运行:|如果[-z “$ AWS_ACCESS_KEY_ID”];然后回声“没有AWS_ACCESS_KEY_ID设置!失败......”退出1;其他回声“凭证是可用的。让我们获取数据!”科幻工作流:版本:2建立:职位:-测试-test-with-data:过滤器:分支机构:分叉的pull请求将CIRCLE_BRANCH设置为pull/XXX忽视:/拉\ [0 - 9]+ /

この新しいtest-with-dataジョブには1点省略した部分があります。今回取り上げる内容を簡潔にするために,実際のデータ取得や,そのデータを使用するテストを実装していないのです。その部分を省略し,認証情報の存在をチェックするのみにとどめています。このジョブがメインリポジトリへのプッシュによって開始されれば,環境変数が利用可能になり,ジョブは成功するはずです。

ワークフローに配置したtest-with-dataジョブには,フォークされたPRでトリガーされた场合はジョブが実行されないようなフィルターを设定しています。前回の记事では,フィルターの代わりに,フォークされたPRの场合には早期段阶で返すような手法を実装していました。フィルターでも处理内容はほぼ同じですが,より洗练された方法となります。

フォークされた公关のレビューワークフローをテストする

テストがスキップされていることをさらに明确化するために,わずかな构成の変更をリポジトリに加えてみます。结局のところ,実际のデータでテストを実行するために,余计な手间をかけて信頼済みジョブを追加しているというのが问题の中心です。つまり,それらのテストを确実に成功させることが,プロジェクトの整合性を确保する最重要事项だと考えられます。

GitHubリポジトリで设置(設定)>分支(ブランチ)に移動し,分支保护规则(ブランチ保護ルール)を追加します。今回のケースではターゲットブランチが触发であるため,需要前状态检查通过合并(マージにはステータスチェック合格が必須)]トグルを有効にして,必要に応じて(ci / circleci:测试およびCI / circleci:测试用数据として表示される)両方のCIジョブを选択します。

ここで,あるユーザーがフォークから公关を発行すると,测试ジョブが実行され,(问题がなければ)成功を示す绿色になります。test-with-dataジョブは実行されませんが(フォークされた公关であるため),必須として指定しているので,公关ページのステータスチェックのセクションに“期望——等待状态报告(必須——ステータスの報告を待機中)“と表示され,マージの前に当該ジョブを実行する必要があることをレビュアーに通知します。さらに良い方法は,PULL_REQUEST_TEMPLATE.mdを作成してレビュアー向けチェックリストを追加し,信頼済みビルドを実行する前に潜在的なセキュリティの问题を検证するよう明示的に指示することです。

この状態の公关について”jklukas /管理-秘密#4“を例に考えてみましょう。この公关を見たレビュアーは,コードの初期スキャンを実施し,認証情報をログに出力する変更がCIジョブに加えられていることに気付き,変更依頼または公关のクローズのいずれかを行います。これによりtest-with-dataは実行されず,認証情報が開示されることはありません。

また,変更が有害なものではなく実行しても安全とレビュアーが判断した場合,公关のコミットをメインリポジトリのブランチにプッシュすることで,信頼済みジョブを実行できます。これはgitを直接起動して手動で実施できますが,少し面倒です。この一般的なワークフローは,公关のフォークをリモートとして追加し,公关のブランチをプルダウンし,そのブランチをメインリポジトリにプッシュしてクリーンアップするというものです。jklukas / git-push-fork-to-upstream-branch使这一行程序更方便:の小さなbashスクリプトをインストールすると,この処理を次のように1行で実行できます。

GIT-推叉至上游分支上游

アップストリームブランチにコードがプッシュされると,フォークされた公关のtest-with-dataのステータスチェックが実行状態になり,問題がなければ完全にグリーンな状態(成功)に移行し,マージの準備が完了します。

参考情報

外部コントリビューターのプルリクエストがある场合のシークレットの管理“ではCIにおける認証情報管理のオプションについて詳しく説明し,アーティファクトのステージングに認証情報を必要とするCIジョブで,フォークされた公关を早期段階で返すような手法を検討しました。

今回の記事では,この手法をさらに洗練させ,リポジトリコミッターがアップストリームブランチにコミットをプッシュすることで,フォークされた公关で信頼済みビルドをトリガーする方法を探りました。この手法が実際に使用されている,より現実的な例はMozilla的服务/ Mozilla的流水线模式で確認できます。Mozillaでは,このリポジトリに格納されているJSONスキーマを使用して,データパイプラインが受信するペイロードのバリデーションを行っています。このユースケースの最重要目標は,実際のクライアントデータのサンプルに対するすべての変更をテストして,以前有効だったペイロードのクラスに対する拒否をパイプラインに生じさせるようなリグレッションをすべて特定することです。このリポジトリが受信する公关は通常Mozillaのスタッフが提案していますが,スタッフは通常メインリポジトリへの書き込み権限を持たないため,公关はフォークから発行されます。このため,フォークされた公关の提案とテストの円滑なプロセスをサポートすることが重要なのです。

また,CircleCIが最近発表した制限付きコンテキストという新机能についてもご确认ください。制限付きコンテキストを使用すると,手动での承认ステップによってトリガーされたワークフローグラフの一部にシークレットを插入することができます。これを基にして,信頼済みビルドをトリガーするレビュアーのために,さらに效率的かつ柔软なアプローチを実现できるようになります。


杰夫Klukas氏は,実験素粒子物理学の知識と経験をバックグラウンドに,教師と研究者という2つの立場で活動されており,ヒッグス粒子の発見にも貢献しています。現在はオハイオ州コロンバスを拠点とするリモートワーカーとして,Mozilla Firefoxのデータプラットフォームに携わっています。以前は,支店を持たないクラウド銀行简单のデータプラットフォーム担当テクニカルリードを務めていました。