EN

Guide / windows-server

Tre presupposti che uno script Exchange non dichiara

Uno script che gira da anni può dipendere da condizioni che nessuno ha scritto. Si scoprono solo rieseguendolo in un ambiente ricostruito da zero.

Rieseguire in laboratorio gli script che funzionano in produzione è il modo più rapido per scoprire cosa davano per scontato. In produzione quelle condizioni sono vere da anni, quindi nessuno le ha mai scritte: fanno parte dell’ambiente, non del codice. In un ambiente ricostruito da zero non sono vere, e ognuna si presenta con un messaggio d’errore che accusa qualcos’altro.

Uno: la sessione in cui ti trovi

Enable-Mailbox rifiutava un parametro che quel comando ha sempre avuto.

A parameter cannot be found that matches parameter name 'PrimarySmtpAddress'

E Get-Mailbox, sulla stessa console, restituiva GUID al posto dei nomi.

Nessuna delle due cose ha senso in una Exchange Management Shell. Hanno senso in una console dove è stato caricato il modulo ExchangeOnlineManagement, che esporta cmdlet con gli stessi nomi di quelli locali e li oscura. I comandi non stavano fallendo: stavano funzionando benissimo, nel posto sbagliato. Andavano al cloud.

Il controllo che chiude la questione in un secondo:

Get-PSSession | Format-Table Name, ComputerName, ConfigurationName, State -AutoSize

E qui si capisce una scelta che negli script di produzione sembrava soltanto pedante: importano i cmdlet locali con un prefisso.

Import-PSSession $sessione -Prefix 2019

Da quel momento il comando locale è Enable-2019Mailbox, che non collide con niente e non può essere oscurato. Sembra un vezzo finché non se ne vede la necessità, ed è l’unica difesa che non dipende da chi esegue.

Due: il nome dell’oggetto

Lo script delle deleghe assegnava FullAccess correttamente, poi si fermava sul Send As.

ufficio.acquisti wasn't found

Lo stesso identificativo, nello stesso script, funzionava una riga sopra e falliva una riga sotto. La ragione è che i due comandi non risolvono allo stesso modo.

ComandoRisolve per
Add-MailboxPermissionsamAccountName
Add-ADPermissionnome dell’oggetto (CN)

L’oggetto si chiamava Ufficio Acquisti, con lo spazio e le maiuscole; il samAccountName era ufficio.acquisti. In produzione i due valori coincidono sempre, perché chi crea gli account segue una convenzione. La convenzione non è scritta da nessuna parte, non è verificata da nessuno script, e regge il funzionamento di metà delle assegnazioni di permessi.

Il rimedio è allineare il CN al samAccountName. Il punto interessante è un altro: il guasto è parziale. Metà dei permessi viene assegnata, l’altra metà no, e uno script che non si ferma alla prima riga lascia un ambiente in uno stato intermedio che sembra a posto.

Tre: i prerequisiti che nessuno verifica

Uno script si fermava con un messaggio che non aiutava nessuno.

[ERROR] Errore generale
Disconnect-ExchangeOnline : is not recognized

Il modulo ExchangeOnlineManagement non era installato sulla macchina da cui lo si eseguiva. Il rimedio è ovvio una volta letta la seconda riga, ma è la prima riga quella che l’utente vede per prima, e non dice niente.

Nessuno degli script verifica i propri prerequisiti. Un collega che li eseguisse da una postazione nuova incontrerebbe lo stesso messaggio, senza indicazioni su cosa fare. Tre righe all’inizio evitano la telefonata:

if (-not (Get-Module -ListAvailable ExchangeOnlineManagement)) {
    throw "Manca il modulo ExchangeOnlineManagement. Installalo con: Install-Module ExchangeOnlineManagement"
}

Gli altri presupposti, in breve

Emersi tutti allo stesso modo, sbattendoci contro:

Gli oggetti devono essere già sincronizzati nel cloud prima di assegnare le deleghe, perché lo script li cerca anche in Exchange Online. Eseguirlo subito dopo la creazione fallisce, e il fallimento non ha niente a che vedere con i permessi.

I gruppi devono essere Universali di Sicurezza, non di distribuzione. Il controllo sul tipo esiste, ma è dentro una funzione, non nella documentazione.

Un prefisso nel nome è strutturale. Lo script antepone una lettera al nome letto dal file di origine. Chi prepara quel file senza saperlo produce oggetti che non verranno mai trovati.

Un attributo è confrontato letteralmente. Il valore di employeeType viene confrontato con "Interno" senza normalizzazione: una maiuscola diversa instrada nel ramo sbagliato, silenziosamente.

Windows PowerShell 5.1, non 7. Il prefisso e i cmdlet remoti si comportano in modo affidabile solo lì.

Gli script non creano gli account. Presuppongono che il passo a monte sia già avvenuto, e non lo dicono.

Le tre lezioni

Un ambiente ricostruito è un collaudo dei presupposti. Non serve a verificare che gli script funzionino — quello si sa già. Serve a scoprire quante cose non stanno nel codice.

Un errore parziale è peggio di un errore totale. Lo script che assegna metà dei permessi e prosegue lascia dietro di sé uno stato che nessuno controllerà, perché non si è fermato niente.

Il messaggio che l’utente legge per primo dovrebbe essere quello utile. Errore generale seguito dalla causa vera è l’ordine sbagliato. Chi legge si ferma alla prima riga.

Laboratorio costruito con il supporto di Ilie.