New Encryption and Certificate Defaults in Microsoft's SQL Server Connection Provider

Note: This blog post is going to borrow a bit from Microsoft's official documentation in "Connect with Azure Data Studio" and from our book, Learn dbatools in a Month of Lunches. It also addresses dbatools 2.0, which is currently in pre-release.

Microsoft recently made some changes to the default encryption settings of the SQL Server connection provider. This change, which is more secure by default, currently impacts dbatools 2.0, Azure Data Studio and I imagine it'll impact future versions of SQL Server Management Studio. It'll actually prevent you from connecting entirely if your SQL Server isn't properly setup for connecting over TLS/SSL.

This is what Azure Data Studio has to say about it when you open up newer versions

Azure Data Studio 1.40 and later includes an important change to the Encrypt property, which is now enabled (set to True) by default for MSSQL provider connections, and SQL Server must be configured with TLS certificates signed by a trusted root certificate authority.

And this is what dbatools 2.0 has to say about it (complete with some dot matrix printer ASCII art)

Historically, and I was suprised by this, most apps including SSMS have defaulted to connecting over an unencrypted channel and it was set to Trust server certificate by default.

Now about year or two ago, Microsoft set Trust server certificate to False by default in newer SQL connection libraries. We started using the new defaults in dbatools 1.1 and it tripped up a lot of people. In the most recently released libraries, Trust server certificate continues to be set to False AND Encrypt is now set to True by default.

So, to be clear, here's what new connection strings will include by default

  • Encrypt=True (aka Mandatory)
  • Trust Server Certificate=False

If your environment isn't setup to support encrypted connections or your certificate isn't setup right, you may run into a variety of error messages including:

  • The target principal name is incorrect
  • An existing connection was forcibly closed by the remote host
  • The certificate chain was issued by an authority that is not trusted
  • The instance of SQL Server you attempted to connect to does not support encryption
  • The remote certificate was rejected by the provided RemoteCertificateValidationCallback

How to fix these errors

In the event that you receive one of the above errors, don't fret. You have two options:

  • Setup SQL Server connection encryption in SQL Server Configuration Manager or dbatools (recommended)
  • Revert to the previous, less secure defaults

If you're tempted to revert to the less secure defaults, you should ask your security team to sniff the SQL Server's traffic and tell you what they can see. I was so shocked the first time I saw it -- an app role password was right there, staring me in the face. Ever since, I always encrypt connections. And surprisingly, I can't recall running into any application that had issues or even needed to change its connection string.

Setting up SQL Server connection encryption

If you'd like to setup the whole thing using a GUI, check out SQLShack's article, "How to set and use encrypted SQL Server connections".

If you'd like to use dbatools, our book covers this in Chapter 24 "Security and Encryption", but here's the code.

 1# Does your AD account have permission to create certificates? Try New-DbaComputerCertificate
 2New-DbaComputerCertificate -ComputerName sql1 -Dns, sql1
 4# If you don't, you can create a Certificate Signing Request that'll work
 5New-DbaComputerCertificateSigningRequest -ComputerName sql1 -Dns, sql1
 7# Unsure if any candidates already exist? Check certs that can be used for encryption        
 8Get-DbaComputerCertificate -ComputerName sql1
10# Already have a cert? Use it!
11Set-DbaNetworkCertificate -SqlInstance SqlInstance -Thumbprint 1245FB1ACBCA44D3EE9640F81B6BA14A92F3D6E2
13# Or get a visual and use some piping        
14Get-DbaComputerCertificate | Out-GridView -PassThru | Set-DbaNetworkCertificate -SqlInstance sql1
16# Once you've got your certs setup, Force Network Encryption        
17Enable-DbaForceNetworkEncryption -SqlInstance sql1

Now you're set and you don't even have to worry about future changes made by Microsoft. But I do recommend setting up a certifiate expiration test and have it alert you if you're about to need to do some updates.

 1# Then setup a check that alerts you if any certs are about to expire
 2Test-DbaComputerCertificateExpiration -ComputerName sql1
 4# But if you'd like to see some output, set a higher therashold
 5Test-DbaComputerCertificateExpiration -ComputerName sqlcs -Threshold 1000
 7ComputerName      : SQLCS
 8Store             : LocalMachine
 9Folder            : My
10Name              : SQL Server
11DnsNameList       : {sqlcs,}
12Thumbprint        : F8094891311522237B4B5D0C6EC6C97F423FD961
13NotBefore         : 10/11/2022 8:47:37 PM
14NotAfter          : 10/10/2024 8:47:37 PM
15Subject           :
16Issuer            : CN=ad-DC1-CA, DC=ad, DC=local
17Algorithm         : sha256RSA
18ExpiredOrExpiring : True
19Note              : This certificate expires in 584 days

Reverting to previous defaults

If you'd like to go back to the way it used to be, I don't know how other apps do it but here's how to do it in dbatools:

1# Set defaults just for this session
2Set-DbatoolsConfig -FullName sql.connection.trustcert -Value $true
3Set-DbatoolsConfig -FullName sql.connection.encrypt -Value $false
5# Set these defaults for all future sessions on this machine
6Set-DbatoolsConfig -FullName sql.connection.trustcert -Value $true -Register
7Set-DbatoolsConfig -FullName sql.connection.encrypt -Value $false -Register

Of you can use the new command available in dbatools 2.0, Set-DbatoolsInsecureConnection:

1# Set these defaults for all future sessions on this machine
4# Set defaults just for this session
5Set-DbatoolsInsecureConnection -SessionOnly

This will have to happen on every computer where you run dbatools. If you have a CI/CD pipeline, this will have to be added to your code. That's what we did for our own pipeline.

1      - name: Set encryption values
2        run: |
3          Set-DbatoolsConfig -FullName sql.connection.trustcert -Value $true -Register
4          Set-DbatoolsConfig -FullName sql.connection.encrypt -Value Optional -Register          

Checking to see what's connected

If you'd like to see which connections are encrypted, you can use the super useful Get-DbaProcess command.

1Get-DbaProcess -SqlInstance sqlcs |
2Where EncryptOption -ne $null |
3Select Login, Program, ClientNetAddress, NetTransport, EncryptOption

If this doesn't work for you, first, let us know in this issue and second, please check your Kerberos settings using Test-DbaSpn and set them as necessary. The new SMO libraries seem to be a bit more strict about Kerberos as well.

Want to try dbatools 2.0?

If you'd like to give it whirl, you can install dbatools from the PowerShell Gallery.

1Install-Module dbatools

There are a bunch of changes and bug fixes and it should even load faster for you. We're really excited about this release! (Just dreading the encryption messaging haha)