Supporting TLS v1.2 with PowerShell SecurityProtocolType

With Microsoft PowerShell v5.1, the default security protocols used for the Invoke-WebRequest and Invoke-RestMethod cmdlets is either SSL v3.0 or TLS v1.0. Both of these protocols are fairly long in the tooth, with SSL v3.0 being somewhat uncommon in the wild when compared to TLS (Transport Layer Security). As more modern devices in the world migrate away from TLS v1.0, you may find yourself staring at some weird errors when attempting to send data over RESTful endpoints.

TLS is serious business.

Error example:

The underlying connection was closed: An unexpected error occurred on a send.
Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host.

That’s no fun. The reason for the error above is due to an endpoint requiring security that is more robust than SSL v3.0 and TLS v1.0 can provide. The connection is being terminated before the payload can be transferred.

There are a few ways to fix this issue. If you’re not using PowerShell v6.0 or better, which includes the -SslProtocol parameter (thanks to #5329), you’ll need to rely on a good ol’ .NET call. If you query `[Net.ServicePointManager]::SecurityProtocol` you can see the various protocols being used by your PowerShell session. Here’s mine:

Ssl3, Tls

The “Tls” item means TLS v1.0, whereas Tls11 and Tls12 are TLS v1.1 and TLS v1.2, respectively. You can see the full list via Intellisense.

Adding Security Protocols

There are numerous posts on how to change the security protocol for your current PowerShell session, such as this quality article entitled Force the Invoke-RestMethod PowerShell cmdlet to use TLS 1.2 from Cody Hosterman.

My only concern with this method is that the session is effectively altered such that only TLS v1.2 connections will work, which may be an issue if you’re mixing different endpoints within the same session, such as with using PowerCLI along side your own homebrew code.

Alternatively, you can simply add TLS v1.2 to your list of security protocols that the session will attempt to use.

try {
  if ([Net.ServicePointManager]::SecurityProtocol -notcontains 'Tls12') {
    [Net.ServicePointManager]::SecurityProtocol += [Net.SecurityProtocolType]::Tls12

The result from this bit of code is as follows:

Ssl3, Tls, Tls12

As you can see, the TLS v1.2 protocol is now added to the ServicePointManager list. This ensures backwards compatibility with older endpoints that may force the use of TLS v1.0 or, heck forbid, SSL v3.0, within the same session. 🙂

And, yes, this code was added to the Rubrik PowerShell Module to support TLS v1.2 protocol. Thanks, Michael!