Public/SEPPmailAPI-Crypto.ps1
|
<#
.SYNOPSIS Lists public domain S/MIME and/or PGP keys across all domains. .DESCRIPTION Retrieves the public S/MIME certificates and/or PGP keys for all domains known to the SEPPmail appliance. The result can be returned either in full detail or - when -list is used - as a compact array of serial numbers / key IDs. This is a read-only query (HTTP GET on /crypto/domain) and supports filtering by cryptographic technology and certificate type. .PARAMETER list If $true, returns an array of serial numbers / key IDs instead of the full certificate/key details. Useful for fast inventory operations. Default: $false .PARAMETER limit Limits the number of returned entries. .PARAMETER technology Restricts the output to a single cryptographic technology. Valid values: 'both', 'smime', 'pgp'. Default: 'both' .PARAMETER onlyMetaData If $true, returns only the certificate/key metadata without the actual certificate or key material. Default: $false .PARAMETER public If $true, includes public S/MIME certificates in the result. .PARAMETER hin If $true, includes HIN (Health Info Net) S/MIME certificates in the result. .PARAMETER SMAHost SEPPmail API hostname. Defaults to the configured value. .PARAMETER SMAPort SEPPmail API port. Defaults to the configured value. .PARAMETER SMAVersion SEPPmail API version. Defaults to the configured value. .PARAMETER SMACred API credentials (PSCredential). Defaults to the configured value. .PARAMETER SMASkipCertCheck Skip SSL certificate validation. Use only in test environments. .OUTPUTS System.Management.Automation.PSCustomObject Returns the domain crypto objects, or - when -list is set - an array of serial numbers / key IDs. .NOTES - Requires an active SEPPmail API session (New-SMAConfiguration). - This is a read-only operation; -WhatIf shows the target URI only. .LINK Get-SMACryptoDomain .LINK Get-SMACryptoDomainKey .EXAMPLE PS C:\> Find-SMACryptoDomain Returns the full crypto details for all domains. May take some time. .EXAMPLE PS C:\> Find-SMACryptoDomain -list Returns only the serial numbers / key IDs of all domain keys. .EXAMPLE PS C:\> Find-SMACryptoDomain -technology smime -onlyMetaData $true Returns only the metadata of all S/MIME certificates, without the certificate material itself. #> function Find-SMACryptoDomain { [CmdletBinding( SupportsShouldProcess = $true )] param ( #region API params [Parameter( Mandatory = $false, HelpMessage = 'if true, return an array of serial keys instead of detailed information' )] [SMARestType('query')] [bool]$list, [Parameter( Mandatory = $false, HelpMessage = 'limit output to #' )] [SMARestType('query')] [int]$limit, [Parameter( Mandatory = $false, HelpMessage = 'limit output to both, smime of pgp' )] [ValidateSet('both','smime','pgp')] [SMARestType('query')] [string]$technology, [Parameter( Mandatory = $false, HelpMessage = 'Parameter to specify if only the certificates/keys metadate should be returned without the certificate' )] [SMARestType('query')] [bool]$onlyMetaData, [Parameter( Mandatory = $false, HelpMessage = 'Parameter to specify if public S/MIME certificate should be processed' )] [SMARestType('query')] [bool]$public, [Parameter( Mandatory = $false, HelpMessage = 'Parameter to specify if HIN S/MIME certificate should be processed' )] [SMARestType('query')] [bool]$hin, #endregion API params #region Config parameters block [Parameter(Mandatory = $false)] [String]$SMAHost = $Script:activeCfg.SMAHost, [Parameter(Mandatory = $false)] [int]$SMAPort = $Script:activeCfg.SMAPort, [Parameter(Mandatory = $false)] [String]$SMAVersion = $Script:activeCfg.SMAPIVersion, [Parameter(Mandatory=$false)] [System.Management.Automation.PSCredential]$SMACred=$Script:activeCfg.SMACred, [Parameter(Mandatory=$false)] [switch]$SMASkipCertCheck=$Script:activeCfg.SMAskipCertCheck #endregion ) begin { Write-verbose "Verifying required variables from SMA Config" if (! (verifyVars -VarList $Script:requiredVarList)) {Throw($missingVarsMessage)} # end if Write-verbose "Rest methdod is $restMethod" $RestMethod = 'GET' Write-Verbose "Creating URL base path" $uriPath = "{0}/{1}" -f 'crypto', 'domain' Write-Verbose "Adding SMA Params" $smaParams=@{ Host = $SMAHost Port = $SMAPort Version = $SMAVersion } } process { Write-Verbose "Getting parameter arrays for Body, Path and Query from $($myInvocation.Mycommand.Parameters.Values)" $paramArrays = Get-SMAParameterArray -ParentPSBoundParameters $PSBoundParameters -ParentInvocation $MyInvocation.MyCommand.Parameters.Values Write-Debug "ParamArrays: $($paramArrays | Out-String)" Write-verbose "Initializing REST-Data structures" [string]$uri = $null [hashtable]$bodyHt = @{} [hashtable]$queryParamHt = @{} Write-verbose "Adding optional path to basepath based on $($paramArrays.Path) parameters" if ($paramArrays.Path.Count -gt 0) { Foreach ($pathParam in $paramArrays.Path) { $uriPath = "{0}/{1}" -f $uriPath, $PSBoundParameters[$pathParam] } } Write-Debug "Final uri path is: $uriPath" Write-verbose "Building body HashTable based on $($paramArrays.Body) parameters" if ($paramArrays.Body.Count -gt 0) { Foreach ($bodyParam in $paramArrays.Body) { $bodyHt[$bodyParam] = $PSBoundParameters[$bodyParam] } } if ($paramArrays.password.Count -gt 0) { Foreach ($passwordParam in $paramArrays.password) { $secureString = $PSBoundParameters[$passwordParam] $plainText = ConvertFrom-SecureString $secureString -AsPlainText $bodyHt[$passwordParam] = $plainText } } $body = $bodyHt | ConvertTo-Json Write-Debug "Body JSON: $body" Write-verbose "Building query string based on $($paramArrays.Query) parameters" if ($paramArrays.Query.Count -gt 0) { Foreach ($queryArrayParam in $paramArrays.Query) { $queryParamHt[$queryArrayParam] = $PSBoundParameters[$queryArrayParam] } } Write-Debug "QueryParams: $($queryParamHt | Out-String)" #TODO: Clean this as parameter added $queryParamHt['list'] = $false Write-Verbose "Constructing full URI based on parameters" if ($queryParamHt) { $uri = New-SMAQueryString -uriPath $uriPath -qParam $queryParamHt @smaParams } else { $uri = New-SMAQueryString -uriPath $uriPath @smaParams } Write-Debug "Final URI: $uri" Write-verbose "Crafting Invokeparam for Invoke-SMARestMethod" $invokeParam = @{ Uri = $uri Method = $RestMethod Cred = $SMACred body = $body SkipCertCheck = $SMASkipCertCheck } Write-Debug "InvokeParam: $($invokeParam | Out-String)" # Prepare WhatIf message based on invokeParam $whatIfTarget = $invokeParam.Uri $whatIfAction = "$($invokeParam.Method) request" if ($invokeParam.body) { $whatIfAction += " with body: $($invokeParam.body)" } if ($PSCmdlet.ShouldProcess($whatIfTarget, $whatIfAction)) { Write-Verbose "Call Invoke-SMARestMethod $uri" $RestResult = Invoke-SMARestMethod @invokeParam #|select-object -ExpandProperty domain #Change based on response structure, e.g. if list=true then do domain else do domains or something like that # Return object if ($RestResult) { $returnData = Format-SMARestResult $RestResult -object return $returnData } else { Write-Information 'Nothing to return' } } else { Write-Verbose "WhatIf: Operation skipped by user" } } end { } } <# .SYNOPSIS Gets the private and public S/MIME and/or PGP keys of a single domain. .DESCRIPTION Retrieves all S/MIME certificates and/or PGP keys of the domain specified by -domainName. The result contains the full certificate/key details. Private key material is only included when a -password is supplied; the password is used to protect the exported private key. This is a read-only query (HTTP GET on /crypto/domain/{domainName}). .PARAMETER onlyMetadata If $true, returns only the certificate/key metadata without the actual certificate or key material. Default: $false .PARAMETER password SecureString password used to protect the exported PGP key or S/MIME private key. When omitted, only public key material is returned. Example: 'MyPassword123!' | ConvertTo-SecureString -AsPlainText -Force .PARAMETER domainName The domain name whose keys should be returned. This parameter is mandatory. .PARAMETER SMAHost SEPPmail API hostname. Defaults to the configured value. .PARAMETER SMAPort SEPPmail API port. Defaults to the configured value. .PARAMETER SMAVersion SEPPmail API version. Defaults to the configured value. .PARAMETER SMACred API credentials (PSCredential). Defaults to the configured value. .PARAMETER SMASkipCertCheck Skip SSL certificate validation. Use only in test environments. .OUTPUTS System.Management.Automation.PSCustomObject Returns the S/MIME certificates and/or PGP keys of the domain. .NOTES - Requires an active SEPPmail API session (New-SMAConfiguration). - Private keys are only included when -password is provided. .LINK Find-SMACryptoDomain .LINK Get-SMACryptoDomainKey .EXAMPLE PS C:\> Get-SMACryptoDomain -domainName 'contoso.com' Returns the public S/MIME certificates and PGP keys of 'contoso.com'. .EXAMPLE PS C:\> $pw = 'MyPassword123!' | ConvertTo-SecureString -AsPlainText -Force PS C:\> Get-SMACryptoDomain -domainName 'contoso.com' -password $pw Returns the keys of 'contoso.com' including the password-protected private key material. #> function Get-SMACryptoDomain { [CmdletBinding( SupportsShouldProcess = $true )] param ( #region API params [Parameter( Mandatory = $false, HelpMessage = 'Limit the number of results' )] [SMARestType('query')] [bool]$onlyMetadata, [Parameter( Mandatory = $false, HelpMessage = 'Password with which a PGP key or S/MIME private key will be protected' )] [SMAParamFilter('password')] [SMARestType('query')] [secureString]$password, [Parameter( Mandatory = $true, HelpMessage = 'limit output to a specific domain name.' )] [SMARestType('path')] [String]$domainName, #endregion API params #region Config parameters block [Parameter(Mandatory = $false)] [String]$SMAHost = $Script:activeCfg.SMAHost, [Parameter(Mandatory = $false)] [int]$SMAPort = $Script:activeCfg.SMAPort, [Parameter(Mandatory = $false)] [String]$SMAVersion = $Script:activeCfg.SMAPIVersion, [Parameter(Mandatory=$false)] [System.Management.Automation.PSCredential]$SMACred=$Script:activeCfg.SMACred, [Parameter(Mandatory=$false)] [switch]$SMASkipCertCheck=$Script:activeCfg.SMAskipCertCheck #endregion ) begin { Write-verbose "Verifying required variables from SMA Config" if (! (verifyVars -VarList $Script:requiredVarList)) {Throw($missingVarsMessage)} # end if Write-verbose "Rest methdod is $restMethod" $RestMethod = 'GET' Write-Verbose "Creating URL base path" $uriPath = "{0}/{1}" -f 'crypto', 'domain' Write-Verbose "Adding SMA Params" $smaParams=@{ Host = $SMAHost Port = $SMAPort Version = $SMAVersion } } process { Write-Verbose "Getting parameter arrays for Body, Path and Query from $($myInvocation.Mycommand.Parameters.Values)" $paramArrays = Get-SMAParameterArray -ParentPSBoundParameters $PSBoundParameters -ParentInvocation $MyInvocation.MyCommand.Parameters.Values Write-Debug "ParamArrays: $($paramArrays | Out-String)" Write-verbose "Initializing REST-Data structures" [string]$uri = $null [hashtable]$bodyHt = @{} [hashtable]$queryParamHt = @{} Write-verbose "Adding optional path to basepath based on $($paramArrays.Path) parameters" if ($paramArrays.Path.Count -gt 0) { Foreach ($pathParam in $paramArrays.Path) { $uriPath = "{0}/{1}" -f $uriPath, $PSBoundParameters[$pathParam] } } Write-Debug "Final uri path is: $uriPath" Write-verbose "Building body HashTable based on $($paramArrays.Body) parameters" if ($paramArrays.Body.Count -gt 0) { Foreach ($bodyParam in $paramArrays.Body) { $bodyHt[$bodyParam] = $PSBoundParameters[$bodyParam] } } if ($paramArrays.password.Count -gt 0) { Foreach ($passwordParam in $paramArrays.password) { $secureString = $PSBoundParameters[$passwordParam] $plainText = ConvertFrom-SecureString $secureString -AsPlainText $bodyHt[$passwordParam] = $plainText } } $body = $bodyHt | ConvertTo-Json Write-Debug "Body JSON: $body" Write-verbose "Building query string based on $($paramArrays.Query) parameters" if ($paramArrays.Query.Count -gt 0) { Foreach ($queryArrayParam in $paramArrays.Query) { $queryParamHt[$queryArrayParam] = $PSBoundParameters[$queryArrayParam] } } Write-Debug "QueryParams: $($queryParamHt | Out-String)" Write-Verbose "Constructing full URI based on parameters" if ($queryParamHt) { $uri = New-SMAQueryString -uriPath $uriPath -qParam $queryParamHt @smaParams } else { $uri = New-SMAQueryString -uriPath $uriPath @smaParams } Write-Debug "Final URI: $uri" Write-verbose "Crafting Invokeparam for Invoke-SMARestMethod" $invokeParam = @{ Uri = $uri Method = $RestMethod Cred = $SMACred body = $body SkipCertCheck = $SMASkipCertCheck } Write-Debug "InvokeParam: $($invokeParam | Out-String)" # Prepare WhatIf message based on invokeParam $whatIfTarget = $invokeParam.Uri $whatIfAction = "$($invokeParam.Method) request" if ($invokeParam.body) { $whatIfAction += " with body: $($invokeParam.body)" } if ($PSCmdlet.ShouldProcess($whatIfTarget, $whatIfAction)) { Write-Verbose "Call Invoke-SMARestMethod $uri" $RestResult = Invoke-SMARestMethod @invokeParam # Return object if ($RestResult) { $returnData = Format-SMARestResult $RestResult -object return $returnData } else { Write-Information 'Nothing to return' } } else { Write-Verbose "WhatIf: Operation skipped by user" } } end { } } <# .SYNOPSIS Gets a single domain S/MIME certificate or PGP key by serial / key ID. .DESCRIPTION Retrieves one specific S/MIME certificate or PGP key of the domain specified by -domainName, identified by its serial number (S/MIME) or key ID (PGP) via -serial_or_keyid. Private key material is only included when a -password is supplied; the password is used to protect the exported private key. This is a read-only query (HTTP GET on /crypto/domain/{domainName}/{serial_or_keyid}). .PARAMETER onlyMetadata If $true, returns only the certificate/key metadata without the actual certificate or key material. Default: $false .PARAMETER hin If $true, the key is treated as a HIN (Health Info Net) S/MIME certificate. .PARAMETER password SecureString password used to protect the exported PGP key or S/MIME private key. When omitted, only public key material is returned. Example: 'MyPassword123!' | ConvertTo-SecureString -AsPlainText -Force .PARAMETER domainName The domain name the key belongs to. This parameter is mandatory. .PARAMETER serial_or_keyid The S/MIME certificate serial number or the PGP key ID identifying the key to return. This parameter is mandatory. .PARAMETER SMAHost SEPPmail API hostname. Defaults to the configured value. .PARAMETER SMAPort SEPPmail API port. Defaults to the configured value. .PARAMETER SMAVersion SEPPmail API version. Defaults to the configured value. .PARAMETER SMACred API credentials (PSCredential). Defaults to the configured value. .PARAMETER SMASkipCertCheck Skip SSL certificate validation. Use only in test environments. .OUTPUTS System.Management.Automation.PSCustomObject Returns the requested S/MIME certificate or PGP key. .NOTES - Requires an active SEPPmail API session (New-SMAConfiguration). - Use Get-SMACryptoDomain or Find-SMACryptoDomain -list to discover the available serial numbers / key IDs. - Private keys are only included when -password is provided. .LINK Find-SMACryptoDomain .LINK Get-SMACryptoDomain .EXAMPLE PS C:\> Get-SMACryptoDomainKey -domainName 'contoso.com' -serial_or_keyid '1A2B3C4D' Returns the certificate/key with serial number / key ID '1A2B3C4D' of 'contoso.com'. .EXAMPLE PS C:\> $pw = 'MyPassword123!' | ConvertTo-SecureString -AsPlainText -Force PS C:\> Get-SMACryptoDomainKey -domainName 'contoso.com' -serial_or_keyid '1A2B3C4D' -password $pw Returns the key including the password-protected private key material. #> function Get-SMACryptoDomainKey { [CmdletBinding( SupportsShouldProcess = $true )] param ( #region API params [Parameter( Mandatory = $false, HelpMessage = 'Limit the number of results' )] [SMARestType('query')] [bool]$onlyMetadata, [Parameter( Mandatory = $false, HelpMessage = 'If set to true an add call will only import the public key material.' )] [SMARestType('query')] [bool]$hin, [Parameter( Mandatory = $false, HelpMessage = 'Password with which a PGP key or S/MIME private key will be protected' )] [SMAParamFilter('password')] [SMARestType('query')] [secureString]$password, [Parameter( Mandatory = $true, HelpMessage = 'specify domain name.' )] [SMARestType('path')] [String]$domainName, [Parameter( Mandatory = $true, HelpMessage = 'specifies the S/MIME certificates serial number or the PGP keys key ID' )] [SMARestType('path')] [String]$serial_or_keyid, #endregion API params #region Config parameters block [Parameter(Mandatory = $false)] [String]$SMAHost = $Script:activeCfg.SMAHost, [Parameter(Mandatory = $false)] [int]$SMAPort = $Script:activeCfg.SMAPort, [Parameter(Mandatory = $false)] [String]$SMAVersion = $Script:activeCfg.SMAPIVersion, [Parameter(Mandatory=$false)] [System.Management.Automation.PSCredential]$SMACred=$Script:activeCfg.SMACred, [Parameter(Mandatory=$false)] [switch]$SMASkipCertCheck=$Script:activeCfg.SMAskipCertCheck #endregion ) begin { Write-verbose "Verifying required variables from SMA Config" if (! (verifyVars -VarList $Script:requiredVarList)) {Throw($missingVarsMessage)} # end if Write-verbose "Rest methdod is $restMethod" $RestMethod = 'GET' Write-Verbose "Creating URL base path" $uriPath = "{0}/{1}" -f 'crypto', 'domain' Write-Verbose "Adding SMA Params" $smaParams=@{ Host = $SMAHost Port = $SMAPort Version = $SMAVersion } } process { Write-Verbose "Getting parameter arrays for Body, Path and Query from $($myInvocation.Mycommand.Parameters.Values)" $paramArrays = Get-SMAParameterArray -ParentPSBoundParameters $PSBoundParameters -ParentInvocation $MyInvocation.MyCommand.Parameters.Values Write-Debug "ParamArrays: $($paramArrays | Out-String)" Write-verbose "Initializing REST-Data structures" [string]$uri = $null [hashtable]$bodyHt = @{} [hashtable]$queryParamHt = @{} Write-verbose "Adding optional path to basepath based on $($paramArrays.Path) parameters" if ($paramArrays.Path.Count -gt 0) { Foreach ($pathParam in $paramArrays.Path) { $uriPath = "{0}/{1}" -f $uriPath, $PSBoundParameters[$pathParam] } } Write-Debug "Final uri path is: $uriPath" Write-verbose "Building body HashTable based on $($paramArrays.Body) parameters" if ($paramArrays.Body.Count -gt 0) { Foreach ($bodyParam in $paramArrays.Body) { $bodyHt[$bodyParam] = $PSBoundParameters[$bodyParam] } } if ($paramArrays.password.Count -gt 0) { Foreach ($passwordParam in $paramArrays.password) { $secureString = $PSBoundParameters[$passwordParam] $plainText = ConvertFrom-SecureString $secureString -AsPlainText $bodyHt[$passwordParam] = $plainText } } $body = $bodyHt | ConvertTo-Json Write-Debug "Body JSON: $body" Write-verbose "Building query string based on $($paramArrays.Query) parameters" if ($paramArrays.Query.Count -gt 0) { Foreach ($queryArrayParam in $paramArrays.Query) { $queryParamHt[$queryArrayParam] = $PSBoundParameters[$queryArrayParam] } } Write-Debug "QueryParams: $($queryParamHt | Out-String)" Write-Verbose "Constructing full URI based on parameters" if ($queryParamHt) { $uri = New-SMAQueryString -uriPath $uriPath -qParam $queryParamHt @smaParams } else { $uri = New-SMAQueryString -uriPath $uriPath @smaParams } Write-Debug "Final URI: $uri" Write-verbose "Crafting Invokeparam for Invoke-SMARestMethod" $invokeParam = @{ Uri = $uri Method = $RestMethod Cred = $SMACred body = $body SkipCertCheck = $SMASkipCertCheck } Write-Debug "InvokeParam: $($invokeParam | Out-String)" # Prepare WhatIf message based on invokeParam $whatIfTarget = $invokeParam.Uri $whatIfAction = "$($invokeParam.Method) request" if ($invokeParam.body) { $whatIfAction += " with body: $($invokeParam.body)" } if ($PSCmdlet.ShouldProcess($whatIfTarget, $whatIfAction)) { Write-Verbose "Call Invoke-SMARestMethod $uri" $RestResult = Invoke-SMARestMethod @invokeParam # Return object if ($RestResult) { $returnData = Format-SMARestResult $RestResult -object return $returnData } else { Write-Information 'Nothing to return' } } else { Write-Verbose "WhatIf: Operation skipped by user" } } end { } } # SIG # Begin signature block # MIIVyAYJKoZIhvcNAQcCoIIVuTCCFbUCAQExDzANBglghkgBZQMEAgEFADB5Bgor # BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG # KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCAIuXmelzXYrMgq # F/F+QT5Pn0LtU8O/Qw9JnzoZkYQSbKCCEgQwggVvMIIEV6ADAgECAhBI/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/ # L9Uo2bC5a4CH2RwwggZvMIIE16ADAgECAhBIqMP3CCLHOHtOKuaWNyeFMA0GCSqG # SIb3DQEBDAUAMFQxCzAJBgNVBAYTAkdCMRgwFgYDVQQKEw9TZWN0aWdvIExpbWl0 # ZWQxKzApBgNVBAMTIlNlY3RpZ28gUHVibGljIENvZGUgU2lnbmluZyBDQSBSMzYw # HhcNMjYwNDE1MDAwMDAwWhcNMjcwNzE0MjM1OTU5WjBmMQswCQYDVQQGEwJERTEP # MA0GA1UECAwGQmF5ZXJuMSIwIAYDVQQKDBlTRVBQbWFpbCBEZXV0c2NobGFuZCBH # bWJIMSIwIAYDVQQDDBlTRVBQbWFpbCBEZXV0c2NobGFuZCBHbWJIMIICIjANBgkq # hkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAvAFzE8MbJpvQt+IdIh1M+bKYsJBFDk4b # 9ySe25IrCi00B9o5XmQtIw42MqyIKbUq1tDARtp9KTQedEP9W+rflAF2l+0Z046J # kiqumU9/enbqWLDyln1aS/p7HOgwZFMhnsR9zH0MfFckiklUmkzJO+vmzYAK7ZmD # xajNLJs0gkGRU2/BecAx/TSvLXMaKONsKZCyMKQCnwo1mCY/tFl5EgUz7YQFrPOR # BQGfQke/hkdBfQDqNRsi/J6+KhJWc6LvgQihdRg/INQbQsTxlow18NWvyFsjjueH # 7kG6HR4YKfbv07xgrsIh8xvq9ZJ1SBhLXmkg4SdoQGASjqR6o3keAX+bDRFf+hml # WWJp/FqVHR5QomF3vbK2/bbz4jAclYSPx/sPasNJ0YnKFkgmowZ7Ysa0KA0/egBg # tI4gJ+8V7zrqIVEG3rMQh9KCdMnJqP2aM9o4gUzQvE1M4x606liX9EWwdLLS+fe7 # 9o+Fzo5oH4wBE/En6hQQkzseHHu+TXCDd6zUUZ/PlTK0gTaDIRXt6UzPNqJ4RiRC # W2pNFcPt078qqVTuwKUXoE4ufxGgXKFrZlCYST/9eG1TnW2oq19nz8A333GCsL3g # poNIKvfmDyGMMNzvx2aeqn2v6e75z8kH19iGSNZ51xT+WgS9F1aIvjz08/T7XAv7 # iDPF1/gPIp8CAwEAAaOCAakwggGlMB8GA1UdIwQYMBaAFA8qyyCHKLjsb0iuK1Sm # KaoXpM0MMB0GA1UdDgQWBBS30/Tq+alF3j2BY5up8n5zpAU23DAOBgNVHQ8BAf8E # BAMCB4AwDAYDVR0TAQH/BAIwADATBgNVHSUEDDAKBggrBgEFBQcDAzBKBgNVHSAE # QzBBMDUGDCsGAQQBsjEBAgEDAjAlMCMGCCsGAQUFBwIBFhdodHRwczovL3NlY3Rp # Z28uY29tL0NQUzAIBgZngQwBBAEwSQYDVR0fBEIwQDA+oDygOoY4aHR0cDovL2Ny # bC5zZWN0aWdvLmNvbS9TZWN0aWdvUHVibGljQ29kZVNpZ25pbmdDQVIzNi5jcmww # eQYIKwYBBQUHAQEEbTBrMEQGCCsGAQUFBzAChjhodHRwOi8vY3J0LnNlY3RpZ28u # Y29tL1NlY3RpZ29QdWJsaWNDb2RlU2lnbmluZ0NBUjM2LmNydDAjBggrBgEFBQcw # AYYXaHR0cDovL29jc3Auc2VjdGlnby5jb20wHgYDVR0RBBcwFYETc3VwcG9ydEBz # ZXBwbWFpbC5jaDANBgkqhkiG9w0BAQwFAAOCAYEAi7fmb5UYoemWG3CC4K2UZWVr # R6GOfi8gbJKgjPbKO4zrCrU/x6cOdyp6scKZfUEGFDf8KH6pP4pAQv1Hsbi49gU2 # kxoUWLlCiipn05qJY663DHx9hlStej/ZdEatou0wyCDiG5xD7kmG+1t6iLyyCBgE # B88tJpzTjI61qXmBTS/FGEOAsB4SDEW1ngA7bc5FOv4IUKA43hp8M+N3GeYFzDqw # JELYEfVVYheBW3o7q4VrCdfFEuaQihOtvfDfYpP6ANgekNn8HdsMT8rx9D1I50Rl # i/qQFo2BOuPyb2SIQPzJvCs5wgi5qgp1nHiN6igumu2Cz7BmGjOazGUgCSUY5Qwy # E8+F+R2tVM+2O15rfX01+e56ZfojBEiEjMwfPHs3fa3V3gokWWNwUMkton/v0R/n # l2zjmOr2okohOINZEDh9frg21zUCN5ZD8Y4zQWuiJLCvvvBZs0JR4c9xl2k2wtw/ # QLPhGU69zM3smGpRoLE8M6zvUvSU7jXjvefazUniMYIDGjCCAxYCAQEwaDBUMQsw # CQYDVQQGEwJHQjEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMSswKQYDVQQDEyJT # ZWN0aWdvIFB1YmxpYyBDb2RlIFNpZ25pbmcgQ0EgUjM2AhBIqMP3CCLHOHtOKuaW # NyeFMA0GCWCGSAFlAwQCAQUAoIGEMBgGCisGAQQBgjcCAQwxCjAIoAKAAKECgAAw # GQYJKoZIhvcNAQkDMQwGCisGAQQBgjcCAQQwHAYKKwYBBAGCNwIBCzEOMAwGCisG # AQQBgjcCARUwLwYJKoZIhvcNAQkEMSIEIHjHVkWX6L0UApnNp3hnQQim2fgJg+Xk # O7ANK7VswNryMA0GCSqGSIb3DQEBAQUABIICAFlaV8WPEH0vyQ0gSU440kuxOn1W # hrQJIBZ6rmgDJnx03BdoO2Ca28zsVJk+rhURlY5YW97/lMLLrsb5Fo632ImzYOP3 # h8e4bo1DDTsr8AqNzViTqL+uH4umaQoTTmnCJkTvAtXL8Yfv11LEj18zClOfuQGA # ueseo+O5Ako+OgYW5bbNPHrhxBdx+rDjdL2gDaKfDAGkRzIsSK3cITFYPTigJk4V # 3j0m6SaYayhcRbw4lje3ZQE7wDHNO3G0ylrzr9g2g5ygHaCcShz5RlpxtpfdtF+1 # jzh4Fty7RlqUVvQtlIOGbjqy2nEj1KB7Gnv0b10msCYI72qBadEZyzyPcoURqYtp # JTe80BLC5uQihLeiL+rBui1ebOFCdTXIAf3RLQCS52yiJJ9MhmR4LHrR4lNDrMD9 # HIfpcmuYg5uvaHD7KzOwcm/kkaSIM2JvaBBmFv9MDo9pftpaOmJL7/P7ZVpSrYpt # jV5rOdmdeOitwqUOSE6O2dITMOXWeR7n+6+HP0BdmmNp8kZNlL7dsZNqa4xlmJ7Y # iX2jdQguuJyLAqnnMcB7tCKmte8OF9Ka5oWU7HLmMfHlLqCcihihEOoKxDwMR5vv # skeEtKfyOCRaeuy/LoKI6Iy8lLJQkWK7g38569UeDOZNvwJUqLkfS4sqXmh4ZZIR # kSf0tUhY2EAHHKPb # SIG # End signature block |