Open kivoli opened 5 years ago
Replacing the cacerts file with a symlink as a work around doesn’t work either:
$ /home/vagrant/.cache/bazel/_bazel_vagrant/install/c25ea2c3043bcba07b93dde10595066c/_embedded_binaries/embedded_tools/jdk/lib/security/cacerts -> /etc/ssl/certs/java/cacerts
$ bazel build //:all
FATAL: corrupt installation: file '/home/vagrant/.cache/bazel/_bazel_vagrant/install/c25ea2c3043bcba07b93dde10595066c/_embedded_binaries/embedded_tools/jdk/lib/security/cacerts' is missing or modified. Please remove '/home/vagrant/.cache/bazel/_bazel_vagrant/install/c25ea2c3043bcba07b93dde10595066c' and try again.
Also found this announcement from last April that states:
Note:
Homebrew and debian packages do not contain the embedded JDK. This change only affects the shell installers.
Is the embedded JDK a packaging bug?
Also found this announcement from last April that states:
That's from April 2017, quite a long while ago.
Is the embedded JDK a packaging bug?
Could be that it's embedded unintentionally as it's not mentioned in the 0.16.0 release notes. Anyway, you might be interested in related issue #5753.
@gertvdijk Indeed — on both accounts. Nevertheless the announcement declared the intent back then. I have not yet found an indicator that the intent has changed. So together with #5753 I guess it’s up for debate what route should be taken.
Personally I would prefer following the Debian way (not embedding dependencies), which, of course, would also help with my requirement of using the system cacerts.
This issue describes behaviour of the OpenJDK build that Bazel is using, I'm not sure there's a good fix in Bazel itself.
If you don't want to use the embedded JDK, you can override it by setting a custom --host_javabase
.
The issue with https://git.cacert.org/cacert.git
reproduces independently of Bazel, for any OpenJDK build from 8 through 11. (I didn't try earlier versions.)
Repro:
import java.io.*;
import java.net.*;
import javax.net.ssl.*;
public class UrlConnect {
public static void main(String[] args) {
String[] defaultArgs = {"https://git.cacert.org/cacert.git"};
if (args.length == 0) {
args = defaultArgs;
}
for (String url : args) {
try (InputStream stream = new URL(url).openStream()) {
System.out.println("OK: " + url);
} catch (SSLHandshakeException ex) {
// This is bad
System.err.println("ERROR: " + url + ": " + ex.toString());
} catch (IOException ex) {
System.out.println("Warning: " + url + ": " + ex.toString());
}
}
}
}
$ java -version
java version "9.0.4"
$ javac UrlConnect.java
$ java UrlConnect
ERROR: https://git.cacert.org/cacert.git: javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
Note that there were some changes related to cacerts starting in 9: http://www.oracle.com/technetwork/java/javase/9all-relnotes-3704433.html#JDK-8189131
The OpenJDK 9 binary for Linux x64 contains an empty cacerts keystore. This prevents TLS connections from being established because there are no Trusted Root Certificate Authorities installed. As a workaround for OpenJDK 9 binaries, users had to set the javax.net.ssl.trustStore System Property to use a different keystore.
"JEP 319: Root Certificates" [1] addresses this problem by populating the cacerts keystore with a set of root certificates issued by the CAs of Oracle's Java SE Root CA Program. As a prerequisite, each CA must sign the Oracle Contributor Agreement (OCA) http://www.oracle.com/technetwork/community/oca-486395.html, or an equivalent agreement, to grant Oracle the right to open-source their certificates.
[1] JDK-8191486
cc @philwo
related: https://groups.google.com/forum/#!topic/bazel-discuss/13uPDObyfQg
@cushon Please note that I do not use git.cacerts.org
. You may have missed my note in the description:
Note: This has nothing to do with CACert but they are the only public site I know that uses a certificate from [a] CA that’s not in most default certificate bundles.
Our problem is with a private company CA.
The reason this is an issue opened with Bazel is because we are using their official Debian packages and these suddenly behave differently. Before 0.16 these packages used the JDK provided by Debian which integrate with the ca-certificates
package managing system level certificates including private or personal CAs via /usr/local/share/ca-certificates
and update-ca-certificates
, generating /etc/ssl/certs/java/cacerts
which in turn is used by Debian’s JDKs and JREs. This is exactly the way we deploy the company CA and it has been working perfectly fine with Bazel, too, so far. Although an announcement from a year ago may be considered outdated by some I’m missing an announcement to the opposite.
Last but not least I understand that there are work arounds but I still have to ask the question if this is a change of the stance taken by the project or, in fact, a bug in packaging. Personally I would obviously prefer for a Debian package to not bring it’s on JDK to the party and break the nice integration features along the way. If the project however thinks that times have changed, I kindly ask it to document the change(s) and ideally also provide work arounds for such issues as part of the official documentation.
You may ask why I don’t just use the work around and be done with it? Since it means hard coding a path in several locations instead of using an “automagic” solution managed by the distribution. Who knows what other stuff will break down the line because our setup is suddenly “non-standard”?
Thank you for linking the Google Groups discussion, matthew indeed has the same issue.
Personally I would obviously prefer for a Debian package to not bring it’s on JDK to the party and break the nice integration features along the way.
Rest assured that the Bazel team feels the same. This will be a temporary measure. Java has recently switched to a six month release schedule and we found that many older but still popular distributions don't ship with a sufficiently recent JDK that we decided to go the embedded way for now.
@buchgr It’s of course nice to hear that the Bazel shares that sentiment but now I’m confused as to what happens next. Even if it is a “temporary measure” it still means it breaks this integration “for now”. Also I would assume that there always will be popular distributions with outdated dependencies.
Or is one of the ideas to have separate repositories per distribution? Actually I just realised that the APT source “component” we use right now is “jdk1.8” which would seem to imply that the Bazel version provided depends on JDK1.8 and already has this kind of differentiation.
This will be a temporary measure. Java has recently switched to a six month release schedule and we found that many older but still popular distributions don't ship with a sufficiently recent JDK that we decided to go the embedded way for now.
RHEL / CentOS, Debian stable, Ubuntu LTS, ... will probably always ship way too outdated JDKs for our needs. It's not like this will change in the future. The idea of using an embedded JDK was to become independent of what JDK versions the popular distributions ship and not break our users when we upgrade to a newer one.
Of course we can ask people who use these distros to just install a suitable JDK via their package manager, even if it means getting it from some PPA or third-party repository, but is that better? When we discussed this ~2 years (?) ago, the sentiment was: "No, requiring people to install system packages from third-party repos just to use Bazel is not acceptable".
I personally think that embedding a JDK in our official releases and distro packages is the right thing to do, as this is the only way to ensure that people use what we actually tested on CI and also use ourselves. We had breakages with JavaBuilder in the past even when people used the correct major version of OpenJDK, but a too new or too old patch version that we didn't test against.
For packages maintained by distributions themselves (this also applies to Homebrew), they would obviously feel different, but then they'd be responsible for picking matching versions of the JDK and Bazel in their overall version ecosystem and testing the results - just as they already successfully do with all other packages they maintain.
Actually I just realised that the APT source “component” we use right now is “jdk1.8” which would seem to imply that the Bazel version provided depends on JDK1.8 and already has this kind of differentiation.
This is just historical baggage - we had a special jdk1.7 build that used an older, fixed version of JavaBuilder for a while, but when Bazel finally broke compatibility and just could no longer build / run with that version, we dropped it. We just kept the remaining jdk1.8 component.
Of course we can ask people who use these distros to just install a suitable JDK via their package manager, even if it means getting it from some PPA or third-party repository, but is that better? When we discussed this ~2 years (?) ago, the sentiment was: "No, requiring people to install system packages from third-party repos just to use Bazel is not acceptable".
That's what we are doing today. See https://docs.bazel.build/versions/master/install-ubuntu.html#using-bazel-custom-apt-repository
We had breakages with JavaBuilder in the past even when people used the correct major version of OpenJDK, but a too new or too old patch version that we didn't test against.
That's a problem and I think you are also aware that we have agreed that going forward we need to be able to supply the correct JavaBuilder for all supported major JDK versions. You additionally also know that we will soon hide the embedded JDK from the --host_javabase
and --javabase
and have the user supply their own JDK for these flags. I think it's out of question that we'll need to ensure that for these flags we are compatible with the distribution JDKs.
@buchgr Why do you think do we even have an embedded JDK, if asking people to simply install the correct one is fine? (No snark intended, honest question.)
For the target --javabase
it's easy an necessary to support a range of JDKs because our toolchain supports cross compilation: users expect to be able to use Bazel to target deployment to a range of JDK versions (currently Java >= 6).
For --host_javabase
the default toolchain is going to track six-monthly JDK releases going forward, so asking Java Bazel users to install the latest release to use as a host JDK would caused similar problems to the ones solved by using an embedded --server_javabase
.
We've been discussing using a remote repository for the default --host_javabase
, which ensures the toolchain works and is less onerous than manually installing a compatible host javabase.
For everyone coming here using Google/search hoping to see a work-around posted, here is one for Debian/Ubuntu and derivatives:
Put in your bazelrc file these two startup options:
startup --host_jvm_args=-Djavax.net.ssl.trustStore=/etc/ssl/certs/java/cacerts \
--host_jvm_args=-Djavax.net.ssl.trustStorePassword=changeit
From earlier comment:
related: https://groups.google.com/forum/#!topic/bazel-discuss/13uPDObyfQg
Thanks @cushon and @philwo!
@gertvdijk: With Bazel 0.16.1 this fails with
INFO: Reading 'startup' options from /path/to/workspace/.bazelrc: --host_jvm_args=-Djavax.net.ssl.trustStore=/etc/ssl/certs/java/cac
erts --host_jvm_args=-Djavax.net.ssl.trustStorePassword=changeit
Server crashed during startup. Now printing /home/ccoalson/.cache/bazel/_bazel_ccoalson/f8087e59fd95af1ae29e8fcb7ff1a3
dc/server/jvm.out
WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access by io.netty.util.internal.ReflectionUtil (file:/home/ccoalson/.cache/bazel/_bazel_ccoalson/install/ca1b8b7c3e5200be14b7f27896826862/_embedded_binaries/A-server.jar) to field sun.nio.ch.SelectorImpl.selectedKeys
WARNING: Please consider reporting this to the maintainers of io.netty.util.internal.ReflectionUtil
WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
WARNING: All illegal access operations will be denied in a future release
@calder
Server crashed during startup.
This indicates something is hopelessly wrong. Some things to check:
Are you indeed running Debian/Ubuntu or a derivative?
Do you have the ca-certificates-java
package installed?
Could you verify the file /etc/ssl/certs/java/cacerts
exists?
$ file /etc/ssl/certs/java/cacerts /etc/ssl/certs/java/cacerts: Java KeyStore
Does upgrading to a current stable Bazel version help? (0.18.1 / 0.19.0 at the time of writing)
Same issue. Any update?
Same issue. Any update?
Please be more specific on your system/environment. I've been using the approach I commented earlier for a year now. Are you able to apply a work-around like that? (probably needs adjustments to your system if not Debian/Ubuntu-like.)
@gertvdijk Oh, why didn't I see that?! Solved my problem. Thanks a lot!
On a Mac, I've installed my root cert to my jvm certs file, for me it's:
/Library/Java/JavaVirtualMachines/zulu-11.jdk/Contents/Home/lib/security/cacerts
I can verify my expected cert is in that file with:
keytool -list -v -keystore /Library/Java/JavaVirtualMachines/zulu-11.jdk/Contents/Home/lib/security/cacerts | grep "My Expected Cert"
In my ~/.bazelrc file, I have:
startup --host_jvm_args="-Djavax.net.ssl.trustStore=/Library/Java/JavaVirtualMachines/zulu-11.jdk/Contents/Home/lib/security/cacerts" \
--host_jvm_args=-Djavax.net.ssl.trustStorePassword=changeit
When I run my go generate
command, I see this at the start:
INFO: Reading 'startup' options from /Users/andy/.bazelrc: --host_jvm_args=-Djavax.net.ssl.trustStore=/Library/Java/JavaVirtualMachines/zulu-11.jdk/Contents/Home/lib/security/cacerts, --host_jvm_args=-Djavax.net.ssl.trustStorePassword=changeit
So It's parsing the file, and doesn't seem to complain about it.
However, it fails to install any packages while I'm on my company's corporate VPN (which is what inserts this cert):
PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
bazel --version
bazel 2.2.0
Any thoughts here?
Hi @AndrewRayCode,
unfortunately I don't know much about how Java handles SSL certificates, but I just had an idea. You could try to run Bazel with your system JDK and see if that makes it work:
# Run Bazel with the embedded JDK
$ bazel info
[...]
java-home: /private/var/tmp/_bazel_philwo/install/d07238c5957d0addf241b6be07f3c14b/embedded_tools/jdk
java-runtime: OpenJDK Runtime Environment (build 11.0.6+10-LTS) by Azul Systems, Inc.
java-vm: OpenJDK 64-Bit Server VM (build 11.0.6+10-LTS, mixed mode) by Azul Systems, Inc.
[...]
# Run Bazel with my system JDK
$ bazel --server_javabase=$JAVA_HOME info
[...]
java-home: /Library/Java/JavaVirtualMachines/zulu-11.jdk/Contents/Home
java-runtime: OpenJDK Runtime Environment (build 11.0.11+9-LTS) by Azul Systems, Inc.
java-vm: OpenJDK 64-Bit Server VM (build 11.0.11+9-LTS, mixed mode) by Azul Systems, Inc.
[...]
I ran into this on macOS. After installing java
via brew install java
, then Java proper (using the .dmg from https://www.java.com/en/download/), it started to work.
Dominik's response unfortunately did not work for me, but adding startup --host_jvm_args=-Djavax.net.ssl.trustStoreType=KeychainStore
finally got this to work for me on macOS when using a private CA. Note that you need to have the relevant certificates installed to your keychain for this to work.
Description of the problem / feature request:
Before Bazel 0.16 at least the Debian packages depended on the system jdk.
Bazel 0.16 apparently embeds the JDK which fundamentally changes the behaviour at least in regards to cacerts. The custom CA certificates that have been added to the system certificate store are of course missing in the embedded JDK’s cacerts:
Bugs: what's the simplest, easiest way to reproduce this bug? Please provide a minimal example if possible.
Set up a Vagrant box with Debian Stretch and install Bazel 0.16 from the APT repository (
http://storage.googleapis.com/bazel-apt stable jdk1.8
). Also install the CACert root CAIn a folder of your choosing, create
and
Note: This has nothing to do with CACert but they are the only public site I know that uses a certificate from CA that’s not in most default certificate bundles.
Now try to “build” the package.
If you use Bazel 0.15 instead the error message will be different:
Note: If the CACert CA is not installed in the system the error message will be the same as with 0.16.
What operating system are you running Bazel on?
Debian 8 Stretch
What's the output of
bazel info release
?What's the output of
git remote get-url origin ; git rev-parse master ; git rev-parse HEAD
?N/A
Have you found anything relevant by searching the web?
!3915 tells me how to override the path to cacerts but it would be better if Bazel just uses the system’s cacerts instead. Personally I think this is a regression breaking backwards compatibility.
Any other information, logs, or outputs that you want to share?
0.16 definitely brings its own cacerts while 0.15 does not even have the jdk folder.