Page MenuHomeFreeBSD

java/openjdk*: Allow users to specify an alternative cacerts file
ClosedPublic

Authored by michaelo on Nov 22 2023, 1:07 PM.
Tags
None
Referenced Files
F84113550: D42720.diff
Sun, May 19, 2:29 PM
Unknown Object (File)
Fri, May 17, 2:35 AM
Unknown Object (File)
Fri, May 10, 2:17 PM
Unknown Object (File)
Wed, May 8, 9:20 AM
Unknown Object (File)
Wed, May 8, 9:19 AM
Unknown Object (File)
Wed, May 8, 9:19 AM
Unknown Object (File)
Wed, May 8, 6:49 AM
Unknown Object (File)
Wed, May 8, 6:49 AM
Subscribers

Details

Summary

Similar to certificate management with certctl(8) users can use custom
enterprise CAs. These need to be assembled into a custom cacerts file.
Therefore, an admin can install a custom truststore to an arbitrary
location and have the OpenJDK port symlink to it by adding
OPENJDK_SYMLINK_CACERTS to make.conf.
E.g., OPENJDK_SYMLINK_CACERTS=/usr/local/etc/ssl/cacerts.

PR: 229329
Approved by: jrm (mentor), otis (mentor), glewis, des, kevans

Diff Detail

Repository
R11 FreeBSD ports repository
Lint
Lint Not Applicable
Unit
Tests Not Applicable

Event Timeline

michaelo created this revision.

This solution is far from ideal because it is disconnected from the management with certctl(8), but other options are even harder to implement:

  • Java expects a Sun-specific bag attribute to be set (2.16.840.1.113894.746875.1.1). There seems to be support in OpenSSL 3.2+, but this is years away for base: https://github.com/openssl/openssl/issues/22215#issuecomment-1791118457. There are lot of issues raised with OpenSSL regarding this. (Note: I haven't tried OpenSSL 3.2 so far for this)
  • Use an alternative KeyStore implementation by default which will read hashed directory from/for OpenSSL: https://github.com/marschall/directory-keystore, maybe others, write a slim one. I am rather reluctant to change that because this changes standard behavior and there is plenty of crappy code out there that assumes that the default trust store type is "JKS". This can only be an additional one. (Note: I haven't tried it yet)

I am totally open to better solutions.

If this gets approved I will apply this to all other LTS releases for consistency reasons.

If none of our "Java people" like @glewis, or no one who has worked on certificate management like @des or @kevans has better ideas or objections by December 6, let's proceed. It's a non-default option, and it can help some enterprise users until a more robust solution comes along.

I don't object either. Nevertheless it seems to me that this should be performed in post-install-LOCALBASE_CACERTS-on within the STAGEDIR. What's your thought?

In D42720#974495, @otis wrote:

I don't object either. Nevertheless it seems to me that this should be performed in post-install-LOCALBASE_CACERTS-on within the STAGEDIR. What's your thought?

While I agree with you, I have chosen the approach from TZUPDATE for consistency reasons.

In D42720#974495, @otis wrote:

I don't object either. Nevertheless it seems to me that this should be performed in post-install-LOCALBASE_CACERTS-on within the STAGEDIR. What's your thought?

While I agree with you, I have chosen the approach from TZUPDATE for consistency reasons.

Maybe @glewis can make it clear why this approach was chosen.

In D42720#974511, @otis wrote:
In D42720#974495, @otis wrote:

I don't object either. Nevertheless it seems to me that this should be performed in post-install-LOCALBASE_CACERTS-on within the STAGEDIR. What's your thought?

While I agree with you, I have chosen the approach from TZUPDATE for consistency reasons.

Maybe @glewis can make it clear why this approach was chosen.

That's so long ago that I don't recall the rationale. It was originally a little different and has morphed through changes in how options were handled, and not always by me I think

java/openjdk8/Makefile
92

I think perhaps LOCALCERTS might be a shorter option name, unless other ports use are using LOCALBASE_CACERTS as a convention

302–304

This doesn't check at all whether ${LOCALBASE}/etc/ssl/cacerts exists or not. It doesn't on my machine, for example. TZUPDATE looks at first glance like it has the same problem, but it adds a dependency on java-zoneinfo, which ensures the zoneinfo data is available. If it didn't exist and I set this option, would I get an empty set of cacerts? That seems bad.

java/openjdk8/Makefile
302–304

This is unintentionally on purpose. The idea is that the admin can place it by some means (I have a custom port, others drop of manually). If you pick this option you know what you do.
What do you prefer to see? Test for existence and then fail? If yes, this means that this port cannot be build independently of the admin dropping the file. In poudriere this adds an unnecessary obstacle.

Custom port:

PORTNAME=       nss-siemens-cacerts-java
PORTVERSION=    20230814
CATEGORIES=     security
DISTFILES=
 
MAINTAINER=     michael.osipov@siemens.com
COMMENT=        Collection of CA certificates trusted by NSS and Siemens for Java
 
NO_ARCH=        yes
NO_BUILD=       yes
NO_TEST=        yes
 
WRKSRC=         ${FILESDIR}
SSLDIR=         ${PREFIX}/etc/ssl
 
PLIST_SUB=      SSLDIR=${SSLDIR}
 
do-install:
        @${MKDIR} ${STAGEDIR}${SSLDIR}
        @${INSTALL_DATA} ${WRKSRC}/cacerts.jks ${STAGEDIR}${SSLDIR}/cacerts
 
.include <bsd.port.mk>

Let me know what you think.

java/openjdk8/Makefile
302–304

My preference would be that if ${LOCALBASE}/etc/ssl/cacerts doesn't exist, and the option is on, then we either error the build (preferred) or don't install the symlink. Either of those makes it less likely that a user shoots themselves in the foot and ends up with an empty cacerts. I don't think it's too much to want a user who knows what they are doing to install the custom cacerts first.

java/openjdk8/Makefile
302–304

I see, but how to build the package then in poudiere if I cannot depend on my custom port or manually dropping of the file ${LOCALBASE}/etc/ssl/cacerts? poudriere testport will always fail.

michaelo marked an inline comment as not done.EditedDec 1 2023, 9:01 AM

I have one idea I will evaluate, but I am afraid it will just move the build time vs installation time problem. I will get back to you in a few days. The idea is inspired by an approach taken by @cy.

java/openjdk8/Makefile
302–304

Sorry for not responding earlier, things have been hectic and I just saw this update. It seems like you're focusing this change on the situation where you have a custom port that installs your own set of certificates? If so, then maybe the best option is to just keep this change local and not commit it to the public ports tree. That way you can build packages locally in the configuration you want, without exposing the broader community of FreeBSD users to the possibility of installing the port without any certificate authority. Yes, that is more painful for you, but removes the risk of a bad install for other users.

If you want to go ahead with it in its current form, then the only other thing I can think of is to make it very clear from the option name and description that this is dangerous and not recommended. Overall I'm uncomfortable with the idea of an option that looks innocuous but will by default create a broken install. Users shouldn't have to read the port Makefile details to figure out that the option isn't safe and is strictly for experts supporting custom installations. Experts can then read the Makefile and decide to use it, aware of the risks.

java/openjdk8/Makefile
302–304

True, it was never meant for the faint of heart. I have two counter-proposals which you might consider better than this one:

  1. Turn this rather into a build variable similar like in 743dbb8f6fce110d31bff7ccf2652396cb53868a to a make.conf variable, e.g., OPENJDK_CACERTS_PATH which will be used to symlink. This makes it crystal clear for people that is not default and one cannot select it by accident and leave you with broken OpenJDK installation.
  2. Create e new port, e.g., security/openjdk-cacerts-craeator. It will contain a single class which will turn /etc/ssl/certs to /etc/ssl/cacerts (truststore). It will be invoked at pkg-install and certlctl(8) will invoke it when java is on PATH and the class in LOCALBASE. Invoking keytool(1) isn't an option because you need one invocation per CA cert and it will take forever.

The first one is cheap. The second one is the most elegant until OpenSSL 3.2 lands in base, but it requires more effort and until the change in certlctl(8) lands in 13.3 and 14.1 base it will take long.

I am willing to work option two if people are willing to review the port and the change in certctl(8).

java/openjdk8/Makefile
302–304

I'm ok with approach number 1. I don't know if it is worth investing in the second approach now if you anticipate that OpenSSL 3.2 will impact that approach and is due in a few months.

java/openjdk8/Makefile
302–304

Great, I will change the code acordingly.

Implement with a variable in make.conf

michaelo retitled this revision from java/openjdk8: allow user to trust extra local certificates to java/openjdk*: Allow user to specify an alternative cacerts file.Jan 26 2024, 4:02 PM
michaelo edited the summary of this revision. (Show Details)

@glewis, as discussed last year I have rewritten the solution using a make variable. Verfied for all affected OpenJDK versions with a Maven build against our internal Nexus instance and expected failure with 18, 19, 20 which I did not touch.

michaelo retitled this revision from java/openjdk*: Allow user to specify an alternative cacerts file to java/openjdk*: Allow users to specify an alternative cacerts file.Jan 26 2024, 4:04 PM

This version looks good to me. Thanks!

This version looks good to me. Thanks!

Appreciated! Can you officially approve the review?

Anyone else willing to review and approve? As soon as Greg approves I will leave every one a week or so then I will merge it.

This revision is now accepted and ready to land.Feb 2 2024, 8:01 AM