Mantenimiento de relaciones gerente-empleado almacenadas en Azure AD

En el pasado, escribí sobre la importancia de estandarizar el proceso de creación de cuentas de Azure AD para que las propiedades de la cuenta terminen llenándose por completo con propiedades como departamento, administrador, etc. Aunque es relativamente fácil asegurarse de que las propiedades de la cuenta sean precisas cuando se crean, con el tiempo, es casi inevitable que surjan imprecisiones a menos que se tomen medidas para validar y corregir errores en los vínculos del administrador de cuentas de usuario de Azure AD. PowerShell es muy útil a este respecto, ya que los scripts para identificar problemas con los datos de la cuenta son fáciles de escribir.

Las relaciones gerente-empleado son posiblemente las actualizaciones más difíciles de administrar. A menudo, los cambios en las líneas de informes ocurren sin ningún conocimiento del departamento de TI. Estos son asuntos de RR. HH. y, a menos que RR. HH. informe a TI sobre la necesidad de actualizar Azure AD, el directorio permanece intacto y desciende gradualmente a un estado inexacto.

La razón por la que la precisión del directorio es importante es que Microsoft 365 resalta los organigramas en varios lugares, como Teams (Figura 1), la tarjeta de perfil de usuario de Microsoft 365 y el explorador de la organización en Outlook para Windows (requiere una licencia de Viva Suite).

Figura 1: Organigrama basado en los vínculos entre gerente y empleado de Azure AD que se muestran en Teams

Obviamente, si Azure AD contiene información inexacta sobre las relaciones de informes, los gráficos generados por las aplicaciones serán engañosos. Ese es un problema que debería solucionarse.

Las grandes organizaciones suelen tener sistemas de recursos humanos sofisticados que pueden incluir una fuente de Azure AD para gestionar cambios como relaciones de informes, departamentos, números de teléfono, ubicaciones físicas, etc. Pero supongamos que nuestra organización no posee tal fuente. En su lugar, debemos idear una forma de replicar lo que podría suceder si hubiera una fuente de recursos humanos disponible.

Definición de una posible solución

Esbozando el tipo de solución que podríamos desarrollar, se me ocurrió lo siguiente:

  • HR proporciona actualizaciones periódicas de información sobre los gerentes y sus departamentos, incluido el gerente de nivel 2 para cada departamento. Para este ejercicio, usaremos un archivo CSV para almacenar estos datos.
  • Un script de PowerShell lee la información de recursos humanos y verifica cada cuenta de usuario para actualizar el administrador según el departamento asignado a la cuenta. Si el usuario es el administrador del departamento, el script actualiza la cuenta con el administrador de nivel 2. Debido a que existe la necesidad de alejarse de los módulos antiguos de Azure AD y MSOL, usaremos cmdlets del SDK de Microsoft Graph PowerShell.

Simple. El script podría ejecutarse de forma interactiva, pero en un entorno de producción, es más probable que se ejecute de forma programada con algo como un runbook de Azure Automation.

Una solución comercial de mantenimiento de directorios como LiveTiles Directory (que solía conocerse como Hyperfish) hará el trabajo de manera más elegante y completa, pero es más divertido codificar una solución casera. Puede descargar el script que escribí de GitHub. Como siempre, los guiones que escribimos son para ilustrar principios en lugar de ser soluciones completamente funcionales. Utilice el script como desee.

Scripting de la solución

La secuencia de comandos de ejemplo pasa por varias fases para encontrar cuentas de usuario, determinar el administrador de departamento adecuado para asignar y, finalmente, actualizar las cuentas. Aquí hay una descripción general de lo que sucede.

Primero, el script lee la información sobre los gerentes de departamento de recursos humanos. Debido a que los datos están en un archivo CSV, el cmdlet Import-CSV es todo lo que se necesita. Sin embargo, es posible que el script deba procesar a miles de empleados, por lo que se necesita un acceso rápido a los datos. Por esta razón, el script carga el nombre del departamento y el administrador (nombre principal del usuario) en una tabla hash. Si el script detecta algún error en los datos de gestión, marca un error y se detiene.

A continuación, la secuencia de comandos encuentra el conjunto de cuentas de usuario de Azure AD para procesar, las cuentas de usuario de Azure AD no siempre están asociadas con personas reales que pueden tener un administrador, por lo que para excluir las cuentas utilizadas para cosas como la sala y los buzones de correo compartidos y las cuentas de invitados, el El script usa una consulta Graph avanzada contra Azure AD con el cmdlet Get-MgUser para buscar cuentas con al menos una licencia asignada. Filtrar la salida de Get-MgUser de esta manera es un comando muy útil que probablemente terminará usando en muchos scripts:

Write-Host "Finding licensed Azure AD accounts..." [array]€Users = Get-MgUser -All -Filter "assignedLicenses/`€count ne 0 and userType eq 'Member'" -ConsistencyLevel eventual -CountVariable UsersFound | Sort-Object DisplayName If (!(€Users)) { Write-Host "Couldn't find any user accounts with assigned licenses!" ; break } 

Después de obtener el conjunto de cuentas de usuario, el script divide las cuentas en aquellas con una propiedad de departamento completada y aquellas que no la tienen. Obviamente, el script solo puede procesar cuentas con departamentos porque usa esa propiedad para encontrar al gerente. Al mismo tiempo, al darse cuenta de que la vida es imperfecta, el script lee un administrador predeterminado para usar cuando no puede coincidir con un departamento:

[array]€UsersNoDepartment = €Users | Where-Object {€Null -eq €_.department} [array]€UsersWithDepartment = €Users | Where-Object {€Null -ne €_.department} # Get default manager to assign people to when we can't find a department manager €DefaultManager = €ManagerData | Where-Object {€_.Department -eq "Default" } | Select-Object -ExpandProperty Manager 

La siguiente parte del script se enfoca en averiguar qué administrador asignar a una cuenta de usuario. Si la búsqueda en la tabla hash usando el valor del departamento para la cuenta de usuario tiene éxito, sabemos qué gerente asignar. Algunos procesos condicionales manejan la situación en la que un usuario es el administrador del departamento. Este código existe porque Microsoft 365 permite que un usuario sea su propio administrador, algo que no sucede muy a menudo en la vida real. Existe otro cheque para la cuenta del CEO, que no tiene un gerente porque está en la parte superior de la organización.

Después de determinar el administrador para asignar a una cuenta de usuario, el script verifica si el administrador ya está presente para la cuenta. Para ello, la secuencia de comandos ejecuta el cmdlet Get-MgUserManager y compara el valor del nombre principal de usuario del administrador con el nombre principal de usuario del administrador de departamento actual. Si los dos coinciden, el script no intentará actualizar la cuenta.

€UserManager = (Get-MgUserManager -UserId €User.Id -ErrorAction SilentlyContinue).additionalProperties.userPrincipalName  If (€DepartmentManager -eq €UserManager) {     # Same manager, so don't update     €DepartmentManager = €Null } 

El paso final es donde el script llama al cmdlet Set-MgUserManagerByRef para actualizar la cuenta. El cmdlet funciona por referencia, lo que significa que la entrada hace referencia a otro objeto (el administrador del departamento). El cmdlet acepta el objeto de destino identificado por su identificador de objeto o nombre principal de usuario (como se usa en este ejemplo). Esto es lo que hace el código:

Write-Host ("Updating user account {0} with manager {1}" -f €User.displayName, €DepartmentManager) €Id = ("https://graph.microsoft.com/v1.0/users/{0}" -f €DepartmentManager)  Set-MgUserManagerByRef -UserId €User.Id -AdditionalProperties @{ "@odata.id" = €Id } 

Como resultado, el script genera un informe sobre las actualizaciones de administración que procesa. La secuencia de comandos exporta el resultado como un archivo CSV y muestra los detalles a través del cmdlet Out-GridView (Figura 2).

Figura 2: Asignaciones de administrador realizadas por el script

La secuencia de comandos también indica si encuentra alguna cuenta que no tenga una propiedad de departamento.

Un poco más complejo de lo previsto

Cuando comencé a escribir el script de ejemplo, pensé que el código terminaría en unas 40 líneas. El script final es aproximadamente el doble (sin ningún tipo de manejo de errores), lo que nuevamente demuestra mi incompetencia al estimar tareas. Saber cómo manejar las asignaciones de administración con PowerShell es algo bueno. Aparte de cualquier otra cosa, este ejercicio demuestra el uso de los cmdlets Get-MgUserManager y Set-MgUserManagerByRef que puede necesitar para actualizar los scripts que usan los módulos de AzureAD y MSOL que eventualmente quedarán obsoletos.