Public/SEPPmailAPI-UserCrypto.ps1

<#
.SYNOPSIS
    Get the S/MIME or PGP Keys of a single locally existing users
.DESCRIPTION
    This CmdLet lets you read one or all keys of an existing user.
.EXAMPLE
    PS C:\> Get-SMAUserKey -eMail 'alice.miller@contoso.com'
    Gets all available keys for a user and shows all details
.EXAMPLE
    PS C:\> Get-SMAUserKey -eMail 'alice.miller@contoso.com' -technology pgp
    Gets pgp keys for a user and shows all details
.EXAMPLE
    PS C:\> Get-SMAUserKey -eMail 'alice.miller@contoso.com' -technology smime -list:$true
    Gets pgp keys for a user and shows the key only.
.EXAMPLE
    PS C:\> Get-SMAUserKey -eMail 'alice.miller@contoso.com' -limit 2
    Gets all keys for a user and shows only 2 keys.
 
.PARAMETER eMail
    The user's e-mail address whose keys should be returned. Mandatory.
    Accepts pipeline input (by value and by property name).
 
.PARAMETER key
    A single key identified by its S/MIME serial number or PGP key ID. When
    supplied, only that key is returned (parameter set 'keyId').
    Aliases: serial, keyId
 
.PARAMETER list
    If $true, returns an array of key names / IDs instead of full details.
 
    Default: $false
 
.PARAMETER limit
    Limits the output to the given number of objects. 0 means no limit.
 
    Default: 0
 
.PARAMETER technology
    Restricts the output to a cryptographic technology.
    Valid values: 'pgp', 'smime', 'both'.
 
    Default: 'both'
 
.PARAMETER password
    SecureString password used to protect exported private key material.
    Accepts pipeline input by property name.
 
.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 user's S/MIME certificates and/or PGP keys.
 
.NOTES
    - Requires an active SEPPmail API session (New-SMAConfiguration).
    - This is a read-only operation (HTTP GET on /crypto/user/{email}).
 
.LINK
    Remove-SMAUserKey
#>

function Get-SMAUserKey
{
    [CmdletBinding()]
    param (
        #region REST-API path and query parameters
        [Parameter(
            ParameterSetName                = 'email',
            Mandatory                       = $true,
            ValueFromPipelineByPropertyName = $true,
            ValueFromPipeline               = $true,
            HelpMessage                     = 'User E-Mail address'
            )]
        [Parameter(
            ParameterSetName                = 'keyId',
            Mandatory                       = $true,
            ValueFromPipelineByPropertyName = $true,
            ValueFromPipeline               = $true,
            HelpMessage                     = 'User E-Mail address'
            )]            
        [string]$eMail,

        [Parameter(
            ParameterSetName                = 'keyId',
            Mandatory                       = $true,
            ValueFromPipelineByPropertyName = $true,
            ValueFromPipeline               = $true,
            HelpMessage                     = 'Keys id or serial number'
            )]
        [Alias('serial','keyId')]
        [string]$key,
    
        [Parameter(
            Mandatory                       = $false,
            HelpMessage                     = 'Show an array of names instead details'
            )]
        [Boolean]$list = $false,

        [Parameter(
            Mandatory                       = $false,
            HelpMessage                     = 'limit output to <n> objects' 
            )]
        [int]$limit = 0,

        [Parameter(
            Mandatory                   = $false,
            HelpMessage                 = 'specify the keytype you want to see (default both)'
            )]
        [ValidateSet('pgp','smime','both')]
        [string]$technology = 'both',

        [Parameter(
            Mandatory                       = $false,
            ValueFromPipelineByPropertyName = $true,
            HelpMessage                     = 'The password for the key'
            )]
        [SecureString]$password,
        #endregion

        #region SMA host parameters
        [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 {
        if (! (verifyVars -VarList $Script:requiredVarList))
        {
            Throw($missingVarsMessage);
        }; # end if
    }
    process {
        try {
            Write-Verbose "Creating URL path"
            if ($PSCmdlet.MyInvocation.BoundParameters.ContainsKey('key')) {
                $uriPath = "{0}/{1}/{2}/{3}" -f 'crypto','user', $eMail.ToLower(), 'serial_or_key'
            } else {
                $uriPath = "{0}/{1}/{2}" -f 'crypto','user', $eMail.ToLower()
            }
    
            # Build querystring hashtable for conversion from parameters. Boundparams are eiter mandatory or have default values
            $boundParam = @{
                      'list' = $list
                     'limit' = $limit
                'technology' = $technology
            }

                if ($PSCmdlet.MyInvocation.BoundParameters.ContainsKey('password')) {$boundParam.password = (ConvertFrom-SecureString -secureString $password -asPlainText)}
                     if ($PSCmdlet.MyInvocation.BoundParameters.ContainsKey('uid')) {$boundParam.uid = $uid}

            $smaParams=@{
                Host=$SMAHost;
                Port=$SMAPort;
                Version=$SMAVersion;
            }; # end smaParams
            $uri = New-SMAQueryString -uriPath $uriPath -qParam $boundParam @smaParams
            
            Write-verbose "Crafting Invokeparam for Invoke-SMARestMethod"
            $invokeParam = @{
                Uri           = $uri 
                Method        = 'GET'
                Cred          =  $SMACred
                SkipCertCheck = $SMASkipCertCheck
            }
    
            Write-Verbose "Call Invoke-SMARestMethod $uri" 
            $userKeyRaw = Invoke-SMARestMethod @invokeParam
            <#
            Write-Verbose 'Filter data and return as PSObject'
            $GetUserKey = $userKeyRaw.Psobject.properties.value
     
            Write-Verbose 'Converting Umlauts from ISO-8859-1'
            $userKey = ConvertFrom-SMAPIFormat -inputObject $getUserKey
            #>

            # Userobject
            if ($UserKeyRaw) {
                return $userKeyRaw
            }
            else {
                Write-Information 'Nothing to return'
            }
        }
        catch {
            Write-Error "An error occured, see $error"
        }
    
    }
    end {

    }
}

<#
.SYNOPSIS
    Removes a single S/MIME or PGP key of a locally existing user.
 
.DESCRIPTION
    Removes one key (identified by its S/MIME serial number or PGP key ID) of
    the user specified by -eMail. By default the associated certificate is
    revoked but the key material is kept; use -delete to finally remove the
    key material and -revoke to control certificate revocation.
 
    Based on the API DELETE /crypto/user/{email}/{serial_or_keyid}.
 
.PARAMETER eMail
    The user's e-mail address whose key should be removed. Mandatory.
    Accepts pipeline input (by value and by property name).
 
.PARAMETER key
    The key to remove, identified by its S/MIME serial number
    (e.g. '0x9FA4185B8B094759F8215E5') or PGP key ID (e.g. 'CE80994BA881F424').
    Mandatory. Accepts pipeline input by property name.
    Aliases: serial, keyid
 
.PARAMETER revoke
    If $true, the certificate is revoked when the key is removed.
 
    Default: $true
 
.PARAMETER delete
    If $true, the key material is finally deleted instead of only removed.
 
    Default: $false
 
.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 API result of the delete operation.
 
.NOTES
    - Requires an active SEPPmail API session (New-SMAConfiguration).
    - This operation is destructive; combine -delete with care.
 
.LINK
    Get-SMAUserKey
 
.EXAMPLE
    PS C:\> Remove-SMAUserKey -eMail 'alice.miller@contoso.com' -Key '0x9FA4185B8B094759F8215E5'
    Removes the key and revokes the certificate, but keeps the key material.
 
.EXAMPLE
    PS C:\> Remove-SMAUserKey -eMail 'alice.miller@contoso.com' -Key '0x9FA4185B8B094759F8215E5' -revoke:$false
    Removes the key without revoking the certificate and keeps the key material.
 
.EXAMPLE
    PS C:\> Remove-SMAUserKey -eMail 'alice.miller@contoso.com' -Key '0x9FA4185B8B094759F8215E5' -delete:$true
    Removes the key, finally deletes the key material and revokes the certificate.
#>

function Remove-SMAUserKey
{
    [CmdletBinding()]
    param (
        #region REST-API path and query parameters
        [Parameter(
            Mandatory                       = $true,
            ValueFromPipelineByPropertyName = $true,
            ValueFromPipeline               = $true,
            HelpMessage                     = 'User E-Mail address'
            )]
        [string]$eMail,

        [Parameter(
            Mandatory                       = $true,
            ValueFromPipelineByPropertyName = $true,
            ValueFromPipeline               = $true,
            HelpMessage                     = 'Keys id or serial number (SMIME 0x9FA4185B8B094759F8215E5), (PGP CE80994BA881F424)'
            )]
        [Alias('serial','keyid')]
        [string]$key,
    
        [Parameter(
            Mandatory                       = $false,
            HelpMessage                     = 'Revoke the certificate'
            )]
        [Boolean]$revoke = $true,

        [Parameter(
            Mandatory                       = $false,
            HelpMessage                     = 'Delete the key finally' 
            )]
        [Boolean]$delete = $false,

        #endregion

        #region SMA host parameters
        [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 {
        if (! (verifyVars -VarList $Script:requiredVarList))
        {
            Throw($missingVarsMessage);
        }; # end if
    }
    process {
        try {
            Write-Verbose "Creating URL path"
            $uriPath = "{0}/{1}/{2}/{3}" -f 'crypto','user', $eMail, 'serial_or_key'
    
            # Build querystring hashtable for conversion from parameters. Boundparams are eiter mandatory or have default values
            $boundParam = @{}

            if ($PSCmdlet.MyInvocation.BoundParameters.ContainsKey('delete')) {$boundParam.delete = $delete}
            if ($PSCmdlet.MyInvocation.BoundParameters.ContainsKey('revoke')) {$boundParam.revoke = $revoke}

            $smaParams=@{
                Host=$SMAHost;
                Port=$SMAPort;
                Version=$SMAVersion;
            }; # end smaParams
            $uri = New-SMAQueryString -uriPath $uriPath -qParam $boundParam @smaParams
            
            Write-verbose "Crafting Invokeparam for Invoke-SMARestMethod"
            $invokeParam = @{
                Uri           = $uri 
                Method        = 'DELETE'
                Cred          = $SMACred
                SkipCertCheck = $SMASkipCertCheck
            }
    
            Write-Verbose "Call Invoke-SMARestMethod $uri" 
            $DeleteKey = Invoke-SMARestMethod @invokeParam
            <#
            Write-Verbose 'Filter data and return as PSObject'
            $GetUserKey = $userKeyRaw.Psobject.properties.value
     
            Write-Verbose 'Converting Umlauts from ISO-8859-1'
            $userKey = ConvertFrom-SMAPIFormat -inputObject $getUserKey
            #>

            # Userobject
            if ($DeleteKey) {
                return $DeleteKey
            }
            else {
                Write-Information 'Nothing to return'
            }
        }
        catch {
            Write-Error "An error occured, see $error"
        }
    
    }
    end {

    }
}

# SIG # Begin signature block
# MIIVyAYJKoZIhvcNAQcCoIIVuTCCFbUCAQExDzANBglghkgBZQMEAgEFADB5Bgor
# BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG
# KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCDdRo81fa91UQb4
# C1l3Hjt+YoT93P2gWKCAWqFxXYm8sqCCEgQwggVvMIIEV6ADAgECAhBI/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
# AQQBgjcCARUwLwYJKoZIhvcNAQkEMSIEIDJXfb02iZpMf67SGForEyzvYfJKeu3M
# byoEQpKd8C+/MA0GCSqGSIb3DQEBAQUABIICAE1IhEFM80SPB60S20ZI7+RDwtKe
# GAe+5MW0gsxuvKjFcSw085/hFQ30oFplEewAk24BbZPuNhxNocLKGJQT/DqumEhg
# WPRFpg+dNdbrDhubYz6N2YwIK19/4m705TxEtoLL7BlxD5MucZjsFbjNuhhinzk4
# Hi/2uAs/y8tlBkFX2GtCRJmDHNP3/Z1kZ7qsGeuDHAvCVBejUz9j2mpSV1qQ3Vjy
# 3i5+lM1OKuvsILryWxRKHwsbStGWZy/etj1bTLgJvcLkPhoy8F6HmPw9JtXAxXz4
# 89sc7HtbJwuBhaek/YrHQULkV0a19Xoygy2jk3qZIcpzD+Kkz99QW7zOlwqNRfgg
# jUtxohPN8Ewtp/4Fc7lLmH28PaB6gj4gEtQ6hcG798nnO5gB/3+GfCscmxbSg0MM
# vVCJ7J3Hq0UjR71yEX4dhifQRHtVPvJcpLCv2cy/QYwv/fjiDU8q0tZYODwToB3w
# jgqsaQwCGrcX+5LoYwmzEI0eXu8kDs2fgqTXorFKFcA8/8AGiRwb5d4MBZwNz/Mu
# 1mtSJH4WUk6n+rAkJHzazFe4rXCCAi1NwmFJKEnHB+UR6IcFDAFBhSV3HPfjFP8I
# Gy8nF6RcvINFV2xIIOU0Lcu8a/SZmUbzbtv05OhL0aGtvMiKYOsW6P82bmHCDOBs
# PzuQmjcud8htyV5n
# SIG # End signature block