Icono del sitio Binario 0

Cómo Extraer y Exportar Información de Políticas de Grupo (GPO) desde Archivos XML con PowerShell

Artículos Guías Manuales Sistemas Linux Windows Redes MySql Binario 0 Binario Cero

Artículos Guías Manuales Sistemas Linux Windows Redes MySql Binario 0 Binario Cero

# Ruta del directorio con los archivos XML de GPO
$directorio = "C:\GPOs_Reportes_xml"

# Salida del CSV
$salidaCSV = "$directorio\gpos_exportadas.csv"

# Crear lista para guardar resultados
$resultados = @()

# Guardar máximo número de políticas para crear columnas después
$maxPoliticas = 0

# Procesar cada archivo XML en el directorio (con subcarpetas)
Get-ChildItem -Path $directorio -Filter *.xml -Recurse | ForEach-Object {
    $archivo = $_.FullName
    try {
        [xml]$xml = Get-Content $archivo

        $dominio = $xml.GPO.Identifier.Domain.'#text'
        $nombreGPO = $xml.GPO.Name

        # --- Corrección para obtener Owner con namespaces ---
        $nsManager = New-Object System.Xml.XmlNamespaceManager($xml.NameTable)
        $nsManager.AddNamespace("gp", "http://www.microsoft.com/GroupPolicy/Types/Security")
        $nsManager.AddNamespace("gpTypes", "http://www.microsoft.com/GroupPolicy/Types")

        $ownerNameNode = $xml.SelectSingleNode("//gp:Owner/gpTypes:Name", $nsManager)
        $owner = if ($ownerNameNode) { $ownerNameNode.InnerText } else { "Desconocido" }

        $activoMaquina = $xml.GPO.Computer.Enabled
        $activoUsuario = $xml.GPO.User.Enabled

        $politicasActivas = @()

        if ($xml.GPO.Computer.ExtensionData) {
            foreach ($ext in $xml.GPO.Computer.ExtensionData.Extension.Policy) {
                if ($ext.State -eq "Enabled") {
                    $politicasActivas += $ext.Name
                }
            }
        }

        if ($xml.GPO.User.ExtensionData) {
            foreach ($ext in $xml.GPO.User.ExtensionData.Extension.Policy) {
                if ($ext.State -eq "Enabled") {
                    $politicasActivas += $ext.Name
                }
            }
        }

        $activaPolitica = if ($politicasActivas.Count -gt 0) { "Si" } else { "No" }

        # --- Extraer info de LinksTo ---
        $linkada = "No"
        if ($xml.GPO.LinksTo) {
            # Comprobar si está Enabled y es true
            if ($xml.GPO.LinksTo.Enabled -and $xml.GPO.LinksTo.Enabled -eq "true") {
                $linkada = "Si"
            }
        }

        # Guardar el máximo de políticas para crear columnas después
        if ($politicasActivas.Count -gt $maxPoliticas) {
            $maxPoliticas = $politicasActivas.Count
        }

        # Guardar datos pero sin crear aún columnas de política, solo el array
        $resultados += [PSCustomObject]@{
            Dominio          = $dominio
            NombreGPO        = $nombreGPO
            ActivaLaPolitica = $activaPolitica
            ActivoUsuario    = $activoUsuario
            ActivoMaquina    = $activoMaquina
            OwnerPolitica    = $owner
            Linkada          = $linkada
            PoliticasActivas = $politicasActivas
        }
    }
    catch {
        Write-Warning "Error procesando ${archivo}: $($_.Exception.Message)"
    }
}

# Ahora construir nuevo array de objetos para exportar con columnas de política
$resultadosParaExportar = @()

foreach ($item in $resultados) {
    # Crear un diccionario base con los campos comunes
    $obj = [ordered]@{
        Dominio          = $item.Dominio
        NombreGPO        = $item.NombreGPO
        ActivaLaPolitica = $item.ActivaLaPolitica
        ActivoUsuario    = $item.ActivoUsuario
        ActivoMaquina    = $item.ActivoMaquina
        OwnerPolitica    = $item.OwnerPolitica
        Linkada          = $item.Linkada
    }

    # Añadir las columnas de políticas dinámicamente
    for ($i = 0; $i -lt $maxPoliticas; $i++) {
        $nombreColumna = "Politica$($i + 1)"
        if ($i -lt $item.PoliticasActivas.Count) {
            $obj[$nombreColumna] = $item.PoliticasActivas[$i]
        }
        else {
            $obj[$nombreColumna] = ""
        }
    }

    $resultadosParaExportar += New-Object PSObject -Property $obj
}

# Exportar a CSV
$resultadosParaExportar | Export-Csv -Path $salidaCSV -NoTypeInformation -Encoding UTF8

Write-Output "Exportado a: $salidaCSV"

En entornos Windows, la gestión y auditoría de Políticas de Grupo (GPO) es fundamental para garantizar la seguridad y correcta configuración de los equipos y usuarios. Muchas veces, estas políticas se exportan en formato XML para su análisis o documentación.

Este script en PowerShell facilita la extracción de información clave de múltiples archivos XML que contienen reportes de GPOs, y genera un CSV con un resumen ordenado y claro. A continuación, te explicamos paso a paso cómo funciona y qué hace cada parte.

¿Qué hace este script?

Explicación detallada del script

1. Definición de rutas y variables iniciales

$directorio = "C:\GPOs_Reportes_xml"
$salidaCSV = "$directorio\gpos_exportadas.csv"
$resultados = @()
$maxPoliticas = 0

Se establece la carpeta donde están los XML, la ruta del CSV de salida, una lista para guardar los resultados, y una variable para controlar el máximo número de políticas activas encontradas en todos los archivos.

2. Lectura y procesamiento de cada archivo XML

Get-ChildItem -Path $directorio -Filter *.xml -Recurse | ForEach-Object {
...
}

Se recorren todos los archivos .xml en la carpeta y subcarpetas. Por cada archivo, se carga el contenido como XML.

3. Extracción de datos relevantes

$dominio = $xml.GPO.Identifier.Domain.'#text'
$nombreGPO = $xml.GPO.Name
$nsManager = New-Object System.Xml.XmlNamespaceManager($xml.NameTable)
$nsManager.AddNamespace("gp", "http://www.microsoft.com/GroupPolicy/Types/Security")
$nsManager.AddNamespace("gpTypes", "http://www.microsoft.com/GroupPolicy/Types")

$ownerNameNode = $xml.SelectSingleNode("//gp:Owner/gpTypes:Name", $nsManager)
$owner = if ($ownerNameNode) { $ownerNameNode.InnerText } else { "Desconocido" }

Aquí se hace uso de un XmlNamespaceManager para navegar correctamente por nodos con namespaces y obtener el nombre del propietario.

$activoMaquina = $xml.GPO.Computer.Enabled
$activoUsuario = $xml.GPO.User.Enabled

Se revisan las políticas activas tanto para la configuración de equipo como para usuario, agregando a un array las que están habilitadas.

$linkada = "No"
if ($xml.GPO.LinksTo) {
if ($xml.GPO.LinksTo.Enabled -and $xml.GPO.LinksTo.Enabled -eq "true") {
$linkada = "Si"
}
}

4. Preparación para exportar: columnas dinámicas según número de políticas

Para que el CSV tenga una columna por cada política activa, primero se detecta el máximo número de políticas activas en todos los GPOs para crear las columnas dinámicamente.

Luego, se construye un nuevo array de objetos donde cada objeto incluye los datos comunes y las políticas activas repartidas en columnas como Politica1, Politica2, etc.

5. Exportación a CSV

Finalmente, la colección se exporta a un archivo CSV en la ruta definida, con codificación UTF-8 y sin tipo de información extra.

$resultadosParaExportar | Export-Csv -Path $salidaCSV -NoTypeInformation -Encoding UTF8

Conclusión

Este script automatiza la extracción de información detallada de GPOs desde archivos XML, facilitando la auditoría y documentación de políticas activas en un entorno Windows. Gracias al uso de PowerShell y manejo avanzado de XML con namespaces, es capaz de extraer datos complejos y presentarlos en un formato fácil de analizar con Excel o cualquier otra herramienta que soporte CSV.

Si gestionas grandes infraestructuras con muchas políticas, este script puede ahorrarte mucho tiempo y ofrecer un reporte limpio y completo.

Salir de la versión móvil