I am using custom certificates (via security.pki.certificates in configuration.nix) but they don’t seem to be propagated to JDK. For instance I don’t see the certificates in /nix/store/yirggs7jnyxbhdmk342f6an4ifkgmbgv-openjdk-17.0.1+12/lib/openjdk/lib/security/cacerts and I am getting SSL errors from Java applications such as davmail. Is there a way to install the custom certificates in JDK?
The way security.pki works is by creating certificate bundles that are linked somewhere in /etc/, then it’s up to the program to use them.
The problem is I’m not sure you can configure openjdk to use an alternative path. For openjdk 8, the path is inside the package itself and is no good: it can’t be updated without rebuild the package (and everything depending on it).
If you know how to do this, I’ll be happy to try implement a solution in NixOS.
After some googling I found that JDKs > 8 have this global system property javax.net.ssl.trustStore to specify the location of an alternative trust store. Can it be used somehow to point to the location where security.pki.certificates &co collect the certificates? Where would global java properties go to in NixOS?
It seems openjdk is already patched to read the default path from JAVAX_NET_SSL_TRUSTSTORE. The format of this newer keystore is PKCS12: I’m not sure we have tools to convert the bundle to this, I’ll look into this.
Nice, I found the existing keystore cacerts from the output of my jdk (e.g. by running sbt 'eval System.getProperty("java.home")', copied it to the new location, added additional certificates, then set JAVAX_NET_SSL_TRUSTSTORE to point to this new cacerts keystore and all worked well.
There’s simply not enough people that care about this. I had to do most of the work myself to get security.pki working for the majority of web browsers.
Anyway, I wasn’t aware of JAVAX_NET_SSL_TRUSTSTORE. An environment isn’t ideal in this case because you usually want that as a last resort to override a default.
Nonetheless, It means openjdk can be patched to look for our trust store by default.
It shouldn’t be too hard to do, but I don’t have much time to look into this now.
Start looking for references to JAVAX_NET_SSL_TRUSTSTORE in the sources.
I suppose the implementation of this variable would be a good place to inject a /etc/ssl/certs/java-cacerts for NixOS.
Change the cacert package to also generate such a file, using the trust extract command.
Link the cacert output to /etc, in the security.pki module (nixos/modules/security/ca.nix).
If you get it working, open a PR and ping me. I’ll be glad to review it.
this is my current cacerts.nix for reference, maybe this works for you as well.
I was thinking it didn’t work and only realized today that i need to use the openjdk, as other jdk’s don’t contain the patch to read the truststore path from the env var.
I am entering a new project for work and I need to install some custom certificates in the JDK (11), which of course spells trouble in NixOS and led me here.
Now, I’m a beginner in NixOS and only have a rough idea what these certificates may be required for. This thread seems to contain all the necessary information to do what I need, but, as it is so often for newcomers, it lacks context that explains what to do with those snippets.
It would be tremendously helpful if somebody who truly understands what’s going on could take the time to compile this into a full tutorial that explains how do this start to end, start being “I got theses three certificates I need to install in a JDK (11) and a system that doesn’t yet have a JDK (except one bundled with Android Studio, which I think I can’t/won’t use)” and end being “sudo nixos-rebuild switch”. Ideally, some comments in the nix files would explain what’s happening and why.
In particular, I see all this nix code, but I have no idea where to place my certificates so they’ll be picked up by it. I’m sure I can figure it out. It would just be so helpful if this information was packaged in a way that wouldn’t have me guessing at first. I know, it’s extra work, but it would make entry into this world so much easier. If somebody actually takes this time, I suppose it would also be great to place this info on the Java page, which currently doesn’t have any useful info for JDK 11.
I’ve had ChatGPT compile a full tutorial from some of the provided posts and have it explain it. I did not get the chance to test it, yet. Maybe somebody could use this as a blueprint for a more detailed answer, but check that it’s actually correct and if perhaps there are better solutions that those suggested by the AI? My Chat with ChatGPT
Since your use case seems to be installing custom certificates that are project-specific rather than system-wide, setting JAVAX_NET_SSL_TRUSTSTORE or passing -Djavax.net.ssl.trustStore=... to the JVM command-line might actually be a suitable solution in your case? Or is that somehow not possible?
(as an aside, though I know it doesn’t help you much in the short term: my impression is that setting custom key/truststores at the JVM level is nowadays generally seen as dealing with this at the wrong granularity level: your application may want to use one set of key/truststores for one type of connection and another set for another type of connection. For that reason I think most client and server APIs/libraries now support passing in the key/truststores to be used for the connections managed by that API, in which case you could solve this at the application (configuration) level)