B. McCartney
B. McCartney

Reputation: 162

SSL/TLS connections not working when deployed as Azure App Service

My team has an application that is currently deployed as an azure cloud service. The application works well, but after deploying as an app service (as a continuous web job), we're seeing many types of TLS connection failures. The TLS certificates are loaded into HTTPS clients and TCP socket clients. Why are these breaking when running as an app service?

TCP:

System.ComponentModel.Win32Exception (0x80004005): The credentials supplied to the package were not recognized
System.Net.SSPIWrapper.AcquireCredentialsHandle(SSPIInterface SecModule, String package, CredentialUse intent, SecureCredential scc)
System.Net.Security.SecureChannel.AcquireCredentialsHandle(CredentialUse credUsage, SecureCredential& secureCredential)
System.Net.Security.SecureChannel.AcquireClientCredentials(Byte[]& thumbPrint)
System.Net.Security.SecureChannel.GenerateToken(Byte[] input, Int32 offset, Int32 count, Byte[]& output)
System.Net.Security.SecureChannel.NextMessage(Byte[] incoming, Int32 offset, Int32 count)
System.Net.Security.SslState.StartSendBlob(Byte[] incoming, Int32 count, AsyncProtocolRequest asyncRequest)
System.Net.Security.SslState.ProcessReceivedBlob(Byte[] buffer, Int32 count, AsyncProtocolRequest asyncRequest)
System.Net.Security.SslState.StartReceiveBlob(Byte[] buffer, AsyncProtocolRequest asyncRequest)
System.Net.Security.SslState.CheckCompletionBeforeNextReceive(ProtocolToken message, AsyncProtocolRequest asyncRequest)
System.Net.Security.SslState.ProcessReceivedBlob(Byte[] buffer, Int32 count, AsyncProtocolRequest asyncRequest)
System.Net.Security.SslState.StartReceiveBlob(Byte[] buffer, AsyncProtocolRequest asyncRequest)
System.Net.Security.SslState.CheckCompletionBeforeNextReceive(ProtocolToken message, AsyncProtocolRequest asyncRequest)
System.Net.Security.SslState.ProcessReceivedBlob(Byte[] buffer, Int32 count, AsyncProtocolRequest asyncRequest)
System.Net.Security.SslState.StartReceiveBlob(Byte[] buffer, AsyncProtocolRequest asyncRequest)
System.Net.Security.SslState.CheckCompletionBeforeNextReceive(ProtocolToken message, AsyncProtocolRequest asyncRequest)
System.Net.Security.SslState.ProcessReceivedBlob(Byte[] buffer, Int32 count, AsyncProtocolRequest asyncRequest)
System.Net.Security.SslState.StartReceiveBlob(Byte[] buffer, AsyncProtocolRequest asyncRequest)
System.Net.Security.SslState.CheckCompletionBeforeNextReceive(ProtocolToken message, AsyncProtocolRequest asyncRequest)
System.Net.Security.SslState.ForceAuthentication(Boolean receiveFirst, Byte[] buffer, AsyncProtocolRequest asyncRequest)
System.Net.Security.SslState.ProcessAuthentication(LazyAsyncResult lazyResult)

HTTP:

System.Net.WebException: The underlying connection was closed: Could not establish trust relationship for the SSL/TLS secure channel. ---> System.Security.Authentication.AuthenticationException: The remote certificate is invalid according to the validation procedure.
System.Net.Security.SslState.StartSendAuthResetSignal(ProtocolToken message, AsyncProtocolRequest asyncRequest, Exception exception)
System.Net.Security.SslState.CheckCompletionBeforeNextReceive(ProtocolToken message, AsyncProtocolRequest asyncRequest)
System.Net.Security.SslState.ProcessReceivedBlob(Byte[] buffer, Int32 count, AsyncProtocolRequest asyncRequest)
System.Net.Security.SslState.StartReceiveBlob(Byte[] buffer, AsyncProtocolRequest asyncRequest)
System.Net.Security.SslState.CheckCompletionBeforeNextReceive(ProtocolToken message, AsyncProtocolRequest asyncRequest)
System.Net.Security.SslState.ProcessReceivedBlob(Byte[] buffer, Int32 count, AsyncProtocolRequest asyncRequest)
System.Net.Security.SslState.StartReceiveBlob(Byte[] buffer, AsyncProtocolRequest asyncRequest)
System.Net.Security.SslState.CheckCompletionBeforeNextReceive(ProtocolToken message, AsyncProtocolRequest asyncRequest)
System.Net.Security.SslState.ProcessReceivedBlob(Byte[] buffer, Int32 count, AsyncProtocolRequest asyncRequest)
System.Net.Security.SslState.StartReceiveBlob(Byte[] buffer, AsyncProtocolRequest asyncRequest)
System.Net.Security.SslState.CheckCompletionBeforeNextReceive(ProtocolToken message, AsyncProtocolRequest asyncRequest)
System.Net.Security.SslState.ForceAuthentication(Boolean receiveFirst, Byte[] buffer, AsyncProtocolRequest asyncRequest)
System.Net.Security.SslState.ProcessAuthentication(LazyAsyncResult lazyResult)
System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
System.Net.TlsStream.ProcessAuthentication(LazyAsyncResult result)
System.Net.TlsStream.Write(Byte[] buffer, Int32 offset, Int32 size)
System.Net.ConnectStream.WriteHeaders(Boolean async)   --- End of inner exception stack trace ---
System.Net.HttpWebRequest.GetRequestStream(TransportContext& context)
System.Net.HttpWebRequest.GetRequestStream()

Remote Certificate:

-----BEGIN CERTIFICATE-----
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
-----END CERTIFICATE-----

Upvotes: 2

Views: 2213

Answers (2)

B. McCartney
B. McCartney

Reputation: 162

Add this to the App Settings in the portal for your app service

WEBSITE_LOAD_CERTIFICATES = *
  • You still need this even if you're not loading certs in the SSL Certificates area of the portal
  • This will impact the web jobs for that app service

Upvotes: 2

evilSnobu
evilSnobu

Reputation: 26314

The thawte Primary Root CA - G3 certificate, with thumbprintF18B538D1BE903B6A6F056435B171589CAF36BF2, is not present in the Trusted Root store on the App Service worker, thus remote cert validation fails. The leaf cert (intermediate) is missing as well.

Certification path

Comparing Trusted Root store, local vs Kudu

Which doesn't make for terribly good news. I see two options, either build a chain on-the-fly (which loads the missing CA cert from disk), or blindly return true from WebRequestHandler and its ServerCertificateValidationCallback delegate property.

NOTE: I do have a working sample somewhere for the first part, let me know if i should look that up. In essence:

  • Load the missing root CA from disk into X509Certificate2
  • Build a chain and add it in
  • Pass it to ServerCertificateValidationCallback in WebRequestHandler

Upvotes: 1

Related Questions