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

解决PowerShell中Azure AD服务主体权限替换而非累加的问题

解决权限被替换而非累加的问题

核心原因

两个函数执行时权限被替换,大概率是函数内部添加新权限前未保留已有权限(比如误执行了移除所有权限的操作,或是用了会覆盖现有权限的命令),或是没有对要添加的权限做去重校验,导致重复操作触发覆盖逻辑。

具体修改方案

我们可以调整Add-Two-Permissions函数,让它合并Add-Permissions中的Microsoft Graph角色权限,再统一添加所有需要的权限,同时确保只添加服务主体尚未拥有的权限。

步骤1:整合权限集合

先把两个函数的权限按类型区分整合:

# 来自Add-Permissions的Microsoft Graph应用权限(角色权限)
$graphAppPermissions = @('User.Read.All','Group.Read.All','GroupMember.Read.All','GroupMember.ReadWrite.All','Directory.Read.All','AuditLog.Read.All')
# Add-Two-Permissions中的Windows Azure Service Management API委派权限(示例为user_impersonation,替换为你的实际权限)
$azureMgmtPermissions = @('user_impersonation')
# Add-Two-Permissions中的Microsoft Graph委派权限(替换为你的实际权限)
$graphDelegatedPermissions = @('示例范围权限1','示例范围权限2')

步骤2:修改函数实现累加逻辑

以下是调整后的Add-Two-Permissions函数(基于AzureAD模块,若使用Az模块可对应替换命令):

function Add-Two-Permissions {
    param(
        [Parameter(Mandatory=$true)]
        [string]$ServicePrincipalId # 服务主体的ObjectId或AppId
    )

    # 定义所有需要添加的权限
    $graphAppPermissions = @('User.Read.All','Group.Read.All','GroupMember.Read.All','GroupMember.ReadWrite.All','Directory.Read.All','AuditLog.Read.All')
    $azureMgmtResourceId = "797f4846-ba00-4fd7-ba43-dac1f8f63013" # Windows Azure Service Management API固定资源ID
    $azureMgmtPermissions = @('user_impersonation')
    $graphResourceId = "00000003-0000-0000-c000-000000000000" # Microsoft Graph固定资源ID
    $graphDelegatedPermissions = @('示例范围权限1','示例范围权限2')

    # 获取目标服务主体
    $sp = Get-AzureADServicePrincipal -Filter "ObjectId eq '$ServicePrincipalId' or AppId eq '$ServicePrincipalId'"
    if (-not $sp) {
        Write-Error "未找到指定的服务主体"
        return
    }

    # --------------------------
    # 处理Microsoft Graph应用权限
    # --------------------------
    $graphSp = Get-AzureADServicePrincipal -Filter "AppId eq '$graphResourceId'"
    $existingAppRoles = Get-AzureADServicePrincipalAppRoleAssignment -ObjectId $sp.ObjectId | Where-Object {$_.ResourceId -eq $graphSp.ObjectId}
    $existingAppRoleIds = $existingAppRoles | ForEach-Object {$_.Id}

    foreach ($perm in $graphAppPermissions) {
        $targetRole = $graphSp.AppRoles | Where-Object {$_.Value -eq $perm}
        if ($targetRole -and $targetRole.Id -notin $existingAppRoleIds) {
            New-AzureADServicePrincipalAppRoleAssignment -ObjectId $sp.ObjectId -ResourceId $graphSp.ObjectId -Id $targetRole.Id -PrincipalId $sp.ObjectId
            Write-Host "已添加Microsoft Graph应用权限:$perm"
        } elseif ($targetRole -and $targetRole.Id -in $existingAppRoleIds) {
            Write-Host "服务主体已拥有Microsoft Graph应用权限:$perm,跳过"
        } else {
            Write-Warning "未找到Microsoft Graph应用权限:$perm"
        }
    }

    # --------------------------
    # 处理Windows Azure Service Management API委派权限
    # --------------------------
    $azureMgmtSp = Get-AzureADServicePrincipal -Filter "AppId eq '$azureMgmtResourceId'"
    $existingOAuthGrants = Get-AzureADServicePrincipalOAuth2PermissionGrant -All $true | Where-Object {$_.ClientId -eq $sp.ObjectId}
    $existingScopes = $existingOAuthGrants | ForEach-Object {$_.Scope -split ' '}

    foreach ($perm in $azureMgmtPermissions) {
        $targetScope = $azureMgmtSp.OAuth2Permissions | Where-Object {$_.Value -eq $perm}
        if ($targetScope -and $perm -notin $existingScopes) {
            New-AzureADServicePrincipalOAuth2PermissionGrant -ClientId $sp.ObjectId -ResourceId $azureMgmtSp.ObjectId -Scope $perm -ConsentType "AllPrincipals"
            Write-Host "已添加Windows Azure Service Management API权限:$perm"
        } elseif ($targetScope -and $perm -in $existingScopes) {
            Write-Host "服务主体已拥有Windows Azure Service Management API权限:$perm,跳过"
        } else {
            Write-Warning "未找到Windows Azure Service Management API权限:$perm"
        }
    }

    # --------------------------
    # 处理Microsoft Graph委派权限
    # --------------------------
    foreach ($perm in $graphDelegatedPermissions) {
        $targetScope = $graphSp.OAuth2Permissions | Where-Object {$_.Value -eq $perm}
        if ($targetScope -and $perm -notin $existingScopes) {
            New-AzureADServicePrincipalOAuth2PermissionGrant -ClientId $sp.ObjectId -ResourceId $graphSp.ObjectId -Scope $perm -ConsentType "AllPrincipals"
            Write-Host "已添加Microsoft Graph委派权限:$perm"
        } elseif ($targetScope -and $perm -in $existingScopes) {
            Write-Host "服务主体已拥有Microsoft Graph委派权限:$perm,跳过"
        } else {
            Write-Warning "未找到Microsoft Graph委派权限:$perm"
        }
    }
}

关键说明

  • 权限去重:先获取服务主体已有的应用角色分配和OAuth2权限授予,对比要添加的权限,只添加未存在的条目,避免重复或覆盖。
  • 权限类型区分:应用权限(角色权限)用New-AzureADServicePrincipalAppRoleAssignment添加,委派权限(范围权限)用New-AzureADServicePrincipalOAuth2PermissionGrant添加,两类逻辑分开处理。
  • 固定资源ID:Windows Azure Service Management API和Microsoft Graph的资源ID是固定值,无需修改。

替代方案:修改原函数逻辑

如果不想重构Add-Two-Permissions,也可以给Add-Permissions加上上述的去重逻辑,然后先调用Add-Permissions再调用Add-Two-Permissions,这样两个函数执行时会自动累加权限。


内容的提问来源于stack exchange,提问作者Harry

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 04:15:15