Saltar al contenido
Microsoft scripts

Scripts de Defender

Acciones pendientes de Microsoft Secure Score

Lista las acciones de mejora que aún dan puntos, de mayor a menor, con su impacto en los usuarios, para planear qué hacer primero.

Antes de correrloSecure Score muestra todas las recomendaciones de un producto sin importar el plan, así que algunas acciones pueden pedir una licencia que no tienes. Títulos y descripciones vienen en inglés, como los entrega Microsoft. Omite los controles marcados como ignorados o resueltos por un tercero.

Ejemplo en México

Escuela privada en Puebla, 90 personas

Con un solo técnico y poco tiempo entre periodos escolares, hay que escoger qué ajustes de seguridad dan más por menos esfuerzo.

.\get-acciones-puntuacion.ps1 -RutaCsv .\acciones.csv

Obtiene la lista priorizada y agenda para vacaciones las acciones que más suman sin afectar a los maestros.

Cómo implementarlo

  1. Instala el módulo si no lo tienes: Install-Module Microsoft.Graph.Authentication -Scope CurrentUser.
  2. Corre el script e inicia sesión con una cuenta con el rol Lector de seguridad.
  3. Abre el CSV: ya viene ordenado por PuntosPendientes.
  4. Elige las acciones con más puntos y menor ImpactoUsuario, y aplícalas desde la columna Liga.
Ver el código completo de get-acciones-puntuacion.ps1
<#
.SYNOPSIS
    ¿Qué acciones de Microsoft Secure Score me faltan y cuáles dan más puntos?

.DESCRIPTION
    Cruza los perfiles de control con la puntuación más reciente y lista las acciones con puntos
    pendientes, de mayor a menor. Omite controles retirados y los que marcaste como ignorados o
    resueltos por un tercero.
    Solo lectura: no cambia nada en el tenant.

.PARAMETER RutaCsv
    Ruta del CSV de salida. Si se omite, solo se muestra en pantalla.

.EXAMPLE
    .\get-acciones-puntuacion.ps1 -RutaCsv .\acciones.csv

.NOTES
    Permisos: SecurityEvents.Read.All
    Rol mínimo: Lector de seguridad
    Licencia: Sin plan específico: Secure Score muestra recomendaciones de los productos que tengas con licencia (Microsoft Entra ID, Exchange Online, Microsoft Defender, entre otros). Aplica a Microsoft 365 Business Premium
    Licencia del código: MIT. Se entrega TAL CUAL, sin garantía. Pruébalo primero en un tenant de pruebas.
#>
[CmdletBinding()]
param(
    [string]$RutaCsv
)

$ErrorActionPreference = 'Stop'
$permisos = @('SecurityEvents.Read.All')

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

$reciente = @((Invoke-MgGraphRequest -Method GET -Uri 'https://graph.microsoft.com/v1.0/security/secureScores?$top=1').value)[0]
if (-not $reciente) { throw 'Graph no devolvió puntuaciones para este tenant.' }
$puntosPorControl = @{}
foreach ($c in $reciente.controlScores) { $puntosPorControl["$($c.controlName)"] = [double]$c.score }

$uri = 'https://graph.microsoft.com/v1.0/security/secureScoreControlProfiles'
$perfiles = while ($uri) {
    $pagina = Invoke-MgGraphRequest -Method GET -Uri $uri
    $pagina.value
    $uri = $pagina.'@odata.nextLink'
}

$filas = foreach ($p in $perfiles) {
    if ($p.deprecated) { continue }
    $ultimo = @($p.controlStateUpdates | Sort-Object { if ($_.updatedDateTime) { [datetimeoffset]"$($_.updatedDateTime)" } else { [datetimeoffset]::MinValue } })[-1]
    if ("$($ultimo.state)" -in @('Ignored', 'ThirdParty')) { continue }
    $maximo = [double]$p.maxScore
    $actuales = [double]$puntosPorControl["$($p.id)"]
    $pendientes = $maximo - $actuales
    if ($pendientes -le 0) { continue }
    [pscustomobject]@{
        Accion           = $p.title
        PuntosPendientes = $pendientes
        PuntosActuales   = $actuales
        PuntosMaximos    = $maximo
        Avance           = if ($actuales -gt 0) { 'Parcial' } else { 'Sin iniciar' }
        Categoria        = $p.controlCategory
        Servicio         = $p.service
        ImpactoUsuario   = $p.userImpact
        Costo            = $p.implementationCost
        Rango            = $p.rank
        Liga             = $p.actionUrl
    }
}
$filas = $filas | Sort-Object @{ Expression = 'PuntosPendientes'; Descending = $true }, Rango

Write-Host "Acciones pendientes: $(@($filas).Count), con $(($filas | Measure-Object PuntosPendientes -Sum).Sum) puntos por ganar"
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
}

Relacionados