Yaroslav
Yaroslav

Reputation: 534

ServiceFabric Local Cluster SSL

I have some misunderstanding with running SF on local cluster with SSL, on localhost. Microsoft created greate article about configuring HTTPS on your endpoints But it works well only if you use their certificate generator CertSetup.ps1 . If you try install your own pfx, it will not work.

First I created localhost self-signed cert by OpenSSL:

set OPENSSL_CONF=W:\OpenSSL-Win32\bin\openssl.cfg
openssl genrsa -out W:\CERTS\wepapissl.key -passout pass:1234567890 -aes256 2048
openssl req -x509 -new -key W:\CERTS\wepapissl.key -days 10000 -out W:\CERTS\wepapissl.crt -passin pass:1234567890 -subj /CN="localhost"
openssl pkcs12 -export -inkey W:\CERTS\wepapissl.key -in W:\CERTS\wepapissl.crt -out W:\CERTS\wepapissl.pfx -passout pass:0987654321 -passin pass:1234567890`

Second I have created default ASP.NET Core Web Application (Core 2.0, API template). And added code for configure Kestrel to use HTTPS:

public static IWebHost BuildWebHost(string[] args) =>
        WebHost.CreateDefaultBuilder(args)
            .UseKestrel(opt =>
            {
                opt.Listen(IPAddress.Any, port, listenOptions =>
                {
                    listenOptions.UseHttps(GetCertificateFromStore());
                });
            })
            .UseStartup<Startup>()
            .Build();

private static X509Certificate2 GetCertificateFromStore()
    {
        var store = new X509Store(StoreName.My, StoreLocation.LocalMachine);
        try
        {
            store.Open(OpenFlags.ReadOnly);
            var certCollection = store.Certificates;
            var currentCerts = certCollection.Find(X509FindType.FindBySubjectDistinguishedName, "CN=localhost", false);
            return currentCerts.Count == 0 ? null : currentCerts[0];
        }
        finally
        {
            store.Close();
        }
    }

I have got expected result. Page with warning about website’s security certificate: Result from ValueController with warning

Third I have created Service Fabric Application (Stateless ASP.NET Core template). Change my ServiceManifest.xml by editing Endpoint section:

<Endpoint Protocol="https" Name="ServiceEndpoint" Type="Input" Port="8256" />

And added code for configure Kestrel to use HTTPS (class Web1 : StatelessService):

    protected override IEnumerable<ServiceInstanceListener> CreateServiceInstanceListeners()
    {
        return new ServiceInstanceListener[]
        {
            new ServiceInstanceListener(serviceContext =>
                new KestrelCommunicationListener(serviceContext, "ServiceEndpoint", (url, listener) =>
                {
                    ServiceEventSource.Current.ServiceMessage(serviceContext, $"Starting Kestrel on {url}");

                    return new WebHostBuilder()
                                .UseKestrel(opt =>
                                {
                                    int port = serviceContext.CodePackageActivationContext.GetEndpoint("ServiceEndpoint").Port;
                                    opt.Listen(IPAddress.IPv6Any, port, listenOptions => 
                                    {
                                        listenOptions.UseHttps(this.GetCertificateFromStore());
                                    });
                                })
                                .ConfigureServices(
                                    services => services
                                        .AddSingleton<StatelessServiceContext>(serviceContext))
                                .UseContentRoot(Directory.GetCurrentDirectory())
                                .UseStartup<Startup>()
                                .UseServiceFabricIntegration(listener, ServiceFabricIntegrationOptions.None)
                                .UseUrls(url)
                                .Build();
                }))
        };
    }

    private X509Certificate2 GetCertificateFromStore()
    {
        var store = new X509Store(StoreName.My, StoreLocation.LocalMachine);
        try
        {
            store.Open(OpenFlags.ReadOnly);
            var certCollection = store.Certificates;
            var currentCerts = certCollection.Find(X509FindType.FindBySubjectDistinguishedName, "CN=localhost", false);
            return currentCerts.Count == 0 ? null : currentCerts[0];
        }
        finally
        {
            store.Close();
        }
    }

Result: Successful build and deploy code on local SF cluster. But my resource can't be reached

P.S. I will repeat again, if you install new cert by using PowerShell provided by Mircosoft - CertSetup.ps1, it works well for SF application. I was trying to dig in PS script, but I can not understand what I missed.

P.P.S I am new in creating certificates, but it seems strange.

  1. I have installed pfx by CertSetup.ps1. All works well (resource is reachable).
  2. Then I have exported cert to pfx with private key and all extended properties
  3. Delete from LocalMachine (MY and Root), CurrentUser (MY) stores
  4. Install exported pfx to LocalMachine (My and Root), CurrentUser (My) stores
  5. Rebuild & Redeploy code
  6. Resoucre can not be reached

Is it magic? Or I miss something?

Upvotes: 3

Views: 1371

Answers (1)

Yaroslav
Yaroslav

Reputation: 534

Couple details was not enough clear for me, any way. Answer: If you tried to use your own generated certificate (openssl, makecert or etc), you shoud set privileges for NETWORK SERVICE.

To manually do this on your dev box, open up certlm.msc, expand Personal->Certificates, and right-click your cert. Select All Tasks->Manage private keys and then add NETWORK SERVICE.

More here: https://github.com/Azure/service-fabric-issues/issues/714#issuecomment-381281701

Upvotes: 1

Related Questions