You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Azure DevOps直接分配用户查询脚本无预期结果求助

问题描述

我编写了一个PowerShell脚本,想要实现以下目标:

  • 获取Azure DevOps中assignmentSource为"direct"的直接分配用户
  • 排除指定的技术账户
  • 从Azure AD获取这些用户的管理器邮箱地址
  • 输出用户邮箱及对应管理器信息

但脚本未返回预期结果:运行时显示找到0个直接分配用户,可实际Azure DevOps中存在此类用户;手动调用Azure DevOps API仅返回自身用户权限,$directUsers.Count始终为0。

附加信息:在macOS上运行PowerShell,使用最新版Microsoft.Graph模块,拥有Azure AD租户所有者权限可读取用户信息。


当前脚本
# Variables
$organization = "org-name"
$azureDevOpsPat = "your-azure-devops-pat"  # PAT with full access
$tenantId = "your-tenant-id"
$clientId = "your-client-id"
$excludedUsers = @(
    "example1@org.com",
    "example2@org.com",
    "example3@org.com"

)

# Scopes for Microsoft Graph
$scopes = @("User.Read.All", "Directory.Read.All")

# Connect to Microsoft Graph
Connect-MgGraph -ClientId $clientId -TenantId $tenantId -Scopes $scopes -DeviceCode

# Azure DevOps API Endpoint
$devOpsApiUrl = "https://vsaex.dev.azure.com/$organization/_apis/userentitlements?api-version=7.0"

# Prepare Azure DevOps API Headers
$devOpsHeaders = @{
    Authorization = ("Basic {0}" -f [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(":$azureDevOpsPat")))
    "Content-Type" = "application/json"
}

# Fetch user entitlements from Azure DevOps
$devOpsResponse = Invoke-RestMethod -Uri $devOpsApiUrl -Headers $devOpsHeaders -Method Get

# Check if the response contains any users
if ($devOpsResponse.count -gt 0) {
    # Include all users with direct assignments
    $directUsers = $devOpsResponse.value | Where-Object {
        $_.accessLevel.assignmentSource -eq "direct"
    }

    foreach ($user in $directUsers) {
        $userEmail = $user.user.mailAddress
        $userPrincipalName = $user.user.principalName

        # Get user identifier for exclusion check (UPN or Email)
        $userIdentifier = if ($userPrincipalName) { $userPrincipalName } else { $userEmail }

        # Check if the user is in the exclusion list
        if ($excludedUsers -contains $userIdentifier) {
            continue
        }

        # Get user details from Microsoft Graph API
        try {
            $userGraphResponse = Get-MgUser -UserId $userIdentifier -ErrorAction Stop
            $userEmail = $userGraphResponse.Mail

            # Get manager's information
            try {
                $managerResponse = Get-MgUserManager -UserId $userIdentifier -ErrorAction Stop
                $managerUpn = $managerResponse.UserPrincipalName
            } catch {
                $managerUpn = $null
            }
        } catch {
            continue
        }

        # Collect email addresses
        if ($userEmail) {
            $userEmailAddresses += $userEmail
        }

        if ($managerUpn) {
            $managerEmailAddresses += $managerUpn
        }
    }

    # Output the lists
    $userEmailsString = $userEmailAddresses -join "; "
    $managerEmailsString = $managerEmailAddresses -join "; "

    Write-Host "User Emails (To): $userEmailsString"
    Write-Host "Manager Emails (CC): $managerEmailsString"
} else {
    Write-Host "No user entitlements found in Azure DevOps."
}

# Disconnect from Microsoft Graph
Disconnect-MgGraph

解决方案

1. 修复Azure DevOps PAT权限

手动调用API仅返回自身权限,说明PAT权限不足。需要给PAT分配**User Entitlements (Read)**权限:

  • 登录Azure DevOps,进入个人设置 -> 个人访问令牌
  • 创建/编辑PAT时,在"User Entitlements"组下勾选Read权限,确保范围覆盖整个组织

2. 处理API分页

Azure DevOps API默认仅返回前100条数据,若用户数量超过100,需添加分页逻辑:

# Fetch user entitlements from Azure DevOps with pagination
$devOpsResponse = @()
$nextUrl = $devOpsApiUrl
do {
    $response = Invoke-RestMethod -Uri $nextUrl -Headers $devOpsHeaders -Method Get
    $devOpsResponse += $response.value
    $nextUrl = $response.nextLink
} while ($nextUrl)

3. 修正用户计数判断逻辑

分页后$devOpsResponse是数组,调整判断逻辑:

# Check if the response contains any users
if ($devOpsResponse.Count -gt 0) {
    # Include all users with direct assignments
    $directUsers = $devOpsResponse | Where-Object {
        $_.accessLevel -and $_.accessLevel.assignmentSource -eq "direct"
    }
    # 后续代码不变
}

4. 初始化集合变量

原脚本中$userEmailAddresses和$managerEmailAddresses未初始化,可能导致意外行为,在循环前添加:

$userEmailAddresses = @()
$managerEmailAddresses = @()

5. 验证accessLevel属性存在性

部分用户可能没有accessLevel属性(如外部用户),添加判断避免报错:

$directUsers = $devOpsResponse | Where-Object {
    $_.accessLevel -and $_.accessLevel.assignmentSource -eq "direct"
}

内容的提问来源于stack exchange,提问作者My ADO Obsession

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 20:55:15