在 Azure DevOps 中使用服務主體和受控識別
Azure DevOps Services
注意
Azure Active Directory (Azure AD) 現在更名為 Microsoft Entra ID。 如需詳細資訊,請參閱 Azure AD 的新名稱。
將 Microsoft Entra 服務主體和受控識別新增為應用程式身分識別,納入您的 Azure DevOps Services 組織,以便授予它們存取組織資源的權限。 針對許多小組,當您驗證公司中支援自動化工作流程的應用程式時,這項功能可以是個人存取令牌(PAT)的可行和慣用替代方案。
關於服務主體和受控識別
服務主體 是Microsoft Entra 應用程式內的安全性物件,可定義應用程式在指定租使用者中可以執行的動作。 它們會在應用程式註冊程式期間於 Azure 入口網站 中設定,並設定為存取 Azure 資源,例如 Azure DevOps。 藉由將服務主體新增至您的組織,並在其中設定許可權,我們可以判斷服務主體是否有權存取您的組織資源,以及哪些服務主體。
受控識別 是另一個Microsoft Entra 功能,其作用類似於應用程式的服務主體。 這些物件提供 Azure 資源的身分識別,並允許支援 Microsoft Entra 驗證的服務輕鬆共享認證。 它們是一個吸引人的選項,因為Microsoft Entra ID 負責認證管理和輪替。 雖然在 Azure 入口網站上設定受控識別可能會看起來不同,但 Azure DevOps 會將這兩個安全性物件視為組織中具有已定義許可權的新應用程式身分識別相同。 在本文中的其餘部分,除非指定,否則我們會將受控識別和服務主體交替稱為服務主體。
使用下列步驟向 Azure DevOps 驗證這些身分識別,以允許他們代表自己執行動作。
設定受控識別和服務主體
您的實作可能會有所不同,但概括而言,下列步驟可協助您開始在工作流程中使用服務主體。 若要跟著做,請考慮查看我們的 範例應用程式。
1.建立新的受控識別或應用程式服務主體
在 Azure 入口網站 中建立應用程式服務主體或受控識別。
選項1:建立應用程式服務主體
當您建立新的應用程式註冊時,會在Microsoft Entra ID 中建立應用程式物件。 應用程式 服務主體 是指定租用戶的這個應用程式物件的表示法。 當您將應用程式註冊為多租用戶應用程式時,有一個唯一的服務主體物件,代表應用程式新增至的每個租用戶的應用程式物件。
進一步資訊:
選項 2:建立受控識別
在 Azure 入口網站 中建立受控識別與使用服務主體設定應用程式有很大的不同。 開始建立程式之前,您必須先考慮您要建立的受控識別類型:
- 系統指派的受控識別: 某些 Azure 服務可讓您直接在服務實例上啟用受控識別。 啟用系統指派的受控識別時,會在 Microsoft Entra 中建立身分識別。 身分識別會繫結至該服務執行個體的生命週期。 因此,當刪除資源時,Azure 會自動為您刪除身分識別。 根據設計,只有該 Azure 資源可以使用此身分識別,自 Microsoft Entra ID 要求權杖。
- 使用者指派的受控識別 您也可以建立受控識別作為獨立 Azure 資源,方法是建立使用者指派的受控識別,並將它指派給 Azure 服務的一或多個實例。 若是使用者指派的受控識別,則會分別管理身分識別與使用該身分識別的資源。
如需詳細資訊,請參閱下列文章和影片:
2.將服務主體新增至 Azure DevOps 組織
在 Microsoft Entra 系統管理中心設定服務主體之後,您必須在 Azure DevOps 中將服務主體新增至您的組織來執行相同的動作。 您可以透過 [使用者] 頁面 或使用 ServicePrincipalEntitlements API 來新增它們。 由於他們無法以互動方式登入,因此可以將使用者新增至組織、專案或小組的使用者帳戶必須新增。 當啟用[允許小組和專案管理員邀請新使用者] 原則時,這類使用者包括專案集合管理員(PCA)或專案管理員和小組管理員。
提示
若要將服務主體新增至組織,請輸入應用程式或受控識別的顯示名稱。 如果您選擇透過 ServicePrincipalEntitlements
API以程式設計方式新增服務主體,請務必傳入 服務主體的物件識別碼,而不是應用程式的物件識別碼。
如果您是 PCA,您也可以將特定專案的存取權授與服務主體,並指派授權。 如果您不是 PCA,您必須連絡 PCA 以更新任何專案成員資格或授權存取層級。
注意
您只能為組織所連線的租使用者新增受控識別或服務主體。 服務主體可以設為多租戶,以同時存取多個租戶。 受管識別只能屬於單一租用戶。 若要存取不同租使用者中的受控識別,請參閱 常見問題中的因應措施。
3.設定服務主體的許可權
將服務主體新增至組織之後,您可以將其視為與標準用戶帳戶類似。 您可以直接在服務主體上指派許可權、將許可權新增至安全組和小組、將其指派給任何存取層級,並從組織中移除。 您也可以使用 Service Principal Graph APIs
對服務主體執行 CRUD 作業。
設定這些許可權可能與您用來為其他 Azure 資源在 Microsoft Entra 應用程式中設定應用程式許可權的方式不同。 Azure DevOps 不會依賴透過 Azure 入口網站 的應用程式註冊可用的「應用程式許可權」設定。 這些應用程式許可權會將許可權套用至所有與租用戶相關聯的組織中的服務主體,而不知曉 Azure DevOps 中的組織、專案或物件許可權。 為了向服務主體提供更細微的權限,我們依賴自己的權限模型,而非Microsoft Entra ID。
4.管理服務主體
服務主體的管理與用戶帳戶不同,主要方式如下:
- 服務主體沒有電子郵件,因此無法透過電子郵件邀請他們加入組織。
- 授權的群組規則目前不適用於服務主體。 如果您想要將存取層級指派給服務主體,最好直接這麼做。
- 服務主體可以新增至Microsoft Entra 群組(在 Azure 入口網站中)。 目前存在技術限制,無法讓我們在Microsoft Entra 群組成員清單中顯示它們。 Azure DevOps 群組沒有這項限制。 也就是說,服務主體仍然繼承其所屬Microsoft Entra 群組上設定的任何群組許可權。
- 使用者不會因為系統管理員建立某個群組並將 Microsoft Entra 群組新增至其中,就立即成為 Azure DevOps 組織的一部分。 我們有一個稱為「具體化」的程式,一旦使用者第一次從Microsoft Entra 群組登入組織,就會發生此程式。 登入組織的用戶可讓我們判斷應授與哪些用戶授權。 由於服務主體無法登入,系統管理員必須如先前所述明確地將它新增至組織。
- 您無法在 Azure DevOps 上修改服務主體的顯示名稱或虛擬人偶。
- 即使已選取 多組織計費,服務主體也會在他們新增的每個組織中取得授權。
5. 取得 Microsoft Entra ID 令牌
(a) 以程式設計方式取得Microsoft Entra ID 令牌
您可以遵循 Microsoft Entra ID 檔,來取得受控識別的存取令牌。 請參閱 服務主體的範例, 和 受控識別。
傳回的存取令牌是具有已定義角色的 JSON Web 令牌 (JWT),可用來使用令牌作為 Bearer存取組織資源。
(b) 使用 Azure CLI 取得Microsoft Entra ID 令牌
針對臨機操作,透過 Azure CLI 取得一次性Microsoft Entra 識別碼令牌可能比較容易。 對於不需要定期輪替永續性令牌的作業,例如 API 呼叫或 Git 複製作業,建議使用此方法。
必要條件
- zh-TW: Azure 租戶識別碼和訂用帳戶識別碼:請確保訂用帳戶與您嘗試存取的 Azure DevOps 組織的租戶相關聯。 如果您不知道租用戶或訂用帳戶標識碼,您可以在 azure 入口網站 中找到該標識碼。
- Azure 應用程式用戶端識別碼和客戶端密碼
- Azure CLI
Databricks 文件提供這些指示,您可以在 其頁面找到更多詳細資訊。
- 使用
az devops login
命令,以服務主體身分登入 Azure CLI。 - 請遵循畫面上的指示並完成登入。
# 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
- 輸入 命令,為已登入的服務主體設定正確的訂用帳戶:
az account set -s <subscription-id>
- 使用 Azure DevOps 資源識別碼
az account get-access-token
產生Microsoft Entra ID 存取令牌:499b84ac-1321-427f-aa17-267ca6975798
。
$accessToken = az account get-access-token --resource 499b84ac-1321-427f-aa17-267ca6975798 --query "accessToken" --output tsv
- 現在,您可以使用
az cli
每個一般命令。 接下來我們嘗試透過在標頭中添加Bearer
令牌來呼叫 Azure DevOps API:
$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
注意
使用 Azure DevOps 應用程式識別碼,而非我們的資源 URI 來產生令牌。
6.使用 Microsoft Entra 標識符令牌向 Azure DevOps 資源進行驗證
在下列影片範例中,我們會從使用 PAT 進行驗證,移至使用服務主體中的令牌。 我們從使用用戶端密碼進行驗證開始,然後使用用戶端憑證移至 。
另一個範例示範如何在 Azure 函式中使用使用者指派的受控識別來連線到 Azure DevOps。
在範例 應用程式集合中尋找應用程式程序代碼,以遵循這些範例。
除了進行 Azure DevOps REST API 呼叫之外,還有一些使用服務主體進行驗證的常見案例,請參閱下列檔:
- 使用 Nuget.exe 或 dotnet將服務主體連接至 NuGet 套件源。
- 使用您的服務主體,透過命令行 將延伸模塊發行至 Visual Studio Marketplace。
- 在 Azure Pipelines 中 由服務主體或受控識別支援
建立無秘密的服務連線。 - 使用服務主體和 Git 認證管理員來複製存放庫
服務主體與使用者有何不同
- 您無法在 Azure DevOps 上修改服務主體的顯示名稱或虛擬人偶。
- 服務主體會將其視為其加入之每個組織的授權,即使 多組織計費也一樣。
- 服務主體不可以是組織擁有者或建立組織。
- 服務主體無法建立令牌,例如 個人存取令牌(PAT) 或 SSH 密鑰。 他們可以產生自己的Microsoft Entra ID 令牌來呼叫 Azure DevOps REST API。
- 服務主體不支援 Azure DevOps OAuth。
常見問題集
問:為何應該使用服務主體或受控識別,而不是 PAT?
答:我們的許多客戶都尋求服務主體或受控識別,以取代現有的 PAT(個人存取令牌)。 這類 PAT 通常屬於服務帳戶(共用小組帳戶),其會使用這些帳戶向 Azure DevOps 資源驗證應用程式。 PAT 必須如此頻繁地輪換一次(至少 180 天)。 不當儲存的 PAT 可能會落入錯誤的手中,並持續其通常較長的壽命。 Microsoft Entra 令牌每小時到期,在洩漏時會限制整體風險因素。 針對常見的 PAT 案例,我們 分享一些範例,以瞭解如何使用 Microsoft Entra 令牌來探索,而不是。
您無法使用服務主體來建立個人存取令牌。
問:服務主體和受控識別的速率限制為何?
答:服務主體和受控識別的速率限制 與使用者
問:使用此功能的成本會更高嗎?
答:根據存取層級,服務主體和受控識別的價格類似使用者。 一個值得注意的變更是我們如何對待服務主體的「多組織計費」。 無論用戶位於哪個組織,使用者只會被視為一個授權。 服務主體會依每位組織的使用者身分計算為一個授權。 此案例類似於標準「使用者指派型計費」。
問:我可以將來自不同租使用者的受控識別新增至我的組織嗎?
答:您只能從組織所連線的相同租使用者新增受控識別。 不過,我們有一個因應措施,可讓您在「資源租使用者」中設定受控識別,其中是您所有的資源。 然後,您可以在組織連線所在的「目標租使用者」中,讓服務主體使用它。 請執行下列步驟作為因應措施:
- 在資源租使用者 Azure 入口網站 中建立使用者指派的受控識別。
- 將它連線到 虛擬機,並將此受控識別 指派給虛擬機。
- 建立 金鑰保存庫 併產生 憑證 (不能為 “PEM” 類型)。 當您產生此憑證時,也會產生具有相同名稱的秘密,以供稍後使用。
- 授與受控識別的存取權,以便從密鑰保存庫讀取私鑰。 使用 [取得/清單] 許可權在密鑰保存庫中建立存取原則(在 [秘密許可權] 下,然後在 [選取主體] 下搜尋受控識別。
- 以 「CER」 格式下載已建立的憑證,以確保它不包含憑證的私人部分。
- 在目標租使用者中建立新的應用程式註冊。
- 在 [憑證與秘密] 索引標籤中,將下載的憑證上傳至這個新的應用程式。
- 將此應用程式的服務主體新增至我們想要存取的 Azure DevOps 組織,並記得使用任何必要許可權設定服務主體。
- 從此服務主體取得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;
}
潛在錯誤
名稱或標識符為 『{repoName
}』 的 Git 存放庫不存在,或您沒有嘗試作業的許可權。
請確定服務主體至少有 「基本」授權 存取存放庫。 「利害關係人」許可證不夠充分。
無法建立物件標識碼為 『{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'} 身分登入一次,以啟用服務的存取權。
如果未邀請服務主體加入組織,您可能會遇到下列錯誤。 請確定服務主體已新增至適當的組織,並具有存取任何必要資源所需的所有許可權。