How to install TLS certificates on pods where Java is deployed - java

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.

Related

Configure additional truststore in Spring Boot Tomcat Server

I have a spring boot client application and a server application. I am implementing MTLS client authentication part. I have a client certificate that is self signed and this needs to be added to a custom truststore in the server. Basically I am looking for a mechanism to add my custom truststore at runtime.
I want the default truststore and the custom truststore to be picked up. I implemented this using TomcatServletWebServerFactory but I did not have any luck. Can someone please help. I am looking for a programmatic solution.
I do not want to change the default java truststore. I still need that.
Since you do not want to replace the existing truststore with your custom one (that could be done by running the JVM with a few system properties) you need to add code that trusts a peer if the builtin or a custom trusttore approve the client.
For this you need to create and install your own Trustmanager. See an example here: https://community.oracle.com/tech/developers/discussion/1535342/java-ssl-trustmanager
If the checkClientTrusted and checkServerTrusted methods do not raise an exception the certificate is approved. Leaving the methods empty would even turn off any certificate validation - not to be recommended.
In order to establish a SSL connection with client certificates between a Spring client application and a Spring server application, there are a few things to note:
Involved Trust Stores
There are two very different trust stores relevant in this context:
The trust store used by the client to determine whether it can trust the server's SSL certificate. When using the java.net package for client requests, the trust store is configured via the JVM property "javax.net.ssl.trustStore" - see e.g. https://docs.oracle.com/javadb/10.8.3.0/adminguide/cadminsslclient.html
The trust store used by Tomcat (the underlying servlet container used by Spring Boot in its default configuration) to determine whether it shall trust a client. This is configured via the spring application property "server.ssl.trust-store" - see https://docs.spring.io/spring-boot/docs/current/reference/html/application-properties.html#application-properties.server.server.ssl.trust-store
In the context of a Spring server application the first one is relevant for connections which the server makes to a second server - so only when the server acts as client as well - e.g. when acting as a proxy server.
The second trust store is relevant for connections between the server and its clients. This is the one you need to deal with.
Certificates in the Tomcat Trust Store
The trust store which is used by Tomcat does NOT contain the client certificates. Instead, it must contain the certificate of the Certificate Authority who has signed the client certificate. So when using self-signed certificates, you need to install the CA certificate which you have generated on your own.
The big advantage of this is, that you do not need to change the server trust store, when you grant access to new clients.
The downside is, that you have to handle a certificate revocation. The CRL (certificate revocation list) is also stored in the trust store. See:
CRL Explained: What Is a Certificate Revocation List?
Merging the Default Trust Store and the Custom Trust Store
As now should be clear, this is not a good idea and would constitute a major security flaw, as it would allow any client which has a certificate signed by a CA in the default trust store (which can be easily obtained) to connect to the server. The server trust store must only contain those certificates which you use to sign your client certificates!
And there is no need to merge the two, as this are totally separate trust stores with totally different functions.
But, of course it is technically feasible to merge trust stores. This can all be done by keytool - see below.
Managing Trust Stores
Adding, deleting, exporting, listing, and printing certificates and CRLs can all be done via the Oracle command line tool "keytool", which is part of the OpenJDK. See
keytool Reference

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 should I implement SSL?

I have a java client which communicates with python server. Both run within out company intranet. None are exposed to Internet. How I am supposed to ensure that communication happens over SSL?
I have read a lot online and I have come up with following conclusions:
I will generate primary key and certificate to be used by clients and server using java keytool. (creating keystore, private key, certificate and truststore,extracting private key from keystore)
Using private key and certificate inside my python server using SSLSocket class as explained here
Using certificate in truststore inside java client as explained here
I have some doubts:
Are above steps ok?
Above seems to be one way SSL. Should I be doing two way SSL?
Should I be creating shared secret key and communicating using it?
I know this is something related to requirements. But I am in doubt as I am doing SSL first time.
SSL certificates requires validation via (HTTP/HTTPS), I suggest you enable HTTP/HTTPS for the location IP on the router/firewall to allow the validation to go through the internet.
If that is not possible, then you might have to do some local-server SSL validation. By generating a "SELF SIGNED" certificate and registering it manually in both locations.

Using SSL with microservices

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.

When to use keystores and when not to?

I have a server side application, that is required to make secured communication with other applications deployed else where. I do have all the information that I need per client(user of my server app) to initiate SSL connection. So, I have client CERT - containing public key, and client private key to be used for SSL and also CA cert that is being used by external application for SSL authentication.
I initiate the SSL connection programatically from within my server application.
So, for every client I create an SSLContext, using an in-memory keystore with all the above imported to it. The various certs and keys are imported programatically using data from my DB. (Note: All of the SSL artefacts are stored in an encrypted manner in DB).
Now my question is that Should I use a physical keystore(A java keystore stored in filesystem) or can I keep all security info in my Database as encrypted blobs.
What is the industry recommended way for the above usecase and why. Any guidelines for the above will be greatly appreciated ...

Categories

Resources