共用方式為


使用範本進行安全性

Azure DevOps Services |Azure DevOps Server 2022 |Azure DevOps Server 2020

本文說明範本如何簡化 Azure Pipelines 的安全性。 範本可以定義管線的外部結構,並協助防止惡意代碼滲透。 範本也可以自動包含執行認證掃描等工作的步驟。 如果小組或組織內的多個管線共用相同的結構,請考慮使用範本。

檢查受保護的資源 會形成 Azure Pipelines 的基本安全性架構。 無論管線結構、階段和作業為何,這些檢查都會套用。 您可以使用範本來協助強制執行這些檢查。

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

先決條件

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

包含和擴充範本

Azure Pipelines 提供 包含擴充 範本。

  • 包含範本會直接在參考範本的外部檔案中包含範本的程式代碼,類似於 #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 }}

下列管線會 擴充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 管線安全性功能

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 代理程式提供給使用者步驟的服務。 使用者步驟會使用 記錄命令來要求服務,這些命令是列印至標準輸出的特製字串。 在受限制模式中,大部分的代理程序服務,例如上傳成品和附加測試結果,都無法使用。

下列範例工作失敗,因為其 target 屬性會指示代理程序不允許發佈成品。

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

restricted 模式中 setvariable ,命令會保持允許,因此需要注意,因為管線變數會匯出為環境變數至後續工作。 如果工作輸出使用者提供的數據,例如透過 REST API 擷取的開啟問題,它們可能會容易受到插入式攻擊。 惡意用戶內容可能會設定可能遭到惡意探索以入侵代理程式主機的環境變數。

為了減輕此風險,管線作者可以使用記錄命令明確宣告哪些變數可設定 setvariable 。 當您指定空白清單時,不允許所有變數設定。

下列範例工作失敗,因為工作只允許設定 expectedVar 變數或前面加上的 ok變數。

- 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 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

範本步驟

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

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 範本,並要求它進行核准。 若要示範管線失敗,請將參考批注化為 params.yml

# azure-pipeline.yml

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

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