# 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?
- Lee todos los archivos XML dentro de una carpeta y sus subcarpetas.
- Extrae datos importantes de cada GPO, como el dominio, nombre, estado de activación, propietario y las políticas activas.
- Identifica si la GPO está vinculada a alguna unidad organizativa u otro contenedor (campo LinksTo).
- Organiza la información en un formato tabular, donde cada política activa aparece en una columna separada.
- Exporta todo el conjunto de datos a un archivo CSV para su posterior análisis o integración en otras herramientas.
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 y nombre del GPO:
$dominio = $xml.GPO.Identifier.Domain.'#text'
$nombreGPO = $xml.GPO.Name
- Propietario (Owner) usando namespaces XML:
$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.
- Estado de activación para usuarios y máquinas:
$activoMaquina = $xml.GPO.Computer.Enabled
$activoUsuario = $xml.GPO.User.Enabled
- Listado de políticas activas:
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.
- Detección de si la GPO está vinculada (Linkada):
$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.