Skip to content

Commit 9cb3ddc

Browse files
authored
Build cacerts during build from Mozilla's list (#2113)
The cacerts trust store provided by OpenJDK lacks a few common certificates (see adoptium/adoptium-support#13). We reached out to OpenJDK, but there was little interest to change the state of affairs (see https://mail.openjdk.java.net/pipermail/jdk-dev/2020-May/004305.html). Consequently, the AdoptOpenJDK TSC decided to replace the bundled trust store with the root CA certificates included in Mozilla Firefox. Mozilla runs a trusted root CA program and is used by, amongst others, most Linux distributions. Running our own root CA program was not an option (too much work, difficult). But we leave the option open to include CA certificates on a case-by-case basis. If anyone wants to build with the stock OpenJDK certificates, pass `--custom-cacerts false`. The list of CA certificates is not downloaded on demand but stored in the repository. This prevents intermittent download failures and makes it easier to inspect what certificates we have bundled with a certain release. Changes are also clearly visible in the revision history. This is also the reason that the cacerts file is built from source during the JDK build. The downside is that the list of certificates needs to be regularly updated. The cacerts trust store is built with keytool from the boot JDK to ensure that it is compatible with the built JDK version.
1 parent 26b06d7 commit 9cb3ddc

File tree

13 files changed

+23871
-75
lines changed

13 files changed

+23871
-75
lines changed

README.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,9 @@ if using docker, keep the container after the build.
185185
--make-exploded-image
186186
creates an exploded image (useful for codesigning jmods). Use --assemble-exploded-image once you have signed the jmods to complete the packaging steps.
187187
188+
--custom-cacerts <true|false>
189+
If true (default), a custom cacerts file will be generated based on Mozilla's list of CA certificates (see folder security/). If false, the file shipped by OpenJDK will be used.
190+
188191
-n, --no-colour
189192
disable colour output.
190193
@@ -228,8 +231,7 @@ For reference, OpenJDK version numbers look like 1.8.0_162-b12 (for Java 8) or
228231
This is typically used in conjunction with -b.
229232
230233
--use-jep319-certs
231-
Use certs defined in JEP319 in Java 8/9. This will increase the volume of traffic downloaded, however will
232-
provide an up to date ca cert list.
234+
Use certs defined in JEP319 in Java 8/9. Deprecated, has no effect.
233235
234236
-v, --version
235237
specify the OpenJDK version to build e.g. jdk8u. Left for backwards compatibility.

docker/dockerfile-generator.sh

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,7 @@ printDockerJDKs() {
243243
printJDK $((JDK_VERSION-1))
244244
echo "RUN ln -sf /usr/lib/jvm/jdk$((JDK_VERSION-1))/bin/java /usr/bin/java" >> $DOCKERFILE_PATH
245245
echo "RUN ln -sf /usr/lib/jvm/jdk$((JDK_VERSION-1))/bin/javac /usr/bin/javac" >> $DOCKERFILE_PATH
246+
echo "RUN ln -sf /usr/lib/jvm/jdk$((JDK_VERSION-1))/bin/keytool /usr/bin/keytool" >> $DOCKERFILE_PATH
246247
fi
247248

248249
# Build 'jdk' with the most recent GA release
@@ -254,6 +255,7 @@ printDockerJDKs() {
254255
printJDK ${JDK_GA}
255256
echo "RUN ln -sf /usr/lib/jvm/jdk${JDK_GA}/bin/java /usr/bin/java" >> $DOCKERFILE_PATH
256257
echo "RUN ln -sf /usr/lib/jvm/jdk${JDK_GA}/bin/javac /usr/bin/javac" >> $DOCKERFILE_PATH
258+
echo "RUN ln -sf /usr/lib/jvm/jdk${JDK_GA}/bin/keytool /usr/bin/keytool" >> $DOCKERFILE_PATH
257259
fi
258260

259261
# if JDK_VERSION is 9, another jdk8 doesn't need to be extracted
@@ -274,6 +276,7 @@ RUN sh -c \"mkdir -p /usr/lib/jvm/jdk$JDKVersion && wget 'https://api.adoptopenj
274276
printCopyFolders(){
275277
echo "
276278
COPY sbin /openjdk/sbin
279+
COPY security /openjdk/security
277280
COPY workspace/config /openjdk/config
278281
COPY pipelines /openjdk/pipelines" >> $DOCKERFILE_PATH
279282
}

makejdk-any-platform.1

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -166,8 +166,12 @@ For reference, OpenJDK version numbers look like 1.8.0_162-b12 (for Java 8) or
166166
This is typically used in conjunction with \fB<-b>\fR.
167167
.TP
168168
.BR \-\-use-jep319-certs
169-
Use certs defined in JEP319 in Java 8/9. This will increase the volume of traffic
170-
downloaded, however will provide an uptodate ca cert list.
169+
Use certs defined in JEP319 in Java 8/9. Deprecated, has no effect.
170+
.TP
171+
.BR \-\-custom-cacerts " " \fI<true|false>\fR
172+
If true (default), a custom cacerts file will be generated based on Mozilla's
173+
list of CA certificates (see folder security/). If false, the file shipped by
174+
OpenJDK will be used.
171175
.TP
172176
.BR \-v ", " \-\-version " " \fI<version>\fR
173177
specify the OpenJDK version to build e.g. jdk8u. Left for backwards compatibility.

sbin/build.sh

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -364,6 +364,11 @@ configureCommandParameters() {
364364
echo "Configuring jvm variants if provided"
365365
addConfigureArgIfValueIsNotEmpty "--with-jvm-variants=" "${BUILD_CONFIG[JVM_VARIANT]}"
366366

367+
if [ "${BUILD_CONFIG[CUSTOM_CACERTS]}" != "false" ] ; then
368+
echo "Configure custom cacerts file security/cacerts"
369+
addConfigureArgIfValueIsNotEmpty "--with-cacerts-file=" "$SCRIPT_DIR/../security/cacerts"
370+
fi
371+
367372
# Now we add any platform-specific args after the configure args, so they can override if necessary.
368373
CONFIGURE_ARGS="${CONFIGURE_ARGS} ${BUILD_CONFIG[CONFIGURE_ARGS_FOR_ANY_PLATFORM]}"
369374

sbin/common/config_init.sh

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ COPY_MACOSX_FREE_FONT_LIB_FOR_JDK_FLAG
4848
COPY_MACOSX_FREE_FONT_LIB_FOR_JRE_FLAG
4949
COPY_TO_HOST
5050
CREATE_DEBUG_SYMBOLS_PACKAGE
51+
CUSTOM_CACERTS
5152
DEBUG_DOCKER
5253
DEBUG_IMAGE_PATH
5354
DISABLE_ADOPT_BRANCH_SAFETY
@@ -212,6 +213,9 @@ function parseConfigurationArguments() {
212213
"--assemble-exploded-image" )
213214
BUILD_CONFIG[ASSEMBLE_EXPLODED_IMAGE]=true;;
214215

216+
"--custom-cacerts" )
217+
BUILD_CONFIG[CUSTOM_CACERTS]="$1"; shift;;
218+
215219
"--codesign-identity" )
216220
BUILD_CONFIG[MACOSX_CODESIGN_IDENTITY]="$1"; shift;;
217221

@@ -480,6 +484,9 @@ function configDefaults() {
480484
BUILD_CONFIG[USER_SUPPLIED_CONFIGURE_ARGS]=${BUILD_CONFIG[USER_SUPPLIED_CONFIGURE_ARGS]:-""}
481485
BUILD_CONFIG[USER_SUPPLIED_MAKE_ARGS]=${BUILD_CONFIG[USER_SUPPLIED_MAKE_ARGS]:-""}
482486

487+
# Whether to use AdoptOpenJDK's cacerts file (true) or use the file provided by OpenJDK (false)
488+
BUILD_CONFIG[CUSTOM_CACERTS]=${BUILD_CONFIG[CUSTOM_CACERTS]:-"true"}
489+
483490
BUILD_CONFIG[DOCKER]=${BUILD_CONFIG[DOCKER]:-"docker"}
484491

485492
BUILD_CONFIG[TMP_SPACE_BUILD]=${BUILD_CONFIG[TMP_SPACE_BUILD]:-false}

sbin/prepareWorkspace.sh

Lines changed: 7 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -510,44 +510,15 @@ checkingAndDownloadingFreeType() {
510510
fi
511511
}
512512

513-
# Download our security certificates
514-
downloadCerts() {
515-
local caLink="$1"
513+
# Generates cacerts file
514+
prepareCacerts() {
515+
echo "Generating cacerts from Mozilla's bundle"
516516

517-
mkdir -p "security"
518-
# Temporary fudge as curl on my windows boxes is exiting with RC=127
519-
if [[ "$OSTYPE" == "cygwin" ]] || [[ "$OSTYPE" == "msys" ]]; then
520-
wget -O "./security/cacerts" "${caLink}"
521-
else
522-
curl -L -o "./security/cacerts" "${caLink}"
523-
fi
524-
}
525-
526-
# Certificate Authority Certs (CA Certs)
527-
checkingAndDownloadCaCerts() {
528-
cd "${BUILD_CONFIG[WORKSPACE_DIR]}/${BUILD_CONFIG[WORKING_DIR]}" || exit
529-
530-
echo "Retrieving cacerts file if needed"
531-
# Ensure it's the latest we pull in
532-
rm -rf "cacerts_area"
533-
mkdir "cacerts_area" || exit
534-
cd "cacerts_area" || exit
535-
536-
if [ "${BUILD_CONFIG[BUILD_VARIANT]}" == "${BUILD_VARIANT_CORRETTO}" ]; then
537-
local caLink="https://github.com/corretto/corretto-8/blob/preview-release/cacerts?raw=true"
538-
downloadCerts "$caLink"
539-
elif [ "${BUILD_CONFIG[USE_JEP319_CERTS]}" != "true" ]; then
540-
git init
541-
git remote add origin -f "${BUILD_CONFIG[OPENJDK_BUILD_REPO_URI]}"
542-
git config core.sparsecheckout true
543-
echo "security/*" >>.git/info/sparse-checkout
544-
git pull origin "${BUILD_CONFIG[OPENJDK_BUILD_REPO_BRANCH]}"
545-
fi
546-
547-
cd "${BUILD_CONFIG[WORKSPACE_DIR]}/${BUILD_CONFIG[WORKING_DIR]}" || exit
517+
cd "$SCRIPT_DIR/../security"
518+
./mk-cacerts.sh --keytool "${BUILD_CONFIG[JDK_BOOT_DIR]}/bin/keytool"
548519
}
549520

550-
# Download all of the dependencies for OpenJDK (Alsa, FreeType, CACerts et al)
521+
# Download all of the dependencies for OpenJDK (Alsa, FreeType, etc.)
551522
downloadingRequiredDependencies() {
552523
if [[ "${BUILD_CONFIG[CLEAN_LIBS]}" == "true" ]]; then
553524
rm -rf "${BUILD_CONFIG[WORKSPACE_DIR]}/libs/freetype" || true
@@ -587,10 +558,6 @@ downloadingRequiredDependencies() {
587558
else
588559
echo "Skipping Freetype"
589560
fi
590-
591-
echo "Checking and download CaCerts dependency"
592-
checkingAndDownloadCaCerts
593-
594561
}
595562

596563
function moveTmpToWorkspaceLocation() {
@@ -676,5 +643,6 @@ function configureWorkspace() {
676643
relocateToTmpIfNeeded
677644
checkoutAndCloneOpenJDKGitRepo
678645
applyPatches
646+
prepareCacerts
679647
fi
680648
}

security/.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
ca-bundle.crt
2+
cacerts
3+
certs/

security/GenerateCertsFile.sh

Lines changed: 0 additions & 26 deletions
This file was deleted.

security/README.md

Lines changed: 41 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,48 @@
11
# Security files for OpenJDK
22

3-
### This repository contains the cacerts file used with OpenJDK
3+
## CA Certificates
44

5-
#### Steps we use to create the cacerts file
5+
The cacerts file that OpenJDK maintains lacks a number of CA certificates that are present in common browsers. As a result, users of OpenJDK cannot connect to servers with Java that they can connect to with their browsers. This causes confusion and [support requests][support-issues].
66

7-
1. Download the following Perl script: https://raw.githubusercontent.com/curl/curl/master/lib/mk-ca-bundle.pl
7+
In May 2020, [we reached out to OpenJDK to discuss this situation][jdk-dev-thread], but no consensus was reached. Consequently, the [AdoptOpenJDK TSC decided to deviate from OpenJDK and distribute a custom trust store][tsc-decision] based on [Mozilla's list of trusted CA certificates][mozilla-certdata] which is also used by many Linux distributions.
88

9-
2. Download the following Java application: https://github.com/use-sparingly/keyutil/releases/download/0.4.0/keyutil-0.4.0.jar (source available at https://github.com/use-sparingly/keyutil)
9+
If you want to build OpenJDK with the original cacerts file, set `--custom-cacerts=false`.
1010

11-
3. Run the provided `GenerateCertsFile.sh` script with: `bash ./GenerateCertsFile.sh` - this will use the above files assuming they're located in the same directory as the script
11+
### Process
1212

13-
4. Use the cacerts provided: it must be in the `jdk/jre/lib/security` or `jdk/lib/security`folder
13+
The `cacerts` file is build as part of the regular JDK build from source. The reason is that vetting blobs in PR is difficult. Because `certdata.txt` cannot be converted directly into a Java Key Store, we do it in multiple steps:
14+
15+
1. Convert `certdata.txt` in a PEM file (`ca-bundle.crt`) with [mk-ca-bundle.pl][mk-ca-bundle.pl].
16+
2. Split `ca-bundle.crt` into individual certificates and import them with `keytool` into a new `cacerts` file.
17+
18+
To generate a new `cacerts` file, run:
19+
20+
$ ./mk-cacerts.sh
21+
22+
If anybody ever plans to replace `mk-ca-bundle.pl`, be sure to read [Can I use Mozilla's set of CA certificates?][can-i-use-mozilla].
23+
24+
### Updating the List of Certificates
25+
26+
Every time Mozilla updates the list of CA certificates, we have to update our copy of `certdata.txt`. Whether it needs to be updated can be checked on [curl's website][curl-ca-extract]. If it needs updating, the process looks as follows:
27+
28+
1. Download the [current version of certdata.txt][mozilla-certdata].
29+
2. Replace the existing file in `security`.
30+
3. Open a pull request to get it merged.
31+
32+
The updated list will be picked up during the next build.
33+
34+
### License
35+
36+
The resulting cacerts file is licensed under the terms of the [source file][mozilla-certdata], the Mozilla Public License, v.2.0.
37+
38+
## Future Work
39+
40+
* Create a GitHub bot that checks whether `certdata.txt` needs updating and automatically creates a PR.
41+
42+
[support-issues]: https://github.com/AdoptOpenJDK/openjdk-support/issues/13
43+
[jdk-dev-thread]: https://mail.openjdk.java.net/pipermail/jdk-dev/2020-May/004305.html
44+
[tsc-decision]: https://github.com/AdoptOpenJDK/openjdk-support/issues/13#issuecomment-635400251
45+
[mozilla-certdata]: https://hg.mozilla.org/releases/mozilla-release/raw-file/default/security/nss/lib/ckfw/builtins/certdata.txt
46+
[mk-ca-bundle.pl]: https://curl.haxx.se/docs/mk-ca-bundle.html
47+
[curl-ca-extract]: https://curl.haxx.se/docs/caextract.html
48+
[can-i-use-mozilla]: https://wiki.mozilla.org/CA/FAQ#Can_I_use_Mozilla.27s_set_of_CA_certificates.3F

security/cacerts

-189 KB
Binary file not shown.

0 commit comments

Comments
 (0)