J'essaie de communiquer avec un service sur PowerShell mais j'échoue lamentablement. Je soupçonne que c'est le certificat et j'ai cherché sur Google la réponse et trouvé deux options, dont aucune ne fonctionnait pour moi. J'ai également essayé de combiner les deux sans succès.
Option 1:
add-type @"
using System.Net;
using System.Security.Cryptography.X509Certificates;
public class TrustAllCertsPolicy : ICertificatePolicy {
public bool CheckValidationResult(
ServicePoint srvPoint, X509Certificate certificate,
WebRequest request, int certificateProblem) {
return true;
}
}
"@
[System.Net.ServicePointManager]::CertificatePolicy = New-Object TrustAllCertsPolicy
$urlJSON = "https://internal.ad.local/path/api_jsonrpc.php"
#Create authentication JSON object using ConvertTo-JSON
$objAuth = (New-Object PSObject | Add-Member -PassThru NoteProperty jsonrpc '2.0' |
Add-Member -PassThru NoteProperty method 'user.authenticate' |
Add-Member -PassThru NoteProperty params @{user="user";password="password"} |
Add-Member -PassThru NoteProperty id '2') | ConvertTo-Json
Invoke-RestMethod -Uri $urlJSON -body $objAuth -method "Post"
Option 2:
[System.Net.ServicePointManager]::ServerCertificateValidationCallback = {$true}
$urlJSON = "https://internal.ad.local/path/api_jsonrpc.php"
#Create authentication JSON object using ConvertTo-JSON
$objAuth = (New-Object PSObject | Add-Member -PassThru NoteProperty jsonrpc '2.0' |
Add-Member -PassThru NoteProperty method 'user.authenticate' |
Add-Member -PassThru NoteProperty params @{user="user";password="password"} |
Add-Member -PassThru NoteProperty id '2') | ConvertTo-Json
Invoke-RestMethod -Uri $urlJSON -body $objAuth -method "Post"
Voici le message d'erreur:
Invoke-RestMethod : The underlying connection was closed: An unexpected error occurred on a send.
At C:\Users\user\AppData\Local\Temp\46eaa6f7-62a0-4c10-88d1-79212d652bc9.ps1:24 char:1
+ Invoke-RestMethod -Uri $urlJSON -body $objAuth -method "Post"
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-RestMethod], WebException
+ FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand
Je pourrais ajouter:
Toutes les suggestions appréciées!
Cordialement, Patrik
Message mis à jour concernant les suggestions de M. Tree ci-dessous:
Name : lambda_method
DeclaringType :
ReflectedType :
Module : RefEmit_InMemoryManifestModule
MethodHandle :
Attributes : PrivateScope, Public, Static
CallingConvention : Standard
IsSecurityCritical : False
IsSecuritySafeCritical : False
IsSecurityTransparent : True
ReturnType : System.Boolean
ReturnParameter :
ReturnTypeCustomAttributes : System.Reflection.Emit.DynamicMethod+RTDynamicMethod+EmptyCAHolder
MemberType : Method
MethodImplementationFlags : NoInlining
IsGenericMethodDefinition : False
ContainsGenericParameters : False
IsGenericMethod : False
IsPublic : True
IsPrivate : False
IsFamily : False
IsAssembly : False
IsFamilyAndAssembly : False
IsFamilyOrAssembly : False
IsStatic : True
IsFinal : False
IsVirtual : False
IsHideBySig : False
IsAbstract : False
IsSpecialName : False
IsConstructor : False
CustomAttributes :
MetadataToken :
Mise à jour 2 basée sur un commentaire de M. Tree:
Invoke-RestMethod : The underlying connection was closed: An unexpected error occurred on a send.
At C:\Users\user\AppData\Local\Temp\ff47910e-fd8e-4be8-9241-99322144976a.ps1:13 char:1
+ Invoke-RestMethod -Uri $urlJSON -body $objAuth -method "Post"
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-RestMethod], WebException
+ FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand
J'ai résolu le mystère tout en résolvant autre chose. Le serveur Web en question ne supportait que TLS1.1 et TLS1.2. Powershell ne semble pas soutenir cela. Si j'ai activé TLS1.0 cela a fonctionné.
Pour forcer TLS1.2, vous pouvez utiliser cette ligne:
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
J'espère que cela aide quelqu'un d'autre et merci pour tous les commentaires utiles!
/ Patrik
Récemment, j'ai beaucoup souffert pour surmonter une situation similaire. Je créais une preuve de concept à l'aide d'un service d'essai SaaS. Le service avait un certificat SSL auto-signé et je voulais donc ignorer les erreurs de certificat lorsque j'essayais d'y appeler une méthode POST (similaire au paramètre "-k" de curl). Après beaucoup de difficultés, j'ai découvert qu'il fallait les deux _ (a) l'appel pour ignorer les erreurs de validation du certificat et (b) un paramètre explicite pour TLS 1.2 en tant que protocole de sécurité. Je pense que ce dernier parce que le service était peut-être en train de réduire les tentatives de connexion en utilisant l'un des autres protocoles. (J'ai passé trop de temps à essayer les différentes variantes possibles, comme suggéré sur différents threads SOF mais indépendamment ...)
Voici le code qui a fonctionné ...
Important: le contournement de la validation du certificat est purement destiné au prototype/PoC. Nous n’avons pas l’intention de le faire en production (et vous ne devriez pas non plus!).
$defaultSecurityProtocol = $null
try
{
#BUGBUG, TODO: Disabling cert validation for the duration of this call...('trial' version cert is self-signed.)
#Remove this after the PoC.
[System.Net.ServicePointManager]::ServerCertificateValidationCallback = { $true }
#Cache the previous protocol setting and explicitly require TLS 1.2
$defaultSecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol
[System.Net.ServicePointManager]::SecurityProtocol = `
[System.Net.SecurityProtocolType]::Tls12
if (-not [String]::IsNullOrWhiteSpace($authZHeaderValue))
{
$response = Invoke-WebRequest `
-Uri $webhookUrl `
-Method "Post" `
-Body $eventJson `
-Header @{ $authZHeaderName = $authZHeaderValue}
}
else
{
$response = Invoke-WebRequest `
-Uri $webhookUrl `
-Method "Post" `
-Body $eventJson
}
}
catch
{
$msg = $_.Exception.Message
$status = $_.Exception.Status
$hr = "{0:x8}" -f ($_.Exception.HResult)
$innerException = $_.Exception.InnerException
#Just issue a warning about being unable to send the notification...
Write-Warning("`n`t[$status] `n`t[0x$hr] `n`t[$msg] `n`t[$innerException]")
}
finally
{
# Set securityProtocol and CertValidation behavior back to the previous state.
[System.Net.ServicePointManager]::SecurityProtocol = $defaultSecurityProtocol
[System.Net.ServicePointManager]::ServerCertificateValidationCallback = $null
}
Vous souhaitez également ajouter que les protocoles de sécurité préférés continuent de changer à mesure que différentes vulnérabilités sont découvertes et que des correctifs sont mis en œuvre. De plus, différents systèmes (piles SSL/TLS dans les systèmes d'exploitation clients et les serveurs/services) ont souvent leur propre rattrapage à faire avec les options les plus récentes/les plus sécurisées. Ainsi, le drapeau qui fonctionnera exactement dépendra des systèmes client et serveur ainsi que du temps (en ce sens que TLS1.2 pourrait ne pas rester préféré quelques mois plus tard). Idéalement, il ne devrait pas être nécessaire de spécifier un drapeau. Veuillez consulter la section "Remarques" dans de ce document MSDN pour plus d'informations.
Il semble que vous tentiez d’appeler une API json avec Invoke-RestMethod
. Selon la documentation :
-ContentType
Spécifie le type de contenu de la demande Web.
Si ce paramètre est omis et que la méthode request est POST, Invoke-RestMethod définit le type de contenu sur "application/x-www-form-urlencoded". Sinon, le type de contenu est non spécifié dans l'appel.
Pour utiliser un corps json, vous devrez utiliser Invoke-RestMethod -ContentType 'application/json' <other args>