# .AUDITORÍA DE PERMISOS M365 Versión: 2.5 Autor: Pablo Web: [integroia.com] Descripción: Evalúa permisos en SharePoint Online, Teams, Grupos M365 y Azure AD Requisitos: Módulos PnP.PowerShell, AzureAD, ExchangeOnlineManagement #> # 1. CONFIGURACIÓN INICIAL $reportPath = "C:\Auditorias\Permisos_$(Get-Date -Format 'yyyyMMdd_HHmm')" $htmlReportPath = "$reportPath\Reporte_Auditoria.html" $csvReportPath = "$reportPath\Datos_Completos.csv" # Crear directorio si no existe if (!(Test-Path $reportPath)) { New-Item -ItemType Directory -Path $reportPath | Out-Null Write-Host "[+] Directorio de reportes creado: $reportPath" -ForegroundColor Green } # 2. FUNCIÓN PARA CONECTAR A SERVICIOS function Connect-Services { try { Write-Host "`n[1/4] Conectando a SharePoint Online..." -ForegroundColor Cyan Connect-PnPOnline -Url "https://[TU-TENANT]-admin.sharepoint.com" -Interactive -ErrorAction Stop Write-Host "[2/4] Conectando a Azure AD..." -ForegroundColor Cyan Connect-AzureAD -AccountId "admin@tudominio.com" | Out-Null Write-Host "[3/4] Conectando a Exchange Online..." -ForegroundColor Cyan Connect-ExchangeOnline -UserPrincipalName "admin@tudominio.com" -ShowProgress $true Write-Host "[4/4] Conectando a Microsoft Teams..." -ForegroundColor Cyan Connect-MicrosoftTeams -AccountId "admin@tudominio.com" | Out-Null return $true } catch { Write-Host "[!] Error de conexión: $_" -ForegroundColor Red return $false } } # 3. AUDITORÍA DE SHAREPOINT ONLINE function Audit-SPOSites { param($ReportData) Write-Host "`n[+] Auditando SharePoint Online..." -ForegroundColor Yellow $sites = Get-PnPTenantSite | Where-Object { $_.Template -ne "REDIRECTSITE" } $progress = 1 foreach ($site in $sites) { Write-Progress -Activity "Analizando sitios" -Status $site.Url -PercentComplete ($progress/$sites.Count*100) try { $conn = Connect-PnPOnline -Url $site.Url -ReturnConnection -ErrorAction Stop # Obtener admins y permisos únicos $admins = Get-PnPSiteCollectionAdmin -Connection $conn $uniquePerms = Get-PnPPropertyBag -Key "vti_uniquepermissions" -Connection $conn # Detección de sharing externo $externalUsers = @() if ($site.SharingCapability -ne "Disabled") { $externalUsers = Get-PnPExternalUser -Connection $conn -ErrorAction SilentlyContinue } # Añadir al reporte $ReportData += [PSCustomObject]@{ Tipo = "SharePoint" Nombre = $site.Title URL = $site.Url Propietario = $site.Owner Admins = ($admins.Email -join "; ") Externos = ($externalUsers.DisplayName -join "; ") UniquePerms = $uniquePerms Sharing = $site.SharingCapability LastModified = $site.LastContentModifiedDate Alerta = if ($externalUsers.Count -gt 5) { "HIGH" } elseif ($admins.Count -gt 3) { "MEDIUM" } else { "LOW" } } } catch { Write-Host "[!] Error en $($site.Url): $_" -ForegroundColor Red } $progress++ } return $ReportData } # 4. AUDITORÍA DE TEAMS Y GRUPOS M365 function Audit-TeamsGroups { param($ReportData) Write-Host "`n[+] Auditando Teams y Grupos M365..." -ForegroundColor Yellow $groups = Get-AzureADMSGroup -Filter "groupTypes/any(c:c eq 'Unified')" -All $true $progress = 1 foreach ($group in $groups) { Write-Progress -Activity "Analizando grupos" -Status $group.DisplayName -PercentComplete ($progress/$groups.Count*100) try { $owners = Get-AzureADGroupOwner -ObjectId $group.Id | Select-Object UserPrincipalName $members = Get-AzureADGroupMember -ObjectId $group.Id | Select-Object UserPrincipalName $guests = $members | Where-Object { $_.UserPrincipalName -like "*#EXT#*" } # Obtener configuración de Teams $teamInfo = $null try { $teamInfo = Get-Team -GroupId $group.Id } catch {} $ReportData += [PSCustomObject]@{ Tipo = if ($teamInfo) { "Teams" } else { "Grupo M365" } Nombre = $group.DisplayName ID = $group.Id Propietarios = ($owners.UserPrincipalName -join "; ") Miembros = ($members.Count) Invitados = ($guests.Count) Creación = $group.CreatedDateTime Alerta = if ($owners.Count -lt 2) { "HIGH" } elseif ($guests.Count -gt 10) { "MEDIUM" } else { "LOW" } } } catch { Write-Host "[!] Error en grupo $($group.DisplayName): $_" -ForegroundColor Red } $progress++ } return $ReportData } # 5. AUDITORÍA DE ROLES AZURE AD function Audit-AzureADRoles { param($ReportData) Write-Host "`n[+] Auditando Roles Privilegiados..." -ForegroundColor Yellow $roles = Get-AzureADDirectoryRole foreach ($role in $roles) { $members = Get-AzureADDirectoryRoleMember -ObjectId $role.ObjectId foreach ($member in $members) { # Verificar MFA $mfaStatus = (Get-MsolUser -ObjectId $member.ObjectId).StrongAuthenticationRequirements.State $ReportData += [PSCustomObject]@{ Tipo = "Azure AD Role" Nombre = $role.DisplayName Usuario = $member.UserPrincipalName MFA = if ($mfaStatus) { "HABILITADO" } else { "DESHABILITADO" } ÚltimoLogin = (Get-MsolUser -ObjectId $member.ObjectId).LastLogonTime Alerta = if (-not $mfaStatus) { "CRITICAL" } else { "LOW" } } } } return $ReportData } # 6. GENERAR REPORTE HTML PROFESIONAL function Generate-Report { param($Data) $htmlHeader = @"
Generado el $(Get-Date) por [Tu Nombre]
Sitios SharePoint analizados: $($Data | Where-Object { $_.Tipo -eq "SharePoint" }).Count
Teams/Grupos auditados: $($Data | Where-Object { $_.Tipo -in @("Teams", "Grupo M365") }).Count
Alertas CRÍTICAS: $($Data | Where-Object { $_.Alerta -eq "CRITICAL" }).Count
Sitio | Propietario | Admins | Externos | Sharing | Riesgo |
---|---|---|---|---|---|
$($item.Nombre) | $($item.Propietario) | $($item.Admins) | $($item.Externos) | $($item.Sharing) | $($item.Alerta) |
Nombre | Propietarios | Miembros | Invitados | Riesgo |
---|---|---|---|---|
$($item.Nombre) | $($item.Propietarios) | $($item.Miembros) | $($item.Invitados) | $($item.Alerta) |
Rol | Usuario | MFA | Último Login | Riesgo |
---|---|---|---|---|
$($item.Nombre) | $($item.Usuario) | $($item.MFA) | $($item.ÚltimoLogin) | $($item.Alerta) |
Auditoría generada automáticamente con PowerShell. Más recursos en tuweb.com
"@ # Combinar todo $fullReport = $htmlHeader + $htmlSharePoint + $htmlTeams + $htmlRoles + $htmlFooter $fullReport | Out-File -FilePath $htmlReportPath -Encoding UTF8 # Exportar datos brutos a CSV $Data | Export-Csv -Path $csvReportPath -NoTypeInformation -Encoding UTF8 } # 7. EJECUCIÓN PRINCIPAL Write-Host "`n=== AUDITORÍA DE PERMISOS M365 ===" -ForegroundColor Cyan Write-Host "Iniciando proceso...`n" -ForegroundColor White if (Connect-Services) { $reportData = @() $reportData = Audit-SPOSites -ReportData $reportData $reportData = Audit-TeamsGroups -ReportData $reportData $reportData = Audit-AzureADRoles -ReportData $reportData Generate-Report -Data $reportData Write-Host "`n[✔] Auditoría completada!" -ForegroundColor Green Write-Host "- Reporte HTML: $htmlReportPath" -ForegroundColor Yellow Write-Host "- Datos completos: $csvReportPath`n" -ForegroundColor Yellow # Abrir reporte automáticamente if ((Read-Host "¿Abrir reporte ahora? (S/N)") -eq "S") { Start-Process $htmlReportPath } } else { Write-Host "[X] No se pudo completar la auditoría. Verifica errores de conexión." -ForegroundColor Red } # Desconexión de servicios Disconnect-PnPOnline Disconnect-AzureAD Disconnect-ExchangeOnline -Confirm:$false Disconnect-MicrosoftTeams