Test-ActivityScript.ps1

<#PSScriptInfo
 
.VERSION 1.0
 
.GUID 49f9e069-aa11-45fd-84f8-7f3ce8ee9317
 
.AUTHOR Kirk Munro
 
.COMPANYNAME Learn on Demand Systems
 
.COPYRIGHT 2018
 
.TAGS Lab Demand LOD Activity Scoring Life Cycle Action Actions
 
.LICENSEURI
 
.PROJECTURI https://github.com/LearnOnDemandSystems/LabAuthor
 
.ICONURI
 
.EXTERNALMODULEDEPENDENCIES
 
.REQUIREDSCRIPTS
 
.EXTERNALSCRIPTDEPENDENCIES
 
.RELEASENOTES
 
.PRIVATEDATA
 
#>


<#
.SYNOPSIS
    Runs an activity script in a very similar manner to how it would be run in Lab on Demand.
.DESCRIPTION
    The Test-ActivityScript command runs an activity script in a very similar manner to how
    it would be run in Lab on Demand.
.EXAMPLE
    PS C:\>$tenant = '44443110-be10-4d21-81cd-516a52dfab13'
 
    PS C:\>$sub = 'ed2efd04-3e88-4df9-8b3c-cf816a1c2571'
 
    PS C:\>$creds = Get-Credential -UserName 'morgan@careerrockit.com'
 
    PS C:\>Test-ActivityScript -TenantId $tenant -SubscriptionId $sub -Credential $creds -ScriptBlock {
        Send-LabNotification -Message 'Inside script'
        Get-AzureRmResourceGroup
    }
 
    This command invokes an activity script that retrieves all resource groups from the Azure
    tenant/scription specified, using the morgan@careerrockit.com account. The activity script
    also sends a notification to the lab when run inside of Lab on Demand as an activity;
    however, when testing outside of Lab on Demand, the Send-LabNotification command will
    simply write a message to the information stream.
.EXAMPLE
    PS C:\>$accessKey = 'AWPY2REJKOIMWQ5WZ8QA'
 
    PS C:\>$secretKey = 'vzjkRUVR/qXRvGOa3eU6qLbWLJ+h6Vv1PebBjvvj'
 
    PS C:\>Test-ActivityScript -AccessKey $accessKey -SecretKey $secretKey -ScriptBlock {
        Send-LabNotification -Message 'Inside script'
        Get-IAMUser
    }
 
    This command invokes an activity script that retrieves all IAM users from the AWS account
    associated with the access key and secret key specified. The activity script also sends a
    notification to the lab when run inside of Lab on Demand as an activity; however, when
    testing outside of Lab on Demand, the Send-LabNotification command will simply write a
    message to the information stream.
.INPUTS
    None
.OUTPUTS
    Whatever your activity script outputs.
.NOTES
    Even if an activity script works when run this way, it may still have issues when run in
    Lab on Demand, so you must still test your activity scripts in Lab on Demand. The advantage
    to performing testing outside of Lab on Demand is that you can step through and debug your
    script, and see all output more easily. A best practice is to get the script working the
    way that you want outside of Lab on Demand, and then copy it into Lab on Demand to make
    sure it works the same way there.
#>

[CmdletBinding(DefaultParameterSetName='Azure')]
[System.Diagnostics.DebuggerStepThrough()]
param(
    # The id (guid) of your Azure tenant.
    [Parameter(Position=0, Mandatory=$true, HelpMessage='The Azure tenant id.', ParameterSetName='Azure')]
    [ValidateScript({
        [CmdletBinding()]
        [System.Diagnostics.DebuggerHidden()]
        param()
        if ($_ -eq [System.Guid]::Empty) {
            throw 'You must provide a non-empty GUID for the TenantId parameter.'
        }
        $true
    })]
    [System.Guid]
    $TenantId,

    # The id (guid) of your Azure subscription.
    [Parameter(Position=1, Mandatory=$true, HelpMessage='The Azure subscription id.', ParameterSetName='Azure')]
    [ValidateScript({
        [CmdletBinding()]
        [System.Diagnostics.DebuggerHidden()]
        param()
        if ($_ -eq [System.Guid]::Empty) {
            throw 'You must provide a non-empty GUID for the SubscriptionId parameter.'
        }
        $true
    })]
    [System.Guid]
    $SubscriptionId,

    # The credentials for an Azure account that will be used to run the script.
    [Parameter(Position=2, Mandatory=$true, HelpMessage='The user credentials used to run the script against the Azure subscription.', ParameterSetName='Azure')]
    [ValidateScript({
        [CmdletBinding()]
        [System.Diagnostics.DebuggerHidden()]
        param()
        if ($_ -eq [System.Management.Automation.PSCredential]::Empty) {
            throw 'You must provide non-empty credentials for the Credential parameter.'
        }
        $true
    })]
    [System.Management.Automation.PSCredential]
    [System.Management.Automation.Credential()]
    $Credential,

    # Indicates that the Azure account credentials identify an Azure service principal. By default Azure account credentials identify an Azure user.
    [Parameter(ParameterSetName='Azure')]
    [System.Management.Automation.SwitchParameter]
    $ServicePrincipal,

    # The access key for the AWS IAM user that will be used to run the script.
    [Parameter(Position=0, Mandatory=$true, HelpMessage='The AWS access key.', ParameterSetName='AWS')]
    [ValidateNotNullOrEmpty()]
    [System.String]
    $AccessKey,

    # The secret for the AWS IAM user that will be used to run the script.
    [Parameter(Position=1, Mandatory=$true, HelpMessage='The AWS secret key.', ParameterSetName='AWS')]
    [ValidateNotNullOrEmpty()]
    [System.String]
    $SecretKey,

    # The activity script that you want to run.
    [Parameter(Position=3, Mandatory=$true, HelpMessage='The script you want to run.', ParameterSetName='Azure')]
    [Parameter(Position=2, Mandatory=$true, HelpMessage='The script you want to run.', ParameterSetName='AWS')]
    [ValidateNotNull()]
    [System.Management.Automation.ScriptBlock]
    $ScriptBlock
)

try {
    $oldPSDefaultParameterValueKeys = @($PSDefaultParameterValues.Keys)
    $PSDefaultParameterValues['Write-Verbose:Verbose'] = $true
    $PSDefaultParameterValues['Write-Information:InformationAction'] = [System.Management.Automation.ActionPreference]::Continue
    $ErrorActionPreference = [System.Management.Automation.ActionPreference]::Stop
    try {
        switch ($PSCmdlet.ParameterSetName) {
            'Azure' {
                $passThruParameters = @{
                        TenantId = $TenantId
                    Subscription = $SubscriptionId
                        Credential = $Credential
                }
                if ($PSCmdlet.MyInvocation.BoundParameters.ContainsKey('ServicePrincipal') -and $ServicePrincipal) {
                    $passThruParameters.Add('ServicePrincipal',$true)
                }
                Connect-AzureRmAccount @passThruParameters > $null
                break
            }
            'AWS' {
                $passThruParameters = @{
                    AccessKey = $AccessKey
                    SecretKey = $SecretKey
                }
                Set-AWSCredential @passThruParameters
                break
            }
        }

        function Send-LabNotification {
            [CmdletBinding()]
            param(
                [Parameter(Position=0, Mandatory=$true, ValueFromPipeline=$true)]
                [ValidateNotNullOrEmpty()]
                [Alias('Msg')]
                [System.String]
                $Message
            )
            Write-Information -MessageData "LAB NOTIFICATION MESSAGE: ${Message}"   
        }

        . $ScriptBlock
    } finally {
        switch ($PSCmdlet.ParameterSetName) {
            'Azure' {
                Disconnect-AzureRmAccount -Username $Credential.UserName > $null
            }
            'AWS' {
                Clear-AWSCredential
            }
        }
    }
} catch {
    throw
} finally {
    foreach ($key in @($PSDefaultParameterValues.Keys)) {
        if ($oldPSDefaultParameterValueKeys -notcontains $key) {
            $PSDefaultParameterValues.Remove($key)
        }
    }
}

# SIG # Begin signature block
# MIIX0AYJKoZIhvcNAQcCoIIXwTCCF70CAQExCzAJBgUrDgMCGgUAMGkGCisGAQQB
# gjcCAQSgWzBZMDQGCisGAQQBgjcCAR4wJgIDAQAABBAfzDtgWUsITrck0sYpfvNR
# AgEAAgEAAgEAAgEAAgEAMCEwCQYFKw4DAhoFAAQUL4NqGg/2F3KGz88eLjtPg2sn
# P6+gghMDMIID7jCCA1egAwIBAgIQfpPr+3zGTlnqS5p31Ab8OzANBgkqhkiG9w0B
# AQUFADCBizELMAkGA1UEBhMCWkExFTATBgNVBAgTDFdlc3Rlcm4gQ2FwZTEUMBIG
# A1UEBxMLRHVyYmFudmlsbGUxDzANBgNVBAoTBlRoYXd0ZTEdMBsGA1UECxMUVGhh
# d3RlIENlcnRpZmljYXRpb24xHzAdBgNVBAMTFlRoYXd0ZSBUaW1lc3RhbXBpbmcg
# Q0EwHhcNMTIxMjIxMDAwMDAwWhcNMjAxMjMwMjM1OTU5WjBeMQswCQYDVQQGEwJV
# UzEdMBsGA1UEChMUU3ltYW50ZWMgQ29ycG9yYXRpb24xMDAuBgNVBAMTJ1N5bWFu
# dGVjIFRpbWUgU3RhbXBpbmcgU2VydmljZXMgQ0EgLSBHMjCCASIwDQYJKoZIhvcN
# AQEBBQADggEPADCCAQoCggEBALGss0lUS5ccEgrYJXmRIlcqb9y4JsRDc2vCvy5Q
# WvsUwnaOQwElQ7Sh4kX06Ld7w3TMIte0lAAC903tv7S3RCRrzV9FO9FEzkMScxeC
# i2m0K8uZHqxyGyZNcR+xMd37UWECU6aq9UksBXhFpS+JzueZ5/6M4lc/PcaS3Er4
# ezPkeQr78HWIQZz/xQNRmarXbJ+TaYdlKYOFwmAUxMjJOxTawIHwHw103pIiq8r3
# +3R8J+b3Sht/p8OeLa6K6qbmqicWfWH3mHERvOJQoUvlXfrlDqcsn6plINPYlujI
# fKVOSET/GeJEB5IL12iEgF1qeGRFzWBGflTBE3zFefHJwXECAwEAAaOB+jCB9zAd
# BgNVHQ4EFgQUX5r1blzMzHSa1N197z/b7EyALt0wMgYIKwYBBQUHAQEEJjAkMCIG
# CCsGAQUFBzABhhZodHRwOi8vb2NzcC50aGF3dGUuY29tMBIGA1UdEwEB/wQIMAYB
# Af8CAQAwPwYDVR0fBDgwNjA0oDKgMIYuaHR0cDovL2NybC50aGF3dGUuY29tL1Ro
# YXd0ZVRpbWVzdGFtcGluZ0NBLmNybDATBgNVHSUEDDAKBggrBgEFBQcDCDAOBgNV
# HQ8BAf8EBAMCAQYwKAYDVR0RBCEwH6QdMBsxGTAXBgNVBAMTEFRpbWVTdGFtcC0y
# MDQ4LTEwDQYJKoZIhvcNAQEFBQADgYEAAwmbj3nvf1kwqu9otfrjCR27T4IGXTdf
# plKfFo3qHJIJRG71betYfDDo+WmNI3MLEm9Hqa45EfgqsZuwGsOO61mWAK3ODE2y
# 0DGmCFwqevzieh1XTKhlGOl5QGIllm7HxzdqgyEIjkHq3dlXPx13SYcqFgZepjhq
# IhKjURmDfrYwggSjMIIDi6ADAgECAhAOz/Q4yP6/NW4E2GqYGxpQMA0GCSqGSIb3
# DQEBBQUAMF4xCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3Jh
# dGlvbjEwMC4GA1UEAxMnU3ltYW50ZWMgVGltZSBTdGFtcGluZyBTZXJ2aWNlcyBD
# QSAtIEcyMB4XDTEyMTAxODAwMDAwMFoXDTIwMTIyOTIzNTk1OVowYjELMAkGA1UE
# BhMCVVMxHTAbBgNVBAoTFFN5bWFudGVjIENvcnBvcmF0aW9uMTQwMgYDVQQDEytT
# eW1hbnRlYyBUaW1lIFN0YW1waW5nIFNlcnZpY2VzIFNpZ25lciAtIEc0MIIBIjAN
# BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAomMLOUS4uyOnREm7Dv+h8GEKU5Ow
# mNutLA9KxW7/hjxTVQ8VzgQ/K/2plpbZvmF5C1vJTIZ25eBDSyKV7sIrQ8Gf2Gi0
# jkBP7oU4uRHFI/JkWPAVMm9OV6GuiKQC1yoezUvh3WPVF4kyW7BemVqonShQDhfu
# ltthO0VRHc8SVguSR/yrrvZmPUescHLnkudfzRC5xINklBm9JYDh6NIipdC6Anqh
# d5NbZcPuF3S8QYYq3AhMjJKMkS2ed0QfaNaodHfbDlsyi1aLM73ZY8hJnTrFxeoz
# C9Lxoxv0i77Zs1eLO94Ep3oisiSuLsdwxb5OgyYI+wu9qU+ZCOEQKHKqzQIDAQAB
# o4IBVzCCAVMwDAYDVR0TAQH/BAIwADAWBgNVHSUBAf8EDDAKBggrBgEFBQcDCDAO
# BgNVHQ8BAf8EBAMCB4AwcwYIKwYBBQUHAQEEZzBlMCoGCCsGAQUFBzABhh5odHRw
# Oi8vdHMtb2NzcC53cy5zeW1hbnRlYy5jb20wNwYIKwYBBQUHMAKGK2h0dHA6Ly90
# cy1haWEud3Muc3ltYW50ZWMuY29tL3Rzcy1jYS1nMi5jZXIwPAYDVR0fBDUwMzAx
# oC+gLYYraHR0cDovL3RzLWNybC53cy5zeW1hbnRlYy5jb20vdHNzLWNhLWcyLmNy
# bDAoBgNVHREEITAfpB0wGzEZMBcGA1UEAxMQVGltZVN0YW1wLTIwNDgtMjAdBgNV
# HQ4EFgQURsZpow5KFB7VTNpSYxc/Xja8DeYwHwYDVR0jBBgwFoAUX5r1blzMzHSa
# 1N197z/b7EyALt0wDQYJKoZIhvcNAQEFBQADggEBAHg7tJEqAEzwj2IwN3ijhCcH
# bxiy3iXcoNSUA6qGTiWfmkADHN3O43nLIWgG2rYytG2/9CwmYzPkSWRtDebDZw73
# BaQ1bHyJFsbpst+y6d0gxnEPzZV03LZc3r03H0N45ni1zSgEIKOq8UvEiCmRDoDR
# EfzdXHZuT14ORUZBbg2w6jiasTraCXEQ/Bx5tIB7rGn0/Zy2DBYr8X9bCT2bW+IW
# yhOBbQAuOA2oKY8s4bL0WqkBrxWcLC9JG9siu8P+eJRRw4axgohd8D20UaF5Mysu
# e7ncIAkTcetqGVvP6KUwVyyJST+5z3/Jvz4iaGNTmr1pdKzFHTx/kuDDvBzYBHUw
# ggUwMIIEGKADAgECAhAECRgbX9W7ZnVTQ7VvlVAIMA0GCSqGSIb3DQEBCwUAMGUx
# CzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3
# dy5kaWdpY2VydC5jb20xJDAiBgNVBAMTG0RpZ2lDZXJ0IEFzc3VyZWQgSUQgUm9v
# dCBDQTAeFw0xMzEwMjIxMjAwMDBaFw0yODEwMjIxMjAwMDBaMHIxCzAJBgNVBAYT
# AlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2Vy
# dC5jb20xMTAvBgNVBAMTKERpZ2lDZXJ0IFNIQTIgQXNzdXJlZCBJRCBDb2RlIFNp
# Z25pbmcgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQD407Mcfw4R
# r2d3B9MLMUkZz9D7RZmxOttE9X/lqJ3bMtdx6nadBS63j/qSQ8Cl+YnUNxnXtqrw
# nIal2CWsDnkoOn7p0WfTxvspJ8fTeyOU5JEjlpB3gvmhhCNmElQzUHSxKCa7JGnC
# wlLyFGeKiUXULaGj6YgsIJWuHEqHCN8M9eJNYBi+qsSyrnAxZjNxPqxwoqvOf+l8
# y5Kh5TsxHM/q8grkV7tKtel05iv+bMt+dDk2DZDv5LVOpKnqagqrhPOsZ061xPeM
# 0SAlI+sIZD5SlsHyDxL0xY4PwaLoLFH3c7y9hbFig3NBggfkOItqcyDQD2RzPJ6f
# pjOp/RnfJZPRAgMBAAGjggHNMIIByTASBgNVHRMBAf8ECDAGAQH/AgEAMA4GA1Ud
# DwEB/wQEAwIBhjATBgNVHSUEDDAKBggrBgEFBQcDAzB5BggrBgEFBQcBAQRtMGsw
# JAYIKwYBBQUHMAGGGGh0dHA6Ly9vY3NwLmRpZ2ljZXJ0LmNvbTBDBggrBgEFBQcw
# AoY3aHR0cDovL2NhY2VydHMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0QXNzdXJlZElE
# Um9vdENBLmNydDCBgQYDVR0fBHoweDA6oDigNoY0aHR0cDovL2NybDQuZGlnaWNl
# cnQuY29tL0RpZ2lDZXJ0QXNzdXJlZElEUm9vdENBLmNybDA6oDigNoY0aHR0cDov
# L2NybDMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0QXNzdXJlZElEUm9vdENBLmNybDBP
# BgNVHSAESDBGMDgGCmCGSAGG/WwAAgQwKjAoBggrBgEFBQcCARYcaHR0cHM6Ly93
# d3cuZGlnaWNlcnQuY29tL0NQUzAKBghghkgBhv1sAzAdBgNVHQ4EFgQUWsS5eyoK
# o6XqcQPAYPkt9mV1DlgwHwYDVR0jBBgwFoAUReuir/SSy4IxLVGLp6chnfNtyA8w
# DQYJKoZIhvcNAQELBQADggEBAD7sDVoks/Mi0RXILHwlKXaoHV0cLToaxO8wYdd+
# C2D9wz0PxK+L/e8q3yBVN7Dh9tGSdQ9RtG6ljlriXiSBThCk7j9xjmMOE0ut119E
# efM2FAaK95xGTlz/kLEbBw6RFfu6r7VRwo0kriTGxycqoSkoGjpxKAI8LpGjwCUR
# 4pwUR6F6aGivm6dcIFzZcbEMj7uo+MUSaJ/PQMtARKUT8OZkDCUIQjKyNookAv4v
# cn4c10lFluhZHen6dGRrsutmQ9qzsIzV6Q3d9gEgzpkxYz0IGhizgZtPxpMQBvwH
# gfqL2vmCSfdibqFT+hKUGIUukpHqaGxEMrJmoecYpJpkUe8wggUyMIIEGqADAgEC
# AhAF6V5I5jKh5PIOTECyjmcvMA0GCSqGSIb3DQEBCwUAMHIxCzAJBgNVBAYTAlVT
# MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j
# b20xMTAvBgNVBAMTKERpZ2lDZXJ0IFNIQTIgQXNzdXJlZCBJRCBDb2RlIFNpZ25p
# bmcgQ0EwHhcNMTgwNDEwMDAwMDAwWhcNMTgxMjE5MTIwMDAwWjBvMQswCQYDVQQG
# EwJDQTEWMBQGA1UECBMNTmV3IEJydW5zd2ljazEQMA4GA1UEBxMHU2hlZGlhYzEa
# MBgGA1UEChMRS2lyayBBbmRyZXcgTXVucm8xGjAYBgNVBAMTEUtpcmsgQW5kcmV3
# IE11bnJvMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA+LFqxPDdvIdO
# MtmTzZEUA0KVdwFo1s23OAuqmOQweomPauxEVegB+x9+FoFG6cAZVoZ9Q+eW/Avg
# Nc44S2WQPKIFKhV8EJYdWgB/n6z3I6yW5LPlGjyNB6Zbl85CA6qKq+3HVpPl6Wjw
# Pw94/1VcP9Eqx7KQq1ZHWmPmjCMe1wtrbaI+W7SO4pdZh25Wy5kh6BHN6KRlh6VA
# T718STxEDu0pMJdfB6i+uPvntbEt/158yc1da3ZmE8Neej5p7QcWWOiM3TC6hbCQ
# TZfl0ybyAIPB9sbUqG8SFzMYyAb8zSiUC5JeQcM5qkmmqm4ymW0d8YHhQcPX+dhm
# SUbrRS+98QIDAQABo4IBxTCCAcEwHwYDVR0jBBgwFoAUWsS5eyoKo6XqcQPAYPkt
# 9mV1DlgwHQYDVR0OBBYEFCDLJR7k6dkAmWoQu4UhyNZjy7g0MA4GA1UdDwEB/wQE
# AwIHgDATBgNVHSUEDDAKBggrBgEFBQcDAzB3BgNVHR8EcDBuMDWgM6Axhi9odHRw
# Oi8vY3JsMy5kaWdpY2VydC5jb20vc2hhMi1hc3N1cmVkLWNzLWcxLmNybDA1oDOg
# MYYvaHR0cDovL2NybDQuZGlnaWNlcnQuY29tL3NoYTItYXNzdXJlZC1jcy1nMS5j
# cmwwTAYDVR0gBEUwQzA3BglghkgBhv1sAwEwKjAoBggrBgEFBQcCARYcaHR0cHM6
# Ly93d3cuZGlnaWNlcnQuY29tL0NQUzAIBgZngQwBBAEwgYQGCCsGAQUFBwEBBHgw
# djAkBggrBgEFBQcwAYYYaHR0cDovL29jc3AuZGlnaWNlcnQuY29tME4GCCsGAQUF
# BzAChkJodHRwOi8vY2FjZXJ0cy5kaWdpY2VydC5jb20vRGlnaUNlcnRTSEEyQXNz
# dXJlZElEQ29kZVNpZ25pbmdDQS5jcnQwDAYDVR0TAQH/BAIwADANBgkqhkiG9w0B
# AQsFAAOCAQEASD7vvOBljJJuQTwD0I+J8ZouxDK8ORJ/2JUUslEFIIZRobfInmzV
# d4ESbqn3vl8XLiBV3l4eFPm7B2Pqinm8zC6bbCig1ZwO5D42vDfVuQ5Go0tG5obj
# jCmmnCNp+jhzEJrJS9Ioz3qeAzqsMTPzMQKsevOfIUoFjeWJt2MkfpcswdvLv4oD
# VEVyLHYA52fDm6YdKxKfDlaizRPIU6jbkV9lO8SuSxpjgepPlRpNRRwDxC2R56Og
# UB7Ob1wcUSMfm67mCougUumXL8bUbMdWgCZYhJT2AxtfeL6RImULxqkEarZJXmpe
# 1PgQWT3+V2cEgjejgjHZDT3q0sxOeeZzyTGCBDcwggQzAgEBMIGGMHIxCzAJBgNV
# BAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdp
# Y2VydC5jb20xMTAvBgNVBAMTKERpZ2lDZXJ0IFNIQTIgQXNzdXJlZCBJRCBDb2Rl
# IFNpZ25pbmcgQ0ECEAXpXkjmMqHk8g5MQLKOZy8wCQYFKw4DAhoFAKB4MBgGCisG
# AQQBgjcCAQwxCjAIoAKAAKECgAAwGQYJKoZIhvcNAQkDMQwGCisGAQQBgjcCAQQw
# HAYKKwYBBAGCNwIBCzEOMAwGCisGAQQBgjcCARUwIwYJKoZIhvcNAQkEMRYEFMSC
# /doRzUrvanF1M2yAnkRZr93eMA0GCSqGSIb3DQEBAQUABIIBAPR24lczVPKeD2x5
# XI74Z7a/uXDaTZ15vYHuFmxt7Os88GISDcOfm45CUZu2gNF57rYSAt57W/GcYiP9
# eJ5GxoCyfWRXEXt+OLx0Ek83/1Dgp+G7IAQOFMBUrvOpPTmNxRHCWBoAv+lACJNz
# nd7Z0JXE3Q+aPDlOJwvB2NEnXN2/bf8b1H4eTEa+SmaRAJVQiTRD6WR/AETXpX8d
# X29SRptmWyt4Pf+DG+A4eZ/C89ws0edvMubRKB9mgECiyiwfwYAvAfYJ/gCVfGRo
# d4+L/mFYJsR3KYmki0yB07gWmOF7oIDDZNrficPwfc9i01CNL750JNyiAg8+iB18
# Pdj4tbyhggILMIICBwYJKoZIhvcNAQkGMYIB+DCCAfQCAQEwcjBeMQswCQYDVQQG
# EwJVUzEdMBsGA1UEChMUU3ltYW50ZWMgQ29ycG9yYXRpb24xMDAuBgNVBAMTJ1N5
# bWFudGVjIFRpbWUgU3RhbXBpbmcgU2VydmljZXMgQ0EgLSBHMgIQDs/0OMj+vzVu
# BNhqmBsaUDAJBgUrDgMCGgUAoF0wGAYJKoZIhvcNAQkDMQsGCSqGSIb3DQEHATAc
# BgkqhkiG9w0BCQUxDxcNMTgwNzEzMjI1MTQ4WjAjBgkqhkiG9w0BCQQxFgQUTUuJ
# WBXGNYoh9xlnx+6ckzA8LFQwDQYJKoZIhvcNAQEBBQAEggEActhGLoTLBCBTkt6r
# JKx39HjPs+EZAgO4QK6iKyGhGW0zCly7s8vFRKV3vG/V3GSwCJljZPn/ocIkcyWQ
# cK23kpsQxfsoG901fHBmlHg6Evl+660nTxcGRsfD/lTFBjGRBvsWV1cLk6RDxE2x
# BlFObaiBTngWWOQGCoUY+AjfSTlBKo+sVc2ozFcxZPSxOUt7px0rwbzaNAMcI0u4
# 1A4jYWLo2/Yqt1+b63WZgM0Gff0iUSCZ/chTbAFFlvEutP99rhw7wfjcALLcebT1
# ZTrqzgirIv9sjFJ6MA6fIqYfFNWuBB9MNDUEca3cMiw+T1u5u+xd5Gng0Rsxxqlz
# P4HaXA==
# SIG # End signature block