Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enable https (SSL Binding) on Service Fabric Mesh Application using gateway #25285

Closed
vikramdadwal opened this issue Feb 19, 2019 · 24 comments
Closed

Comments

@vikramdadwal
Copy link

vikramdadwal commented Feb 19, 2019

I have deployed a new mesh app with an Asp.Net API core container image. I am able to successfully deploy and access the API using http://[]:80. I used the Following configuration in gateway yaml file:

http:

  • name: BenApiHTTP
    port: 80
    hosts:
    • name: "*"
      routes:
      • name: benapi
        match:
        path:
        value: "/benapiservice/"
        rewrite: "/"
        type: Prefix
        destination:
        applicationName: BenApplication
        serviceName: BenApi
        endpointName: BenApiListener

Now I want to use my own ssl (Custom Domain) certificate and wants to enable the same api using https i.e. on port 443. I do not see any example on how to enable https with SSL binding. So my questions are:

  • How to upload the ssl certificate in mesh? OR if we need to do in Containers ?
  • Which port I have to expose in the Service Listener ?
  • What Yaml updates I have to make in gateway.yaml to enable https ?
  • How to set the Domain for the gateway url ?

Same has been asked in Stackoverflow: https://stackoverflow.com/questions/54545764/how-to-enable-tls-ssl-https-in-azure-service-fabric-mesh-for-asp-net-core-applic


Document Details

Do not edit this section. It is required for docs.microsoft.com ➟ GitHub issue linking.

@Karishma-Tiwari-MSFT
Copy link
Member

Thanks for the question. We are currently investigating and will update you shortly.

@mimckitt
Copy link
Contributor

@dkkapur @aljo-microsoft do we need to do anything specific for SF mesh to enable HTTPS? I don't find any docs on this. Do we support HTTPS at this time?

@dkkapur
Copy link
Contributor

dkkapur commented Feb 19, 2019

We don't have support through the gateway today, but there is still a path to do this. The general requirement here is that you need to get a cert into your container, which can be done by putting it in the container as part of the image or mounting it through a Secret in combination with Key vault. Tagging @aljo-microsoft to provide more details on this front. From what I know, I would recommend the latter path which would then require updates to your yaml in the form of adding a secret, rather than modifying the gateway + port aspects.

@aljo-microsoft
Copy link
Contributor

@dragav
To provide clarity.

@vikramdadwal
Copy link
Author

@dkkapur @MicahMcKittrick-MSFT : Thanks for the quick response. Based on the answer provided, I have the following questions:

  • When would the https support be available with gateways? As I guess that is the minimum/basic security level an API service, exposed to the internet, should provide?
  • It would be great if you can provide a sample Mesh App (Asp.Net core) which expose through https as per the procedure explained. The official samples do not have any https scenarios covered.

Please NOTE: This (https SSL binding) is the last hurdle we are facing on choosing the new Micro-service architecture we are trying to build from scratch. Kubernetes is the other Orchestration option we are exploring (But we are more interested in SFMesh, as its a fully managed serverless service). So it would be of great help if this is something can be achieved easily here.

Thanks.

@aljo-microsoft
Copy link
Contributor

@vikramdadwal
SFMesh isn't comparable to AKS; SFRP is. As both SFRP and AKS you can ssh/rdp into host machines you own. SFMesh is a server less platform that abstracts machines away.

Today as Deep stated, binding a certificate to a listener within a container, whether deployed into a private or public network, can be achieved by delivering the certificate to the container its self.

I.E. Container can reach out and download your PKI certificates, and bind them to listeners they create.

E.G. Containers are self contained, so you can whatever you want inside them.

An alternative to encrypting your certificate inside your images, and pass in the decryption password at deployment time (commonly via Environment Variable) to your container to decrypt a certificate and use it how you desire; is to use Secrets, and Secrets/Values SFMesh resources to pass in the certificate as a secret value.

@MicahMcKittrick-MSFT
Please wait for @dragav to provide additional clarity around using the Secrets, and Secrets/Values SFMesh resources to deliver a certificate for binding to a listeners.

@vikramdadwal
Copy link
Author

vikramdadwal commented Feb 20, 2019

@aljo-microsoft . Thanks for providing a descriptive explanation.
I will wait for @dragav response for container implementation.

Also with container certificate approach the thing I still do not understand is that how the gateway will talk to the 443 secure listener of the container i.e. Gateway is still open to internet with 80 port (as mentioned in YAML file). Also what would be the subject name of SSL certificate here?

OR

Are you mentioning that I need to remove the gateway altogether and directly call the container listener ? if yes then how ? Because of these confusions I need a full working example to understand the concept here.

I am new to containers so forgive me If I am asking very basic stuff.

@vikramdadwal
Copy link
Author

I was able to enable https binding within the container with certificate. I was able to host the same in SFMesh as shown below the app is running fine:

image

Now I need information regarding how to access it using public IP (using gateway or any other option). Please suggest.

Thanks.

@andrewdmoreno
Copy link
Contributor

@vikramdadwal While we wait for a response on your question do you mind sharing in more detail what you were able to configure? I'm also following this conversation to see the options available for accomplishing this.

@vikramdadwal
Copy link
Author

@andrewdmoreno I was able to accomplish the following:

  1. Create a Mesh project in VS2017
  2. Create a basic Asp.Net Core API
  3. Create secret in the mesh (I have to manually update the ARM json for the same. Check Secret ARM template not working #25070
  4. Bind Asp.NEt core to SSL certificate and listen on port 443 (Check this sample: https://cmatskas.com/enforcing-https-only-traffic-with-asp-net-core-and-kestrel/)

@andrewdmoreno
Copy link
Contributor

@vikramdadwal Interesting. On my end I tried slighty different approach and was able to get a certificate from key vault passed in to the service via arm / environment variable, which I then pass to the kestrel listen options similar to the article you reference above.

Everything works locally. I can run it using the same image and hit the service as expected. When I deploy to mesh, however, it doesn't run and there are no logs or any other messages that I have been able to find. Container continuously starts/stops. Still trying to figure out the best way to troubleshoot.

@aljo-microsoft
Copy link
Contributor

@vikramdadwal and @andrewdmoreno
Network topology works the same for all Azure resources.

SF Mesh Gateway resource is a very simple ingress load balancer for Containers managed by the mesh service.

Given both of you have successfully bound your containers listeners to your certificate, and have completed the SSL encryption of HTTP communication and Server Identification part of the SSL authentication flow; what is next is minimum the network topology deployment.

I.E. Your Server within your containers certificate's Common Name or Subject Alternative Name should match the domain name you own, if you don't want browsers to throw errors when clients connect, and hosting your domain in Azure is documented here: https://docs.microsoft.com/azure/dns/dns-delegate-domain-azure-dns.

E.G.
After delegating your domains name servers to your Azure DNS zone name servers, add the following two records to your DNS Zone:
An 'A' record for domain APEX that is NOT an Alias record set to all IP Addresses your custom domain will resolve.
A 'C' record for Microsoft sub domains you provisioned that are NOT an Alias record set. For example, you could use your Traffic Manager or Load Balancer's DNS name.

Your SF Gateway resource doesn't have a parity for all Standard Load Balancer functionality; specifically health probes is a feature not duplicated.

I.E. An example of a network deployment is a client has trusted CA issuer cert or private PKI issuer cert or intermediate issuer cert installed and requests your custom domain https://<My Custom Domain .Net>; which you delegated to Azure DNS Zone naming servers. You created DNS records for you domain to route to your Traffic Manager, which routes to requests to your Public IP Configured Standard Load Balancer, that is configured with routing rules and health probes to your SF Mesh Container's gateway resource; the gateway resource has routing rules for your Container instances. The container instances have an encrypted CA Issued SSL Encryption and Server Identification certificate built into the image, and use Secrets and Secrets/Values resource to pass in the decryption password at deployment time. The certificate is decrypted and bound to its listener, enabling the SSL handshake to complete with the client.

Soon an SF App MSI will be available, enabling you to obtain a managed identity token, and authenticate to AAD supported resources like Keyvault (By declaring an Application property in your template); which would allow an alternative to building your containers images with an encrypted certificate, as you could use a system assigned identity that you authorize to your KV resources, to authenticate and download your full certificate directly from keyvault. Could also currently manually register a Service Principle with AAD, pass that secret value to your container, and use it to get tokens for authenticating to services.

Something to be mindful of is your clients need to trust server certificate (so self signed shouldn't be used for production, and you should be using a Trusted Certificate Authority issued certificate).

@MicahMcKittrick-MSFT
#please-close as I've answered all the user's questions.

@vikramdadwal
Copy link
Author

@aljo-microsoft : Thanks for the explanation but that is a lot of azure networking jargon ;) I was looking for a simple solution which is easy to understand by an Application developer. A sample would be great.

My guess is, this will eventually be available in GA and yes I agree MSI will ease lots of azure access related use cases here. Thanks.

@andrewdmoreno
Copy link
Contributor

@aljo-microsoft - As @vikramdadwal mentioned above, I also don't think that the response to this issue is quite sufficient for closing.

On my machine only I can access my endpoint (which is directly hitting the container) using https albeit with a browser warning, which is expected given the cert I am using was provisioned by key vault.

When I deploy the same image and configuration to mesh is there an additional step that needs to happen for the handshake to occur using the public ip address due to the gateway being in the middle?

Our wireshark trace seem to indicate that the handshake is not happening, nor do any logs get produced from asp net core that would indicate it's reaching that far. We've enabled Trace logging to try and troubleshoot further to no avail. As an aside, if we remove the 's' and connect via http but specifying port 443, we do at least get asp net core logs indicating that it failed which is expected given that our kestrel listener is only allowing https traffic.

2019-02-25T19:38:35.031201913+00:00 stdout F dbug: HttpsConnectionAdapter[1]
2019-02-25T19:38:35.031201913+00:00 stdout F       Failed to authenticate HTTPS connection.
2019-02-25T19:38:35.031201913+00:00 stdout F System.IO.IOException: The handshake failed due to an unexpected packet format.

I assume @vikramdadwal is stuck in the same place as I am and some guidance would be greatly appreciated.

@andrewdmoreno
Copy link
Contributor

andrewdmoreno commented Feb 26, 2019

For @vikramdadwal and any others that come across this issue, the problem at the present time is that https cannot be used with the http routing config. After chatting with @dkkapur and team I have been able to confirm that switching to tcp variation of routing config with port 443 instead of using http config solved this issue for me and I am able to call my service on the public ip address using https on port 443.

{
    "tcp": [
        {
            "destination": {
                "applicationName": "ApplicationName",
                "endpointName": "EndpointName",
                "serviceName": "ServiceName"
            },
            "name": "TcpRule1",
            "port": 443
        }
    ]
}

@vikramdadwal
Copy link
Author

@andrewdmoreno I tried replacing the http with tcp as mentioned, but still not able to hit the service with https. Following are the snapshots (service codepackage, gateway and postman) from my arm json. My container image exposed port 443 and is running fine in mesh.

image

Its simply say no response. Is something I am missing here ?

@andrewdmoreno
Copy link
Contributor

@vikramdadwal - you confirmed these also I would imagine?

  • Kestrel listener config was configured to port 443
  • Docker file was updated to expose 443

@vikramdadwal
Copy link
Author

@andrewdmoreno: yes they are.

@vikramdadwal
Copy link
Author

@andrewdmoreno : It worked for me too. Did a silly mistake during destination settings. Thanks.

@dkkapur : In case of tcp how to specify multiple destinations (i.e. if we are hosting more than 1 service)? In http we had this routes concept, but not sure how to achieve the same in tcp ?

@dkkapur
Copy link
Contributor

dkkapur commented Mar 4, 2019

@vikramdadwal see https://docs.microsoft.com/en-us/azure/service-fabric-mesh/service-fabric-mesh-howto-configure-gateways#tcp-routing-rules for more info on this. Quick note - tcp routing rules are 1:1 for port:endpoint.

@jancorluy
Copy link

@andrewdmoreno I tried replacing the http with tcp as mentioned, but still not able to hit the service with https. Following are the snapshots (service codepackage, gateway and postman) from my arm json. My container image exposed port 443 and is running fine in mesh.

image

Its simply say no response. Is something I am missing here ?

@andrewdmoreno I tried replacing the http with tcp as mentioned, but still not able to hit the service with https. Following are the snapshots (service codepackage, gateway and postman) from my arm json. My container image exposed port 443 and is running fine in mesh.

image

Its simply say no response. Is something I am missing here ?

Hi @vikramdadwal I couldn't help noticing to see that you use secrets there in your service fabric mesh application, I would like to use them too in combination with azure key vault. Can you link me to any documentation or provide me with a sample on how to use it?

@andrewdmoreno
Copy link
Contributor

@jancorluy - Yeah I think something must have changed since I reported that I got it working. After subsequent deployments of my application it has stopped functioning for me. I have opened Azure/service-fabric-mesh-preview#353 with a sample git repo just trying to get the out of box asp net core api sample to run using https. Has been quite frustrating.

Not sure if @vikramdadwal is still having success with his solution.

@brechtvhb
Copy link

Any update on this?

@oatsoda
Copy link

oatsoda commented Aug 28, 2019

Is there any documentation or details of how to configure this for older OWIN Self-hosted style applications?

Normally you would use netsh commands to bind certificates. With Docker I would normally put this in the container startup (rather than build-time so that I can vary which certificate per environment) but with the Service Fabric Mesh Local Cluster this doesn't seem to be executed...

@PRMerger9 PRMerger9 added the Pri2 label Aug 28, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests