Using SSL with microservices - java

I am having doubts about how to secure my microservices application with SSL.
A quik situation sketch :
I have a amazon ec2 instance with a loadbalancer in front.
On the ec2 instance I am running 5 microservices with a registry and a gateway application ( in a VPC ).
The loadbalancer uses a certificate from the Amazon certificate manager.
I also have a self signed certificate generated with the keytool.
Now the question I am having is :
Should I only configure the self signed certificate for my gateway application and register the self signed certificate with the loadbalancer as a trusted certificate or should I configure the self signed certificate for every microservice also ?
Regards,

You want to have microservices exposed to end user, and secured with https.
If you want security, please don't use self signed certificates. Let's Encrypt is much better option.
You can use API Gateway for that, it goes with https. It may be single endpoint for your all services - then directories can lead to different services. On the other hand, if all that goes on single machine, I would use single JVM... But that is different story.
Other option is more unclear. According to comments - not only for me. If your microservices are exposed to internet - you can terminate https on your load balancers. What I don't get is that >>my gateway application<<. It looks like there is something in between end user, and microservices... If that is true then https should be terminates somewhere there.
As a side note - I have no idea why you have load balancer in front of EC2 instance. Usually LB is used in front of auto scaling group to spread load among it's instances. If you want to automate that - Elastic Beanstalk is good option.

Related

How to install TLS certificates on pods where Java is deployed

How can I install certificates on pods or servers where Java code is deployed?
There's two ways:
(Perhaps not what you're looking for) Use AWS Application Load Balancer and AWS Certificate Manager to terminal TLS. This is done by creating Service of type LoadBalancer with annotation service.beta.kubernetes.io/aws-load-balancer-ssl-cert: ... (and some others). Note that you can't access the ACM private key, so this doesn't work if you want to terminate TLS in Java.
Use cert-mananager to generate a certificate with Let's Encrypt or another supported service. Create an Issuer and then create a Certificate and a Secret to store its private key in the appropriate namespace. Then you can reference the Secret in your pods and load them in Java.
If you go the second route but would like to have a single certificate that is reused across namespaces, then you have to use something like syncator to replicate the Secrets across namespaces.

Distributed Java Application inside docker swarm

My goal is to run a distributed NIFI cluster inside docker containers on a docker swarm. The configurations I made to the official NIFI docker image work in a way that I am able to run the cluster.
For the cluster I use a single service and each replica is a separate NIFI instance. Since this works I want to continue with security now. I started by applying a publically signed wildcard certificate to the java application using a secret (handing over the trust- and keystore). For my opinion this could be a feasable approach for most distributed java applications. But with NIFI I now got the issue that NIFI itself does not support wildcard certificates.
I am currently thinking about an approach how to run the cluster in a way that each container has its own certificate. My current idea is to run self signed certificates inside the container using a self managed internal CA which the NIFI JVMs can trust. Since I am not 100% sure if this would be the right approach to this issue I am thankful for hints and ideas.
NIFI uses some ports to do the communication and requests are issued using the HTTP/S protocol. NIFI itself runs as java application on the nodes/containers.
Apache NiFi provides a TLS Toolkit which automates much of this process for you. It can run an ephemeral or long-lived internal certificate authority (CA) which generates internal keys and uses them to create a self-signed CA certificate and sign incoming certificate signing requests (CSR). Each node that comes online can reach out to the CA service and install a properly-configured certificate in its keystore and truststore, and automatically populate the nifi.properties file with the locations and passwords for those files with a single command-line invocation. This can be configured to run at deployment time via Dockerfile, Ruby/Python/shell script, etc.
A HMAC/SHA-256 signature is calculated over the SPKI using a shared secret token value to ensure rogue/malicious services don't get issued certificates. All the certificates will be signed by the same CA cert, and this is already populated in the truststore, so each node in the cluster will trust the others. The requested CN is also populated in the SAN entries, and additional SAN entries are supported, so this is RFC 6125 compliant.
As noted above, wildcard certificates are not supported and not recommended, for a litany of reasons (some enumerated here) but also because a more secure deployment of unique certificates is made easy using the provided toolkit. There are ongoing efforts (NIFI-5443, NIFI-5398) to modify some internal cluster communications to be resilient in the face of wildcard certificates, but these are not currently available.

How to create a public url for a Webapp

I have been given an assignment for User registration and login using Spring boot. Front end I have used thymeleaf.I have developed the application in my localhost.
Below are the deliverable
Deliverables
● Source code ---- Done with GitHub
● Public working url of the webapp --- How to do???
● Tests - unit and integration tests. you may also choose to use a ci ---- Done
I would like to know how to create a public working URL for a project developed on localhost.
This process is called deployment. You may use Heroku, just follow the instructions. At the end, you will get an URL like http://my-lovely-app.herokuapp.com/ which is public and working.
Just go to the command line and navigate to your program by typing “cd (the path to your web app)”. Then in the command line type “gcloud app deploy”. Then click on the link to your site.
to answer this question, one needs first to understand an overview of an http(s) request lifecycle:
user enters an URL in his browser: https://some.domain:8080/request/path?param1=value1&param2=value2
the browser splits the URL into protocol scheme ("https"), server DNS name ("some.domain"), port (8080), request path ("/request/path") and query-string ("param1=value1&param2=value2"). If a port is omitted, the default port for the given protocol is assumed (80 for HTTP, 443 for HTTPS, etc)
the browser performs a DNS lookup to translate server DNS name to an IP address.
the browser makes a TCP connection to server's IP address (in theory HTTP can also use UDP, but it is rarely used, so we will skip this case)
if HTTPS was used, the browser and the server perform TLS handshake during which, among others, they exchange and verify each other's SSL/TLS certificate chains (usually it's only server presenting its certs and the browser verifying them, but you can also install client certificate and a key in your browser)
the browser sends the HTTP request over TLS (in case of HTTPS) or over bare TCP (in case of HTTP) to the server.
the server running software appropriate to execute your app routes the request to it to obtain a response that it will send back to the browser.
Points 1, 2 and 6 do not require any setup from you side.
For point 3 to work, you need to have a proper DNS record on some public DNS server.
For point 4 to work, your server needs to have a public IP address assigned by an ISP.
For point 5 to work, your server needs to have installed a valid SSL/TLS certificate issued by some certificate authority (you can skip it if you need only HTTP)
For point 7 to work, your server needs to have appropriate software and your app installed similarly as your local dev machine.
There are a lot of services available that provide all 3 or some subset of them for you, some of them even for free up to some capacity.
Let's start with a server and an IP address:
the most hardcore and low-level approach is to buy a public IP from your ISP and host your app on your local machine. this is not recommended however because of availability issues: whenever there is any network or power outage or if you turn off your machine, your app will be down. other solutions provide much better level of service (they have redundant power sources, internet connections and staff making sure that everything works 24/7)
a bit higher level approach is to buy a virtual or dedicated server from some hosting company (search the web for "VPS", "dedicates server" or "VM hosting" to find one in your area. Well know global ones are for example Google Cloud Compute Engine, AWS EC2, M$ Azure, OVH). These companies will provide for you a server with a public IP, full administrative access (via SSH usually) and some guarantees on it's availability (usually ranging from 99% to 99.99% -> the more 9s the more expensive it is). After that you will need to install and configure all necessary software to run your app on such server. These companies often offer DNS entry in their subdomain and an HTTPS ceritficate in a package for a small to even zero fee. Many of them also offer packages containing a separate domain of your choice and sometimes a certificate.
the most high level solution is a cloud app service (like mentioned in the other answer Heroku, AWS Beanstalk, Google App Engine, kubernetes cluster etc). These services will provide a configurable size pool of instances hosting your app with some load balancing in front of them. This will make your app easy to scale and have a very high availability rate. This is the best solution in most cases: just make sure that the given service provider supports technology stack required by your app. Again, companies providing such services often have packages with DNS entries and HTTPS certificates.
If you need to buy a DNS domain separately (you didn't like any of the packages offered by the server provider) just search for "DNS names" or "domain names" and you will find a lot of resellers. These resellers will provide you a console where you can bind IP address of your server to the DNS name.
Finally if you need to obtain SSL/TLS certificate, you can also search for providers on the web or you can use free automatic certs from https://letsencrypt.org/
That's pretty much it.

Heroku: Spring Boot Gradle app with https tomcat server and certificate pinning

I have a Spring Boot java app that uses a self-signed certificate to communicate with the android front-end.
I use a tomcat server as my container for the app:
compile 'org.springframework.boot:spring-boot-starter-tomcat'
Now, I have enabled https / ssl:
TomcatEmbeddedServletContainerFactory tomcat = (TomcatEmbeddedServletContainerFactory) container;
tomcat.addConnectorCustomizers(connector -> {
connector.setPort(Integer.parseInt(serverPort));
connector.setSecure(true);
connector.setScheme("https");
I have to enable SSL as I want my android frontend to communicate to my server securely. I use the technique called certificate pinning which means I add the same self-signed certificate to both my server and my android app. For any http communications between the two, the communication will be encrypted with the keys of the same certificate and hence the server and android app will be able to understand one another.
When I load it into Heroku, I get errors each time I try to call the server:
2015-12-11T20:04:32.424629+00:00 heroku[router]: at=error code=H13 desc="Connection closed without response" method=GET path="/getfood?postid=566348364a918a12046ce96f" host=app.herokuapp.com request_id=bf975c13-69f3-45f5-9e04-ca6817b6c410 fwd="197.89.172.181" dyno=web.1 connect=0ms service=4ms status=503 bytes=0
According to this blog by Julie: http://juliekrueger.com/blog/
As a side note, Heroku apps are https enabled by default. The server I
was installing had Tomcat configured to use https, and trying to
access an endpoint was returning a code=H13 desc="Connection closed
without response" error. After I removed that configuration the error
went away.
I can fix the error by just removing the ssl / https from my tomcat server, but as I mentioned, I want to use the certificate pinning technique for secure communications.
I was thinking whether it was possible to disable the SSL on heroku side but keep my tomcat server SSL active but I already contacted Heroku and they told me that disabling the piggyback SSL that comes standard with their service is not possible.
I also looked at the paid alternative here called SSL Endpoint but it seems only userful for custom domains. Since all endpoints are coded within my android app and is not visible to the user, it makes no sense for me to use a custom domain. Furthermore, I don't think it will solve my problem as its sole objective seems to be to create the custom domain:
SSL Endpoint is only useful for custom domains. All default
appname.herokuapp.com domains are already SSL-enabled and can be
accessed by using https, for example, https://appname.herokuapp.com.
I googled for a few days now and cannot seem to come up with a solution. Disabling ssl on my tomcat side would not be acceptable in my mind as it poses too much risks. I would even consider other services (Azure etc) if this would solve my problem.
Any ideas on how I can solve this?
With Heroku, in order to use your own custom SSL, you need to use a custom domain and the SSL Endpoint addon, it will probably won't make sense for your case, but it is the only way to use your own certificate.
And I haven't tried all the providers out there, but with the ones I tried, the scenario is exactly the same, it is possible to use custom SSL cert only if you are using a custom domain.
Although, browsing google a bit, found this blog post where it ilustrates how to use an intermediate DNS service to comunicate with Heroku. In the communication between the DNS service and Heroku, the provided heroku SSL cert is used, but from the client to the DNS service a different certificate is used, so it might be of some help.
Update: A possible solution would be to use Amazon Web Services, where the deal is that you rent VM's and you are allowed to setup your own environment, meaning that you can install your own tomcat and use your own custom SSL.
Update 2: Also there is CloudFront with AWS, where you can use your own certificates explained here

How to secure communication in client-server app?

I've got backend running on the tomcat server and client running in the browser. Application is built on Spring 3 MVC + Spring security framework. How to secure the communication ? Is there other option than just to set the server to be accessed only via HTTPS ? I've got no experience with this so it might be a stupid question, but will this affect my application and do I have to set something up in my app, when the server shall communicate with client via GET/POST request via https ?
It depends somewhat what you mean by "secure." If you want privacy, you must use TLS (SSL) as a transport.
If you're only concerned with authentication, then you have another option: Digest Authentication.
Digest Authentication allows the client (browser, usually) and the server to exchange authentication credentials in a secure manner without securing the entire communication. If you use Digest Authentication, then third parties can still:
See what data the client and server exchange
Insert themselves between the client and server and alter the exchange
What third parties cannot do is spoof the authentication or steal username/passwords in transit.
If that's not secure enough, you need TLS. You do not necessarily have to purchase a certificate. You can use OpenSSL to generate your own. This certificate will not automatically be trusted by browsers, however, so you can't really use it for public sites.
You will need to consult your server documentation for how to set up HTTPS or Digest Authentication, depending on which fits your needs.
Your application should not be affected by switching from HTTP to HTTPS, Tomcat handles this or maybe an Apache in front. It's important to understand, that HTTPS is a server-thing, not an application topic, because the client makes a connection to the server (Tomcat), not to your application. Check out the Tomcat documentation, it's pretty clear about how things work.
And, like the others said: From what you've said it's best to use HTTPS (TLS/SSL). Certificates are a bit frightning at the beginning, but it's worth to invest the time.
HTTPS is the (S)ecure form of HTTP, since you have an HTTP client server application I would certainly used HTTPS. All you need is to create an SSL certicate for your website and restrict access to your website to HTTPS only, then you are 99.99% secure.
Your certicate can be either commercial from Versign or equivalent or some open source engine.
for the clients nothing needs to be done to support HTTPS

Categories

Resources