Service Fabric Asp.Net 核心无状态服务上的 HTTP 和 HTTPS 终结点

Both HTTP and HTTPS endpoints on Service Fabric Asp.Net Core stateless Service

我有一个 Service Fabric 无状态 Asp.Net 核心服务。

该服务使用 HTTP 端点。 我需要支持 HTTPS 端点以及 HTTP

目前我的步数:

  1. 将证书添加到 Azure KeyVault
  2. 更新 ApplicationManifest.xml 为:

    <Policies>
      <EndpointBindingPolicy EndpointRef="ServiceEndpointHttps" CertificateRef="Certificate" />
    </Policies>
    

最后

<Certificates>
    <EndpointCertificate X509StoreName="MY" X509FindValue="XXXX" Name="Certificate" />
  </Certificates>
  1. 在 ServiceManifest.xml 中使用端口 443 添加端点

我现在只剩下启用 HTTPS 端点了。 在 Program.cs 我有这个:

  public static void Main(string[] args)
        {
            ServiceRuntime.RegisterServiceAsync("MyType", context => new WebHostingService(context, "ServiceEndpoint")).GetAwaiter().GetResult();

            Thread.Sleep(Timeout.Infinite);
        }
 internal sealed class WebHostingService : StatelessService, ICommunicationListener
        {
            private readonly string _endpointName;

            private IWebHost _webHost;

            public WebHostingService(StatelessServiceContext serviceContext, string endpointName)
                : base(serviceContext)
            {
                _endpointName = endpointName;
            }

            #region StatelessService

            protected override IEnumerable<ServiceInstanceListener> CreateServiceInstanceListeners()
            {
                return new[] { new ServiceInstanceListener(_ => this) };
            }

            #endregion StatelessService

            #region ICommunicationListener

            void ICommunicationListener.Abort()
            {
                _webHost?.Dispose();
            }

            Task ICommunicationListener.CloseAsync(CancellationToken cancellationToken)
            {
                _webHost?.Dispose();

                return Task.FromResult(true);
            }

            Task<string> ICommunicationListener.OpenAsync(CancellationToken cancellationToken)
            {
                var endpoint = FabricRuntime.GetActivationContext().GetEndpoint(_endpointName);

                string serverUrl = $"{endpoint.Protocol}://{FabricRuntime.GetNodeContext().IPAddressOrFQDN}:{endpoint.Port}";

                _webHost = new WebHostBuilder().UseKestrel()
                                               .UseContentRoot(Directory.GetCurrentDirectory())
                                               .UseStartup<Startup>()
                                               .UseUrls(serverUrl)
                                               .Build();

                _webHost.Start();

                return Task.FromResult(serverUrl);
            }

            #endregion ICommunicationListener
        }

如何在此处注册 HTTPS 端点?

添加第二个 ServiceRuntime.RegisterServiceAsync 无效。

此外,启用它后,我如何安装(从门户或 powershell)KeyVault 中的证书到已经部署的虚拟机规模集和 运行?

我周末刚遇到这个问题。我听从了一些关于不使用 Kestrel 而是使用 WebListener 的建议:

new WebHostBuilder()
.UseWebListener()
.UseContentRoot(Directory.GetCurrentDirectory())
.UseStartup<Startup>()
.UseUrls($"{endpoint.Protocol}://+:{endpoint.Port}")
.Build();

另请注意 url 使用 + 而不是 FabricRuntime.GetNodeContext().IPAddressOrFQDN

希望对您有所帮助。

我决定使用 Azure 应用程序网关。

您实际上可以使用 Kestrel + HTTPS + Service Fabric,但这更像是一次冒险。

1)证书需要自己找(见下文) 2)如果你在你的本地机器上测试,你需要将证书添加到 LocalMachine 并确保你授予网络服务权限(mmc\证书\本地机器\个人\证书,右键单击所有任务\管理私钥...)

        private X509Certificate2 FindCertificate(string thumbprint)
        {
            X509Store store = new X509Store(StoreName.My, StoreLocation.LocalMachine);
            try
            {
                store.Open(OpenFlags.ReadOnly);
                X509Certificate2Collection col = store.Certificates.Find(X509FindType.FindByThumbprint,
                    thumbprint, false); // Don't validate certs, since the test root isn't installed.
                if (col == null || col.Count == 0)
                    return null;
                return col[0];
            }
            finally
            {
                store.Close();
            }
        }

        Task<string> ICommunicationListener.OpenAsync(CancellationToken cancellationToken)
        {
            var endpoint = FabricRuntime.GetActivationContext().GetEndpoint(_endpointName);

            string serverUrl = $"{endpoint.Protocol}://{FabricRuntime.GetNodeContext().IPAddressOrFQDN}:{endpoint.Port}";

            _webHost = new WebHostBuilder().UseKestrel(options =>
                                            {
                                                options.UseHttps(FindCertificate("<thumbprint-remove-magic-character at the beginning if copy&paste from MMC>"));
                                            })