Public/Set-VdcCredential.ps1

function Set-VdcCredential {
    <#
    .SYNOPSIS
    Update credential values

    .DESCRIPTION
    Update values for credential objects in TLSPDC.


    .PARAMETER Path
    The full path to the credential object

    .PARAMETER Password
    New password for a password, username/password, or certificate credential. Provide a string, SecureString, or PSCredential.

    .PARAMETER Username
    New username for a username/password credential.
    A password is also required.

    .PARAMETER Certificate
    PKCS #12 certificate object for a certificate credential.
    You can provide either a certificate object or CertificatePath to a .p12 or .pfx file.
    A private key password is also required for -Password.

    .PARAMETER CertificatePath
    Path to a certificate for a certificate credential.
    You can provide either a local path to a .p12 or .pfx file or a certificate object with -Certificate.
    A private key password is also required for -Password.

    .PARAMETER CertificateLinkPath
    Provide a path to an existing TLSPDC certificate object to be used as the certificate for a certificate credential.

    .PARAMETER Expiration
    Expiration date in UTC for the credential. Provide a DateTime object.
    This can be set for username or password credentials.

    .PARAMETER Value
    Hashtable containing the keys/values to be updated.
    This parameter will be deprecated in a future release. Use specific parameters for the credential type.
    The values allowed to be updated are specific to the object type.
    See https://docs.venafi.com/Docs/current/TopNav/Content/SDK/WebSDK/r-SDK-POST-Credentials-FriendlyName.php for details.

    .PARAMETER VenafiSession
    Authentication for the function.
    The value defaults to the script session object $VenafiSession created by New-VenafiSession.
    A TLSPDC token can also be provided.
    If providing a TLSPDC token, an environment variable named VDC_SERVER must also be set.

    .INPUTS
    Path

    .OUTPUTS
    None

    .EXAMPLE
    Set-VdcCredential -Path '\VED\Policy\Password Credential' -Password 'my-new-password'

    Set a new password for a password credential

    .EXAMPLE
    Set-VdcCredential -Path '\VED\Policy\UsernamePassword Credential' -Password 'my-new-password' -Username 'greg'

    Set a new password for a username/password credential

    .EXAMPLE
    Set-VdcCredential -Path '\VED\Policy\Certificate Credential' -Password 'my-pk-password' -Certificate $p12

    Set a new certificate for a certificate credential

    .EXAMPLE
    Set-VdcCredential -Path '\VED\Policy\Password Credential' -Password 'my-new-password' -Expiration (Get-Date).AddDays(30)

    Set a new password for a password credential and set the expiration date to 30 days from now

    .EXAMPLE
    Set-VdcCredential -Path '\VED\Policy\Certificate Credential' -CertificateLinkPath '\VED\Policy\Certificates\newcert.domain.com'

    Set an existing TLSPDC certificate object as the certificate for a certificate credential

    .LINK
    http://VenafiPS.readthedocs.io/en/latest/functions/Set-VdcCredential/

    .LINK
    https://github.com/Venafi/VenafiPS/blob/main/VenafiPS/Public/Set-VdcCredential.ps1

    .LINK
    https://docs.venafi.com/Docs/current/TopNav/Content/SDK/WebSDK/r-SDK-POST-Credentials-update.php

    .LINK
    https://docs.venafi.com/Docs/current/TopNav/Content/SDK/WebSDK/r-SDK-POST-Credentials-FriendlyName.php

    #>


    [CmdletBinding(SupportsShouldProcess, DefaultParameterSetName = 'Password')]
    [Alias('Set-TppCredential')]
    [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidUsingUsernameAndPasswordParams', '', Justification = 'Password is used for more than just username/password credentials so a credential object is not appropriate.')]

    param (
        [Parameter(Mandatory, ValueFromPipeline, ValueFromPipelineByPropertyName)]
        [ValidateNotNullOrEmpty()]
        [ValidateScript( {
                if ( $_ | Test-TppDnPath ) {
                    $true
                }
                else {
                    throw "'$_' is not a valid DN path"
                }
            })]
        [String] $Path,

        [Parameter(ParameterSetName = 'Password', Mandatory)]
        [Parameter(ParameterSetName = 'UsernamePassword', Mandatory)]
        [Parameter(ParameterSetName = 'Certificate', Mandatory)]
        [Parameter(ParameterSetName = 'CertificatePath', Mandatory)]
        [ValidateScript(
            {
                if ( $_ -is [string] -or $_ -is [securestring] -or $_ -is [pscredential] ) {
                    $true
                }
                else {
                    throw 'Unsupported type. Provide either a String, SecureString, or PSCredential.'
                }
            }
        )]
        [psobject] $Password,

        [Parameter(ParameterSetName = 'UsernamePassword', Mandatory)]
        [string] $Username,

        [Parameter(ParameterSetName = 'Certificate', Mandatory)]
        [ValidateScript(
            {
                if ( -not $_.HasPrivateKey ) {
                    throw 'Certificate must contain a private key'
                }
                $true
            }
        )]
        [System.Security.Cryptography.X509Certificates.X509Certificate2] $Certificate,

        [Parameter(Mandatory, ParameterSetName = 'CertificatePath', ValueFromPipelineByPropertyName)]
        [ValidateNotNullOrEmpty()]
        [ValidateScript(
            {
                if ( -not (Test-Path -Path (Resolve-Path -Path $_) -PathType Leaf) ) {
                    throw "'$_' is not a valid file path"
                }

                if ([System.IO.Path]::GetExtension((Resolve-Path -Path $_)) -notin '.pfx', '.p12') {
                    throw "$_ is not a .p12 or .pfx file"
                }

                $true
            }
        )]
        [String] $CertificatePath,

        [Parameter(ParameterSetName = 'CertificateLinkPath', Mandatory)]
        [ValidateScript(
            {
                if ( $_ | Test-TppDnPath ) {
                    $true
                }
                else {
                    throw "'$_' is not a valid DN path"
                }
            }
        )]
        [string] $CertificateLinkPath,

        [Parameter(ParameterSetName = 'Password')]
        [Parameter(ParameterSetName = 'UsernamePassword')]
        [Parameter(ParameterSetName = 'Certificate')]
        [Parameter(ParameterSetName = 'CertificatePath')]
        [Parameter(ParameterSetName = 'CertificateLinkPath')]
        [datetime] $Expiration,

        [Parameter(ParameterSetName = 'OldValue', Mandatory)]
        [hashtable] $Value,

        [Parameter()]
        [psobject] $VenafiSession
    )

    begin {
        Test-VenafiSession -VenafiSession $VenafiSession -Platform 'VDC'

        $params = @{

            Method  = 'Post'
            UriLeaf = 'Credentials/Update'
            Body    = @{
                Values = @()
            }
        }

        if ( $PSBoundParameters.ContainsKey('Password') ) {
            $newPassword = $Password | ConvertTo-PlaintextString

            $params.Body.Values += @{
                'Name'  = 'Password'
                'Type'  = 'string'
                'Value' = $newPassword
            }
        }

        if ( $Username ) {
            $params.Body.Values += @{
                'Name'  = 'Username'
                'Type'  = 'string'
                'Value' = $Username
            }
        }

        if ( $Certificate ) {
            $params.Body.Values += @{
                'Name'  = 'Certificate'
                'Type'  = 'byte[]'
                'Value' = [System.Convert]::ToBase64String($Certificate.Export(1))
            }
        }

        if ( $CertificatePath ) {
            if ($PSVersionTable.PSVersion.Major -lt 6) {
                $cert = Get-Content $CertificatePath -Encoding Byte
            }
            else {
                $cert = Get-Content $CertificatePath -AsByteStream
            }
            $params.Body.Values += @{
                'Name'  = 'Certificate'
                'Type'  = 'byte[]'
                'Value' = [System.Convert]::ToBase64String($cert)
            }
        }

        if ( $Expiration ) {
            $params.Body.Expiration = '/Date({0})/' -f [int64]($Expiration.ToUniversalTime() - [datetime]'1970-01-01T00:00:00Z').TotalMilliseconds
        }

        # used with -Value parameter, to be deprecated
        $CredTypes = @{
            'Password Credential'          = @{
                'FriendlyName' = 'Password'
                'ValueName'    = @{
                    'Password' = 'string'
                }
            }
            'Username Password Credential' = @{
                'FriendlyName' = 'UsernamePassword'
                'ValueName'    = @{
                    'Username' = 'string'
                    'Password' = 'string'
                }
            }
            'Certificate Credential'       = @{
                'FriendlyName' = 'Certificate'
                'ValueName'    = @{
                    'Certificate' = 'byte[]'
                    'Password'    = 'string'
                }
            }
        }
    }

    process {

        # lookup path so we know the type of cred we're dealing with
        $tppObject = Get-VdcObject -Path $Path
        $thisType = $tppObject.TypeName


        # ensure the values looking to be updated are appropriate for this object type
        if ( $Value ) {
            Write-Warning "-Value will be deprecated in a future release. Use specific parameters for the credential type instead."

            if ( -not $CredTypes[$thisType] ) {
                throw "Credential type '$thisType' is not supported yet. Submit an enhancement request."
            }

            $friendlyName = $CredTypes[$thisType].FriendlyName
            $params.Body.FriendlyName = $friendlyName

            $newValues = $Value.GetEnumerator() | ForEach-Object {
                $thisValue = $CredTypes[$thisType].ValueName[$_.Key]
                if ( $thisValue ) {
                    @{
                        'Name'  = $_.Key
                        'Type'  = $thisValue
                        'Value' = $_.Value
                    }
                }
                else {
                    throw ('''{0}'' is not a valid item for type ''{1}''' -f $_.Key, $thisType)
                }
            }

            $params.Body.Values = @($newValues)
        }
        else {
            switch ($tppObject.TypeName) {
                'Password Credential' {
                    $params.Body.FriendlyName = 'Password'
                }
                'Username Password Credential' {
                    $params.Body.FriendlyName = 'UsernamePassword'
                }
                'Certificate Credential' {
                    $params.Body.FriendlyName = 'Certificate'
                }
                Default {
                    Write-Error "$Path : credential type '$thisType' is not supported yet. Submit an enhancement request."
                    continue
                }
            }

            if ( $PSCmdlet.ParameterSetName -notlike ('{0}*' -f $params.Body.FriendlyName) ) {
                Write-Error "$Path : the credential type for this object, $thisType, does not match the parameters provided"
                continue
            }
        }

        # certificate link path workaround
        if ( $CertificateLinkPath ) {
            $certParams = @{
                Path      = $Path
                Attribute = @{
                    'Certificate' = $CertificateLinkPath
                }
            }

            Set-VdcAttribute @certParams
            return
        }


        if ( $PSCmdlet.ShouldProcess( $Path )) {
            $params.Body.CredentialPath = $Path
            $response = Invoke-VenafiRestMethod @params

            if ( $response.Result -ne 1 ) {
                Write-Error $response.Error
            }
        }
    }
}
# SIG # Begin signature block
# MIIhigYJKoZIhvcNAQcCoIIhezCCIXcCAQExDzANBglghkgBZQMEAgEFADB5Bgor
# BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG
# KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCBxn/CM0FkFIrGC
# InCQeeHn3icrt4X6AsCwzAP0oCKhy6CCGokwggd8MIIFZKADAgECAhAD8JaetbYh
# gELYx9Duvn5RMA0GCSqGSIb3DQEBCwUAMGkxCzAJBgNVBAYTAlVTMRcwFQYDVQQK
# Ew5EaWdpQ2VydCwgSW5jLjFBMD8GA1UEAxM4RGlnaUNlcnQgVHJ1c3RlZCBHNCBD
# b2RlIFNpZ25pbmcgUlNBNDA5NiBTSEEzODQgMjAyMSBDQTEwHhcNMjQwODIxMDAw
# MDAwWhcNMjUwOTEyMjM1OTU5WjCBgzELMAkGA1UEBhMCVVMxDTALBgNVBAgTBFV0
# YWgxFzAVBgNVBAcTDlNhbHQgTGFrZSBDaXR5MRUwEwYDVQQKEwxWZW5hZmksIElu
# Yy4xHjAcBgNVBAsTFVByb2Zlc3Npb25hbCBTZXJ2aWNlczEVMBMGA1UEAxMMVmVu
# YWZpLCBJbmMuMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAxungR693
# DIQWU/77slVOdl/qc5leazfxKxl7tkKdNFwCDFrDOAn4/5lIKCl/DZc9RYL5F7Kd
# sdw9Qgi96JWgw0Z29FWcyxYW4xX7IHHhlNzrt/Qc2u+DDk7IZGrMi+OQcGNYxvvG
# HkgZ640nTkX/rPcsctOiYMg57vXUjtYS+u5RfhsJCw3cqCWynTzxKxoQxsTR4NK8
# CW4B/6JYh2V2ni17Bbve074PVKY4Hv+Zmc3F5OHrnfEo51Rv/UcrEdoVvq+Qz5tr
# 89TAd8/QenZ+oomRXG0EmL5UdRn+1Csdk8xoBhHBhgTRmtH+dYwyBSFdWrJ5yTqC
# r198PCe1s4r4eVhrWQdlmI8IWf1uQABq38e/jtLYNJFauurelEN6Fp1bItXuL/Ne
# ncPjOQgmxiufVZ+BYjLYSB4N7vudToDV69B3h8qtVyq0TdAEvyYNcla36li3Ob5K
# qrop+duc37BmHWasgcDXx+Vo6+SyfSaZVNgvw64ihxoVZr/BCkS57zvE/NBnn5rL
# WoVtFWd7tDaoElwCjVbJFNK6RoWCN11aKJKNvUNycb5bR8e3FiuJFZ8rm/4WJvx0
# GNBD53FxKT3fZcZmClb43+C4+s03a6p05X+EIBNDsAlfS44yFy+7t7u8eyM7vmDV
# aVPacOo6yYUPTPxQBENoQeGsecQlWuUQPgcCAwEAAaOCAgMwggH/MB8GA1UdIwQY
# MBaAFGg34Ou2O/hfEYb7/mF7CIhl9E5CMB0GA1UdDgQWBBTTo4VJ8oyO4K/8Z6vN
# vRU44blkbjA+BgNVHSAENzA1MDMGBmeBDAEEATApMCcGCCsGAQUFBwIBFhtodHRw
# Oi8vd3d3LmRpZ2ljZXJ0LmNvbS9DUFMwDgYDVR0PAQH/BAQDAgeAMBMGA1UdJQQM
# MAoGCCsGAQUFBwMDMIG1BgNVHR8Ega0wgaowU6BRoE+GTWh0dHA6Ly9jcmwzLmRp
# Z2ljZXJ0LmNvbS9EaWdpQ2VydFRydXN0ZWRHNENvZGVTaWduaW5nUlNBNDA5NlNI
# QTM4NDIwMjFDQTEuY3JsMFOgUaBPhk1odHRwOi8vY3JsNC5kaWdpY2VydC5jb20v
# RGlnaUNlcnRUcnVzdGVkRzRDb2RlU2lnbmluZ1JTQTQwOTZTSEEzODQyMDIxQ0Ex
# LmNybDCBlAYIKwYBBQUHAQEEgYcwgYQwJAYIKwYBBQUHMAGGGGh0dHA6Ly9vY3Nw
# LmRpZ2ljZXJ0LmNvbTBcBggrBgEFBQcwAoZQaHR0cDovL2NhY2VydHMuZGlnaWNl
# cnQuY29tL0RpZ2lDZXJ0VHJ1c3RlZEc0Q29kZVNpZ25pbmdSU0E0MDk2U0hBMzg0
# MjAyMUNBMS5jcnQwCQYDVR0TBAIwADANBgkqhkiG9w0BAQsFAAOCAgEAk5iA6e3z
# vlKHWEzVa8GVTb0XfMnSj6UcB8WbKmjFR0FlI33Vy8LvoCyX4TamxGJxmbR/BT6V
# lwPMI4UTQCUS4b3N+yGDUBmqqCLqN0W0OJbun6Y0UscEcWr8RsAY0lp3SFjcUa1c
# ixLsSI/9cQTV+6bIJUScvlXEOYIenjiIO/RTX9y+8/lfgVBYS69bjDUzU/WxcZ3R
# vGZ5sPVko6al7frjz0uL/F/aCbCw2N0eO/sqI4IfWQZ3CVromQjBEzogj7K2OuB3
# V2Gw3IfSvQobmuTtveOhwp/ma+4V46YYx0mQKrDS0jniMGYstoJeFGMhvr9oac0Q
# +wO/PmHBp93m9SfoiUTmKYJMIu9+Jd+8rF6m2/SqRESk1HKD+RgGURt6B38K6dcf
# URJXY/r/wgnH0Xb2yMorFOKGkyX2D5hMs1pzgvL3F3B2/SmH2RORDA45UfOCtWQE
# 6yYnGjZmabCZl4YFWZsoo9pZXXK3b5narfokdh3AEH2RpIEBtWuZYPgqf8X2a5rt
# QrskHMEhY3WHZTZNnncsXSe1cAbPlnDge+byzWYyVc1PtiWE9krTdyJ+TKaTeJTU
# NW73unKsU5JMwA77ASchFEfPtLBLjKJh44vFzYuRJGIXoUK2bdPk3JLmvApx6Ty5
# PP8HdjkQzchgpQHVVQe3KAR1ppN42x/9ESEwggWNMIIEdaADAgECAhAOmxiO+dAt
# 5+/bUOIIQBhaMA0GCSqGSIb3DQEBDAUAMGUxCzAJBgNVBAYTAlVTMRUwEwYDVQQK
# EwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xJDAiBgNV
# BAMTG0RpZ2lDZXJ0IEFzc3VyZWQgSUQgUm9vdCBDQTAeFw0yMjA4MDEwMDAwMDBa
# Fw0zMTExMDkyMzU5NTlaMGIxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2Vy
# dCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xITAfBgNVBAMTGERpZ2lD
# ZXJ0IFRydXN0ZWQgUm9vdCBHNDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoC
# ggIBAL/mkHNo3rvkXUo8MCIwaTPswqclLskhPfKK2FnC4SmnPVirdprNrnsbhA3E
# MB/zG6Q4FutWxpdtHauyefLKEdLkX9YFPFIPUh/GnhWlfr6fqVcWWVVyr2iTcMKy
# unWZanMylNEQRBAu34LzB4TmdDttceItDBvuINXJIB1jKS3O7F5OyJP4IWGbNOsF
# xl7sWxq868nPzaw0QF+xembud8hIqGZXV59UWI4MK7dPpzDZVu7Ke13jrclPXuU1
# 5zHL2pNe3I6PgNq2kZhAkHnDeMe2scS1ahg4AxCN2NQ3pC4FfYj1gj4QkXCrVYJB
# MtfbBHMqbpEBfCFM1LyuGwN1XXhm2ToxRJozQL8I11pJpMLmqaBn3aQnvKFPObUR
# WBf3JFxGj2T3wWmIdph2PVldQnaHiZdpekjw4KISG2aadMreSx7nDmOu5tTvkpI6
# nj3cAORFJYm2mkQZK37AlLTSYW3rM9nF30sEAMx9HJXDj/chsrIRt7t/8tWMcCxB
# YKqxYxhElRp2Yn72gLD76GSmM9GJB+G9t+ZDpBi4pncB4Q+UDCEdslQpJYls5Q5S
# UUd0viastkF13nqsX40/ybzTQRESW+UQUOsxxcpyFiIJ33xMdT9j7CFfxCBRa2+x
# q4aLT8LWRV+dIPyhHsXAj6KxfgommfXkaS+YHS312amyHeUbAgMBAAGjggE6MIIB
# NjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTs1+OC0nFdZEzfLmc/57qYrhwP
# TzAfBgNVHSMEGDAWgBRF66Kv9JLLgjEtUYunpyGd823IDzAOBgNVHQ8BAf8EBAMC
# AYYweQYIKwYBBQUHAQEEbTBrMCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdp
# Y2VydC5jb20wQwYIKwYBBQUHMAKGN2h0dHA6Ly9jYWNlcnRzLmRpZ2ljZXJ0LmNv
# bS9EaWdpQ2VydEFzc3VyZWRJRFJvb3RDQS5jcnQwRQYDVR0fBD4wPDA6oDigNoY0
# aHR0cDovL2NybDMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0QXNzdXJlZElEUm9vdENB
# LmNybDARBgNVHSAECjAIMAYGBFUdIAAwDQYJKoZIhvcNAQEMBQADggEBAHCgv0Nc
# Vec4X6CjdBs9thbX979XB72arKGHLOyFXqkauyL4hxppVCLtpIh3bb0aFPQTSnov
# Lbc47/T/gLn4offyct4kvFIDyE7QKt76LVbP+fT3rDB6mouyXtTP0UNEm0Mh65Zy
# oUi0mcudT6cGAxN3J0TU53/oWajwvy8LpunyNDzs9wPHh6jSTEAZNUZqaVSwuKFW
# juyk1T3osdz9HNj0d1pcVIxv76FQPfx2CWiEn2/K2yCNNWAcAgPLILCsWKAOQGPF
# mCLBsln1VWvPJ6tsds5vIy30fnFqI2si/xK4VC0nftg62fC2h5b9W9FcrBjDTZ9z
# twGpn1eqXijiuZQwggauMIIElqADAgECAhAHNje3JFR82Ees/ShmKl5bMA0GCSqG
# SIb3DQEBCwUAMGIxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMx
# GTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xITAfBgNVBAMTGERpZ2lDZXJ0IFRy
# dXN0ZWQgUm9vdCBHNDAeFw0yMjAzMjMwMDAwMDBaFw0zNzAzMjIyMzU5NTlaMGMx
# CzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5EaWdpQ2VydCwgSW5jLjE7MDkGA1UEAxMy
# RGlnaUNlcnQgVHJ1c3RlZCBHNCBSU0E0MDk2IFNIQTI1NiBUaW1lU3RhbXBpbmcg
# Q0EwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDGhjUGSbPBPXJJUVXH
# JQPE8pE3qZdRodbSg9GeTKJtoLDMg/la9hGhRBVCX6SI82j6ffOciQt/nR+eDzMf
# UBMLJnOWbfhXqAJ9/UO0hNoR8XOxs+4rgISKIhjf69o9xBd/qxkrPkLcZ47qUT3w
# 1lbU5ygt69OxtXXnHwZljZQp09nsad/ZkIdGAHvbREGJ3HxqV3rwN3mfXazL6IRk
# tFLydkf3YYMZ3V+0VAshaG43IbtArF+y3kp9zvU5EmfvDqVjbOSmxR3NNg1c1eYb
# qMFkdECnwHLFuk4fsbVYTXn+149zk6wsOeKlSNbwsDETqVcplicu9Yemj052FVUm
# cJgmf6AaRyBD40NjgHt1biclkJg6OBGz9vae5jtb7IHeIhTZgirHkr+g3uM+onP6
# 5x9abJTyUpURK1h0QCirc0PO30qhHGs4xSnzyqqWc0Jon7ZGs506o9UD4L/wojzK
# QtwYSH8UNM/STKvvmz3+DrhkKvp1KCRB7UK/BZxmSVJQ9FHzNklNiyDSLFc1eSuo
# 80VgvCONWPfcYd6T/jnA+bIwpUzX6ZhKWD7TA4j+s4/TXkt2ElGTyYwMO1uKIqjB
# Jgj5FBASA31fI7tk42PgpuE+9sJ0sj8eCXbsq11GdeJgo1gJASgADoRU7s7pXche
# MBK9Rp6103a50g5rmQzSM7TNsQIDAQABo4IBXTCCAVkwEgYDVR0TAQH/BAgwBgEB
# /wIBADAdBgNVHQ4EFgQUuhbZbU2FL3MpdpovdYxqII+eyG8wHwYDVR0jBBgwFoAU
# 7NfjgtJxXWRM3y5nP+e6mK4cD08wDgYDVR0PAQH/BAQDAgGGMBMGA1UdJQQMMAoG
# CCsGAQUFBwMIMHcGCCsGAQUFBwEBBGswaTAkBggrBgEFBQcwAYYYaHR0cDovL29j
# c3AuZGlnaWNlcnQuY29tMEEGCCsGAQUFBzAChjVodHRwOi8vY2FjZXJ0cy5kaWdp
# Y2VydC5jb20vRGlnaUNlcnRUcnVzdGVkUm9vdEc0LmNydDBDBgNVHR8EPDA6MDig
# NqA0hjJodHRwOi8vY3JsMy5kaWdpY2VydC5jb20vRGlnaUNlcnRUcnVzdGVkUm9v
# dEc0LmNybDAgBgNVHSAEGTAXMAgGBmeBDAEEAjALBglghkgBhv1sBwEwDQYJKoZI
# hvcNAQELBQADggIBAH1ZjsCTtm+YqUQiAX5m1tghQuGwGC4QTRPPMFPOvxj7x1Bd
# 4ksp+3CKDaopafxpwc8dB+k+YMjYC+VcW9dth/qEICU0MWfNthKWb8RQTGIdDAiC
# qBa9qVbPFXONASIlzpVpP0d3+3J0FNf/q0+KLHqrhc1DX+1gtqpPkWaeLJ7giqzl
# /Yy8ZCaHbJK9nXzQcAp876i8dU+6WvepELJd6f8oVInw1YpxdmXazPByoyP6wCeC
# RK6ZJxurJB4mwbfeKuv2nrF5mYGjVoarCkXJ38SNoOeY+/umnXKvxMfBwWpx2cYT
# gAnEtp/Nh4cku0+jSbl3ZpHxcpzpSwJSpzd+k1OsOx0ISQ+UzTl63f8lY5knLD0/
# a6fxZsNBzU+2QJshIUDQtxMkzdwdeDrknq3lNHGS1yZr5Dhzq6YBT70/O3itTK37
# xJV77QpfMzmHQXh6OOmc4d0j/R0o08f56PGYX/sr2H7yRp11LB4nLCbbbxV7HhmL
# NriT1ObyF5lZynDwN7+YAN8gFk8n+2BnFqFmut1VwDophrCYoCvtlUG3OtUVmDG0
# YgkPCr2B2RP+v6TR81fZvAT6gt4y3wSJ8ADNXcL50CN/AAvkdgIm2fBldkKmKYcJ
# RyvmfxqkhQ/8mJb2VVQrH4D6wPIOK+XW+6kvRBVK5xMOHds3OBqhK/bt1nz8MIIG
# wjCCBKqgAwIBAgIQBUSv85SdCDmmv9s/X+VhFjANBgkqhkiG9w0BAQsFADBjMQsw
# CQYDVQQGEwJVUzEXMBUGA1UEChMORGlnaUNlcnQsIEluYy4xOzA5BgNVBAMTMkRp
# Z2lDZXJ0IFRydXN0ZWQgRzQgUlNBNDA5NiBTSEEyNTYgVGltZVN0YW1waW5nIENB
# MB4XDTIzMDcxNDAwMDAwMFoXDTM0MTAxMzIzNTk1OVowSDELMAkGA1UEBhMCVVMx
# FzAVBgNVBAoTDkRpZ2lDZXJ0LCBJbmMuMSAwHgYDVQQDExdEaWdpQ2VydCBUaW1l
# c3RhbXAgMjAyMzCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAKNTRYcd
# g45brD5UsyPgz5/X5dLnXaEOCdwvSKOXejsqnGfcYhVYwamTEafNqrJq3RApih5i
# Y2nTWJw1cb86l+uUUI8cIOrHmjsvlmbjaedp/lvD1isgHMGXlLSlUIHyz8sHpjBo
# yoNC2vx/CSSUpIIa2mq62DvKXd4ZGIX7ReoNYWyd/nFexAaaPPDFLnkPG2ZS48jW
# Pl/aQ9OE9dDH9kgtXkV1lnX+3RChG4PBuOZSlbVH13gpOWvgeFmX40QrStWVzu8I
# F+qCZE3/I+PKhu60pCFkcOvV5aDaY7Mu6QXuqvYk9R28mxyyt1/f8O52fTGZZUdV
# nUokL6wrl76f5P17cz4y7lI0+9S769SgLDSb495uZBkHNwGRDxy1Uc2qTGaDiGhi
# u7xBG3gZbeTZD+BYQfvYsSzhUa+0rRUGFOpiCBPTaR58ZE2dD9/O0V6MqqtQFcmz
# yrzXxDtoRKOlO0L9c33u3Qr/eTQQfqZcClhMAD6FaXXHg2TWdc2PEnZWpST618Rr
# IbroHzSYLzrqawGw9/sqhux7UjipmAmhcbJsca8+uG+W1eEQE/5hRwqM/vC2x9XH
# 3mwk8L9CgsqgcT2ckpMEtGlwJw1Pt7U20clfCKRwo+wK8REuZODLIivK8SgTIUlR
# fgZm0zu++uuRONhRB8qUt+JQofM604qDy0B7AgMBAAGjggGLMIIBhzAOBgNVHQ8B
# Af8EBAMCB4AwDAYDVR0TAQH/BAIwADAWBgNVHSUBAf8EDDAKBggrBgEFBQcDCDAg
# BgNVHSAEGTAXMAgGBmeBDAEEAjALBglghkgBhv1sBwEwHwYDVR0jBBgwFoAUuhbZ
# bU2FL3MpdpovdYxqII+eyG8wHQYDVR0OBBYEFKW27xPn783QZKHVVqllMaPe1eNJ
# MFoGA1UdHwRTMFEwT6BNoEuGSWh0dHA6Ly9jcmwzLmRpZ2ljZXJ0LmNvbS9EaWdp
# Q2VydFRydXN0ZWRHNFJTQTQwOTZTSEEyNTZUaW1lU3RhbXBpbmdDQS5jcmwwgZAG
# CCsGAQUFBwEBBIGDMIGAMCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdpY2Vy
# dC5jb20wWAYIKwYBBQUHMAKGTGh0dHA6Ly9jYWNlcnRzLmRpZ2ljZXJ0LmNvbS9E
# aWdpQ2VydFRydXN0ZWRHNFJTQTQwOTZTSEEyNTZUaW1lU3RhbXBpbmdDQS5jcnQw
# DQYJKoZIhvcNAQELBQADggIBAIEa1t6gqbWYF7xwjU+KPGic2CX/yyzkzepdIpLs
# jCICqbjPgKjZ5+PF7SaCinEvGN1Ott5s1+FgnCvt7T1IjrhrunxdvcJhN2hJd6Pr
# kKoS1yeF844ektrCQDifXcigLiV4JZ0qBXqEKZi2V3mP2yZWK7Dzp703DNiYdk9W
# uVLCtp04qYHnbUFcjGnRuSvExnvPnPp44pMadqJpddNQ5EQSviANnqlE0PjlSXcI
# WiHFtM+YlRpUurm8wWkZus8W8oM3NG6wQSbd3lqXTzON1I13fXVFoaVYJmoDRd7Z
# ULVQjK9WvUzF4UbFKNOt50MAcN7MmJ4ZiQPq1JE3701S88lgIcRWR+3aEUuMMsOI
# 5ljitts++V+wQtaP4xeR0arAVeOGv6wnLEHQmjNKqDbUuXKWfpd5OEhfysLcPTLf
# ddY2Z1qJ+Panx+VPNTwAvb6cKmx5AdzaROY63jg7B145WPR8czFVoIARyxQMfq68
# /qTreWWqaNYiyjvrmoI1VygWy2nyMpqy0tg6uLFGhmu6F/3Ed2wVbK6rr3M66ElG
# t9V/zLY4wNjsHPW2obhDLN9OTH0eaHDAdwrUAuBcYLso/zjlUlrWrBciI0707NMX
# +1Br/wd3H3GXREHJuEbTbDJ8WC9nR2XlG3O2mflrLAZG70Ee8PBf4NvZrZCARK+A
# EEGKMYIGVzCCBlMCAQEwfTBpMQswCQYDVQQGEwJVUzEXMBUGA1UEChMORGlnaUNl
# cnQsIEluYy4xQTA/BgNVBAMTOERpZ2lDZXJ0IFRydXN0ZWQgRzQgQ29kZSBTaWdu
# aW5nIFJTQTQwOTYgU0hBMzg0IDIwMjEgQ0ExAhAD8JaetbYhgELYx9Duvn5RMA0G
# CWCGSAFlAwQCAQUAoIGIMBkGCSqGSIb3DQEJAzEMBgorBgEEAYI3AgEEMBwGCSqG
# SIb3DQEJBTEPFw0yNDA5MTYxNTMxMjZaMBwGCisGAQQBgjcCAQsxDjAMBgorBgEE
# AYI3AgEVMC8GCSqGSIb3DQEJBDEiBCCriXg2VLpYWgD8XVp51aySOw0TDajBH/3V
# eVg5sb66YjANBgkqhkiG9w0BAQEFAASCAgBUtLZGe1p//Qgliil/kM1RrRc8+Y+n
# bwnzd6IrJknbIJgV4Qte/Qt5Fopt+VevC7XMNM4It5YRy6SWh1vjsTEs97xTxSzt
# swmJ7JokWkquTGL5l0gcKC3Nk5Hrobattjxu5cFqx6SkBDGTzoFBWlSFcjpXqMxh
# 8x6Pg0OGm26o+DZcYmIl7AmksMZPaW6sIz6TERU4qV2KraX7muq4vcLEw2GwwxBo
# Jipf2S7OacpUBmPTBsEE3slLPsOXB3XtNBQeZpoJMXxvbR+gGmFauNdxWwIksc0e
# oPPpZsfi90Kv3BAb9dnaocx8EsFiItOvve8+xHVRax/0H+rDA13EuY+YHi5WpRB8
# 2NsxJt1IPoryO4z7o7AczA+UjpmowDFKIcM3QVAaxSPjrIEc3snIYSqIr77lNNnx
# x88ogE0NsIkSDrYUokgeR7/ypFiDBjAV3VIQxjVvhpTSLZ0u0V5TOA0KiqpMJcWl
# lTaP4TKdHbN4Jau2Ggv5OPID117AUExFcNZ+0B4qDpwKbXOpuhAxV1NzFT8qai5Z
# BzBzfd2wd6Be3K+ecG4DwdVUjSBQL8qO2o1J3c7VPwcdUzqLaiSD00bAUXPH6byM
# CMIK6ygFObuVRNvCHvieXSube1Ho8qFDJ/0n3EKMwicYS/sgUzUrdrvlSkJd5ErK
# BZmlYRsiQ2EU1qGCAyAwggMcBgkqhkiG9w0BCQYxggMNMIIDCQIBATB3MGMxCzAJ
# BgNVBAYTAlVTMRcwFQYDVQQKEw5EaWdpQ2VydCwgSW5jLjE7MDkGA1UEAxMyRGln
# aUNlcnQgVHJ1c3RlZCBHNCBSU0E0MDk2IFNIQTI1NiBUaW1lU3RhbXBpbmcgQ0EC
# EAVEr/OUnQg5pr/bP1/lYRYwDQYJYIZIAWUDBAIBBQCgaTAYBgkqhkiG9w0BCQMx
# CwYJKoZIhvcNAQcBMBwGCSqGSIb3DQEJBTEPFw0yNDA5MTYxNTMxMjdaMC8GCSqG
# SIb3DQEJBDEiBCBiqXpmc456LLhsOOrrtg7ODm0X6RLGrSD06ChG5msMYzANBgkq
# hkiG9w0BAQEFAASCAgA7ZjCimJxwdPMWk39onW2PeDrDNHb/JaRJuQVL3ZpPq/1k
# 90j8PVMncLxXumd9FW1ZXomQQze3Co+KlG+Sv48NTfWQcsTvNC8dcdbPgnoBhWwd
# yh2lWopadvcnFKpAgLWWM6LHAfjaNJX6Prke/WqAgJgNbvRa3NzBLQLihxxtH6RP
# k8ziYCPYXCb1WgxvivbJ60xAhJbvB4PIXF+JRNSC4Seb/0tYNqxge8LzM8AuNkPT
# tztd00J53XyL4Qpe2P34d1GjMw+xBl3cK4JTVUqnCos8D9hRWsLmv79DHzWdncb7
# YXwgktA8SBpDhm4M5jJm3Z8p/qx+pdSRC6GU8nsXmUuybjb5D0NAsXWOQmQv8lhX
# N3ig2iZWpFCEno472gvhyk/xva4CmR8TsxqXEdL05L4K/ac8P7Jqj9Lg4giKJY7C
# G/ZlmpEuDGcJWvxe3fS+EypmY4VHdpFuMH4lDS40v1zguDW+fECZ9cUIQDZhrzyF
# ABRSwmmVxxyHaCT4gIsbKhCGTFDB+J6zUGkeSmQCEPS0Q063WiU8y5CexSM03l6d
# 4e2x7wIuj4MK414EhsdxWbIJJI451OaJvyK/GUWUC7WByEgtTZjVKhBaruwtlVjh
# ocQKi6hLKZl1flYTy8uxeUDbnnOnh6BTyhhn2lOtayfkJCQSWf7W+0pPrZ+q6Q==
# SIG # End signature block