You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

89 lines
4.2 KiB

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Fabric;
  4. using System.IO;
  5. using System.Linq;
  6. using System.Net;
  7. using System.Security.Cryptography.X509Certificates;
  8. using System.Threading;
  9. using System.Threading.Tasks;
  10. using Microsoft.AspNetCore.Hosting;
  11. using Microsoft.Extensions.DependencyInjection;
  12. using Microsoft.ServiceFabric.Services.Communication.AspNetCore;
  13. using Microsoft.ServiceFabric.Services.Communication.Runtime;
  14. using Microsoft.ServiceFabric.Services.Runtime;
  15. using Microsoft.ServiceFabric.Data;
  16. namespace ApiGw_Base
  17. {
  18. /// <summary>
  19. /// The FabricRuntime creates an instance of this class for each service type instance.
  20. /// </summary>
  21. internal sealed class ApiGw_Base : StatelessService
  22. {
  23. public ApiGw_Base(StatelessServiceContext context)
  24. : base(context)
  25. { }
  26. /// <summary>
  27. /// Optional override to create listeners (like tcp, http) for this service instance.
  28. /// </summary>
  29. /// <returns>The collection of listeners.</returns>
  30. protected override IEnumerable<ServiceInstanceListener> CreateServiceInstanceListeners()
  31. {
  32. return new ServiceInstanceListener[]
  33. {
  34. new ServiceInstanceListener(serviceContext =>
  35. new KestrelCommunicationListener(serviceContext, "ServiceEndpoint", (url, listener) =>
  36. {
  37. ServiceEventSource.Current.ServiceMessage(serviceContext, $"Starting Kestrel on {url}");
  38. return new WebHostBuilder()
  39. .UseKestrel(opt =>
  40. {
  41. int port = serviceContext.CodePackageActivationContext.GetEndpoint("ServiceEndpoint").Port;
  42. opt.Listen(IPAddress.IPv6Any, port, listenOptions =>
  43. {
  44. listenOptions.UseHttps(GetCertificateFromStore());
  45. listenOptions.NoDelay = true;
  46. });
  47. })
  48. .ConfigureServices(
  49. services => services
  50. .AddSingleton<StatelessServiceContext>(serviceContext))
  51. .UseContentRoot(Directory.GetCurrentDirectory())
  52. .UseStartup<Startup>()
  53. .UseServiceFabricIntegration(listener, ServiceFabricIntegrationOptions.None)
  54. .UseUrls(url)
  55. .Build();
  56. }))
  57. };
  58. }
  59. /// <summary>
  60. /// Finds the ASP .NET Core HTTPS development certificate in development environment. Update this method to use the appropriate certificate for production environment.
  61. /// </summary>
  62. /// <returns>Returns the ASP .NET Core HTTPS development certificate</returns>
  63. private static X509Certificate2 GetCertificateFromStore()
  64. {
  65. string aspNetCoreEnvironment = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT");
  66. if (string.Equals(aspNetCoreEnvironment, "Development", StringComparison.OrdinalIgnoreCase))
  67. {
  68. const string aspNetHttpsOid = "1.3.6.1.4.1.311.84.1.1";
  69. const string CNName = "CN=localhost";
  70. using (X509Store store = new X509Store(StoreName.My, StoreLocation.LocalMachine))
  71. {
  72. store.Open(OpenFlags.ReadOnly);
  73. var certCollection = store.Certificates;
  74. var currentCerts = certCollection.Find(X509FindType.FindByExtension, aspNetHttpsOid, true);
  75. currentCerts = currentCerts.Find(X509FindType.FindByIssuerDistinguishedName, CNName, true);
  76. return currentCerts.Count == 0 ? null : currentCerts[0];
  77. }
  78. }
  79. else
  80. {
  81. throw new NotImplementedException("GetCertificateFromStore should be updated to retrieve the certificate for non Development environment");
  82. }
  83. }
  84. }
  85. }