透過範本的安全性
Azure DevOps Services |Azure DevOps Server 2022 |Azure DevOps Server 2020
檢查受保護的資源 是 Azure Pipelines 安全性的基本建置組塊。 不論管線的階段和作業結構為何,檢查工作。 如果小組或組織中的數個管線具有相同的結構,您可以進一步簡化使用 範本的安全性。
Azure Pipelines 提供兩種範本: 包括 和 擴充。
包含的範本在 C++ 中的行為就像 #include
在 C++ 中一樣:就像您直接將範本的程式碼貼到外部檔案中一樣,它會參考它。 例如,這裡包含範本 (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
在受限制模式中仍允許的其中一個命令是 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()
範本強制執行
如果您可以強制執行範本,則範本只是安全性機制。 強制使用範本的控制點是 受保護的資源。 您可以在代理程式組件區或其他受保護的資源上設定核准和檢查,例如存放庫。 如需範例,請參閱 新增存放庫資源檢查。
下一步
接下來,瞭解如何透過 變數和參數安全地取得輸入。