Prepare-Moverequest.ps1

Wenn Sie nicht mit Prepare-MoveRequest arbeiten wollen, dann ist auf Org2Org MoveRequest noch der Weg über eine CSV-Datei beschrieben.

Mit dem Wechsel von Exchange 2007  nach Exchange 2010 hat Microsoft eine aus meiner Sicht sinnvolle Änderung bezüglich einer Cross-Org-Migration durchgeführt. Das Exchange 2007 Commandlet "Move-Mailbox" hat nicht nur die Postfachinhalte von einer Organisation in die andere Organisation übertragen, sondern auch noch das Zielpostfach anhand ProxyAdresses, SIDHistory, ObjectSID LegacyExchangeDN "gesucht" und gematched. Bei Exchange 2010 wird nur noch das Feld "msExchMailboxGUID" zum Matchen genutzt.

Auf der einen Seite bedeutet dies, dass Sie die Zielumgebung nun entsprechend vorbereiten müssen. Andererseits können Sie dann aber auch sicher sein, dass die Übereinstimmung dann auch wirklich zuverlässig und Eindeutig sind. Das war vorher auch etwas von der Reihenfolge der Suche abhängig. für die Vorbereitung hat Microsoft die nun fehlende Logik in einem sehr leistungsfähigen PowerShell-Skript untergebracht. Prepare-MoveRequest.ps1 ist auf jedem Exchange 2010 Server im Verzeichnis "Scripts" enthalten und wird durch Servicepacks auch aktualisiert.

Ich begrüße diesen Wechsel, da Sie nun selbst im Skript die Funktionsweise nachvollziehen und sogar auf die eigenen Bedürfnisse anpassen können. Das ist besser als eine verkapselte EXE oder ein Commandlet, deren genauer Funktion verborgen bleibt.

Was macht Prepare-Moverequest.PS1?

Prepare-Moverequest.ps1 bereitet den Zielforest derart vor, dass es dort Active Directory Benutzer gibt, die in Exchange als "MailUser" erscheinen. Es sind also schon Benutzerobjekte im Active Directory aber in der Exchange-Sichtweise sind es erst einmal Kontakte. Diese Kontakte haben als Zieladresse (TargetAddress) eine SMTP-Adresse, die Mails an diesen Empfänger weiter an das Quellpostfach sendet. Aber Prepare-Moverequest macht kein "Provisioning", d.h. ein "Update-Recipient" o.ä. findet nicht statt. Damit ein MailUser fehlerfrei durchgeht, reicht der Inhalt in mailnickname, ProxyAddresses und TargetAddress. Prepare-MoveRequest kann auch eingesetzt werden, wenn es überhaupt keinen Verzeichnisabgleich gibt, weil es dann entsprechende „MailUser“ anlegt. Sollte es im Ziel aber bereits Benutzerobjekte oder Mailkontakte geben, dann werden diese anhand verschiedener Kriterien sogar gematched.

Einschränkungen

Auch wenn Prepare-MoveRequest ein sehr leistungsfähiges Skript ist, so gibt es ein paar Einschränkungen, die nicht verschwiegen werden sollen:

  • DauerSync
    Das Skript ist kein Ersatz oder Lösung für einen "Verzeichnisabgleich" zwischen zwei Organisationen sondern dient nur der Vorbereitung einer Migration. Es löscht z.B. keine Objekte im Ziel, so dass die Verzeichnisse auseinanderlaufen
  • Nur "Postfächer"
    Mit dem Fokus auf eine Migration ist verständlich, dass Prepare-MoveRequest auch nur Postfächer in der Quelle sucht und auf Objekte im Ziel abbilden will. Verteiler und Kontakte sind außen vor. Das können Sie aber z.B. mit dem ADMT -Active Directory Migration Toolkit bewerkstelligen
  • Automapping
    Leider übernimmt Prepare-Moverequest keine Einträge des Automappings. Diese Funktion ist gerade bei einer Shared Mailbox interessant, um diese automatisiert bei Benutzern einzubinden. Auch hier ist "Nacharbeit" erforderlich.

Neuanlage

Der einfachste Startpunkt ist die Neuanlage von Objekten über Prepare-Moverequest.

.\prepare-moverequest.ps1 `
   -identity test@msxfaq.quelle `
   -remoteforestdomaincontroller dcquelle.msxfaq.quelle`
   -remoteforestcredential $remote `
   -LocalForestDomainController dcziel.msxfaq.ziel `
   -localforestcredential $local `
   -TargetMailUserOU "OU=Import,DC=msxfaq,DC=ziel" `
   -mailboxdeliverydomain msxfaq.quelle `
   -Disable
   -verbose

Auf der Konsole wird dann in etwas ausgegeben. Sie können schön sehen, was das Skript so tut.

VERBOSE: Setting displayName to Test TestSN
VERBOSE: Setting Mail to User1@msxfaq.quelle
VERBOSE: Setting mailNickName to User1
VERBOSE: Setting msExchMailboxGuid to fca24a96-5a54-4a2f-b9a7-f1aec452abe1
VERBOSE: Setting msExchUserCulture to de-DE
VERBOSE: Setting proxyAddresses to SMTP:User1@msxfaq.quelle X400:C=DE;A= ;P=Erste Organisati;O=Exchange;S=TestSN;G=Test; FAX:User1@FAX
VERBOSE: Setting UserAccountControl to 514
VERBOSE: Setting UserPrincipalName to User1@msxfaq.quelle
VERBOSE: Setting samaccountname to User1
VERBOSE: Setting msExchVersion to 44220983382016
VERBOSE: Setting msExchRecipientDisplayType to -2147483642
VERBOSE: Setting msExchRecipientTypeDetails to 128
Appending x500:/o=Erste Organisation/ou=Erste administrative Gruppe/cn=Recipients/cn=User1 to proxyAddresses of New Object in Local forest.
VERBOSE: Setting targetAddress to SMTP:User1@msxfaq.quelle
VERBOSE: Setting countryCode to 0
VERBOSE: Setting Department to Abteilung
VERBOSE: Setting facsimileTelephoneNumber to +495251304650
VERBOSE: Setting givenName to Test
VERBOSE: Setting msExchHideFromAddressLists to False
VERBOSE: Setting Sn to TestSN
VERBOSE: Setting telephoneNumber to +495251304600
VERBOSE: Setting Title to Titel
VERBOSE: Setting Description to TestUser
VERBOSE: Setting msExchMDBRulesQuota to 64 
VERBOSE: Setting msExchPoliciesExcluded to {26491cfc-9e50-4857-861b-0cb8df22b5d7}
VERBOSE: Setting textEncodedORAddress to X400:C=DE;A= ;P=Erste Organisati;O=Exchange;S=TestSN;G=Test;
WARNING: Cannot find corresponding object für CN=group1,DC=msxfaq,DC=quelle in current forest. 'member' not Updated.
VERBOSE: Invoke Update-Recipient to Update LegacyExchangeDN.
Appending x500:/o=MailOrg/ou=Exchange Administrative Group (FYDIBOHF23SPDLT)/cn=Recipients/cn=Test to proxy Addresses of Object(CN=Test TestSN,DC=msxfaq,DC=quelle) in Source forest.
Preparation für User1@msxfaq.quelle done.
1 mailbox(s) ready to move.

Sie können also recht genau sehen, was das Skript macht. Über den Parameter "Identity" können Sie einzelne (Test-)Benutzer durchproben, ehe Sie die komplette Liste abarbeiten.

Ich würde das Skript immer mit "-verbose" starten
Zudem würde ich mit "Start-Transcript" auch die Protokollierung der Konsole in eine Datei aktivieren.

Matching und Merging

Wenn Prepare-Moverequest nicht zur Neuanlage von Objekten verwendet wird, sondern bestehenden Objekte verwenden muss, dann "kommen folgende "Match-Regeln" zum Einsatz:

  • ProxyAddresses
    Es wird geschaut, ob es eine Übereinstimmung einer "ProxyAdresses" der Quelle mit dem Ziel gibt. Dazu muss das Zielobjekt natürlich bereits "MailEnabled" sein (z.B. ein Kontakt) oder zumindest das Feld "ProxyAddresses" durch einen anderen Prozess gefüllt worden sein.
  • MasterAccountSid
    Für spezielle Umgebungen mit einem Ressourceforst kann prepare-Moverequest auch das Feld msExchMasterAccountSID nutzen, um das Zielobjekt anhand der SID des Quellobjekts zu finden. Das ist aber ein eher seltener Fall. Prepare-Moverequest kann aber selbst die MasterAccountSID setzen. Siehe "Parameter -LinkedMailbox"

ADMT migriert per Default nicht die Felder "mail", "msExchMailboxGuid" und "proxyAddresses, wenn der Zielforest bereits Exchange installiert ist. Sollte der Zielforest aber noch kein Exchange enthalten, dann werden diese Werte übertragen, was zu korrupten Elementen führt.
937537 You find that several custom attributes are missing when you use ADMT to migrate Users between two forests

Die folgende Tabelle soll aufzeigen, was aus einem Zielobjekt durch Prepare-Moverequest gemacht wird, wenn mit "-UseLocalObjekt" ein Merge angefordert wird.

Feld\Quellobjekt

MailContact

MailUser

User ohne Mail

Aktion

Wird zu MailUser

Wird erweitert

Skip

msExchMailboxGUID

Aus Quelle

Aus Quelle bei „-OverwriteLocalObject“ oder "-UseLocalObject"

Skip

msExchArchiveGUID

Aus Quelle

Aus Quelle bei „-OverwriteLocalObject“ oder "-UseLocalObject"

Skip

msExchArchiveName

Aus Quelle

Aus Quelle bei „-$OverwriteLocalObject“ oder "-UseLocalObject"

Skip

sAMAccountName

Aus Quelle

Nein

Skip

objectSid

In MasterAccountSID,
wenn "/LinkedMailUser“ aktiv

In MasterAccountSID,
wenn "/LinkedMailUser“ aktiv und
User in der Quelle Disabled

Skip

masterAccountSid

Wenn „LinkedMailUser“ gesetzt

Leider nein

Skip

UserAccountControl

514 (Disabled)

Keine Änderung

Skip

UserPrincipalName

Aus Quelle

Keine Änderung

Skip

LegacyExchangeDN

Wird neu generiert
in Quelle als X500

Wird erweitert

Skip

Mail

Nicht geändert !

Aus Quelle bei „-OverwriteLocalObject“
Nicht geändert !

Skip

ProxyAddresses

Nicht geändert !

Aus Quelle bei „-OverwriteLocalObject“
Nicht geändert !

Skip

Ist das Ziel angelegt oder gefunden worden, dann überträgt Prepare-MoveRequest jede Menge Felder vom Quellobjekt in das Zielobjekt. Die genaue Liste ist abhängig davon, ob das Ziel neu angelegt oder ein bestehendes Objekt "recycled" wurde.

Parameter "UseLocalObject"

Normalerweise legt Prepare-MoveRequest neue Mailenabled User im Ziel an. Wenn allerdings schon Objekte mit einer entsprechenden Target-Address vorhanden sind, dann stoppt das Skript mit einem Fehler, dass es den Benutzer schon vorhanden ist. Mit der Option "Use-LocalObject" wird das Skript angewiesen, den bestehenden Benutzer zu nutzen oder zu aktualisieren.

Findet Prepare-Moverequest keinen passenden Benutzer, wird der Eintrag mit einem Error übersprungen!

Prepare-Moverequest kann keine "Konsolidierung" über Domänen hinweg durchführen. Wenn der Kontakt also in einer anderen Domäne vorhanden ist, dann wird die Zusammenführung nicht funktionieren.

Zudem werden nur drei Properties kopiert.

  • msExchMailboxGUID
  • msExchArchiveGUID
  • msExchArchiveName

Das kann man auch auf der Bildschirmausgabe ("-verbose") sehen':

VERBOSE: Local ad account with dupplicate proxy addresses found: CN=Test,OU=Import,DC=msxfaq,DC=test2
VERBOSE: Merging Mailbox properties to local MailUser
VERBOSE: Setting msExchMailboxGUID to fca24a96-5a54-4a2f-b9a7-f1aec452abe1
Preparation für test@msxfaq.test2 done. Local recipient info Merged.

Die Quelle hat kein Archiv, so dass hier nur ein Property übrig bleibt. Diese drei Properties sind für die spätere Migration relevant. Alle anderen Felder sollten durch den Prozess bereits kopiert worden sein, der vorab die MailKontakte oder MailUser angelegt hat. In Verbindung mit ADMT kommt diesem Switch eine besondere Funktion zu.

When a User is created via ADMT, the PrepareMoveRequest script doesn't work since there are no proxyAddresses für the script to match the source forest User with the target forest User. The recommended approach is to copy at least 1 proxy address using ADMT.
However, if you use the -UseLocalObject parameter, the script will only copy the 3 mandatory parameters (msExchMailboxGUID, msExchArchiveGUID, msExchArchiveName).
Quelle: Exchange 2010 Cross-Forest Mailbox Moves (http://blogs.technet.com/b/exchange/archive/2010/08/10/3410619.aspx)

Parameter "-OverwriteLocalObject"

Dieser Parameter ist erst seit Exchange 2010 SP1 verfügbar und entspannt ein Problem der früheren Versionen in Verbindung mit ADMT. Wurde Prepare-Moverequest mit der Option "-UserExistingObjekt" aufgerufen, dann wurden nur die drei elementaren Felder übertragen, da davon ausgegangen wurde, dass alle anderen Felder durch einen anderen Prozess bereits beschrieben wurden. Das ist der Fall, wenn z.B. ADMT vorab eingesetzt wurde.

Mit "-OverwriteLocalObject" wird prepare-Moverequest.ps1 explizit angewiesen, bei dem bestehenden Objekte auch die anderen Felder (z.B. Ort, Straße etc.) aus der Quelle auf das Zielobjekt zu schreiben. Es kann damit nicht mit "-UseLocalObject" parallel verwendet werden.

Parameter "-MailDeliveryDomain"

Wenn Prepare-Moverequest die Mailenabled User anlegt, muss er eine "TargetAddress" mit angeben. Damit er die "richtige Adresse" verwendet, müssen Sie über den Parameter "MailDeliveryDomain" die SMTP-Domäne der Quelle angeben, in der das Postfach noch vorhanden ist. Prepare-Moverequest sucht sich dann eine der ProxyAddresses, um daraus die TargetAddress zu bilden.

Bitte fassen Sie den Parameter mit "-Zeichen ein, damit es wirklich nur der String ist.
Im Code ist ein "Compare" des Domainanteils mit dieser Variable und der Wert sollte keine Leerzeichen oder CRLF am Anfang oder Ende haben.

Parameter "-LinkedMailbox"

Achtung: Linked Mailbox
Warum auch immer setzt das Skript den Wert für "msExchMasterAccoundSID" nur, wenn das Quellkonto deaktiviert ist.

Leider kopiert Prepare-Moverequest nur dann mit der Option „LinkedMailUser“ die msExchmasterAccountSID, wenn es einen MailContact konvertiert, einen MailUser anlegt oder das Quellkonto deaktiviert ist. Der temporäre Betrieb als Ressourceforest mit TargetAddress ist gerade während Migrationen eine interessante Option. Das Anmeldekonto verbleibt noch in der Quelle, wenn zuerst die Postfächer verschiedener Firmen in eine Organisation konsolidiert werden.

Wurden aber die Benutzer schon vorher per ADMT schon mal im Ziel angelegt, dann matched prepare-Moverequest das Objekt aber kopiert in diesem Fall den msExchMasterAccountSID nur, wenn die Quelle deaktiviert ist. Das passt natürlich nur, wenn das Postfach schon in der Quelle eine LinkedMailbox war.

Aber da Prepare-Moverequest ein PowerShell-Skript ist, können Sie diese Verhalten ja leicht so anpassen, dass das Feld auch kopiert wird, wenn des Zielkonto deaktiviert ist. Relevant ist bei der Version aus Exchange 2010 SP1 die Zeile 870, die einfach derart abgeändert wird, dass der Status des Zielkontos überprüft wird. Wenn das Zielkonto deaktiviert ist, dann wird die msExchMasterAccountSID kopiert

Parameter "-DisableEmailAddressPolicy"

Normalerweise würde der Exchange Server im Ziel das Objekt direkt den Empfängerrichtlinien unterwerfen. Wenn das nicht gewollt ist, kann es auch deaktiviert werden. Den Erfolg können Sie im Log sehen:

VERBOSE: Disable EmailAddressPolicy.

Auch wenn ein DisableEmailAddressPolicy als schnelle Lösung funktioniert, so ist langfristig die Verwaltung von Empfängern ohne Richtlinien ein aufwändiges Geschäft (Ausnahme: Provisioningtools). Daher würde ich eher eine passende Empfängerrichtlinie anlegen, die zuerst die neu migrierten Objekte korrekt konfiguriert und nach der Migration auch neue Postfächer gleich korrekt einrichtet

Übergabe per Pipeline oder "-Identity"

Wenn nur ein Postfach "vorbereitet" werden soll, dann gebe ich die Mailbox über den Parameter "Identity" an. Sollen mehrere Postfächer umgestellt werden, dann bietet es sich an, die Adressen der Mailboxen über die Pipeline zu übergeben. Alternative kann das Skript natürlich auch über eine For-Schleife aufgerufen werden und als "-identity" die Adresse übergeben werden.

Bei der Übergabe aus der Pipeline ist darauf zu achten, dass nur die Mailadresse (ohne Leerzeichen) übergeben wird. Gerade wenn man mit "Get-Content" eine Textdatei einliest, kann dies passieren und Prepare-Moverequest findet das Postfach dann nicht. Es macht keinen "TRIM"

DirSync mit Prepare-Moverequest.ps1

Ehe Sie nun frohlocken und Prepare-Moverequest als kostenfreie Alternative zu MISS, FIM und und anderen Tools ansehen, sei hier eine Warnung ausgesprochen.

Prepare-Moverequest kann keinen DirSync ersetzen!

Ein Verzeichnisabgleich (Siehe auch Verzeichnisabgleich) beinhaltet weitere Funktionen. Prepare-Moverequest.ps1 hat folgende Einschränkungen:

  • Keine Verteiler, Kontakte und Public Folder
    Diese Objekte werden durch das Skript einfach ignoriert. Das ist natürlich für eine produktive Migration nicht tolerierbar. Gerade Verteiler (Gruppen) können zwar per ADMT übertragen werden und Prepare-MoveRequest kann sogar die Member aktualisieren, aber weder ADMT noch Prepare-MoveRequest kopieren die Exchange Properties.
  • Änderungen im Ziel werden überschrieben
    Prepare-MoveRequest überschreibt immer wieder die Zieldaten mit den Quelldaten. Nur wenn das Zielobjekt schon ein Postfach geworden ist, wird dies blockiert.
  • keine Löschaktionen umsetzen.
    Wird ein Objekt in der Quelle gelöscht, dann wird das Ziel nicht entfernt.
  • Keine Kennwort oder SIDHistory
    Hierzu sind ADMT und andere Skripte erforderlich.

Wer also nicht in einer kurzen Zeit die Migration durchführen kann, sollte sich Gedanken über einen echten Verzeichnisabgleich machen.

Automapping

Bei den Einschränkungen weiter oben habe ich schon beschrieben dass Prepare-Moverequest keine "Automapping"-Einträge kopiert. Beim Automapping wird an dem AD-Objekte der SharedMailbox im Feld "msExchDelegateListLink" hinterlegt, welche andere Postfächer "berechtigt" sind. Nach dem Umzug der Postfächer in das Ziel ist das Feld aber leer aber die Berechtigungen sind schon noch da. Damit haben wir nun zwei Optionen:

  1. Automapping anhand der Rechte neu aufbauen
    Mittels "Get-MailboxPermission" kann ich ermitteln, welche Postfächer welche berechtigten Benutzer haben und damit das Automapping nachführen. Das ist allerdings nicht ganz sicher, da dann alle berechtigten Benutzer ein Automapping bekommen.
  2. Automapping kopieren
    Der zweite und bessere Weg ist die Übernahme der Automapping-Einträge auf der Quelle. Dies kann durch einen Export aus der Quelle und einen passenden Import im Ziel erfolgen. Natürlich sind die Strings mit den DistinguishedNames angepasst werden.

Für den Export und späteren Import von Automapping-Einträgen habe ich ein eigenes Skript gebaut:

Prepare-Moverequest mit Office 365

Bei der Migration mit Office 365 kommt eine leicht abgewandelte Version zum Einsatz. Das mit Office 365 auch ein "DirSync" enthalten ist (Siehe DirSync) ist hier ein Modul für den genutzten FIM erforderlich und eine angepasste Version des Skripts.

Prepare für Online Mailbox Move
http://www.microsoft.com/en-us/download/details.aspx?id=17741

Ich gehe auf dieser Seite nicht weiter auf diese besondere Version ein.

Weitere Links