テンプレートによるセキュリティ

保護されたリソースのチェックは、Azure Pipelines のセキュリティの基本的な構成要素です。 パイプラインのステージとジョブの構造に関係なく作業を確認します。 チームまたは組織内の複数のパイプラインが同じ構造を持つ場合は、 テンプレートを使用してセキュリティをさらに簡略化できます。

Azure Pipelines に は、インクルード拡張 の2種類のテンプレートが用意されています。 インクルードされたテンプレートは #include C++ のように動作します。これは、テンプレートのコードを外部ファイルに貼り付けて参照する場合と同様です。 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 構文を強制的に使用することができます。

テンプレートでは、ユーザーステップを書き直すことができ、特定の承認されたタスクの実行のみが許可されます。 たとえば、インラインスクリプトの実行を禁止することができます。

警告

次の例では、"script" というリテラルステップのみが禁止されています。 アドホックスクリプトの完全なロックダウンを行うには、"bash"、"pwsh"、"powershell"、およびこれらの手順を戻すタスクをブロックする必要もあります。

# template.yml
parameters:
- name: usersteps
  type: stepList
  default: []
steps:
- ${{ each step in parameters.usersteps }}:
  - ${{ each pair in step }}:
    ${{ if ne(pair.key, 'script') }}:
      ${{ pair.key }}: ${{ pair.value }}
# azure-pipelines.yml
extends:
  template: template.yml
  parameters:
    usersteps:
    - task: MyTask@1
    - 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()

次の手順

次に、 変数とパラメーターを使用して入力を安全に取得する方法について説明します。