AzureAD/EXOAD

Wenn Exchange OnPremises, ADSync, AzureAD und Exchange Online zusammenarbeiten, dann kann es zu der ein oder anderen Unstimmigkeit kommen. Diese Seite beschreibt ein Troubleshooting, wenn alte Mail-Objekte in Exchange Online vorhanden sind und Mailadressen von aktuellen Objekten damit blockieren.

Viele Verzeichnisdienste

Auf der Seite Azure AD - Ein Verzeichnisdienst, oder zwei oder mehr habe ich schon die Vorarbeiten zum Verständnis der Verzeichnisdienste gelegt. Exchange Online nutzt mehrere eigene "Exchange Ressourcen-Forests" und auch das AzureAD ist nicht ein großes weltweites AD. Mit ADSync erfolgt der Abgleich mit dem lokalen AD und in dieser Topologie kann es durchaus zu Replikationskonflikten kommen. Oft fällt es erst dann auf, wenn Mails nicht ankommen aber laut Messagetracking dennoch zugestellt werden oder Auswertungen auf Unstimmigkeiten stoßen:

Es kann hier durchaus sein, dass eine Identität, die jeweils ein AzureAD-Objekt als auch ein Exchange Online-Objekt hat, nicht synchron sind. Manchmal sehen Sie auch in einer Fehlermeldung diese Doppelstrategie, z.B. bei Set-MailUser:

PS C:\>Set-MailUser user1@uclabor.de

Write-ErrorMessage : Microsoft.Exchange.Configuration.DualWrite.LocStrings.UnableToWriteToAadException
An Azure Active Direcory call was made to keep object in sync between Azure Active Directory and Exchange Online. However, it failed. 
Detailed Error Message: Unable to update the specified properties for on-premises mastered Directory 
   sync objects or objects currently untergoing migration. Dualwrite (Graph) Requestid.....
   The issue may be transient and please retry a couple of minutes later. If issue persists, please see exception members for more information

Hier sehen Sie, dass Set-MailUser in der Exchange Online Powershell V2 nicht nur in das ExchangeOnlineAD sondern auch AzureAD schreiben will. Das AzureAD verhindert aber einen Schreibzugriff für Felder, die durch ADSync verwaltet werden. In meinem Fall geht es aber darum, dass ein Objekt in Exchange Online eine Mailadresse belegt, die ein anderes Objekten haben sollten. Doch gehen wir schrittweise vor:

Info-Adresse

Bei einem Kunden gab es historisch eine E-Mailadresse in der Form "info@<firmendomain>", welche damals mit Exchange OnPremises auf einen öffentlichen Ordner verwiesen hat. Eine ADSync-Replikation hat dann auch ein entsprechendes Objekt in Exchange Online angelegt:

PS C:\> Get-Recipient info@uclabor.de  | fl name,reci*

Name           : Anfragen
RecipientType        : PublicFolder
RecipientTypeDetails : PublicFolder

Interessant wurde die Frage aber nun, wohin Mails an diesen Ordner gegangen sind, denn in der Cloud gab es keine öffentlichen Ordner aber laut Messagetracking wurden mails an eine SharedMailbox zugestellt. Also habe ich im Azure AD nach der Mailadresse gesucht und wurde fündig.

PS C:\> (Get-AzureADUser -Filter "ProxyAddresses eq 'smtp:info@uclabor.de'") | fl displayname,mail,objecttype

DisplayName : Anfragen
Mail        : anfragen@uclabor.de
ObjectType  : User


PS C:\> (Get-AzureADUser -Filter "ProxyAddresses eq 'smtp:info@uclabor.de'").proxyaddresses

SMTP:anfragen@uclabor.de
smtp:anfragen@uclabor.onmicrosoft.com
X500:/o=UCLabor/ou=Exchange Administrative Group (FYDIBOHF23SPDLT)/cn=Recipients/cn=796ccf4a57704978945705712171d20b-Anf
x500:/o=ExchangeLabs/ou=Exchange Administrative Group (FYDIBOHF23SPDLT)/cn=Recipients/cn=9ee31e38bbb145dc977d7abbc4920b86-Anfrage
smtp:fax@uclabor.de
smtp:anfragen@uclabor.mail.onmicrosoft.com
smtp:anfragen@uclabor.de
smtp:demail@uclabor.de
smtp:gate@uclabor.de
smtp:globalsign@uclabor.de
smtp:info@uclabor.de

Das hat mich natürlich alarmiert, dass es im Exchange Online Verzeichnis ein "Public Folder"-Objekt mit der Mailadresse "info@uclabor.de" gibt und im AzureAD die gleiche Mailadresse ein komplett anderes Objekt hat. Daher habe ich nun in der Exchange PowerShell mal geschaut, welche Adressen das im AzureAD gefundene Objekt in Exchange Online hat.

PS C:\> Get-Recipient anfragen@uclabor.de | fl primarysmtpaddress,RecipientType*

PrimarySmtpAddress   : anfragen@uclabor.de
RecipientType        : UserMailbox
RecipientTypeDetails : SharedMailbox


PS C:\> (Get-Recipient anfragen@uclabor.de).emailaddresses

SMTP:anfragen@uclabor.de
smtp:fax@uclabor.de
smtp:anfragen@uclabor.mail.onmicrosoft.com
smtp:anfragen@uclabor.onmicrosoft.com
X500:/o=UCLabor/ou=Exchange Administrative Group (FYDIBOHF23SPDLT)/cn=Recipients/cn=796ccf4a57704978945705712171d20b-Anf

Es ist offensichtlich, dass diese Objekt in Exchange Online nur eine Teilmenge der ProxyAddresses hat, die das Azure AD hat. Da ich Exchange Hybrid nutze, habe ich nun noch mal im lokalen Exchange nach der SharedMailbox gesucht. Gefunden habe ich die erwartete "RemoteMailbox" vom Typ "RemoteSharedMailbox mit allen Mailadressen.

[PS] C:\> Get-Recipient info@uclabor.de | fl re*

ResourceType         :
RecipientType        : MailUser
RecipientTypeDetails : RemoteSharedMailbox
RetentionPolicy      :


[PS] C:\Windows\system32>( Get-Recipient info@uclabor.de).emailaddresses | ft Proxyaddressstring

ProxyAddressString
------------------
smtp:info@uclabor.de
smtp:anfragen@uclabor.de
smtp:anfragen@uclabor.mail.onmicrosoft.com
smtp:fax@uclabor.de
X500:/CN=Mail Public Folder/CN=Version_1_0/CN=d5459543-dfb4-412e-98f7-449b7bf7dfb5/CN=000000001A447390AA6611CD9BC800...
x500:/o=ExchangeLabs/ou=Exchange Administrative Group (FYDIBOHF23SPDLT)/cn=Recipients/cn=9ee31e38bbb145dc977d7abbc49...
X400:C=DE;A= ;P=UCLabor;O=Hoevelhof;S=anfragen;

Das lokale AD-Objekt hat sogar die "info"-Adresse, die sogar im AzureAD vorhanden ist aber nicht am zugeordneten Objekt in Exchange Online steht. Dort ist die Adresse von einem "PublicFolder"-Objekt belegt, welches scheinbar vor langer Zeit einmal per ADSync repliziert und nicht weggeräumt wurde. Ich kann mir das sogar erklären, denn ADSync kann nur Objekte löschen, wenn es den Löschbefehl in der Quelle sieht. Wenn Sie die ADSync-Konfiguration aber ändern und z.B. die OU mit den MailPublicFolder-Objekten aus der Replikation entfernen oder die Checkbox in der ADSync-Konfiguration für "Öffentliche Ordner" deaktivieren, dann wird die Synchronisationsregel entfernt. Das Objekt bleibt dann aber zurück, da auch die "Delete"-Funktion nicht mehr greift. Siehe auch ADSync - Objekte löschen und zurückholen.

Im AzureAD-Connect-Status sind diese Unstimmigkeiten aber nicht zu sehen:

Auch ein Blicks in das lokale ADSync Metaverse zeigt, dass es OnPremises wohl noch eine rudimentäre Public Folder Struktur gibt, von der zwei drei System-Objekte anscheinend sogar noch Mailenabled sein sollten:

Da wurde wohl noch nicht komplett aufgeräumt, was ich in dem Zuge gleich nachgeholt habe. Allerdings ist mein "Info"-Ordner hier auch nicht mehr da. Über die Zeittempel des Exchange Online Objekts konnte ich in etwa nachhalten, wann das Objekt erstmals angelegt und letztmalig geändert wurde.

PS C:\> Get-MailPublicFolder info@uclabor.de | fl name,when*

Name           : Anfragen
WhenChanged    : 19.11.2019 18:58:00
WhenCreated    : 01.03.2016 16:41:15
WhenChangedUTC : 19.11.2019 17:58:00
WhenCreatedUTC : 01.03.2016 15:41:15

Die letzte Änderung dieses Objects in Exchange Online ist schon fast 3 Jahre her und ADSync kennt das Objekt nicht.

Public Folder in EXO

Mein Ziel wäre es, das scheinbar überzählige "PublicFolder"-Objekt in Exchange Online zu entfernen. Ehe ich das aber mache, prüfe ich zur Sicherheit noch einmal, dass es wirklich keine Public Folder gibt.

PS C:\> Get-PublicFolder
Get-PublicFolder: |Microsoft.Exchange.Data.StoreObjects.ObjectNotFoundException|Es konnten keine aktiven Postfächer für öffentliche
Ordner für Organisation uclabor.onmicrosoft.com gefunden werden. Entweder wurden keine Postfächer für öffentliche
Ordner bereitgestellt, oder sie wurden im HoldForMigration-Modus bereitgestellt. Wenn Sie aktuell keine Migration
ausführen, erstellen Sie ein Postfach für öffentliche Ordner.

Zudem habe ich in ExchangeOnline noch mal nah anderen MailPublicFolder-Objekten gesucht und wurde ebenfalls fündig.

PS C:\> (Get-MailPublicFolder).count
38

Da habe ich dann noch mal weiter geschaut aber alle hatten ein leeres Feld "ContentMailbox"

PS C:\> Get-MailPublicFolder  | ft name,contentmailbox

Name                         ContentMailbox
----                         --------------
PubFolder1
PubFolder2
PubFolder3
Anfragen
...

Hier steht mal ein Aufräumen im OnPremises Exchange aber noch mehr in Exchange Online an.

Mailrouting

Ehe ich aber das PublicFolder-Objekt in Exchange Online gelöscht habe, habe ich eine Mail an diese Mailadresse gesendet. Mich hat schon interessiert, welches Objekt nun Exchange Online für das Mailrouting heranzieht. Landen die Mails auf einem Exchange Frontend-Server, der sich dann das finale Zielobjekt anhand des AzureAD oder doch des Exchange Online Forests sucht? Dazu habe ich den MX-Record aus dem Internet über den vorgeschalteten Spamfilter (NoSpamProxy) auf den Office 365 Tenant geroutet und eine Testmail gesendet. Die Mail war zustellbar und landete in der "Shared Mailbox", obwohl dieses Postfach im Exchange Online Verzeichnis nicht die entsprechende Mailadresse hat.

Ich folgere daher daraus, dass die Exchange SMTP-Dienste sich an dem Feld "ProxyAddresses" im AzureAD orientieren und nicht am Feld "EMailAddresses" im Exchange Online Verzeichnis.

Eine Bestätigung dazu habe ich nicht aber es erscheint mir logisch, da auch "outlook.com" die gleiche Infrastruktur nutzt und nicht jeder Tenant auch Exchange Online lizenziert haben muss um Mails zu routen.

Cleanup

Nach all den Analysen und Prüfungen war ich mir sicher dass ich das Exchange Online Objekt vom Typ "MailPublicFolder" entfernen kann. Leider gibt es kein "Remove-MailPublicFolder" aber ein Disable-MailPublicFolder.

Also habe ich experimentiert, indem ich zuerst alle Felder mit einem "*id*" ermittelt habe.

PS C:\> Get-MailPublicFolder info@uclabor.de | fl *id*

EntryId                       :
OnPremisesObjectId            : 753b0a50-919a-4363-bd54-521d7769ab4b
ExternalDirectoryObjectId     :
HiddenFromAddressListsEnabled : False
Identity                      : Anfragen
Id                            : Anfragen
IsValid                       : True
ExchangeObjectId              : db681705-f9cb-41b7-84d2-2aeff3a0e033
OrganizationId                : EURPR04A003.prod.outlook.com/Microsoft Exchange Hosted
                                Organizations/uclabor.onmicrosoft.com - EURPR04A003.prod.outlook.com/ConfigurationUnits/uclabor.onmicrosoft.com/Configuration
Guid                          : db681705-f9cb-41b7-84d2-2aeff3a0e033

Dann habe ich plump versucht, den Ordner über die "OnPremisesObjectId" zu deaktivieren:

PS C:\> Disable-MailPublicFolder -Identity 753b0a50-919a-4363-bd54-521d7769ab4b

Confirm
Are you sure you want to perform this action?
E-Mail-aktivierte öffentliche Ordner –Identität:"753b0a50-919a-4363-bd54-521d7769ab4b" wird deaktiviert.
[Y] Yes  [A] Yes to All  [N] No  [L] No to All  [S] Suspend  [?] Help (default is "Y"): y
WARNING: Fehler beim Auffinden des öffentlichen Ordners "753b0a50-919a-4363-bd54-521d7769ab4b" aufgrund 
     des folgenden Fehlers: Microsoft.Exchange.Data.StoreObjects.ObjectNotFoundException: 
     Es konnten keine aktiven Postfächer für öffentliche Ordner für Organisation uclabor.onmicrosoft.com gefunden werden. 
     Entweder wurden keine Postfächer für öffentliche Ordner bereitgestellt, oder sie wurden im HoldForMigration-Modus bereitgestellt. 
     Wenn Sie aktuell keine Migration ausführen, erstellen Sie ein Postfach für öffentliche Ordner.
   at Microsoft.Exchange.Data.Storage.PublicFolderSessionCache.GetHierarchyMailboxGuidForUser()
   at Microsoft.Exchange.Data.Storage.PublicFolderSessionCache.GetPublicFolderSession(Guid publicFolderMailboxGuid)
   at Microsoft.Exchange.Data.Storage.Management.PublicFolderDataProvider..ctor(IConfigurationSession configurationSession, String action, Guid mailboxGuid)
   at Microsoft.Exchange.Management.MapiTasks.DisableMailPublicFolder.InternalProcessRecord()

Das hat lauf der Meldung nicht funktioniere. Interessanterweise war der Ordner dann aber dennoch weg:

PS C:\> Get-MailPublicFolder info@uclabor.de
Get-MailPublicFolder: Ex6F9304|Microsoft.Exchange.Configuration.Tasks.ManagementObjectNotFoundException|Der Vorgang konnte nicht ausgeführt
werden, weil das Objekt 'info@uclabor.de' nicht auf 'AM6PR04A03DC001.EURPR04A003.prod.outlook.com' gefunden wurde.

Anscheinend löscht der Befehl schon das Verzeichnisobjekt und dann kann nur beim Ordner in der Datenbank das "Mailenabled"-Bit nicht abschalten. Damit sollte aber die Mailadresse "info@uclabor.de" nicht mehr blockiert werden. Allerdings kann ich nun der SharedMailbox diese Adresse nicht direkt zuweisen, da auch die SharedMailbox im Exchange Hybrid Mode weiterhin von ADSync verwaltet wird. Ich habe daher einen ADSync FullSync angestoßen mit:

PS C:\> Start-ADSyncSyncCycle -PolicyType initial

ADSync hat aber natürlich keine "Änderung" in Richtung AzureAD oder Exchange Online erkannt und daher nichts geändert. Also habe ich im lokalen AD die Mailadressen verändert

  1. Entfernen der "info"-Adresse
  2. ADSync Delta-Sync
  3. Kontrolle
    Im AzureAD war die Mailadresse weg
    Interessanterweise war in Exchange Online die Adresse weg aber alle anderen fehlenden Adressen waren nun da
  4. Addieren der "info"-Adresse
  5. ADSync Delta-Sync
  6. Kontrolle
    Nun erscheint auch die "Info"-Adresse und die Objekte sind in Sync

Allein das Entfernen oder Ändern der ProxyAddresses scheint einen Provisioning-Lauf zu Exchange Online anzustoßen. Vermutlich hätte ich die "Info"-Adresse gar nicht erst entfernen und neu addieren müssen. Das Addieren einer weiteren temporären Adresse dürfte den gleichen Effekt haben.

Healthcheck AzureAD/EXOAD-Vergleich

Wenn es solche Inkonsistenzen geben kann, dann sollte man doch wohl auch ein Skript schreiben, welches solche Dinge gegenseitig prüft. In Bezug auf die Mailadressen sollte das dann doch recht einfach sein. Ich muss nur aus beiden Verzeichnissen eine Liste der Mailadressen und zugehörigen Objekten erstellen, wobei natürlich irgendwie ein "Match" der Objekte möglich sein muss. Während ich aber in Exchange mit "Get-Recipient" quasi alle Objekte erhalten, ist das im AzureAD nicht so einfach, da man explizit den Typ (User, Group, Contact) etc. angeben muss. Als "Matchcode" bietet sich das Feld AzureAD:ObjectId und EXOAD:ExternalDirectoryObjectId an. Folgende Fälle kann es aber geben.

Ein AzureAD Objekte hat immer eine ObjectID. Ein EXOAD-Objekt hat auch immer eine ID und eine GUID aber eben nicht immer eine ExternalDirectoryObjectId

EXOAD:ExternalDirectoryObjectId

AzureAD:ObjectId

Beschreibung

Match

Match

Wenn ich auf beiden Seiten ein Objekt habe, bei denen der Inhalt von "ExternalDirectoryObjectId" auch im AzureAD matched, dann ist es das gleiche Objekte und sollte auch ansonsten gleich sein

Gesetzt

Leer ??

Ich hab tatsächlich Objekte im EXOAD gefunden, bei denen das Feld gesetzt ist und es kein entsprechendes Objekt im AzureAD gibt

Leer

Gesetzt

Natürlich gibt es Objekte im AzureAD, die in Exchange nicht vorhanden sind, z.B. ein Benutzer ohne Exchange Lizenz

Leer

nicht vorhanden

Es gibt Objekte im EXOAD, für die es keinen Verweis auf ein AzureAD-Objekt gibt. Bei mir waren das "PublicFolder" und die DiscoverySearch Mailbox

Get-Recipient -Filter {ExternalDirectoryObjectId -eq $null} | ft identity,reci*

Diese Objekte kann ich im AzureAD so wohl nicht finden

Um einen Vergleich einfach zu machen, nutze ich eine PowerShell, in der ich sowohl das Modul der "Exchange Online PowerShell" als auch "AzureAD" importiere und mich dann ausgehend von "Get-Recipient" weiter durcharbeite. Nach meinem Verständnis sollte es zu jedem Objekt im Exchange Online AD auch ein AzureAD-Objekt geben.

Write-Host "Verbindung mit Exchange Online PowerShell"
Import-Module ExchangeOnlineManagement
Connect-ExchangeOnline

Write-Host "Verbindung mit AzureAD"
Import-Module AzureAD -UseWindowsPowerShell
Connect-AzureAD

Write-Host "Objekte mit Mailadresse einsammeln"

$exorecipients = Get-Recipient -resultsize unlimited
$azureadobjects = Get-AzureADContact
Get-AzureADGroup
Get-AzureADUser
...

Der Vergleich verschiedener Verzeichnisse auf Übereinstimmung verfolgt mit immer wieder, z.B. Compare-GAL.

Aktuell ist das Skript noch nicht "öffentlich"

Einschätzung

Es war wohl eher ein glücklicher Umstand, dass ich für diesen Case über das Messagetracking an eine Adresse mittels Exchange Online PowerShell und Get-Recipient die Zustellung in der Cloud überprüft habe und zu meiner Überraschung einen "MailPublicFolder" gefunden haben. So habe ich gelernt, dass Exchange Online und Azure AD unterschiedliche Verzeichnisdienste nutzen, das SMTP-Routing sich auf die AzureAD-Information stützt und überzählige Objekte im EXOAD unbemerkt verhindern, dass Mailadressen an die eigentlichen Objekte eingetragen werden.

In diesem Fall konnte ich das Problem selbst lösen aber wenn dies nicht möglich ist, dann bleibt nur ein Support Ticket im Microsoft Tenant, dass das mal ein Consultant auf den Fehler schaut. Als Administrator können Sie meines Wissens z.B. keinen "FullSync" oder "Reset" des Azure AD Provisioning Service starten, um solche Inkonsistenzen zu bereinigen. Es ist doch immer wieder schön, dass auch Microsoft mit Unstimmigkeiten im Provisioning und Dirsync zu kämpfen hat. Nur die Quelle des Fehlers habe ich nicht mehr ermitteln können.

Weitere Links