Las migraciones a Exchange Online fallan con el error “TooManyBadItemsPermanentException”

Algunos habéis podido observar en los últimos años que un mayor número de migraciones están fallando debido a encontrar demasiados ítems corruptos. Si analizamos más de cerca el motivo, veréis que el informe de migración contiene entradas haciendo referencia a elementos corruptos y no ha sido posible traducir las entradas principales de seguridad. Quería tomar unos minutos y proporcionar más información para ayudar a comprender lo que esto significa, por qué pasa ahora, y qué se puede hacer al respecto. Durante una migración de buzones de correo, existen varias fases por las que pasamos. Empezamos con una copia de la jerarquía de carpetas (incluyendo las vistas asociadas a dichas carpetas), posteriormente realizamos una copia inicial de los datos (lo que llamamos la sincronización inicial) y una vez finalizada la sincronización inicial, copiamos las reglas y descriptores de seguridad. En el informe de movimiento veremos entradas similares a las siguientes:

Stage: CreatingFolderHierarchy. Percent complete: 10 Initializing folder hierarchy from mailbox <guid>: X folders total Folder hierarchy initialized for mailbox <guid>: X folders created Stage: LoadingMessages Copying messages is complete. Copying rules and security descriptors.

Por los momentos vamos a centrarnos en la fase de copia de reglas y descriptores de seguridad.

Los descriptores de seguridad son listas de control de acceso o ACLs (Access Control Lists) que se comprenden de Entradas de Control de Acceso o ACEs (Access Control Entries) y que se almacenan en formato SDDL. En el contexto de un buzón, se incluyen tanto los descriptores de seguridad de buzón o permisos de buzón (Mailbox Security Descriptor / Mailbox Permissions) como los descriptores de seguridad de carpetas (también conocidos como Folder Security Descriptors o permisos de carpetas individuales).

Ahora, cuando nos fijamos en el Mailbox Security Descriptor, debe tenerse en cuenta que únicamente se copian los permisos de buzón explícitos. Estos incluyen permisos concedidos mediante el CmdLet Add-MailboxPermission, o la consola de administración de Exchange (2010)/Exchange Admin Center (2013 y 2016) para agregar permisos de acceso total o “Full Access”. Cualquier permiso heredado no se evaluará durante la fase de copiado. Por ejemplo, los permisos de “Receive-As” otorgados en un objeto de base de datos en Active Directory resultan siendo un permiso heredado de Full Access para todos los buzones alojados en dicha base de datos. Cuando estos buzones se migran a Exchange Online, dichos permisos heredados no llegan a copiarse.

Una vez descrito brevemente los Security Descriptors, echemos un vistazo al problema comentado al principio de este artículo. A mediados del 2016, se introdujo un cambio en Exchange Online en el que, si un Security Principal no pudiese ser validado/mapeado a un objeto de Exchange Online, se marcaría como un ítem corrupto o defectuoso. Anteriormente, dichos permisos no resolubles simplemente se ignoraban y luego eran los administradores los que tenían que investigar por qué de repente ciertos permisos dejaban de funcionar después de la migración. Con este cambio, los administradores pueden consultar cuales son los permisos no resolubles o que no se puedan asociar a otros objetos de Exchange Online y por lo tanto poder anticiparse a posibles futuras incidencias relacionadas con los buzones migrados, por lo tanto, desde mi perspectiva como un ingeniero de soporte, dicho cambio es beneficioso para la organización. Es probable que este comportamiento continúe evolucionando según pasa el tiempo, pero mi consejo es el de familiarizarse con él para entender que es lo que ocurre en realidad.

¿Cómo podría afectarle esto en su entorno? Bueno, dado que estaremos incrementando el número de ítems corruptos por cada permiso que no podamos asociar a un objeto en Exchange Online, una vez alcanzado o sobrepasado el umbral establecido para el número de elementos corruptos/inválidos en la migración (por defecto es 10 en un lote de migración o Migration Batch y 0 en el caso de Move Requests – salvo que se especifique un valor superior), la migración/movimiento de buzón fallará. Dependiendo del estado de permisos, se podría observar potencialmente un número elevado de entradas relacionadas con estos en el informe de movimiento. En dicho informe podremos ver entradas tales como las siguientes:

11/12/2016 8:44:43 AM [EXO MRS Server] A corrupted item was encountered: Unable to translate principals for folder "Folder Name"/"FolderNTSD": Failed to find a principal from the source forest.

5/19/2016 6:33:50 PM [EXO MRS Server] A corrupted item was encountered: Unable to translate principals to the target mailbox: Failed to find a principal in the target forest that corresponds to the following source forest principal values: Alias: <alias>; DisplayName: <Display Name>; MailboxGuid: <mailbox guid>; SID: <SID of User>; ObjectGuid:

<Object GUID>; LegDN: <legacyExchangeDN>; Proxies: [X500:<legacyExchagneDN format>; SMTP:user@contoso.com;];.

 

5/19/2016 6:33:50 PM [EXO MRS Server] A corrupted item was encountered: Unable to translate principals to the target mailbox: Failed to find a principal in the target forest that corresponds to the following source forest principal values: SID: <SID of User>; ObjectGuid: <Object GUID>;.

De acuerdo, ¿entonces cuál es la lógica aplicada para validar los permisos?... Existen 4 pasos básicos asociados a este proceso que paso a detallar a continuación:

Exchange Online necesita resolver el SID presente en el Security Descriptor (presente en carpeta o buzón)

  1. Exchange Online realiza una petición al MRS Proxy de On-Premises pasando el SID a resolver
  2. El MRS Proxy de On-Premises consulta el SID proporcionado al Active Directory, el cual devolverá un conjunto de atributos (incluyendo el SID primario y el legacyExchangeDN)
  3. Exchange Online recogerá el valor del legacyExchangeDN obtenido en el paso anterior e intentará coincidirlo con un objeto de Exchange Online que contenga dicho valor como una dirección proxy X500.

Normalmente, la sincronización de directorios se encargará de estampar el legacyExchangeDN de cada lado como una dirección proxy X500, pero esto no significa que el legacyExchangeDN de On-Premises deba coincidir con la dirección proxy X500 de un objeto habilitado para correo – o Mail-Enabled recipient presente en Exchange Online (p.e. un buzón, MailUser, Mail-enabled Security Group…). Si este último es el caso, entonces es cuando la resolución del permiso fallará.

Existen dos tipos de excepciones relacionados con permisos y me gustaría diferenciarlas:

SourcePrincipalMappingException – Cuando se nos presenta esta excepción, es porque el MRS Proxy intenta consultar el SID en el Active Directory de On-Premises y no ha podido resolverse.

Es muy común encontrarnos con este escenario y normalmente es provocado cuando un usuario deja la organización y su cuenta es eliminada. También podemos ver esta excepción cuando el SID en cuestión es parte del SIDHistory de una cuenta de On-Premises, dado que cuando el MRS Proxy intenta consultar el SID, únicamente buscaremos por ObjectSID o msExchMasterAccountSID y, por ende, MRS Proxy no consultará el SIDHistory, por lo tanto, dicha excepción será la esperada. La situación en el que el SIDHistory tenga valores no es algo habitual, pero desde luego es algo para tener en cuenta.

Nota: Exchange Online tiene implícito un límite excepcional de ítems corruptos para que los movimientos no fallen por este tipo de excepción, siempre y cuando el número no supere los 1000.

TargetPrincipalMappingException – Esta excepción indica que no podemos mapear o relacionar el permiso a una cuenta de usuario en el bosque de destino (Exchange Online). Un ejemplo perfecto de esto sería el de un usuario o grupo al que se le han otorgado permisos sobre un buzón, pero ese usuario o grupo se encuentra excluido del ámbito de sincronización con la nube. Después de intentar mover el buzón mediante MRS, dicho usuario o grupo no estará presente en Exchange Online y por lo tanto obtendremos de forma esperada esta excepción.

Otro escenario que podemos encontrarnos es si un grupo de seguridad que no esté Mail-Enabled, se haya utilizado para otorgar permisos. Este tipo de grupos (no Mail-Enabled) no se sincronizan con Exchange Online y por lo tanto no existirán en el bosque de destino.

 

Para resolver el problema tenemos dos opciones:

  1. Incrementar el límite de ítems corruptos (Bad Item Limit) para tener en cuenta los errores de permisos. En entornos complejos en los que hay múltiples versiones de Exchange y los objetos han estado de un lado a otro, podemos encontrarnos con miles de errores de permisos, por lo que no sería descabellado establecer un valor elevado en el Bad Item Limit. Las buenas noticias es que según Exchange ha ido evolucionando a lo largo de los años, la posibilidad de encontrarnos mensajes corruptos es relativamente baja, por lo que la mayoría de los ítems corruptos que encontremos serán permisos que no podamos resolver y no contenido del buzón en si. No obstante, podemos identificarlos mediante el análisis del informe de movimiento. Más adelante en este mismo post veremos como hacerlo.
  2. La segunda opción consiste en cancelar la petición de movimiento, arreglar los permisos en cuestión (bien eliminándolos o arreglando su resolución) y volver a intentar el movimiento de nuevo. ¿Y si quiero arreglar dichos permisos y continuar con el movimiento? Bueno, no voy a decir que no lo hagáis, sin embargo, no cambiará nada y únicamente estaremos perdiendo el tiempo, dado que únicamente evaluaremos los permisos una única vez al final de la copia inicial de los datos. Si el movimiento falla por superar el número de ítems corruptos (debido a permisos), no volveremos a evaluarlos y daremos el movimiento como fallido con las excepciones descritas anteriormente. Por lo que las únicas opciones se reducirán a incrementar el Bad Item Limit o volver a lanzar el movimiento recreándolo desde cero después de arreglar dichos permisos.

Tal y como había prometido, vamos a ver como analizar el informe de movimiento con relación a los errores de permisos. Para ello deberemos hacer uso de PowerShell para exportar el informe de movimiento y almacenarlo en una variable temporal.

Para guardar el informe en una variable temporal deberemos ejecutar la siguiente línea en una Ventana de PowerShell conectada a una sesión de Exchange Online:

$movereport = Get-MoveRequestStatistics <move request identity> -IncludeReport

También podemos exportar informe a un fichero XML y analizarlo en local ejecutando la siguiente línea:

Get-MoveRequestStatistics <move request identity> -IncludeReport | Export-CliXml c:\temp\movereport.xml

Una vez exportado el fichero XML, podemos guardarlo en una variable para poder trabajar con el mediante la siguiente línea (sin necesidad de conectarnos a Exchange Online):

$movereport = Import-CliXml c:\temp\movereport.xml

Si anteriormente no habéis visto lo que contiene un informe de movimiento, simplemente puedo indicar que la información contenida (de todo tipo) es oro en paño, y que podremos encontrar a través del portal.

Ahora que tenemos el informe de movimiento almacenado en una variable (a la que llamamos $movereport), podemos acceder a la preciada información haciendo llamadas a ella tal y como podemos ver a continuación:

$movereport.report.baditems – Esto nos devolverá una lista de todos los ítems corruptos que se han encontrado. Una recomendación interesante es que podemos hacer uso de “Out-GridView” (o OGV) para poder ver los resultados en una ventana grafica en lugar de mostrarlos en la ventana de PowerShell.

$movereport.report.baditems | Out-GridView $movereport.report.baditems | OGV

Lo bueno de hacer uso de Out-GridView es que podemos jugar con filtros sobre la marcha. Por ejemplo, podemos comprobar los items corruptos y relacionarlos con los errores de permisos simplemente eligiendo “Add criteria”, seleccionando la opción “Kind”, y hacemos clic en “Add”.

Cambiamos la condición “Contains” a “Does not contain”, y escribimos “Security”. De esta forma únicamente mostraremos los ítems corrutos de cualquier otro tipo.

Ahora que hemos identificado el cambio de comportamiento, y observado cómo solucionarlo, vamos a terminar hablando sobre que aproximación deberíamos tener en cuenta a la hora de planificar la migración.

La aproximación recomendada de cara a este cambio de comportamiento sería la de continuar migrando con un número bajo de BadItemLimit, y manualmente corregir aquellos que fallen. Recomendamos esto porque las migraciones que resulten fallidas podrían indicar bien que existen BASTANTES permisos corruptos en origen (más de 1000) o bien que son permisos validos pero que simplemente dichas cuentas no existen en Exchange Online y por lo tanto no es posible mapearlas. Ambas condiciones no deberían ser comunes, por lo que sería recomendable llevar a cabo una investigación sobre que ha sido la verdadera causa.

 

Agradecimientos especiales a Brad Hughes y el resto del equipo de MRS por su asistencia y revisión de este contenido, y por supuesto a Ben Winzenz por tomarse su tiempo en redactarlo (su versión en inglés puede encontrarse en https://blogs.technet.microsoft.com/exchange/2017/05/30/toomanybaditemspermanentexception-error-when-migrating-to-exchange-online/)