Restaurar permisos revocados concedidos a las aplicaciones
En este artículo, aprenderá a restaurar los permisos revocados previamente concedidos a una aplicación. Puede restaurar los permisos de una aplicación a la que se le concedieron permisos para acceder a los datos de la organización. También puede restaurar permisos para una aplicación a la que se concedieron permisos para actuar como usuario.
Actualmente, la restauración de permisos solo es posible a través de PowerShell de Microsoft Graph y llamadas de Microsoft Graph API. No se pueden restaurar los permisos a través del Centro de administración de Microsoft Entra. En este artículo, aprenderá a restaurar permisos mediante PowerShell de Microsoft Graph.
Requisitos previos
Para restaurar permisos revocados previamente para una aplicación, necesita:
- Una cuenta de Azure con una suscripción activa. Cree una cuenta gratuita.
- Uno de los siguientes roles: Administrador de aplicaciones en la nube, Administrador de aplicaciones.
- Un propietario de la entidad de servicio que no sea administrador puede invalidar los tokens de actualización.
Restaurar permisos revocados para una aplicación
Puede probar diferentes métodos para restaurar permisos:
- Use el botón Conceder consentimiento del administrador en la página Permisos de la aplicación para volver a aplicar el consentimiento. Este consentimiento aplica el conjunto de permisos que el desarrollador de la aplicación solicitó originalmente en el manifiesto de la aplicación.
Nota
Al volver a conceder el consentimiento del administrador, se quitarán los permisos concedidos que no formen parte del conjunto predeterminado configurado por el desarrollador.
- Si conoce el permiso específico que se revoca, puede concederlo de nuevo manualmente mediante PowerShell o Microsoft Graph API.
- Si no conoce los permisos revocados, puede usar los scripts proporcionados en este artículo para detectar y restaurar permisos revocados.
En primer lugar, establezca el valor servicePrincipalId en el script en el valor de id. de la aplicación empresarial cuyos permisos desea restaurar. Este identificador también se denomina object ID
en la página Aplicaciones empresariales del Centro de administración de Microsoft Entra.
A continuación, ejecute cada script con $ForceGrantUpdate = $false
para ver una lista de los permisos delegados o exclusivos de la aplicación que tal vez se hayan quitado. Incluso si los permisos ya se han restaurado, es posible que los eventos de revocación de los registros de auditoría sigan apareciendo en los resultados del script.
Deje $ForceGrantUpdate
establecido en $true
si desea que el script intente restaurar los permisos revocados que detecte. Los scripts solicitan confirmación, pero no solicitan aprobación individual para cada permiso que restaura.
Tenga cuidado al conceder permisos a las aplicaciones. Para obtener más información sobre cómo evaluar los permisos, consulte Evaluar permisos.
Restaurar permisos delegados
# 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 = "aaaaaaaa-bbbb-cccc-1111-222222222222"
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
}
Restaurar permisos solo de aplicación
Nota:
La concesión de permisos de Microsoft Graph solo para aplicaciones necesita el rol Administrador de roles con privilegios.
# 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 = "aaaaaaaa-bbbb-cccc-1111-222222222222"
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
}