Exchange CU und RequireSSL
Diese Seite beschreibt ein Fehlerbild und dessen Lösung, welches anscheinend beim Update von Exchange 2016/2019/SE Servern gerne mal auftritt. Zudem blicken wir etwas in die Eingeweide von Exchange und PowerShell.
Der Fehler: New-PushNotificationsVirtualDirectory
Die denken sich nichts Böses, haben ihren Exchange Server schön in Wartung genommen und starten die Installation des aktuellsten Exchange CU Updates. Wie sie sicher wissen, ist auch ein Exchange CU mittlerweile immer eine Vollinstallation auf einer ISO-Datei mit 5+GB Platzbedarf. Beim einem Updates des Server werden quasi auch alle Installationsschritte komplett durchlaufen, was entsprechend dauert. Es bietet sich natürlich an, den Server vorab einmal durchzustarten und Backup und Monitoring-Dienste, die SNMP, WMI u..a. blockieren könnten, ebenfalls zu pausieren. Wenn Sie dann noch die ganzen Voraussetzungen wie erforderliche .NET Updates und Schema-Updates erledigt haben, kopiert das Setup die Exchange Binaries und konfiguriert unter anderen auch virtuelle Verzeichnisse. Und hier kann sie folgender Fehler unsanft aus den Träumen holen:
New-PushNotificationsVirtualDirectory ` -Role Mailbox -OAuthAuthentication:$RoleIsDatacenter ` -DomainController $RoleDomainController ` -RequireSSL $PushNotificationVDConfig.RequireSSL ` -ExtendedProtectionFlags $PushNotificationVDConfig.ExtendedProtectionFlags ` -ExtendedProtectionSPNList $PushNotificationVDConfig.ExtendedProtectionSPNList ` -ExtendedProtectionTokenChecking $RoleEPTokenCheckingRequireOrNone; } " ausgeführt wurde: "System.Management.Automation.ParameterBindingException: Das Argument kann nicht an den Parameter "RequireSSL" gebunden werden, da es NULL ist.
Natürlich haben wir Google und Co angeworfen und einige aber nicht viele Meldungen zu dem Thema gefunden. Eine Lösung war aber nicht dabei, außer den Server zu entfernen und einen anderen Server neu zu installieren. Das ist natürlich kein Lösungsweg. Einige Meldungen beziehen sich zwar auf New-PushNotificationsVirtualDirectory aber beschreiben eher den Fehler, dass das Verzeichnis schon da ist.
- Exchange 2019 CU 13 Update-Error: $PushNotificationVDConfig.RequireSSL
https://learn.Microsoft.com/en-us/answers/questions/1433526/exchange-2019-cu-13-update-error-pushnotificationv - Exchange 2019 CU14 - Error on Mailbox
Role - CAS -
Get-PushNotificationsVirtualDirectory -
Cannot bind argument to parameter 'RequireSSL'
because it is null.
https://learn.Microsoft.com/en-us/answers/questions/1620906/exchange-2019-cu14-error-on-mailbox-role-cas-get-p - Exchange Server 2013 SP1 Standard:
Installation failing can't progress
http://www.networksteve.com/exchange/topic.php/Exchange_Server_2013_SP1_Standard:_Installation_failing_can't_pr/?TopicId=45122&Posts=5 - "Cannot convert null to type" error and
Exchange 2019 CU14 RecoverServer fails
https://support.Microsoft.com/en-us/topic/-cannot-convert-null-to-type-error-and-exchange-2019-cu14-recoverserver-fails-2f0e1202-8253-4bfc-a9bb-d575ccfa7cef - Exchange 2019 install - Existing Hybrid
and existing Exchange 2013
https://www.reddit.com/r/exchangeserver/comments/1bjiud9/exchange_2019_install_existing_hybrid_and/ - Nach Ex-Migration: Fehler beim Entfernen
des alten Exchange
https://www.mcseboard.de/topic/209568-nach-ex-migration-fehler-beim-entfernen-des-alten-exchange/ - Exchange Upgrade von EX 2010 auf Ex 2016
- Fehler beim installieren von Exchange 2016
Postfachrolle
https://www.frankysweb.de/community/exchange2016/exchange-upgrade-von-ex-2010-auf-ex-2016-fehler-beim-installieren-von-exchange-2016-postfachrolle/ - Exchange 2016:- CU14 failure on Mailbox
role while creating virtual directories
https://www.collaborationpro.com/exchange-2016-cu14-failure-on-mailbox-role-while-creating-virtual-directories/
Es bietet sich immer an, mit dem Exchange HealthChecker erst einmal nach allgemeinen Konfigurationsfehlern Ausschau zu halten und speziell Meldungen zu TLS und Zertifikaten möglichst vorab zu bereinigen. Aber bei dem Fehler half dies auch nicht.
Extended Protection?
Wann immer es auf "SSL" u.a. kommt, dann könnte es ja auch etwas mit Exchange Extended Protection zu tun haben. Damit sichert Microsoft den NTLM-Zugriff auf Exchange durch strengere Vorgaben bei der Anmeldung ab und dazu gehört auch, dass SSL erzwungen wird, damit Extended Protection auch genutzt werden kann. Exchange hat diese Funktion mit Exchange 2019 CU14 automatisch aktiviert und da der Fehler bei einem Update von Exchange 2019 CU12 Nov23SU erfolgt ist, könnten Sie das Update ja auch einmal ohne diese Option starten, z.B. mit
Setup.EXE /Mode:Upgrade /IAcceptExchangeServerLicenseTerms_DiagnosticDataOn /DoNotEnableEP_FEEWS
Allerdings hat das auch nicht geholfen und ich weiß nicht, ob Microsoft genug "Fehler" mit der Option "DiagnosticDataOn" bekommt, um hier ein Problem zu sehen und den Code robuster zu machen.
Analyse
Wir sehen in der Fehlermeldung einen Auszug aus einem PowerShell-Script, indem das Exchange Setup mit dem Befehl "New-PushNotificationsVirtualDirectory" ein Verzeichnis anlegt und parametrisiert. Einer der Parameter ist "RequireSSL", der mit dem Inhalt aus der Variablen "$PushNotificationVDConfig.RequireSSL" gefüllt wird. Dieser Wert scheint aber "NULL" zu sein und damit kommt das Commandlet nicht zurecht. Der Fehler beendet dann das komplette Setup und sie haben einen "halben" Server. Wer nun nach "New-PushNotificationsVirtualDirectory" sucht, wird keine entsprechende Anleitung finden, denn diese Commandlet gehört nicht zur regulären Exchange PowerShell.

Es ist Bestandteil der "Exchange Installation PowerShell". Sie haben richtig gelesen, dass Microsoft für die Installation von Exchange eine eigene PowerShell mit einer besonderen Erweiterung installiert, die dann diese Funktionen bereitstellt und durch lesbare PowerShell-Skripte genutzt werden. Wenn das Setup abbricht, dann ist diese Laufzeitumgebung aber noch vorhanden und insbesondere die ganzen "Install-Skripte" liegen weiter auf dem Server. Sie müssen nur mal nach C:\ExchangeSetupLogs schauen und finden dort nicht nur die Textdatei und MSILogs, sondern auch alle PowerShell-Skripte:

In einer der Dateien muss sich ja der Code verstecken. Mit einem "FINDSTR" oder "Select-String" ist das schnell zu finden.
PS C:\ExchangeSetupLogs> Select-String New-PushNotificationsVirtualDirectory *.ps1 Install-ClientAccessRole-20221110-2119020920797867910.ps1:964: New-PushNotificationsVirtualDirectory ` -Role Mailbox ` -OAuthAuthentication:$RoleIsDatacenter ` -DomainController $RoleDomainController;
Die Datei heißt bei ihnen sicherlich anders, da Sie einen Zeitstempel enthält.
Da die meisten Administratoren das Verzeichnis nicht kennen oder nie aufräumen, ist dies für Consultants für mich natürlich ein Schatz bei der Suche nach früheren Fehlversuchen.
Allerdings habe ich in dem Powershell-Skript nur folgende Zeilen gefunden.
Get-PushNotificationsVirtualDirectory ` -ShowMailboxVirtualDirectories ` -server $RoleFqdnOrName ` -DomainController $RoleDomainController ` | Remove-PushNotificationsVirtualDirectory ` -DomainController $RoleDomainController New-PushNotificationsVirtualDirectory ` -Role Mailbox -OAuthAuthentication:$RoleIsDatacenter ` -DomainController $RoleDomainController;
Also bin ich dann doch wieder auf die Datei "C:\ExchangeSetupLogs\ExchangeSetup.Log", in der mehr Details zum Fehler stehen: (Zur Lesbarkeit umgebrochen)
if ($RoleDoNotEnableEP) {
New-PushNotificationsVirtualDirectory `
-Role Mailbox `
-OAuthAuthentication:$RoleIsDatacenter `
-DomainController $RoleDomainController `
-RequireSSL $PushNotificationVDConfig.RequireSSL `
-ExtendedProtectionFlags $PushNotificationVDConfig.ExtendedProtectionFlags `
-ExtendedProtectionSPNList $PushNotificationVDConfig.ExtendedProtectionSPNList `
-ExtendedProtectionTokenChecking $PushNotificationVDConfig.ExtendedProtectionTokenChecking;
}
else {
New-PushNotificationsVirtualDirectory `
-Role Mailbox `
-OAuthAuthentication:$RoleIsDatacenter `
-DomainController $RoleDomainController `
-RequireSSL $PushNotificationVDConfig.RequireSSL `
-ExtendedProtectionFlags $PushNotificationVDConfig.ExtendedProtectionFlags `
-ExtendedProtectionSPNList $PushNotificationVDConfig.ExtendedProtectionSPNList `
-ExtendedProtectionTokenChecking $RoleEPTokenCheckingRequireOrNone;
}
Sie sehen gut, dass die Einstellung zu "RoleDoNotEnableEP" nicht relevant ist, da in beiden Fällen ein "New-PushNotificationsVirtualDirectory" mit dem Parameter "-RequireSSL $PushNotificationVDConfig.RequireSSL" ausgeführt wird. Der Fehlermeldung zufolge muss bei -RequireSSL $PushNotificationVDConfig.RequireSSL ein Wert übergeben werden. "NULL" ist nicht gültig. Also bin ich im Code rückwärts gelaufen um die Zuweisung von $PushNotificationVDConfig zu finden und es steht direkt vor dem Block mit der Neuanlage.
($PushNotificationVDConfig = Get-PushNotificationsVirtualDirectory `
-ShowMailboxVirtualDirectories `
-server $RoleFqdnOrName `
-DomainController $RoleDomainController) `
| Remove-PushNotificationsVirtualDirectory `
-DomainController $RoleDomainController;
Das Exchange Setup liest hier die bestehende Konfiguration aus und entfernt dann das virtuelle Verzeichnis gleich mit. Leider protokolliert Exchange hier nicht die Ergebnisse. Bei der Neuanlage sieht es aber so aus, als ob das Feld normalerweise ein "True" oder "False" hat aber im Fehlerfall der Wert "Null" ist. Zum Glück habe ich weitere Server, bei denen das Update erfolgreich war und dort finde ich im "ExchangeServerSetup.log" weitere Details:
[11.01.2025 20:21:37.0515] [2] Beginning processing New-PushNotificationsVirtualDirectory
[11.01.2025 20:21:37.0531] [2] Searching objects "EX01.UCLABOR.DE" of type "Server" under the root "$null".
[11.01.2025 20:21:37.0593] [2] Previous operation run on domain controller 'DC01.UCLABOR.DE'.
[11.01.2025 20:21:37.0593] [2] Processing object "EX01\PushNotifications".
[11.01.2025 20:21:43.0296] [2] The properties changed on the object '' (CN=PushNotifications (Exchange Back End),CN=HTTP,CN=Protocols,
CN=EX01,CN=Servers,CN=Exchange Administrative Group (FYDIBOHF23SPDLT),CN=Administrative Groups,
CN=First Organization,CN=Microsoft Exchange,CN=Services,CN=Configuration,DC=UCLABOR,DC=DE) are:
"{ MetabasePath[msExchMetabasePath]='IIS://EX01.UCLABOR.DE/W3SVC/2/ROOT/PushNotifications',
AuthenticationMethodFlags[msExchInternalAuthenticationMethods]='Ntlm, WindowsIntegrated',
AuthenticationMethodFlags[msExchExternalAuthenticationMethods]='Ntlm, WindowsIntegrated',
Id[distinguishedName]='EX01\PushNotifications (Exchange Back End)',
InternalAuthenticationMethods[msExchInternalAuthenticationMethods]={ 'Ntlm', 'WindowsIntegrated' },
ExternalAuthenticationMethods[msExchExternalAuthenticationMethods]={ 'Ntlm', 'WindowsIntegrated' },
OrganizationId[msExchOURoot, msExchCU]='' }".
[11.01.2025 20:21:43.0296] [2] Saving object "EX01\PushNotifications (Exchange Back End)" of type "ADPushNotificationsVirtualDirectory" and state "New".
[11.01.2025 20:21:43.0312] [2] Previous operation run on domain controller 'DC01.UCLABOR.DE'.
[11.01.2025 20:21:45.0249] [2] Searching objects "EX01\PushNotifications (Exchange Back End)" of type "ADPushNotificationsVirtualDirectory" under the root "$null".
[11.01.2025 20:21:45.0249] [2] Previous operation run on domain controller 'DC01.UCLABOR.DE'.
[11.01.2025 20:21:45.0249] [2] Ending processing New-PushNotificationsVirtualDirectory
Mit dem LDAP-Pfad können wir uns das Objekte auch etwas genauer in ADSIEDIT anschauen:

Einzig die beiden Felder "msexchangeinternalauthentication" und "msexchangeexternalauthentication" fallen mir hier auf Anhieb auf. Zu beiden Feldern ist das Internet ebenfalls sehr schweigsam. Daher habe ich mir meine vorhandenen Server angeschaut, die Werte protokolliert und mit der PowerShell verglichen.
| Webseite | Internal | External | Ausgabe |
|---|---|---|---|
Autodisover (Default) |
1171 |
1171 |
InternalAuthenticationMethods : {Basic, Ntlm, WindowsIntegrated, WSSecurity, OAuth}
ExternalAuthenticationMethods : {Basic, Ntlm, WindowsIntegrated, WSSecurity, OAuth}
LiveIdNegotiateAuthentication : False
WSSecurityAuthentication : True
LiveIdBasicAuthentication : False
BasicAuthentication : True
DigestAuthentication : False
WindowsAuthentication : True
OAuthAuthentication : True
AdfsAuthentication : False
|
Autodisover (Backend) |
146 |
146 |
|
PowerShell (Default) |
1 |
1 |
CertificateAuthentication : True
InternalAuthenticationMethods : {Basic}
ExternalAuthenticationMethods : {Basic}
LiveIdNegotiateAuthentication : False
WSSecurityAuthentication : False
LiveIdBasicAuthentication : False
BasicAuthentication : True
DigestAuthentication : False
WindowsAuthentication : False
OAuthAuthentication : False
AdfsAuthentication : False
RequireSSL : False
|
MAPI (Default) |
9218 |
9218 |
IISAuthenticationMethods : {Ntlm, OAuth, Negotiate}
InternalAuthenticationMethods : {Ntlm, OAuth, Negotiate}
ExternalAuthenticationMethods : {Ntlm, OAuth, Negotiate}
|
Das einzige Commandlet mit einem "-RequireSSL"-Parameter ist dabei "Set-PowerShellVirtualDirectory". Ich habe daher mal schnell hier den Werte geändert und auf Änderungen gehofft.
Get-PowerShellVirtualDirectory `
-Server ex01 `
| Set-PowerShellVirtualDirectory `
-RequireSSL $true
Viel schlimmer war, dass ich den Werte nicht mehr auf "$False" zurückdrehen konnte, da die PowerShell mich mehr nutzbar war. Ich konnte die Änderung aber IIS wieder zurückdrehen.

Ein Blick mit ADSIEDIT in das entsprechende Objekt hat gezeigt, dass sich dort aber nichts geändert hat. Das geht recht einfach mit "whenChanged". Das PowerShell Virtual Directory hat keine Änderung erfahren:

Dieser Ausflug hat mir gezeigt, dass die Exchange Commandlets auch direkt die IIS-Konfiguration auf dem Server anpassen. Das ist zwar noch kein Beweis aber die Einstellung des virtuellen Verzeichnisses liegt sicher in der METABASE des IIS. Bei mir ist das C:\Windows\System32\inetsrv\config\applicationHost.config. Und hier finde ich auch die Konfiguration zur PushNotification:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<location path="Exchange Back End/PushNotifications">
<system.webServer>
<directoryBrowse enabled="false" showFlags="Date, Size, Extension, LongDate" />
<handlers accessPolicy="Read, Script" />
<security>
<access sslFlags="Ssl, Ssl128" />
<authentication>
<windowsAuthentication enabled="true">
<providers>
<clear />
<add value="Negotiate" />
<add value="NTLM" />
</providers>
<extendedProtection tokenChecking="None" />
</windowsAuthentication>
<clientCertificateMappingAuthentication enabled="false" />
<anonymousAuthentication enabled="true" />
<iisClientCertificateMappingAuthentication enabled="false" />
<digestAuthentication enabled="false" />
<basicAuthentication enabled="false" />
</authentication>
</security>
<defaultDocument enabled="true">
<files>
<clear />
<add value="Default.htm" />
<add value="Default.asp" />
<add value="index.htm" />
<add value="index.html" />
<add value="iisstart.htm" />
<add value="default.aspx" />
</files>
</defaultDocument>
</system.webServer>
</location>
</configuration>
Hier finde ich einen Eintrag "<access sslFlags="Ssl, Ssl128" />" und auch wenn ich es nicht beschwören möchte, so könnte hier die Ursache liegen. Beim PowerShell-Verzeichnis ohne SSL-Zwang steht hier:
<access sslFlags="SslNegotiateCert" />
Wenn wenn ich den Eintrag beim PowerShellVirtualDirectory wegnehme, dann bricht das sofort meine Exchange PowerShell.
Insofern würde ich auch bei den "Push Notifications" den Wert einmal prüfen. Hier die Default-Einstellungen eines Exchange 2016 Server.

Für die Überprüfung von Exchange Servern gab es früher noch den ExBPA - Exchange Best Practice Analyzer und mittlerweile den Exchange HealthChecker. Letzterer ist ein PowerShell-Script, indem ich auch sehen konnte, dass die IIS-Einstellungen geprüft werden. Wenn Sie dort in den Code schauen, finden Sie:
# Hier liest das Skript die Werte aus der IIS Konfiguration $appHostConfigPath = "$($env:WINDIR)\System32\inetSrv\config\applicationHost.config" $appHostConfig.Load($appHostConfigPath)
# Hier parst Microsoft dann die XML-Datei um die Konfiguration des Webservers zu lesen
[string]$sslSettings = $configNode.'system.webServer'.security.access.sslFlags
if ([string]::IsNullOrEmpty($sslSettings)) {
Write-Verbose "Failed to find SSL settings for the path. Falling back to the root."
# Sieh sehen hier aber auch, dass der Healtch Checker keinen Fehler meldet,
# wenn der Eintrag fehlt und stattdessen den Wert der "Root" nimmt.
Dann werden die Werte aufgeteilt und verglichen:
....
if ($null -ne $sslSettings) {
[array]$sslFlags = ($sslSettings.Split(",").ToLower()).Trim()
} else {
$sslFlags = $null
}
# SSL flags: https://docs.Microsoft.com/iis/configuration/system.webserver/security/access#attributes
$requireSsl = $false
$ssl128Bit = $false
$clientCertificate = "Unknown"
if ($null -eq $sslFlags) {
Write-Verbose "Failed to find SSLFlags"
} elseif ($sslFlags.Contains("none")) {
$clientCertificate = "Ignore"
} else {
if ($sslFlags.Contains("ssl")) { $requireSsl = $true }
if ($sslFlags.Contains("ssl128")) { $ssl128Bit = $true }
if ($sslFlags.Contains("sslNegotiateCert".ToLower())) {
$clientCertificate = "Accept"
} elseif ($sslFlags.Contains("sslRequireCert".ToLower())) {
$clientCertificate = "Require"
} else {
$clientCertificate = "Ignore"
}
}
....
Es kann also sein, dass der Exchange HealthChecker durch aus ein "True" liefert, weil er beim Fehlen des Eintrags die Einstellung aus der Wurzel übernimmt, wohingegen ein "Get-PushNotificationsVirtualDirectory" dann einfach ein "$Null" liefert.
Leider konnte ich das nicht prüfen, da ich keine Exchange Install PowerShell starten konnte und es außer *-VirtualPowerShellDirectory" keine anderen Commandlets gibt, die ein "SSLRequired" auslesen.
Exchange Install PowerShell
Es hat mir keine Ruhe gelassen, was denn "Get-PushNotificationsVirtualDirectory" ausliest, habe erst mal alle DLLS nach diesem String durchsucht und wurde hier fündig:;
C:\Windows\Temp\ExchangeSetup\Microsoft.Exchange.PowerShell.Configuration.dll C:\Windows\Temp\ExchangeSetup\Microsoft.Exchange.PowerSharp.Management.dll C:\Windows\Temp\ExchangeSetup\Microsoft.Exchange.Management.RbacDefinition.dll C:\Windows\Temp\ExchangeSetup\Microsoft.Exchange.Management.Deployment.Xml.dll
Ich gehe nun nicht davon aus, dass all diese DLLs den gleichen Code enthalten aber es könnte auch andere Fehler geben
Zusammenfassung
Anhand eines Fehlers bei der Installation bin ich in unfreiwillig in die Tiefen des Setup und der Fehlersuche eingetreten. Letztlich habe ich bei mir das Problem damit gelöst und musste nicht einen Server komplett neu installieren, denn auch eine einfache "Wiederholung" hat nicht geholfen. Über die Telemetrie dürfte Microsoft diesen und andere Fehler natürlich mitbekommen und vermutlich wurde dieser Fehler schon behoben. Aber vielleicht helfen die Analysen dem ein oder anderen Admin, wenn er einen Fehler bei der Installation hat.
Weitere Links
- Exchange HealthChecker
- Exchange Extended Protection
-
Recipient Management without Exchange Server
behind the Scenes - Icewolf Blog
https://blog.icewolf.ch/archive/2022/05/31/recipient-management-without-exchange-server-behind-the-scenes/















