使用服務主體和受控識別

Azure DevOps Services

將 Microsoft Entra 服務主體和受控識別新增至 Azure DevOps 組織,以授與組織資源的存取權。 針對許多小組,當您驗證公司中支援自動化工作流程的應用程式時,這項功能可以是個人存取令牌(PAT)的可行和慣用替代方案

關於服務主體和受控識別

服務主體 是 Microsoft Entra 應用程式內的安全性物件,可定義應用程式可在指定租用戶中執行的動作。 它們會在應用程式註冊程式期間於 Azure 入口網站 中設定,並設定為存取 Azure 資源,例如 Azure DevOps。 藉由將服務主體新增至您的組織,並在其中設定許可權,我們可以判斷服務主體是否有權存取您的組織資源,以及哪些服務主體。

受控識別 是另一個與應用程式服務主體類似的 Microsoft Entra 功能。 這些物件提供 Azure 資源的身分識別,並允許支援 Microsoft Entra 驗證的服務輕鬆共享認證。 它們是吸引人的選項,因為 Microsoft Entra ID 會負責認證管理和輪替。 雖然受控識別的設定在 Azure 入口網站 上看起來可能不同,但 Azure DevOps 會將這兩個安全性對象視為組織中具有定義許可權的新身分識別相同。 在本文中的其餘部分,除非指定,否則我們會將受控識別和服務主體交替稱為服務主體。

使用下列步驟向 Azure DevOps 驗證這些身分識別,以允許他們代表自己執行動作。

設定受控識別和服務主體

您的實作可能會有所不同,但概括而言,下列步驟可協助您開始在工作流程中使用服務主體。 請考慮查看我們的 其中一個範例應用程式 ,以自行遵循範例。

1.建立新的受控識別或應用程式服務主體

Azure 入口網站 中建立應用程式服務主體或受控識別。

建立應用程式服務主體

當您建立新的應用程式註冊時,會在 Microsoft Entra ID 中建立應用程式物件。 應用程式 服務主體 是指定租用戶的這個應用程式物件的表示法。 當您將應用程式註冊為多租用戶應用程式時,有一個唯一的服務主體物件,代表應用程式新增至的每個租用戶的應用程式物件。

進一步資訊:

建立受控識別

在 Azure 入口網站 中建立受控識別與使用服務主體設定應用程式有很大的不同。 開始建立程式之前,您必須先考慮您要建立的受控識別類型:

  • 系統指派的受控識別: 某些 Azure 服務可讓您直接在服務實例上啟用受控識別。 啟用系統指派的受控識別時,會在 Microsoft Entra 中建立身分識別。 身分識別會繫結至該服務執行個體的生命週期。 因此,當刪除資源時,Azure 會自動為您刪除身分識別。 根據設計,只有該 Azure 資源可以使用此身分識別,自 Microsoft Entra ID 要求權杖。
  • 使用者指派的受控識別 您也可以建立受控識別作為獨立 Azure 資源,方法是建立使用者指派的受控識別,並將它指派給 Azure 服務的一或多個實例。 若是使用者指派的受控識別,則會分別管理身分識別與使用該身分識別的資源。

如需詳細資訊,請參閱下列文章和影片:

2.在 Azure DevOps 組織中新增及管理服務主體

在 Microsoft Entra 系統管理中心設定服務主體之後,您必須在 Azure DevOps 中執行相同的動作,方法是將服務主體新增至您的組織。 您可以透過 [使用者] 頁面 或使用 ServicePrincipalEntitlements API 來新增它們。 由於他們無法以互動方式登入,因此可以將使用者新增至組織、專案或小組的使用者帳戶必須新增。 這類使用者包括 Project Collection 管理員 istrators (PCA) 或 Project 管理員 istrators 和 Team 管理員 istrators,當啟用[允許小組和專案管理員邀請新使用者] 原則

提示

若要將服務主體新增至組織,請輸入應用程式或受控識別的顯示名稱。 如果您選擇透過 ServicePrincipalEntitlements API 以程式設計方式新增服務主體,請務必傳入 服務主體的物件識別碼 ,而不是應用程式的物件標識碼。

如果您是 PCA,您也可以將特定專案的存取權授與服務主體,並指派授權。 如果您不是 PCA,您必須連絡 PCA 以更新任何專案成員資格或授權存取層級。

Screenshot of service principals and managed identities in the Users Hub.

注意

您只能為組織所連線的租使用者新增受控識別或服務主體。 若要存取不同租使用者中的受控識別,請參閱 常見問題中的因應措施。

將服務主體新增至組織之後,您可以將其視為與標準用戶帳戶類似。 您可以直接在服務主體上指派許可權、將許可權新增至安全組和小組、將其指派給任何存取層級,並從組織中移除。 您也可以使用 Service Principal Graph APIs 對服務主體執行 CRUD 作業。

服務主體的管理與用戶帳戶不同,主要方式如下:

  • 服務主體沒有電子郵件,因此無法透過電子郵件邀請他們加入組織。
  • 授權的群組規則目前不適用於服務主體。 如果您想要將存取層級指派給服務主體,最好直接這麼做。
  • 雖然服務主體可以新增至 Microsoft Entra 群組(在 Azure 入口網站 中),但我們目前的技術限制可防止我們在 Microsoft Entra 群組成員清單中顯示它們。 Azure DevOps 群組沒有這項限制。 也就是說,服務主體仍然繼承其所屬 Microsoft Entra 群組上設定的任何群組許可權。
  • 並非 Microsoft Entra 群組中的所有使用者都立即屬於 Azure DevOps 組織的一部分,只是因為系統管理員建立群組並將 Microsoft Entra 群組新增至其中。 我們有一個稱為「具體化」的程式,一旦 Microsoft Entra 群組的使用者第一次登入組織,就會發生此程式。 登入組織的用戶可讓我們判斷應授與哪些用戶授權。 由於服務主體無法登入,系統管理員必須如先前所述明確地將它新增至組織。
  • 您無法在 Azure DevOps 上修改服務主體的顯示名稱或虛擬人偶。
  • 即使已選取多組織計費服務主體也會計算為其新增至的每個組織的授權。

3.使用 Microsoft Entra ID 令牌存取 Azure DevOps 資源

取得 Microsoft Entra 識別碼令牌

您可以遵循 Microsoft Entra ID 檔來取得受控識別的存取令牌。 如需詳細資訊,請參閱服務主體受控識別的範例。

傳回的存取令牌是具有已定義角色的 JWT,可用來使用令牌作為 持有人存取組織資源。

使用 Microsoft Entra 識別碼令牌向 Azure DevOps 資源進行驗證

在下列影片範例中,我們會從使用 PAT 進行驗證,移至使用服務主體中的令牌。 我們從使用用戶端密碼進行驗證開始,然後使用用戶端憑證移至 。

  • 雖然服務主體可以新增至 Microsoft Entra ID 群組(在 Azure 入口網站 中),但我們目前的技術限制可防止我們在 Microsoft Entra ID 群組成員清單中顯示它們。 Azure DevOps 群組沒有這項限制。 也就是說,服務主體仍會繼承其所屬 Microsoft Entra ID 群組上設定的任何群組許可權。
  • 並非 Microsoft Entra 識別符群組中的所有使用者都是 Azure DevOps 組織的一部分,只是因為系統管理員建立群組並將 Microsoft Entra ID 群組新增至其中。 我們有一個稱為「具體化」的程式,一旦 Microsoft Entra ID 群組的使用者第一次登入組織,就會發生此程式。 登入組織的用戶可讓我們判斷應授與哪些用戶授權。 由於服務主體無法登入,系統管理員必須如先前所述明確地將它新增至組織。
  • 您無法在 Azure DevOps 上修改服務主體的顯示名稱或虛擬人偶。
  • 即使已選取多組織計費服務主體也會計算為其新增至的每個組織的授權。

另一個範例示範如何在 Azure 函式中使用使用者指派的受控識別來連線到 Azure DevOps。

在範例 應用程式集合中尋找應用程式程序代碼,以遵循這些範例。

服務主體可用來呼叫 Azure DevOps REST API 並執行大部分的動作,但受限於下列作業:

注意

您只能使用應用程式識別碼,而不是與 Azure DevOps 相關聯的資源 URI 來產生令牌。

常見問題集

一般

問:為何應該使用服務主體或受控識別,而不是 PAT?

答:我們的許多客戶都尋求服務主體或受控識別,以取代現有的 PAT(個人存取令牌)。 這類 PAT 通常屬於服務帳戶(共用小組帳戶),其會使用這些帳戶向 Azure DevOps 資源驗證應用程式。 PAT 必須如此頻繁地輪換一次(至少 180 天)。 由於 PAT 只是持有人令牌,這表示代表用戶使用者名稱和密碼的令牌字串,因此很難使用它們,因為它們很容易落入錯誤的人的手中。 Microsoft Entra 令牌每小時到期,且必須使用重新整理令牌重新產生,才能取得新的存取令牌,這會在外泄時限制整體風險因素。

您無法使用服務主體來建立個人存取令牌。

問:服務主體和受控識別的速率限制為何?

答:目前,服務主體和受控識別的速率限制與使用者相同

問:使用此功能的成本會更高嗎?

答:根據存取層級,服務主體和受控識別的價格類似使用者。 一個值得注意的變更是我們如何對待服務主體的「多組織計費」。 無論用戶位於哪個組織,使用者只會被視為一個授權。 服務主體會依每位組織的使用者身分計算為一個授權。 此案例類似於標準「使用者指派型計費」。

問:我可以搭配 Azure CLI 使用服務主體或受控識別嗎?

答:是的! 在 Azure CLI 中要求 PAT 的任何位置,也可以接受 Microsoft Entra ID 存取令牌。 如需如何在 中傳遞 Microsoft Entra 令牌,以向 CLI 進行驗證,請參閱這些範例。

# To authenticate with a command: After typing this command, the az devops login will prompt you to enter a token. You can add an Entra ID token too! Not just a PAT.
az devops login

# To authenticate a service principal with a password or cert:
az login --service-principal -u <app-id> -p <password-or-cert> --tenant <tenant>

# To authenticate a managed identity:
az login --identity

現在,讓我們取得 Microsoft Entra 令牌(Azure DevOps 資源的 UUID 為 499b84ac-1321-427f-aa17-267ca6975798),並嘗試藉由將標頭中傳遞為 Bearer 令牌來呼叫 Azure DevOps API:

Write-Host "Obtain access token for Service Connection identity..."
$accessToken = az account get-access-token --resource 499b84ac-1321-427f-aa17-267ca6975798 --query "accessToken" --output tsv

Write-Host "Use access token with Azure DevOps REST API to list projects in the organization..."
$apiVersion = "7.1-preview.1"
$uri = "https://dev.azure.com/${yourOrgname}/_apis/projects?api-version=${apiVersion}"
$headers = @{
    Accept = "application/json"
    Authorization = "Bearer $accessToken"
}
Invoke-RestMethod -Uri $uri -Headers $headers -Method Get | Select-Object -ExpandProperty value ` | Select-Object id, name

現在,您可以使用 az cli 每個一般命令。

問:我可以將來自不同租使用者的受控識別新增至我的組織嗎?

答:您只能從組織所連線的相同租使用者新增受控識別。 不過,我們有一個因應措施,可讓您在「資源租使用者」中設定受控識別,其中是您所有的資源。 然後,您可以在組織連線所在的「目標租使用者」中,讓服務主體使用它。 請執行下列步驟作為因應措施:

  1. 在資源租使用者 Azure 入口網站 中建立使用者指派的受控識別
  2. 連線 至虛擬機,並將此受控識別指派給虛擬機。
  3. 建立 金鑰保存庫 併產生 憑證 (不能為 “PEM” 類型)。 當您產生此憑證時,也會產生具有相同名稱的秘密,以供稍後使用。
  4. 授與受控識別的存取權,以便從密鑰保存庫讀取私鑰。 使用 [取得/清單] 許可權在密鑰保存庫中建立存取原則(在 [秘密許可權] 下,然後在 [選取主體] 下搜尋受控識別。
  5. 以 「CER」 格式下載已建立的憑證,以確保它不包含憑證的私人部分。
  6. 在目標租使用者中建立新的應用程式註冊。
  7. 在 [憑證與秘密] 索引標籤中,將下載的憑證上傳至這個新的應用程式。
  8. 將此應用程式的服務主體新增至我們想要存取Azure DevOps 組織,並記得使用任何必要許可權設定服務主體。
  9. 若要從使用此使用受控識別憑證的服務主體取得 Microsoft Entra 存取令牌,請參閱下列程式代碼範例:

注意

您必須一如既往地輪替憑證。

public static async Task<string> GetSecret(string keyVaultName, string secretName)
{
	var keyVaultUri = new Uri("https://" + keyVaultName + ".vault.azure.net");
	var client = new SecretClient(keyVaultUri, new ManagedIdentityCredential());
	var keyVaultSecret = await client.GetSecretAsync(secretName);

	var secret = keyVaultSecret.Value;
	return secret.Value;
}

private static async Task<AuthenticationResult> GetAppRegistrationAADAccessToken(string applicationClientID, string appTenantId)
{
	IConfidentialClientApplication app;

	byte[] privateKeyBytes = Convert.FromBase64String(GetSecret(keyVaultName, secretName));
	X509Certificate2 certificateWithPrivateKey = new X509Certificate2(privateKeyBytes, (string)null, X509KeyStorageFlags.MachineKeySet);

	app = ConfidentialClientApplicationBuilder.Create(applicationClientID)
		.WithCertificate(certificateWithPrivateKey)
		.WithAuthority(new Uri(string.Format(CultureInfo.InvariantCulture, "https://login.microsoftonline.com/{0}", appTenantId)))
		.Build();
	app.AddInMemoryTokenCache();

	string AdoAppClientID = "499b84ac-1321-427f-aa17-267ca6975798/.default";
	string[] scopes = new string[] { AdoAppClientID };

	var result = await app.AcquireTokenForClient(scopes).ExecuteAsync();

	return result;
}

Artifacts

問:我可以使用服務主體來連線到摘要嗎?

答:是,您可以使用服務主體連線到任何 Azure Artifacts 摘要。 在下列範例中,我們示範如何使用 NuGet、npm 和 Maven 的 Microsoft Entra ID 令牌進行連線,但其他摘要類型也應該運作。

使用 Microsoft Entra 令牌設定 NuGet 專案
  1. 在與 .csproj.sln 檔案相同的資料夾中,將 nuget.config 檔案新增至您的專案。

    <?xml version="1.0" encoding="utf-8"?>
    <configuration>
      <packageSources>
        <clear />
        <add key="FeedName" value="https://pkgs.dev.azure.com/<ORGANIZATION_NAME>/<PROJECT_NAME>/_packaging/<FEED_NAME>/nuget/v3/index.json" />
      </packageSources>
    </configuration>
    
  2. 取得服務主體的 Microsoft Entra 識別碼令牌

  3. 執行下列命令以使用您的認證進行驗證,然後使用 setapikey 命令新增令牌。 此命令會將摘要來源新增至 nuget.config:

    nuget sources add -name <FEED_NAME> -source <SOURCE_URL> -username <USERNAME> -password <PASSWORD>
    
    nuget setapikey <YOUR_ACCESS_TOKEN> -source <SOURCE_URL> 
    

使用 Microsoft Entra 令牌設定 npm 專案

注意

vsts-npm-auth 工具不支援 Microsoft Entra 存取令牌。

  1. .npmrc將 新增至專案,位於與 package.json相同的目錄中。

    registry=https://pkgs.dev.azure.com/Fabrikam/_packaging/FabrikamFeed/npm/registry/ 
    always-auth=true
    
  2. 取得服務主體或受控識別的存取令牌。

  3. 將此程式代碼新增至您的 ${user.home}/.npmrc ,並將 佔位元 [AAD_SERVICE_PRINCIPAL_ACCESS_TOKEN] 取代為上一個步驟中的存取令牌。

    //pkgs.dev.azure.com/Fabrikam/_packaging/FabrikamFeed/npm/:_authToken=[AAD_SERVICE_PRINCIPAL_ACCESS_TOKEN]
    

使用 Microsoft Entra 令牌設定 Maven 專案
  1. 將存放庫新增至您的 pom.xml<repositories><distributionManagement> 區段。

    <repository>
      <id>Fabrikam</id>
      <url>https://pkgs.dev.azure.com/Fabrikam/_packaging/FabrikamFeed/maven/v1</url>
      <releases>
        <enabled>true</enabled>
      </releases>
      <snapshots>
        <enabled>true</enabled>
      </snapshots>
    </repository>
    
  2. 取得服務主體或受控識別的存取令牌。

  3. 在 中${user.home}/.m2新增或編輯檔案,settings.xml並將 佔位元[AAD_SERVICE_PRINCIPAL_ACCESS_TOKEN]取代為上一個步驟中的存取令牌。

    <settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
              xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
              xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0
                                  https://maven.apache.org/xsd/settings-1.0.0.xsd">
      <servers>
        <server>
          <id>Fabrikam</id>
          <username>Fabrikam</username>
          <password>[AAD_SERVICE_PRINCIPAL_ACCESS_TOKEN]</password>
        </server>
      </servers>
    </settings>
    

市場平台

問:我可以使用服務主體將擴充功能發佈至 Visual Studio Marketplace 嗎?

A: 可以。 請執行下列步驟。

  1. 將服務主體新增為發行者帳戶的成員。 您可以使用設定檔 - 取得,從其設定檔取得服務主體的識別碼。 然後,您可以使用 上一個步驟中的標識符,將服務主體新增為發行者的成員

  2. 使用 SP 透過 TFX CLI 發佈延伸模組。 執行下列 TFX CLI 命令以使用 SP 存取權杖:

tfx extension publish --publisher my-publisher --vsix my-publisher.my-extension-1.0.0.vsix --auth-type pat -t <AAD_ACCESS_TOKEN>

管線

問:我可以在服務聯機中使用受控識別嗎? 如何更輕鬆地在服務連線中輪替服務主體的秘密? 我是否可以避免將秘密完全儲存在服務連線中?

Azure 支援 使用 OpenID 連線 通訊協定的工作負載身分識別同盟,這可讓我們在 Azure Pipelines 中建立無秘密的服務連線,並由服務主體或受控識別搭配 Microsoft Entra ID 中的同盟認證。 在其執行中,管線可以使用 Microsoft Entra 令牌交換自己的內部令牌,藉此取得 Azure 資源的存取權。 實作之後,建議在產品中使用此機制,以使用 目前存在的其他類型的 Azure 服務連線 。 此機制也可以用來設定任何其他 OIDC 相容服務提供者的無秘密部署。 此機制處於預覽狀態。

Repos

問:我是否可以使用服務主體來執行 Git 作業,例如複製存放庫?

答:請參閱下列範例,說明我們如何傳遞 服務主體的 Microsoft Entra ID 令牌 ,而不是 PAT,以在 PowerShell 腳本中複製存放庫。

$ServicePrincipalAadAccessToken = 'Entra ID access token of a service principal'
git -c http.extraheader="AUTHORIZATION: bearer $ServicePrincipalAadAccessToken" clone https://dev.azure.com/{yourOrgName}/{yourProjectName}/_git/{yourRepoName}

提示

若要讓您的令牌更安全,請使用認證管理員,因此您不需要每次輸入認證。 我們建議 使用 Git 認證管理員,如果環境變數變更,可以接受 Microsoft Entra 令牌(也就是 Microsoft Identity OAuth 令牌), 而不是 PAT。

如何從 Azure CLI 取得存取令牌以呼叫 git fetch 的實用秘訣:

  1. 開啟存放庫的 Git 組態:
git config -e
  1. 新增下列幾行,其中 Azure DevOps 資源的 UUID 為 499b84ac-1321-427f-aa17-267ca6975798
[credential]
    helper = "!f() { test \"$1\" = get && echo \"password=$(az account get-access-token --resource 499b84ac-1321-427f-aa17-267ca6975798 --query accessToken -o tsv)\"; }; f" 
  1. 測試其運作方式:
GIT_TRACE=1 GCM_TRACE=1 GIT_CURL_VERBOSE=1 git fetch

潛在錯誤

無法建立物件標識碼為 『{provided objectId}』 的服務主體

租用戶中沒有任何服務主體 provided objectId 已連線到您的組織。 其中一個常見原因是您傳入應用程式註冊的物件標識碼,而不是其服務主體的對象標識碼。 請記住,服務主體是代表指定租使用者之應用程式的物件,而不是應用程式本身。 service principal object ID您可以在租使用者的[企業應用程式] 頁面中找到 。 搜尋應用程式的名稱,然後選取傳回的「企業應用程式」結果。 此結果是服務主體/企業應用程式的頁面,您可以使用此頁面上找到的對象識別碼,在 Azure DevOps 中建立服務主體。

拒絕存取: {ID of the caller identity} 需要資源使用者的下列許可權,才能執行此動作:新增使用者

此錯誤可能是因為下列其中一個原因所造成:

  • 您不是組織、專案集合管理員或專案或小組管理員的擁有者。
  • 您是專案或小組管理員,但 已停用「允許小組和專案管理員邀請新使用者」 的原則。
  • 您是可以邀請新使用者的專案或小組系統管理員,但您正嘗試在邀請新使用者時指派授權。 不允許專案或小組系統管理員將授權指派給新使用者。 新使用者的預設存取層級會新增 任何新的受邀使用者。 請連絡 PCA 以變更授權存取層級。

Azure DevOps Graph 清單 API 會傳回空的清單,即使我們知道組織中有服務主體

Azure DevOps Graph 清單 API 可能會傳回空白清單,即使仍有更多使用者要傳回的頁面也一樣。 continuationToken使用 來逐一查看清單,您最終可以找到傳回服務主體的頁面。 continuationToken如果 傳回 ,這表示透過 API 提供更多結果。 雖然我們計劃改善此邏輯,但目前,第一個 X 結果可能會傳回空白。

TF401444:在網頁瀏覽器中至少以 {tenantId'tenantId\servicePrincipalObjectId'} 身分登入一次,以啟用服務的存取權。

如果未邀請服務主體加入組織,您可能會遇到下列錯誤。 請確定服務主體已新增至適當的組織,並具有存取任何必要資源所需的所有許可權。