Azure DevOps Services |Azure DevOps Server 2022 |Azure DevOps Server 2020
パイプラインは、スクリプトを実行し、コードを運用環境にデプロイするための強力な機能を提供しますが、この機能とセキュリティのバランスを取る必要があります。 パイプラインが悪意のあるコードの導管になることは決してありません。 セキュリティと、開発チームが必要とする柔軟性とパワーのバランスを取ることが不可欠です。
この記事では、脅威や脆弱性からパイプラインを保護するために必要なセキュリティ関連の構成の概要について説明します。
[前提条件]
カテゴリ | 要件 |
---|---|
Azure DevOps | - 「Azure DevOps をセキュリティで保護する」の推奨事項を実装します。 - YAML と Azure Pipelines に関する基本的な知識。 詳細については、「最初のパイプラインの作成」を参照してください。 |
アクセス許可 | - パイプラインのアクセス許可を変更するには: プロジェクト管理者グループのメンバー。 - 組織のアクセス許可を変更するには: プロジェクト コレクション管理者グループのメンバー。 |
プロジェクト、リポジトリ、およびサービス接続アクセスを制限する
セキュリティを強化するには、プロジェクトの分離、ブランチ ポリシーの使用、フォークのセキュリティ対策の追加を検討してください。 サービス接続のスコープを最小限に抑え、最も安全な認証方法を使用します。
- 個別のプロジェクト: 各製品とチームを個別のプロジェクトで管理します。 これにより、ある製品のパイプラインが別の製品から開いているリソースに誤ってアクセスするのを防ぎ、横方向の露出を最小限に抑えることができます。
- プロジェクト レベルの ID を使用する: コレクション レベルの ID ではなく、パイプラインに対してプロジェクト ベースのビルド ID を使用します。 プロジェクト レベルの ID は、関連するプロジェクト内のリソースにのみアクセスでき、悪意のあるアクターによる不正アクセスのリスクを最小限に抑えます。 詳細については、 スコープ付きビルド ID と ジョブ承認スコープに関する説明を参照してください。
- ブランチ ポリシーを使用する: コードとパイプラインに安全に変更を加えるために、アクセス許可とブランチ ポリシーを適用します。 さらに、パイプラインの アクセス許可とチェックをリポジトリに追加することを検討してください。
-
フォークのセキュリティを強化する: GitHub からパブリック リポジトリを使用する場合は、ビルドをフォークする方法を慎重に検討してください。 組織外から発生したフォークは、特にリスクを伴います。
- フォークビルドにシークレットを提供しない: 既定では、パイプラインはフォークをビルドするように設定されていますが、シークレットや保護されたリソースはパイプライン内のジョブに自動的には公開されません。 セキュリティを維持するために、この保護を無効にしないことが不可欠です。
- フォーク ビルドを手動でトリガーすることを検討する: 自動フォーク ビルドをオフにし、pull request コメントを使用してこれらのコントリビューションを手動でビルドします。 この設定により、ビルドをトリガーする前にコードを確認できます。 詳細については、「 自動フォーク ビルドをオフにする」を参照してください。
- フォーク ビルドにシークレットを提供しないでください。既定では、パイプラインに関連付けられているシークレットは、フォークの要求検証をプルするために使用できません。 フォークのビルドでシークレットを使用できるようにするオプションを有効にしないでください。 この設定を見つけて確認する方法については、「 フォークからの投稿」を参照してください。
- フォーク ビルドを手動でトリガーすることを検討する: 自動フォーク ビルドをオフにし、pull request コメントを使用してこれらのコントリビューションを手動でビルドします。 この設定により、ビルドをトリガーする前にコードを確認できます。 これを行う方法については、「 自動フォーク ビルドをオフにする」を参照してください。
- フォーク ビルドに Microsoft ホスト型エージェントを使用する: セルフホステッド エージェントでフォークからビルドを実行しないようにします。 これを行うと、外部組織が企業ネットワーク内のコンピューターで外部コードを実行できるようになります。 可能な限り、Microsoft でホストされるエージェントを使用します。
- トークン スコープの制限に Azure Pipelines GitHub アプリを使用する: GitHub フォークプル要求をビルドすると、Azure Pipelines によって、パイプラインで GitHub リポジトリのコンテンツを変更できなくなります。 この制限は、Azure Pipelines GitHub アプリを使用して GitHub と統合する場合にのみ適用されます。
セキュリティで保護されたサービス接続
- サービス接続のスコープを最小限に抑える: サービス接続は、必要なリソースにのみアクセスできる必要があります。 新しい Azure Resource Manager サービス接続を作成するときは、常に特定のリソース グループを選択します。 リソース グループに、ビルドに必要な VM またはリソースのみが含まれていることを確認します。 サービス接続を設定する方法については、「 Azure Resource Manager サービス接続を使用する」を参照してください。
- 認証にワークロード ID フェデレーションを使用する: 可能な限り、Azure サービス接続のサービス プリンシパルではなくワークロード ID フェデレーションを使用します。 ワークロード ID フェデレーションでは、業界標準テクノロジである Open ID Connect (OIDC) を使用して、シークレットに依存せずに Azure と Azure DevOps の間の認証を容易にします。 これを行う方法については、「 ワークロード ID フェデレーションを使用したサービス接続の作成 (自動)」を参照してください。
- GitHub アプリのアクセスを最小限に抑える: Azure DevOps に GitHub アプリを構成する場合は、パイプラインを使用してビルドするリポジトリにのみアクセス権を付与します。
クラシック パイプラインではなく YAML パイプラインを使用する
セキュリティを強化し、誤って構成されるリスクを軽減するには、クラシック パイプラインではなく YAML パイプラインを使用します。 この予防措置により、サービス接続など、同じリソースを共有する YAML とクラシック パイプラインから発生するセキュリティ上の懸念が回避されます。 組織でクラシック パイプラインを使用している場合は、 パイプラインを YAML に移行します。
- YAML には、コードとしてのインフラストラクチャの利点があります。手順と依存関係はコードで定義されているため、YAML パイプラインは他のコードと同様に扱います。 また、パイプライン構成を明確に把握でき、誤った構成が発生するリスクも軽減されます。
- YAML パイプラインを強化されたセキュリティ対策と組み合わせることができます。コード レビューとプル要求を通じて、 ブランチ ポリシー を使用して、不適切なマージを防ぐためにプル要求のレビュー プロセスを設定します。
-
リソース アクセス管理: リソース所有者は、YAML パイプラインが特定のリソースにアクセスできるかどうかを制御します。 このセキュリティ機能により、別のリポジトリを盗むなどの攻撃を防ぐことができます。
承認とチェックを使用して、各パイプライン実行のアクセス制御を提供します。
- 保護されたブランチ チェック: 特定のブランチの手動コード レビュー プロセスがある場合は、この保護をパイプラインに拡張できます。 リソースの保護されたブランチ チェックを使用すると、承認されていないブランチでパイプラインが自動的に実行されなくなります。
- 手動承認チェック: 手動承認チェックを使用して、指定されたユーザーまたはグループによって手動で承認されるまで、パイプライン要求で保護されたリソースの使用をブロックします。
- 営業時間の確認: このチェックを使用して、指定した日付と時間枠内にパイプラインデプロイが開始されることを確認します。
- クラシック パイプラインの作成を無効にする: クラシック ビルド パイプラインとクラシック リリース パイプラインの作成を個別に無効にします。 両方を無効にした場合、ユーザー インターフェイスまたは REST API を使用してクラシック ビルド パイプライン、クラシック リリース パイプライン、タスク グループ、またはデプロイ グループを作成することはできません。 詳細については、「 クラシック パイプラインの作成を無効にする」を参照してください。
セキュリティで保護されたエージェント
コンテナーをセキュリティで保護するには、ボリュームを読み取り専用としてマークし、リソース制限を設定し、信頼されたイメージを使用し、脆弱性をスキャンして、セキュリティ ポリシーを適用します。
- セルフホステッド エージェントの代わりに Microsoft でホストされるエージェントを使用します。Microsoft ホステッド エージェントは、パイプラインの実行ごとに分離とクリーンな仮想マシンを提供します。 セルフホステッド エージェントではなく、Microsoft でホストされるエージェントを使用します。 詳細については、Microsoft ホステッド エージェントに関するページを参照してください。
- プロジェクトごとにエージェントを分離する: 横方向の移動を軽減し、プロジェクト間のクロスコンタミネーションを防ぐために、それぞれを特定のプロジェクト専用の個別のエージェント プールに維持します。
- 低い特権のアカウントを使用してエージェントを実行する: システム セキュリティを強化するには、セルフホステッド エージェントを実行するために最も低い特権アカウントを使用します。 たとえば、マシン アカウントまたはマネージド サービス ID を使用することを検討してください。 Azure DevOps リソースに直接アクセスできる ID でエージェントを実行しないでください。
-
運用成果物と機密性の高いエージェント プールを分離する: セキュリティの問題を防ぐために、さまざまなエージェント プールを使用します。
- 運用成果物に別のエージェント プールを使用する: 個別のエージェント プールを使用して運用成果物を分離し、非運用ブランチからの偶発的なデプロイを防ぎます。
- セグメントの機密性の高いプール: 機密性の高いワークロードと機密性の低いワークロード用に個別のプールを作成します。 適切なプールに関連付けられているビルド定義の資格情報のみを許可します。
- セルフホステッド エージェントの制限付きファイアウォールを構成する: エージェントの機能を引き続き許可しながら、ファイアウォールをできるだけ制限的に設定し、セキュリティと使いやすさのバランスを取ります。
- セルフホステッド エージェント プールを定期的に更新する: 脆弱なコードが実行されていないことを確認するために、セルフホステッド エージェントを定期的に更新して最新の状態に保ち、悪用のリスクを軽減します。
変数とパラメーターを安全に使用する
シークレットを設定するためのベスト プラクティスに従って、パイプラインで変数とパラメーターを安全に使用します。 ベスト プラクティスには、シークレットの使用の制限、キュー時間変数の使用、脅威や脆弱性からパイプラインを保護するためのシェル タスク引数の検証の有効化などがあります。
- シークレットへのアクセスを制限する: シークレットまたはキーがパイプラインに表示されないようにします。 ワークロード ID フェデレーションなどのシークレットレス認証方法に移動するか、UI、変数グループ、または Azure Key Vault から提供される変数グループでシークレットを設定します。
- シェル パラメーター検証を有効にする: [シェル タスク引数の検証を有効にする] 設定 が有効になっている場合、セミコロン、引用符、かっこなどの文字のチェックが追加されます。 [Settings>>] で、組織レベルまたはプロジェクト レベルでシェル タスク引数パラメーターの検証を有効にします。
- キュー時に設定できる変数を制限する: 組織の設定でキュー時に設定できる制限変数の設定を有効にすることで、ユーザーがキュー時に新しい変数を定義できないようにします>Pipelines>Settings。
-
変数の代わりにパラメーターを使用する: 変数とは異なり、実行中のパイプラインではパイプライン パラメーターを変更できません。 パラメーターには、
number
やstring
などのデータ型があり、特定の値のサブセットに制限できます。 この制限は、パイプラインのユーザーが構成可能な側面で、定義済みのリストからの値のみを受け入れ、パイプラインが任意のデータを受け入れないようにする必要がある場合に重要です。 - テンプレートからのシークレットの参照: パイプライン YAML にシークレット パラメーターを含むインライン スクリプトを直接含める代わりに、テンプレートを使用してメイン パイプラインから機密情報を抽象化します。 この方法を実装するには、スクリプト用に個別の YAML ファイルを作成し、そのスクリプトを別の安全なリポジトリに格納します。 その後、テンプレートを参照し、パラメーターとして YAML にシークレット変数を渡すことができます。 セキュリティで保護された変数は、Azure Key Vault、変数グループ、またはパイプライン UI から取得する必要があります。 詳細については、「 テンプレートを使用する」を参照してください。
-
ブランチ ポリシーと変数グループのアクセス許可を使用してシークレットを制限する: 変数グループのアクセス許可、条件付きジョブの挿入、ブランチ ポリシーの組み合わせを使用して、シークレットが
main
ブランチに関連付けられていることを確認できます。 詳細については、「シークレットの 保護」を参照してください。 -
setvariable を使用して変数の設定を制限する:
settableVariables
属性を使用して、パイプライン作成者がパイプラインで設定できる変数を構成します。 この設定がないと、パイプライン作成者は、setvariable
ログ コマンドを使用して、無制限の新しい変数を宣言できます。 空のリストwith settableVariables
を指定すると、すべての変数設定は許可されません。 詳細については、YAML スキーマのsettableVariables
属性 を参照してください。
シークレットを保護する最善の方法は、最初にシークレットを持たないようにする方法です。 シークレットは可能な限り使用しないでください。YAML ファイルに保存しないでください。また、セキュリティを維持するためにログに記録または印刷されないようにします。
- 可能な限りシークレットの使用を避ける: パイプラインで、シークレットを使用してワークロード ID フェデレーションやマネージド ID とのサービス接続などのタスクを実行する場合とは異なる方法を使用できるかどうかを確認します。 マネージド ID を使用すると、アプリケーションとサービスは、明示的な資格情報を必要とせずに Azure で認証できます。 詳細については、「 サービス プリンシパルとマネージド ID の使用」を参照してください。 YAML にシークレットを配置しない: 機密値をプレーンテキストとして Azure Pipelines .yml ファイルに格納しないでください。
- シークレットをログに記録または出力しない: シークレットをコンソールにエコーしたり、コマンド ライン パラメーターでシークレットを使用したり、ファイルにログを記録したりしないようにします。 Azure Pipelines は、可能な限りログからシークレットをスクラブしようとしますが、シークレットが漏えいするあらゆる方法をキャッチすることはできません。
- JSON などの構造化データをシークレットとして使用しないでください。機密値ごとに個別のシークレットを作成します。 この方法により、編集精度が向上し、機密データが誤って公開されるリスクが最小限に抑えられます。
シークレットの監査とローテーション
パイプラインをセキュリティで保護するには、タスクとログのシークレット処理を定期的に監査し、不要なシークレットを確認して削除し、シークレットをローテーションしてセキュリティ リスクを最小限に抑えます。
- タスクとログでのシークレット処理の監査: タスクをチェックして、シークレットがホストに送信されたりログに出力されたりしていないことを確認します。 エラー ログを含め、すべてのログ ファイルにシークレットがないことを確認します。
- 登録済みのシークレットを確認する: パイプライン内のシークレットがまだ必要であることを確認し、不要になったシークレットを削除して、乱雑さと潜在的なセキュリティ リスクを軽減します。
- シークレットをローテーションする: 侵害されたシークレットが悪用される可能性がある期間を最小限に抑えるために、シークレットを定期的にローテーションします。
悪意のあるコードの実行を防ぐ
テスト済みでサニタイズされたコードのみがパイプラインを通じて実行されるようにするには、パイプラインで一般的な問題を定期的に確認します。
- コード スキャン: シェル コマンドの挿入を回避するために、引数内の特殊文字をエスケープします。 GitHub Advanced Security for Azure DevOps を使用して、コード スキャンを自動化できます。
- 入力を検証し、パラメーターを使用する: 入力パラメーターと引数を検証して、意図しない動作を防ぎます。 SQL インジェクションを防ぐために、スクリプトでパラメーター化されたクエリを使用します。 ランタイム パラメーターArgument インジェクションなど、変数に関連するセキュリティの問題を回避するのに役立ちます。
-
スクリプトで PATH を使用しないでください。エージェントの
PATH
設定に依存することは、以前のスクリプトまたはツールによって変更される可能性があるため、危険です。 常に完全修飾パスを使用してください。 - 使用可能なタスクを制御する: Marketplace からタスクをインストールして実行する機能を無効にします。これによって、パイプラインで実行されるコードをより詳細に制御できます。
コンテナーをセキュリティ保護する
構成の変更、スキャン、ポリシーを使用してコンテナーをセキュリティで保護する方法について説明します。
-
ボリュームを読み取り専用としてマークする: コンテナーには、ホスト エージェントを操作するために必要なタスク、ツール、および外部コンポーネント用のシステム提供のボリューム マウントが含まれます。 セキュリティを強化するために、
externals
、tasks
、およびtools
を読み取り専用に設定します。 - コンテナー固有のリソース制限の設定: CPU とメモリに制限を設定して、コンテナーが過剰なリソースを消費するのを防ぎ、サービス拒否やセキュリティの脆弱性を引き起こす可能性があります。
-
信頼できるイメージを使用する: Azure Container Registry や Docker Hub などの信頼できるソースからの公式および検証済みイメージを使用します。
latest
タグに依存するのではなく、一貫性と信頼性を維持するために、常に特定のバージョンまたはタグを指定してください。 基本イメージを定期的に更新して、最新のセキュリティ パッチとバグ修正プログラムを含めます。 - 脆弱性のコンテナーをスキャンし、実行時の脅威保護を適用する: Microsoft Defender for Cloud などのツールを使用して、セキュリティ リスクを監視および検出します。 さらに、Azure Container Registry では、デプロイ前にコンテナー イメージのセキュリティを確保するために、統合された 脆弱性スキャン が提供されます。 また、Azure DevOps 拡張機能を使用してサードパーティのスキャン ツールを統合して、セキュリティ チェックを追加することもできます。
- 特権エスカレーションを防ぎ、必要最小限の特権でコンテナーを確実に実行するためのセキュリティ ポリシーを実装します。たとえば、Azure Kubernetes Service (AKS)、 ロールベースのアクセス制御、 ポッド セキュリティ アドミッション では、コンテナー特権を制限し、ルート以外の実行を確保し、重要なリソースへのアクセスを制限するポリシーを適用できます。
- ネットワーク ポリシーを利用する: ネットワーク ポリシー を使用してコンテナー間の通信を制限し、承認されたコンテナーのみがネットワーク内の機密リソースにアクセスできるようにします。 さらに、 Azure Policy for AKS を適用して、信頼されたコンテナー イメージのみがデプロイされるようにするなど、コンテナー セキュリティのベスト プラクティスを適用できます。
テンプレートを使用してベスト プラクティスを適用する
最小限のテンプレートから始めて、拡張機能を徐々に適用します。 このアプローチにより、セキュリティ プラクティスを実装する際に、すべてのパイプラインをカバーする一元化された開始点が確保されます。
- 拡張テンプレートを使用する: 拡張テンプレートは外側の構造を定義し、対象を絞ったカスタマイズの特定のポイントを提供します。 拡張テンプレートを使用すると、 悪意のあるコードがパイプラインに侵入するのを防ぐことができます。
- 手順を使用してアクセスを制限する: パッケージのダウンロードなどの手順をホストではなくコンテナーで実行することで、ネットワーク アクセスを制限します。 コンテナーで手順を実行すると、悪意のあるアクターがエージェントの構成を変更したり、後で実行するために悪意のあるコードを残したりできなくなります。