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/"; "api.apps.appsplatform.us" = "https://service.apps.appsplatform.us/"; "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/"; "api.flow.appsplatform.us" = "https://service.flow.appsplatform.us/"; "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/"; "api.bap.appsplatform.us" = "https://service.apps.appsplatform.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.value__ $message = $errorResponse.Error.Message Write-Verbose "Status Code: '$code'. Message: '$message'" $response = New-Object -TypeName PSObject ` | Add-Member -PassThru -MemberType NoteProperty -Name StatusCode -Value $response.StatusCode.value__ ` | Add-Member -PassThru -MemberType NoteProperty -Name StatusDescription -Value $response.StatusDescription ` | Add-Member -PassThru -MemberType NoteProperty -Name Headers -Value $response.Headers ` | Add-Member -PassThru -MemberType NoteProperty -Name Error -Value $errorResponse.Error ` | Add-Member -PassThru -MemberType NoteProperty -Name Message -Value $message ` | Add-Member -PassThru -MemberType NoteProperty -Name Internal -value $response; } 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 # AgEAAgEAAgEAAgEAAgEAMCEwCQYFKw4DAhoFAAQUl/2O6qKH/XRYFGWIgz/ZNb1e # IaCgghhqMIIE2jCCA8KgAwIBAgITMwAAAU7p4swGDp/D4wAAAAABTjANBgkqhkiG # 9w0BAQUFADB3MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4G # A1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSEw # HwYDVQQDExhNaWNyb3NvZnQgVGltZS1TdGFtcCBQQ0EwHhcNMTkxMTEzMjE0MjIy # WhcNMjEwMjExMjE0MjIyWjCByjELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hp # bmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jw # b3JhdGlvbjElMCMGA1UECxMcTWljcm9zb2Z0IEFtZXJpY2EgT3BlcmF0aW9uczEm # MCQGA1UECxMdVGhhbGVzIFRTUyBFU046RUFDRS1FMzE2LUM5MUQxJTAjBgNVBAMT # HE1pY3Jvc29mdCBUaW1lLVN0YW1wIFNlcnZpY2UwggEiMA0GCSqGSIb3DQEBAQUA # A4IBDwAwggEKAoIBAQCKrMC6fpkKrN7BeazrwaFAyFGK8qmZ7Qn+GM7/0VKHWDAH # nA51YfrzmJ+D3OPPbk4TgKHbp1H9pAE14RMNYcA2SUxBsP3ltSjvtTleQduR1kta # KAPUC7Me5QOTqmg61PBU/vvfR718fKL334zCgxK4kfe44hjWViuLO5n0oOTCleTF # DPwoJhfVzJ46ktYSmwC2vh+wxT6194QGp7FHNhhgtbXSy1GdOZT0mxncWd+p6AZ9 # UUozks1z7dzVCCCjAv2bnVU3e305rOhUyWx3I0EBmCQttYPgBSHXZ/gbn0ps2krB # NtC5sJsmiueDvEBcJ2tqJ2ErwVrj9xtMY7mdOVQ9AgMBAAGjggEJMIIBBTAdBgNV # HQ4EFgQUT8Ap7h7zLLx0qxRNrqocZ5hta5YwHwYDVR0jBBgwFoAUIzT42VJGcArt # QPt2+7MrsMM1sw8wVAYDVR0fBE0wSzBJoEegRYZDaHR0cDovL2NybC5taWNyb3Nv # ZnQuY29tL3BraS9jcmwvcHJvZHVjdHMvTWljcm9zb2Z0VGltZVN0YW1wUENBLmNy # bDBYBggrBgEFBQcBAQRMMEowSAYIKwYBBQUHMAKGPGh0dHA6Ly93d3cubWljcm9z # b2Z0LmNvbS9wa2kvY2VydHMvTWljcm9zb2Z0VGltZVN0YW1wUENBLmNydDATBgNV # HSUEDDAKBggrBgEFBQcDCDANBgkqhkiG9w0BAQUFAAOCAQEAmt9luXJoszhPKQbP # AV9MtJd8g1v4QCCLsMQP3oVcTwr0MGS4PQJln3z/xXHmsCudWsstHpZcToah/2hE # Gp7mQBIk8XKwjLet+zGxV1pMw2qjgMgYRVEYlIQuV6Nj/ETeXMYDET3q/aEYwD+/ # i3F/tg4Su/y4hs1ay1DGXpbhMDGWfdJrunfK0ls+8ow48rVIX9efHfqnnhVOndfE # KTrv46W/VZSM6+qnWP4L/vj05ylMH7JBSJEXEhHf14l8M9OuYp4vQsDfxF+kTN8S # e7WK9xGIlqrkyiqFrGtqdfwe7IOrugKewhn0zo2KHBXiuRh4iY9/aCxb6F6qwxKj # pCE5dzCCBf8wggPnoAMCAQICEzMAAAGHchdyFVlAxwkAAAAAAYcwDQYJKoZIhvcN # 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 # KwYBBAGCNwIBFTAjBgkqhkiG9w0BCQQxFgQUW5k0uVy242iHyfVIqNjz+2qZexUw # NAYKKwYBBAGCNwIBDDEmMCSgEoAQAFQAZQBzAHQAUwBpAGcAbqEOgAxodHRwOi8v # dGVzdCAwDQYJKoZIhvcNAQEBBQAEggEAwNWmLTfmysvjm8GCXhgXvZAFW8k5FB9f # 69FuntxGMo872+i5WDPEPi/w1zlxAHEV7RnXBlsiYDTwSWfQLJXcueIZxgcZPOdF # MWmDyFoc6msPTaumU7kh+KUsi7tGXsCxzsBGq5YS8zBqhMiUZOV4HLEWeXYwDxjb # nHNVC+Z/yEkjdqW5T0KuCxa+hP8dPCt1tJajJMR5bz5w27abC/U8DB/uzMASwyMB # ZjstozaPAW1rSjHEhSqdcesid7wqH1W1bnmHjwMF7cWPRYu+e8lgmDaLYbRZoSX2 # TWcs9jePU3ngZQ4I/Tmy/V0kHx3RevJ1W6qxiANbQYRHo05briO6bKGCAigwggIk # BgkqhkiG9w0BCQYxggIVMIICEQIBATCBjjB3MQswCQYDVQQGEwJVUzETMBEGA1UE # CBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9z # b2Z0IENvcnBvcmF0aW9uMSEwHwYDVQQDExhNaWNyb3NvZnQgVGltZS1TdGFtcCBQ # Q0ECEzMAAAFO6eLMBg6fw+MAAAAAAU4wCQYFKw4DAhoFAKBdMBgGCSqGSIb3DQEJ # AzELBgkqhkiG9w0BBwEwHAYJKoZIhvcNAQkFMQ8XDTIwMDUyNzAwNTIyOVowIwYJ # KoZIhvcNAQkEMRYEFJ6nR7ybWzxcT6D2SVXIX0qn1OmZMA0GCSqGSIb3DQEBBQUA # BIIBACHoRgDBUNkUKWL+0UDYJzabMVze+CI3I89CimxRzwxU1Y+QEFxwQPM4y3YN # d4jFNeigLZ604/rt2ttD0eYpJ+yNlUVd4edZWr5q45s0rnoDNgW9r9Q/unxYZKjI # dZsurAQezHmjEhOepHgv4Qwmgd+imxc7nzQkoE7KRrOeCW5a+Pwz8/6PbE5Sdgf7 # y+jVwR0c5cvpsNRfqyiwjxggJbVfqgvt1nqLRQiO1gqwfqbCkdl3IB5bKzxHy9Jn # JcWH/LNRmXbysuAfNTesPyrHKGXkMtA8sHQHEw0MN49DRlVYgSpMbZFuf0XDxU1K # FQX39wf8M21gNs4dJ47bJ0CQzgQ= # SIG # End signature block |