共用方式為


安全範本

Azure DevOps 服務 |Azure DevOps Server |Azure DevOps Server 2022

Azure Pipelines 範本可讓您 在 YAML 管線中定義可重複使用的內容、邏輯和參數。 本文說明範本如何藉由下列方式協助增強管線安全性:

  • 定義管線的外部結構,以協助防止惡意程式碼滲透。
  • 自動包含執行認證掃描等任務的步驟。
  • 協助強制執行 受保護資源的檢查,這些資源會形成 Azure Pipelines 的基本安全性架構,並套用至所有管線結構和元件。

本文是一系列的一部分,可協助您實作 Azure Pipelines 的安全性措施。 如需詳細資訊,請參閱 保護 Azure Pipelines

先決條件

類別 要求
Azure DevOps - 在讓 Azure DevOps 安全且保護 Azure Pipelines 中實作建議。
- YAML 和 Azure Pipelines 的基本知識。 如需詳細資訊,請參閱 建立您的第一個管線
許可 - 若要修改管線許可權: 專案管理員群組的成員
- 若要修改組織許可權: 專案集合系統管理員群組的成員。

包含和擴充範本

Azure Pipelines 提供 包含擴充 範本。

  • 範本會 includes 直接將範本的程式碼包含在參考範本的外部檔案中,類似 #include 於 C++。 下列範例管線會將 include-npm-steps.yml 範本 steps 插入 區段。

      steps:
      - template: templates/include-npm-steps.yml 
    
  • extends範本會定義管道的外部結構,並提供目標自訂的特定點。 在C++的內容中, extends 範本類似於繼承。

當您使用 extends 範本時,您也可以在 includes 範本和最終管線中執行常見的組態片段。 如需詳細資訊,請參閱 在 管線中使用 YAML 範本來取得可重複使用且安全的程式

擴充範本

若要取得最安全的管線,請從使用 extends 範本開始。 這些範本定義了管道的外部結構,並有助於防止惡意程式碼滲透。

下列範例顯示名為 template.yml 的範本檔案。

parameters:
- name: usersteps
  type: stepList
  default: []
steps:
- ${{ each step in parameters.usersteps }}:
  - ${{ step }}

下列範例管線會擴充 template.yml 範本。

# 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 管線語法包含數個內建保護。 Extends 範本可以強制使用它們來增強管線安全性。 您可以實作下列任何限制。

步驟目標

您可以限制指定的步驟在容器中執行,而不是在主機上執行。 容器中的步驟無法存取代理程式主機,因此無法修改代理程式組態,或留下惡意程式碼以供稍後執行。

例如,您可以在容器中執行使用者步驟,以防止他們存取網路,這樣他們就無法從未經授權的來源擷取套件,或將程式碼和密碼上傳到外部位置。

下列範例管線會在代理程式主機上執行可能變更主機網路的步驟,然後在容器內執行限制網路存取的步驟。

resources:
  containers:
  - container: builder
    image: mysecurebuildcontainer:latest
steps:
- script: echo This step runs on the agent host
- script: echo This step runs inside the builder container
  target: builder

型別安全參數

在管線執行之前,範本及其參數會轉換為常數。 範本參數 可以增強輸入參數的類型安全性。

在下列範例範本中,參數會列舉特定選項,而不是允許任何字串,以限制可用的管線集區選項。

# template.yml
parameters:
- name: userpool
  type: string
  default: Azure Pipelines
  values:
  - Azure Pipelines
  - private-pool-1
  - private-pool-2

pool: ${{ parameters.userpool }}
steps:
- script: echo Hello world

若要擴充範本,管線必須指定一個可用的集區選項。

# azure-pipelines.yml
extends:
  template: template.yml
  parameters:
    userpool: private-pool-1

代理程式記錄命令限制

使用者步驟會使用 記錄命令來要求服務,這些命令是列印至標準輸出的特製字串。 您可以限制日誌指令為使用者的步驟提供的服務。 在restricted模式中,大部分代理服務(例如上傳構件及附加測試結果)都無法用於執行日誌記錄命令。

在下列範例中, target 內容會指示代理程式限制發佈構件,因此構件發佈作業會失敗。

- task: PublishBuildArtifacts@1
  inputs:
    artifactName: myartifacts
  target:
    commands: restricted

記錄命令中的變數

setvariable 命令在 restricted 模式中仍然可用,因此處理輸出使用者提供資料的作業,例如透過 REST API 擷取的未解決問題,可能容易受到注入攻擊。 惡意使用者內容可能會設定變數,以環境變數的形式匯出至後續工作,並可能危害代理程式主機。

若要降低此風險,您可以使用 logging 指令明確 setvariable 宣告可設定的變數。 如果您在 中 settableVariables指定空清單,則不允許所有變數設定。

下列範例會將 settableVariables 限制於 expectedVar,以及任何以 ok 作為前置詞的變數。 工作失敗,因為它嘗試設定名為 BadVar的不同變數。

- task: PowerShell@2
  target:
    commands: restricted
    settableVariables:
    - expectedVar
    - ok*
  inputs:
    targetType: 'inline'
    script: |
      Write-Host "##vso[task.setvariable variable=BadVar]myValue"

條件式階段或作業執行

您可以限制階段和作業只在特定條件下執行。 下列範例可確保受限的程式碼僅於 main 分支建置。

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

語法修改

Azure Pipelines 範本具有逐一查看和修改 YAML 語法的彈性。 藉由使用反覆專案,您可以強制執行特定的 YAML 安全性功能。

範本也可以重寫使用者步驟,只允許核准的工作執行。 例如,範本可以防止內嵌指令碼執行。

下列範例範本會防止執行指令碼步驟類型 bashpowershellpwshscript 。 若要完全鎖定腳本,您也可以封鎖 BatchScriptShellScript

# 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 following lines 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 is stripped out and not run
    - bash: echo This step is stripped out and not run
    - powershell: echo "This step is stripped out and not run"
    - pwsh: echo "This step is stripped out and not run"
    - script: echo This step is stripped out and not run
    - task: CmdLine@2
      displayName: Test - stripped out
      inputs:
        script: echo This step is stripped out and not run
    - task: MyOtherTask@2

範本步驟

範本可以自動在管線中包含步驟,例如執行認證掃描或靜態程式碼檢查。 下列範本會在使用者在每個作業中的步驟前後插入步驟。

parameters:
  jobs: []

jobs:
- ${{ each job in parameters.jobs }}: 
  - ${{ each pair in job }}:  
      ${{ if ne(pair.key, 'steps') }}:
        ${{ pair.key }}: ${{ pair.value }}
    steps:                            
    - task: CredScan@1 
    - ${{ job.steps }} 
    - task: PublishMyTelemetry@1 
      condition: always()

範本強制執行

範本作為安全機制的有效性取決於強制執行。 強制執行範本使用方式的關鍵控制點是 受保護的資源

您可以設定代理程式集區或其他受保護資源(例如存放庫)的核准和檢查。 如需範例,請參閱 新增存放庫資源檢查

必要範本

若要強制使用特定範本,請在資源的服務連線上設定 必要範本 驗證。 只有在管線從範本延伸時,才會套用這項檢查。

當您檢視管線作業時,您可以監視檢查的狀態。 如果管線未從所需的範本延伸,檢查就會失敗。

顯示核准失敗檢查的螢幕快照。

當您使用必要的範本時,檢查會通過。

顯示通過核准檢查的螢幕快照。

例如,下列 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 }}

下列範例管線會 擴充params.yml 範本,並要求它進行核准。 若要示範管線失敗,請註解掉對extends引用。

# azure-pipeline.yml

resources:
 containers:
     - container: my-container
       endpoint: my-service-connection
       image: mycontainerimages

extends:
    template: params.yml
    parameters:
        yesNo: true
        image: 'windows-latest'