Microsoft.PowerApps.RestClientModule.psm1
$local:ErrorActionPreference = "Stop" #Import-Module "$(Split-Path $script:MyInvocation.MyCommand.Path)\Microsoft.PowerApps.AuthModule.psm1" # -Force function Get-AudienceForHostName { [CmdletBinding()] Param( [string] $Uri ) $hostMapping = @{ "management.azure.com" = "https://management.azure.com/"; "api.powerapps.com" = "https://service.powerapps.com/"; "tip1.api.powerapps.com" = "https://service.powerapps.com/"; "tip2.api.powerapps.com" = "https://service.powerapps.com/"; "graph.windows.net" = "https://graph.windows.net/"; "api.bap.microsoft.com" = "https://service.powerapps.com/"; "tip1.api.bap.microsoft.com" = "https://service.powerapps.com/"; "tip2.api.bap.microsoft.com" = "https://service.powerapps.com/"; "api.flow.microsoft.com" = "https://service.flow.microsoft.com/"; "tip1.api.flow.microsoft.com" = "https://service.flow.microsoft.com/"; "tip2.api.flow.microsoft.com" = "https://service.flow.microsoft.com/"; "gov.api.bap.microsoft.us" = "https://gov.service.powerapps.us/"; "high.api.bap.microsoft.us" = "https://high.service.powerapps.us/"; "gov.api.powerapps.us" = "https://gov.service.powerapps.us/"; "high.api.powerapps.us" = "https://high.service.powerapps.us/"; "gov.api.flow.microsoft.us" = "https://gov.service.flow.microsoft.us/"; "high.api.flow.microsoft.us" = "https://high.service.flow.microsoft.us/"; } $uriObject = New-Object System.Uri($Uri) $host = $uriObject.Host if ($hostMapping[$host] -ne $null) { return $hostMapping[$host]; } Write-Verbose "Unknown host $host. Using https://management.azure.com/ as a default"; return "https://management.azure.com/"; } function Invoke-Request( [CmdletBinding()] [Parameter(Mandatory=$True)] [string] $Uri, [Parameter(Mandatory=$True)] [string] $Method, [object] $Body = $null, [Hashtable] $Headers = @{}, [switch] $ParseContent, [switch] $ThrowOnFailure ) { [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 $audience = Get-AudienceForHostName -Uri $Uri $token = Get-JwtToken -Audience $audience $Headers["Authorization"] = "Bearer $token"; $Headers["User-Agent"] = "PowerShell cmdlets 1.0"; try { if ($Body -eq $null -or $Body -eq "") { $response = Invoke-WebRequest -Uri $Uri -Headers $Headers -Method $Method -UseBasicParsing } else { $jsonBody = ConvertTo-Json $Body -Depth 20 $response = Invoke-WebRequest -Uri $Uri -Headers $Headers -Method $Method -ContentType "application/json; charset=utf-8" -Body $jsonBody -UseBasicParsing } if ($ParseContent) { if ($response.Content) { return ConvertFrom-JsonWithErrorHandling -JsonString $response.Content; } } return $response } catch { $response = $_.Exception.Response if ($_.ErrorDetails) { $errorResponse = ConvertFrom-JsonWithErrorHandling -JsonString $_.ErrorDetails; $code = $response.StatusCode $message = $errorResponse.Error.Message Write-Verbose "Status Code: '$code'. Message: '$message'" } if ($ThrowOnFailure) { throw; } else { return $response } } } function InvokeApi { <# .SYNOPSIS Invoke an API. .DESCRIPTION The InvokeApi cmdlet invokes an API based on input parameters. Use Get-Help InvokeApi -Examples for more detail. .EXAMPLE InvokeApi -Method GET -Route $uri -Body $body -ThrowOnFailure Call $uri API as GET method with $body input and throw exception on failure. #> [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [string]$Method, [Parameter(Mandatory = $true)] [string]$Route, [Parameter(Mandatory = $false)] [object]$Body = $null, [Parameter(Mandatory = $false)] [switch]$ThrowOnFailure, [Parameter(Mandatory = $false)] [string]$ApiVersion = "2016-11-01" ) Test-PowerAppsAccount; $uri = $Route ` | ReplaceMacro -Macro "{apiVersion}" -Value $ApiVersion ` | ReplaceMacro -Macro "{flowEndpoint}" -Value $global:currentSession.flowEndpoint ` | ReplaceMacro -Macro "{powerAppsEndpoint}" -Value $global:currentSession.powerAppsEndpoint ` | ReplaceMacro -Macro "{bapEndpoint}" -Value $global:currentSession.bapEndpoint ` | ReplaceMacro -Macro "{graphEndpoint}" -Value $global:currentSession.graphEndpoint ` | ReplaceMacro -Macro "{cdsOneEndpoint}" -Value $global:currentSession.cdsOneEndpoint; Write-Verbose $uri If($ThrowOnFailure) { $result = Invoke-Request ` -Uri $uri ` -Method $Method ` -Body $body ` -ParseContent ` -ThrowOnFailure ` -Verbose:($PSCmdlet.MyInvocation.BoundParameters["Verbose"].IsPresent -eq $true); } else { $result = Invoke-Request ` -Uri $uri ` -Method $Method ` -Body $body ` -ParseContent ` -Verbose:($PSCmdlet.MyInvocation.BoundParameters["Verbose"].IsPresent -eq $true); } if($result.nextLink) { $nextLink = $result.nextLink $resultValue = $result.value while($nextLink) { If($ThrowOnFailure) { $nextResult = Invoke-Request ` -Uri $nextLinkuri ` -Method $Method ` -Body $body ` -ParseContent ` -ThrowOnFailure ` -Verbose:($PSCmdlet.MyInvocation.BoundParameters["Verbose"].IsPresent -eq $true); } else { $nextResult = Invoke-Request ` -Uri $nextLink ` -Method $Method ` -Body $body ` -ParseContent ` -Verbose:($PSCmdlet.MyInvocation.BoundParameters["Verbose"].IsPresent -eq $true); } $nextLink = $nextResult.nextLink $resultValue = $resultValue + $nextResult.value } return New-Object -TypeName PSObject ` | Add-Member -PassThru -MemberType NoteProperty -Name value -Value $resultValue ` } return $result; } function InvokeApiNoParseContent { <# .SYNOPSIS Invoke an API without parsing return content. .DESCRIPTION The InvokeApiNoParseContent cmdlet invokes an API based on input parameters without parsing return content. Use Get-Help InvokeApiNoParseContent -Examples for more detail. .EXAMPLE InvokeApiNoParseContent -Method PUT -Route $uri -Body $body -ThrowOnFailure Call $uri API as PUT method with $body input and throw exception on failure. #> [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [string]$Method, [Parameter(Mandatory = $true)] [string]$Route, [Parameter(Mandatory = $false)] [object]$Body = $null, [Parameter(Mandatory = $false)] [switch]$ThrowOnFailure, [Parameter(Mandatory = $false)] [string]$ApiVersion = "2016-11-01" ) Test-PowerAppsAccount; $uri = $Route ` | ReplaceMacro -Macro "{apiVersion}" -Value $ApiVersion ` | ReplaceMacro -Macro "{flowEndpoint}" -Value $global:currentSession.flowEndpoint ` | ReplaceMacro -Macro "{powerAppsEndpoint}" -Value $global:currentSession.powerAppsEndpoint ` | ReplaceMacro -Macro "{bapEndpoint}" -Value $global:currentSession.bapEndpoint ` | ReplaceMacro -Macro "{graphEndpoint}" -Value $global:currentSession.graphEndpoint ` | ReplaceMacro -Macro "{cdsOneEndpoint}" -Value $global:currentSession.cdsOneEndpoint; Write-Verbose $uri If($ThrowOnFailure) { $result = Invoke-Request ` -Uri $uri ` -Method $Method ` -Body $body ` -ThrowOnFailure ` -Verbose:($PSCmdlet.MyInvocation.BoundParameters["Verbose"].IsPresent -eq $true); } else { $result = Invoke-Request ` -Uri $uri ` -Method $Method ` -Body $body ` -Verbose:($PSCmdlet.MyInvocation.BoundParameters["Verbose"].IsPresent -eq $true); } if($result.nextLink) { $nextLink = $result.nextLink $resultValue = $result.value while($nextLink) { If($ThrowOnFailure) { $nextResult = Invoke-Request ` -Uri $nextLinkuri ` -Method $Method ` -Body $body ` -ThrowOnFailure ` -Verbose:($PSCmdlet.MyInvocation.BoundParameters["Verbose"].IsPresent -eq $true); } else { $nextResult = Invoke-Request ` -Uri $nextLink ` -Method $Method ` -Body $body ` -Verbose:($PSCmdlet.MyInvocation.BoundParameters["Verbose"].IsPresent -eq $true); } $nextLink = $nextResult.nextLink $resultValue = $resultValue + $nextResult.value } return New-Object -TypeName PSObject ` | Add-Member -PassThru -MemberType NoteProperty -Name value -Value $resultValue ` } return $result; } function ReplaceMacro { <# .SYNOPSIS Replace macro to the specified value. .DESCRIPTION The ReplaceMacro cmdlet replace macro in input string with the specified value. Use Get-Help ReplaceMacro -Examples for more detail. .EXAMPLE ReplaceMacro -Macro "{apiVersion}" -Value $ApiVersion Replace {apiVersion} to $ApiVersion. #> param ( [Parameter(Mandatory = $true, ValueFromPipeline = $true)] [string]$Input, [Parameter(Mandatory = $true)] [string]$Macro, [Parameter(Mandatory = $false)] [string]$Value ) return $Input.Replace($Macro, $Value) } function BuildFilterPattern { param ( [Parameter(Mandatory = $false)] [object]$Filter ) if ($Filter -eq $null -or $Filter.Length -eq 0) { return New-Object System.Management.Automation.WildcardPattern "*" } else { return New-Object System.Management.Automation.WildcardPattern @($Filter,"IgnoreCase") } } function ConvertFrom-JsonWithErrorHandling { param ( [Parameter(Mandatory = $true)] [string]$JsonString ) try { return ConvertFrom-Json $JsonString } catch { Write-Verbose "Invalid JSON string: '$JsonString', falling back to .NET deserialization." # try to de-serialize the json string by using .Net json serializer [void][System.Reflection.Assembly]::LoadWithPartialName("System.Web.Extensions") return (New-Object -TypeName System.Web.Script.Serialization.JavaScriptSerializer -Property @{MaxJsonLength=67108864}).DeserializeObject($JsonString) } } function ResolveEnvironment { param ( [Parameter(Mandatory = $false)] [string]$OverrideId ) if (-not [string]::IsNullOrWhiteSpace($OverrideId)) { return $OverrideId; } elseif ($global:currentSession.selectedEnvironment) { return $global:currentSession.selectedEnvironment; } return "~default"; } function Select-CurrentEnvironment { <# .SYNOPSIS Sets the current environment for listing powerapps, flows, and other environment resources .DESCRIPTION The Select-CurrentEnvironment cmdlet sets the current environment in which commands will execute when an environment is not specified. Use Get-Help Select-CurrentEnvironment -Examples for more detail. .PARAMETER EnvironmentName Environment identifier (not display name). .PARAMETER Default Shortcut to specify the default tenant environment .EXAMPLE Select-CurrentEnvironment -EnvironmentName 3c2f7648-ad60-4871-91cb-b77d7ef3c239 Select environment 3c2f7648-ad60-4871-91cb-b77d7ef3c239 as the current environment. Cmdlets invoked after running this command will operate against this environment. .EXAMPLE Select-CurrentEnvironment ~default Select the default environment. Cmdlets invoked after running this will operate against the default environment. #> param ( [Parameter(Mandatory = $true, Position = 0, ValueFromPipelineByPropertyName=$true, ParameterSetName = "Name")] [String]$EnvironmentName, [Parameter(Mandatory = $true, ParameterSetName = "Default")] [Switch]$Default ) Test-PowerAppsAccount; if ($Default) { $global:currentSession.selectedEnvironment = "~default"; } else { $global:currentSession.selectedEnvironment = $EnvironmentName; } } # SIG # Begin signature block # MIIdgAYJKoZIhvcNAQcCoIIdcTCCHW0CAQExCzAJBgUrDgMCGgUAMGkGCisGAQQB # gjcCAQSgWzBZMDQGCisGAQQBgjcCAR4wJgIDAQAABBAfzDtgWUsITrck0sYpfvNR # AgEAAgEAAgEAAgEAAgEAMCEwCQYFKw4DAhoFAAQUiVK8msay++YyT4pBVLWTz2ur # D6ygghhqMIIE2jCCA8KgAwIBAgITMwAAAUU7oIAM2OBxRwAAAAABRTANBgkqhkiG # 9w0BAQUFADB3MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4G # A1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSEw # HwYDVQQDExhNaWNyb3NvZnQgVGltZS1TdGFtcCBQQ0EwHhcNMTkxMTEzMjE0MjE1 # WhcNMjEwMjExMjE0MjE1WjCByjELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hp # bmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jw # b3JhdGlvbjElMCMGA1UECxMcTWljcm9zb2Z0IEFtZXJpY2EgT3BlcmF0aW9uczEm # MCQGA1UECxMdVGhhbGVzIFRTUyBFU046N0JGMS1FM0VBLUI4MDgxJTAjBgNVBAMT # HE1pY3Jvc29mdCBUaW1lLVN0YW1wIFNlcnZpY2UwggEiMA0GCSqGSIb3DQEBAQUA # A4IBDwAwggEKAoIBAQDesb5NK9wP8/ay+t3yB39GoQchq7sgq2BlGh7sUPXBXM23 # Mwf/RRgF0LDdnjNqnt9rpLQxMdGZD8jmAyMXzMP3tUqonz1bYmLjY5tlCtt26LDg # riadbyW17I7Zw6fj/iOgbtsuxgMomdUcZoNNDyw4VTEwovCW6c5eihoYlL5+v7KW # zEkZH6IK12ylShj1ms8vr/iSG6TdWc+bCdDI8tugQl3H4hyrUAyuWV9/qgqsfn4/ # E/XMCqOE5GWR3drNtAWPTWJj8//9/8M3RkpLQY59roCZalhx/KXpupfn0PubDbCq # 2ks1/QO7yeRL1ddSqXJIMpRnDq6F9xfDYMWFsiJPAgMBAAGjggEJMIIBBTAdBgNV # HQ4EFgQUbKMjkIQEYGZbp4fofG1rAp06JyAwHwYDVR0jBBgwFoAUIzT42VJGcArt # QPt2+7MrsMM1sw8wVAYDVR0fBE0wSzBJoEegRYZDaHR0cDovL2NybC5taWNyb3Nv # ZnQuY29tL3BraS9jcmwvcHJvZHVjdHMvTWljcm9zb2Z0VGltZVN0YW1wUENBLmNy # bDBYBggrBgEFBQcBAQRMMEowSAYIKwYBBQUHMAKGPGh0dHA6Ly93d3cubWljcm9z # b2Z0LmNvbS9wa2kvY2VydHMvTWljcm9zb2Z0VGltZVN0YW1wUENBLmNydDATBgNV # HSUEDDAKBggrBgEFBQcDCDANBgkqhkiG9w0BAQUFAAOCAQEAXgE7Q/v/6I5MjtOP # zD1Olu8c5faV/gc5fAEq34VJPIeAShdj4iVUL2vOhiSMIo9AISEr7vf0OQ7ZG0sL # LpB+QPU37wJOqlIurjDOe6qKFLOiixJIMrkYwqXF0XCZcJUOYJo2si/VfeYfnoH8 # FSu+dExduy8horubCqoF7/56KWWl7TT0QUfnZnBU+jyQrlibwaO8CAGPPXDlVJ03 # 1Yo6wouodm6UbJ95vLio6Y09yoxN2jWBsIXeRQyAd/rpyFmicphodwFvBZfyULRA # iljuvfnR0xxLYXQJm+F2ynHZccCOTLi55tNcwCo/lv25uCL0iVwqtpvAewfnYdsB # ZULJMTCCBf8wggPnoAMCAQICEzMAAAGHchdyFVlAxwkAAAAAAYcwDQYJKoZIhvcN # AQELBQAwfjELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNV # BAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEoMCYG # A1UEAxMfTWljcm9zb2Z0IENvZGUgU2lnbmluZyBQQ0EgMjAxMTAeFw0yMDAzMDQx # ODM5NDdaFw0yMTAzMDMxODM5NDdaMHQxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpX # YXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQg # Q29ycG9yYXRpb24xHjAcBgNVBAMTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjCCASIw # DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAM63yQtzs/dPswoiGi5gd7AwWaer # wDK7sU6FkJBptXAGnZVLhbIHZB7hNAFPxoHOcA0MQ+Mco109PxfPlw1qWLpcd59L # yL9Ze0XS9Kw/w0S/qYEe4DanV/DbAH8XR0ewncZ9nlzSw8mOSWyJio/Dn3EnniQz # 3Ug6CI7Y5TOM0CWM+JuMJZ8ftTNDVM8dzh3B6KWzwYQitsFFvshbCI5svXaNZPhi # HvU1CC8n0Wfr5SEP3Ha6Td0uPzi/C3U24VCK0onEhXR9WxE1HdptBU4uqkO6BuvR # LM0vqjzHM4cvk5eIYbCDp6SJcDX/ZddjvJUVzf22V50O1mNKM1t7HXPPBJcCAwEA # AaOCAX4wggF6MB8GA1UdJQQYMBYGCisGAQQBgjdMCAEGCCsGAQUFBwMDMB0GA1Ud # DgQWBBSGi/hnI73prGQl0yOnO7bNVc4lyzBQBgNVHREESTBHpEUwQzEpMCcGA1UE # CxMgTWljcm9zb2Z0IE9wZXJhdGlvbnMgUHVlcnRvIFJpY28xFjAUBgNVBAUTDTIz # MDAxMis0NTgzODUwHwYDVR0jBBgwFoAUSG5k5VAF04KqFzc3IrVtqMp1ApUwVAYD # VR0fBE0wSzBJoEegRYZDaHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9j # cmwvTWljQ29kU2lnUENBMjAxMV8yMDExLTA3LTA4LmNybDBhBggrBgEFBQcBAQRV # MFMwUQYIKwYBBQUHMAKGRWh0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9wa2lvcHMv # Y2VydHMvTWljQ29kU2lnUENBMjAxMV8yMDExLTA3LTA4LmNydDAMBgNVHRMBAf8E # AjAAMA0GCSqGSIb3DQEBCwUAA4ICAQCLGbJLoTq+mtYP0oU0gH0bnPIy4iNkA65Q # nUQr9WWDoVvdkdeONTABMohxdsW4ULpavgo2tTgNj+wFWqZpvkAL+N7dulSmO3Gk # TKpSq09zfTASD+s72+Yqaoqgs9Pfuy9zY1UGYY2X7zmo7h9X/DsLHsnQFuqTX0px # E12O3p4qhOdM8cEeVUdAgdmkzFpxsU4CQmuoBWRhl3PuKQ1dPFX4ZFvfq0LgHIw3 # ETYMXu8V29qJk/QJVnkHInaACFcx0r366zHNWT3Xeop17U4C5Z2/6ud2qQAibx9S # VGevixpIKDtwhtTAIJ/XXrBQnsS4kODS8d7KGcJ4ecFvIfdFmQcSLah+Z+CcUhIl # kN0wB5VkZU6HbQmnnRcHOqiSk/N5nrNzX+DIgs3KJWAT5E+SOdRCyF3V/U8yCfe2 # ezYLPtsmJVRqoQ7ef2pEWDLkm4tp7pTB4Z8B46jd2AtnGKQrNizeEMxoS0mrwg/v # VxftBd7qWcyZdT8d1/Panz3tl36RT69m8ojdzAt+5VCArZFnbP4pzcrd1E/PatfJ # wrlcK5Fma8Zpv9ZutmILvAlBqmAGh2W0wjkYx0WsGD0h4Xv+s/gSpVBd4q169OVl # eOm42GGO5H7YMy391a5+NemJb3VujdofoRqM4AteajGCW0KnUruGtLqCay+P3hwt # F/nRBDhTxDCCBgcwggPvoAMCAQICCmEWaDQAAAAAABwwDQYJKoZIhvcNAQEFBQAw # XzETMBEGCgmSJomT8ixkARkWA2NvbTEZMBcGCgmSJomT8ixkARkWCW1pY3Jvc29m # dDEtMCsGA1UEAxMkTWljcm9zb2Z0IFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5 # MB4XDTA3MDQwMzEyNTMwOVoXDTIxMDQwMzEzMDMwOVowdzELMAkGA1UEBhMCVVMx # EzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoT # FU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEhMB8GA1UEAxMYTWljcm9zb2Z0IFRpbWUt # U3RhbXAgUENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAn6Fssd/b # SJIqfGsuGeG94uPFmVEjUK3O3RhOJA/u0afRTK10MCAR6wfVVJUVSZQbQpKumFww # JtoAa+h7veyJBw/3DgSY8InMH8szJIed8vRnHCz8e+eIHernTqOhwSNTyo36Rc8J # 0F6v0LBCBKL5pmyTZ9co3EZTsIbQ5ShGLieshk9VUgzkAyz7apCQMG6H81kwnfp+ # 1pez6CGXfvjSE/MIt1NtUrRFkJ9IAEpHZhEnKWaol+TTBoFKovmEpxFHFAmCn4Tt # VXj+AZodUAiFABAwRu233iNGu8QtVJ+vHnhBMXfMm987g5OhYQK1HQ2x/PebsgHO # IktU//kFw8IgCwIDAQABo4IBqzCCAacwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4E # FgQUIzT42VJGcArtQPt2+7MrsMM1sw8wCwYDVR0PBAQDAgGGMBAGCSsGAQQBgjcV # AQQDAgEAMIGYBgNVHSMEgZAwgY2AFA6sgmBAVieX5SUT/CrhClOVWeSkoWOkYTBf # MRMwEQYKCZImiZPyLGQBGRYDY29tMRkwFwYKCZImiZPyLGQBGRYJbWljcm9zb2Z0 # MS0wKwYDVQQDEyRNaWNyb3NvZnQgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHmC # EHmtFqFKoKWtTHNY9AcTLmUwUAYDVR0fBEkwRzBFoEOgQYY/aHR0cDovL2NybC5t # aWNyb3NvZnQuY29tL3BraS9jcmwvcHJvZHVjdHMvbWljcm9zb2Z0cm9vdGNlcnQu # Y3JsMFQGCCsGAQUFBwEBBEgwRjBEBggrBgEFBQcwAoY4aHR0cDovL3d3dy5taWNy # b3NvZnQuY29tL3BraS9jZXJ0cy9NaWNyb3NvZnRSb290Q2VydC5jcnQwEwYDVR0l # BAwwCgYIKwYBBQUHAwgwDQYJKoZIhvcNAQEFBQADggIBABCXisNcA0Q23em0rXfb # znlRTQGxLnRxW20ME6vOvnuPuC7UEqKMbWK4VwLLTiATUJndekDiV7uvWJoc4R0B # hqy7ePKL0Ow7Ae7ivo8KBciNSOLwUxXdT6uS5OeNatWAweaU8gYvhQPpkSokInD7 # 9vzkeJkuDfcH4nC8GE6djmsKcpW4oTmcZy3FUQ7qYlw/FpiLID/iBxoy+cwxSnYx # PStyC8jqcD3/hQoT38IKYY7w17gX606Lf8U1K16jv+u8fQtCe9RTciHuMMq7eGVc # WwEXChQO0toUmPU8uWZYsy0v5/mFhsxRVuidcJRsrDlM1PZ5v6oYemIp76KbKTQG # dxpiyT0ebR+C8AvHLLvPQ7Pl+ex9teOkqHQ1uE7FcSMSJnYLPFKMcVpGQxS8s7Ow # TWfIn0L/gHkhgJ4VMGboQhJeGsieIiHQQ+kr6bv0SMws1NgygEwmKkgkX1rqVu+m # 3pmdyjpvvYEndAYR7nYhv5uCwSdUtrFqPYmhdmG0bqETpr+qR/ASb/2KMmyy/t9R # yIwjyWa9nR2HEmQCPS2vWY+45CHltbDKY7R4VAXUQS5QrJSwpXirs6CWdRrZkocT # dSIvMqgIbqBbjCW/oO+EyiHW6x5PyZruSeD3AWVviQt9yGnI5m7qp5fOMSn/DsVb # XNhNG6HY+i+ePy5VFmvJE6P9MIIHejCCBWKgAwIBAgIKYQ6Q0gAAAAAAAzANBgkq # hkiG9w0BAQsFADCBiDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24x # EDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlv # bjEyMDAGA1UEAxMpTWljcm9zb2Z0IFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5 # IDIwMTEwHhcNMTEwNzA4MjA1OTA5WhcNMjYwNzA4MjEwOTA5WjB+MQswCQYDVQQG # EwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwG # A1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSgwJgYDVQQDEx9NaWNyb3NvZnQg # Q29kZSBTaWduaW5nIFBDQSAyMDExMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIIC # CgKCAgEAq/D6chAcLq3YbqqCEE00uvK2WCGfQhsqa+laUKq4BjgaBEm6f8MMHt03 # a8YS2AvwOMKZBrDIOdUBFDFC04kNeWSHfpRgJGyvnkmc6Whe0t+bU7IKLMOv2akr # rnoJr9eWWcpgGgXpZnboMlImEi/nqwhQz7NEt13YxC4Ddato88tt8zpcoRb0Rrrg # OGSsbmQ1eKagYw8t00CT+OPeBw3VXHmlSSnnDb6gE3e+lD3v++MrWhAfTVYoonpy # 4BI6t0le2O3tQ5GD2Xuye4Yb2T6xjF3oiU+EGvKhL1nkkDstrjNYxbc+/jLTswM9 # sbKvkjh+0p2ALPVOVpEhNSXDOW5kf1O6nA+tGSOEy/S6A4aN91/w0FK/jJSHvMAh # dCVfGCi2zCcoOCWYOUo2z3yxkq4cI6epZuxhH2rhKEmdX4jiJV3TIUs+UsS1Vz8k # A/DRelsv1SPjcF0PUUZ3s/gA4bysAoJf28AVs70b1FVL5zmhD+kjSbwYuER8ReTB # w3J64HLnJN+/RpnF78IcV9uDjexNSTCnq47f7Fufr/zdsGbiwZeBe+3W7UvnSSmn # Eyimp31ngOaKYnhfsi+E11ecXL93KCjx7W3DKI8sj0A3T8HhhUSJxAlMxdSlQy90 # lfdu+HggWCwTXWCVmj5PM4TasIgX3p5O9JawvEagbJjS4NaIjAsCAwEAAaOCAe0w # ggHpMBAGCSsGAQQBgjcVAQQDAgEAMB0GA1UdDgQWBBRIbmTlUAXTgqoXNzcitW2o # ynUClTAZBgkrBgEEAYI3FAIEDB4KAFMAdQBiAEMAQTALBgNVHQ8EBAMCAYYwDwYD # VR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBRyLToCMZBDuRQFTuHqp8cx0SOJNDBa # BgNVHR8EUzBRME+gTaBLhklodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpL2Ny # bC9wcm9kdWN0cy9NaWNSb29DZXJBdXQyMDExXzIwMTFfMDNfMjIuY3JsMF4GCCsG # AQUFBwEBBFIwUDBOBggrBgEFBQcwAoZCaHR0cDovL3d3dy5taWNyb3NvZnQuY29t # L3BraS9jZXJ0cy9NaWNSb29DZXJBdXQyMDExXzIwMTFfMDNfMjIuY3J0MIGfBgNV # HSAEgZcwgZQwgZEGCSsGAQQBgjcuAzCBgzA/BggrBgEFBQcCARYzaHR0cDovL3d3 # dy5taWNyb3NvZnQuY29tL3BraW9wcy9kb2NzL3ByaW1hcnljcHMuaHRtMEAGCCsG # AQUFBwICMDQeMiAdAEwAZQBnAGEAbABfAHAAbwBsAGkAYwB5AF8AcwB0AGEAdABl # AG0AZQBuAHQALiAdMA0GCSqGSIb3DQEBCwUAA4ICAQBn8oalmOBUeRou09h0ZyKb # C5YR4WOSmUKWfdJ5DJDBZV8uLD74w3LRbYP+vj/oCso7v0epo/Np22O/IjWll11l # hJB9i0ZQVdgMknzSGksc8zxCi1LQsP1r4z4HLimb5j0bpdS1HXeUOeLpZMlEPXh6 # I/MTfaaQdION9MsmAkYqwooQu6SpBQyb7Wj6aC6VoCo/KmtYSWMfCWluWpiW5IP0 # wI/zRive/DvQvTXvbiWu5a8n7dDd8w6vmSiXmE0OPQvyCInWH8MyGOLwxS3OW560 # STkKxgrCxq2u5bLZ2xWIUUVYODJxJxp/sfQn+N4sOiBpmLJZiWhub6e3dMNABQam # ASooPoI/E01mC8CzTfXhj38cbxV9Rad25UAqZaPDXVJihsMdYzaXht/a8/jyFqGa # J+HNpZfQ7l1jQeNbB5yHPgZ3BtEGsXUfFL5hYbXw3MYbBL7fQccOKO7eZS/sl/ah # XJbYANahRr1Z85elCUtIEJmAH9AAKcWxm6U/RXceNcbSoqKfenoi+kiVH6v7RyOA # 9Z74v2u3S5fi63V4GuzqN5l5GEv/1rMjaHXmr/r8i+sLgOppO6/8MO0ETI7f33Vt # Y5E90Z1WTk+/gFcioXgRMiF670EKsT/7qMykXcGhiJtXcVZOSEXAQsmbdlsKgEhr # /Xmfwb1tbWrJUnMTDXpQzTGCBIAwggR8AgEBMIGVMH4xCzAJBgNVBAYTAlVTMRMw # EQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVN # aWNyb3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMTH01pY3Jvc29mdCBDb2RlIFNp # Z25pbmcgUENBIDIwMTECEzMAAAGHchdyFVlAxwkAAAAAAYcwCQYFKw4DAhoFAKCB # lDAZBgkqhkiG9w0BCQMxDAYKKwYBBAGCNwIBBDAcBgorBgEEAYI3AgELMQ4wDAYK # KwYBBAGCNwIBFTAjBgkqhkiG9w0BCQQxFgQU/h79gw7ChQFl1AuGbQjJ+q6GdZQw # NAYKKwYBBAGCNwIBDDEmMCSgEoAQAFQAZQBzAHQAUwBpAGcAbqEOgAxodHRwOi8v # dGVzdCAwDQYJKoZIhvcNAQEBBQAEggEAXZ8fjz/EBryKP8k7bJcWSdLyNYA6381L # vuRAZ/KIE8yNG7VJtrsZBaT6bgUv8OaaeXdC01wdVEZMUi2FMn0nohHvhYXI1g98 # rGPgWMIDwWVF+W0rDkve7KEC1KXhJj2aiyPHn+o7vROvrfvN8qWDW1yutppVHOrP # tTk92Qc5LafaMAJBvvwb6QQiHXF/C+KxmGHrPDsBUFa8LmZERWnxEqwi9/lqrBxN # PH6NPn2tTRo3y2m8ppbh6INBhBbV6Q8wasNEDjzMqASQrEebMFQM5kXASqdo7/zt # 7b8H7S3/gcdgwjHoYKEbhyTnMsuisbRtOoRDubv1nN8/zLENz4qNh6GCAigwggIk # BgkqhkiG9w0BCQYxggIVMIICEQIBATCBjjB3MQswCQYDVQQGEwJVUzETMBEGA1UE # CBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9z # b2Z0IENvcnBvcmF0aW9uMSEwHwYDVQQDExhNaWNyb3NvZnQgVGltZS1TdGFtcCBQ # Q0ECEzMAAAFFO6CADNjgcUcAAAAAAUUwCQYFKw4DAhoFAKBdMBgGCSqGSIb3DQEJ # AzELBgkqhkiG9w0BBwEwHAYJKoZIhvcNAQkFMQ8XDTIwMDUwNTAwMTMxM1owIwYJ # KoZIhvcNAQkEMRYEFBccYjcrsqtILdY14RAaYDAtIUz7MA0GCSqGSIb3DQEBBQUA # BIIBAJsaUCAH7T7p5lCskkkG9n71VILXGMT1cRZfAEov+IJiytnKwddJpwB6Qbj8 # YLvOzmcw836nuOWHwNaKqePAoyNKr+rGyZf8eDwuUuBXGvgY3sqoc/A8XsCwp6M5 # p0VX58VzZcE5OFmdQV3QCC1JMkI48OGhwiEOHXmWeF+qU5HSZVmSwl8HacM5J7Az # XWGUReL1MLwnEgzQMJmLtpYyiPIoV1QjRZZuvEDcRTekK2EllrD5UcKEHdmUj2ZU # dJP41Co2FlA48yX0AJmnz3eVSf2P8tImacWDah7Jv2c7+r7VHwuhwAFZc6KqozZu # CQ0Vvyj+SspgcNR17ZGr2NZcJRo= # SIG # End signature block |