HTTPS 不适用于具有自定义域的 Service Fabric 上的 Kestrel 3.2.187/ASPNET Core 2.1.5 运行

HTTPS not working with Kestrel 3.2.187/ASPNET Core 2.1.5 running on the Service Fabric with a custom domain

我们正在 运行 在我们的远程开发集群上安装一个 Service Fabric 应用程序。它由几个有状态和无状态服务组成,并以几个 front-end APIs 运行ning on Kestrel 为前端。

到目前为止,由于未用于生产,Kestrel 配置为使用 self-signed 证书,该证书也用于反向代理和集群本身,服务为 运行直接在 Azure 提供的默认域上,<app>.<region>.cloudapp.azure.com.

我们现在正处于 self-signed 证书错误成为问题的发展阶段,第三方回调拒绝连接,因此现在是时候开始使用正确的域和证书了为此。

到目前为止,我做了以下事情:

无论我如何尝试,都无法与服务器建立HTTPS 连接。尝试仍然使用旧证书的其他登台服务器的端点,它按预期工作。

使用 openssl s_client -connect devcluster.someexampledomain.com:<port> -prexit,我得到:

---
no peer certificate available
---
No client certificate CA names sent
---

ETW 上没有记录任何错误或异常,一切似乎都井井有条。我怀疑这可能与证书的 CN 有关,但我 运行 没有想法尝试找出发生了什么以及如何修复它。

一直在尝试使用 Fiddler 对此进行研究,但我并没有从中得到多少,session 仅以 fiddler.network.https> HTTPS handshake to <myhost> (for #191) failed. System.IO.IOException Authentication failed because the remote party has closed the transport stream.

结尾

有人知道如何在 Kestrel 端添加一些日志记录吗?我不认为在 Azure 虚拟机上安装 Fiddler 运行我的集群是一个可行的解决方案。

深入研究 Kestrel 源代码后,我发现它记录在 "Microsoft-AspNetCore-Server-Kestrel""Microsoft-Extensions-Logging" 下,因此添加这些文件的传输我发现了发生的事情。

连接因以下异常而终止:

System.ComponentModel.Win32Exception (0x8009030D): The credentials supplied to the package were not recognized
   at System.Net.SSPIWrapper.AcquireCredentialsHandle(SSPIInterface secModule, String package, CredentialUse intent, SCHANNEL_CRED scc)
   at System.Net.Security.SslStreamPal.AcquireCredentialsHandle(CredentialUse credUsage, SCHANNEL_CRED secureCredential)
   at System.Net.Security.SslStreamPal.AcquireCredentialsHandle(X509Certificate certificate, SslProtocols protocols, EncryptionPolicy policy, Boolean isServer)
   at System.Net.Security.SecureChannel.AcquireServerCredentials(Byte[]& thumbPrint, Byte[] clientHello)
   at System.Net.Security.SecureChannel.GenerateToken(Byte[] input, Int32 offset, Int32 count, Byte[]& output)
   at System.Net.Security.SecureChannel.NextMessage(Byte[] incoming, Int32 offset, Int32 count)
   at System.Net.Security.SslState.StartSendBlob(Byte[] incoming, Int32 count, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.ProcessReceivedBlob(Byte[] buffer, Int32 count, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.PartialFrameCallback(AsyncProtocolRequest asyncRequest)
--- End of stack trace from previous location where exception was thrown ---
   at System.Net.Security.SslState.EndProcessAuthentication(IAsyncResult result)
   at System.Threading.Tasks.TaskFactory`1.FromAsyncCoreLogic(IAsyncResult iar, Func`2 endFunction, Action`1 endAction, Task`1 promise, Boolean requiresSynchronization)
--- End of stack trace from previous location where exception was thrown ---
   at Microsoft.AspNetCore.Server.Kestrel.Https.Internal.HttpsConnectionAdapter.InnerOnConnectionAsync(ConnectionAdapterContext context)
   at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.HttpConnection.ApplyConnectionAdaptersAsync()

这使它成为 Certificate problem with a new machine - credentials supplied to package not recognized 的体现。

我花了一些时间试图弄清楚解决这个问题的最佳方法是什么,Service Fabric documentation 有一个脚本来修改权限,但这听起来不对。

事实证明,这可以直接在 ApplicationManifest 中完成,如下所示:

<Principals>
    <Users>
        <User Name="NETWORK SERVICE" AccountType="NetworkService" />
    </Users>
</Principals>
<Policies>
    <SecurityAccessPolicies>
        <SecurityAccessPolicy ResourceRef="HttpsCert2" PrincipalRef="NETWORK SERVICE" ResourceType="Certificate" />
    </SecurityAccessPolicies>
</Policies>
<Certificates>
    <SecretsCertificate X509FindValue="[HttpsCertThumbprint]" Name="HttpsCert" />
</Certificates>

要让 SecurityAccessPolicy 找到 ResourceRef,它 必须 SecretsCertificate,而不是 EndpointCertificate。由于 EndpointBindingPolicy 需要一个 EndpointCertificate,我只是添加了一个 SecretsCertificate 和一个 EndpointCertificate,但名称不同。他们都指的是同一个证书,所以它有效。不得不将它们加倍感觉不是特别干净,但这是我现在的解决方案。