2015-09-02 16 views
10

Sto provando a comunicare con un servizio tramite PowerShell ma sto fallendo miseramente. Sospetto che sia il certificato e ho cercato su Google la risposta e ho trovato due opzioni, nessuna delle quali ha funzionato per me. Ho anche provato a combinare i due senza successo.Powershell Invoke-RestMethod su HTTPS

Opzione 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" 

Opzione 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" 

Ecco il messaggio di errore:

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 

mi permetto di aggiungere:

  • surf direttamente al servizio funziona con un browser web
  • Ho provato ad aprire a HTTP come bene, e che ha funzionato
  • Il certificato utilizzato dal servizio è self-signed, ma di fiducia da parte mia macchina tramite un Certficate root (nessun avviso è un problema in IE o Chrome)
  • Ho effettuato acquisizioni di rete e mi sono assicurato che un pacchetto raggiungesse effettivamente il server.

Qualsiasi suggerimento apprezzato!

Cordiali saluti, Patrik

Post aggiornato da suggerimenti formulati dal sig Albero di seguito:

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    : 

Update 2 sulla base di un commento di Mr 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 
+1

Provare '{$ true} -come [Net.Security.RemoteCertificateValidationCallback]' nel secondo esempio ... La CA è installata nell'archivio LocalMachine o CurrentUser? –

+0

Grazie per il vostro aiuto. La CA è installata con il mio account CurrentUser e Computer in Trusted Root Certification. Aggiungerà il risultato del comando che hai postato nel mio post in alto. – PatrikJ

+0

(non so cosa cercare lì) – PatrikJ

risposta

20

ho risolto il mistero, mentre la risoluzione di un'altra cosa. Il server Web in questione supportava solo TLS1.1 e TLS1.2. Powershell NON sembra supportarlo. Se ho abilitato TLS1.0 ha funzionato.

Per forzare TLS1.2 è possibile utilizzare questa linea:

[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 

Sperare che aiuti qualcun altro e grazie per tutti i commenti utili!

/Patrik

+1

Mi ha aiutato un sacco. Grazie per la pubblicazione! – floyd

0

Risulta stai cercando di invocare un'API JSON con Invoke-RestMethod. Secondo il documentation:

-ContentType

Specifica il tipo di contenuto della richiesta web.

Se questo parametro viene omesso e il metodo richiesta è POST, Invoke-RestMethod imposta il tipo di contenuto di "application/x-www-form-urlencoded". Altrimenti, il tipo di contenuto è non specificato nella chiamata.

Per utilizzare un corpo JSON, è necessario utilizzare Invoke-RestMethod -ContentType 'application/json' <other args>

0

ho passato un sacco di dolore di recente al fine di superare una situazione simile. Stavo creando un proof of concept usando un servizio SaaS di prova. Il servizio aveva un certificato SSL autofirmato, quindi volevo ignorare gli errori del certificato mentre tentavo di richiamare un metodo POST (simile al parametro "-k" per curl). Dopo molte difficoltà, ho trovato che era necessario entrambi - (a) la chiamata per ignorare gli errori di convalida del cert e (b) un'impostazione esplicita per TLS 1.2 come protocollo di sicurezza. Penso che quest'ultimo perché il servizio stava forse diminuendo i tentativi di connettersi usando uno qualsiasi degli altri protocolli. (Ho speso troppo tempo cercando le diverse varianti per fare ciascuna come suggerito in varie discussioni SOF ma indipendentemente ...)

Ecco il codice che ha lavorato ...

Importante: Il bypass di convalida CERT puramente per il prototipo/PoC. Non intendiamo farlo in produzione (e non dovresti neanche farlo!).

$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 
} 

vogliono anche aggiungere che i protocolli di sicurezza preferite continuano a cambiare come i vari vulnerabilità vengono scoperte e correzioni attuate. Inoltre, i diversi sistemi (stack SSL/TLS nei sistemi operativi e server/servizi client) hanno spesso il proprio interesse con le opzioni più recenti/più sicure. Quindi esattamente quale flag potrebbe funzionare sarà una funzione dei sistemi client e server e anche del tempo (in quanto TLS1.2 potrebbe non rimanere preferito qualche mese dopo). Idealmente non si dovrebbe assolutamente specificare un flag. Per ulteriori informazioni, consultare la sezione "Osservazioni" in this MSDN document.