Una migrazione tenant-to-tenant raramente fallisce sulle cose che sono state pianificate. Fallisce sul reparto amministrativo che il lunedì mattina non vede più le cassette condivise a cui aveva accesso, sul gruppo di distribuzione che era stato censito con quattrocento membri quando ne aveva milleduecento, sulla licenza che non si riesce ad assegnare perché all’utente manca un campo che nessuno aveva guardato.
Sono tutti problemi della stessa famiglia: cose che non erano nell’inventario. E l’inventario, in una migrazione fra tenant Microsoft 365, non è un elenco di caselle: è un insieme di identificatori tecnici che vanno raccolti prima, perché dopo il cutover non sono più leggibili dove servivano.
Abbiamo raccolto in un toolkit i dieci controlli che facciamo noi prima di aprire un progetto di migrazione. Sono gratuiti, di sola lettura, e girano su Microsoft 365 Business Premium.
Cosa fotografano i dieci script
01 Domini e record DNS. I domini custom con stato di verifica e i record di servizio
pubblicati oggi: MX, TXT di verifica e SPF, CNAME, SRV di Teams.
02 Cassette con ExchangeGuid e ArchiveGuid. Sono i due identificatori che vanno riportati
sugli oggetti mail-enabled del tenant di destinazione perché il servizio di spostamento riconosca
la cassetta come la stessa. Senza, la migrazione non parte.
03 Deleghe. FullAccess, SendAs e SendOnBehalf. Non si spostano insieme alla cassetta: vanno
ricostruite una per una, e questo è l’elenco di cosa ricostruire.
04 Gruppi. Distribution list, gruppi di sicurezza mail-enabled, gruppi Microsoft 365 e
dinamici, con membri e owner.
05 Gap di licenza. SKU assegnati per utente, chi ha usageLocation valorizzata e —
soprattutto — chi riceve le licenze da un gruppo invece che direttamente: sul tenant di
destinazione quel gruppo va ricreato prima, altrimenti quelle licenze non si riassegnano da sole.
06 SharePoint e OneDrive. Numero di siti, volume occupato, i più grandi.
07 Teams. Team, owner e canali distinti fra standard, privati e condivisi. I canali
condivisi sono quelli che possono ospitare membri di un’altra organizzazione, e in una migrazione
fra tenant meritano un censimento a parte.
08 Mail flow. Connettori, domini accettati, domini remoti e regole di trasporto: la
configurazione che, se dimenticata, si manifesta come posta che smette di arrivare il giorno del
cutover.
09 Oggetti Entra. Utenti cloud-only contro sincronizzati da on-premises, guest, e i gruppi
di sicurezza non abilitati alla posta che Exchange non vede.
10 Cruscotto. I numeri messi insieme, con i volumi normalizzati.
Le tre trappole che abbiamo disinnescato
Questa è la parte che vale più del codice, perché sono difetti che non producono un errore: lo script gira pulito, esporta il CSV, e il numero è sbagliato.
I limiti impliciti che troncano. ResultSize vale 1000 su tutti i Get-* di Exchange Online,
e Get-SPOSite -Limit vale 200. Oltre quelle soglie l’elenco si ferma senza dire niente: su un
tenant con novecento siti se ne dimensionano duecento, e il totale è sbagliato di quattro quinti.
C’è un default gemello ancora più insidioso: -IncludePersonalSite vale $false, quindi un
report sui volumi non contiene nemmeno un OneDrive — cioè spesso metà di quello che devi
spostare.
Le proprietà che non arrivano se non le chiedi. Get-MgUser restituisce undici proprietà, e
usageLocation non è fra queste. Senza -Property esplicito il campo esce vuoto per tutti e lo
script conclude che nessuno l’ha impostata: è il falso positivo perfetto, perché è esattamente il
controllo che quello script deve fare. Sulla stessa riga c’è onPremisesSyncEnabled, che è
tri-stato: vale $true per gli utenti sincronizzati e $null — non $false — per i
cloud-only. Un filtro -eq $false non trova nessuno, e un tenant ibrido risulta interamente
cloud. Da lì in poi il piano di mappatura è sbagliato in radice.
Il permesso che sembra una delega e non lo è. NT AUTHORITY\SELF ha FullAccess assegnato
direttamente, non ereditato. Il filtro che si trova in giro, Where-Object { -not $_.IsInherited },
quindi non lo esclude: il report esce con una delega fantasma su ogni cassetta del tenant, e
l’elenco delle deleghe da ricostruire risulta gonfiato del doppio. Vanno esclusi anche i permessi
con Deny, che sovrascrivono gli Allow apparenti ereditati dai gruppi di amministrazione.
Due tenant significa due esecuzioni
Connect-MgGraph sostituisce la sessione del processo, ed Exchange Online e SharePoint tengono
un contesto per sessione. Il toolkit va quindi eseguito su un tenant per volta, in processi
PowerShell distinti, e i CSV si confrontano dopo.
Non è pignoleria: uno script che provasse a tenere origine e destinazione nello stesso processo riporterebbe due volte lo stesso tenant, e — di nuovo — senza dare errore.
Cosa il toolkit non fa, dichiarato
Non genera i record DNS da creare sul tenant di destinazione. I CNAME DKIM del target dipendono dal prefisso del suo dominio iniziale e dalla partizione assegnata: valori che esistono solo dopo aver aggiunto e verificato il dominio di là. Un runbook DNS costruito dal tenant di origine sarebbe sbagliato, e non se ne accorgerebbe nessuno fino al cutover.
E non verifica Organization Relationship, MailboxMoveCapability o la raggiungibilità
dell’endpoint di migrazione. In un pre-flight quegli oggetti non esistono ancora: un semaforo rosso
non significherebbe nulla.
Un toolkit che promettesse quelle due cose sarebbe più bello da leggere in una scheda prodotto. Ma darebbe risposte inventate su un progetto in cui una risposta sbagliata si paga con un cutover rifatto.
Da dove partire
L’ordine che consigliamo è 09 → 05 → 02 → 03 → 04 → 01 → 08 → 06 → 07 → 10: si
comincia dalle identità perché la distinzione fra cloud-only e sincronizzati decide il tipo di
progetto, e si chiude con il cruscotto passandogli il CSV dei volumi SharePoint.
Se dal pre-flight esce un quadro più complicato del previsto — un tenant ibrido, canali condivisi con organizzazioni esterne, licenze assegnate via gruppo — è il momento giusto per parlarne con noi: sono esattamente le condizioni in cui una migrazione va disegnata prima e non durante.