skip to Main Content

TLS (Transport Layer Security) Wake Up Call

Remember when good old mom used to say to you when you were growing up – “A Word to the Wise is Sufficient””?

Well, here it is straight from the horse’s mouth! See footnote below.

Get your act together if you write code for the Dynamics 365 platform!

 

 

 

 

 

 

 

Microsoft is now enforcing the use of TLS 1.2+ only with the release of the v9 platform.

I am going to share with you the colorful details of it with some real-world examples which I got straight from the horse’s mouth – the Product Manager at Microsoft who owns this technology.

If you want to read the dry technical version you can find it here –  https://support.microsoft.com/en-us/help/4051700 and here: https://blogs.msdn.microsoft.com/crm/2017/09/28/updates-coming-to-dynamics-365-customer-engagement-connection-security/

Start Reading

The Microsoft tools and platforms though v8 have been based on .net 4.5.2,  which defaults to TLS 1.0 for security.  What this means is that CRM and Dynamics Tools shipped up through v8 will not seamlessly connect to v9.  When this shows up it always manifests as an auth failure.

Looking at the logs, you will see a message that looks like this:

In 8.1 connectors :

Microsoft.Xrm.Tooling.CrmConnectControl Information: 8 : Login Status in Connect is =  Validating connection to Microsoft Dynamics CRM…
Microsoft.Xrm.Tooling.Connector.CrmServiceClient Error: 2: ERROR REQUESTING Token FROM THE Authentication context
Microsoft.Xrm.Tooling.Connector.CrmServiceClient Error: 2 : Source  : mscorlib
Method   : ThrowIfExceptiona
Date         : 1/19/2018
Time        : 10:23:27 AM
Error        : One or more errors occurred.
Stack Trace  : at System.Threading.Tasks.Task.ThrowIfExceptional(Boolean includeTaskCanceledExceptions)at System.Threading.Tasks.Task`1.GetResultCore(Boolean waitCompletionNotification) at System.Threading.Tasks.Task`1.get_Result() at Microsoft.Xrm.Tooling.Connector.CrmWebSvc.ExecuteAuthenticateServiceProcess(Uri serviceUrl, ClientCredentials clientCredentials, UserIdentifier user, String clientId, Uri redirectUri, PromptBehavior promptBehavior, String tokenCachePath, Boolean isOnPrem, String authority, Uri& targetServiceUrl, AuthenticationContext& authContext, String& resource)

======================================================================================================================

Inner Exception Level 1           :
Source            : Microsoft.IdentityModel.Clients.ActiveDirectory
Method          : Close
Date                : 1/19/2018
Time               : 10:23:27 AM
Error              : Object reference not set to an instance of an object.
Stack Trace   : at Microsoft.IdentityModel.Clients.ActiveDirectory.HttpWebResponseWrapper.Close()
at Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationParameters.<CreateFromResourceUrlCommonAsync>d__0.MoveNext()
— End of stack trace from previous location where exception was thrown — at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationParameters.<CreateFromResourceUrlAsync>d__8.MoveNext()

======================================================================================================================

In the bits on NuGet now the error will look like this:

Inner Exception Level 1:
Source                              : System
Method                            : GetResponse
Date                                  : 1/16/2018
Time                                 : 4:37:46 PM
Error                                 : The underlying connection was closed: An unexpected error occurred on a send.
Stack Trace                      : at System.Net.HttpWebRequest.GetResponse()at System.ServiceModel.Description.MetadataExchangeClient.MetadataLocationRetriever.DownloadMetadata(TimeoutHelper timeoutHelper)at System.ServiceModel.Description.MetadataExchangeClient.MetadataRetriever.Retrieve(TimeoutHelper timeoutHelper)

======================================================================================================================

Inner Exception Level 2
Source                                : System
Method                              : Read
Date                                    : 1/16/2018
Time                                   : 4:37:46 PM
Error                                  : Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host.
Stack Trace                       : at System.Net.Sockets.NetworkStream.Read(Byte[] buffer, Int32 offset, Int32 size)at System.Net.FixedSizeReader.ReadPacket(Byte[] buffer, Int32 offset, Int32 count) at System.Net.Security.SslState.StartReceiveBlob(Byte[] buffer, AsyncProtocolRequest asyncRequest)
======================================================================================================================

Errors like this, in conjunction with trying to connect to a new trial or a v9 instance is a dead giveaway that it’s a TLS Problem.

Oh Uh, what do I do to fix this?

 There are a few ways to deal with this,

For tools Microsoft provides

The most simple and easy way to deal with it is to use the current SDK tools..  In their effort to help keep folks up to date, Microsoft, unfortunately, has made getting the SDK tools a bit more complicated but they did it for good reasons.

Historically, they would post a point in time copy of all the tools and samples into a massive download,  the problem is that to get all that together, it required a number of teams to work together to put a package together to post, this slowed down pushing updates.

Some of you may have noticed that they do not have the 9.x SDK posted that way.  If you have not noticed yet … They are not using a Single download anymore

They have moved over to NuGet to provide the current SDK bits.  This allows Microsoft to quickly patch and update SDK assemblies and tools.

They talked about it here: https://blogs.msdn.microsoft.com/crm/2017/11/01/whats-new-for-customer-engagement-developer-documentation-in-version-9-0/

To help with the SDK Download and to keep you current,  the documentation guru’s wrote up a handy PowerShell script in the documentation to help you get and keep current the SDK. It is one link off the central dev page bug. For reference the direct link is:  https://docs.microsoft.com/en-us/dynamics365/customer-engagement/developer/download-tools-nuget.  Using that script will always keep you current going forward with tools.

For Code built with the Microsoft SDK

The most simple and easy way to deal with this is to recompile your code with .net 4.6.2+.   If your code is already compiled with .net 4.6.2+ then your good to go.  EXCEPT if you started with Visual Studio and a project that started with .4.5.2   There is a quirk in VS which causes it to run in 4.5.2 mode even after you have changed the build version.  The simple way to deal with this is to clean your project after you change the .net version, close VS and delete the bin directory ( You need to get rid of the .vhost. files ) then restart VS and reload your project.  That should kick it into using the .net 4.6.+ runtime.   *note: this does not impact the binaries,  only on the debug experience in vs.

For existing code that cannot be recompiled

Microsoft exposes a registry setting in the blog articles that can be applied that will force .net to use TLS 1.2,  However, they want to stress caution with this though as it is very much the sledgehammer approach as it forces all .net software on the machine to use TLS 1.2 +.

For non .Net software

Check with your vendor on how to enabled TLS,  for most languages it can be done with a simple config entry

One important note for .net based apps.

It is really attractive to use the command: ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;

However, they cannot discourage enough from using this approach.  This forces the TLS 1.2 protocol all the time.  While this seems great,  if you ship software that lives more than a year or so, when the next security protocol appears and is adopted by the industry, your application with being at risk.

For Powershell

With regard to PowerShell scripts, however,  You will need to add  [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::TLS12 to your Powershell Script BEFORE you call Get-CrmConnection.

—————————————————————————————————————————————

This blog post is an edited for our blog version of the content provided to Business Solutions (CRM) MVPs by Matt Barbour.

Leave a Reply

Your email address will not be published. Required fields are marked *

Back To Top