downloading a web page with powershell using a x.509 certificate - powershell

I am having a problem with PowerShell on Windows 10 trying to download a file from a site that uses an X.509 certificate to authenticate the client. I have this certificate installed in my certificate store in IE and I also have exported the PFX file. Here's what I have tried:
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::ssl3 and also tls12
trying to get the certificate using System.Security.Cryptography.X509Certificates.X509Certificates2
trying to set the credentials via Get-Credential and then passing it
I've used the Invoke-WebRequest command as well as System.Net.WebClient trying to get this to work. The error message I'm getting is as follows:
PS P:\PSScripts> P:\PSScripts\DownloadSslHtml.ps1
VERBOSE: GET https://somewebsite.com/GetReports.do?reportTypeId=1234
with 0-byte payload
Invoke-WebRequest : The request was aborted: Could not create SSL/TLS secure channel.
At P:\PSScripts\DownloadSslHtml.ps1:20 char:1
+ Invoke-WebRequest -Uri $url -UserAgent ([Microsoft.PowerShell.Command ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-
WebRequest], WebException + FullyQualifiedErrorId :
WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeWebRequestCommand
Now I have seen a lot of people with this "SSL/TLS secure channel" error and they fixed it by specifying the encryption method as TLS12 or SSL3, neither of which is working for me. I'm confused how to proceed. Any thoughts? The website is using TLS1.2 AES with 256 bit encryption ECDH 256 bit exchange.
EDIT: Here's my powershell code:
$url = "https://somewebsite.com/GetReports.do?reportTypeId=1234"
$outputFile = "P:/DownloadedData/file.html"
$PFXPath = "P:/Properties/Config/mycert.pfx"
$PFXPassword = "cert_password"
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::tls12
$cert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2
$cert.Import($PFXPath,$PFXPassword,'DefaultKeySet')
Invoke-WebRequest -Uri $url -UserAgent ([Microsoft.PowerShell.Commands.PSUserAgent]::InternetExplorer) -Certificate $cert -OutFile $outputFile -Verbose

I changed this line:
$cert.Import($PFXPath,$PFXPassword,'DefaultKeySet')
to this:
$cert.Import($PFXPath,$PFXPassword,'UserKeySet')
And now it works!

Related

Google Text-to-Speech : Error could not auto authenticate

I'm using the google text to speech API in the powershell. I've created the project, enabled the api, created the key, when I tell it this
$cred = gcloud auth application-default print-access-token
$headers = #{ "Authorization" = "Bearer $cred" }
Invoke-WebRequest -Method POST
-Headers $headers -ContentType: "application/json; charset=utf-8"
-InFile request.json `
-Uri "https://texttospeech.googleapis.com/v1/text:synthesize" | Select-Object -Expand Content
And this is after I set the environment, I get this error message
ERROR: (gcloud.auth.application-default.print-access-token) Could not automatically determine credentials. Please set GOOGLE_APPLICATION_CREDENTIALS or explicitly create credentials and re-run the application. For more information, please see https://cloud.google.com/docs/authentication/getting-started
Invoke-WebRequest : The remote server returned an error: (403) Forbidden.
At line:4 char:1
Invoke-WebRequest `
+ CategoryInfo : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-WebRequest], WebExc
eption
+ FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeWebRequestCommand
I have attempted to recreate the key thinking that was maybe the issue but I keep getting this error here no matter what I do, I am using this code to point to the key
$env:GOOGLE_APPLICATION_CREDENTIALS=C:\IVR2\IVR2-ba991f7cce6a.json
For an application, you would set the env variable GOOGLE_APPLICATION_CREDENTIALS which is the location of your service account json file.
It looks like you're using gcloud to get creds and including an authorization header. That should work too. Does your gcloud command return an error?

powershell could not create ssl/tsl secure

I'm using a powershell script to download and execute a file, but since some time I go I get a could not create ssl/tsl secure channel.
$down = New-Object System.Net.WebClient;
$url = 'url';
$file = 'file';
$down.DownloadFile($url,$file);
$exec = New-Object -com shell.application;
$exec.shellexecute($file);
exit;
TLS 1.2 should be enabled to get it working. In PowerShell you can find out which protocols your system supports by running this code:
[Enum]::GetNames([Net.SecurityProtocolType]) -contains 'Tls12'
If the result is True then your system supports TLS 1.2. You can find out which protocols are being used by running:
[System.Net.ServicePointManager]::SecurityProtocol.HasFlag([Net.SecurityProtocolType]::Tls12)
If the result is True then TLS 1.2 is being used . However, you can add TLS 1.2 explicitly by using:
[Net.ServicePointManager]::SecurityProtocol = [Net.ServicePointManager]::SecurityProtocol -bor [Net.SecurityProtocolType]::Tls12
This should solve these problems.
It may be that the site you are connection to requires TLS 1.2, whereas powershell uses TLS 1.0 by default (if I remember correctly)
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
$down = New-Object System.Net.WebClient
$url = 'https://github.com/mpdairy/posh.git'
$file = 'C:\ExistingDirectory\test.git'
$down.DownloadFile($url,$file)
$exec = New-Object -com shell.application
$exec.shellexecute($file)
exit
Without using Tls 1.2, I get this error:
Exception calling "DownloadFile" with "2" argument(s): "The request was aborted: Could not create SSL/TLS
secure channel."
At line:1 char:1
+ $down.DownloadFile($url,$file)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : WebException
I ran into the same error trying to install Wiki.js in Windows server. The issue was the ps1 script included TLS 1.1 as a fallback. The steps below can be changed for any other powershell install
To fix this;
I downloaded the install.ps1 file from installation instructions on Wiki.js installation
iex ((New-Object System.Net.WebClient).DownloadString('https://wiki.js.org/install.ps1'))
Removed "tls11, tls" from the first line
From:
[Net.ServicePointManager]::SecurityProtocol = "tls12, tls11, tls"
To:
[Net.ServicePointManager]::SecurityProtocol = "tls12"
Saved the file in a local directory and changed directory (CD) into
the local directory Ran the command
"iex .\install.ps1"
It's all good now.
Refer this sample code. I written this couple of years when Terraform moved to TLS.
$source=<folder where file suppose to be present>
Write-Verbose -Verbose "Downloading Terraform Required"
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::TLS12
$wc = New-Object System.Net.WebClient
if ((test-path "${source}\terraform.zip") -eq $false) {
$wc.downloadfile("https://releases.hashicorp.com/terraform/0.11.2/terraform_0.11.2_windows_amd64.zip","${source}\terraform.zip")
}
Add-Type -assembly "system.io.compression.filesystem"
[io.compression.zipFile]::ExtractToDirectory("$source\terraform.zip", $destination)
I had the same problem just before and how I fixed it is by changing the link. Make sure the page you're trying to download is a RAW file, for example -
https://raw.githubusercontent.com/TTT2866/Batch-username-generator/master/username_generator.bat
and not
https://github.com/TTT2866/Batch-username-generator/blob/master/username_generator.bat
Note the "raw" in the first link

Powershell Invoke-RestMethod Call using Windows store certificate (Basic Authorization ?)

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
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.

Having trouble uploading large files with Invoke-RestMethod

I am trying to use the Hashicorp Atlas restful api to upload box files into but I am running into problems when uploading large files.
I am currently using the following command which works with small files like 100mb but most box files are well over 4GB where I start to see the problem:
$Filename = "c:\box\mybox.box"
$uploadpath = "https://archivist.hashicorp.com/v1/object/example"
$Timeout = 86400 #24 hours
Invoke-RestMethod -Uri $uploadPath -Method Put -InFile $Filename -TimeoutSec $Timeout -ContentType "multipart/form-data"
The error:
Invoke-RestMethod : The underlying connection was closed: An unexpected error occurred on a send.
At C:\Program Files\WindowsPowerShell\Modules\atlasbox\1.1.15\AtlasBox.psm1:642 char:5
+ Invoke-RestMethod -Uri $uploadPath -Method Put -InFile $Filename ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-RestMethod], WebException
+ FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand
If I use CURL command as per the documentation it works fine.
curl -X PUT --upload-file /path/to/my.box https://archivist.hashicorp.com/v1/object/example
Any idea how to make Invoke-RestMethod behave the same way curl does?
I can't take a dependency on curl because not all systems I run this on will have WSL installed and no curl.
Documentation for Atlas API is here: https://atlas.hashicorp.com/help/api/vagrant/box-providers
Looks like it might be getting weird on the SSL cert? I would try some of the recommendations here to start with, definitely an oddity specific to those cmdlets though:
Powershell v3 Invoke-WebRequest HTTPS error

Invoke-WebRequest with PScredentials

I'm trying to retrieve a file from an external HTTPS site. My code below works a treat in POSH 3.0, but in POSH 4.0, not so much. The message I get is below. Anyone experiencing the same issue, know how to resolve this or a workaround?
Invoke-WebRequest :
Authentication Required.
You must be authenticated to access this URL.
URL: https://www.mywebsite.com
User name:
At line:4 char:1
+ Invoke-WebRequest -Uri https://www.mywebsite.com/report.pdf ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-WebRequest], WebException
+ FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeWebRequestCommand
$pw = ConvertTo-Securestring -AsPlainText -Force -String "myPWD"
$cred = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList ("myUser",$pw)
Invoke-WebRequest -Uri https://www.mywebsite.com/report.pdf -Credential $cred -OutFile C:\report.pdf
So I found that even though I could access the website and retrieve my content with my browser, the McAfee Web Gateway was preventing Powershell from doing the same thing. Once we whitelisted the URL, BOOM, no problems. Thanks everyone for the additional ideas in helping me troubleshoot this!