Azure DevOps流水线启用VM Trusted Launch时间歇性报LinkedAuthorizationFailed错误
场景概述
通过Azure DevOps流水线,先用Terraform在Azure创建虚拟机,接着在同一流水线内执行PowerShell脚本:停止VM、修改配置启用Trusted Launch后重启。多数情况下流程正常,但间歇性在Update-AzVM步骤失败。
流水线代码片段
pool: vmImage: windows-latest jobs: - job: Build steps: - task: TerraformInstaller@0 displayName: Install terraform inputs: terraformVersion: latest - task: AzureCLI@2 displayName: Create build resources (VM, ...) name: terraform_apply inputs: azureSubscription: <redacted> scriptType: pscore scriptLocation: inlineScript inlineScript: | terraform init if ($LASTEXITCODE -ne 0) { throw "Terraform init failed with exitcode $LASTEXITCODE" } $buildId = "$(Build.BuildNumber)" -replace "\.","-" $prefix = "pipeline-" + $buildId Write-Host "Prefix is $prefix" Write-Host "##vso[task.setvariable variable=resourcePrefix]$prefix" $Env:TF_VAR_prefix="pipeline-$buildId" $imageUrl = "https://<redacted>.blob.core.windows.net/<redacted>.vhd" Write-Host "image_uri is $imageUrl" $Env:TF_VAR_image_uri="$imageUrl" $diskSize = "${{ parameters.diskSize }}" Write-Host "disk_size is $diskSize" $Env:TF_VAR_disk_size="$diskSize" terraform apply -auto-approve if ($LASTEXITCODE -ne 0) { throw "Terraform apply failed with exitcode $LASTEXITCODE" } # Export the IP address for usage in later tasks $ip = (terraform output -json | ConvertFrom-Json).vm_ip.value Write-Host "##vso[task.setvariable variable=vmIp]$ip" Write-Host "IP is: $ip" $vmName = (terraform output -json | ConvertFrom-Json).vm_name.value Write-Host "##vso[task.setvariable variable=vmName]$vmName" Write-Host "VM name is: $vmName" - task: AzurePowerShell@5 displayName: Enabling trusted launch inputs: azureSubscription: <redacted> ScriptType: InlineScript azurePowerShellVersion: LatestVersion Inline: | Stop-AzVM -ResourceGroupName "<redacted>" -Name "$(vmName)" -Force $vm = Get-AzVM -ResourceGroupName "<redacted>" -VMName "$(vmName)" $vm | Update-AzVM -SecurityType TrustedLaunch -EnableSecureBoot $true -EnableVtpm $true Start-AzVM -ResourceGroupName "<redacted>" -Name "$(vmName)"
间歇性错误信息
The client '<redacted>' with object id '<redacted>' has permission to perform action 'Microsoft.Compute/virtualMachines/write' on scope '/subscriptions/<redacted>/resourceGroups/<redacted>/providers/Microsoft.Compute/virtualMachines/<redacted>'; however, it does not have permission to perform action(s) 'Microsoft.ManagedIdentity/userAssignedIdentities/assign/action' on the linked scope(s) '/subscriptions/<redacted>/resourceGroups/Built-In-Identity-RG/providers/Microsoft.ManagedIdentity/userAssignedIdentities/Built-In-Identity-westeurope' (respectively) or the linked scope(s) are invalid. ErrorCode: LinkedAuthorizationFailed StatusCode: 403 ReasonPhrase: Forbidden
解决方案建议
1. 补充服务主体的托管标识权限
错误核心是流水线使用的服务主体,对Built-In-Identity-RG资源组下的用户分配托管标识,缺少Microsoft.ManagedIdentity/userAssignedIdentities/assign/action权限:
- 直接给服务主体在该托管标识资源(或所属资源组)上分配Managed Identity Operator角色,该角色包含所需的分配权限;
- 或者通过自定义RBAC角色,仅授予
Microsoft.ManagedIdentity/userAssignedIdentities/assign/action单个权限,遵循最小权限原则。
2. 添加操作等待与重试逻辑
间歇性失败大概率是Azure资源状态同步延迟导致:Terraform创建VM后,关联的托管标识或RBAC权限未完全生效,就执行了Update操作:
- 等待VM完全停止:在
Stop-AzVM后,添加循环等待,确认VM进入deallocated状态再执行后续操作:Stop-AzVM -ResourceGroupName "<redacted>" -Name "$(vmName)" -Force # 等待VM完全停止 do { Start-Sleep -Seconds 10 $vmStatus = Get-AzVM -ResourceGroupName "<redacted>" -Name "$(vmName)" -Status } while ($vmStatus.Statuses[1].Code -ne 'PowerState/deallocated') - 给Update-AzVM添加重试:用循环包裹Update操作,失败后重试几次:
$retryCount = 3 $retryInterval = 15 $success = $false for ($i=1; $i -le $retryCount; $i++) { try { $vm | Update-AzVM -SecurityType TrustedLaunch -EnableSecureBoot $true -EnableVtpm $true $success = $true break } catch { Write-Warning "Update attempt $i failed: $_" Start-Sleep -Seconds $retryInterval } } if (-not $success) { throw "Failed to update VM after $retryCount attempts" }
3. 统一资源组变量,避免硬编码
当前PowerShell脚本中的资源组是硬编码值,建议改为从Terraform输出或流水线变量获取,比如在Terraform中输出资源组名称,然后在流水线中传递,减少人为错误。
4. 检查Terraform创建的VM配置
确认Terraform创建VM时,是否自动关联了用户分配托管标识。如果是,可考虑在Terraform阶段就配置Trusted Launch,避免后续PowerShell修改,减少跨步骤的状态同步问题。
内容的提问来源于stack exchange,提问作者Thomas Ljungberg Kristensen
相关产品推荐
相关产品推荐

