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.ymlextends範本會定義管道的外部結構,並提供目標自訂的特定點。 在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 安全性功能。
範本也可以重寫使用者步驟,只允許核准的工作執行。 例如,範本可以防止內嵌指令碼執行。
下列範例範本會防止執行指令碼步驟類型 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 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'