Public/Connectors.ps1
$ModuleVersion = $myInvocation.MyCommand.Version <# .SYNOPSIS Read existing SEPPmail Exchange Online connectors .DESCRIPTION SEPPmail uses 2 Connectors to transfer messages between SEPPmail and Exchange Online This commandlet will show existing connectors. .EXAMPLE Get-SM365Connectors #> function Get-SM365Connectors { [CmdletBinding()] Param () if (!(Test-SM365ConnectionStatus)) { throw [System.Exception] "You're not connected to Exchange Online - please connect prior to using this CmdLet" } else { Write-Information "Connected to Exchange Organization `"$Script:ExODefaultDomain`"" -InformationAction Continue $inbound = Get-SM365InboundConnectorSettings $outbound = Get-SM365OutboundConnectorSettings if (Get-OutboundConnector -outvariable obc | Where-Object Identity -eq $($outbound.Name)) { $obc|select-object Name,Enabled,WhenCreated,SmartHosts } else { Write-Warning "No SEPPmail Outbound Connector with name `"$($outbound.Name)`" found" } if (Get-InboundConnector -outvariable ibc | Where-Object Identity -eq $($inbound.Name)) { $ibc|select-object Name,Enabled,WhenCreated,TlsSenderCertificateName } else { Write-Warning "No SEPPmail Inbound Connector with Name `"$($inbound.Name)`" found" } } } <# .SYNOPSIS Adds SEPPmail Exchange Online connectors .DESCRIPTION SEPPmail uses 2 Connectors to transfer messages between SEPPmail and Exchange Online This commandlet will create the two connectors for you. The -SEPPmailFQDN must point to a SEPPmail Appliance with a valid certificate to establish the TLS connection. To use a wildcard certifiacate, use the -TLSCertName parameter. .EXAMPLE New-SM365Connectors -SEPPmailFQDN 'securemail.contoso.com' -TLSCertName '*.contoso.com' Takes the Exchange Online environment settings and creates Inbound and Outbound connectors to a SEPPmail Appliance with a wildcard TLS certificate .EXAMPLE New-SM365Connectors -SEPPmailFQDN 'securemail.contoso.com' Takes the Exchange Online environment settings and creates Inbound and Outbound connectors to a SEPPmail Appliance. Assumes that the TLS certificate is identical with the SEPPmail FQDN .EXAMPLE New-SM365Connectors -SEPPmailFQDN 'securemail.contoso.com' -CBCCertName 'inbound.contoso.com' For MSP Setups with Certificate Based Connectors (CBC) we need different certificates for inbound and coutbound connectors. Takes the Exchange Online environment settings and creates Inbound and Outbound connectors to a SEPPmail Appliance. Uses the FQDN as certificate name for the outbound connector and takes the -CBCCertName as the certificate name for the inbound connector See the SEPPmail online manual for details on how to setup ARC/CBC here https://docs.seppmail.com/de/09_ht_mso365_ssl_certificate.html?q=CBC .EXAMPLE New-SM365Connectors -SEPPmailFQDN 'securemail.contoso.com' -AllowSelfSignedCertificates Same as above, just no officially trusted certificate needed. .EXAMPLE New-SM365Connectors -SEPPmailFQDN securemail.contoso.com -NoOutBoundTlsCheck Same as the default config, just with no TLS encryption at all. .EXAMPLE New-SM365Connectors -SEPPmailFQDN securemail.contoso.com -Disabled Use this option if you want to create the connectors, but just disable them on creation, use the -Disabled switch. .EXAMPLE New-SM365Connectors -SEPPmailIp '51.144.46.62' Use this if your SEPPmail is just accessible via an IP Address, use the -SEPPmailIP parameter. .EXAMPLE New-SM365Connectors -SEPPmailFQDN securemail.contoso.com -NoAntiSpamWhiteListing To avoid, adding the SEPPmail to the ANTI-SPAM WhiteList of Microsoft Defender use the example below #> function New-SM365Connectors { [CmdletBinding( SupportsShouldProcess = $true, ConfirmImpact = 'Medium', DefaultParameterSetName = 'FqdnTls' )] param ( #region FqdnTls [Parameter( Mandatory = $true, HelpMessage = 'FQDN of the SEPPmail Appliance, i.e. securemail.contoso.com', ParameterSetName = 'FqdnTls', Position = 0 )] [Parameter( Mandatory = $true, HelpMessage = 'FQDN of the SEPPmail Appliance, i.e. securemail.contoso.com', ParameterSetName = 'FqdnNoTls', Position = 0 )] [ValidatePattern("^(?!:\/\/)(?=.{1,255}$)((.{1,63}\.){1,127}(?![0-9]*$)[a-z0-9-]+\.?)$")] [Alias('FQDN','SMFQDN')] [String] $SEPPmailFQDN, #endregion fqdntls #region TLSSenderCertificateName [Parameter( Mandatory = $false, HelpMessage = 'Name of the certificate if different from the SEPPmail-FQDN. Read the cetificate name in your SEPPmail under SSL==>Issued to==>Name (CN)', ParameterSetname = 'FqdnTls', Position = 1 )] [Alias('TLSCertName','CertName')] [String] $TLSCertificateName, #endregion #region selfsigned [Parameter( Mandatory = $false, HelpMessage = 'OutBound Connector trusts also self signed certificates', ParameterSetName = 'FqdnTls' )] [Alias('AllowSelfSigned','SelfSigned')] [Switch] $AllowSelfSignedCertificates, #endregion SelfSigned #region NoOutboundTls [Parameter( Mandatory = $false, HelpMessage = 'OutBound Connector allows also non-TLS conenctions', ParameterSetName = 'FqdnNoTls' )] [Alias('NoTls')] [Switch] $NoOutBoundTlsCheck, #endregion NoTls #region IP [Parameter( Mandatory = $true, HelpMessage = 'If SEPPmail has no FQDN and is represented as an IP Address', ParameterSetName = 'Ip', Position = 0 )] [ValidatePattern("(\b25[0-5]|\b2[0-4][0-9]|\b[01]?[0-9][0-9]?)(\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}")] [Alias('SMIP','SMIPAddress')] [string] $SEPPmailIP, #endregion IP #region NoAntiSpamWhiteListing [Parameter( HelpMessage = 'Do not Add SEPPmailIP to the HostedConnectionFilterPolicy', ParameterSetName = 'FqdnTls' )] [Parameter( HelpMessage = 'Do not Add SEPPmailIP to the HostedConnectionFilterPolicy', ParameterSetName = 'FqdnNoTls' )] [Parameter( HelpMessage = 'Do not Add SEPPmailIP to the HostedConnectionFilterPolicy', ParameterSetName = 'Ip' )] [switch]$NoAntiSpamWhiteListing, #endRegion #region disabled [Parameter( Mandatory = $false, HelpMessage = 'Disable the connectors on creation', ParameterSetName = 'FqdnTls' )] [Parameter( Mandatory = $false, HelpMessage = 'Disable the connectors on creation', ParameterSetName = 'FqdnNoTls' )] [Parameter( Mandatory = $false, HelpMessage = 'Disable the connectors on creation', ParameterSetName = 'Ip' )] [switch]$Disabled, #endregion disabled #region MSP-CBC [Parameter( Mandatory = $false, HelpMessage = 'MSP setup requires a second certificate', ParameterSetName = 'FqdnTls', Position = 0 )] [string]$CBCcertName #endregion ) begin { if(!(Test-SM365ConnectionStatus)) {throw [System.Exception] "You're not connected to Exchange Online - please connect prior to using this CmdLet"} Write-Information "Connected to Exchange Organization `"$Script:ExODefaultDomain`"" -InformationAction Continue #resolve IP if ($PSCmdLet.ParameterSetName -like 'Fqdn*') { try { Write-Verbose "Transform $SEPPmailFQDN to IP Adress for IP based options" $SEPPmailIP = ([System.Net.Dns]::GetHostAddresses($SEPPmailFQDN).IPAddressToString) Write-Verbose "$SEPPmailFQDN equals the IP(s): $SEPPmailIP" } catch { Write-Error "Could not resolve IP Address of $SEPPmailFQDN. Please check SEPPmailFQDN hostname and try again." break } } Write-Verbose "Prepare Values out of Parametersets" If ($PsCmdLet.ParameterSetName -like 'FqdnTls') { $InboundTlsDomain = $SEPPmailFQDN if ($CBCcertName) { $InboundTlsDomain = $CBCcertName }else { $InboundTlsDomain = $SEPPmailFQDN } } else { [string[]]$SenderIPAddresses = $SEPPmailIP } #region collecting existing connectors Write-Verbose "Collecting existing connectors" $allInboundConnectors = Get-InboundConnector $allOutboundConnectors = Get-OutboundConnector Write-Verbose "Testing for hybrid Setup" $HybridInboundConn = $allInboundConnectors |Where-Object {(($_.Name -clike 'Inbound from *') -or ($_.ConnectorSource -clike 'HybridWizard'))} $HybridOutBoundConn = $allOutboundConnectors |Where-Object {(($_.Name -clike 'Outbound to *') -or ($_.ConnectorSource -clike 'HybridWizard'))} if ($HybridInboundConn -or $HybridOutBoundConn) { Write-Warning "!!! - Hybrid Configuration detected - we assume you know what you are doing. Be sure to backup your connector settings before making any change." if($InteractiveSession) { Write-Verbose "Ask user to continue if Hybrid is found." Do { try { [ValidateSet('y', 'Y', 'n', 'N')]$hybridContinue = Read-Host -Prompt "Create SEPPmail connectors in hybrid environment ? (Y/N)" } catch {} } until ($?) if ($hybridContinue -eq 'n') { Write-Verbose "Exiting due to user decision." break } } else { # should we error out here, since connector creation might be dangerous? } } else { Write-Information "No Hybrid Connectors detected, seems to be a clean cloud-only environment" -InformationAction Continue } #endregion } process { #region OutboundConnector $param = Get-SM365OutboundConnectorSettings if ($PsCmdLet.ParameterSetname -like 'fqdn*') { $param.SmartHosts = $SEPPmailFQDN } else { $param.SmartHosts = $SenderIPAddresses } Write-Verbose "Set Tls outbound domain depending in ParameterSetName $PsCmdLet.ParameterSetName" if ($PsCmdLet.ParameterSetName -eq 'FqdnTls') { $param.TlsDomain = $SEPPmailFQDN if ($AllowSelfSignedCertificates) { $param.TlsSettings = 'EncryptionOnly' $param.Remove('TlsDomain') } } if ($PsCmdLet.ParameterSetName -ne 'FqdnTls') { $param.TlsSettings = $null } Write-verbose "if -disabled switch is used, the connector stays deactivated" if ($Disabled) { $param.Enabled = $false } Write-Verbose "Read existing SEPPmail outbound connector" $existingSMOutboundConn = $allOutboundConnectors | Where-Object Name -like '`[SEPPmail`]*' # only $false if the user says so interactively [bool]$createOutBound = $true #Set Default Value if ($existingSMOutboundConn) { Write-Warning "Found existing SEPPmail outbound connector with name: `"$($existingSMOutboundConn.Name)`" created on `"$($existingSMOutboundConn.WhenCreated)`" pointing to SEPPmail `"$($existingSMOutboundConn.TlsDomain)`" " if($InteractiveSession) { [string] $tmp = $null Do { try { [ValidateSet('y', 'Y', 'n', 'N')]$tmp = Read-Host -Prompt "Shall we delete and recreate the outbound connector (will only work if no rules use it)? (Y/N)" break } catch {} } until ($?) if ($tmp -eq 'y') { $createOutbound = $true Write-Verbose "Removing existing Outbound Connector $($existingSMOutboundConn.Name) !" if ($PSCmdLet.ShouldProcess($($existingSMOutboundConn.Name), 'Removing existing SEPPmail Outbound Connector')) { $existingSMOutboundConn | Remove-OutboundConnector -Confirm:$false # user already confirmed action if (!$?) { throw $error[0] } } } else { Write-Warning "Leaving existing SEPPmail outbound connector `"$($existingSMOutboundConn.Name)`" untouched." $createOutbound = $false } } else { throw [System.Exception] "Outbound connector $($outbound.Name) already exists" } } else {Write-Verbose "No existing Outbound Connector found"} if($createOutbound) { Write-Verbose "Creating SEPPmail Outbound Connector $($param.Name)!" if ($PSCmdLet.ShouldProcess($($param.Name), 'Creating Outbound Connector')) { Write-Debug "Outbound Connector settings:" $param.GetEnumerator() | ForEach-Object{ Write-Debug "$($_.Key) = $($_.Value)" } $Now = Get-Date $param.Comment += "`n#Created with SEPPmail365 PowerShell Module version $ModuleVersion on $now" if ($TLSCertificateName.Length -gt 0) { $param.TlsDomain = $TLSCertificateName } [void](New-OutboundConnector @param) if(!$?) {throw $error[0]} } } #endregion OutboundConnector #region - Inbound Connector Write-Verbose "Read Inbound Connector Settings" $inbound = Get-SM365InboundConnectorSettings if ($PSCmdLet.ParametersetName -eq 'FqdnTls') { $inbound.TlsSenderCertificateName = $InboundTlsDomain } Write-verbose "if -disabled switch is used, the connector stays deactivated" if ($disabled) { $inbound.Enabled = $false } # Due to ARC Setup of Exo tenants and EFSkipLastIP is $true by default, EFSKipIP´s must be empty in certain setups. if ($PsCmdLet.ParameterSetName -ne 'FqdnTls') { Write-Verbose "Setting SEPPmail IP Address(es) $SEPPmailIP for EFSkipIP´s and Anti-SPAM Whitelist" # Remove all IPv6 addresses [string[]]$SEPPmailIpRange = Remove-IPv6Address -IPArray $SEPPmailIP $inbound.EFSkipIPs = $SEPPmailIpRange } Write-Verbose "Read existing SEPPmail Inbound Connector from Exchange Online" $existingSMInboundConn = $allInboundConnectors | Where-Object Name -like '`[SEPPmail`]*' # only $false if the user says so interactively [bool]$createInbound = $true if ($existingSMInboundConn) { Write-Warning "Found existing SEPPmail inbound Connector with name: `"$($existingSMInboundConn.Name)`", created `"$($existingSMInboundConn.WhenCreated)`" incoming SEPPmail is `"$($existingSMInboundConn.TlsSenderCertificateName)`"" if($InteractiveSession) { [string] $tmp = $null Do { try { [ValidateSet('y', 'Y', 'n', 'N')]$tmp = Read-Host -Prompt "Shall we delete and recreate the inbound connector (will only work if no rules use it)? (Y/N)" break } catch {} } until ($?) if ($tmp -eq 'y') { $createInbound = $true Write-Verbose "Removing existing SEPPmail Inbound Connector $($existingSMInboundConn.Name) !" if ($PSCmdLet.ShouldProcess($($existingSMInboundConn.Name), 'Removing existing SEPPmail inbound Connector')) { $existingSMInboundConn | Remove-InboundConnector -Confirm:$false # user already confirmed action if (!$?) { throw $error[0] } } } else { Write-Warning "Leaving existing SEPPmail Inbound Connector `"$($existingSMInboundConn.Name)`" untouched." $createInbound = $false } } else { throw [System.Exception] "Inbound connector $($inbound.Name) already exists" } } else {Write-Verbose "No existing Inbound Connector found"} if($createInbound) { # necessary assignment for splatting $param = $inbound Write-Verbose "Modify params based on ParameterSet" Write-Verbose "IP based Config, using $SenderIPAdresses" if ($PSCmdLet.ParameterSetName -eq 'Ip') { $param.SenderIPAddresses = $SenderIPAddresses $param.RequireTls = $false $param.EFSkipLastIP = $false } Write-Verbose "FQDN and Self Signed certificates, TLSCertificatename = $SEPPmailFQDN" if (($PSCmdLet.ParameterSetName -eq 'FqdnTls') -and ($AllowSelfSignedCertificates)) { $param.RestrictDomainsToCertificate = $false $param.TlsSenderCertificateName = $SEPPmailFQDN } Write-Verbose "FQDN and certificatename equals FQDN, using $SEPPmailFQDN as TLSCertificateName" if (($PSCmdLet.ParameterSetName -eq 'FqdnTls') -and ($TLSCertificateName.Length -eq 0) -and (!($CBCCertName))) { $param.TlsSenderCertificateName = $SEPPmailFQDN } Write-Verbose "FQDN and certificatename specified, using $TlscertificateName as TLSCertificateName" if (($PSCmdLet.ParameterSetName -eq 'FqdnTls') -and ($TLSCertificateName.Length -gt 0)) { $param.TlsSenderCertificateName = $TLSCertificateName } Write-Verbose "NoTls, using $SEPPmailFQDN as TLSCertificateName" if ($PSCmdLet.ParameterSetName -eq 'FqdnNoTls') { $param.TlsSenderCertificateName = $SEPPmailFQDN } Write-Verbose "Creating SEPPmail Inbound Connector $($param.Name)!" if ($PSCmdLet.ShouldProcess($($param.Name), 'Creating Inbound Connector')) { Write-Debug "Inbound Connector settings:" $param.GetEnumerator() | Foreach-Object { Write-Debug "$($_.Key) = $($_.Value)" } $Now = Get-Date $ModuleVersion = $myInvocation.MyCommand.Version $param.Comment += "`n#Created with SEPPmail365 PowerShell Module version $ModuleVersion on $now" [void](New-InboundConnector @param) if(!$?) { throw $error[0] } else { #region - Add SMFQDN to hosted Connection Filter Policy Whitelist if ($NoAntiSpamWhiteListing -eq $true) { Write-Verbose "Adding SEPPmail Appliance to allowlist in 'Hosted Connection Filter Policy'" Write-Verbose "Collecting existing WhiteList" $hcfp = Get-HostedConnectionFilterPolicy [string[]]$existingAllowList = $hcfp.IPAllowList Write-verbose "Adding SEPPmail Appliance to Policy $($hcfp.Id)" if ($existingAllowList) { $FinalIPList = ($existingAllowList + $SEPPmailIP)|sort-object -Unique } else { $FinalIPList = Remove-IPv6Address -IPArray $SEPPmailIP } Write-verbose "Adding IPaddress list with content $finalIPList to Policy $($hcfp.Id)" if ($FinalIPList) { Set-HostedConnectionFilterPolicy -Identity $hcfp.Id -IPAllowList $finalIPList } } #endRegion - Hosted Connection Filter Policy WhiteList } } } #endRegion InboundConnector } end { } } <# .SYNOPSIS Removes the SEPPmail inbound and outbound connectors .DESCRIPTION Convenience function to remove the SEPPmail connectors .EXAMPLE Remove-SM365Connectors .EXAMPLE Remove-SM365Connectors -leaveAntiSpamWhiteList Removes the connectors but leaves the IP Adress of the SEPPmail appliance in the ansiSpam Allowlist. #> function Remove-SM365Connectors { [CmdletBinding(SupportsShouldProcess=$true, ConfirmImpact='Medium')] Param ( [Switch]$leaveAntiSpamWhiteList ) if (!(Test-SM365ConnectionStatus)) { throw [System.Exception] "You're not connected to Exchange Online - please connect prior to using this CmdLet" } Write-Information "Connected to Exchange Organization `"$Script:ExODefaultDomain`"" -InformationAction Continue $inbound = Get-SM365InboundConnectorSettings $outbound = Get-SM365OutboundConnectorSettings $hcfp = Get-HostedConnectionFilterPolicy if($PSCmdlet.ShouldProcess($outbound.Name, "Remove SEPPmail outbound connector $($Outbound.Name)")) { if (Get-OutboundConnector | Where-Object Identity -eq $($outbound.Name)) { Remove-OutboundConnector $outbound.Name } else { Write-Warning 'No SEPPmail Outbound Connector found' } } if($PSCmdlet.ShouldProcess($inbound.Name, "Remove SEPPmail inbound connector $($inbound.Name)")) { $InboundConnector = Get-InboundConnector | Where-Object Identity -eq $($inbound.Name) if ($inboundConnector) { Write-Verbose 'Collect Inbound Connector IP for later Whitelistremoval' [string]$InboundSEPPmailIP = $null if ($inboundConnector.SenderIPAddresses.count -le 1) { $InboundSEPPmailIP = $InboundConnector.SenderIPAddresses[0] } if ($inboundConnector.TlsSenderCertificateName) { try { $InboundSEPPmailIP = ([System.Net.Dns]::GetHostAddresses($($inboundConnector.TlsSenderCertificateName)).IPAddressToString) } catch { $InboundSEPPmailIP = $null } } Remove-InboundConnector $inbound.Name Write-Verbose "If Inbound Connector has been removed, remove also Whitelisted IPs" if ((!($leaveAntiSpamWhiteList)) -and (!(Get-InboundConnector | Where-Object Identity -eq $($inbound.Name))) -and ($InboundSEPPmailIP)) { Write-Verbose "Remove SEPPmail Appliance IP from Whitelist in 'Hosted Connection Filter Policy'" Write-Verbose "Collecting existing WhiteList" [System.Collections.ArrayList]$existingAllowList = $hcfp.IPAllowList Write-verbose "Removing SEPPmail Appliance IP $InboundSEPPmailIP from Policy $($hcfp.Id)" if ($existingAllowList) { $existingAllowList.Remove($InboundSEPPmailIP) Set-HostedConnectionFilterPolicy -Identity $hcfp.Id -IPAllowList $existingAllowList Write-Information "IP: $InboundSEPPmailIP removed from Hosted Connection Filter Policy $hcfp.Id" } } } else { Write-Warning 'No SEPPmail Inbound Connector found' } } } if (!(Get-Alias 'Set-SM365Connectors' -ErrorAction SilentlyContinue)) { New-Alias -Name Set-SM365Connectors -Value New-SM365Connectors } # SIG # Begin signature block # MIIVzAYJKoZIhvcNAQcCoIIVvTCCFbkCAQExDzANBglghkgBZQMEAgEFADB5Bgor # BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG # KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCDmuRyqEzE7D6Ku # FthtnQzQ9ZXB5sJU1PQJJkhVzWO07KCCEggwggVvMIIEV6ADAgECAhBI/JO0YFWU # jTanyYqJ1pQWMA0GCSqGSIb3DQEBDAUAMHsxCzAJBgNVBAYTAkdCMRswGQYDVQQI # DBJHcmVhdGVyIE1hbmNoZXN0ZXIxEDAOBgNVBAcMB1NhbGZvcmQxGjAYBgNVBAoM # EUNvbW9kbyBDQSBMaW1pdGVkMSEwHwYDVQQDDBhBQUEgQ2VydGlmaWNhdGUgU2Vy # dmljZXMwHhcNMjEwNTI1MDAwMDAwWhcNMjgxMjMxMjM1OTU5WjBWMQswCQYDVQQG # EwJHQjEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMS0wKwYDVQQDEyRTZWN0aWdv # IFB1YmxpYyBDb2RlIFNpZ25pbmcgUm9vdCBSNDYwggIiMA0GCSqGSIb3DQEBAQUA # A4ICDwAwggIKAoICAQCN55QSIgQkdC7/FiMCkoq2rjaFrEfUI5ErPtx94jGgUW+s # hJHjUoq14pbe0IdjJImK/+8Skzt9u7aKvb0Ffyeba2XTpQxpsbxJOZrxbW6q5KCD # J9qaDStQ6Utbs7hkNqR+Sj2pcaths3OzPAsM79szV+W+NDfjlxtd/R8SPYIDdub7 # P2bSlDFp+m2zNKzBenjcklDyZMeqLQSrw2rq4C+np9xu1+j/2iGrQL+57g2extme # me/G3h+pDHazJyCh1rr9gOcB0u/rgimVcI3/uxXP/tEPNqIuTzKQdEZrRzUTdwUz # T2MuuC3hv2WnBGsY2HH6zAjybYmZELGt2z4s5KoYsMYHAXVn3m3pY2MeNn9pib6q # RT5uWl+PoVvLnTCGMOgDs0DGDQ84zWeoU4j6uDBl+m/H5x2xg3RpPqzEaDux5mcz # mrYI4IAFSEDu9oJkRqj1c7AGlfJsZZ+/VVscnFcax3hGfHCqlBuCF6yH6bbJDoEc # QNYWFyn8XJwYK+pF9e+91WdPKF4F7pBMeufG9ND8+s0+MkYTIDaKBOq3qgdGnA2T # OglmmVhcKaO5DKYwODzQRjY1fJy67sPV+Qp2+n4FG0DKkjXp1XrRtX8ArqmQqsV/ # AZwQsRb8zG4Y3G9i/qZQp7h7uJ0VP/4gDHXIIloTlRmQAOka1cKG8eOO7F/05QID # AQABo4IBEjCCAQ4wHwYDVR0jBBgwFoAUoBEKIz6W8Qfs4q8p74Klf9AwpLQwHQYD # VR0OBBYEFDLrkpr/NZZILyhAQnAgNpFcF4XmMA4GA1UdDwEB/wQEAwIBhjAPBgNV # HRMBAf8EBTADAQH/MBMGA1UdJQQMMAoGCCsGAQUFBwMDMBsGA1UdIAQUMBIwBgYE # VR0gADAIBgZngQwBBAEwQwYDVR0fBDwwOjA4oDagNIYyaHR0cDovL2NybC5jb21v # ZG9jYS5jb20vQUFBQ2VydGlmaWNhdGVTZXJ2aWNlcy5jcmwwNAYIKwYBBQUHAQEE # KDAmMCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5jb21vZG9jYS5jb20wDQYJKoZI # hvcNAQEMBQADggEBABK/oe+LdJqYRLhpRrWrJAoMpIpnuDqBv0WKfVIHqI0fTiGF # OaNrXi0ghr8QuK55O1PNtPvYRL4G2VxjZ9RAFodEhnIq1jIV9RKDwvnhXRFAZ/ZC # J3LFI+ICOBpMIOLbAffNRk8monxmwFE2tokCVMf8WPtsAO7+mKYulaEMUykfb9gZ # pk+e96wJ6l2CxouvgKe9gUhShDHaMuwV5KZMPWw5c9QLhTkg4IUaaOGnSDip0TYl # d8GNGRbFiExmfS9jzpjoad+sPKhdnckcW67Y8y90z7h+9teDnRGWYpquRRPaf9xH # +9/DUp/mBlXpnYzyOmJRvOwkDynUWICE5EV7WtgwggYaMIIEAqADAgECAhBiHW0M # UgGeO5B5FSCJIRwKMA0GCSqGSIb3DQEBDAUAMFYxCzAJBgNVBAYTAkdCMRgwFgYD # VQQKEw9TZWN0aWdvIExpbWl0ZWQxLTArBgNVBAMTJFNlY3RpZ28gUHVibGljIENv # ZGUgU2lnbmluZyBSb290IFI0NjAeFw0yMTAzMjIwMDAwMDBaFw0zNjAzMjEyMzU5 # NTlaMFQxCzAJBgNVBAYTAkdCMRgwFgYDVQQKEw9TZWN0aWdvIExpbWl0ZWQxKzAp # BgNVBAMTIlNlY3RpZ28gUHVibGljIENvZGUgU2lnbmluZyBDQSBSMzYwggGiMA0G # CSqGSIb3DQEBAQUAA4IBjwAwggGKAoIBgQCbK51T+jU/jmAGQ2rAz/V/9shTUxjI # ztNsfvxYB5UXeWUzCxEeAEZGbEN4QMgCsJLZUKhWThj/yPqy0iSZhXkZ6Pg2A2NV # DgFigOMYzB2OKhdqfWGVoYW3haT29PSTahYkwmMv0b/83nbeECbiMXhSOtbam+/3 # 6F09fy1tsB8je/RV0mIk8XL/tfCK6cPuYHE215wzrK0h1SWHTxPbPuYkRdkP05Zw # mRmTnAO5/arnY83jeNzhP06ShdnRqtZlV59+8yv+KIhE5ILMqgOZYAENHNX9SJDm # +qxp4VqpB3MV/h53yl41aHU5pledi9lCBbH9JeIkNFICiVHNkRmq4TpxtwfvjsUe # dyz8rNyfQJy/aOs5b4s+ac7IH60B+Ja7TVM+EKv1WuTGwcLmoU3FpOFMbmPj8pz4 # 4MPZ1f9+YEQIQty/NQd/2yGgW+ufflcZ/ZE9o1M7a5Jnqf2i2/uMSWymR8r2oQBM # dlyh2n5HirY4jKnFH/9gRvd+QOfdRrJZb1sCAwEAAaOCAWQwggFgMB8GA1UdIwQY # MBaAFDLrkpr/NZZILyhAQnAgNpFcF4XmMB0GA1UdDgQWBBQPKssghyi47G9IritU # pimqF6TNDDAOBgNVHQ8BAf8EBAMCAYYwEgYDVR0TAQH/BAgwBgEB/wIBADATBgNV # HSUEDDAKBggrBgEFBQcDAzAbBgNVHSAEFDASMAYGBFUdIAAwCAYGZ4EMAQQBMEsG # A1UdHwREMEIwQKA+oDyGOmh0dHA6Ly9jcmwuc2VjdGlnby5jb20vU2VjdGlnb1B1 # YmxpY0NvZGVTaWduaW5nUm9vdFI0Ni5jcmwwewYIKwYBBQUHAQEEbzBtMEYGCCsG # AQUFBzAChjpodHRwOi8vY3J0LnNlY3RpZ28uY29tL1NlY3RpZ29QdWJsaWNDb2Rl # U2lnbmluZ1Jvb3RSNDYucDdjMCMGCCsGAQUFBzABhhdodHRwOi8vb2NzcC5zZWN0 # aWdvLmNvbTANBgkqhkiG9w0BAQwFAAOCAgEABv+C4XdjNm57oRUgmxP/BP6YdURh # w1aVcdGRP4Wh60BAscjW4HL9hcpkOTz5jUug2oeunbYAowbFC2AKK+cMcXIBD0Zd # OaWTsyNyBBsMLHqafvIhrCymlaS98+QpoBCyKppP0OcxYEdU0hpsaqBBIZOtBajj # cw5+w/KeFvPYfLF/ldYpmlG+vd0xqlqd099iChnyIMvY5HexjO2AmtsbpVn0OhNc # WbWDRF/3sBp6fWXhz7DcML4iTAWS+MVXeNLj1lJziVKEoroGs9Mlizg0bUMbOalO # hOfCipnx8CaLZeVme5yELg09Jlo8BMe80jO37PU8ejfkP9/uPak7VLwELKxAMcJs # zkyeiaerlphwoKx1uHRzNyE6bxuSKcutisqmKL5OTunAvtONEoteSiabkPVSZ2z7 # 6mKnzAfZxCl/3dq3dUNw4rg3sTCggkHSRqTqlLMS7gjrhTqBmzu1L90Y1KWN/Y5J # KdGvspbOrTfOXyXvmPL6E52z1NZJ6ctuMFBQZH3pwWvqURR8AgQdULUvrxjUYbHH # j95Ejza63zdrEcxWLDX6xWls/GDnVNueKjWUH3fTv1Y8Wdho698YADR7TNx8X8z2 # Bev6SivBBOHY+uqiirZtg0y9ShQoPzmCcn63Syatatvx157YK9hlcPmVoa1oDE5/ # L9Uo2bC5a4CH2RwwggZzMIIE26ADAgECAhAMcJlHeeRMvJV4PjhvyrrbMA0GCSqG # SIb3DQEBDAUAMFQxCzAJBgNVBAYTAkdCMRgwFgYDVQQKEw9TZWN0aWdvIExpbWl0 # ZWQxKzApBgNVBAMTIlNlY3RpZ28gUHVibGljIENvZGUgU2lnbmluZyBDQSBSMzYw # HhcNMjMwMzIwMDAwMDAwWhcNMjYwMzE5MjM1OTU5WjBqMQswCQYDVQQGEwJERTEP # MA0GA1UECAwGQmF5ZXJuMSQwIgYDVQQKDBtTRVBQbWFpbCAtIERldXRzY2hsYW5k # IEdtYkgxJDAiBgNVBAMMG1NFUFBtYWlsIC0gRGV1dHNjaGxhbmQgR21iSDCCAiIw # DQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAOapobQkNYCMP+Y33JcGo90Soe9Y # /WWojr4bKHbLNBzKqZ6cku2uCxhMF1Ln6xuI4ATdZvm4O7GqvplG9nF1ad5t2Lus # 5SLs45AYnODP4aqPbPU/2NGDRpfnceF+XhKeiYBwoIwrPZ04b8bfTpckj/tvenB9 # P8/9hAjWK97xv7+qsIz4lMMaCuWZgi8RlP6XVxsb+jYrHGA1UdHZEpunEFLaO9Ss # OPqatPAL2LNGs/JVuGdq9p47GKzn+vl+ANd5zZ/TIP1ifX76vorqZ9l9a5mzi/HG # vq43v2Cj3jrzIQ7uTbxtiLlPQUqkRzPRtiwTV80JdtRE+M+gTf7bT1CTvG2L3scf # YKFk7S80M7NydxV/qL+l8blGGageCzJ8svju2Mo4BB+ALWr+gBmCGqrM8YKy/wXR # tbvdEvBOLsATcHX0maw9xRCDRle2jO+ndYkTKZ92AMH6a/WdDfL0HrAWloWWSg62 # TxmJ/QiX54ILQv2Tlh1Al+pjGHN2evxS8i+XoWcUdHPIOoQd37yjnMjCN593wDzj # XCEuDABYw9BbvfSp29G/uiDGtjttDXzeMRdVCJFgULV9suBVP7yFh9pK/mVpz+aC # L2PvqiGYR41xRBKqwrfJEdoluRsqDy6KD985EdXkTvdIFKv0B7MfbcBCiGUBcm1r # fLAbs8Q2lqvqM4bxAgMBAAGjggGpMIIBpTAfBgNVHSMEGDAWgBQPKssghyi47G9I # ritUpimqF6TNDDAdBgNVHQ4EFgQUL96+KAGrvUgJnXwdVnA/uy+RlEcwDgYDVR0P # AQH/BAQDAgeAMAwGA1UdEwEB/wQCMAAwEwYDVR0lBAwwCgYIKwYBBQUHAwMwSgYD # VR0gBEMwQTA1BgwrBgEEAbIxAQIBAwIwJTAjBggrBgEFBQcCARYXaHR0cHM6Ly9z # ZWN0aWdvLmNvbS9DUFMwCAYGZ4EMAQQBMEkGA1UdHwRCMEAwPqA8oDqGOGh0dHA6 # Ly9jcmwuc2VjdGlnby5jb20vU2VjdGlnb1B1YmxpY0NvZGVTaWduaW5nQ0FSMzYu # Y3JsMHkGCCsGAQUFBwEBBG0wazBEBggrBgEFBQcwAoY4aHR0cDovL2NydC5zZWN0 # aWdvLmNvbS9TZWN0aWdvUHVibGljQ29kZVNpZ25pbmdDQVIzNi5jcnQwIwYIKwYB # BQUHMAGGF2h0dHA6Ly9vY3NwLnNlY3RpZ28uY29tMB4GA1UdEQQXMBWBE3N1cHBv # cnRAc2VwcG1haWwuY2gwDQYJKoZIhvcNAQEMBQADggGBAHnWpS4Jw/QiiLQi2EYv # THCtwKsj7O3G7wAN7wijSJcWF7iCx6AoCuCIgGdWiQuEZcv9pIUrXQ6jOSRHsDNX # SvIhCK9JakZJSseW/SCb1rvxZ4d0n2jm2SdkWf5j7+W+X4JHeCF9ZOw0ULpe5pFs # IGTh8bmTtUr3yA11yw4vHfXFwin7WbEoTLVKiL0ZUN0Qk+yBniPPSRRlUZIX8P4e # iXuw7lh9CMaS3HWRKkK89w//18PjUMxhTZJ6dszN2TAfwu1zxdG/RQqvxXUTTAxU # JrrCuvowtnDQ55yXMxkkSxWUwLxk76WvXwmohRdsavsGJJ9+yxj5JKOd+HIZ1fZ7 # oi0VhyOqFQAnjNbwR/TqPjRxZKjCNLXSM5YSMZKAhqrJssGLINZ2qDK/CEcVDkBS # 6Hke4jWMczny8nB8+ATJ84MB7tfSoXE7R0FMs1dinuvjVWIyg6klHigpeEiAaSaG # 5KF7vk+OlquA+x4ohPuWdtFxobOT2OgHQnK4bJitb9aDazGCAxowggMWAgEBMGgw # VDELMAkGA1UEBhMCR0IxGDAWBgNVBAoTD1NlY3RpZ28gTGltaXRlZDErMCkGA1UE # AxMiU2VjdGlnbyBQdWJsaWMgQ29kZSBTaWduaW5nIENBIFIzNgIQDHCZR3nkTLyV # eD44b8q62zANBglghkgBZQMEAgEFAKCBhDAYBgorBgEEAYI3AgEMMQowCKACgACh # AoAAMBkGCSqGSIb3DQEJAzEMBgorBgEEAYI3AgEEMBwGCisGAQQBgjcCAQsxDjAM # BgorBgEEAYI3AgEVMC8GCSqGSIb3DQEJBDEiBCCB/FAr3ZViOr74a8jAWaPuI+gn # dt/mFZ3Viaqka8kiMzANBgkqhkiG9w0BAQEFAASCAgB0NMhqB4Wh87Woal8bpJy/ # 6XHS4siHyT6JzWmDqtg1wilTTPGhasWCcJhUz8LFZIJKEW3VCiTKK4VpEgqQDMsx # PJKvcWvF7M0+g8LDAzo/5/PTljoUz8vGpSs8jRdrYB6CfmUZdybCCDi1Yim3Mfyl # xSnoxuH0S5CpHcT8I7PHAPtPyIfIFMLlTTNzQq1TbIOHOtPqjV+vGbFtvcdZRdY9 # Be4Rly9YnKPuOt5Zd3qcE9VOjdmQ9cXsTNWzE5rawPyHjbszlvXlx9nD6XBFcglk # fujHAHPr3AUaIWIIBa1Fq42qVuFIBXzH5ELuTuy/18w3i+Q8RoAeL0g7evpYJNVO # /RG9RbfL9jQYuTFu/Fe2Yj9Ydri4oAi3e7Gs+kdxW6e6O6kk9MVB/o1i1dck5m6D # cNSA2MSlZigLRxYJgazijkcFlNuAmf1DbB0M9Gd84ktSK+o0vksCo4wWVW7FJmo9 # hMboEAHdo5lWGpQ/XQKnUf+/aLG/OL+JdbMjLHjt05tHShAL6TvlsQHQwd0W3bjO # wE0N5nTxIWr8e6Slcsg2hctls6buYOZKei7CqJ3j1uXM31YCeTkVTxcxuTNqAT6A # v09uquzPv3BRGUvkYbYLEW3bpECKC3r0lN89/x+tlTDrzeMUmbzZmgSCXYIuZkWx # eEWJhF+nclJB1i0rKpjJ0Q== # SIG # End signature block |