functions/Get-DbaNetworkConfiguration.ps1
function Get-DbaNetworkConfiguration { <# .SYNOPSIS Returns the network configuration of a SQL Server instance as shown in SQL Server Configuration Manager. .DESCRIPTION Returns a PowerShell object with the network configuration of a SQL Server instance as shown in SQL Server Configuration Manager. As we get information from SQL WMI and also from the registry, we use PS Remoting to run the core code on the target machine. For a detailed explanation of the different properties see the documentation at: https://docs.microsoft.com/en-us/sql/tools/configuration-manager/sql-server-network-configuration .PARAMETER SqlInstance The target SQL Server instance or instances. .PARAMETER Credential Credential object used to connect to the Computer as a different user. .PARAMETER OutputType Defines what information is returned from the command. Options include: Full, ServerProtocols, TcpIpProperties, TcpIpAddresses or Certificate. Full by default. Full returns one object per SqlInstance with information about the server protocols and nested objects with information about TCP/IP properties and TCP/IP addresses. It also outputs advanced properties including information about the used certificate. ServerProtocols returns one object per SqlInstance with information about the server protocols only. TcpIpProperties returns one object per SqlInstance with information about the TCP/IP protocol properties only. TcpIpAddresses returns one object per SqlInstance and IP address. If the instance listens on all IP addresses (TcpIpProperties.ListenAll), only the information about the IPAll address is returned. Otherwise only information about the individual IP addresses is returned. For more details see: https://docs.microsoft.com/en-us/sql/database-engine/configure-windows/configure-a-server-to-listen-on-a-specific-tcp-port Certificate returns one object per SqlInstance with information about the configured network certificate and whether encryption is enforced. .PARAMETER EnableException By default, when something goes wrong we try to catch it, interpret it and give you a friendly warning message. This avoids overwhelming you with "sea of red" exceptions, but is inconvenient because it basically disables advanced scripting. Using this switch turns this "nice by default" feature off and enables you to catch exceptions with your own try/catch. .NOTES Tags: Connection, SQLWMI Author: Andreas Jordan (@JordanOrdix), ordix.de Website: https://dbatools.io Copyright: (c) 2021 by dbatools, licensed under MIT License: MIT https://opensource.org/licenses/MIT .LINK https://dbatools.io/Get-DbaNetworkConfiguration .EXAMPLE PS C:\> Get-DbaNetworkConfiguration -SqlInstance sqlserver2014a Returns the network configuration for the default instance on sqlserver2014a. .EXAMPLE PS C:\> Get-DbaNetworkConfiguration -SqlInstance winserver\sqlexpress, sql2016 -OutputType ServerProtocols Returns information about the server protocols for the sqlexpress on winserver and the default instance on sql2016. #> [CmdletBinding()] param ( [parameter(Mandatory, ValueFromPipeline)] [DbaInstanceParameter[]]$SqlInstance, [PSCredential]$Credential, [ValidateSet('Full', 'ServerProtocols', 'TcpIpProperties', 'TcpIpAddresses', 'Certificate')] [string]$OutputType = 'Full', [switch]$EnableException ) begin { $scriptBlock = { # This scriptblock will be processed by Invoke-Command2 on the target machine. # We take an object as the first parameter which has to include the properties ComputerName, InstanceName and SqlFullName, # so normally a DbaInstanceParameter. $instance = $args[0] $verbose = @( ) # As we go remote, ensure the assembly is loaded [void][System.Reflection.Assembly]::LoadWithPartialName('Microsoft.SqlServer.SqlWmiManagement') $wmi = New-Object Microsoft.SqlServer.Management.Smo.Wmi.ManagedComputer $null = $wmi.Initialize() $wmiServerProtocols = ($wmi.ServerInstances | Where-Object { $_.Name -eq $instance.InstanceName } ).ServerProtocols $wmiSpSm = $wmiServerProtocols | Where-Object { $_.Name -eq 'Sm' } $wmiSpNp = $wmiServerProtocols | Where-Object { $_.Name -eq 'Np' } $wmiSpTcp = $wmiServerProtocols | Where-Object { $_.Name -eq 'Tcp' } $outputTcpIpProperties = [PSCustomObject]@{ Enabled = ($wmiSpTcp.ProtocolProperties | Where-Object { $_.Name -eq 'Enabled' } ).Value KeepAlive = ($wmiSpTcp.ProtocolProperties | Where-Object { $_.Name -eq 'KeepAlive' } ).Value ListenAll = ($wmiSpTcp.ProtocolProperties | Where-Object { $_.Name -eq 'ListenOnAllIPs' } ).Value } $wmiIPn = $wmiSpTcp.IPAddresses | Where-Object { $_.Name -ne 'IPAll' } $outputTcpIpAddressesIPn = foreach ($ip in $wmiIPn) { [PSCustomObject]@{ Name = $ip.Name Active = ($ip.IPAddressProperties | Where-Object { $_.Name -eq 'Active' } ).Value Enabled = ($ip.IPAddressProperties | Where-Object { $_.Name -eq 'Enabled' } ).Value IpAddress = ($ip.IPAddressProperties | Where-Object { $_.Name -eq 'IpAddress' } ).Value TcpDynamicPorts = ($ip.IPAddressProperties | Where-Object { $_.Name -eq 'TcpDynamicPorts' } ).Value TcpPort = ($ip.IPAddressProperties | Where-Object { $_.Name -eq 'TcpPort' } ).Value } } $wmiIPAll = $wmiSpTcp.IPAddresses | Where-Object { $_.Name -eq 'IPAll' } $outputTcpIpAddressesIPAll = [PSCustomObject]@{ Name = $wmiIPAll.Name TcpDynamicPorts = ($wmiIPAll.IPAddressProperties | Where-Object { $_.Name -eq 'TcpDynamicPorts' } ).Value TcpPort = ($wmiIPAll.IPAddressProperties | Where-Object { $_.Name -eq 'TcpPort' } ).Value } $wmiService = $wmi.Services | Where-Object { $_.DisplayName -eq "SQL Server ($($instance.InstanceName))" } $serviceAccount = $wmiService.ServiceAccount $regRoot = ($wmiService.AdvancedProperties | Where-Object Name -eq REGROOT).Value $vsname = ($wmiService.AdvancedProperties | Where-Object Name -eq VSNAME).Value $verbose += "regRoot = '$regRoot' / vsname = '$vsname'" if ([System.String]::IsNullOrEmpty($regRoot)) { $regRoot = $wmiService.AdvancedProperties | Where-Object { $_ -match 'REGROOT' } $vsname = $wmiService.AdvancedProperties | Where-Object { $_ -match 'VSNAME' } $verbose += "regRoot = '$regRoot' / vsname = '$vsname'" if (![System.String]::IsNullOrEmpty($regRoot)) { $regRoot = ($regRoot -Split 'Value\=')[1] $vsname = ($vsname -Split 'Value\=')[1] $verbose += "regRoot = '$regRoot' / vsname = '$vsname'" } else { $verbose += "Can't find regRoot" } } if ($regRoot) { $regPath = "Registry::HKEY_LOCAL_MACHINE\$regRoot\MSSQLServer\SuperSocketNetLib" try { $acceptedSPNs = (Get-ItemProperty -Path $regPath -Name AcceptedSPNs).AcceptedSPNs $thumbprint = (Get-ItemProperty -Path $regPath -Name Certificate).Certificate $cert = Get-ChildItem Cert:\LocalMachine -Recurse -ErrorAction SilentlyContinue | Where-Object Thumbprint -eq $thumbprint | Select-Object -First 1 $extendedProtection = switch ((Get-ItemProperty -Path $regPath -Name ExtendedProtection).ExtendedProtection) { 0 { $false } 1 { $true } } $forceEncryption = switch ((Get-ItemProperty -Path $regPath -Name ForceEncryption).ForceEncryption) { 0 { $false } 1 { $true } } $hideInstance = switch ((Get-ItemProperty -Path $regPath -Name HideInstance).HideInstance) { 0 { $false } 1 { $true } } $outputCertificate = [PSCustomObject]@{ VSName = $vsname ServiceAccount = $serviceAccount ForceEncryption = $forceEncryption FriendlyName = $cert.FriendlyName DnsNameList = $cert.DnsNameList Thumbprint = $cert.Thumbprint Generated = $cert.NotBefore Expires = $cert.NotAfter IssuedTo = $cert.Subject IssuedBy = $cert.Issuer Certificate = $cert } $outputAdvanced = [PSCustomObject]@{ ForceEncryption = $forceEncryption HideInstance = $hideInstance AcceptedSPNs = $acceptedSPNs ExtendedProtection = $extendedProtection } } catch { $outputCertificate = $outputAdvanced = "Failed to get information from registry: $_" } } else { $outputCertificate = $outputAdvanced = "Failed to get information from registry: Path not found" } [PSCustomObject]@{ ComputerName = $instance.ComputerName InstanceName = $instance.InstanceName SqlInstance = $instance.SqlFullName.Trim('[]') SharedMemoryEnabled = $wmiSpSm.IsEnabled NamedPipesEnabled = $wmiSpNp.IsEnabled TcpIpEnabled = $wmiSpTcp.IsEnabled TcpIpProperties = $outputTcpIpProperties TcpIpAddresses = $outputTcpIpAddressesIPn + $outputTcpIpAddressesIPAll Certificate = $outputCertificate Advanced = $outputAdvanced Verbose = $verbose } } } process { foreach ($instance in $SqlInstance) { try { $computerName = Resolve-DbaComputerName -ComputerName $instance.ComputerName -Credential $Credential $null = Test-ElevationRequirement -ComputerName $computerName -EnableException $true $netConf = Invoke-Command2 -ScriptBlock $scriptBlock -ArgumentList $instance -ComputerName $computerName -Credential $Credential -ErrorAction Stop foreach ($verbose in $netConf.Verbose) { Write-Message -Level Verbose -Message $verbose } # Test if object is filled to test if instance was found on computer if ($null -eq $netConf.SharedMemoryEnabled) { Stop-Function -Message "Failed to collect network configuration from $($instance.ComputerName) for instance $($instance.InstanceName). No data was found for this instance, so skipping." -Target $instance -ErrorRecord $_ -Continue } if ($OutputType -eq 'Full') { [PSCustomObject]@{ ComputerName = $netConf.ComputerName InstanceName = $netConf.InstanceName SqlInstance = $netConf.SqlInstance SharedMemoryEnabled = $netConf.SharedMemoryEnabled NamedPipesEnabled = $netConf.NamedPipesEnabled TcpIpEnabled = $netConf.TcpIpEnabled TcpIpProperties = $netConf.TcpIpProperties TcpIpAddresses = $netConf.TcpIpAddresses Certificate = $netConf.Certificate Advanced = $netConf.Advanced } } elseif ($OutputType -eq 'ServerProtocols') { [PSCustomObject]@{ ComputerName = $netConf.ComputerName InstanceName = $netConf.InstanceName SqlInstance = $netConf.SqlInstance SharedMemoryEnabled = $netConf.SharedMemoryEnabled NamedPipesEnabled = $netConf.NamedPipesEnabled TcpIpEnabled = $netConf.TcpIpEnabled } } elseif ($OutputType -eq 'TcpIpProperties') { [PSCustomObject]@{ ComputerName = $netConf.ComputerName InstanceName = $netConf.InstanceName SqlInstance = $netConf.SqlInstance Enabled = $netConf.TcpIpProperties.Enabled KeepAlive = $netConf.TcpIpProperties.KeepAlive ListenAll = $netConf.TcpIpProperties.ListenAll } } elseif ($OutputType -eq 'TcpIpAddresses') { if ($netConf.TcpIpProperties.ListenAll) { $ipConf = $netConf.TcpIpAddresses | Where-Object { $_.Name -eq 'IPAll' } [PSCustomObject]@{ ComputerName = $netConf.ComputerName InstanceName = $netConf.InstanceName SqlInstance = $netConf.SqlInstance Name = $ipConf.Name TcpDynamicPorts = $ipConf.TcpDynamicPorts TcpPort = $ipConf.TcpPort } } else { $ipConf = $netConf.TcpIpAddresses | Where-Object { $_.Name -ne 'IPAll' } foreach ($ip in $ipConf) { [PSCustomObject]@{ ComputerName = $netConf.ComputerName InstanceName = $netConf.InstanceName SqlInstance = $netConf.SqlInstance Name = $ip.Name Active = $ip.Active Enabled = $ip.Enabled IpAddress = $ip.IpAddress TcpDynamicPorts = $ip.TcpDynamicPorts TcpPort = $ip.TcpPort } } } } elseif ($OutputType -eq 'Certificate') { if ($netConf.Certificate -like 'Failed*') { Stop-Function -Message "Failed to collect certificate information from $($instance.ComputerName) for instance $($instance.InstanceName): $($netConf.Certificate)" -Target $instance -Continue } $output = [PSCustomObject]@{ ComputerName = $netConf.ComputerName InstanceName = $netConf.InstanceName SqlInstance = $netConf.SqlInstance VSName = $netConf.Certificate.VSName ServiceAccount = $netConf.Certificate.ServiceAccount ForceEncryption = $netConf.Certificate.ForceEncryption FriendlyName = $netConf.Certificate.FriendlyName DnsNameList = $netConf.Certificate.DnsNameList Thumbprint = $netConf.Certificate.Thumbprint Generated = $netConf.Certificate.Generated Expires = $netConf.Certificate.Expires IssuedTo = $netConf.Certificate.IssuedTo IssuedBy = $netConf.Certificate.IssuedBy Certificate = $netConf.Certificate.Certificate } $defaultView = 'ComputerName,InstanceName,SqlInstance,VSName,ServiceAccount,ForceEncryption,FriendlyName,DnsNameList,Thumbprint,Generated,Expires,IssuedTo,IssuedBy'.Split(',') if (-not $netConf.Certificate.VSName) { $defaultView = $defaultView | Where-Object { $_ -ne 'VSNAME' } } $output | Select-DefaultView -Property $defaultView } } catch { Stop-Function -Message "Failed to collect network configuration from $($instance.ComputerName) for instance $($instance.InstanceName)." -Target $instance -ErrorRecord $_ -Continue } } } } # SIG # Begin signature block # MIIZewYJKoZIhvcNAQcCoIIZbDCCGWgCAQExCzAJBgUrDgMCGgUAMGkGCisGAQQB # gjcCAQSgWzBZMDQGCisGAQQBgjcCAR4wJgIDAQAABBAfzDtgWUsITrck0sYpfvNR # AgEAAgEAAgEAAgEAAgEAMCEwCQYFKw4DAhoFAAQUUDYYJy9nuyw0Aels14Qc50rP # TDugghSJMIIE/jCCA+agAwIBAgIQDUJK4L46iP9gQCHOFADw3TANBgkqhkiG9w0B # AQsFADByMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYD # VQQLExB3d3cuZGlnaWNlcnQuY29tMTEwLwYDVQQDEyhEaWdpQ2VydCBTSEEyIEFz # c3VyZWQgSUQgVGltZXN0YW1waW5nIENBMB4XDTIxMDEwMTAwMDAwMFoXDTMxMDEw # NjAwMDAwMFowSDELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDkRpZ2lDZXJ0LCBJbmMu # MSAwHgYDVQQDExdEaWdpQ2VydCBUaW1lc3RhbXAgMjAyMTCCASIwDQYJKoZIhvcN # AQEBBQADggEPADCCAQoCggEBAMLmYYRnxYr1DQikRcpja1HXOhFCvQp1dU2UtAxQ # tSYQ/h3Ib5FrDJbnGlxI70Tlv5thzRWRYlq4/2cLnGP9NmqB+in43Stwhd4CGPN4 # bbx9+cdtCT2+anaH6Yq9+IRdHnbJ5MZ2djpT0dHTWjaPxqPhLxs6t2HWc+xObTOK # fF1FLUuxUOZBOjdWhtyTI433UCXoZObd048vV7WHIOsOjizVI9r0TXhG4wODMSlK # XAwxikqMiMX3MFr5FK8VX2xDSQn9JiNT9o1j6BqrW7EdMMKbaYK02/xWVLwfoYer # vnpbCiAvSwnJlaeNsvrWY4tOpXIc7p96AXP4Gdb+DUmEvQECAwEAAaOCAbgwggG0 # MA4GA1UdDwEB/wQEAwIHgDAMBgNVHRMBAf8EAjAAMBYGA1UdJQEB/wQMMAoGCCsG # AQUFBwMIMEEGA1UdIAQ6MDgwNgYJYIZIAYb9bAcBMCkwJwYIKwYBBQUHAgEWG2h0 # dHA6Ly93d3cuZGlnaWNlcnQuY29tL0NQUzAfBgNVHSMEGDAWgBT0tuEgHf4prtLk # YaWyoiWyyBc1bjAdBgNVHQ4EFgQUNkSGjqS6sGa+vCgtHUQ23eNqerwwcQYDVR0f # BGowaDAyoDCgLoYsaHR0cDovL2NybDMuZGlnaWNlcnQuY29tL3NoYTItYXNzdXJl # ZC10cy5jcmwwMqAwoC6GLGh0dHA6Ly9jcmw0LmRpZ2ljZXJ0LmNvbS9zaGEyLWFz # c3VyZWQtdHMuY3JsMIGFBggrBgEFBQcBAQR5MHcwJAYIKwYBBQUHMAGGGGh0dHA6 # Ly9vY3NwLmRpZ2ljZXJ0LmNvbTBPBggrBgEFBQcwAoZDaHR0cDovL2NhY2VydHMu # ZGlnaWNlcnQuY29tL0RpZ2lDZXJ0U0hBMkFzc3VyZWRJRFRpbWVzdGFtcGluZ0NB # LmNydDANBgkqhkiG9w0BAQsFAAOCAQEASBzctemaI7znGucgDo5nRv1CclF0CiNH # o6uS0iXEcFm+FKDlJ4GlTRQVGQd58NEEw4bZO73+RAJmTe1ppA/2uHDPYuj1UUp4 # eTZ6J7fz51Kfk6ftQ55757TdQSKJ+4eiRgNO/PT+t2R3Y18jUmmDgvoaU+2QzI2h # F3MN9PNlOXBL85zWenvaDLw9MtAby/Vh/HUIAHa8gQ74wOFcz8QRcucbZEnYIpp1 # FUL1LTI4gdr0YKK6tFL7XOBhJCVPst/JKahzQ1HavWPWH1ub9y4bTxMd90oNcX6X # t/Q/hOvB46NJofrOp79Wz7pZdmGJX36ntI5nePk2mOHLKNpbh6aKLzCCBRowggQC # oAMCAQICEAMFu4YhsKFjX7/erhIE520wDQYJKoZIhvcNAQELBQAwcjELMAkGA1UE # BhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3LmRpZ2lj # ZXJ0LmNvbTExMC8GA1UEAxMoRGlnaUNlcnQgU0hBMiBBc3N1cmVkIElEIENvZGUg # U2lnbmluZyBDQTAeFw0yMDA1MTIwMDAwMDBaFw0yMzA2MDgxMjAwMDBaMFcxCzAJ # BgNVBAYTAlVTMREwDwYDVQQIEwhWaXJnaW5pYTEPMA0GA1UEBxMGVmllbm5hMREw # DwYDVQQKEwhkYmF0b29sczERMA8GA1UEAxMIZGJhdG9vbHMwggEiMA0GCSqGSIb3 # DQEBAQUAA4IBDwAwggEKAoIBAQC8v2N7q+O/vggBtpjmteofFo140k73JXQ5sOD6 # QLzjgija+scoYPxTmFSImnqtjfZFWmucAWsDiMVVro/6yGjsXmJJUA7oD5BlMdAK # fuiq4558YBOjjc0Bp3NbY5ZGujdCmsw9lqHRAVil6P1ZpAv3D/TyVVq6AjDsJY+x # rRL9iMc8YpD5tiAj+SsRSuT5qwPuW83ByRHqkaJ5YDJ/R82ZKh69AFNXoJ3xCJR+ # P7+pa8tbdSgRf25w4ZfYPy9InEvsnIRVZMeDjjuGvqr0/Mar73UI79z0NYW80yN/ # 7VzlrvV8RnniHWY2ib9ehZligp5aEqdV2/XFVPV4SKaJs8R9AgMBAAGjggHFMIIB # wTAfBgNVHSMEGDAWgBRaxLl7KgqjpepxA8Bg+S32ZXUOWDAdBgNVHQ4EFgQU8MCg # +7YDgENO+wnX3d96scvjniIwDgYDVR0PAQH/BAQDAgeAMBMGA1UdJQQMMAoGCCsG # AQUFBwMDMHcGA1UdHwRwMG4wNaAzoDGGL2h0dHA6Ly9jcmwzLmRpZ2ljZXJ0LmNv # bS9zaGEyLWFzc3VyZWQtY3MtZzEuY3JsMDWgM6Axhi9odHRwOi8vY3JsNC5kaWdp # Y2VydC5jb20vc2hhMi1hc3N1cmVkLWNzLWcxLmNybDBMBgNVHSAERTBDMDcGCWCG # SAGG/WwDATAqMCgGCCsGAQUFBwIBFhxodHRwczovL3d3dy5kaWdpY2VydC5jb20v # Q1BTMAgGBmeBDAEEATCBhAYIKwYBBQUHAQEEeDB2MCQGCCsGAQUFBzABhhhodHRw # Oi8vb2NzcC5kaWdpY2VydC5jb20wTgYIKwYBBQUHMAKGQmh0dHA6Ly9jYWNlcnRz # LmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydFNIQTJBc3N1cmVkSURDb2RlU2lnbmluZ0NB # LmNydDAMBgNVHRMBAf8EAjAAMA0GCSqGSIb3DQEBCwUAA4IBAQCPzflwlQwf1jak # EqymPOc0nBxiY7F4FwcmL7IrTLhub6Pjg4ZYfiC79Akz5aNlqO+TJ0kqglkfnOsc # jfKQzzDwcZthLVZl83igzCLnWMo8Zk/D2d4ZLY9esFwqPNvuuVDrHvgh7H6DJ/zP # Vm5EOK0sljT0UQ6HQEwtouH5S8nrqCGZ8jKM/+DeJlm+rCAGGf7TV85uqsAn5JqD # En/bXE1AlyG1Q5YiXFGS5Sf0qS4Nisw7vRrZ6Qc4NwBty4cAYjzDPDixorWI8+FV # OUWKMdL7tV8i393/XykwsccCstBCp7VnSZN+4vgzjEJQql5uQfysjcW9rrb/qixp # csPTKYRHMIIFMDCCBBigAwIBAgIQBAkYG1/Vu2Z1U0O1b5VQCDANBgkqhkiG9w0B # AQsFADBlMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYD # VQQLExB3d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVk # IElEIFJvb3QgQ0EwHhcNMTMxMDIyMTIwMDAwWhcNMjgxMDIyMTIwMDAwWjByMQsw # CQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cu # ZGlnaWNlcnQuY29tMTEwLwYDVQQDEyhEaWdpQ2VydCBTSEEyIEFzc3VyZWQgSUQg # Q29kZSBTaWduaW5nIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA # +NOzHH8OEa9ndwfTCzFJGc/Q+0WZsTrbRPV/5aid2zLXcep2nQUut4/6kkPApfmJ # 1DcZ17aq8JyGpdglrA55KDp+6dFn08b7KSfH03sjlOSRI5aQd4L5oYQjZhJUM1B0 # sSgmuyRpwsJS8hRniolF1C2ho+mILCCVrhxKhwjfDPXiTWAYvqrEsq5wMWYzcT6s # cKKrzn/pfMuSoeU7MRzP6vIK5Fe7SrXpdOYr/mzLfnQ5Ng2Q7+S1TqSp6moKq4Tz # rGdOtcT3jNEgJSPrCGQ+UpbB8g8S9MWOD8Gi6CxR93O8vYWxYoNzQYIH5DiLanMg # 0A9kczyen6Yzqf0Z3yWT0QIDAQABo4IBzTCCAckwEgYDVR0TAQH/BAgwBgEB/wIB # ADAOBgNVHQ8BAf8EBAMCAYYwEwYDVR0lBAwwCgYIKwYBBQUHAwMweQYIKwYBBQUH # AQEEbTBrMCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdpY2VydC5jb20wQwYI # KwYBBQUHMAKGN2h0dHA6Ly9jYWNlcnRzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydEFz # c3VyZWRJRFJvb3RDQS5jcnQwgYEGA1UdHwR6MHgwOqA4oDaGNGh0dHA6Ly9jcmw0 # LmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydEFzc3VyZWRJRFJvb3RDQS5jcmwwOqA4oDaG # NGh0dHA6Ly9jcmwzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydEFzc3VyZWRJRFJvb3RD # QS5jcmwwTwYDVR0gBEgwRjA4BgpghkgBhv1sAAIEMCowKAYIKwYBBQUHAgEWHGh0 # dHBzOi8vd3d3LmRpZ2ljZXJ0LmNvbS9DUFMwCgYIYIZIAYb9bAMwHQYDVR0OBBYE # FFrEuXsqCqOl6nEDwGD5LfZldQ5YMB8GA1UdIwQYMBaAFEXroq/0ksuCMS1Ri6en # IZ3zbcgPMA0GCSqGSIb3DQEBCwUAA4IBAQA+7A1aJLPzItEVyCx8JSl2qB1dHC06 # GsTvMGHXfgtg/cM9D8Svi/3vKt8gVTew4fbRknUPUbRupY5a4l4kgU4QpO4/cY5j # DhNLrddfRHnzNhQGivecRk5c/5CxGwcOkRX7uq+1UcKNJK4kxscnKqEpKBo6cSgC # PC6Ro8AlEeKcFEehemhor5unXCBc2XGxDI+7qPjFEmifz0DLQESlE/DmZAwlCEIy # sjaKJAL+L3J+HNdJRZboWR3p+nRka7LrZkPas7CM1ekN3fYBIM6ZMWM9CBoYs4Gb # T8aTEAb8B4H6i9r5gkn3Ym6hU/oSlBiFLpKR6mhsRDKyZqHnGKSaZFHvMIIFMTCC # BBmgAwIBAgIQCqEl1tYyG35B5AXaNpfCFTANBgkqhkiG9w0BAQsFADBlMQswCQYD # VQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGln # aWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgQ0Ew # HhcNMTYwMTA3MTIwMDAwWhcNMzEwMTA3MTIwMDAwWjByMQswCQYDVQQGEwJVUzEV # MBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29t # MTEwLwYDVQQDEyhEaWdpQ2VydCBTSEEyIEFzc3VyZWQgSUQgVGltZXN0YW1waW5n # IENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvdAy7kvNj3/dqbqC # mcU5VChXtiNKxA4HRTNREH3Q+X1NaH7ntqD0jbOI5Je/YyGQmL8TvFfTw+F+CNZq # FAA49y4eO+7MpvYyWf5fZT/gm+vjRkcGGlV+Cyd+wKL1oODeIj8O/36V+/OjuiI+ # GKwR5PCZA207hXwJ0+5dyJoLVOOoCXFr4M8iEA91z3FyTgqt30A6XLdR4aF5FMZN # JCMwXbzsPGBqrC8HzP3w6kfZiFBe/WZuVmEnKYmEUeaC50ZQ/ZQqLKfkdT66mA+E # f58xFNat1fJky3seBdCEGXIX8RcG7z3N1k3vBkL9olMqT4UdxB08r8/arBD13ays # 6Vb/kwIDAQABo4IBzjCCAcowHQYDVR0OBBYEFPS24SAd/imu0uRhpbKiJbLIFzVu # MB8GA1UdIwQYMBaAFEXroq/0ksuCMS1Ri6enIZ3zbcgPMBIGA1UdEwEB/wQIMAYB # Af8CAQAwDgYDVR0PAQH/BAQDAgGGMBMGA1UdJQQMMAoGCCsGAQUFBwMIMHkGCCsG # AQUFBwEBBG0wazAkBggrBgEFBQcwAYYYaHR0cDovL29jc3AuZGlnaWNlcnQuY29t # MEMGCCsGAQUFBzAChjdodHRwOi8vY2FjZXJ0cy5kaWdpY2VydC5jb20vRGlnaUNl # cnRBc3N1cmVkSURSb290Q0EuY3J0MIGBBgNVHR8EejB4MDqgOKA2hjRodHRwOi8v # Y3JsNC5kaWdpY2VydC5jb20vRGlnaUNlcnRBc3N1cmVkSURSb290Q0EuY3JsMDqg # OKA2hjRodHRwOi8vY3JsMy5kaWdpY2VydC5jb20vRGlnaUNlcnRBc3N1cmVkSURS # b290Q0EuY3JsMFAGA1UdIARJMEcwOAYKYIZIAYb9bAACBDAqMCgGCCsGAQUFBwIB # FhxodHRwczovL3d3dy5kaWdpY2VydC5jb20vQ1BTMAsGCWCGSAGG/WwHATANBgkq # hkiG9w0BAQsFAAOCAQEAcZUS6VGHVmnN793afKpjerN4zwY3QITvS4S/ys8DAv3F # p8MOIEIsr3fzKx8MIVoqtwU0HWqumfgnoma/Capg33akOpMP+LLR2HwZYuhegiUe # xLoceywh4tZbLBQ1QwRostt1AuByx5jWPGTlH0gQGF+JOGFNYkYkh2OMkVIsrymJ # 5Xgf1gsUpYDXEkdws3XVk4WTfraSZ/tTYYmo9WuWwPRYaQ18yAGxuSh1t5ljhSKM # Ycp5lH5Z/IwP42+1ASa2bKXuh1Eh5Fhgm7oMLSttosR+u8QlK0cCCHxJrhO24XxC # QijGGFbPQTS2Zl22dHv1VjMiLyI2skuiSpXY9aaOUjGCBFwwggRYAgEBMIGGMHIx # CzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3 # dy5kaWdpY2VydC5jb20xMTAvBgNVBAMTKERpZ2lDZXJ0IFNIQTIgQXNzdXJlZCBJ # RCBDb2RlIFNpZ25pbmcgQ0ECEAMFu4YhsKFjX7/erhIE520wCQYFKw4DAhoFAKB4 # MBgGCisGAQQBgjcCAQwxCjAIoAKAAKECgAAwGQYJKoZIhvcNAQkDMQwGCisGAQQB # gjcCAQQwHAYKKwYBBAGCNwIBCzEOMAwGCisGAQQBgjcCARUwIwYJKoZIhvcNAQkE # MRYEFHruYZvQDzaHio/eJfx/1hS0MgceMA0GCSqGSIb3DQEBAQUABIIBAIwe7M7M # JEpq7sYm4NmH6C8jRIl2TbbCV7ATzYhx+RkPC2mxyj+1HSSU9QOEzbyfrvTYirUl # D0ZHb/cP6lXbmkYOXqOqXxQoFaPwzICZR4judzYEA8effFsPomRYG1tuxVDGUKzt # o1VweesUVyiHJDs0jz7gy/xMvSVIqHZTovNvj1NAzBh+S5sS+zYOhCb4p08dWWXN # X2nanG25XfIg765vr838rOMNDieO6NV+eZgXIiyjCfNrtGZs5lsMD+ijGmIMqzoO # Fvbu50s1fNzmSDt822ExxT9nKsHDXtIcChR78yM8/1sBya8is4TUVtOzfyW/d1pB # GBR9hWXh0+zkngShggIwMIICLAYJKoZIhvcNAQkGMYICHTCCAhkCAQEwgYYwcjEL # MAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3 # LmRpZ2ljZXJ0LmNvbTExMC8GA1UEAxMoRGlnaUNlcnQgU0hBMiBBc3N1cmVkIElE # IFRpbWVzdGFtcGluZyBDQQIQDUJK4L46iP9gQCHOFADw3TANBglghkgBZQMEAgEF # AKBpMBgGCSqGSIb3DQEJAzELBgkqhkiG9w0BBwEwHAYJKoZIhvcNAQkFMQ8XDTIy # MDExNDE2MTQwMFowLwYJKoZIhvcNAQkEMSIEIJLQRX5m2zQ5H1roPQvlv6U1TMq8 # livFRj64ANOByxS0MA0GCSqGSIb3DQEBAQUABIIBAAl9obuY9Fvix6OILAPb1iNY # VGx2R3cop4QEhWN0FfKdK4KFOGuo+T+y60UnVJ2DlFTXUQuhySQMF+pM+L9zaChv # q4lRck/4Xes0WpKQOaAhwi0NXMJ9d6OjCL7ftZ0DgqYQ4+EWkisTfiyOphxSf7Mz # OUr6EYBLfDNwZmVmHta0jfuaZuzT48sIXepOxwM+FTRD9AWjaS+SVaBIriDBuZL7 # zhHETp4rnXqYW4XQtGWrYgYr+JSKYYc+t6+8SDS+dLrap2u8b4S5w2l+XMoAYCZV # NsIsZ3eakTqr9vQOXx43Erx8mJPgdUzPJywjpfYq6GBmTjWL4/tBr0KUlE9c/u8= # SIG # End signature block |