AWS PowerShell customize SSO Callback: There is no Runspace available to run scripts in this thread

Viewed 200

I'm using the PowerShell (v7) script below to customize AWS SSO Login FLow. It's based on a working .net implementation:

$ErrorActionPreference = "Stop"
Import-Module -Name "AWSPowerShell.NetCore"

$profileName = "my-sso-profile"

$chain = New-Object Amazon.Runtime.CredentialManagement.CredentialProfileStoreChain

$credentials = $null
$chain.TryGetAWSCredentials($profileName, [ref]$credentials)

$ssoCredentials = [Amazon.Runtime.SSOAWSCredentials]$credentials
$ssoCredentials.Options.ClientName = "Example-SSO-Script"
$ssoCredentials.Options.SsoVerificationCallback = [System.Action[Amazon.Runtime.SsoVerificationArguments]]{
    param($x)
    # Launch SSO Login Flow in Browser
    Start-Process $x.VerificationUriComplete
}

Set-AWSCredential -Credential $ssoCredentials
# Print details about current Credential
Get-StsCallerIdentity

Error

When I run this script in Powershell (v7), I get an exception:

There is no Runspace available to run scripts in this thread. You can provide one in the DefaultRunspace property of the System.Management.Automation.Runspaces.Runspace type. The script block you attempted to invoke was: param($x) …cationUriComplete

Looks like there is an issue invoking my script delegate in$ssoCredentials.Options.SsoVerificationCallback

Question

How can I configure my Script/PowerShell Session so that my SsoVerificationCallback delegate executes without throwing an error?

Research

I'm guessing the problem has something to do with the C# code invoking the SsoVerificationCallback delegate, which is now a PSScriptBlock(?), and something going wrong marshalling back and forth between C# and PowerShell.

Looking around SO, the SsoVerificationCallback invocation isn't Async, though it is invoked inside an async method GetSsoTokenAsync, so I don't think Runspace issus using async APIs from Powershell applies.

And I'm not making a web call directly, so tips in blog such as https://www.agilepointnxblog.com/powershell-error-there-is-no-runspace-available-to-run-scripts-in-this-thread/ recommended setting [System.Net.ServicePointManager]::ServerCertificateValidationCallback = $null also didn't make any impact.

1 Answers

While I'm hazy on the details, the following general information may be helpful:

While PowerShell script blocks ({ ... }) generally can be used as .NET delegates, their invocation only succeeds if the calling thread has a PowerShell runspace associated with it - script blocks cannot execute otherwise.

If a given script-block-based delegate is called (back) from the PowerShell session's own foreground thread, this requirement is by definition met; e.g., passing a script block as a MatchEvaluator delegate to [regex]::Replace():

PS> [regex]::Replace('woo', 'o$', { param($m) $m.Value + 't!' })
woot!

However, it seems that in your case a different thread - one without an associated PowerShell runspace - is calling your script-block-based delegate, which results in the error you saw.

There may be a - cumbersome, nontrivial - workaround based on ad-hoc compilation of C# code, as shown in this answer.

Related