With Powershell 7 there have been several changes to Invoke-RestMethod
. I've written some modules that are wrappers for several Invoke-RestMethod calls to simplify the interaction with our API for my colleagues. In Powershell 5.1 this code runs fine:
Invoke-RestMethod -Method Get -Uri "http://localhost/MyServer/MyApi" -UseDefaultCredentials
In Powershell 7 this generates an error because I'm using an HTTP resource rather than HTTPS:
Invoke-RestMethod: The cmdlet cannot protect plain text secrets sent over unencrypted connections. To suppress this warning and send plain text secrets over unencrypted networks, reissue the command specifying the AllowUnencryptedAuthentication parameter.
To get around this you just need to add -AllowUnencryptedAuthentication
to the call and it works, but that only works for Powershell 7. If I add the flag in a Powershell 5.1 environment it generates an error because the flag doesn't exist:
Invoke-RestMethod : A parameter cannot be found that matches parameter name 'AllowUnencryptedAuthentication'.
There is a workaround by doing the following, but making this change to every single module is going to be a PITA since the Invoke-RestMethod
varies from module to module:
if ($PSVersionTable.PSVersion.Major -gt 5) {
Invoke-RestMethod -Method Get -Uri "http://localhost/MyServer/MyApi" -UseDefaultCredentials -AllowUnencryptedAuthentication
}
else {
Invoke-RestMethod -Method Get -Uri "http://localhost/MyServer/MyApi" -UseDefaultCredentials
}
I know that you can pass values like -Verbose
using something like $PSCmdlet.MyInvocation.BoundParameters["Verbose"].IsPresent
as described here but I need to completely remove the flag if I'm in a 5.1 or earlier environment and add it for 7 or later. Is there a way to do this in one line or do I need to make the above change to every module?
CodePudding user response:
You could do it using only one condition that checks if the version is PowerShell Core, and if it is, add AllowUnencryptedAuthentication = $true
as default value using the preference variable $PSDefaultParameterValues
:
if($IsCoreCLR) {
$PSDefaultParameterValues['Invoke-RestMethod:AllowUnencryptedAuthentication'] = $true
}
A simple example using a temporary module with an advanced function:
$PSDefaultParameterValues = @{
'Test-PSDefaultParameterValues:param1' = 'hello'
'Test-PSDefaultParameterValues:param2' = 'world!'
}
New-Module -Name temp -ScriptBlock {
function Test-PSDefaultParameterValues {
[CmdletBinding()]
param($param1, $param2)
"$param1 $param2"
}
} -Function Test-PSDefaultParameterValues | Import-Module
Test-PSDefaultParameterValues
You could also use Splatting as mclayton pointed out in a comment. This way would be preferable in my opinion instead of updating the session state of a possible user of your module, however this would also need to be updated in all your function calls:
# this would be the default params for calling the cmdlet
$param = @{
Method = 'Get'
Uri = 'http://localhost/MyServer/MyApi'
UseDefaultCredentials = $true
}
# then we check if this is Core, and then add the missing
# parameter to the splat hashtable
if($IsCoreCLR) {
$param['AllowUnencryptedAuthentication'] = $true
}
Invoke-RestMethod @param