Azure DevOps YAML Pipeline 權限控管與安全防護全解析

14 分鐘閱讀

原本要寫英文問句,寫到一半發現我英文太菜,就變成半英半中了😆

琳 avatar

About Azure DevOps Pipeline: YAML vs Classic Pipelines, I had heard that Classic Pipeline 可以設定獨立的權限控管,使得僅 Build Admin 可以變更 Pipeline 而 Contributor 不行;YAML Pipeline 只要能提交變更的 Contributor 都可能變更 Pipeline 內容,所以更推薦使用 Classic Pipeline.

我想請你研究官方文件確認它的真實性,告訴我是否能在 YAML Pipeline 中禁止一般 Contributor 變更 Pipeline YAML 檔案。

Felo Search avatar
Felo Search

您的觀察點出了 Classic 與 YAML Pipelines 權限控管模型的根本差異。

傳統 Classic Pipeline 的權限控管較為直接,但 YAML Pipeline 透過將管線定義程式碼化的方式,提供了更細緻且更符合現代 Git 工作流程的深度防禦策略。雖然一般 Contributor 理論上可以編輯儲存庫中的任何檔案,但 Azure DevOps 提供了多層次的機制來有效禁止他們任意變更 Pipeline YAML 檔案。

關鍵在於,保護 YAML Pipeline 的重點已從單純的 UI 權限設定轉移到對原始程式碼儲存庫的治理。

透過結合分支原則、必要拉取請求 (Pull Request)、程式碼審核、執行條件檢查以及 YAML 範本,不僅可以達成與 Classic Pipeline 相同的控管效果,甚至能實現更嚴格、更安全的 CI/CD 流程。直接修改 Edit build pipeline 權限對 YAML 檔案本身無效,但結合儲存庫原則可以完全鎖定其變更權限。

權限模型的根本差異:Classic vs. YAML

Classic Pipelines 的權限模型

在傳統的 Classic Pipeline 中,管線的定義(包含任務、步驟、變數等)是作為一個獨立的物件儲存在 Azure DevOps 服務內,而非儲存庫中 1。因此,其權限控管非常直觀:

這種方式簡單明瞭,因為它將管線的「定義權」與程式碼的「提交權」完全分開。

YAML Pipelines 的權限模型

YAML Pipeline 的核心理念是「管線即程式碼」(Pipeline as Code) 56。管線定義本身就是一個 YAML 檔案(通常是 azure-pipelines.yml),與您的應用程式程式碼一同存放在 Git 儲存庫中 7。這個轉變導致了權限模型的根本性變化:

YAML Pipeline 的潛在安全風險

您所擔憂的情境是真實存在的,且在社群中有廣泛討論。如果沒有適當的防護措施,一個惡意或無心的 Contributor 可能會利用其儲存庫權限帶來風險:

保護 YAML Pipeline 的多層次防禦策略

雖然 Contributor 預設可以編輯 YAML 檔案,但 Azure DevOps 提供了一系列強大的工具來鎖定和保護它。這些策略的核心是將安全控制融入 Git 工作流程中。

1. 透過分支原則強制執行程式碼審核

這是最基本且最有效的防線。您可以針對重要的分支(例如 mainreleases/*)設定分支原則,以確保沒有任何變更可以未經審查就合併進去 12

下圖展示了如何在分支原則中針對特定路徑新增自動審核者:

2. 在 YAML 內部進行執行階段檢查

為了防堵在個人分支上執行惡意管線的漏洞,您可以在 azure-pipelines.yml 檔案的開頭加入條件檢查,限制此管線只能在指定的分支上執行。

# azure-pipelines.yml

trigger:
- main

pool:
  vmImage: 'ubuntu-latest'

steps:
# 第一步:驗證分支是否為 main
- script: |
    echo "Checking branch: $(Build.SourceBranchName)"
    if [ "$(Build.SourceBranchName)" != "refs/heads/main" ]; then
      echo "##vso[task.logissue type=error]This pipeline can only be run on the main branch."
      exit 1
    fi
  displayName: 'Verify source branch'

# 後續的建構與部署步驟...
- script: echo "Running build steps on main branch..."

3. 使用 YAML 範本 (Templates) 實現集中控管

這是最高級也最安全的作法,它能將管線的核心邏輯抽取出來,由專門的團隊進行維護,而開發人員只能在受限的框架內進行操作 15

以下是一個範例,展示如何使用 extends 範本來限制可執行的任務:

# 位於受保護的範本儲存庫:templates/secure-template.yml
parameters:
- name: userSteps
  type: stepList
  default: []

jobs:
- job: SecureBuild
  steps:
  - script: echo "Mandatory security scan..." # 強制執行的安全步驟
  
  # 遍歷開發人員傳入的步驟
  - ${{ each step in parameters.userSteps }}:
    # 檢查是否為被禁止的 script 任務
    - ${{ if contains(step, 'script') }}:
        # 若包含 script,則引發 YAML 語法錯誤來中斷管線
        'script-is-not-allowed': error 
    - ${{ else }}:
        # 若非 script,則正常插入步驟
        - ${{ step }}

  - script: echo "Mandatory signing step..." # 強制執行的簽署步驟
# 位於開發人員的儲存庫:azure-pipelines.yml
# 強制繼承自安全範本
extends:
  template: secure-template.yml@templates # @templates 指向範本儲存庫
  parameters:
    userSteps:
    - task: Npm@1 # 允許的任務
      inputs:
        command: 'install'
    - script: 'echo "This will be rejected"' # 這個步驟會被範本拒絕,導致管線失敗

結論

您的觀察點出了 Classic 與 YAML Pipeline 在權限管理上的差異,但「YAML Pipeline 較不安全」的結論並不成立。事實上,YAML Pipeline 透過將管線程式碼化的方式,將安全控制提升到了另一個層次。

YAML Pipeline 仰賴 Git flow 來防止惡意變更;而 Classic Pipeline 則是透過傳統的 RBAC 管控。

就我的個人觀點來說,人類總是會犯錯,應該盡可能地將安全防護自動化、程式化,減少對人類判斷的依賴。 將重要的 Pipeline 檔案放在 Contributor 可以直接修改的儲存庫中和日常變更混在一起,再仰賴人類去審核阻擋它,並不是一個理想的安全設計。但是將 Pipeline 檔案獨立到另一個儲存庫中,在小型專案團隊中也有點過度設計。

因此 Classic Pipeline 仍然有其存在的價值。

  1. 給我來點自動化- Pipeline 簡介與策略思考 - iT 邦幫忙

  2. How to restrict edit access to Azure pipeline?

  3. 关于权限、访问和安全组- Azure DevOps - Microsoft Learn

  4. Can't edit pipelines even though I am the administrator.

  5. Customize your pipeline - Azure Pipelines | Microsoft Learn

  6. [Azure DevOps] 使用Azure Pipelines 实现CI - dino.c - 博客园

  7. Customize your pipeline - Azure Pipelines | Microsoft Learn

  8. git - Protect Azure Pipeline Yaml File from Being Edited - Stack Overflow ↩2 ↩3 ↩4 ↩5

  9. My "Edit Build Pipeline" Permissions in Azure DevOps are set ...

  10. My "Edit Build Pipeline" Permissions in Azure DevOps are ...

  11. Protect Azure Pipeline Yaml File from Being Edited ↩2 ↩3 ↩4

  12. Git branch policies and settings - Azure Repos

  13. Disable creation of classic pipelines - Azure DevOps Blog

  14. How do I restrict pipelines to specific branches without using ...

  15. How to use YAML templates for reusable and secure pipelines - Azure Pipelines | Microsoft Learn ↩2 ↩3

  16. How to use YAML templates for reusable and secure pipelines

  17. How to use YAML templates for reusable and secure pipelines