From 67bc378f882f8390df255fd658e71fa4a9d4c626 Mon Sep 17 00:00:00 2001 From: David Paulson Date: Wed, 9 Aug 2023 17:37:24 -0500 Subject: [PATCH] Make sure we invoke actions in remote context correctly --- .../Get-ExchangeAES256CBCDetails.ps1 | 64 +++++++++++-------- 1 file changed, 38 insertions(+), 26 deletions(-) diff --git a/Diagnostics/HealthChecker/DataCollection/ExchangeInformation/Get-ExchangeAES256CBCDetails.ps1 b/Diagnostics/HealthChecker/DataCollection/ExchangeInformation/Get-ExchangeAES256CBCDetails.ps1 index 01e8eabd31..08270470cd 100644 --- a/Diagnostics/HealthChecker/DataCollection/ExchangeInformation/Get-ExchangeAES256CBCDetails.ps1 +++ b/Diagnostics/HealthChecker/DataCollection/ExchangeInformation/Get-ExchangeAES256CBCDetails.ps1 @@ -20,34 +20,21 @@ function Get-ExchangeAES256CBCDetails { begin { Write-Verbose "Calling: $($MyInvocation.MyCommand)" - $aes256CBCSupported = $false - $msipcRegistryAclAsExpected = $false - $regPathToCheck = "HKLM:\SOFTWARE\Microsoft\MSIPC\Server" - # Translates to: "NetworkService", "FullControl", "ContainerInherit, ObjectInherit", "None", "Allow" - # See: https://learn.microsoft.com/dotnet/api/system.security.accesscontrol.registryaccessrule.-ctor?view=net-7.0#system-security-accesscontrol-registryaccessrule-ctor(system-security-principal-identityreference-system-security-accesscontrol-registryrights-system-security-accesscontrol-inheritanceflags-system-security-accesscontrol-propagationflags-system-security-accesscontrol-accesscontroltype) - $networkServiceAcl = New-Object System.Security.AccessControl.RegistryAccessRule( - (New-Object System.Security.Principal.SecurityIdentifier("S-1-5-20")), 983103, 3, 0, 0 - ) - } process { - # First, check if the build running on the server supports AES256-CBC - if (Test-ExchangeBuildGreaterOrEqualThanSecurityPatch -CurrentExchangeBuild $VersionInformation -SU "Aug23SU") { - - Write-Verbose "AES256-CBC encryption for information protection is supported by this Exchange Server build" - $aes256CBCSupported = $true - # As build supports AES256-CBC, next step is to check that the registry key exists and permissions are set as expected - $params = @{ - ComputerName = $Server - ScriptBlock = { Test-Path -Path $regPathToCheck } - CatchActionFunction = ${Function:Invoke-CatchActions} - } + function GetRegistryAclCheckScriptBlock { + $sbMsipcRegistryAclAsExpected = $false + $regPathToCheck = "HKLM:\SOFTWARE\Microsoft\MSIPC\Server" + # Translates to: "NetworkService", "FullControl", "ContainerInherit, ObjectInherit", "None", "Allow" + # See: https://learn.microsoft.com/dotnet/api/system.security.accesscontrol.registryaccessrule.-ctor?view=net-7.0#system-security-accesscontrol-registryaccessrule-ctor(system-security-principal-identityreference-system-security-accesscontrol-registryrights-system-security-accesscontrol-inheritanceflags-system-security-accesscontrol-propagationflags-system-security-accesscontrol-accesscontroltype) + $networkServiceAcl = New-Object System.Security.AccessControl.RegistryAccessRule( + (New-Object System.Security.Principal.SecurityIdentifier("S-1-5-20")), 983103, 3, 0, 0 + ) + $pathExists = Test-Path $regPathToCheck - if ((Invoke-ScriptBlockHandler @params) -eq $false) { + if ($pathExists -eq $false) { Write-Verbose "Unable to query Acl of registry key $regPathToCheck assuming that the key doesn't exist" } else { - $params.ScriptBlock = { Get-Acl -Path $regPathToCheck } - $acl = Invoke-ScriptBlockHandler @params - + $acl = Get-Acl -Path $regPathToCheck # ToDo: As we have multiple places in HC where we query acls, we should consider creating a function # that can be used to do the acl call, similar to what we do in Get-ExchangeRegistryValues.ps1. Write-Verbose "Registry key exists and Acl was successfully queried - validating Acl now" @@ -62,15 +49,40 @@ function Get-ExchangeAES256CBCDetails { if (@($aclMatch).Count -ge 1) { Write-Verbose "Acl for NetworkService is as expected" - $msipcRegistryAclAsExpected = $true + $sbMsipcRegistryAclAsExpected = $true } else { Write-Verbose "Acl for NetworkService was not found or is not as expected" } } catch { Write-Verbose "Unable to verify Acl on registry key $regPathToCheck" - Invoke-CatchActions + # Unable to use Invoke-CatchActions because of remote script block } } + + return [PSCustomObject]@{ + PathExits = $pathExists + RegistryKeyConfiguredAsExpected = $sbMsipcRegistryAclAsExpected + } + } + + $aes256CBCSupported = $false + $msipcRegistryAclAsExpected = $false + } process { + # First, check if the build running on the server supports AES256-CBC + if (Test-ExchangeBuildGreaterOrEqualThanSecurityPatch -CurrentExchangeBuild $VersionInformation -SU "Aug23SU") { + + Write-Verbose "AES256-CBC encryption for information protection is supported by this Exchange Server build" + $aes256CBCSupported = $true + + $params = @{ + ComputerName = $Server + ScriptBlock = ${Function:GetRegistryAclCheckScriptBlock} + CatchActionFunction = ${Function:Invoke-CatchActions} + } + $results = Invoke-ScriptBlockHandler @params + Write-Verbose "Found Registry Path: $($results.PathExits)" + Write-Verbose "Configured Correctly: $($results.RegistryKeyConfiguredAsExpected)" + $msipcRegistryAclAsExpected = $results.RegistryKeyConfiguredAsExpected } else { Write-Verbose "AES256-CBC encryption for information protection is not supported by this Exchange Server build" }