最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

azure - Calls for powershell script to remove Delegated API Permissions from app registrations - Stack Overflow

programmeradmin3浏览0评论

I've written a powershell script that essentially goes through app registrations and removes all delegated permissions from them.

Currently I'm using a PATCH request to microsoft graph to set API permissions/requiredResourceAccess (as found here) to be an empty array if there are only delegated api permissions. However if there are application api permissions I'm using an Update-MgApplication command to replace the permissions with only the existing application api permissions.

This is because I was having errors trying to set the body of a PATCH request to be the remaining application api permissions.

I wanted to know if there was a more efficient way to write this script that made use of the correct calls whether it be Microsoft graph or MG powershell commands.

function main {
    $TenantId = "XXX"   

    $Parameters = @{
        TenantId = $TenantId
    }

    Remove-ManifestPermissions @Parameters
}

function Remove-ManifestPermissions
{
    [CmdletBinding()]
    param (
        [Parameter(Mandatory)]
        [Guid]
        $TenantId    
    )

    $requiredScopes = @(
        "Application.ReadWrite.All",
        "DelegatedPermissionGrant.ReadWrite.All"
    )

    $null = Connect-MgGraph -Scopes $requiredScopes -TenantId $TenantId

    $apps = Get-MgApplication -All

    foreach ($app in $apps)
    {
        Write-Host "Reviewing App: $( $app.DisplayName )"
        
        # Get the service principal associated with the app
        $servicePrincipal = Get-MgServicePrincipal -Filter "AppId eq '$($app.AppId)'"
        $apiPermissions = Get-MgServicePrincipalOauth2PermissionGrant -ServicePrincipal $servicePrincipal.Id
        foreach ($perm in $apiPermissions)
        {
            # Remove Admin Access Grant
            Write-Host " - Revoking admin consent from API permissions..."
            Remove-MgOauth2PermissionGrant -Oauth2PermissionGrantId $perm.Id
        }
            
        $appManifest = Get-MgApplication -ApplicationId $app.Id

        if ($appManifest.RequiredResourceAccess[0].ResourceAccess) #$appManifest.RequiredResourceAccess.Count gt- 0
        {
            Write-Host "Processing ResourceAppId: $( $app.DisplayName ) with $( $appManifest.RequiredResourceAccess[0].ResourceAccess.Count ) API Permissions."
            $appManifest.RequiredResourceAccess[0].ResourceAccess = $appManifest.RequiredResourceAccess[0].ResourceAccess | Where-Object { $_.Type -eq 'Role' }

            if ($appManifest.RequiredResourceAccess[0].ResourceAccess.Count -gt 0)
            {
                Update-MgApplication -ApplicationId $app.Id -RequiredResourceAccess $appManifest.RequiredResourceAccess
                Write-Host "$( $app.DisplayName ) has $( $appManifest.RequiredResourceAccess[0].ResourceAccess.Count ) API Permission(s) remaining."
            }

            # If all API Permissions are delegated permissions, remove the RequiredResourceAccess entry
            elseif ($appManifest.RequiredResourceAccess[0].ResourceAccess.Count -eq 0)
            {
                $uri = ".0/applications/$($app.Id)"
                $body = @{
                    requiredResourceAccess = @()
                } | ConvertTo-Json -Depth 3

                Invoke-MgGraphRequest -Method PATCH -Uri $uri -Body $body -ContentType "application/json"
            }

            # Update the manifest if there are role type API permissions
            Write-Host "No Delegated Permissions remain for $( $app.DisplayName )"
        }
        else
        {
            Write-Host "No API Permissions found for $( $app.DisplayName )"
        }
    }
    Disconnect-MgGraph | Out-Null
}
main

I've written a powershell script that essentially goes through app registrations and removes all delegated permissions from them.

Currently I'm using a PATCH request to microsoft graph to set API permissions/requiredResourceAccess (as found here) to be an empty array if there are only delegated api permissions. However if there are application api permissions I'm using an Update-MgApplication command to replace the permissions with only the existing application api permissions.

This is because I was having errors trying to set the body of a PATCH request to be the remaining application api permissions.

I wanted to know if there was a more efficient way to write this script that made use of the correct calls whether it be Microsoft graph or MG powershell commands.

function main {
    $TenantId = "XXX"   

    $Parameters = @{
        TenantId = $TenantId
    }

    Remove-ManifestPermissions @Parameters
}

function Remove-ManifestPermissions
{
    [CmdletBinding()]
    param (
        [Parameter(Mandatory)]
        [Guid]
        $TenantId    
    )

    $requiredScopes = @(
        "Application.ReadWrite.All",
        "DelegatedPermissionGrant.ReadWrite.All"
    )

    $null = Connect-MgGraph -Scopes $requiredScopes -TenantId $TenantId

    $apps = Get-MgApplication -All

    foreach ($app in $apps)
    {
        Write-Host "Reviewing App: $( $app.DisplayName )"
        
        # Get the service principal associated with the app
        $servicePrincipal = Get-MgServicePrincipal -Filter "AppId eq '$($app.AppId)'"
        $apiPermissions = Get-MgServicePrincipalOauth2PermissionGrant -ServicePrincipal $servicePrincipal.Id
        foreach ($perm in $apiPermissions)
        {
            # Remove Admin Access Grant
            Write-Host " - Revoking admin consent from API permissions..."
            Remove-MgOauth2PermissionGrant -Oauth2PermissionGrantId $perm.Id
        }
            
        $appManifest = Get-MgApplication -ApplicationId $app.Id

        if ($appManifest.RequiredResourceAccess[0].ResourceAccess) #$appManifest.RequiredResourceAccess.Count gt- 0
        {
            Write-Host "Processing ResourceAppId: $( $app.DisplayName ) with $( $appManifest.RequiredResourceAccess[0].ResourceAccess.Count ) API Permissions."
            $appManifest.RequiredResourceAccess[0].ResourceAccess = $appManifest.RequiredResourceAccess[0].ResourceAccess | Where-Object { $_.Type -eq 'Role' }

            if ($appManifest.RequiredResourceAccess[0].ResourceAccess.Count -gt 0)
            {
                Update-MgApplication -ApplicationId $app.Id -RequiredResourceAccess $appManifest.RequiredResourceAccess
                Write-Host "$( $app.DisplayName ) has $( $appManifest.RequiredResourceAccess[0].ResourceAccess.Count ) API Permission(s) remaining."
            }

            # If all API Permissions are delegated permissions, remove the RequiredResourceAccess entry
            elseif ($appManifest.RequiredResourceAccess[0].ResourceAccess.Count -eq 0)
            {
                $uri = "https://graph.microsoft/v1.0/applications/$($app.Id)"
                $body = @{
                    requiredResourceAccess = @()
                } | ConvertTo-Json -Depth 3

                Invoke-MgGraphRequest -Method PATCH -Uri $uri -Body $body -ContentType "application/json"
            }

            # Update the manifest if there are role type API permissions
            Write-Host "No Delegated Permissions remain for $( $app.DisplayName )"
        }
        else
        {
            Write-Host "No API Permissions found for $( $app.DisplayName )"
        }
    }
    Disconnect-MgGraph | Out-Null
}
main
Share Improve this question edited Mar 20 at 11:28 jammyjoe asked Mar 19 at 15:33 jammyjoejammyjoe 1051 gold badge2 silver badges6 bronze badges 1
  • 1 Why are you querying all applications $apps = Get-MgApplication -All and then querying them again $appManifest = Get-MgApplication -ApplicationId $app.Id ? This doesn't make sense. – Santiago Squarzon Commented Mar 19 at 22:31
Add a comment  | 

1 Answer 1

Reset to default 1

I agree with @Santiago Squarzon, Instead of querying the application again (Get-MgApplication -ApplicationId $app.Id), we simply use $app.RequiredResourceAccess directly within the loop. Since $app already contains this data (from Get-MgApplication -All), there's no need to retrieve it again:

For sample, I have API permissions like below:

function main {
    $TenantId = "TenantID"   

    $Parameters = @{
        TenantId = $TenantId
    }

    Remove-ManifestPermissions @Parameters
}

function Remove-ManifestPermissions
{
    [CmdletBinding()]
    param (
        [Parameter(Mandatory)]
        [Guid]
        $TenantId    
    )

    $requiredScopes = @(
        "Application.ReadWrite.All",
        "DelegatedPermissionGrant.ReadWrite.All"
    )

    # Connect to Microsoft Graph
    $null = Connect-MgGraph -Scopes $requiredScopes -TenantId $TenantId

    # Get all apps
    $apps = Get-MgApplication -All

    foreach ($app in $apps)
    {
        Write-Host "Reviewing App: $($app.DisplayName)"
        
        # Get the service principal associated with the app
        $servicePrincipal = Get-MgServicePrincipal -Filter "AppId eq '$($app.AppId)'"
        $apiPermissions = Get-MgServicePrincipalOauth2PermissionGrant -ServicePrincipal $servicePrincipal.Id
        foreach ($perm in $apiPermissions)
        {
            # Remove Admin Access Grant
            Write-Host " - Revoking admin consent from API permissions..."
            Remove-MgOauth2PermissionGrant -Oauth2PermissionGrantId $perm.Id
        }
            
        # Now directly use the app's RequiredResourceAccess property
        if ($app.RequiredResourceAccess.Count -gt 0)
        {
            $resourceAccess = $app.RequiredResourceAccess[0].ResourceAccess

            Write-Host "Processing ResourceAppId: $($app.DisplayName) with $($resourceAccess.Count) API Permissions."
            
            # Only keep role-based permissions (remove delegated permissions)
            $resourceAccess = $resourceAccess | Where-Object { $_.Type -eq 'Role' }

            if ($resourceAccess.Count -gt 0)
            {
                # Update the app manifest with remaining application permissions
                $app.RequiredResourceAccess[0].ResourceAccess = $resourceAccess
                Update-MgApplication -ApplicationId $app.Id -RequiredResourceAccess $app.RequiredResourceAccess
                Write-Host "$($app.DisplayName) has $($resourceAccess.Count) API Permission(s) remaining."
            }
            elseif ($resourceAccess.Count -eq 0)
            {
                # If no role-based permissions remain, remove the RequiredResourceAccess entry
                $uri = "https://graph.microsoft/v1.0/applications/$($app.Id)"
                $body = @{
                    requiredResourceAccess = @()
                } | ConvertTo-Json -Depth 3

                Invoke-MgGraphRequest -Method PATCH -Uri $uri -Body $body -ContentType "application/json"
                Write-Host "All API permissions removed for $($app.DisplayName)."
            }
        }
        else
        {
            Write-Host "No API Permissions found for $($app.DisplayName)"
        }
    }

    # Disconnect from Microsoft Graph
    Disconnect-MgGraph | Out-Null
}

main

The delegated API permissions revoked and removed successfully:

发布评论

评论列表(0)

  1. 暂无评论