<# .SYNOPSIS ¿Qué alertas de severidad alta se generaron en los últimos días? .DESCRIPTION Lista las alertas de severidad alta creadas en los últimos N días en Microsoft Defender XDR, con su estado, producto de origen, categoría y liga al portal. Solo lectura: no cambia nada en el tenant. .PARAMETER Dias Días hacia atrás. Por defecto, 7. .PARAMETER RutaCsv Ruta del CSV de salida. Si se omite, solo se muestra en pantalla. .PARAMETER ZonaHoraria Zona horaria para mostrar las fechas. Por defecto, Central Standard Time (Mexico). .EXAMPLE .\get-alertas-alta-severidad.ps1 -Dias 14 -RutaCsv .\alertas.csv .NOTES Permisos: SecurityAlert.Read.All Rol mínimo: Lector de seguridad Licencia: Cualquier licencia con acceso a Microsoft Defender XDR, por ejemplo Microsoft 365 Business Premium, Microsoft Defender for Business, Microsoft Defender for Endpoint, Microsoft Defender for Office 365 Plan 2 o Microsoft 365 E5 Licencia del código: MIT. Se entrega TAL CUAL, sin garantía. Pruébalo primero en un tenant de pruebas. #> [CmdletBinding()] param( [ValidateRange(1, 365)] [int]$Dias = 7, [string]$RutaCsv, [string]$ZonaHoraria = 'Central Standard Time (Mexico)' ) $ErrorActionPreference = 'Stop' $permisos = @('SecurityAlert.Read.All') $zona = [TimeZoneInfo]::FindSystemTimeZoneById($ZonaHoraria) if (-not (Get-Command Connect-MgGraph -ErrorAction SilentlyContinue)) { throw 'Falta el módulo. Instálalo con: Install-Module Microsoft.Graph.Authentication -Scope CurrentUser' } Connect-MgGraph -Scopes $permisos -NoWelcome function ConvertirFecha($valor) { if (-not $valor) { return $null } $utc = if ($valor -is [datetime]) { $valor.ToUniversalTime() } else { ([datetimeoffset]"$valor").UtcDateTime } [TimeZoneInfo]::ConvertTimeFromUtc($utc, $zona).ToString('yyyy-MM-dd HH:mm') } $estados = @{ new = 'Nueva'; inProgress = 'En progreso'; resolved = 'Resuelta' } $desde = (Get-Date).ToUniversalTime().AddDays(-$Dias).ToString('yyyy-MM-ddTHH:mm:ssZ') $uri = "https://graph.microsoft.com/v1.0/security/alerts_v2?`$filter=severity eq 'high' and createdDateTime ge $desde" $alertas = while ($uri) { $pagina = Invoke-MgGraphRequest -Method GET -Uri $uri $pagina.value $uri = $pagina.'@odata.nextLink' } $filas = foreach ($a in $alertas) { [pscustomobject]@{ Creada = ConvertirFecha $a.createdDateTime Alerta = $a.title Estado = if ($estados["$($a.status)"]) { $estados["$($a.status)"] } else { $a.status } Origen = $a.serviceSource Categoria = $a.category Responsable = if ($a.assignedTo) { $a.assignedTo } else { 'Sin asignar' } Incidente = $a.incidentId Liga = $a.alertWebUrl } } Write-Host "Alertas de severidad alta en $Dias días: $(@($filas).Count)" if ($RutaCsv) { # UTF-8 con BOM para que Excel en español muestre bien los acentos. $filas | Export-Csv -Path $RutaCsv -NoTypeInformation -Encoding utf8BOM Write-Host "CSV guardado en $RutaCsv" } else { $filas | Format-Table -AutoSize }