Ripristinare le autorizzazioni revocate concesse alle applicazioni

Questo articolo illustra come ripristinare le autorizzazioni revocate in precedenza concesse a un'applicazione. È possibile ripristinare le autorizzazioni per un'applicazione a cui sono state concesse le autorizzazioni per accedere ai dati dell'organizzazione. È anche possibile ripristinare le autorizzazioni per un'applicazione a cui sono state concesse le autorizzazioni per fungere da utente.

Attualmente, il ripristino delle autorizzazioni è possibile solo tramite microsoft Graph PowerShell e le chiamate API Microsoft Graph. Non è possibile ripristinare le autorizzazioni tramite l'interfaccia di amministrazione di Microsoft Entra. Questo articolo illustra come ripristinare le autorizzazioni usando Microsoft Graph PowerShell.

Prerequisiti

Per ripristinare le autorizzazioni precedentemente revocate per un'applicazione, è necessario:

  • Un account Azure con una sottoscrizione attiva. Creare un account gratuitamente.
  • Uno dei ruoli seguenti: Global Amministrazione istrator, Cloud Application Amministrazione istrator, Application Amministrazione istrator.
  • Un proprietario dell'entità servizio che non è un amministratore è in grado di invalidare i token di aggiornamento.

Ripristinare le autorizzazioni revocate per un'applicazione

È possibile provare metodi diversi per il ripristino delle autorizzazioni:

  • Usare il pulsante Concedi consenso amministratore nella pagina Autorizzazioni per l'app per applicare nuovamente il consenso. Questo consenso applica il set di autorizzazioni richieste originariamente dallo sviluppatore dell'app nel manifesto dell'app.

Nota

Il consenso dell'amministratore regranting rimuoverà tutte le autorizzazioni concesse che non fanno parte del set predefinito configurato dallo sviluppatore.

  • Se si conosce l'autorizzazione specifica revocata, è possibile concederla di nuovo manualmente usando PowerShell o l'API Microsoft Graph.
  • Se non si conoscono le autorizzazioni revocate, è possibile usare gli script forniti in questo articolo per rilevare e ripristinare le autorizzazioni revocate.

Prima di tutto, impostare il valore servicePrincipalId nello script sul valore ID per l'app aziendale le cui autorizzazioni si desidera ripristinare. Questo ID viene chiamato anche nella pagina Applicazioni aziendali dell'interfaccia object ID di amministrazione di Microsoft Entra.

Eseguire quindi ogni script con $ForceGrantUpdate = $false per visualizzare un elenco di autorizzazioni delegate o solo app che potrebbero essere state rimosse. Anche se le autorizzazioni sono già state ripristinate, revocare gli eventi dai log di controllo potrebbero comunque essere visualizzati nei risultati dello script.

Lasciare $ForceGrantUpdate impostato su $true se si vuole che lo script tenti di ripristinare le autorizzazioni revocate rilevate. Gli script richiedono una conferma, ma non richiedono l'approvazione individuale per ogni autorizzazione ripristinata.

Prestare attenzione quando si concedono le autorizzazioni alle app. Per altre informazioni su come valutare le autorizzazioni, vedere Valutare le autorizzazioni.

Ripristinare le autorizzazioni delegate

# WARNING: Setting $ForceGrantUpdate to true will modify permission grants without
# prompting for confirmation. This can result in unintended changes to your
# application's security settings. Use with caution!
$ForceGrantUpdate = $false

# Set the start and end dates for the audit log search
# If setting date use yyyy-MM-dd format
# endDate is set to tomorrow to include today's audit logs
$startDate = (Get-Date).AddDays(-7).ToString('yyyy-MM-dd')
$endDate = (Get-Date).AddDays(1).ToString('yyyy-MM-dd')

# Set the service principal ID
$servicePrincipalId = "efe87e5d-05cb-4b19-9b36-1eb923448697"

Write-Host "Searching for audit logs between $startDate and $endDate" -ForegroundColor Green
Write-Host "Searching for audit logs for service principal $servicePrincipalId" -ForegroundColor Green

if ($ForceGrantUpdate -eq $true) {
    Write-Host "WARNING: ForceGrantUpdate is set to true. This will modify permission grants without prompting for confirmation. This can result in unintended changes to your application's security settings. Use with caution!" -ForegroundColor Red
    $continue = Read-Host "Do you want to continue? (Y/N)"
    if ($continue -eq "Y" -or $continue -eq "y") {
        Write-Host "Continuing..."
    } else {
        Write-Host "Exiting..."
        exit
    }
}

# Connect to MS Graph
Connect-MgGraph -Scopes "AuditLog.Read.All","DelegatedPermissionGrant.ReadWrite.All" -ErrorAction Stop | Out-Null

# Create a hashtable to store the OAuth2PermissionGrants
$oAuth2PermissionGrants = @{}

function Merge-Scopes($oldScopes, $newScopes) {
    $oldScopes = $oldScopes.Trim() -split '\s+'
    $newScopes = $newScopes.Trim() -split '\s+'
    $mergedScopesArray = $oldScopes + $newScopes | Select-Object -Unique
    $mergedScopes = $mergedScopesArray -join ' '
    return $mergedScopes.Trim()
}

# Function to merge scopes if multiple OAuth2PermissionGrants are found in the audit logs
function Add-Scopes($resourceId, $newScopes) {
    if($oAuth2PermissionGrants.ContainsKey($resourceId)) {
        $oldScopes = $oAuth2PermissionGrants[$resourceId]
        $oAuth2PermissionGrants[$resourceId] = Merge-Scopes $oldScopes $newScopes
    }
    else {
        $oAuth2PermissionGrants[$resourceId] = $newScopes
    }
}

function Get-ScopeDifference ($generatedScope, $currentScope) {
    $generatedScopeArray = $generatedScope.Trim() -split '\s+'
    $currentScopeArray = $currentScope.Trim() -split '\s+'
    $difference = $generatedScopeArray | Where-Object { $_ -notin $currentScopeArray }
    $difference = $difference -join ' '
    return $difference.Trim()
}

# Set the filter for the audit log search
$filterOAuth2PermissionGrant = "activityDateTime ge $startDate and activityDateTime le $endDate" +
    " and Result eq 'success'" +
    " and ActivityDisplayName eq 'Remove delegated permission grant'" +
    " and targetResources/any(x: x/id eq '$servicePrincipalId')"
try {
    # Retrieve the audit logs for removed OAuth2PermissionGrants
    $oAuth2PermissionGrantsAuditLogs = Get-MgAuditLogDirectoryAudit -Filter $filterOAuth2PermissionGrant -All -ErrorAction Stop
}
catch {
    Disconnect-MgGraph | Out-Null
    throw $_
}

# Remove User Delegated Permission Grants
$oAuth2PermissionGrantsAuditLogs = $oAuth2PermissionGrantsAuditLogs | Where-Object {
    -not ($_.TargetResources.ModifiedProperties.OldValue -eq '"Principal"')
}

# Merge duplicate OAuth2PermissionGrants from AuditLogs using Add-Scopes
foreach ($auditLog in $oAuth2PermissionGrantsAuditLogs) {
    $resourceId = $auditLog.TargetResources[0].Id
    # We only want to process OAuth2PermissionGrant Audit Logs where $servicePrincipalId is the clientId not the resourceId
    if ($resourceId -eq $servicePrincipalId) {
        continue
    }
    $oldScope = $auditLog.TargetResources[0].ModifiedProperties | Where-Object { $_.DisplayName -eq "DelegatedPermissionGrant.Scope" } | Select-Object -ExpandProperty OldValue
    if ($oldScope -eq $null) {
        $oldScope = ""
    }
    $oldScope = $oldScope.Replace('"', '')
    $newScope = $auditLog.TargetResources[0].ModifiedProperties | Where-Object { $_.DisplayName -eq "DelegatedPermissionGrant.Scope" } | Select-Object -ExpandProperty NewValue
    if ($newScope -eq $null) {
        $newScope = ""
    }
    $newScope = $newScope.Replace('"', '')
    $scope = Merge-Scopes $oldScope $newScope
    Add-Scopes $resourceId $scope
}

$permissionCount = 0
foreach ($resourceId in $oAuth2PermissionGrants.keys) {
    $scope = $oAuth2PermissionGrants[$resourceId]
    $params = @{
        clientId = $servicePrincipalId
        consentType = "AllPrincipals"
        resourceId = $resourceId
        scope = $scope
    }

    try {
        $currentOAuth2PermissionGrant = Get-MgOauth2PermissionGrant -Filter "clientId eq '$servicePrincipalId' and consentType eq 'AllPrincipals' and resourceId eq '$resourceId'" -ErrorAction Stop
        $action = "Creating"
        if ($currentOAuth2PermissionGrant -ne $null) {
            $action = "Updating"
        }
        Write-Host "--------------------------"
        if ($ForceGrantUpdate -eq $true) {
            Write-Host "$action OAuth2PermissionGrant with the following parameters:"
        } else {
            Write-Host "Potentially removed OAuth2PermissionGrant scopes with the following parameters:"
        }
        Write-Host "    clientId: $($params.clientId)"
        Write-Host "    consentType: $($params.consentType)"
        Write-Host "    resourceId: $($params.resourceId)"
        if ($currentOAuth2PermissionGrant -ne $null) {
            $scopeDifference = Get-ScopeDifference $scope $currentOAuth2PermissionGrant.Scope
            if ($scopeDifference -eq "") {
                Write-Host "OAuth2PermissionGrant already exists with the same scope" -ForegroundColor Yellow
                if ($ForceGrantUpdate -eq $true) {
                    Write-Host "Skipping Update" -ForegroundColor Yellow
                }
                continue
            }
            else {
                Write-Host "    scope diff: '$scopeDifference'"
            }
        }
        else {
            Write-Host "    scope: '$($params.scope)'"
        }
        if ($ForceGrantUpdate -eq $true -and $currentOAuth2PermissionGrant -eq $null) {
            New-MgOauth2PermissionGrant -BodyParameter $params -ErrorAction Stop | Out-Null
            Write-Host "OAuth2PermissionGrant was created successfully" -ForegroundColor Green
        }
        if ($ForceGrantUpdate -eq $true -and $currentOAuth2PermissionGrant -ne $null) {
            Write-Host "    Current Scope: '$($currentOAuth2PermissionGrant.scope)'" -ForegroundColor Yellow
            Write-Host "    Merging with scopes from audit logs" -ForegroundColor Yellow
            $params.scope = Merge-Scopes $currentOAuth2PermissionGrant.scope $params.scope
            Write-Host "    New Scope: '$($params.scope)'" -ForegroundColor Yellow
            Update-MgOauth2PermissionGrant -OAuth2PermissionGrantId $currentOAuth2PermissionGrant.id -BodyParameter $params -ErrorAction Stop | Out-Null
            Write-Host "OAuth2PermissionGrant was updated successfully" -ForegroundColor Green
        }
        $permissionCount++
    }
    catch {
        Disconnect-MgGraph | Out-Null
        throw $_
    }
}

Disconnect-MgGraph | Out-Null

if ($ForceGrantUpdate -eq $true) {
    Write-Host "--------------------------"
    Write-Host "$permissionCount OAuth2PermissionGrants were created/updated successfully" -ForegroundColor Green
} else {
    Write-Host "--------------------------"
    Write-Host "$permissionCount OAuth2PermissionGrants were found" -ForegroundColor Green
}

Ripristinare le autorizzazioni solo app

Nota

Per concedere le autorizzazioni di Microsoft Graph solo app è necessario il ruolo di amministratore globale.

# WARNING: Setting $ForceGrantUpdate to true will modify permission grants without
# prompting for confirmation. This can result in unintended changes to your
# application's security settings. Use with caution!
$ForceGrantUpdate = $false

# Set the start and end dates for the audit log search
# If setting date use yyyy-MM-dd format
# endDate is set to tomorrow to include today's audit logs
$startDate = (Get-Date).AddDays(-7).ToString('yyyy-MM-dd')
$endDate = (Get-Date).AddDays(1).ToString('yyyy-MM-dd')

# Set the service principal ID
$servicePrincipalId = "efe87e5d-05cb-4b19-9b36-1eb923448697"

Write-Host "Searching for audit logs between $startDate and $endDate" -ForegroundColor Green
Write-Host "Searching for audit logs for service principal $servicePrincipalId" -ForegroundColor Green

if ($ForceGrantUpdate -eq $true) {
    Write-Host "WARNING: ForceGrantUpdate is set to true. This will modify permission grants without prompting for confirmation. This can result in unintended changes to your application's security settings. Use with caution!" -ForegroundColor Red
    $continue = Read-Host "Do you want to continue? (Y/N)"
    if ($continue -eq "Y" -or $continue -eq "y") {
        Write-Host "Continuing..."
    } else {
        Write-Host "Exiting..."
        exit
    }
}

# Connect to MS Graph
Connect-MgGraph -Scopes "AuditLog.Read.All","Application.Read.All","AppRoleAssignment.ReadWrite.All" -ErrorAction Stop | Out-Null

# Set the filter for the audit log search
$filterAppRoleAssignment = "activityDateTime ge $startDate and activityDateTime le $endDate" + 
    " and Result eq 'success'" +
    " and ActivityDisplayName eq 'Remove app role assignment from service principal'" +
    " and targetResources/any(x: x/id eq '$servicePrincipalId')"

try {
    # Retrieve the audit logs for removed AppRoleAssignments
    $appRoleAssignmentsAuditLogs = Get-MgAuditLogDirectoryAudit -Filter $filterAppRoleAssignment -All -ErrorAction Stop
}
catch {
    Disconnect-MgGraph | Out-Null
    throw $_
}

$permissionCount = 0
foreach ($auditLog in $appRoleAssignmentsAuditLogs) {
    $resourceId = $auditLog.TargetResources[0].Id
    # We only want to process AppRoleAssignments Audit Logs where $servicePrincipalId is the principalId not the resourceId
    if ($resourceId -eq $servicePrincipalId) {
        continue
    }
    $appRoleId = $auditLog.TargetResources[0].ModifiedProperties | Where-Object { $_.DisplayName -eq "AppRole.Id" } | Select-Object -ExpandProperty OldValue
    $appRoleId = $appRoleId.Replace('"', '')
    $params = @{
        principalId = $servicePrincipalId
        resourceId = $resourceId
        appRoleId = $appRoleId
    }

    try {
        $sp = Get-MgServicePrincipal -ServicePrincipalId $resourceId
        $appRole = $sp.AppRoles | Where-Object { $_.Id -eq $appRoleId }

        Write-Host "--------------------------"
        if ($ForceGrantUpdate -eq $true) {
            Write-Host "Creating AppRoleAssignment with the following parameters:"
        } else {
            Write-Host "Potentially removed AppRoleAssignment with the following parameters:"
        }
        Write-Host "    principalId: $($params.principalId)"
        Write-Host "    resourceId: $($params.resourceId)"
        Write-Host "    appRoleId: $($params.appRoleId)"
        Write-Host "    appRoleValue: $($appRole.Value)"
        Write-Host "    appRoleDisplayName: $($appRole.DisplayName)"
        if ($ForceGrantUpdate -eq $true) {
            New-MgServicePrincipalAppRoleAssignment -ServicePrincipalId $servicePrincipalId -BodyParameter $params -ErrorAction Stop | Out-Null
            Write-Host "AppRoleAssignment was created successfully" -ForegroundColor Green
        }
        $permissionCount++
    }
    catch {
        if ($_.Exception.Message -like "*Permission being assigned already exists on the object*") {
            Write-Host "AppRoleAssignment already exists skipping creation" -ForegroundColor Yellow
        }
        else {
            Disconnect-MgGraph | Out-Null
            throw $_
        }
    }
}

Disconnect-MgGraph | Out-Null

if ($ForceGrantUpdate -eq $true) {
    Write-Host "--------------------------"
    Write-Host "$permissionCount AppRoleAssignments were created successfully" -ForegroundColor Green
} else {
    Write-Host "--------------------------"
    Write-Host "$permissionCount AppRoleAssignments were found" -ForegroundColor Green
}