テンプレートによるセキュリティ
Azure DevOps Services | Azure DevOps Server 2022 | Azure DevOps Server 2020
保護されたリソースのチェックは、Azure Pipelines のセキュリティの基本的な構成要素です。 チェックは、パイプラインの構造 (ステージとジョブ) に関係なく機能します。 チームまたは組織内の複数のパイプラインの構造が同じ場合は、テンプレートを使用すると、さらに簡単にセキュリティを確保できます。
Azure Pipelines には、インクルードと拡張の 2 種類のテンプレートが用意されています。
インクルードされるテンプレートは、C++ の #include
のように動作します。これは、テンプレートのコードをそのまま外部ファイルに貼り付けて、それを参照するような動作です。 たとえば、このインクルード テンプレート (include-npm-steps.yml
) は、steps
に挿入されます。
steps:
- template: templates/include-npm-steps.yml
引き続き C++ の例で説明すると、extends
テンプレートは継承に似ています。テンプレートは、パイプラインの外部構造と、テンプレート コンシューマーがターゲットを変更できる一連の場所を提供します。
拡張テンプレートを使用する
最も安全なパイプラインのためには、extends
テンプレートから開始することをお勧めします。
外部構造を指定することで、テンプレートでは悪意のあるコードがパイプラインに侵入することを防ぐことができます。
テンプレートと最終的なパイプラインの両方で includes
を使用することで、構成の共通部分を取り外すこともできます。
拡張テンプレートを使用する場合、パイプラインは次の例のようになります。
# template.yml
parameters:
- name: usersteps
type: stepList
default: []
steps:
- ${{ each step in parameters.usersteps }}:
- ${{ step }}
# azure-pipelines.yml
resources:
repositories:
- repository: templates
type: git
name: MyProject/MyTemplates
ref: refs/tags/v1
extends:
template: template.yml@templates
parameters:
usersteps:
- script: echo This is my first step
- script: echo This is my second step
extends
テンプレートを設定するときには、そのテンプレートを特定の Git ブランチまたはタグに固定することを検討してください。
そうすることで、破壊的変更が必要になった場合に、既存のパイプラインは影響を受けなくなります。
前述の例では、この機能を使用しています。
YAML によって適用されるセキュリティ機能
YAML 構文にはいくつかの保護機能が組み込まれており、拡張テンプレートでは、それらのいずれか、またはすべての使用を適用できます。
ステップ ターゲット
ホストではなくコンテナーで実行する一部のステップを制限します。 エージェントのホストにアクセスしないと、ユーザー ステップではエージェントの構成を変更することや、悪意のあるコードを後で実行するために残したりすることができなくなります。 コンテナーの安全性が向上するように、最初にホストでコードを実行します。 たとえば、ネットワークへのアクセスを制限することをお勧めします。 ネットワークへのオープン アクセスがないと、ユーザー ステップでは承認されていないソースからパッケージにアクセスしたり、コードとシークレットをネットワークの場所にアップロードしたりできなくなります。
resources:
containers:
- container: builder
image: mysecurebuildcontainer:latest
steps:
- script: echo This step runs on the agent host, and it could use docker commands to tear down or limit the container's network
- script: echo This step runs inside the builder container
target: builder
エージェント ログ コマンドの制限
Azure Pipelines エージェントがユーザー ステップに提供するサービスを制限します。 ステップは、"ログ コマンド" (stdout に出力される特別に書式設定された文字列) を使用してサービスを要求します。 制限モードでは、成果物のアップロードやテスト結果の添付など、エージェントのほとんどのサービスが使用できなくなります。
# this task will fail because its `target` property instructs the agent not to allow publishing artifacts
- task: PublishBuildArtifacts@1
inputs:
artifactName: myartifacts
target:
commands: restricted
制限モードでも使用できるコマンドの 1 つは、setvariable
コマンドです。 パイプライン変数は後続のタスクに環境変数としてエクスポートされるため、ユーザー指定のデータを出力するタスク (REST API から取得された未解決の問題の内容など) は、インジェクション攻撃に対して脆弱になる可能性があります。 そのようなユーザー コンテンツは、エージェント ホストの悪用に使用できる環境変数を設定できます。 これを禁止するために、パイプライン作成者は setvariable
ログ コマンドを使用して、設定可能な変数を明示的に宣言できます。 空のリストを指定すると、すべての変数の設定が禁止されます。
# this task will fail because the task is only allowed to set the 'expectedVar' variable, or a variable prefixed with "ok"
- task: PowerShell@2
target:
commands: restricted
settableVariables:
- expectedVar
- ok*
inputs:
targetType: 'inline'
script: |
Write-Host "##vso[task.setvariable variable=BadVar]myValue"
ステージまたはジョブの条件付き挿入
特定の条件下でステージとジョブを実行するように制限します。 条件は、たとえば、特定のブランチのみをビルドする場合に役立ちます。
jobs:
- job: buildNormal
steps:
- script: echo Building the normal, unsensitive part
- ${{ if eq(variables['Build.SourceBranchName'], 'refs/heads/main') }}:
- job: buildMainOnly
steps:
- script: echo Building the restricted part that only builds for main branch
拡張テンプレートを使用して特定の構文を要求する
テンプレートは反復して、YAML 構文を変更または禁止できます。 反復では、前述の機能を含む特定の YAML 構文の使用を強制できます。
テンプレートでは、ユーザー ステップを書き換えて、承認された特定のタスクの実行のみを許可することができます。 たとえば、インライン スクリプトの実行を防止できます。
警告
次の例では、"bash"、"powershell"、"pwsh"、"script" タイプのステップは実行できなくなります。 アドホック スクリプトを完全にロックダウンする場合は、"BatchScript" と "ShellScript" もブロックする必要があります。
# template.yml
parameters:
- name: usersteps
type: stepList
default: []
steps:
- ${{ each step in parameters.usersteps }}:
- ${{ if not(or(startsWith(step.task, 'Bash'),startsWith(step.task, 'CmdLine'),startsWith(step.task, 'PowerShell'))) }}:
- ${{ step }}
# The lines below will replace tasks like Bash@3, CmdLine@2, PowerShell@2
- ${{ else }}:
- ${{ each pair in step }}:
${{ if eq(pair.key, 'inputs') }}:
inputs:
${{ each attribute in pair.value }}:
${{ if eq(attribute.key, 'script') }}:
script: echo "Script removed by template"
${{ else }}:
${{ attribute.key }}: ${{ attribute.value }}
${{ elseif ne(pair.key, 'displayName') }}:
${{ pair.key }}: ${{ pair.value }}
displayName: 'Disabled by template: ${{ step.displayName }}'
# azure-pipelines.yml
extends:
template: template.yml
parameters:
usersteps:
- task: MyTask@1
- script: echo This step will be stripped out and not run!
- bash: echo This step will be stripped out and not run!
- powershell: echo "This step will be stripped out and not run!"
- pwsh: echo "This step will be stripped out and not run!"
- script: echo This step will be stripped out and not run!
- task: CmdLine@2
displayName: Test - Will be stripped out
inputs:
script: echo This step will be stripped out and not run!
- task: MyOtherTask@2
タイプ セーフ パラメーター
テンプレートとそのパラメーターは、パイプラインの実行前に定数に変換されます。 テンプレート パラメーター は、入力パラメーターに型セーフを提供します。 たとえば、パイプラインで使用可能なプールは、フリーフォーム文字列ではなく、選択可能なオプションの列挙を提供することで制限できます。
# template.yml
parameters:
- name: userpool
type: string
default: Azure Pipelines
values:
- Azure Pipelines
- private-pool-1
- private-pool-2
pool: ${{ parameters.userpool }}
steps:
- script: # ... removed for clarity
# azure-pipelines.yml
extends:
template: template.yml
parameters:
userpool: private-pool-1
必須テンプレートを設定する
特定のテンプレートの使用を必須にするには、リソースまたは環境に対する必須テンプレートのチェックを設定します。 必須テンプレートのチェックは、テンプレートから拡張する場合に使用できます。
このチェックの状態は、パイプライン ジョブを表示するときに確認できます。 パイプラインが必須のテンプレートから拡張されない場合、チェックは失敗して、実行は停止します。 チェックに失敗したことが示されます。
必須テンプレートが使用されているときには、チェックに合格したことが示されます。
このテンプレート params.yml
は、リソースの承認で必須になります。 パイプラインの失敗をトリガーするには、params.yml
への参照をコメントアウトします。
# params.yml
parameters:
- name: yesNo
type: boolean
default: false
- name: image
displayName: Pool Image
type: string
default: ubuntu-latest
values:
- windows-latest
- ubuntu-latest
- macOS-latest
steps:
- script: echo ${{ parameters.yesNo }}
- script: echo ${{ parameters.image }}
# azure-pipeline.yml
resources:
containers:
- container: my-container
endpoint: my-service-connection
image: mycontainerimages
extends:
template: params.yml
parameters:
yesNo: true
image: 'windows-latest'
追加の手順
テンプレートでは、パイプライン作成者がステップを含めなくてもステップを追加できます。 そうしたステップは、資格情報のスキャンや静的コードのチェックを実行するために使用できます。
# template to insert a step before and after user steps in every job
parameters:
jobs: []
jobs:
- ${{ each job in parameters.jobs }}: # Each job
- ${{ each pair in job }}: # Insert all properties other than "steps"
${{ if ne(pair.key, 'steps') }}:
${{ pair.key }}: ${{ pair.value }}
steps: # Wrap the steps
- task: CredScan@1 # Pre steps
- ${{ job.steps }} # Users steps
- task: PublishMyTelemetry@1 # Post steps
condition: always()
テンプレートの強制
テンプレートは、それを強制できる場合にのみセキュリティ メカニズムになります。 テンプレートの使用を強制するコントロール ポイントは、保護されたリソースです。 エージェント プールやリポジトリなどの保護されたリソースに対して承認とチェックを構成できます。 例については、「リポジトリ リソース チェックの追加」を参照してください。
次のステップ
次に、変数とパラメーターを使用して安全に入力を取得する方法について説明します。
フィードバック
https://aka.ms/ContentUserFeedback」を参照してください。
以下は間もなく提供いたします。2024 年を通じて、コンテンツのフィードバック メカニズムとして GitHub の issue を段階的に廃止し、新しいフィードバック システムに置き換えます。 詳細については、「フィードバックの送信と表示