ActiveSync Leichen

Eher zufällig habe ich mal wieder ein "Get-MobileDevice" auf meinem alten On-Premises Server gemacht und war erstaunt, dass meinem Postfach noch Mobilgeräte zugeordnet waren. Und das wo mein Postfach doch schon lange in Exchange Online ist. Da musste ich dann doch noch mal genauer nachschauen.

Dieses Fehlverhalten ist Microsoft bekannt und in einer zukünftigen Version des MRS (Mailbox Replication Service) korrigiert werden. Bis dahin können Sie weiter mein Skript nutzen.

Get-MobileDevice

Dieses Commandlet löst das mittlerweile abgekündigte "Get-ActiveSyncDevice" ab und generiert eine Liste der mobilen Geräte, die ihrem Exchange Server bekannt sind. Dabei handelt es sich nicht mehr nur um die reinen "ActiveSync"-Partnerschaften. Es gibt auch andere Partnerschaften, z.B.: auf Basis von REST oder die "Outlook for Android" oder "Outlook for IOS"-Apps. Die Funktion ist sowohl für Exchange On-Premises als auch Exchange Online verfügbar.

Über den Parameter "-mailbox" kann ich die Ausgabe auch auf genau einen Benutzer beschränken. Da meine Mailbox aber schon in Exchange Online ist, findet das Commandlet bei mir natürlich nichts mehr:

Aber ich kann natürlich auch "nachträglich" filtern.

[PS] C:\>Get-MobileDevice | ? {$_.UserDisplayName -eq "msxfaq.de/Abteilung/Technik/Carius, Frank"} | ft name

Name
----
WindowsMail§74E4E6B4B0A54D5868EE273DA9E8A371
WP8§CB7411FB16A806AA97B899EE8B7AF440
Outlook§6A04BD027438964D
TestActiveSyncConnectivity§1017200971
Outlook§A2FC79D2D57744CF
Android§android1441184316434
WP8§7D8C810231A79DBCED48F227BB330390
Android§android1415442986709
iPhone§4KGQP16GIH3JVB8GP5BN3ILNT0
WP8§9C2C7744CF106A1354A32122237FA609

Das ist deutlicher Hinweis, dass das Commandlet nicht auf eine Information im Postfach zugreift, sondern die Daten aus dem Active Directory abruft. Das habe ich auf der Seite EAS AD-Objekte beschrieben.

Der Blick ins AD

Ich habe daher mit ADSIEDIT einfach meinen AD-Benutzer im lokalen Active Directory analysiert und dort die alten Einträge gefunden.

Diese Daten werden nicht durch ADSync in die Cloud repliziert aber wurden auch nicht durch die Migration in die Cloud aktualisiert oder entfernt.

Es sind also Altlasten, die weder vom Administrator durch Exchange Commandlets noch durch den Exchange Server selbst bereinigt werden

Cleanup mit Hindernissen

Die Aufräumaktion muss ich also manuell durchführen. Gesucht werden einfach alle Partnerschaften, zu denen es kein Postfach gibt und löscht diese:

Das Skript funktioniert nur, wenn die Benutzer nicht in den OUs verschoben wurden, denn das Property "UserDisplayName" am ActiveSync-Device wird durch den Move des Users nicht aktualisiert und der Benutzer ein Postfach ist

# verienfachte Version

foreach ($device in (Get-MobileDevice)) {
   if (get-mailbox -identity $device.userdisplayname -erroraction silentlycontinue) {
      write-host "Valid Partnership found for user $($device.userdisplayname)"
   }
   else {
      write-host "Orphaned Partnership found for user $($device.userdisplayname)"
      Remove-MobileDevice -identity $device.deviceid -confirm:$false -verbose
   }
}

Leider habe ich da die Rechnung ohne den Wirt gemacht, denn "Remove-MobileDevice" prüft vorher ab, ob es eine passende Mailbox gibt und bricht in meinem Falle dann ab:

Allein mit Exchange Commandlets kommen wir hier nicht weiter.

Cleanup mit ADSI

In dem Fall bleibt also nur die Entfernung des Objekts per PowerShell und AD-Commandlets. Der Befehl "Get-MobileDevice" macht auch nur eine Suche nach allen Gerätepartnerschaften, die im AD hinterlegt sind aber über Remove-MobileDevice kann der Eintrag nicht entfernt werden.

Allerdings enthält die Rückgabe von "Get-MobileDevice" sehr wohl den DistinguishedName des Objekts. Hier ein Auszug:

[PS] C:\>Get-MobileDevice -ResultSize 1

FriendlyName            : iphone9
DeviceId                : xxxx
DeviceImei              :
DeviceMobileOperator    : OperatorName
UserDisplayName         : msxfaq.net/test/Testuser 
DeviceAccessState       : Allowed
DeviceAccessStateReason : Individual
DeviceAccessControlRule :
Name                    : WindowsMail§ECFFC83A49E4
DistinguishedName       : CN=WindowsMail§ECFFC83A4,CN=ExchangeActiveSyncDevices,CN=Testuser,
                          OU=Test,DC=msxfaq,DC=net
Identity                : msxfaq.net/Test/Testser/ExchangeActiveSyncDevices/WindowsMail§ECFFC83A4
ObjectCategory          : msxfaq.net/Configuration/Schema/ms-Exch-Active-Sync-Device
ObjectClass             : {top, msExchActiveSyncDevice}
Id                      : msxfaq.net/Test/Testuser/ExchangeActiveSyncDevices/WindowsMail§ECFFC83A4

Damit lässt sich dann direkt auf das Benutzerobjekt schließen, indem z.B. der DistinguishedName geparst wird, man muss nur die ersten beiden CN-Einträge entfernen., z.B.:

"CN=partnerid,CN=ExchangeActivesyncDevice,CN=testuser,OU=Test,DC=carius,DC=de".split(",")[2..100] -join ","

Der einfache Ausdruck schlägt fehlt, wenn der CN des Device ein "Komma" enthält oder die OU-Struktur tiefer als 127 Ebenen ist. Das ist aber relativ unwahrscheinlich

Folgender "einfacher Code" löscht die Geräte

foreach ($device in (Get-MobileDevice)) {
   $userdn = $device.distingiushedname.split(",")[2..127] -join ","
   if (get-mailbox -identity $$userdn -erroraction silentlycontinue) {
      Write-Host "Valid Partnership found for user $($device.userdisplayname)"
   }
   else {
      Write-Host "Orphaned Partnership found for user $($device.userdisplayname)"
      Write-Host "Remove $($device.distinguishedname)"
      remove-ADObject `
         -identity $device.distinguishedname `
         -confirm:$false `
         -verbose
   }
}

Damit werden die Elemente dann direkt im Active Directory entfernt:

Genau genommen könnte ich auch per LDAP direkt nach den Objekten suchen und nach über das LDAP-Feld msExchRemoteRecipientType und insbesondere msExchRemoteRecipientType die Benutzer finden, die kein Postfach mehr haben.

In der Situation macht es natürlich auch keinen Sinn die Geräte vorher erst mit einem "Clean-MobileDevice" löschen zu lassen. Das funktioniert nur, wenn das Gerät noch einmal synchronisiert. In meinem Beispiel ist das Gerät aber gar nicht mehr lokal sondern mit der Cloud verbunden.

Container "ExchangeActiveSyncDevice" entfernen

Manchmal reicht es aber nicht nur die obsoleten Partnerschaften im AD zu entfernen. Wenn Sie einen Benutzer z.B. mit ADMT -Active Directory Migration Toolkit, MoveTree oder Move-ADObject verschieben wollen, dann funktioniert dies nicht mit weiteren Containern unter den Benutzern.

Das ist mir bei einem Kunden aufgefallen, der alle Postfächer nach Exchange Online verschoben hat und danach die Domänen konsolidieren wollte. Die Benutzer, die im lokalen Exchange nur noch eine "RemoteMailbox" waren, konnten nicht mit Move-ADObject zwischen Domänen verschoben werden. Hier waren es aber nicht allein die EAS-Partnerschaften sondern der gesamte "ExchangeActiveSyncDevice"-Container unter dem Benutzer

Speziell für Remote-Mailboxen können Sie daher den kompletten Container noch einfach entfernen:

foreach ($remotemailbox in Get-RemoteMailbox) {
   Remove-Adobject `
      -Identity "CN=ExchangeActiveSyncDevices,$($remotmailbox.distinguishedname)" `
      -Recursive
}

Diese einfache Funktion bearbeitet nur die lokale Domain. Wenn Sie mehrere Domains haben, dann müssen Sie mit Remove-ADObject noch einen Server der Zieldomain angeben. Leider sind die Commandlets hier nicht schlau genug.

Dann müssen Sie eine Ehrenrunde über die verschiedenen Domains drehen oder erst die Domains auflisten und dann die DCs dazu ermitteln.

$domains = (Get-ADForest).domains
$dcs = ForEach ($domain in $domains) {
   Get-ADDomainController -DomainName $domain -Discover -Service PrimaryDC | Select -ExpandProperty hostname
}

Oder die nutzen die Exchange PowerShell mit dem Parameter "Domaincontroller"

param ($domain)

$dc = (Get-ADDomainController `
          -DomainName $domain `
          -Discover).hostname[0]
foreach ($remotemailbox in (Get-RemoteMailbox -domaincontroller $dc)) {
   Remove-Adobject `
      -Identity "CN=ExchangeActiveSyncDevices,$($remotmailbox.distinguishedname)" `
      -domaincontroller $dc `
      -Recursive
}

Vielleicht ist es aber auch grade mal gut, solche Massenänderungen nicht gleich auf den kompletten Forest anzuwenden, sondern Domain für Domain durchzugehen.

Hinweis:
Die Exchange Commandlets nutzen RBAC und die LDAP-Aktionen führt der Exchange Server aus. Die Active Directory-PowerShell arbeitet hingegen direkt mit ihrem Benutzer. Sie müssen dann schon die entsprechenden AD-Berechtigungen mitbringen.

Weitere Links