Exportar y eliminar OU vacías en Active Directory

Tenemos una implementación de FIM (Forefront Identity Manager) que siempre está haciendo cosas raras.

La última de estas es que debido a un cambio en el ERP fueron creadas cientos de OU vacias en el Active Directory 🙂

Maravilloso…

Afortunadamente, con PowerShell y ActiveRoles fue muy fácil saber cuáles fueron estas OU. Aquí os dejo el script:


$OUS = Get-QADObject -Type organizationalunit -SizeLimit 0

$output = @()

foreach($OU in $OUS) {
$Children = Get-QADObject -SearchRoot $OU -LdapFilter “(!(objectClass=organizationalUnit))” -SizeLimit 1 -WarningAction SilentlyContinue | Measure-Object
$outputObj = “” | select OU,CanonicalName,HasChildren,Level
$outputObj.OU = $OU.Name
$outputObj.CanonicalName = $OU.CanonicalName

if ($Children.Count -ne 0) {
$outputObj.HasChildren = “Yes”
}
else {
$outputObj.HasChildren = “No”
}

$outputObj.Level = $OU.CanonicalName.Split(“/”).Count
$output += $outputObj
}

$output | export-csv -notypeinformation -encoding utf8 -delimiter “;” EmptyOUs.csv

Este nos va a exportar un CSV que luego podemos abrir en Excel. En este se muestra la OU, el nombre canónico de la OU, si tiene hijos que no sean otras OU vacías y el nivel de la OU (siendo la raíz del dominio el nivel 0).

Una vez que tenegamos identificadas las OU vacías, podemos exportar el listado de los nombres canónicos de las OU a borrar y borrarlas con el siguiente comando:

LA SIGUIENTE LINEA ES PELIGROSA, ASEGURATE DE TENER UN BACKUP DEL AD ACTUALIZADO ANTES DE EJECUTARLA

get-content -encoding utf8 MiLista.txt | Remove-QADObject -DeleteTree -Force -Confirm:$false

Convertir NDR IMCEAEX a dirección X500

Si alguna vez has borrado por error o has restaurado un buzón/contacto/grupo de Exchange a un usuario diferente del original, probablemente has recibido quejas de los usuarios diciendo que cada vez que envían un correo al usuario en cuestión reciben un NDR de Exchange con un mensaje parecido al siguiente:

captura ndr

El motivo de esto es que Outlook almacena los usuarios de Exchange como contactos X500 en la caché de Autocompletar (¿Por qué? No se, pero viene de muy atrás). Para solucionar esto la KB2807779 nos dice que podemos limpiar la cache de Autocompletar de Outlook o agregar un contacto X500 al usuario de Exchange. El problema es que no hay forma sencilla de aplicar la primera opción de forma automatizada a muchos usuarios a la vez, así que normalmente solo nos queda la segunda.

Para aplicar la segunda solución debemos abrir las propiedades de un buzón/contacto/grupo en Exchange, ir a la pestaña de direcciones de correo y agregar una dirección personalizada X500. ¿Qué ponemos como dirección? Tenemos que copiar la dirección que nos devuelve en el mensaje de error de NDR y reemplazar ciertos caracteres tal y como nos explica esta entrada.

Como soy vago, muy vago. Hice una pequeña funcion en PowerShell para no tener que hacer este reemplazo manualmente. Aquí os la dejo.

function Convert-IMCEAEX ($address) {
$address = $address.Replace("+20"," ")
$address = $address.Replace("+28","(")
$address = $address.Replace("+29",")")
$address = $address.Replace("+2E",".")
$address = $address.Replace("_","/")
$address = $address.Replace("IMCEAEX-","")

$lastIndex = $address.LastIndexOf("@")
if ($lastIndex -gt 0) {
$address = $address.Substring(0, $lastIndex)
}

return $address
}

Creo que está bastante claro lo que hace. Simplemente le pasamos la dirección “sucia” y esta nos la limpia.

Exportar listado de dispositivos con ActiveSync y su cuenta asociada

Aquí os dejo un script para saber qué dispositivos tenemos sincronizados con nuestra organización. Es muy recomendable ejecutarlo cada cierto tiempo para hacer limpieza de dispositivos que hace tiempo que no se conectan, que pertenecen a usuarios que ya se han ido de la empresa, o simplemente tener una idea de quienes tienen sincronizado su correo con dispositivos móviles.

Esta pensado para Exchange 2010, pero debería funcionar en otras versiones también.

Descargar

Crear Directorio Personal/Carpeta Particular (Home Directory) con Powershell

Seguimos migrando el servidor de ficheros…

Esta vez toca mover los directorios personales (carpeta particular en AD) de todos los usuarios al nuevo servidor.

Ir usuario a usuario cambiando este directorio es muy tedioso, por lo que una vez más vamos a usar PowerShell para terminar mas rápido.

Lo primero que tenemos que hacer es crear los directorios en el nuevo servidor para después mover los datos. Una de las cosas que hay que tener cuenta al mover estos directorios personales de cada usuario es que solo ese usuario (y los administradores del servidor) deben tener acceso a estos. Cuando este directorio se asigna desde la interfaz de administración de Active Directory esta se encarga de asignar los permisos requeridos, pero cuando lo haces directamente desde el servidor de ficheros los permisos se deben cambiar manualmente.

Afortunadamente, los de Scripting Guy de Microsoft crearon una serie de posts donde explican como hacer esto a través de PowerShell, el problema es que el código que está en la parte 3 de la serie, que debería hacer todas estas tareas, tiene varios bugs.

Desde aquí te puedes decargar ese código corregido y convertido en una funcion (Create-HomeDirectory). Recuerda cambiar los valores de HomeDrive, UserRoot y Domain por los valores que correspondan para tu entorno.

Para usar la función solo tienes que ejecutar Create-HomeDirectory NombreUsuario.

Una vez que esten creados todos los directorios con los permisos correspondientes en el nuevo servidor solo queda mover los datos con Cortar y Pegar, Robocopy o cualquier otra herramienta.

Convertir SID en Base64 a String con Powershell

Si exportas los datos del Active Directory usando LDIFDE te darás cuenta de que algunos campos vienen en formato Base64. Por lo general esto no es un problema, ya que estos se pueden decodificar usando cualquier herramienta de las muchas que hay en la web para este propósito. Sin embargo, en el caso del SID, si intentas pasar de Base64 a String verás que la salida esta compuesta de un montón de caracteres extraños.

Para pasar esto al formato que todos conocemos de S-1-5-***** puedes utilizar el siguiente script:

$sidBase64 = "AQUAAAAAAAUVAAAAPXj3WXwxNhGBjE3aTQQAAA=="

$sid = [System.Convert]::FromBase64String($sidBase64)

$nuevoSid = New-Object System.Security.Principal.SecurityIdentifier($sid, 0)

$nuevoSid.ToString()

sid

Referencia

Exportar detalle de Shortcuts de Enterprise Vault desde Exchange

Debido a una incidencia que tuvimos con el Enterprise Vault, tuve que buscar la forma de exportar los shortcuts de un buzón de Exchange a CSV para despues hacer un control de daños de cuáles correos teníamos que recuperar.

No fue una tarea fácil, pero al final lo logré teniendo como base el genial script de Michel de Rooij de este enlace.

Para ejecutar el script solo hay que descargar el Exchange Web Services API y ponerlo en la misma carpeta del script, luego hay que modificar los 5 parámetros del script y ejecutarlo.

El script no es bonito, ni está documentado, ni tiene control de errores (cuando tenga tiempo lo hago), pero funciona (por lo menos en Exchange 2010 SP3).

Descargar script.

Exportar permisos de un árbol de carpetas

Cualquier servidor de ficheros de un tamaño considerable siempre va a tener problemas de permisos. Esto normalmente es causado por permisos mal otorgados, por desconocimiento de los adminstradores o por no tener una politica de gestión de los permisos.

Una vez que los permisos están mal es muy difícil corregirlos, no porque sea técnicamente imposible, sino porque lleva mucho tiempo, ya que necesitamos saber qué permisos están definidos en cuáles carpetas y si estos se heredan a las carpetas inferiores no. Luego esta información hay que trasladársela al responsable de la carpeta para que defina los permisos correctos y poder corregirlos.

Este script es muy útil para esto, exporta en formato CSV los permisos de un árbol de carpetas. Para hacer el listado más fácil de leer sólo se exportan los permisos no heredados, es decir, si tienes 200 carpetas y sólo 3 de estas tienen permisos especiales definidos, sólo estas 3 apareceran en el reporte, ya que por lógica las demás carpetas heredan de su respectiva carpeta madre.


$allFolders = Get-ChildItem -Recurse "Ruta de la carpeta" | ? {$_.PSisContainer}

$output = @()

foreach($folder in $allFolders)
{
$notInherited = ($folder.FullName | Get-Acl).Access | where {$_.isinherited -eq $false}

if($notInherited -ne $null)
{
$all = ($folder.FullName | Get-Acl).access
foreach ($item in $all)
{
$outputObj = "" | Select FullName,IdentityReference,FileSystemRights

$outputObj.FullName = $folder.FullName
$outputObj.IdentityReference = $item.IdentityReference
$outputObj.FileSystemRights = $item.FileSystemRights

$output += $outputObj
}
}
}

$output | Export-Csv -NoTypeInformation -Encoding utf8 -Delimiter ";" Reporte.csv

Incluir manager al exportar un listado de usuarios

Un requisito muy común a la hora de exportar un listado de usuarios del Active Directory es incluir el manager o responsable de una persona dentro del listado.

Hacer esto con PowerShell es muy sencillo, utilizando nuestro viejo ActiveRoles podemos ejecutar el siguiente comando:

Get-QADUser | Select-Object Name,Department,Title,Manager,Company

¿Problema? El comando nos devuelve todos los datos, pero el manager viene con su Distinguished Name (DN: CN=El Jefe,OU=Mi OU,DC=MiDominio,DC=Root). Esto puede que sea correcto, pero no nos es de mucha utilidad a la hora de pasarle la información al auditor que necesita este listado para ayer por la mañana 🙂 .

Para solucionar este detalle podemos hacer dos cosas, decirle al auditor que es “eche e o que hai”, con lo que seguramente te mirará con mala cara y luego se chivará con el jefe, o entregarle un listado en condiciones. Para esto último tenemos que usar las propiedades calculadas de la siguiente forma:

Get-QADUser | Select-Object Name,Department,Title,@{Expression={(Get-QADUser $_.Manager).Name};Label="Manager"},Company

Listo, puedes entregarle la información la información al auditor y seguir tomándote el café mientras le cuentas a tus compis lo mal que lo ha hecho Lenovo con todo el rollo de Superfish.

Administrar Active Directory con PowerShell y ActiveRoles Management Shell

La administración de Active Directory se ha hecho más sencilla con el paso de los años, se ha pasado por la interfaz ADUC (Active Directory Users and Computers), herramientas de línea de comando, el Centro de administración de Active Directory y en los últimos años los Snap-ins de PowerShell. Las interfaces gráficas son muy útiles para tareas puntulaes, tales como cambiar el nombre de un usuario, bloquear y desbloquear cuentas o mover PCs de una OU a otra. Sin embargo, para trabajos en lote es mejor utilizar scripts de PowerShell. El Snap-in de Active Directory incluído en las herramientas de RSAT de Windows 7 están bien, pero en mi opinión tiene fallos que dificultan su utilización. No quiero entrar en detalle, pero uno de estos fallos es que no muestra los Time Stamps de algunos campos en un formato legible y estos campos se utilizan mucho en los scripts.

Un sustituto de este Snap-in es el ActiveRoles Managemente Shell ofrecido de forma gratuita por DELL (antes Quest) desde hace algunos años. Lo puedes descargar desde aquí.

Algunos ejemplos de scripts que se pueden ejecutar con esta herramienta son los siguientes:

  • Listar usuarios con su última fecha de logon (la diferencia entre LastLogon y LastLogonTimeStamp para el próximo post)
    Get-QADUser -IncludedProperties LastLogonTimeStamp | Select-Object Name,ParentContainer,LastLogonTimeStamp
  • Listar usuarios deshabilitados
    Get-QADUser -Disabled:$true
  • Deshabilitar todas las cuentas de equipo que estén inactivas
    Get-QADComputer -Inactive | Disable-QADComputer
  • Exportar todos los usuarios de la OU Administración a un CSV delimitado por punto y coma
    Get-QADUser -SearchRoot "chorbo.es/Administracion" | Export-Csv -NoTypeInformation -Encoding UTF8 -Delimiter ";" UsuariosAdministracion.csv