Monday, December 4, 2023

 

The following is a case study for an automation involving a web request.

A PowerShell script written to invoke a remote method by sending a web request works find when executed locally on a PowerShell Terminal but fails to run the command when the script is part of an automation workflow aka runbook. The error encountered is “Name or service not known.” even though the remote method is hosted in an app service. If the app service were denying the request, a 403 statuscode might have appeared in the error but this is not the case. The request does not reach the target. The following article explains how to diagnose this situation.

Before we begin diagnosing the specific cmdlet, it is important to check that the associated module is imported. This can be done with `ipmo Microsoft.PowerShell.Utility` directive. It is also necessary to ensure that the execution policy of the script permits the call. This can be relaxed with `Set-ExecutionPolicy -ExecutionPolicy Unrestricted -Force -Scope Process` command. Also, the logged in user or identity making the call must have the necessary permissions to do so or assign the web app contributor role to the principal.

First, the automation, by its nature, cannot be interactive, so the parameters must be checked to include an option to progress without involvement. For example, the $progressPreference = “silentlyContinue” may help here.

Second, the parameter to debug the call might yield more information than regular invocation. The ‘-Debug’ parameter, for example, may indicate that the TLS handshake failed which resulted in the call not going through. It could also indicate a timeout in getting a response when the request was valid indicating other reasons why the call could not go through.

When the TLS handshake fails, it might most likely arise from the certificate validation. A caller making a web request can choose to skip the validation when the method is to a target that falls under the control of the owner owning the automation as well as the app service.  A PowerShell method to trust all certificates might be something as simple as:

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

 

A try-catch handler around the request can also indicate not only the exception but also other modules that might be involved in the request from the associated stacktrace. For example,

try {

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

}

catch {

    $_.Exception | Format-List -Force

}

may indicate the error when it would otherwise be omitted from the logs.

It is also possible that the target might not be reachable over the network and this can be diagnosed with:

$DnsCheck = Resolve-DnsName $uri -ErrorAction SilentlyContinue

Similarly, other parameters to the web-request can also help here such as –UseBasicParsing to indicate that this is not a web request from a browser, -Proxy ‘http://w.x.y.z:80’ -ProxyCredential $creds where the credentials are obtained from $creds = New-AzADSpCredential -ServicePrincipalName <ServicePrincipalName> and specifying the method such as with -Method GET.

These are some of the ways in which the web request can be made to succeed.

No comments:

Post a Comment