存取 Azure DevOps 與 Microsoft Entra 工作負載身分識別

Azure DevOps 服務

備註

這項功能將於本週和下週陸續推出。 如果你還沒在 Azure DevOps Services 專案看到這個功能,幾天後再回來看看。

Azure DevOps 服務連線,允許你的管線透過使用 Microsoft Entra 工作負載身份,在無需個人存取權杖(PAT)的情況下,對 Azure DevOps 進行認證。 服務主體與受控身份透過工作負載身份聯合存取 Azure DevOps,這是一種無需密碼的方法,免除管理與輪替秘密的需求。

福利

  • 免 PAT 認證:消除建立、儲存及輪換 個人存取令牌的需求。
  • 最低權限:使用每個管線權限,而非共用 建置服務帳號權限
  • 提升安全性:使用 Entra 聯邦憑證並自動輪換令牌。
  • 跨組織存取:透過單一服務連線存取不同組織Azure DevOps資源。
  • 稽核軌跡:所有驗證嘗試皆登錄於Azure DevOps稽核日誌中。

支援的案例

Azure DevOps 服務連線支援以下情境:

  • Repository resources:查看不同Azure DevOps組織的程式碼庫。
  • Artifact feeds:存取組織間的 Azure Artifacts feed(NuGet、npm、Maven、Python、Cargo、Conda),無需 PAT 即可。
  • REST API 呼叫:從內嵌腳本認證至 Azure DevOps REST API。
  • Extension publishing:將擴充內容發佈到 Visual Studio Marketplace。

先決條件

要建立 Azure DevOps 服務連線,你需要:

  • Azure DevOps 組織
  • Entra 服務主體或管理身份 用於認證
  • CreatorAdministrator 角色,負責在 Azure DevOps 專案中管理服務連線。 預設情況下, 端點創建者 群組的成員擁有創建者角色。 欲了解更多資訊,請參閱 設定服務連線安全性
  • 若跨組織存取資源,必須將服務主體或託管身分新增為每個目標組織的使用者。

步驟一:在同一組織內建立服務連結

如果你的服務主體與服務連線在同一個 Azure DevOps 組織中:

將服務負責人加入你的組織

  1. 在你的Azure DevOps組織中,請前往 Organization Settings>Users

  2. 選取 [ 新增使用者]。

  3. 請輸入服務負責人的詳細資料:

    • 名稱:服務主體或受管理身份名稱或物件識別碼
    • 存取等級:選擇適當的存取權限。 使用 Basic 進行標準存取
  4. 將服務主體或管理身份指派到你將建立服務連線的專案中,例如將其加入 Readers 群組

  5. 選取 [新增] 並確認。

  6. 將任何額外的資源層級權限分配給服務主體或受管理身份

步驟二:建立服務連結

  1. 在你的 Azure DevOps 專案中,請前往 專案設定>服務連接

  2. 選取 [新增服務連線]

  3. 選擇 Azure DevOps 作為服務連線類型。

  4. 完成表單:

    • 身份:選擇你新增到組織的服務主體
    • 服務連接名稱:輸入連接的描述性名稱(例如, my-azdo-connection
    • 描述 (可選):補充連結目的細節
  5. 選擇 儲存 以建立服務連結。

建立跨組織存取的服務連線

若要存取與同一 Entra ID 租戶結合的不同 Azure DevOps 組織中的資源:

  1. 請依照「 在同一組織內建立服務連結」的步驟,但在建立服務連結時選擇 「不同組織 」。

  2. 輸入目標 Azure DevOps 組織名稱。

  3. 你也必須 將服務主體新增為 目標組織的使用者。

在你的管線中使用服務連線

查看不同組織的資料庫

pool:
  vmImage: 'ubuntu-latest'

resources:
  repositories:
  - repository: external-repo
    type: git
    endpoint: my-azdo-connection
    name: 'external-project/external-repo'
    ref: 'refs/heads/main'

steps:
- checkout: self
- checkout: external-repo

參考其他組織的範本

resources:
  repositories:
    - repository: templates 
      type: git
      endpoint: my-azdo-connection
      name: 'external-project/external-repo'
      ref: "refs/heads/main"    
      
steps:
- template: azdosc-template.yml@templates

存取工件饋源

在工件認證任務中使用服務連線:

- task: NuGetAuthenticate@1
  inputs:
    nuGetServiceConnections: 'my-azdo-connection'

- task: DotNetCoreCLI@2
  inputs:
    command: 'restore'
    projects: '**/*.csproj'

從腳本呼叫 Azure DevOps

- task: AzureCLI@3
  displayName: Secret-less
  inputs:
    connectionType: 'azureDevOps'
    azureDevOpsServiceConnection: 'my-azdo-connection'
    scriptType: 'pscore'
    scriptLocation: 'inlineScript'
    inlineScript: |
      az rest --method get `
              --url "https://status.dev.azure.com/_apis/status/health?api-version=7.1-preview.1" `
              --resource 499b84ac-1321-427f-aa17-267ca6975798 `
              --query "sort_by(services[?id=='Pipelines'].geographies | [], &name)" `
              -o table

      az devops configure -l

      az devops project list --query "value[].{Name:name, Id:id}" `
                            -o table

      az pipelines pool list --query "[].{Id:id, Name:name}" `
                            -o table

- task: AzureCLI@3
  displayName: Use Entra access token
  inputs:
    connectionType: 'azureDevOps'
    azureDevOpsServiceConnection: 'my-azdo-connection'
    scriptType: 'pscore'
    scriptLocation: 'inlineScript'
    inlineScript: |
      # Get access token for Azure DevOps
      $token = az account get-access-token --resource "499b84ac-1321-427f-aa17-267ca6975798" `
                                           --query "accessToken" `
                                           --output tsv
      
      # Use token in REST API call
      $headers = @{
        Authorization = "Bearer $token"
        "Content-Type" = "application/json"
      }
      
      $body = @{
        name = "Test Build"
      } | ConvertTo-Json
      
      Invoke-RestMethod -Uri "$(System.CollectionUri)$(System.TeamProject)/_apis/build/definitions?api-version=7.1" `
                        -Method POST `
                        -Headers $headers `
                        -Body $body

AzureCLI@3任務使用 Azure DevOps CLI,該程式預裝於Microsoft託管代理程式。 在自架代理程式上,你需要 Azure CLI 以及 azure-devops。 如果擴充功能尚未安裝, azure-devops AzureCLI@3任務會在執行時安裝它。

安全性最佳做法

  • 最小權限:只指派服務主體它為特定管線任務所需的權限。
  • 稽核存取:定期檢視稽核日誌以監控服務連線使用情況。
  • 範圍使用:為不同專案或組織使用獨立的服務連線,以限制共享權限。

Troubleshooting

小提示

為了提升安全性,請只指派服務主體所需的權限,定期檢視稽核日誌,並為不同專案或組織分別使用獨立的服務連線。

服務連線建立失敗

原因: 服務主體沒有被加入你的組織,或者你沒有必要的權限。

修正:

管線無法驗證

原因: 服務連線名稱與 YAML 參考不符,或是服務主體缺乏目標資源的權限。

修正:

  • 檢查你的管線 YAML 中的服務連線名稱是否與你建立的名稱相符。
  • 檢查服務主體是否對你所存取的資源擁有適當的權限。
  • 請檢查 Azure DevOps 的稽核日誌是否有認證失敗。
  • 請參閱 服務負責人與受管身份常見問題。
  • 關於Microsoft Entra AADSTS 狀態碼,請查看 錯誤訊息清單。

跨組織存取無法運作

原因: 你沒有把服務主體加為兩個組織的使用者,或者你把目標組織名稱拼錯了。

修正:

  • 在兩個組織中都將服務主體加入 為使用者
  • 檢查服務連線設定中目標組織名稱是否正確拼寫。
  • 檢查服務主體在目標組織中是否擁有所需的權限。

常見的錯誤訊息

Message 意義與緩解措施
錯誤:TF401444:請至少在網頁瀏覽器中以 72f988bf-86f1-41af-91ab-2d7cd011db47\72f988bf-86f1-41af-91ab-2d7cd011db47\115c3ab3-943b-4e0c-96ed-1a1763fbaa44 登入一次,以啟用服務存取權限。 檢查你是否將服務主體 新增為組織的使用者
管理身份/服務主體<sp/msi name> 無法存取Azure DevOps組織 <org>。 請確認該身分已經添加到組織中。 請參閱 https://aka.ms/azdosc#prerequisites 將服務主體新增為目標組織的 使用者 ,並指派到所需的專案中。
你沒有權限使用所選身份。 服務連線已儲存為草稿。 要完成設定,請聯絡身份擁有者,在 Azure 入口網站中使用下方的發行者與主體識別碼建立聯邦憑證。 已登入的使用者沒有足夠的權限來建立聯邦憑證。 依照顯示的指示,直接在身份上建立聯邦憑證。
VS800075:ID 為「vstfs:///Classification/TeamProject/00000000-0000-00000000-000000000000」的專案不存在,或您沒有權限存取。 服務連線身份不會被加入專案中。 前往服務連結詳情頁面>查看目前組織中的存取權限>的會員資格>,選擇一個群組以將身份加入,例如Readers群組。 或者,前往組織設定>使用者>,選擇使用在服務連線中的身份,>,然後選取該身份需要存取的專案。

Microsoft Entra ID 錯誤訊息

下表列出常見的 Microsoft Entra ID 錯誤代碼及與工作負載身份服務連線相關的可能問題:

Message 可能的問題
AADSTS700016:找不到標識符為 '****' 的應用程式 用於服務連線的身分識別已不存在、可能已從服務連線中移除或設定不正確。 如果您使用預先建立的身分識別手動設定服務連線,請確定 appID/clientId 已正確設定 。
AADSTS7000215:提供的客戶端密碼無效。 您使用的服務連線其憑證已經過期。 將服務連線轉換為工作負載身分識別同盟 ,並以同盟認證取代過期的秘密。
AADSTS700024:用戶端宣告不在有效的時間範圍內 如果錯誤發生在大約 1 小時後,請改為使用 工作負載身分識別聯盟和受控識別 的服務連線。 受控識別令牌的 存留期約為24小時
如果錯誤發生在 1 小時前但 10 分鐘後,請將那些(隱含地)請求存取權杖(例如存取 Azure 儲存)的指令移到腳本的開頭。 存取權杖會被快取以供後續指令使用。
AADSTS70021:找不到與提供的聲明相符的聯邦身分識別記錄。 聲明發行者:https://app.vstoken.visualstudio.com 未建立同盟認證,或簽發者 URL 不正確。 正確的簽發者 URL 格式 https://login.microsoftonline.com/XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX為 。 您可以透過編輯並儲存服務連線來修正簽發者 URL。 如果 Azure DevOps 沒有建立你的身份,你必須手動更新發行人。 您可以在服務連接的編輯對話框中找到正確的頒發者,如果使用 REST API,則可以在回應中找到正確的頒發者。
AADSTS70021:找不到與提供的聲明相符的聯邦身分識別記錄。 聲明發行者:https://login.microsoftonline.com/XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX。 斷言主題: sc://<org>/<project>/<service-connection>. 簽發者 URL 或聯盟主體不一致。 Azure DevOps 組織或專案被重新命名,或手動建立的服務連線被重新命名,而未更新身分識別中的聯邦對象。
AADSTS700211:找不到提供的聲明簽發者的相符同盟身份記錄 未建立同盟認證,或簽發者 URL 不正確。
AADSTS700213:找不到與提供的宣告主體相符的聯邦身分識別記錄 未建立聯邦憑證,或主體不正確。
AADSTS700223 工作負載身份聯合在 Microsoft Entra 租戶上被限制或停用。 在此案例中,可能會改用同盟的受控識別。 如需更多訊息,請參閱使用受控識別的工作負載身分識別
AADSTS70025:用戶端應用程式未設定同盟身分識別認證 請確定已在應用程式註冊或受控識別上設定同盟認證。
Microsoft Entra 拒絕了Azure DevOps發出的憑證,錯誤代碼為 AADSTS700238 工作負載身份聯盟在 Microsoft Entra 租戶上受到限制。 您組織的簽發者 (https://login.microsoftonline.com/XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX) 不允許將工作負載身分識別同盟與您正在使用的工作負載身分識別類型 (應用程式註冊和/或受控識別) 搭配使用。 請向您的 Microsoft Entra 租戶管理員或管理團隊請求,允許 Azure DevOps 組織進行工作負載身份聯邦。
AADSTS70052:身分識別必須是受管理的身分識別、單一租用戶應用程式或服務帳戶 多租戶應用程式包含signInAudience: AzureADMultipleOrgs的註冊,目前不被 Microsoft Entra 發行者支援。 使用 signInAudience: AzureADMyOrg 並分割對多個租用戶的存取權,以改為針對每個租用戶使用不同的服務連線。 若您依賴 ARM 操作,在單一請求中存取多個租戶(例如虛擬網路的跨租戶對等連接),您可以聯絡支援,讓您的 Azure DevOps 組織改用 Azure DevOps 發行者。
AADSTS900382:跨雲端不支援機密用戶端 某些主權雲端會封鎖工作負載身分識別同盟。

您所看到的 AADSTS 錯誤是否沒有列在上面? 請檢查 Microsoft Entra 驗證與授權錯誤碼

下一步