Public/Invoke-VcWorkflow.ps1

function Invoke-VcWorkflow {
    <#
    .SYNOPSIS
    Start a machine or machine identity workflow
 
    .DESCRIPTION
    Start a workflow to either test machine credentials or provision or discover machine identities
 
    .PARAMETER ID
    Machine or machine identity id for the workflow to trigger.
    Workflows 'Test' and 'GetConfig' require the machine ID.
    Workflows 'Provision' and 'Discover' require the machine identity ID.
 
    .PARAMETER Workflow
    The name of the workflow to trigger.
    Valid values are 'Test', 'GetConfig', 'Provision', or 'Discover'.
 
    .PARAMETER ThrottleLimit
    Limit the number of threads when running in parallel; the default is 100. Applicable to PS v7+ only.
 
    .PARAMETER VenafiSession
    Authentication for the function.
    The value defaults to the script session object $VenafiSession created by New-VenafiSession.
    A TLSPC key can also provided.
 
    .EXAMPLE
    Invoke-VcWorkflow -ID '1345baf1-fc56-49b7-aa03-78e35bfe0a1a' -Workflow 'Provision'
 
    ID Success WorkflowName WorkflowID
    -- ------- ------------ ----------
    1345baf1-fc56-49b7-aa03-78e35bfe0a1a True Provision 345b9d33-8c8a-4d4b-9fea-124f3a72f957
 
    Trigger provisioning
 
    .EXAMPLE
    Invoke-VcWorkflow -ID '1345baf1-fc56-49b7-aa03-78e35bfe0a1a' -Workflow 'Test'
 
    ID : 1345baf1-fc56-49b7-aa03-78e35bfe0a1a
    Success : False
    WorkflowName : Test
    WorkflowID : 345b9d33-8c8a-4d4b-9fea-124f3a72f957
    Error : failed to connect to Citrix ADC: [ERROR] nitro-go: Failed to create resource of type login, name=login, err=failed: 401 Unauthorized ({ "errorcode": 354,
                       "message": "Invalid username or password", "severity": "ERROR" })
 
    Trigger test connection, but it failed
 
    .EXAMPLE
    Find-VcObject -Type MachineIdentity -Filter @('and', @('certificateValidityEnd', 'lt', (get-date).AddDays(30)), @('certificateValidityEnd', 'gt', (get-date))) | ForEach-Object {
        $renewResult = $_ | Invoke-VenafiCertificateAction -Renew
        # optionally add renew validation
        $_ | Invoke-VcWorkflow -Workflow 'Provision'
    }
 
    ID Success WorkflowName WorkflowID
    -- ------- ------------ ----------
    1345baf1-fc56-49b7-aa03-78e35bfe0a1a True Provision 345b9d33-8c8a-4d4b-9fea-124f3a72f957
    89fa4370-2026-11ee-8a18-ff9579bb988e True Provision 7598917c-7027-4927-be73-e592bcc4c567
 
    Renew and provision all machine identities with certificates expiring within 30 days
 
    .INPUTS
    ID
 
    .OUTPUTS
    pscustomobject
    #>



    [CmdletBinding()]
    [Alias('Invoke-VaasWorkflow')]

    param (
        [Parameter(Mandatory, ValueFromPipeline, ValueFromPipelineByPropertyName)]
        [Alias('machineID', 'machineIdentityID')]
        [string] $ID,

        [Parameter()]
        [ValidateSet('Test', 'GetConfig', 'Provision', 'Discover')]
        [string] $Workflow = 'Test',

        [Parameter()]
        [int32] $ThrottleLimit = 100,

        [Parameter()]
        [psobject] $VenafiSession
    )

    begin {
        Test-VenafiSession -VenafiSession $VenafiSession -Platform 'VC'
        $allIDs = [System.Collections.Generic.List[string]]::new()
    }

    process {
        $allIDs.Add($ID)
    }

    end {

        Invoke-VenafiParallel -InputObject $allIDs -ScriptBlock {

            $thisID = $PSItem
            $workflow = $using:Workflow
            $thisWebSocketID = (New-Guid).Guid

            try {

                $URL = 'wss://api.venafi.cloud/ws/notificationclients/' + $thisWebSocketID
                $WS = New-Object System.Net.WebSockets.ClientWebSocket
                $CT = New-Object System.Threading.CancellationToken

                if ( $VenafiSession.GetType().Name -in 'PSCustomObject', 'VenafiSession' ) {
                    $WS.Options.SetRequestHeader("tppl-api-key", $VenafiSession.Key.GetNetworkCredential().password)
                }
                else {
                    $WS.Options.SetRequestHeader("tppl-api-key", $VenafiSession)
                }

                #Get connected
                $Conn = $WS.ConnectAsync($URL, $CT)

                While ( !$Conn.IsCompleted ) {
                    Start-Sleep -Milliseconds 100
                }

                Write-Verbose "Connecting to $($URL)..."
                $Size = 2048
                $Array = [byte[]] @(, 0) * $Size

                #Send Starting Request
                $Command = [System.Text.Encoding]::UTF8.GetBytes("ACTION=Command")
                $Send = New-Object System.ArraySegment[byte] -ArgumentList @(, $Command)
                $Conn = $WS.SendAsync($Send, [System.Net.WebSockets.WebSocketMessageType]::Text, $true, $CT)

                While (!$Conn.IsCompleted) {
                    Start-Sleep -Milliseconds 100
                }

                #Start reading the received items
                $Recv = New-Object System.ArraySegment[byte] -ArgumentList @(, $Array)
                $Conn = $WS.ReceiveAsync($Recv, $CT)

                Write-Verbose 'Triggering workflow'

                $triggerParams = @{
                    UriLeaf = "machines/$thisID/workflows"
                    Method  = 'Post'
                    Body    = @{
                        'workflowInput' = @{
                            'wsClientId' = $thisWebSocketID
                        }
                        'workflowName'  = 'testConnection'
                    }

                }

                switch ($Workflow) {
                    'GetConfig' {
                        $triggerParams.Body.workflowName = 'getTargetConfiguration'
                    }

                    'Provision' {
                        $triggerParams.Body.workflowName = 'provisionCertificate'
                        $triggerParams.UriLeaf = "machineidentities/$thisID/workflows"
                    }

                    'Discover' {
                        $triggerParams.Body.workflowName = 'discoverCertificates'
                        $triggerParams.UriLeaf = "machineidentities/$thisID/workflows"
                    }
                }

                $null = Invoke-VenafiRestMethod @triggerParams

                While (!$Conn.IsCompleted) {
                    Start-Sleep -Milliseconds 100
                }

                $response = ''
                $Recv.Array[0..($Conn.Result.Count - 1)] | ForEach-Object { $response += [char]$_ }

                Write-Verbose $response

                $responseObj = $response | ConvertFrom-Json

                $out = [pscustomobject]@{
                    ID           = $thisID
                    Success      = $true
                    WorkflowName = $Workflow
                    WorkflowID   = $thisWebSocketID
                }

                if ( $responseObj.data.result -ne $true ) {
                    $out.Success = $false
                    $out | Add-Member @{'Error' = $responseObj.data.result.message }
                }

                $out

            }
            finally {
                if ( $WS ) {
                    $WS.Dispose()
                }
            }
        } -ThrottleLimit $ThrottleLimit -ProgressTitle 'Invoking workflow'
    }
}

# SIG # Begin signature block
# MIIoFQYJKoZIhvcNAQcCoIIoBjCCKAICAQExCzAJBgUrDgMCGgUAMGkGCisGAQQB
# gjcCAQSgWzBZMDQGCisGAQQBgjcCAR4wJgIDAQAABBAfzDtgWUsITrck0sYpfvNR
# AgEAAgEAAgEAAgEAAgEAMCEwCQYFKw4DAhoFAAQUcerFb1U20t/8CsEWIaI8Lw6/
# XNWggiE9MIIFjTCCBHWgAwIBAgIQDpsYjvnQLefv21DiCEAYWjANBgkqhkiG9w0B
# AQwFADBlMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYD
# VQQLExB3d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVk
# IElEIFJvb3QgQ0EwHhcNMjIwODAxMDAwMDAwWhcNMzExMTA5MjM1OTU5WjBiMQsw
# CQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cu
# ZGlnaWNlcnQuY29tMSEwHwYDVQQDExhEaWdpQ2VydCBUcnVzdGVkIFJvb3QgRzQw
# ggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC/5pBzaN675F1KPDAiMGkz
# 7MKnJS7JIT3yithZwuEppz1Yq3aaza57G4QNxDAf8xukOBbrVsaXbR2rsnnyyhHS
# 5F/WBTxSD1Ifxp4VpX6+n6lXFllVcq9ok3DCsrp1mWpzMpTREEQQLt+C8weE5nQ7
# bXHiLQwb7iDVySAdYyktzuxeTsiT+CFhmzTrBcZe7FsavOvJz82sNEBfsXpm7nfI
# SKhmV1efVFiODCu3T6cw2Vbuyntd463JT17lNecxy9qTXtyOj4DatpGYQJB5w3jH
# trHEtWoYOAMQjdjUN6QuBX2I9YI+EJFwq1WCQTLX2wRzKm6RAXwhTNS8rhsDdV14
# Ztk6MUSaM0C/CNdaSaTC5qmgZ92kJ7yhTzm1EVgX9yRcRo9k98FpiHaYdj1ZXUJ2
# h4mXaXpI8OCiEhtmmnTK3kse5w5jrubU75KSOp493ADkRSWJtppEGSt+wJS00mFt
# 6zPZxd9LBADMfRyVw4/3IbKyEbe7f/LVjHAsQWCqsWMYRJUadmJ+9oCw++hkpjPR
# iQfhvbfmQ6QYuKZ3AeEPlAwhHbJUKSWJbOUOUlFHdL4mrLZBdd56rF+NP8m800ER
# ElvlEFDrMcXKchYiCd98THU/Y+whX8QgUWtvsauGi0/C1kVfnSD8oR7FwI+isX4K
# Jpn15GkvmB0t9dmpsh3lGwIDAQABo4IBOjCCATYwDwYDVR0TAQH/BAUwAwEB/zAd
# BgNVHQ4EFgQU7NfjgtJxXWRM3y5nP+e6mK4cD08wHwYDVR0jBBgwFoAUReuir/SS
# y4IxLVGLp6chnfNtyA8wDgYDVR0PAQH/BAQDAgGGMHkGCCsGAQUFBwEBBG0wazAk
# BggrBgEFBQcwAYYYaHR0cDovL29jc3AuZGlnaWNlcnQuY29tMEMGCCsGAQUFBzAC
# hjdodHRwOi8vY2FjZXJ0cy5kaWdpY2VydC5jb20vRGlnaUNlcnRBc3N1cmVkSURS
# b290Q0EuY3J0MEUGA1UdHwQ+MDwwOqA4oDaGNGh0dHA6Ly9jcmwzLmRpZ2ljZXJ0
# LmNvbS9EaWdpQ2VydEFzc3VyZWRJRFJvb3RDQS5jcmwwEQYDVR0gBAowCDAGBgRV
# HSAAMA0GCSqGSIb3DQEBDAUAA4IBAQBwoL9DXFXnOF+go3QbPbYW1/e/Vwe9mqyh
# hyzshV6pGrsi+IcaaVQi7aSId229GhT0E0p6Ly23OO/0/4C5+KH38nLeJLxSA8hO
# 0Cre+i1Wz/n096wwepqLsl7Uz9FDRJtDIeuWcqFItJnLnU+nBgMTdydE1Od/6Fmo
# 8L8vC6bp8jQ87PcDx4eo0kxAGTVGamlUsLihVo7spNU96LHc/RzY9HdaXFSMb++h
# UD38dglohJ9vytsgjTVgHAIDyyCwrFigDkBjxZgiwbJZ9VVrzyerbHbObyMt9H5x
# aiNrIv8SuFQtJ37YOtnwtoeW/VvRXKwYw02fc7cBqZ9Xql4o4rmUMIIGrjCCBJag
# AwIBAgIQBzY3tyRUfNhHrP0oZipeWzANBgkqhkiG9w0BAQsFADBiMQswCQYDVQQG
# EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNl
# cnQuY29tMSEwHwYDVQQDExhEaWdpQ2VydCBUcnVzdGVkIFJvb3QgRzQwHhcNMjIw
# MzIzMDAwMDAwWhcNMzcwMzIyMjM1OTU5WjBjMQswCQYDVQQGEwJVUzEXMBUGA1UE
# ChMORGlnaUNlcnQsIEluYy4xOzA5BgNVBAMTMkRpZ2lDZXJ0IFRydXN0ZWQgRzQg
# UlNBNDA5NiBTSEEyNTYgVGltZVN0YW1waW5nIENBMIICIjANBgkqhkiG9w0BAQEF
# AAOCAg8AMIICCgKCAgEAxoY1BkmzwT1ySVFVxyUDxPKRN6mXUaHW0oPRnkyibaCw
# zIP5WvYRoUQVQl+kiPNo+n3znIkLf50fng8zH1ATCyZzlm34V6gCff1DtITaEfFz
# sbPuK4CEiiIY3+vaPcQXf6sZKz5C3GeO6lE98NZW1OcoLevTsbV15x8GZY2UKdPZ
# 7Gnf2ZCHRgB720RBidx8ald68Dd5n12sy+iEZLRS8nZH92GDGd1ftFQLIWhuNyG7
# QKxfst5Kfc71ORJn7w6lY2zkpsUdzTYNXNXmG6jBZHRAp8ByxbpOH7G1WE15/teP
# c5OsLDnipUjW8LAxE6lXKZYnLvWHpo9OdhVVJnCYJn+gGkcgQ+NDY4B7dW4nJZCY
# OjgRs/b2nuY7W+yB3iIU2YIqx5K/oN7jPqJz+ucfWmyU8lKVEStYdEAoq3NDzt9K
# oRxrOMUp88qqlnNCaJ+2RrOdOqPVA+C/8KI8ykLcGEh/FDTP0kyr75s9/g64ZCr6
# dSgkQe1CvwWcZklSUPRR8zZJTYsg0ixXNXkrqPNFYLwjjVj33GHek/45wPmyMKVM
# 1+mYSlg+0wOI/rOP015LdhJRk8mMDDtbiiKowSYI+RQQEgN9XyO7ZONj4KbhPvbC
# dLI/Hgl27KtdRnXiYKNYCQEoAA6EVO7O6V3IXjASvUaetdN2udIOa5kM0jO0zbEC
# AwEAAaOCAV0wggFZMBIGA1UdEwEB/wQIMAYBAf8CAQAwHQYDVR0OBBYEFLoW2W1N
# hS9zKXaaL3WMaiCPnshvMB8GA1UdIwQYMBaAFOzX44LScV1kTN8uZz/nupiuHA9P
# MA4GA1UdDwEB/wQEAwIBhjATBgNVHSUEDDAKBggrBgEFBQcDCDB3BggrBgEFBQcB
# AQRrMGkwJAYIKwYBBQUHMAGGGGh0dHA6Ly9vY3NwLmRpZ2ljZXJ0LmNvbTBBBggr
# BgEFBQcwAoY1aHR0cDovL2NhY2VydHMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0VHJ1
# c3RlZFJvb3RHNC5jcnQwQwYDVR0fBDwwOjA4oDagNIYyaHR0cDovL2NybDMuZGln
# aWNlcnQuY29tL0RpZ2lDZXJ0VHJ1c3RlZFJvb3RHNC5jcmwwIAYDVR0gBBkwFzAI
# BgZngQwBBAIwCwYJYIZIAYb9bAcBMA0GCSqGSIb3DQEBCwUAA4ICAQB9WY7Ak7Zv
# mKlEIgF+ZtbYIULhsBguEE0TzzBTzr8Y+8dQXeJLKftwig2qKWn8acHPHQfpPmDI
# 2AvlXFvXbYf6hCAlNDFnzbYSlm/EUExiHQwIgqgWvalWzxVzjQEiJc6VaT9Hd/ty
# dBTX/6tPiix6q4XNQ1/tYLaqT5Fmniye4Iqs5f2MvGQmh2ySvZ180HAKfO+ovHVP
# ulr3qRCyXen/KFSJ8NWKcXZl2szwcqMj+sAngkSumScbqyQeJsG33irr9p6xeZmB
# o1aGqwpFyd/EjaDnmPv7pp1yr8THwcFqcdnGE4AJxLafzYeHJLtPo0m5d2aR8XKc
# 6UsCUqc3fpNTrDsdCEkPlM05et3/JWOZJyw9P2un8WbDQc1PtkCbISFA0LcTJM3c
# HXg65J6t5TRxktcma+Q4c6umAU+9Pzt4rUyt+8SVe+0KXzM5h0F4ejjpnOHdI/0d
# KNPH+ejxmF/7K9h+8kaddSweJywm228Vex4Ziza4k9Tm8heZWcpw8De/mADfIBZP
# J/tgZxahZrrdVcA6KYawmKAr7ZVBtzrVFZgxtGIJDwq9gdkT/r+k0fNX2bwE+oLe
# Mt8EifAAzV3C+dAjfwAL5HYCJtnwZXZCpimHCUcr5n8apIUP/JiW9lVUKx+A+sDy
# Divl1vupL0QVSucTDh3bNzgaoSv27dZ8/DCCBrAwggSYoAMCAQICEAitQLJg0pxM
# n17Nqb2TrtkwDQYJKoZIhvcNAQEMBQAwYjELMAkGA1UEBhMCVVMxFTATBgNVBAoT
# DERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3LmRpZ2ljZXJ0LmNvbTEhMB8GA1UE
# AxMYRGlnaUNlcnQgVHJ1c3RlZCBSb290IEc0MB4XDTIxMDQyOTAwMDAwMFoXDTM2
# MDQyODIzNTk1OVowaTELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDkRpZ2lDZXJ0LCBJ
# bmMuMUEwPwYDVQQDEzhEaWdpQ2VydCBUcnVzdGVkIEc0IENvZGUgU2lnbmluZyBS
# U0E0MDk2IFNIQTM4NCAyMDIxIENBMTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCC
# AgoCggIBANW0L0LQKK14t13VOVkbsYhC9TOM6z2Bl3DFu8SFJjCfpI5o2Fz16zQk
# B+FLT9N4Q/QX1x7a+dLVZxpSTw6hV/yImcGRzIEDPk1wJGSzjeIIfTR9TIBXEmtD
# mpnyxTsf8u/LR1oTpkyzASAl8xDTi7L7CPCK4J0JwGWn+piASTWHPVEZ6JAheEUu
# oZ8s4RjCGszF7pNJcEIyj/vG6hzzZWiRok1MghFIUmjeEL0UV13oGBNlxX+yT4Us
# SKRWhDXW+S6cqgAV0Tf+GgaUwnzI6hsy5srC9KejAw50pa85tqtgEuPo1rn3MeHc
# reQYoNjBI0dHs6EPbqOrbZgGgxu3amct0r1EGpIQgY+wOwnXx5syWsL/amBUi0nB
# k+3htFzgb+sm+YzVsvk4EObqzpH1vtP7b5NhNFy8k0UogzYqZihfsHPOiyYlBrKD
# 1Fz2FRlM7WLgXjPy6OjsCqewAyuRsjZ5vvetCB51pmXMu+NIUPN3kRr+21CiRshh
# WJj1fAIWPIMorTmG7NS3DVPQ+EfmdTCN7DCTdhSmW0tddGFNPxKRdt6/WMtyEClB
# 8NXFbSZ2aBFBE1ia3CYrAfSJTVnbeM+BSj5AR1/JgVBzhRAjIVlgimRUwcwhGug4
# GXxmHM14OEUwmU//Y09Mu6oNCFNBfFg9R7P6tuyMMgkCzGw8DFYRAgMBAAGjggFZ
# MIIBVTASBgNVHRMBAf8ECDAGAQH/AgEAMB0GA1UdDgQWBBRoN+Drtjv4XxGG+/5h
# ewiIZfROQjAfBgNVHSMEGDAWgBTs1+OC0nFdZEzfLmc/57qYrhwPTzAOBgNVHQ8B
# Af8EBAMCAYYwEwYDVR0lBAwwCgYIKwYBBQUHAwMwdwYIKwYBBQUHAQEEazBpMCQG
# CCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdpY2VydC5jb20wQQYIKwYBBQUHMAKG
# NWh0dHA6Ly9jYWNlcnRzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydFRydXN0ZWRSb290
# RzQuY3J0MEMGA1UdHwQ8MDowOKA2oDSGMmh0dHA6Ly9jcmwzLmRpZ2ljZXJ0LmNv
# bS9EaWdpQ2VydFRydXN0ZWRSb290RzQuY3JsMBwGA1UdIAQVMBMwBwYFZ4EMAQMw
# CAYGZ4EMAQQBMA0GCSqGSIb3DQEBDAUAA4ICAQA6I0Q9jQh27o+8OpnTVuACGqX4
# SDTzLLbmdGb3lHKxAMqvbDAnExKekESfS/2eo3wm1Te8Ol1IbZXVP0n0J7sWgUVQ
# /Zy9toXgdn43ccsi91qqkM/1k2rj6yDR1VB5iJqKisG2vaFIGH7c2IAaERkYzWGZ
# gVb2yeN258TkG19D+D6U/3Y5PZ7Umc9K3SjrXyahlVhI1Rr+1yc//ZDRdobdHLBg
# XPMNqO7giaG9OeE4Ttpuuzad++UhU1rDyulq8aI+20O4M8hPOBSSmfXdzlRt2V0C
# FB9AM3wD4pWywiF1c1LLRtjENByipUuNzW92NyyFPxrOJukYvpAHsEN/lYgggnDw
# zMrv/Sk1XB+JOFX3N4qLCaHLC+kxGv8uGVw5ceG+nKcKBtYmZ7eS5k5f3nqsSc8u
# pHSSrds8pJyGH+PBVhsrI/+PteqIe3Br5qC6/To/RabE6BaRUotBwEiES5ZNq0RA
# 443wFSjO7fEYVgcqLxDEDAhkPDOPriiMPMuPiAsNvzv0zh57ju+168u38HcT5uco
# P6wSrqUvImxB+YJcFWbMbA7KxYbD9iYzDAdLoNMHAmpqQDBISzSoUSC7rRuFCOJZ
# DW3KBVAr6kocnqX9oKcfBnTn8tZSkP2vhUgh+Vc7tJwD7YZF9LRhbr9o4iZghurI
# r6n+lB3nYxs6hlZ4TjCCBsIwggSqoAMCAQICEAVEr/OUnQg5pr/bP1/lYRYwDQYJ
# KoZIhvcNAQELBQAwYzELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDkRpZ2lDZXJ0LCBJ
# bmMuMTswOQYDVQQDEzJEaWdpQ2VydCBUcnVzdGVkIEc0IFJTQTQwOTYgU0hBMjU2
# IFRpbWVTdGFtcGluZyBDQTAeFw0yMzA3MTQwMDAwMDBaFw0zNDEwMTMyMzU5NTla
# MEgxCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5EaWdpQ2VydCwgSW5jLjEgMB4GA1UE
# AxMXRGlnaUNlcnQgVGltZXN0YW1wIDIwMjMwggIiMA0GCSqGSIb3DQEBAQUAA4IC
# DwAwggIKAoICAQCjU0WHHYOOW6w+VLMj4M+f1+XS512hDgncL0ijl3o7Kpxn3GIV
# WMGpkxGnzaqyat0QKYoeYmNp01icNXG/OpfrlFCPHCDqx5o7L5Zm42nnaf5bw9Yr
# IBzBl5S0pVCB8s/LB6YwaMqDQtr8fwkklKSCGtpqutg7yl3eGRiF+0XqDWFsnf5x
# XsQGmjzwxS55DxtmUuPI1j5f2kPThPXQx/ZILV5FdZZ1/t0QoRuDwbjmUpW1R9d4
# KTlr4HhZl+NEK0rVlc7vCBfqgmRN/yPjyobutKQhZHDr1eWg2mOzLukF7qr2JPUd
# vJscsrdf3/Dudn0xmWVHVZ1KJC+sK5e+n+T9e3M+Mu5SNPvUu+vUoCw0m+PebmQZ
# BzcBkQ8ctVHNqkxmg4hoYru8QRt4GW3k2Q/gWEH72LEs4VGvtK0VBhTqYggT02ke
# fGRNnQ/fztFejKqrUBXJs8q818Q7aESjpTtC/XN97t0K/3k0EH6mXApYTAA+hWl1
# x4Nk1nXNjxJ2VqUk+tfEayG66B80mC866msBsPf7Kobse1I4qZgJoXGybHGvPrhv
# ltXhEBP+YUcKjP7wtsfVx95sJPC/QoLKoHE9nJKTBLRpcCcNT7e1NtHJXwikcKPs
# CvERLmTgyyIryvEoEyFJUX4GZtM7vvrrkTjYUQfKlLfiUKHzOtOKg8tAewIDAQAB
# o4IBizCCAYcwDgYDVR0PAQH/BAQDAgeAMAwGA1UdEwEB/wQCMAAwFgYDVR0lAQH/
# BAwwCgYIKwYBBQUHAwgwIAYDVR0gBBkwFzAIBgZngQwBBAIwCwYJYIZIAYb9bAcB
# MB8GA1UdIwQYMBaAFLoW2W1NhS9zKXaaL3WMaiCPnshvMB0GA1UdDgQWBBSltu8T
# 5+/N0GSh1VapZTGj3tXjSTBaBgNVHR8EUzBRME+gTaBLhklodHRwOi8vY3JsMy5k
# aWdpY2VydC5jb20vRGlnaUNlcnRUcnVzdGVkRzRSU0E0MDk2U0hBMjU2VGltZVN0
# YW1waW5nQ0EuY3JsMIGQBggrBgEFBQcBAQSBgzCBgDAkBggrBgEFBQcwAYYYaHR0
# cDovL29jc3AuZGlnaWNlcnQuY29tMFgGCCsGAQUFBzAChkxodHRwOi8vY2FjZXJ0
# cy5kaWdpY2VydC5jb20vRGlnaUNlcnRUcnVzdGVkRzRSU0E0MDk2U0hBMjU2VGlt
# ZVN0YW1waW5nQ0EuY3J0MA0GCSqGSIb3DQEBCwUAA4ICAQCBGtbeoKm1mBe8cI1P
# ijxonNgl/8ss5M3qXSKS7IwiAqm4z4Co2efjxe0mgopxLxjdTrbebNfhYJwr7e09
# SI64a7p8Xb3CYTdoSXej65CqEtcnhfOOHpLawkA4n13IoC4leCWdKgV6hCmYtld5
# j9smViuw86e9NwzYmHZPVrlSwradOKmB521BXIxp0bkrxMZ7z5z6eOKTGnaiaXXT
# UOREEr4gDZ6pRND45Ul3CFohxbTPmJUaVLq5vMFpGbrPFvKDNzRusEEm3d5al08z
# jdSNd311RaGlWCZqA0Xe2VC1UIyvVr1MxeFGxSjTredDAHDezJieGYkD6tSRN+9N
# UvPJYCHEVkft2hFLjDLDiOZY4rbbPvlfsELWj+MXkdGqwFXjhr+sJyxB0JozSqg2
# 1Llyln6XeThIX8rC3D0y33XWNmdaifj2p8flTzU8AL2+nCpseQHc2kTmOt44Owde
# OVj0fHMxVaCAEcsUDH6uvP6k63llqmjWIso765qCNVcoFstp8jKastLYOrixRoZr
# uhf9xHdsFWyuq69zOuhJRrfVf8y2OMDY7Bz1tqG4QyzfTkx9HmhwwHcK1ALgXGC7
# KP845VJa1qwXIiNO9OzTF/tQa/8Hdx9xl0RBybhG02wyfFgvZ0dl5Rtztpn5aywG
# Ru9BHvDwX+Db2a2QgESvgBBBijCCB3wwggVkoAMCAQICEASyQEzq0fdqCZAgPWOK
# ulswDQYJKoZIhvcNAQELBQAwaTELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDkRpZ2lD
# ZXJ0LCBJbmMuMUEwPwYDVQQDEzhEaWdpQ2VydCBUcnVzdGVkIEc0IENvZGUgU2ln
# bmluZyBSU0E0MDk2IFNIQTM4NCAyMDIxIENBMTAeFw0yMzA5MTMwMDAwMDBaFw0y
# NDA5MTIyMzU5NTlaMIGDMQswCQYDVQQGEwJVUzENMAsGA1UECBMEVXRhaDEXMBUG
# A1UEBxMOU2FsdCBMYWtlIENpdHkxFTATBgNVBAoTDFZlbmFmaSwgSW5jLjEeMBwG
# A1UECxMVUHJvZmVzc2lvbmFsIFNlcnZpY2VzMRUwEwYDVQQDEwxWZW5hZmksIElu
# Yy4wggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDPaBrbDQ0fOiorU2nC
# Zx7SrZVmSiwwhrgzDh4WENmJKVpZbBdtYoERBUQSd3+Y+WY4y/aPAEQ9oF1PNfhu
# nkDiCvY3CnDYeOv2ex8G64w1WQIKKZd2OpsuGLJTShshiT7kQwfQufCfUC6lNuO2
# PreSqztkN8tFWrqNS0YlV18MoGsgCPKZ49eLnwbX33UnqLyiDe8qGE73uxZyIZct
# uWKtQU0ylmkrfZSsevZCSUiqFKjW5y9NPvHwQVbk/ffPZ6eJAIO+ywRSxXu8N1zj
# OWXaKj4HWPu9U6Jwsb4/wnGGPLXex4qyYBdLB8gPnW1Y7dXZJ8RkTbF+7FE31ss5
# 1fIH3zTyJ8gDLEubPfoqruRpf8tDp4Z5UPBue90BShRwIpgYrsU9hCEnRmfG1clE
# p9BTistpki1W2cls99cYlfVpcljXR8plK+cR9hGtxvqkxUXELIAyhkRTddKD1tLS
# hz1+D4VOOSdzPJcWMwP3s9lbwZwsBdZK6Ruy3LNIe+HQ2He3IbJc/LL7IbEyoDDp
# 6WincVwbWyrpGL2BI0D6gLMPZV/Cgqk8meiYsMati4Jgz9TVYbaGL/OCeGf8u797
# wUpOQjxlGFUHVh+/hWCvEZLHRYEj7hYHoHCLouNWZK5qwlnQ6huXuKTn2eSx5hzz
# zlTluOBZmtRteF/DfiVStWR8yQIDAQABo4ICAzCCAf8wHwYDVR0jBBgwFoAUaDfg
# 67Y7+F8Rhvv+YXsIiGX0TkIwHQYDVR0OBBYEFKgZ4jlQ/frPU8WlXRbihgk1MZUo
# MD4GA1UdIAQ3MDUwMwYGZ4EMAQQBMCkwJwYIKwYBBQUHAgEWG2h0dHA6Ly93d3cu
# ZGlnaWNlcnQuY29tL0NQUzAOBgNVHQ8BAf8EBAMCB4AwEwYDVR0lBAwwCgYIKwYB
# BQUHAwMwgbUGA1UdHwSBrTCBqjBToFGgT4ZNaHR0cDovL2NybDMuZGlnaWNlcnQu
# Y29tL0RpZ2lDZXJ0VHJ1c3RlZEc0Q29kZVNpZ25pbmdSU0E0MDk2U0hBMzg0MjAy
# MUNBMS5jcmwwU6BRoE+GTWh0dHA6Ly9jcmw0LmRpZ2ljZXJ0LmNvbS9EaWdpQ2Vy
# dFRydXN0ZWRHNENvZGVTaWduaW5nUlNBNDA5NlNIQTM4NDIwMjFDQTEuY3JsMIGU
# BggrBgEFBQcBAQSBhzCBhDAkBggrBgEFBQcwAYYYaHR0cDovL29jc3AuZGlnaWNl
# cnQuY29tMFwGCCsGAQUFBzAChlBodHRwOi8vY2FjZXJ0cy5kaWdpY2VydC5jb20v
# RGlnaUNlcnRUcnVzdGVkRzRDb2RlU2lnbmluZ1JTQTQwOTZTSEEzODQyMDIxQ0Ex
# LmNydDAJBgNVHRMEAjAAMA0GCSqGSIb3DQEBCwUAA4ICAQANZ3pxjdxS5dfEWE7g
# 75U9E/E2K25iik7LeuC8uKjpidxh9tt9kpGYoFhvv0B7pz82zPords+WGz1S5ezp
# RWVXBGEel/zDWSjUj2VkuNkzyBuC9d62HIgHdu8MOstfIRJRfiIAv9QM3K4OOxAE
# 5N77ta/Jc+tmGqUkvSTA7qRowV9+b5X7NpMGtJrNyjsYuVdW2nr6NZgQdJ3PJp42
# Bjk3iPecqWx1WjguHKe7KoL1pPJZ/EL0o8qlE2r20bGRMfKN4IHrVj/IDoLrcakO
# Z+hm0PTHjqfOvWvsAblz/9N36D2woDitpqLZHFyYtfCggQb/lb/rRwpMBTjgSdRb
# h6n+uY8EEumKdjdyD6TZvlSMEhRth5tqdFUeJmaAK0spBgsd0fzK70tlz3ojp0aa
# bTwLzOxk9PKJiD0lp0o+UB2QjewHV3zbrdR+xrrO8cS9IrdCe60vEd9053/tdHCp
# JbH+heuTyOCC8CjcgAYRf9L5xEGMVi2Ypm6FlQ9BKHwtuJR+xEuwb92iagonDUlV
# m5t4U5GAHLKxyogMAigCm2PJl6golqX4wXUOGQacF6FQ11l76riHjdyvnvcJmXhd
# nBjnDfLd6RzgCGWz2QT9W8yqTEZ8ehOzCZpJUzcQm5nnUUKDTnjOiRoESDFnj/n2
# C+NQp9E25RgLwV8Pkt2PSgjbVDGCBkIwggY+AgEBMH0waTELMAkGA1UEBhMCVVMx
# FzAVBgNVBAoTDkRpZ2lDZXJ0LCBJbmMuMUEwPwYDVQQDEzhEaWdpQ2VydCBUcnVz
# dGVkIEc0IENvZGUgU2lnbmluZyBSU0E0MDk2IFNIQTM4NCAyMDIxIENBMQIQBLJA
# TOrR92oJkCA9Y4q6WzAJBgUrDgMCGgUAoHgwGAYKKwYBBAGCNwIBDDEKMAigAoAA
# oQKAADAZBgkqhkiG9w0BCQMxDAYKKwYBBAGCNwIBBDAcBgorBgEEAYI3AgELMQ4w
# DAYKKwYBBAGCNwIBFTAjBgkqhkiG9w0BCQQxFgQUGxyOtad/1InOvSXf6Fhj40F6
# kO8wDQYJKoZIhvcNAQEBBQAEggIAEp30Q6jiod7t1M3WJJIzZviG3KR0llTU1ijS
# OXmLM1z0VaRBcyuhcPpWFFtnbfRo1Q6C9uQqmV8JbYvFZC4dWmQs7VYqebI0EunG
# Nj5nzSA9rnPY0ns7kOdsrydT2r0j8rDN8KRP7z7TfdL7DoY/xp5kPHGqWIpLenV9
# +NRQ91pwrecHieMeWUI2N1YHjOqRbIXdv7d+/EwYXEr0zCGf6oyhJcoTVDO0OiWR
# mUOXVm/kS3i8ooJjLty2Gj2E6+EB8/EKVRDx6N3gIED8n0qlidEPsQ6Fn18fCZr1
# X26mmSPvnBGjbjyPxAAqd9x+CZM6fOFky5nhS6yHTQLkDu5JIYOsgGHJjjMj09Kg
# 0c8DWz+0DoLOr1opq8SC17TKz1kkr7pZWaAC5Xirj0/ZK8O0WV4oMr37+M6myz+A
# RGCwUEyASf9nINF4UYgukx2uf6sqUUyNYdg+yH/nf9h5A+ZezpRJuivTWvjw04Dk
# q1LMI9N3Dk/i2ahzZcxBoWSufCD74PPx3X261NHBb9gQqShMDkckAM0iRqGzCjTO
# a1gA+LKCSiG8YnKPyYFE2PlBakQdq4kp8uk6lZTywZDOnT/pjglDfPo4F9BGl6sH
# up1sT0tJn+kipTWAcwzKPooF97zOW4P5p3ck6BhBSzh9lVNeEJKipP52AX59AjyN
# GgZe1fWhggMgMIIDHAYJKoZIhvcNAQkGMYIDDTCCAwkCAQEwdzBjMQswCQYDVQQG
# EwJVUzEXMBUGA1UEChMORGlnaUNlcnQsIEluYy4xOzA5BgNVBAMTMkRpZ2lDZXJ0
# IFRydXN0ZWQgRzQgUlNBNDA5NiBTSEEyNTYgVGltZVN0YW1waW5nIENBAhAFRK/z
# lJ0IOaa/2z9f5WEWMA0GCWCGSAFlAwQCAQUAoGkwGAYJKoZIhvcNAQkDMQsGCSqG
# SIb3DQEHATAcBgkqhkiG9w0BCQUxDxcNMjQwMTA4MTYyMzU1WjAvBgkqhkiG9w0B
# CQQxIgQgj8Eof2NRXa5tAqKAzaBR3KKdPlceb0jTY9YU/UP2No4wDQYJKoZIhvcN
# AQEBBQAEggIAnSae6kRHVj3BqHlS3WXJUTltXRka933J4cvqvBZ2XXIwl0LTSwy4
# 6VezDYnhGVttFx5Uli35Fd0fCj4860dMEwrCSM813PdMVOkJ5mRFBC+99tNfN74T
# Qib1cydhjb8UMvuN5GlPcKhrnc8IH83AvpGjDr/bXAXQjOD8AtfpgYe3e9MMuNSD
# uObHGDgaCefqv1VCvyhu8lPKK+IHhyJI6OLeSGO2xuP8qKOmP28u8PpKtpP75GXJ
# YgNKuI0sjtfqXAUU0BODybYzoBJ5EaAE+NdSKK6K1V5LjITOdKKFDHSHIEpHbElw
# 2BcqSgPrF+4ednkR+UM34z9Z3SWjm2bs6KEtSWxCxBYh+FmYuplDNGcOYjNZ277f
# xLbQgyYBKGCs53P+zzGT3jDShButqrb6dfq+BY7dzK47wbMxx599uu3XaWS7j39X
# Iw09byJYXPIo+FGKtRXp+o6grRMT2oDwl9+o+y5PljxGup6xIzbf1M84Cd+vx/6H
# 19yeloNQGDSoP1ihrLu1XXIbsRyBb///FfCJ8zC7HaZheyor4layhR+u9zoN89+r
# Mji4Jw6o4DwUDasvsqJjG9AKv96GfgLAN3IaEPPfRJW+/ecCbhde/AlLUAu/tBHt
# bhAPzd+JXzjtkCz/KvVl2CR/ORxtswU0qddCnsvMfmk8SgZTuBZVIBs=
# SIG # End signature block