リポジトリとパイプラインをセキュリティで保護する

完了

自動化を使用してインフラストラクチャをデプロイする場合、パイプラインとリポジトリは強力かつ重要なものとなります。 現在、制御された環境に変更を適用する唯一の方法であるためです。

Azure DevOps 組織、GitHub リポジトリ、パイプラインの多くの部分を保護する必要があります。 次の表は、保護する最も重要な要素の一部と、それらの要素を適切に保護しない場合に発生する可能性がある脆弱性の例を示しています。

保護する要素 脆弱性の例
Azure DevOps 組織または GitHub リポジトリ (誰がそれにアクセスでき、何を実行できるかを含む)。 不満を持つ元従業員がコード リポジトリを削除する。
リポジトリ内の重要なブランチと、それらのブランチのコードを変更するために何を行う必要があるか。 誰かが保護されていない Bicep コードをリポジトリの "メイン" ブランチに誤ってコミットする。
インフラストラクチャ定義、テスト、アプリケーション コードなど、リポジトリ内のコード。 誰かが書いたコードをテストすることを忘れ、それが運用環境にリリースされたときに正しく動作しない。
パイプライン定義。 誰かが誤って、パイプラインのログにデータベース接続文字列を書き込むパイプライン ステップを追加する。
パイプラインを実行するエージェントまたはランナー。 ドラフトの pull request に対して実行されているパイプラインで、セキュリティの脆弱性がエージェントにインストールされ、それが後から運用環境のデプロイに使用される。
パイプライン内で実行される可能性があるサード パーティのタスクまたはコンポーネント。 サード パーティのパイプライン タスクによって、サービス プリンシパルの資格情報が悪意のある Web サイトに送信される。
パイプラインで Azure へのアクセスに使用するサービス プリンシパル。 非運用サービス プリンシパルが誤って運用環境に変更を加える。
パイプラインで外部システムにアクセスするために使用するシークレット。 チーム メンバーがプロトタイプ用の新しいパイプライン定義ファイルを書き、それを誤って運用環境に接続する。

次は、Azure DevOps と GitHub でコード リポジトリとデプロイ パイプラインに関するガバナンスと制御を適用するために使用できる、いくつかのアプローチについて学習します。

ユーザーとアクセス許可の管理

Azure DevOps 組織または GitHub リポジトリへのアクセスをどのように許可するかを検討します。 誰がアクセス権を持ち、何ができるかについて考えてください。

組織の Microsoft Entra インスタンスをパイプラインの ID プロバイダーとして使用することをお勧めします。 そのようにして、誰かが組織に参加または離職するたびに、パイプラインへのアクセスが自動的に許可または取り消されるようにすることができます。 Microsoft Entra ID を使用すると、条件付きアクセスや多要素認証などの保護を簡単に実装することもできます。

Note

Microsoft Entra と GitHub の統合を使用するには、組織に GitHub Enterprise ライセンスが必要です。

また、一緒にアクセス許可を付与できるユーザーの集まりを表す "チーム" (GitHub) または "グループ" (Azure DevOps) を作成することもできます。 そうすると、アクセス許可を個別に割り当てる必要はありません。 チームまたはグループにユーザーを追加すること、およびそこから削除することで、ユーザーのアクセス許可を簡単に変更できます。

ヒント

Azure DevOps には、Azure で使用しているモデルとは異なる "最小特権" アクセス許可モデルが使用されています。 Azure DevOps では、"拒否" アクセス許可は "許可" アクセス許可をオーバーライドします。 これは、異なるアクセス許可のセットを持つ複数のグループに割り当てられている場合に、すべてのグループで許可されているアクションのみを実行できることを意味しています。

アクセス許可がどのように割り当てられているか (特にグループに対して) を確実に把握してください。

重要なコード ブランチを保護する

パイプラインと自動化は、"メイン" などの特定のコード ブランチを識別することに基づいている必要があります。 通常、これらの指定されたブランチのコードは信頼され、運用環境へのデプロイが許可されます。 制御を適用することで、重要なブランチにあるコードが検証済みでレビュー済みであることが確実になります。

重要なコード ブランチへの直接コミットを防ぐために、"ブランチ保護規則" (GitHub) または "ブランチ ポリシー" (Azure Repos) を使用することを検討してください。 そうすると、pull request を使用して変更をマージすることをチームに要求できます。 自動チェックと手動レビュー プロセスを適用して、変更がマージされる前に有効であることを確認できます。

コードのテストとレビューを行う

インフラストラクチャ定義を含め、すべてのコードのレビューとテストに関する想定事項をチームが理解していることを確認します。

パイプライン定義は YAML ファイルであるため、コードの形式です。 パイプライン定義に対する変更をレビューして評価する必要があります。 そうしないと、サービス プリンシパルの資格情報を漏えいさせたり、Azure 資産に対して危険な変更を加えたりするパイプライン ステップが誤って、または悪意を持って作成される可能性があります。

パイプライン定義ファイルに対する変更は、十分にレビューする必要があります。 パイプラインには高い特権があり、特別な注意が必要であることをチームの全員が理解していることを確認します。

パイプラインのエージェントとランナーを保護する

パイプラインは、"エージェント" (Azure Pipelines の場合) または "ランナー" (GitHub Actions の場合) 上で実行されます。 エージェントとランナーは仮想マシンと考えることができます。 パイプライン定義で指定したタスクとスクリプトを実行して、これらの仮想マシンを制御します。

Azure Pipelines と GitHub Actions の両方で、Microsoft または GitHub が構成および保守する "ホステッド" 型のエージェントとランナーが提供されます。 プラットフォーム所有者は、推奨されるセキュリティ プラクティスに準拠するようにマシンを構成します。 プラットフォーム所有者の責任には、オペレーティング システムの脆弱性に修正プログラムを適用することが含まれます。

あるいは、エージェントとランナーとして独自の物理マシンまたは仮想マシンを使用することもできます。 この種のマシンは、''セルフホステッド'' エージェントとランナーと呼ばれます。 セルフホステッド エージェントとランナーを使用する場合、マシンが正しく構成され、脅威から保護されていることを確かめる責任はご自身にあります。

Microsoft でホストされるエージェントと GitHub でホストされるランナーはエフェメラルです。 エージェントまたはランナーに対するファイルまたは構成の変更は、パイプラインの実行が終了すると破棄されます。 エージェントまたはランナーをセルフホストする場合、複数の個別パイプラインまたは環境 (運用環境と非運用環境を含む) 用に、同じマシンが使用される可能性があります。 誰かが作成したパイプライン定義が、エージェントのオペレーティング システム上の重要なファイルを変更し、pull request からパイプラインを実行するものであったとします。 運用環境に対する次回のデプロイ実行時、エージェントが再利用される可能性があります。 すると、破損したファイルが運用環境にどのような影響を与える可能性があるかを予測する方法はありません。

これらの理由から、Microsoft ホステッド エージェントと GitHub ホスト ランナーを可能な場合は常に使用することをお勧めします。 セルフホステッド ランナーを使用する必要がある場合は、その構成と使用に関連したリスクを慎重に評価してください。

パイプライン内で実行されるサード パーティのコンポーネントを評価する

コミュニティ提供の GitHub Actions または Azure DevOps 拡張機能を使用する場合は、拡張機能を構築したユーザーとその機能が何であるかを理解します。 サード パーティのパイプライン コンポーネントは、サービス プリンシパルの資格情報にアクセスできる場合があり、したがって Azure 内の環境全体にアクセスできる可能性があります。

Azure DevOps では通常、あらゆる拡張機能は組織の管理者が承認した後に使用できるようになります。 ご自身が組織の管理者である場合は、使用する各コンポーネントに関連したセキュリティ リスクを考慮してください。 それらが信頼できる安全なものであることを確認する責任があります。

サード パーティのアクションまたはタスクを使用する場合は、常にバージョンを指定します。 レビューした正確なバージョンを指定することを検討してください。 以降のバージョンをパイプラインで自動的に使用できるようにすると、レビューしていないリスクが生じる可能性があります。

パイプラインのサービス プリンシパルをセキュリティで保護する

サービス プリンシパルは、パイプラインで Azure やその他のサービスにアクセスするために使用されます。 サービス プリンシパルを保護し、資格情報の不適切な使用ができないようにすることが重要です。 複数レイヤーの保護を適用することを検討してください。

まず、サービス プリンシパルの資格情報を保護することを検討できます。

  • 可能な限り "マネージド ID" または "ワークロード ID" を使用し、資格情報を保存することは徹底して避けてください。 すべてのパイプラインでマネージド ID やワークロード ID を使用することはできなくても、可能な場合は使用することをお勧めします。
  • サービス プリンシパルの資格情報を定期的に変更または "ローテーション" する方法を計画します。 たとえば、組織で 90 日または 120 日ごとに資格情報をローテーションするポリシーを使用している場合があります。 ローテーションを行う担当者と、資格情報が使用されているすべての場所を更新する方法を検討します。
  • シークレット、キー、証明書を管理して組織の他の部分に公開されないようにする役割を果たす、シークレット "管理人" を指定することを検討してください。

次に、サービス プリンシパルに付与するアクセス許可について考えます。

  • パイプラインのサービス プリンシパルに Microsoft Entra 条件付きアクセス ポリシーを適用します。 これらのポリシーは、危険なサインインと動作を識別するのに役立ちます。 たとえば、パイプラインのサービス プリンシパルのサインインが常に、ある 1 つの地理的領域から行われる場合、予期しない場所からのサインインを条件付きアクセスで検出して防止できます。これは、資格情報が侵害されたことを示している可能性があります。
  • 各サービス プリンシパルに付与するアクセス許可を慎重に検討してください。 たとえば、共有リソースの構成を読み取るために使用するサービス プリンシパルがあるとします。 そのサービス プリンシパルに "閲覧者" アクセスのみを許可することが可能か検討してください。そのサービス プリンシパルは、それ以外の特権を必要とする操作を行う必要がないからです。
  • サービス プリンシパルに割り当てる各アクセス許可の最小 "スコープ" を使用します。 たとえば、サービス プリンシパルを 1 つのリソース グループにデプロイするだけでよい場合は、サブスクリプション全体ではなく、そのリソース グループをロールの割り当てのスコープとします。
  • 環境ごとに別々のサービス プリンシパルを使用します。 そうすることで、プリンシパルの資格情報が侵害された場合や、誰かが 1 つの環境へのアクセス権を取得した場合でも、他の環境にアクセスすることはできません。

サービス接続とシークレットを保護する

"サービス接続" (Azure Pipelines) または "シークレット" (GitHub) には、パイプラインで Azure 環境へのアクセスに使用するサービス プリンシパルの資格情報が含まれています。 サービス接続とシークレットを保護し、各サービス接続とシークレットをどのパイプラインで使用するかを制御することが重要です。 そうしないと、非運用環境で、運用リソースにアクセスできるサービス プリンシパルの使用を誤って有効にしてしまう可能性があります。

Azure DevOps では、サービス接続を作成するときに、新しいパイプラインまたは環境で使用できるようになる前に承認を要求するように構成できます。

Azure DevOps では、特定のサービス接続に "チェック" を関連付けることもできます。 チェックにより、さらに保護レイヤーが追加されます。 たとえば、運用サービス接続に対するチェックを構成して、それがリポジトリの "メイン" ブランチのコードでのみ使用されていることを確認できます。 このチェックは、承認されていないコードが運用環境にデプロイされるのを防ぐのに役立ちます。

GitHub では、環境固有のシークレットを構成し、GitHub Actions ワークフローでその環境が操作されているときに、シークレット値のみが提供されるようにすることができます。 環境固有のシークレットと承認などの環境の制御を使用することで、運用環境へのデプロイに非運用環境のデプロイが使用されるリスクを軽減できます。 また、ワークロード ID を使用して、GitHub Actions ワークフローで資格情報を使用しないようにし、資格情報が漏えいする可能性を排除することもできます。

GitHub のセキュリティ機能を使用する

GitHub には、評価して使用する必要があるセキュリティ機能が用意されています。 これには次の機能があります。

  • Dependabot は、ソース コードの依存関係をスキャンして既知の脆弱性を検出します。
  • "シークレット スキャン" は、キーや資格情報のように見えるリポジトリ内のテキストを識別します。 リポジトリにシークレットを保存することは不適切な方法です。 リポジトリ内のシークレットに対してアラートが表示された場合は、シークレットの値が侵害されていることを考慮し、それを取り消すか変更する必要があります。
  • "監査" は、誰が GitHub 構成に変更を加えたかを把握するためのものです。
  • "セキュリティの概要" は、組織のリポジトリ全体のすべてのセキュリティ アラートを統合します。

Azure DevOps 監査ログを使用する

Azure DevOps には、パイプライン、ブランチ ポリシー、リポジトリと、その他のリソースに変更を加えたのは誰かを把握するのに役立つ、"監査ログ" が用意されています。 監査を有効にし、監査ログを定期的に確認することをお勧めします。

リポジトリとパイプラインを保護する

リポジトリとパイプラインに適用できる重要な制御について説明しました。 次に、このユニットで前述した各重要な要素を保護するために使用できる制御を検討しましょう。

保護する要素 適用する制御
Azure DevOps 組織または GitHub リポジトリ (誰がそれにアクセスでき、何を実行できるかを含む)。
  • 認証には Microsoft Entra ID を使用します。
  • チームとグループを使用してアクセス許可を割り当てます。
  • 監査ログを有効にし、監査ログを定期的に確認します。
リポジトリ内の重要なブランチと、それらのブランチのコードを変更するために何を行う必要があるか。 ブランチ保護規則またはブランチ ポリシーを適用します。
インフラストラクチャ定義、テスト、アプリケーション コードなど、リポジトリ内のコード。
  • コード レビューの要件を適用します。
  • 自動または手動のテストを追加します。
  • GitHub で Dependabot とシークレット スキャンを使用します。
パイプライン定義。 コード レビューの要件を適用します。
パイプラインを実行するエージェントまたはランナー。
  • Azure Pipelines の場合、Microsoft ホステッド エージェントを使用します。
  • GitHub Actions の場合、GitHub ホスト ランナーを使用します。
パイプライン内で実行される可能性があるサード パーティのタスクまたはコンポーネント。 すべてのサード パーティの拡張機能とタスクに関連したセキュリティ リスクを確認します。
パイプラインで Azure へのアクセスに使用するサービス プリンシパル。
  • GitHub Actions でワークロード ID を使用します。 Azure Pipelines の場合は、サービス プリンシパルを使用し、資格情報を定期的にローテーションします。
  • 環境ごとに別々のサービス プリンシパルを使用します。
  • 条件付きアクセス ポリシーを適用します。
パイプラインで外部システムにアクセスするために使用するシークレット。
  • Azure DevOps の場合、サービス接続で承認とチェックを使用します。
  • GitHub の場合、環境固有のシークレットとワークロード ID を使用します。