DSCResources/MSFT_xExchExchangeCertificate/MSFT_xExchExchangeCertificate.psm1
function Get-TargetResource { [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSDSCUseVerboseMessageInDSCResource", "")] [CmdletBinding()] [OutputType([System.Collections.Hashtable])] param ( [Parameter(Mandatory = $true)] [System.String] $Thumbprint, [Parameter(Mandatory = $true)] [System.Management.Automation.PSCredential] [System.Management.Automation.Credential()] $Credential, [Parameter(Mandatory = $true)] [ValidateSet('Present', 'Absent')] [System.String] $Ensure, # Only used by Test-TargetResource [Parameter()] [System.Boolean] $AllowExtraServices = $false, [Parameter()] [System.Management.Automation.PSCredential] [System.Management.Automation.Credential()] $CertCreds, [Parameter()] [System.String] $CertFilePath, [Parameter()] [System.String] $DomainController, [Parameter()] [System.String[]] $Services ) Write-FunctionEntry -Parameters @{'Thumbprint' = $Thumbprint} -Verbose:$VerbosePreference # Establish remote PowerShell session Get-RemoteExchangeSession -Credential $Credential -CommandsToLoad 'Get-ExchangeCertificate' -Verbose:$VerbosePreference $cert = GetExchangeCertificate @PSBoundParameters if ($null -ne $cert) { $returnValue = @{ Thumbprint = [System.String] $Thumbprint Services = [System.String[]] $cert.Services.ToString().Split(',').Trim() } } $returnValue } function Set-TargetResource { [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [System.String] $Thumbprint, [Parameter(Mandatory = $true)] [System.Management.Automation.PSCredential] [System.Management.Automation.Credential()] $Credential, [Parameter(Mandatory = $true)] [ValidateSet('Present', 'Absent')] [System.String] $Ensure, # Only used by Test-TargetResource [Parameter()] [System.Boolean] $AllowExtraServices = $false, [Parameter()] [System.Management.Automation.PSCredential] [System.Management.Automation.Credential()] $CertCreds, [Parameter()] [System.String] $CertFilePath, [Parameter()] [System.String] $DomainController, [Parameter()] [System.String[]] $Services ) Write-FunctionEntry -Parameters @{'Thumbprint' = $Thumbprint} -Verbose:$VerbosePreference # Establish remote PowerShell session Get-RemoteExchangeSession -Credential $Credential -CommandsToLoad '*ExchangeCertificate' -Verbose:$VerbosePreference $cert = GetExchangeCertificate @PSBoundParameters # Check whether any UM services are being enabled, and if they weren't enable before. If so, we should stop those services, enable the cert, then start them up $needUMServiceReset = $false $needUMCallRouterServiceReset = $false if ($null -ne $cert) { $currentServices = Convert-StringToArray -StringIn $cert.Services -Separator ',' } if ((Test-ArrayElementsInSecondArray -Array2 $Services -Array1 'UM' -IgnoreCase) -eq $true) { if ($null -eq $cert -or (Test-ArrayElementsInSecondArray -Array2 $currentServices -Array1 'UM' -IgnoreCase) -eq $false) { $needUMServiceReset = $true } } if ((Test-ArrayElementsInSecondArray -Array2 $Services -Array1 'UMCallRouter' -IgnoreCase) -eq $true) { if ($null -eq $cert -or (Test-ArrayElementsInSecondArray -Array2 $currentServices -Array1 'UMCallRouter' -IgnoreCase) -eq $false) { $needUMCallRouterServiceReset = $true } } # Stop required services before working with the cert if ($needUMServiceReset -eq $true) { Write-Verbose -Message 'Stopping service MSExchangeUM before enabling the UM service on the certificate' Stop-Service -Name MSExchangeUM -Confirm:$false } if ($needUMCallRouterServiceReset -eq $true) { Write-Verbose -Message 'Stopping service MSExchangeUMCR before enabling the UMCallRouter service on the certificate' Stop-Service -Name MSExchangeUMCR -Confirm:$false } # The desired cert is not present. Deal with that scenario. if ($null -eq $cert) { # If the cert is null and it's supposed to be present, then we need to import one if ($Ensure -eq 'Present') { $cert = Import-ExchangeCertificate -FileData ([Byte[]] $(Get-Content -Path "$($CertFilePath)" -Encoding Byte -ReadCount 0)) -Password:$CertCreds.Password -Server $env:COMPUTERNAME } } else { # cert is present and it shouldn't be. Remove it if ($Ensure -eq 'Absent') { Remove-ExchangeCertificate -Thumbprint $Thumbprint -Confirm:$false -Server $env:COMPUTERNAME } } # Cert is present. Set props on it if ($Ensure -eq 'Present') { if ($null -ne $cert) { $previousError = Get-PreviousError Enable-ExchangeCertificate -Thumbprint $Thumbprint -Services $Services -Force -Server $env:COMPUTERNAME Assert-NoNewError -CmdletBeingRun 'Enable-ExchangeCertificate' -PreviousError $previousError -Verbose:$VerbosePreference } else { Write-Error 'Failed to install certificate' } } # Start UM services that were stopped earlier if ($needUMServiceReset -eq $true) { Write-Verbose -Message 'Starting service MSExchangeUM' Start-Service -Name MSExchangeUM -Confirm:$false } if ($needUMCallRouterServiceReset -eq $true) { Write-Verbose -Message 'Starting service MSExchangeUMCR' Start-Service -Name MSExchangeUMCR -Confirm:$false } } function Test-TargetResource { [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSDSCUseVerboseMessageInDSCResource", "")] [CmdletBinding()] [OutputType([System.Boolean])] param ( [Parameter(Mandatory = $true)] [System.String] $Thumbprint, [Parameter(Mandatory = $true)] [System.Management.Automation.PSCredential] [System.Management.Automation.Credential()] $Credential, [Parameter(Mandatory = $true)] [ValidateSet('Present', 'Absent')] [System.String] $Ensure, # Only used by Test-TargetResource [Parameter()] [System.Boolean] $AllowExtraServices = $false, [Parameter()] [System.Management.Automation.PSCredential] [System.Management.Automation.Credential()] $CertCreds, [Parameter()] [System.String] $CertFilePath, [Parameter()] [System.String] $DomainController, [Parameter()] [System.String[]] $Services ) Write-FunctionEntry -Parameters @{'Thumbprint' = $Thumbprint} -Verbose:$VerbosePreference # Establish remote PowerShell session Get-RemoteExchangeSession -Credential $Credential -CommandsToLoad 'Get-ExchangeCertificate' -Verbose:$VerbosePreference $cert = GetExchangeCertificate @PSBoundParameters $testResults = $true if ($null -ne $cert) { if ($Ensure -eq 'Present') { if (!(CompareCertServices -ServicesActual $cert.Services -ServicesDesired $Services -AllowExtraServices $AllowExtraServices)) { Write-InvalidSettingVerbose -SettingName 'Services' -ExpectedValue $Services -ActualValue $cert.Services -Verbose:$VerbosePreference $testResults = $false } } else { Write-Verbose -Message "Certificate with thumbprint $Thumbprint still exists" $testResults = $false } } else { if ($Ensure -ne 'Absent') { Write-Verbose -Message "Certificate with thumbprint $Thumbprint does not exist" $testResults = $false } } return $testResults } # Runs Get-ExchangeCertificate, only specifying Thumbprint, ErrorAction, and optionally DomainController function GetExchangeCertificate { [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [System.String] $Thumbprint, [Parameter(Mandatory = $true)] [System.Management.Automation.PSCredential] [System.Management.Automation.Credential()] $Credential, [Parameter(Mandatory = $true)] [ValidateSet('Present', 'Absent')] [System.String] $Ensure, # Only used by Test-TargetResource [Parameter()] [System.Boolean] $AllowExtraServices = $false, [Parameter()] [System.Management.Automation.PSCredential] [System.Management.Automation.Credential()] $CertCreds, [Parameter()] [System.String] $CertFilePath, [Parameter()] [System.String] $DomainController, [Parameter()] [System.String[]] $Services ) # Remove params we don't want to pass into the next command Remove-FromPSBoundParametersUsingHashtable -PSBoundParametersIn $PSBoundParameters -ParamsToKeep 'Thumbprint', 'DomainController' return (Get-ExchangeCertificate @PSBoundParameters -ErrorAction SilentlyContinue -Server $env:COMPUTERNAME) } <# .Synopsis Compares whether services from a certificate object match the services that were requested. If AllowsExtraServices is true, it is OK for more services to be on the cert than were requested, as long as the requested services are present. #> function CompareCertServices { param ( [Parameter()] [System.String] $ServicesActual, [Parameter()] [System.String[]] $ServicesDesired, [Parameter()] [System.Boolean] $AllowExtraServices ) $actual = Convert-StringToArray -StringIn $ServicesActual -Separator ',' if ($AllowExtraServices -eq $true) { if (!([System.String]::IsNullOrEmpty($ServicesDesired)) -and $ServicesDesired.Contains('NONE')) { $result = $true } else { $result = Test-ArrayElementsInSecondArray -Array1 $ServicesDesired -Array2 $actual -IgnoreCase } } else { $result = Compare-ArrayContent -Array1 $actual -Array2 $ServicesDesired -IgnoreCase } return $result } Export-ModuleMember -Function *-TargetResource Export-ModuleMember -Function CompareCertServices |