1

I would like to call a remote Rest web service from a Windows server hosting the remote certificate. I've exported the certificate from the remote server and added it to the Windwos store. (/Personal/myCert)

I would like to use it on a Invoke-RestMethod PowerShell command. Here bellow is the code I've tried

# Variables
$Remote_Uri = "https://remote.example.com/service/search"
$Remote_CertificateName = "myCert"
$Remote_ApiKey = "oisdjfSOEDJFKQDfSDKFjsQDKFJ"
$Remote_ContentType = "application/json"
$LocalArtifactPath = "C:\RemoteObjects.json"

# Get Certificate
$Remote_CertificateThumbprint = (Get-ChildItem -Path Cert:\LocalMachine\My | Where-Object {$_.Subject -match $Remote_CertificateName}).Thumbprint;
$Certificate = Get-ChildItem -Path Cert:\LocalMachine\My\$Remote_CertificateThumbprint

# Basic Encoding
$encoding = [System.Text.Encoding]::ASCII.GetBytes($Certificate)
$encodedString = [System.Convert]::ToBase64String($encoding)
$BasicAuth = "Basic " + $encodedString

# Set Headers
$Headers = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
$Headers.Add("Authorization", $BasicAuth)
$Headers.Add("api", $Remote_ApiKey)
$Headers.Add("Content-Type", $Remote_ContentType)

# Self-signed certificate
[System.Net.ServicePointManager]::ServerCertificateValidationCallback = { $true } 

# Call Rest Service
Invoke-RestMethod -Method Get -Uri $Remote_Uri -OutFile $LocalArtifactPath -Headers $Headers 
Invoke-RestMethod -Method Get -Uri $Remote_Uri -OutFile $LocalArtifactPath -Certificate $Certificate
Invoke-RestMethod -Method Get -Uri $Remote_Uri -OutFile $LocalArtifactPath -CertificateThumbprint $Remote_CertificateThumbprint

# Self-signed certificate off
[System.Net.ServicePointManager]::ServerCertificateValidationCallback = $null

The three lines with Invoke-RestMethod commands failed with respectively :

  • Wrong header (this was expected but I gave it a try)
  • Authorization is empty or scheme is not basic
  • Certificate thumbprint not found

I've got the rest call working with @{"AUTHORIZATION"="Basic Base64Encode(user:pass)"} so I can tell the service is answering but I would like not to use user:pass in my script.

I would like to use the Certificate I've added to the Windows Store. I'm wondering about two things :

  • Is the "Basic" authorization scheme is the good one to use with a certificate ?
  • In powershell, how to use a certificate from the local windows store running Invoke-RestMethod command ?

Thank you for your help

Johny E
  • 25
  • 2
  • 6
  • It seems you want to make a call using a *client* certificate. This certificate is not the same as the *server* certificate. To authenticate with a client certificate, the *server* needs to have the certificate used by the caller and use it for verifying their identity. The server's own certificate can't be used for this purpose, as that only identifies the server. – Jeroen Mostert Aug 21 '17 at 10:19
  • Thank you for your anwser @JeroenMostert. The remote server I'd like to access has provided to me a "client certificate" that I've added to the local Windows Certificate Store (Maybe this part is an error). This is the certificate I'd like to use in my powershell command. I've tested it with SoapUI and it worked as described. I've added "client certificate" to SoapUI, and call the service using this authentication. The remote service replied correctly. I'd like to reproduce the same replacing SoapUI by powershell. Then the place to "add the certificate" is the Windows store no ? – Johny E Aug 21 '17 at 12:03
  • Yes. Just verifying that you really do want client certificate authentication and you're using the correct certificate (it's easy to get this wrong). Have you verified the contents of `$Certificate`? Is the certificate visible in `dir cert:\LocalMachine\My`? – Jeroen Mostert Aug 21 '17 at 12:11
  • You may need to install the certificate to `CurrentUser\My` certificate store. Standard users don't have permissions to access keys installed in the `LocalMachine\My` store. – Crypt32 Aug 21 '17 at 12:14
  • Indeed, this command returns my certificate and its thumbprint. Also when I run the powershell command one by one everything is set. @Crypt32 thank you for the idea. It will solve an issue that I will probably face in the future. But atm I'm admin of the machine running powershell. – Johny E Aug 21 '17 at 12:18
  • Anyway. Normal admin session is not elevated. – Crypt32 Aug 21 '17 at 12:32
  • You're right, I've added it to `CurrentUser\My` but same error with `-Certificate $Certificate` parameter. _Invoke-RestMethod : The underlying connection was closed: An unexpected error occurred on a send_. – Johny E Aug 21 '17 at 12:48

1 Answers1

0

Adding this [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 in my script fixed the "The underlying connection was closed" issue.

Before this crosscheck whether IIS is enabled in your system.

neuhaus
  • 3,886
  • 1
  • 10
  • 27
Shunmugam V
  • 73
  • 1
  • 8