I am building an internal PKI for our microservices. The way it works right now is
There's an Offline Root CA and online Issuing CA
on start up a microservice
generates a keypair , a csr and keystore
loads the CA certificate into it's truststore
sends a request to Issuing CA to sign the certificate
gets new certificate and stores it
What we envision is to create a short lived (say 24 hours or less in validity) certificate for each microservice and when it is about to or when it expires the microservice should generate a new CSR and get it signed and continue working as usual. Is this possible and what are the challenges to be faced if were to go in this direction ?
Leaving aside why you need such a low refresh time for an internal network, your architecture is viable
To consider:
The issuing CA must be online and should process the CSR and return a valid certificate during the startup of the microservice and have a reasonably short response time
The public certificate of the Offline Root CA should be included previously in the trustsore of each microservice. I would recommend to include it programmaticaly to avoid security risks
Check if your SSL server is hot-swappable and the certificate can be updated during start-up or they must be done before the microservice starts (not all servers support it)
Note that you will not be able to use SSL-pinning
SSL pinning is implemented adding the server certificate to the truststore instead of the issuing CA to avoid that other certificate of the same CA is accepted
The certificate is usually installed manually an offline in the client truststore but in your case you have to distribute each certificate to the clients that are going to use the microservice. The solution is unpractical due to you have to.securize the channel, distribute them to each client, install them and ensure all steps are synchronized.
Do not forget also that the old certificates must be deleted from truststore because if they are present, they still would be accepted by clients
Related
I want to setup mutual authentication on Tomcat 8.
I have done the setup of keys primarily keystore and truststore and the setup is working with Firefox tested.
When accessing the URL I am prompted for certificate and when appropriate certificate is provided I am allowed the access.
The piece of puzzle I am missing is, the truststore that I have which has CA cert and public keys of few clients. This CA should be a self signed CA, not from known authorities on the web, as.
I just do not want anybody to have access, people using my CA only should be able to access. Assuming say abc.com has certificate signed by authority godady or verisign, which are well known and trusted should not be able to call. I want strict access.
In my truststore I just want to keep CA no public keys, I do not want to keep adding certs as clients grow up. Clients would use my CA.
I think my self signed CA in truststore and clients using my CA only in chain for their certificates should be good enough for secure(only clients with my CA) scalable solution, where I do not have to keep adding clients in truststore.
Please advice my assumptions are correct for a production cloud based system.
Thanks for the time.
Yes, your assumption are correct. During SSL handshake server will ask client to provide any certificate issued by CA present in server trust-store. Also you need to consider that client trust-store should have issuing CA of server certificate otherwise it will show untrusted server certificate on client/browser.
I've got an app written using the Spark Java framework, with TLS enabled.
See:
Service https = ignite()
.port(8443)
.secure(keystorePath, keystorePass, truststorePath, truststorePass);
This is being served on port 443 via an iptables rule that redirects incoming 443 to 8443.
The problem I am having is that when using the Qualys ssl labs test (https://www.ssllabs.com/ssltest/) the server is not providing the intermediate certificates that have been configured in my truststore.
Similar results occur when I use openssl s_client:
Verify return code: 21 (unable to verify the first certificate)
Along with
depth=0 /OU=Domain Control Validated/OU=PositiveSSL/CN=my.app.com
verify error:num=20:unable to get local issuer certificate
verify return:1
depth=0 /OU=Domain Control Validated/OU=PositiveSSL/CN=my.app.com
verify error:num=27:certificate not trusted
verify return:1
depth=0 /OU=Domain Control Validated/OU=PositiveSSL/CN=my.app.com
verify error:num=21:unable to verify the first certificate
verify return:1
From what I can tell, it appears that the server (spark java app, or embedded Jetty I suppose) is not serving up the intermediate certificates for chain validation.
Browsers see the site as secure, but I believe that's because the browsers are downloading the necessary intermediate certificates on their own.
The reason that this is a problem is that I am trying to use Stripe payment webhooks, and they have strict regulations in terms of the TLS cert chain being valid.
I am not sure where to begin on figuring out why these intermediate certs are not being served by my app. Could anyone offer some advice?
I have more or less the same exact problem. I followed the instructions at the Java Spark website (sparse that they are) and only get a Server Error for my efforts.
I imported a third-party certificate in my keystore file. I generated the CSR externally to the java keytool.
I moved the keystone file on the server where the "mydomain.com" exists.
I have the same basic code to do a test "secureHello" (per their documentation), passing the path to the keystore.jks file as the first parameter, and the password as the second.
RESULT: SERVER ERROR.
Not sure what I can try next. Clearly, I'm missing something.
4 hours banging my head on the desk so far (today)...
SSL certs never ends to dazzle me. I have an web-app and it makes a rest call to another service from a partner to fetch certain data. They use a self sign'ed or an internal CA generated for the Company. The issue is whenever the other end updates there SSL cert, my app fails. This is because the public cert (.cer) that i downloaded from their website and imported in the java trustore of my app doesn't match with their new site. To fix this, i have to re-download their latest public server cert and import again to my java trust store.
Assuming that they use a consistent ROOT CA or an intermediate CA cert to sign their ever changing SSL certs, can i just import the ROOT CA or the INTERMEDIATE CA once and for in my java trust store all to deal with this? So, as long as they don't change the ROOT CA or the INTERMEDIATE CA, my app will be able to make the call.
So their self signed CERT is not built from ROOT CA. Their CERT they generated themselves, so that is why it is considered untrustworthy by default. So every time they generate a new one, this is what happens:
Your app says hello to their server
Their server sends the newly generated CERT which includes information like: Public key, algorithm, cert valid date range, etc.
Your app gets the new CERT and compares it with the old CERT and realizes, oh, these are not the same.
Your app says, well, this is not trustworthy and throws an error.
This is by design because this would be similar to the same result of a man-in-the-middle attack. Your client only trusts certain CAs for that reason. The job of a CA is to certify against certs to see if they are good or bad. If you can add certs on the fly like that without the CA's knowledge, then the CA really has no idea which certs to trust.
So there could be an intermediate Certificate Authority that this company has opened up to you or that they have worked with to provide to you. You would have to ask them to see if they are using some kind of CA at all that you could connect to.
I doubt this the case because you said they are using "self-signed" certs which implies that they are not working with any CA.
I'm having an issue sending our certificate (client) to another server during a web service call.
We're expected to return the certificate with the CN:
b2b-test
however whenever we receive the servers certificate and attempt to send our own, we're getting:
Unable to find valid certificate path to requested target
From my understanding, if I put our certificate b2b-test inside of our keystore jre/lib/security/cacerts, then when receiving the server request, it should send the appropriate certificate.
How does the client know which key from the keystore it should send to the server? Should I be specifying the exact certificate to send during my request, or is it enough for it to be in the keystore?
Currently the server is sending back the certificate
b2b-a
The certificate chain shows:
*** Certificate chain
chain [0] = [
[
Version: V3
Subject: CN=b2b-a, OU=Web Technologies
The URL for the service is:
https://b2b-a/service
If I configure it like one way ssl, and put the servers certificate into our cacerts, then it picks up their cert and fails the handshake (I'm assuming because it's expecting our cert and not theirs back due to it being a two way setup).
I'm a little stumped here. Any clarification on what I've said is greatly appreciated.
The "Unable to find valid certificate path to requested target" error usually occurs when one side passes a certificate for which the other side doesn't trust any of the certs in the chain. You'll generally (always?) see the error message on the side that's receiving the cert (the side that's missing the truststore).
If you're the client and they're the server, one-way SSL would send their cert from them to you and you would validate it (making sure that the hostname matches the content in the cert), but it would not send any cert from you to them nor would they do any validation.
You'll want to make sure you're configuring a truststore that contains either the b2b-a certificate or a certificate that was used to sign it (but that cert doesn't appear to have any root CAs, so you're stuck with directly importing the cert itself). So yes, you want to do what you wrote in your post and put their certificate into your cacerts. And you'll also need to make sure that the b2b-a service trusts the cert you're sending (or a root CA that was used to sign your cert, if any), so you'll need to put your cert into their cacerts as well, or do something equivalent.
Note that putting a cert in cacerts (or in a truststore JKS) DOES NOT send any certs to anyone; any truststore is used only to allow you to validate that you trust the certificate someone else provides you, either because you trust the cert or because you trust a CA cert that was used to sign the cert. No certs are picked out of the cacerts directory to send to another machine.
If you're using a JKS rather than the JRE directory (which is generally a better idea, since you can specify a different set of trusted certs for your process without changing the default set for anyone running a Java project within your JRE), it's possible to use the same JKS as both a keystore and a truststore (you'll just provide the same filename and password for both the keystore and the truststore properties), or you can have two separate files; either approach will work.
From my understanding, if I put our certificate b2b-test inside of our keystore jre/lib/security/cacerts, then when receiving the server request, it should send the appropriate certificate.
Certainly not. That's a truststore. A source of trusted certificates. Don't mess with it. It isn't used for the purpose you require and in any case it is updated every Java dot release, which clobbers your changes.
Your own certificate and private/public key pair should go in a file of your own, a keystore, which is defined to JSSE by the javax.net.ssl.keyStore and javax.net.ssl.keyStorePassword system properties, or by more complex means described in the JSSE Reference Guide.
The keystore is a precious and confidential file containing your private key. Guard and protect it. Private key leakage would compromise your security and identity.
When I create an SSLServerSocket in Java 7 the server correctly uses my server certificate and key. The certificate was issued by a sub-ca of a ca. Therefore the complete chain from the root cert to the server cert has four certificates.
The complete chain is present in the keystore/truststore.
However when a client connects the server always sends only the server certificate itself.
This also applies to Java based web servers like Jetty.
Because most clients have only the root ca certificate installed and not the two sub-ca certificates this is a big problem.
How can I force Java to send the full certificate chain in the SSL/TLS handshake?
A key entry in a keystore isn't just for a single certificate, but for a certificate chain (see KeyStore.setKeyEntry, which takes a Certificate[] chain parameter).
If you want a specific chain to be used, it needs to be set up as a chain in the entry where you have the certificate and its private key. Whether the intermediate certificates are also in the same keystore, in different entries doesn't really matter.
This is a very similar problem to getting a client to send the full client-certificate chain. The same keystore configuration steps should also work from a server point of view, as described in this question.