Encuentre usuarios de Entra ID con PowerShell
Utilice filtros para dirigirse a buzones de correo y cuentas de usuario de Entra ID
Los scripts de PowerShell a menudo comienzan buscando un conjunto de cuentas de usuario de Entra ID o buzones de correo de Exchange para procesar. El enfoque clásico es ejecutar un cmdlet como Get-ExoMailbox o Get-MgUser para encontrar los objetos deseados. Sin embargo, las cosas pueden volverse un poco complicadas cuando intentas recuperar el conjunto óptimo. Por ejemplo:
- Solo buzones de usuario (excluidos los buzones compartidos y de sala).
- Solo cuentas con licencia (centrándose en las cuentas de usuario a las que se les asignan licencias para usar los servicios de Microsoft 365).
El primer conjunto se encuentra fácilmente con:
[array]$Mailboxes = Get-ExoMailbox -RecipientTypeDetails UserMailbox -ResultSize UnlimitedEl segundo con:
[array]$Users = Get-MgUser -Filter "assignedLicenses/`$count ne 0 and userType eq 'Member'" -ConsistencyLevel eventual -CountVariable Records -All -Property Id, displayName, AssignedLicensesLa sintaxis del último ejemplo es más compleja porque utiliza un filtro Graph para buscar cuentas con al menos una licencia (el recuento es mayor que 0) que son miembros (no invitados) del inquilino. También es lo que Microsoft denomina una consulta avanzada contra objetos Entra ID, razón por la cual el parámetro de nivel de coherencia está presente.
El problema es que las cuentas utilizadas por buzones compartidos y buzones de sala pueden tener licencias. Los buzones de correo compartidos necesitan licencias para usar un archivo o tener una cuota de buzones mayor, mientras que los buzones de sala tienen licencias cuando los usan dispositivos Teams Rooms. Es posible que su secuencia de comandos no necesariamente desee procesar estas cuentas porque la intención es tratar con cuentas propiedad de humanos en lugar de salas o dispositivos.
Después de crear la matriz de buzones de correo compartidos y de sala, es fácil filtrar la matriz de usuarios para eliminar cuentas que no están en esa matriz:
[array]$NonUserAccounts = Get-ExoMailbox -RecipientTypeDetails SharedMailbox, RoomMailbox -ResultSize Unlimited | Select-Object UserPrincipalName, ExternalDirectoryObjectId
Write-Host "Removing non-user accounts from set to be processed..."
$Users = $Users | Where-Object {$_.Id -notin $NonUserAccounts.ExternalDirectoryObjectId}
El resultado es una matriz que contiene cuentas de usuarios con licencia que pertenecen a humanos. Utilizo esta técnica en el script para crear un informe HTML de los gerentes y sus subordinados directos.
Buscar cuentas de usuario para empleados
Entra ID incluye varios atributos para los datos de los empleados. Tres atributos importantes son:
- EmployeeId: un valor de cadena que contiene el identificador del empleado asignado por la organización. A menudo se trata de un número.
- EmployeeHireDate: valor de la fecha en que el empleado se unió a la organización.
- EmployeeType: un valor de cadena para indicar el tipo de empleado. Por ejemplo, podría almacenar valores como "Temporal", "Permanente" y "A tiempo parcial" en este atributo.
Los atributos de los empleados no forman parte del conjunto predeterminado devuelto por Graph. Puede filtrar según los atributos de forma normal, pero si desea ver los datos, debe especificar los atributos en la solicitud de gráfico. Por ejemplo, este comando Get-MgUser busca cuentas de miembros con algún valor en el atributo EmployeeId sin incluir el valor del atributo en los datos devueltos por Graph. La comparación con un espacio es una de las debilidades que hay que tener en cuenta cuando se trabaja con Graph.
[array]$Employees = Get-MgUser -filter "userType eq 'Member' and EmployeeId ge ' '"
$Employees | Format-Table DisplayName, EmployeeId
DisplayName EmployeeId
----------- ----------
Rene Artois
Tony Redmond
Para ver los datos del empleado, especifique las propiedades para que devuelva la llamada:
[array]$Employees = Get-MgUser -filter "userType eq 'Member' and EmployeeId ge ' '" -Property Id, displayname, userprincipalname, employeeid, employeehiredate, employeetype
$Employees | Format-Table DisplayName, EmployeeId, EmployeeType, EmployeeHireDate
DisplayName EmployeeId EmployeeType EmployeeHireDate
----------- ---------- ------------ ----------------
Rene Artois 111888 Permanent 08/03/2018 00:00:00
Tony Redmond 150847 Permanent 01/01/2011 00:00:00
Desafortunadamente, Graph no admite el filtrado según las propiedades de tipo de empleado o fecha de contratación del empleado (consulte esta página como referencia). Si desea filtrar según la fecha de contratación, cree la matriz de empleados como se muestra arriba y utilice un filtro del lado del cliente. Por ejemplo, este código busca empleados contratados en los últimos diez años:
$CheckDate = (Get-Date).AddDays(-3650)
$Employees | Where-Object {$CheckDate -as [datetime] -lt $_.EmployeeHireDate}
Mientras que este comando encuentra cuentas con el tipo de empleado marcado como permanente.
$Employees | Where-Object {$_.EmployeeType -eq "Permanent"}También necesitará un filtro del lado del cliente para utilizar los operadores de comparación Me gusta, Coincidencia y otros disponibles en PowerShell. Las solicitudes de gráficos se limitan a eq, and, o y startswith al evaluar cuentas de usuario.
Encuentre cuentas de usuario con atributos personalizados de Exchange
El uso de cualquier consulta contra Entra ID depende de que haya datos precisos en los atributos consultados. Mi experiencia es que relativamente pocos inquilinos de Microsoft 365 completan los atributos de empleado disponibles en Entra ID. Esto podría deberse a que muchas organizaciones son híbridas o tienen otras razones para no utilizar los atributos de los empleados (como no saber que están disponibles) o que se utilizan otros esquemas. Por ejemplo, las organizaciones que utilizan Active Directory y Exchange Server a veces marcan cuentas "humanas" almacenando un valor en un atributo personalizado (extensión). El atributo puede almacenar valores como Empleado, Temporal, Consultor y Cuenta de servicio para indicar el propósito de la cuenta. Este ejemplo busca cuentas de usuario con licencia donde ExtensionAttribute2 almacena "Empleado" para marcar cuentas que pertenecen a humanos.
[array]$EmployeeAccounts = Get-MgUser -Filter "onPremisesExtensionAttributes/extensionAttribute2 eq 'Employee' and assignedLicenses/`$count ne 0 and userType eq 'Member'" -ConsistencyLevel eventual -CountVariable Records -AllSi su organización utiliza atributos personalizados de Exchange para almacenar información de los empleados, no hay una buena razón para cambiar al uso de los atributos de ID de Entra, a menos que desee o necesite utilizar los atributos de Exchange para un propósito diferente. El cambio es cuestión de leer los atributos de Exchange Online y escribirlos en Entra ID, por lo que es sencillo. A continuación se muestra un código simple para ilustrar cómo obtener los detalles de los empleados de Exchange Online y escribirlos en la cuenta del usuario. El valor de EmployeeType se toma de CustomAttribute2, mientras que el valor de EmployeeHireDate proviene de la fecha de creación del buzón.
[array]$Mailboxes = Get-ExoMailbox -RecipientTypeDetails UserMailbox -ResultSize Unlimited -Properties CustomAttribute2, WhenCreated
ForEach ($Mbx in $Mailboxes) {
Update-MgUser -UserId $Mbx.ExternalDirectoryObjectId -EmployeeType $Mbx.CustomAttribute2 -EmployeeHireDate (Get-Date($Mbx.WhenCreated))
}
División del procesamiento
A veces, una organización abarca tantas cuentas que lleva mucho tiempo recuperar todas las cuentas. En estas circunstancias, puede dividir el procesamiento dividiendo las cuentas en conjuntos convenientes. Algunas personas utilizan departamentos como base para el procesamiento y otras utilizan países. En este ejemplo, recuperamos cuentas de usuarios con licencia según el apellido. La figura 1 muestra el resultado.
[array]$Surnames = "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "W", "X", "Y", "Z"
ForEach ($S in $Surnames) {
$Filter = "assignedLicenses/`$count ne 0 and userType eq 'Member' and startsWith(surname,('$S'))"
[array]$Users = Get-MgUser -Filter $Filter -ConsistencyLevel eventual -CountVariable Records -All
If ($Users) {
Write-Host ("{0} users have surname starting with {1}" -f $Users.count, $S)
Write-Host "---------------------------------------------"
$Users | Format-Table DisplayName, Surname
Write-Host ""
} Else {
Write-Host ("No users found with surname starting with {0}" -f $S)
}
}
Parte de una transición
Realizar llamadas efectivas para buscar buzones de correo y/o cuentas de usuario puede ser la clave para crear o deshacer un script de PowerShell. El cambio del módulo obsoleto de Azure AD a los comandos Graph API o Graph SDK introduce un nuevo formato de filtro con el que es más difícil trabajar y carece de parte de la flexibilidad disponible a través de los operadores de comparación estándar de PowerShell. Actualizar scripts para usar Graph puede ser un desafío a veces, pero la forma positiva de ver las cosas es que ofrece la oportunidad de mejorar la eficiencia del código. Esto no es algo importante para organizaciones pequeñas y medianas, pero marca una gran diferencia cuando se administran decenas de miles de cuentas o buzones de correo.
