Azure DevOps Services | Azure DevOps Server 2022 - Azure DevOps Server 2019
注意
我们正在推出新的 Azure 服务连接创建体验。 在你的组织中接收它取决于各种因素,你仍可能会看到较旧的用户体验。
你可以使用 Azure 资源管理器服务连接来连接到 Azure 资源,例如管道中的 Azure Key Vault。 通过此连接,你可以使用管道部署到 Azure 资源(例如 Azure 应用程序服务应用),无需每次都进行身份验证。
有多个身份验证选项可用于使用 Azure 资源管理器服务连接来连接到 Azure。 建议将 工作负荷标识联合 与应用注册或托管标识配合使用。 工作负荷标识联合可以消除机密和机密管理的需求。
建议的选项:
- 应用注册(自动)与工作负荷身份联合认证
- 用于创建工作负载身份联合凭据并连接到现有用户分配的托管身份的托管身份。 如果 无权创建应用注册,请使用此选项。
- 应用注册或托管标识(手动),与工作负荷标识联合身份验证或机密。 手动配置比自动配置更耗时,仅当已尝试自动选项时,才应使用。
注意
有其他不使用工作负荷身份联合的 Azure 资源管理服务连接身份验证选项。 这些选项可用于向后兼容性以及特殊情况,但不建议使用。 如果是第一次设置服务连接,请使用工作负载身份联合。 如果您已经有服务连接,请首先尝试将其转换为使用工作负载身份联合认证。
使用工作负荷身份验证联合创建应用注册(自动)
- 你拥有 Azure 订阅的所有者角色。
- 你未连接到 Azure Stack 或 Azure 美国政府 环境。
- 你使用的任何市场扩展任务都经过了更新,以支持工作负载标识联合身份验证。
通过此选项,Azure DevOps 会自动查询您要连接到的订阅、管理组或机器学习工作区,并创建用于身份验证的工作负载联合身份验证。
> 在 Azure DevOps 项目中,转到“项目设置”“服务连接”。
有关详细信息,请参阅 “打开项目设置”。
选择 “新建服务连接”,然后选择 “Azure 资源管理器 ”和 “下一步”。
选择具有工作负荷标识联合凭据的应用注册(自动)。
选择 范围级别。 选择 “订阅”、“ 管理组”或 “机器学习工作区”。 管理组 是容器,有助于管理跨多个订阅的访问、策略和合规性。 机器学习工作区用于创建机器学习项目。
对于 订阅 范围,请输入以下参数:
参数 说明 订阅 必需。 选择 Azure 订阅。 资源组 可选。 选择 Azure 资源组。 对于 管理组 范围,请选择 Azure 管理组。
对于 机器学习工作区 范围,请输入以下参数:
参数 说明 订阅 必需。 选择 Azure 订阅。 资源组 必需。 选择包含工作区的资源组。 机器学习工作区 必需。 选择 Azure 机器学习工作区。
输入 服务连接名称。
(可选)输入服务连接的说明。
选择 “授予对所有管道的访问权限 ”可让所有管道使用此连接。 不建议使用此选项。 而是 单独授权每个管道使用服务连接。
选择“ 保存”。
为现有用户分配的托管标识创建服务连接
使用此选项为现有用户分配的托管标识自动创建工作负荷标识凭据。 在开始之前,需要拥有 现有的用户分配的托管标识 。
> 在 Azure DevOps 项目中,转到“项目设置”“服务连接”。
有关详细信息,请参阅 “打开项目设置”。
选择 “新建服务连接”,然后选择 “Azure 资源管理器 ”和 “下一步”。
选择“托管标识” 。
在 步骤 1:托管标识详细信息:
- 选择托管身份的订阅。 这是包含托管标识的 Azure 订阅。
- 选择用于托管标识的资源组。 这是包含托管标识的资源组。
- 选择“托管标识”。 这是资源组中将用于访问资源的托管标识。
在 步骤 2:Azure 范围:
选择 范围级别。 选择 “订阅”、“ 管理组”或 “机器学习工作区”。 管理组 是容器,有助于管理跨多个订阅的访问、策略和合规性。 机器学习工作区用于创建机器学习项目。
对于 订阅 范围,请输入以下参数:
参数 说明 服务连接的订阅 必需。 选择托管标识将访问的 Azure 订阅名称。 服务连接的资源组 可选。 输入数据以便只让一个资源组访问托管标识。 对于 管理组 范围,请输入以下参数:
参数 说明 管理组 必需。 选择 Azure 管理组。 对于 机器学习工作区 范围,请输入以下参数:
参数 说明 订阅 必需。 选择 Azure 订阅名称。 服务连接的资源组 可选。 选择包含工作区的资源组。 ML 工作空间 必需。 输入现有 Azure 机器学习工作区的名称。
在 步骤 3:服务连接详细信息: 部分,输入或选择以下参数:
参数 说明 服务连接名称 必需。 在任务属性中引用此服务连接时将使用的名称。 不是 Azure 订阅的名称。 服务管理参考 可选。 ITSM 数据库中的上下文信息。 描述 可选。 输入服务连接的说明。 在“ 安全 ”部分中,选择“ 授予对所有管道的访问权限 ”,以允许所有管道使用此服务连接。 如果未选择此选项,则必须手动授予对使用此服务连接的每个管道的访问权限。
选择 “保存” 以验证并创建服务连接。
将现有服务连接转换为使用工作负载标识联合身份验证
你可以快速转换现有的 Azure 资源管理器服务连接,以使用工作负载标识联合身份验证而不是机密进行身份验证。 如果服务连接满足这些要求,则可以在 Azure DevOps 中使用服务连接转换工具:
- Azure DevOps 最初创建了服务连接。 如果你手动创建服务连接,则无法使用服务连接转换工具转换服务连接,因为 Azure DevOps 无权修改自己的凭据。
- 只有一个项目使用服务连接。 无法转换 跨项目服务连接。
若要转换服务连接,请执行以下操作:
> 在 Azure DevOps 项目中,转到“项目设置”“服务连接”。
有关详细信息,请参阅 “打开项目设置”。
选择要转换为使用工作负载标识的服务连接。
选择“转换”。
如果现有凭据的机密已过期,你将看到一个不同的转换选项。
再次选择“转换”,确认你想要创建新的服务连接。
转换可能需要几分钟时间。 如果要还原连接,必须在七天内还原它。
使用脚本转换多个服务连接
使用脚本同时更新多个服务连接,以立即使用工作负荷标识联合身份验证进行身份验证。
此示例 PowerShell 脚本需要两个参数:Azure DevOps 组织(示例:https://dev.azure.com/fabrikam-tailspin
)和 Azure DevOps 项目(示例:Space game web agent
)。 然后,该脚本检索 Azure DevOps 项目和组织的相关服务连接。
将服务连接转换为使用工作负载联合身份验证时,系统会提示您对每个尚未使用它的连接确认更新。 确认后,脚本通过 Azure DevOps REST API 更新这些服务连接以使用工作负荷联合身份验证。
该脚本需要 PowerShell 7.3 或更高版本 和 Azure CLI 才能运行。 将此脚本保存为 .ps1
文件,然后用 PowerShell 7 运行此文件。
#!/usr/bin/env pwsh
<#
.SYNOPSIS
Convert multiple Azure Resource Manager service connection(s) to use Workload identity federation
.LINK
https://aka.ms/azdo-rm-workload-identity-conversion
.EXAMPLE
./convert_azurerm_service_connection_to_oidc_simple.ps1 -Project <project> -OrganizationUrl https://dev.azure.com/<organization>
#>
#Requires -Version 7.3
param (
[parameter(Mandatory=$true,HelpMessage="Name of the Azure DevOps Project")]
[string]
[ValidateNotNullOrEmpty()]
$Project,
[parameter(Mandatory=$true,HelpMessage="Url of the Azure DevOps Organization")]
[uri]
[ValidateNotNullOrEmpty()]
$OrganizationUrl
)
$apiVersion = "7.1"
$PSNativeCommandArgumentPassing = "Standard"
#-----------------------------------------------------------
# Log in to Azure
$azdoResource = "499b84ac-1321-427f-aa17-267ca6975798" # application id of Azure DevOps
az login --allow-no-subscriptions --scope ${azdoResource}/.default
$OrganizationUrl = $OrganizationUrl.ToString().Trim('/')
#-----------------------------------------------------------
# Retrieve the service connection
$getApiUrl = "${OrganizationUrl}/${Project}/_apis/serviceendpoint/endpoints?authSchemes=ServicePrincipal&type=azurerm&includeFailed=false&includeDetails=true&api-version=${apiVersion}"
az rest --resource $azdoResource -u "${getApiUrl} " -m GET --query "sort_by(value[?authorization.scheme=='ServicePrincipal' && data.creationMode=='Automatic' && !(isShared && serviceEndpointProjectReferences[0].projectReference.name!='${Project}')],&name)" -o json `
| Tee-Object -Variable rawResponse | ConvertFrom-Json | Tee-Object -Variable serviceEndpoints | Format-List | Out-String | Write-Debug
if (!$serviceEndpoints -or ($serviceEndpoints.count-eq 0)) {
Write-Warning "No convertible service connections found"
exit 1
}
foreach ($serviceEndpoint in $serviceEndpoints) {
# Prompt user to confirm conversion
$choices = @(
[System.Management.Automation.Host.ChoiceDescription]::new("&Convert", "Converting service connection '$($serviceEndpoint.name)'...")
[System.Management.Automation.Host.ChoiceDescription]::new("&Skip", "Skipping service connection '$($serviceEndpoint.name)'...")
[System.Management.Automation.Host.ChoiceDescription]::new("&Exit", "Exit script")
)
$prompt = $serviceEndpoint.isShared ? "Convert shared service connection '$($serviceEndpoint.name)'?" : "Convert service connection '$($serviceEndpoint.name)'?"
$decision = $Host.UI.PromptForChoice([string]::Empty, $prompt, $choices, $serviceEndpoint.isShared ? 1 : 0)
if ($decision -eq 0) {
Write-Host "$($choices[$decision].HelpMessage)"
} elseif ($decision -eq 1) {
Write-Host "$($PSStyle.Formatting.Warning)$($choices[$decision].HelpMessage)$($PSStyle.Reset)"
continue
} elseif ($decision -ge 2) {
Write-Host "$($PSStyle.Formatting.Warning)$($choices[$decision].HelpMessage)$($PSStyle.Reset)"
exit
}
# Prepare request body
$serviceEndpoint.authorization.scheme = "WorkloadIdentityFederation"
$serviceEndpoint.data.PSObject.Properties.Remove('revertSchemeDeadline')
$serviceEndpoint | ConvertTo-Json -Depth 4 | Write-Debug
$serviceEndpoint | ConvertTo-Json -Depth 4 -Compress | Set-Variable serviceEndpointRequest
$putApiUrl = "${OrganizationUrl}/${Project}/_apis/serviceendpoint/endpoints/$($serviceEndpoint.id)?operation=ConvertAuthenticationScheme&api-version=${apiVersion}"
# Convert service connection
az rest -u "${putApiUrl} " -m PUT -b $serviceEndpointRequest --headers content-type=application/json --resource $azdoResource -o json `
| ConvertFrom-Json | Set-Variable updatedServiceEndpoint
$updatedServiceEndpoint | ConvertTo-Json -Depth 4 | Write-Debug
if (!$updatedServiceEndpoint) {
Write-Debug "Empty response"
Write-Error "Failed to convert service connection '$($serviceEndpoint.name)'"
exit 1
}
Write-Host "Successfully converted service connection '$($serviceEndpoint.name)'"
}
恢复使用密钥的现有服务连接
你可以在七天内还原转换后的自动服务连接及其机密。 7 天后,手动创建新机密。
如果你手动创建和还原服务连接,则无法使用服务连接转换工具转换服务连接,因为 Azure DevOps 无权修改自己的凭据。
若要转换服务连接,请执行以下操作:
> 在 Azure DevOps 项目中,转到“管道”“服务连接”。
选择要还原的现有服务连接。
选择“将转换还原到原始方案”。
再次选择“还原”以确认所做选择。
创建使用现有服务主体的服务连接
如果要使用一组预定义的访问权限,但尚未为此目的定义服务主体,请按照以下教程之一创建新的服务主体:
要创建使用现有服务主体的服务连接,请执行以下操作:
> 在 Azure DevOps 项目中,转到“项目设置”“服务连接”。
有关详细信息,请参阅 “打开项目设置”。
选择 “新建服务连接”,然后选择 “Azure 资源管理器 ”和 “下一步”。
选择 “服务主体”(手动) 和 “下一步”。
从 “新建 Azure 服务连接 ”对话框中,选择 “环境”。 如果选择 Azure Stack,请输入环境 URL,如下所示
https://management.local.azurestack.external
。选择 范围级别。 选择“订阅”或“管理组”。 管理组 是容器,有助于管理跨多个订阅的访问、策略和合规性。
对于 订阅 范围,请输入以下参数:
参数 说明 订阅 ID 必需。 输入 Azure 订阅 ID。 订阅名称 必需。 输入 Azure 订阅名称。 对于 管理组 范围,请输入以下参数:
参数 说明 管理组 ID 必需。 输入 Azure 管理组 ID。 管理组名称 必需。 输入 Azure 管理组名称。
在 “身份验证 ”部分中,输入或选择以下参数:
参数 说明 服务主体 ID 必需。 输入服务主体 ID。 凭据 选择 “服务主体密钥 ”或 “证书”。 如果选择 了服务主体密钥,请输入密钥(密码)。 如果选择 “证书”,请输入证书。 租户 ID 必需。 输入租户 ID。 验证 选择此选项以验证你输入的设置。 在“详细信息”部分中,输入以下参数:
参数 说明 连接名称 必需。 在任务属性中引用此服务连接时将使用的名称。 不是 Azure 订阅的名称。 描述 可选。 输入服务连接的说明。 安全 选择 “授予对所有管道的访问权限 ”,以允许所有管道使用此服务连接。 如果未选择此选项,则必须手动授予对使用此服务连接的每个管道的访问权限。 选择 “验证并保存 ”以验证并创建服务连接。
帮助和支持
- 浏览 故障排除提示。
- 获取 有关 Stack Overflow 的建议。
- 在 Azure DevOps 开发人员社区中发布问题、搜索答案或建议功能。
- 获取 对 Azure DevOps 的支持。