Andrija
Andrija

Reputation: 14473

Rest call from Powershell on Azure DevOps issue

I'm trying to call rest service on K8S from powershell Agent Job task on Azure DevOps.

$TOKEN=""
$APISERVER="https://xyz.sk1.us-east-2.eks.amazonaws.com"

[System.Net.ServicePointManager]::ServerCertificateValidationCallback = { $True }
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12

$headers = @{
    'Authorization' = 'Bearer ' + $TOKEN
}

#Invoke-RestMethod -Method Get -Uri $APISERVER/api/v1/namespaces/default/pods/ -Headers $headers

try {
    Invoke-RestMethod -Method Get -Uri APISERVER/api/v1/namespaces/default/pods/ -Headers $headers
}
catch {
    $_.Exception | Format-List -Force
}

[System.Net.ServicePointManager]::ServerCertificateValidationCallback = $null

Exception:

Status         : SendFailure
Response       :
Message        : The underlying connection was closed: An unexpected error occurred on a send.
Data           : {}
InnerException : System.Management.Automation.PSInvalidOperationException: 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:  $True
                    at System.Net.TlsStream.EndWrite(IAsyncResult asyncResult)
                    at System.Net.ConnectStream.WriteHeadersCallback(IAsyncResult ar)
TargetSite     : System.Net.WebResponse GetResponse(System.Net.WebRequest)
StackTrace     :    at Microsoft.PowerShell.Commands.WebRequestPSCmdlet.GetResponse(WebRequest request)
                    at Microsoft.PowerShell.Commands.WebRequestPSCmdlet.ProcessRecord()
HelpLink       :
Source         : Microsoft.PowerShell.Commands.Utility
HResult        : -2146233079

As you can see in script, I already changed security protocol and added ServerCertificateValidationCallback delegate.

Any help would be appreciated, thanks.

EDIT1: similar approach using curl works. Same token, same address, also insecure.

Upvotes: 0

Views: 699

Answers (1)

Mengdi Liang
Mengdi Liang

Reputation: 18958

The underlying connection was closed: An unexpected error occurred on a send.

This error caused by in your powershell script, you configured the ServerCertificateValidationCallback to return $true manually which default value is $null, disabled the SSL certificate validation through the System.Net.ServicePointManager endpoint.

Unfortunately, ServerCertificateValidationCallback does not apply to asynchronous callback functions, such like Invoke-WebRequest and Invoke-RestMethod are executed within their own thread to provide the appropriate runtime space for other threads to execute threads at the same time.

Here I show is trust all certificates while requesting data to website. Ignore certificate verification by trusting all certificates with TrustAllCertsPolicy.


Method 1 with C#:

Add the below script to trust all certificates:

add-type @"
    using System.Net;
    using System.Security.Cryptography.X509Certificates;
    public class TrustAllCertsPolicy : ICertificatePolicy {
        public bool CheckValidationResult(
            ServicePoint srv, X509Certificate certi,
            WebRequest req, int certificateIssue) {
            return true;
        }
    }
"@
[System.Net.ServicePointManager]::CertificatePolicy = New-Object TrustAllCertsPolicy

Or if you want to use pure Powershell script instead of using C# script, use CheckValidationResult method to implements the application certificate validation policy:

class TrustAllCertsPolicy : System.Net.ICertificatePolicy {
    [bool] CheckValidationResult([System.Net.ServicePoint] $srv,
                                 [System.Security.Cryptography.X509Certificates.X509Certificate] $certi,
                                 [System.Net.WebRequest] $req,
                                 [int] $a) {
        return $true
    }
}
[System.Net.ServicePointManager]::CertificatePolicy = [TrustAllCertsPolicy]::new()

Set return true to set the certificate should be honored directly.

All this solve the error which displayed on my powershell task and work to get the url content:

enter image description here

(To solve the certification error, I modify my k8s url and change to test with get https://google.com)

Upvotes: 2

Related Questions