From 4b93228e00cfe43bcc29410e0bd7c8be8163a8be Mon Sep 17 00:00:00 2001 From: Ed Morley <501702+edmorley@users.noreply.github.com> Date: Wed, 8 May 2024 21:36:04 +0100 Subject: [PATCH] Improvements to Java certificates store creation (#300) Even though the base images intentionally don't ship with a JRE, we include the Java certificates store in the image, so that the JVM buildpacks can configure Java apps to use it instead of the one that ships in each JRE release. This allows the Java certs store to be updated via base image updates, like the non-Java `ca-certificates` package. For older Ubuntu versions, the `ca-certificates-java` package explicitly depended on a JRE, meaning we had to install both a JRE and `ca-certificates-java`, then remove both in a way that left the certs store (which is generated via a post-install trigger) behind. This leaves the package in a "removed but not purged" state, which can be seen via the `package status: config-files` in `installed-packages*.txt`. However, as of Ubuntu 24.04, the `ca-certificates-java` package no longer has an explicit dependency on a JRE, meaning we can remove the JRE without causing `ca-certificates-java` to be uninstalled transitively. As such for Heroku-24, the `apt-get remove ca-certificates-java` step can be removed. In addition, the upstream java certs store JKS vs PKCS12 format bug (that was the reason the JRE version was pinned to v8) has long since been fixed (in 2018), so for Heroku-24 we can safely switch back to using `default-jre-headless` (which for Ubuntu 24.04 maps to JRE v21). Lastly, for Heroku-20/22 I've backported some of the no-op comment /command streamlining improvements (but otherwise the changes there are a no-op). GUS-W-15713117. --- heroku-20/setup.sh | 21 ++++++++++++-------- heroku-22/setup.sh | 21 ++++++++++++-------- heroku-24-build/installed-packages-amd64.txt | 2 +- heroku-24-build/installed-packages-arm64.txt | 2 +- heroku-24/installed-packages-amd64.txt | 2 +- heroku-24/installed-packages-arm64.txt | 2 +- heroku-24/setup.sh | 21 ++++++++++---------- 7 files changed, 41 insertions(+), 30 deletions(-) diff --git a/heroku-20/setup.sh b/heroku-20/setup.sh index e11f90d2..ddf7c7a4 100755 --- a/heroku-20/setup.sh +++ b/heroku-20/setup.sh @@ -157,16 +157,21 @@ apt-get install -y --no-install-recommends "${packages[@]}" cp /build/imagemagick-policy.xml /etc/ImageMagick-6/policy.xml -# Temporarily install ca-certificates-java to generate the certificates store used -# by Java apps. Generation occurs in a post-install script which requires a JRE. -# We're using OpenJDK 8 rather than something newer, to work around: -# https://github.com/heroku/base-images/pull/103#issuecomment-389544431 +# Install ca-certificates-java so that the JVM buildpacks can configure Java apps to use the Java certs +# store in the base image instead of the one that ships in each JRE release, allowing certs to be updated +# via base image updates. Generation of the `cacerts` file occurs in a post-install script which requires +# a JRE, however, we don't want a JRE in the final image so remove it afterwards. apt-get install -y --no-install-recommends ca-certificates-java openjdk-8-jre-headless -# Using remove rather than purge so that the generated certs are left behind. +# For Ubuntu versions prior to 24.04 the ca-certificates-java package has a direct dependency on a JRE, so +# we can't remove the JRE without also removing ca-certificates-java. However, we can work around this by +# not using `--purge` when removing ca-certificates-java, which leaves behind the generated certs store. apt-get remove -y ca-certificates-java -apt-get purge -y openjdk-8-jre-headless -apt-get autoremove -y --purge -test "$(file -b /etc/ssl/certs/java/cacerts)" = "Java KeyStore" +apt-get remove -y --purge --auto-remove openjdk-8-jre-headless +# Check that the certs store (a) wasn't purged during removal of ca-certificates-java, (b) uses the JKS +# format not PKCS12, since in the past there was an upstream regression for this: +# https://github.com/heroku/base-images/pull/103#issuecomment-389544431 +# https://bugs.launchpad.net/ubuntu/+source/ca-certificates-java/+bug/1771363 +test "$(file --brief /etc/ssl/certs/java/cacerts)" = "Java KeyStore" rm -rf /root/* rm -rf /tmp/* diff --git a/heroku-22/setup.sh b/heroku-22/setup.sh index cda1bb7e..8d6acabb 100755 --- a/heroku-22/setup.sh +++ b/heroku-22/setup.sh @@ -159,16 +159,21 @@ apt-get install -y --no-install-recommends "${packages[@]}" cp /build/imagemagick-policy.xml /etc/ImageMagick-6/policy.xml -# Temporarily install ca-certificates-java to generate the certificates store used -# by Java apps. Generation occurs in a post-install script which requires a JRE. -# We're using OpenJDK 8 rather than something newer, to work around: -# https://github.com/heroku/base-images/pull/103#issuecomment-389544431 +# Install ca-certificates-java so that the JVM buildpacks can configure Java apps to use the Java certs +# store in the base image instead of the one that ships in each JRE release, allowing certs to be updated +# via base image updates. Generation of the `cacerts` file occurs in a post-install script which requires +# a JRE, however, we don't want a JRE in the final image so remove it afterwards. apt-get install -y --no-install-recommends ca-certificates-java openjdk-8-jre-headless -# Using remove rather than purge so that the generated certs are left behind. +# For Ubuntu versions prior to 24.04 the ca-certificates-java package has a direct dependency on a JRE, so +# we can't remove the JRE without also removing ca-certificates-java. However, we can work around this by +# not using `--purge` when removing ca-certificates-java, which leaves behind the generated certs store. apt-get remove -y ca-certificates-java -apt-get purge -y openjdk-8-jre-headless -apt-get autoremove -y --purge -test "$(file -b /etc/ssl/certs/java/cacerts)" = "Java KeyStore" +apt-get remove -y --purge --auto-remove openjdk-8-jre-headless +# Check that the certs store (a) wasn't purged during removal of ca-certificates-java, (b) uses the JKS +# format not PKCS12, since in the past there was an upstream regression for this: +# https://github.com/heroku/base-images/pull/103#issuecomment-389544431 +# https://bugs.launchpad.net/ubuntu/+source/ca-certificates-java/+bug/1771363 +test "$(file --brief /etc/ssl/certs/java/cacerts)" = "Java KeyStore" rm -rf /root/* rm -rf /tmp/* diff --git a/heroku-24-build/installed-packages-amd64.txt b/heroku-24-build/installed-packages-amd64.txt index 9d414bce..ddc52cb7 100644 --- a/heroku-24-build/installed-packages-amd64.txt +++ b/heroku-24-build/installed-packages-amd64.txt @@ -18,7 +18,7 @@ bsdutils build-essential bzip2 ca-certificates -ca-certificates-java (package status: config-files) +ca-certificates-java cmake cmake-data comerr-dev diff --git a/heroku-24-build/installed-packages-arm64.txt b/heroku-24-build/installed-packages-arm64.txt index 83f9da00..23944b9f 100644 --- a/heroku-24-build/installed-packages-arm64.txt +++ b/heroku-24-build/installed-packages-arm64.txt @@ -18,7 +18,7 @@ bsdutils build-essential bzip2 ca-certificates -ca-certificates-java (package status: config-files) +ca-certificates-java cmake cmake-data comerr-dev diff --git a/heroku-24/installed-packages-amd64.txt b/heroku-24/installed-packages-amd64.txt index 297dd6f2..bde28d72 100644 --- a/heroku-24/installed-packages-amd64.txt +++ b/heroku-24/installed-packages-amd64.txt @@ -10,7 +10,7 @@ bind9-libs bsdutils bzip2 ca-certificates -ca-certificates-java (package status: config-files) +ca-certificates-java coreutils curl dash diff --git a/heroku-24/installed-packages-arm64.txt b/heroku-24/installed-packages-arm64.txt index 297dd6f2..bde28d72 100644 --- a/heroku-24/installed-packages-arm64.txt +++ b/heroku-24/installed-packages-arm64.txt @@ -10,7 +10,7 @@ bind9-libs bsdutils bzip2 ca-certificates -ca-certificates-java (package status: config-files) +ca-certificates-java coreutils curl dash diff --git a/heroku-24/setup.sh b/heroku-24/setup.sh index 71c559f8..e768ed3a 100755 --- a/heroku-24/setup.sh +++ b/heroku-24/setup.sh @@ -119,16 +119,17 @@ apt-get install -y --no-install-recommends "${packages[@]}" # https://github.com/docker-library/docs/blob/master/ubuntu/README.md#locales locale-gen en_US.UTF-8 -# Temporarily install ca-certificates-java to generate the certificates store used -# by Java apps. Generation occurs in a post-install script which requires a JRE. -# We're using OpenJDK 8 rather than something newer, to work around: -# https://github.com/heroku/stack-images/pull/103#issuecomment-389544431 -apt-get install -y --no-install-recommends ca-certificates-java openjdk-8-jre-headless -# Using remove rather than purge so that the generated certs are left behind. -apt-get remove -y ca-certificates-java -apt-get purge -y openjdk-8-jre-headless -apt-get autoremove -y --purge -test "$(file -b /etc/ssl/certs/java/cacerts)" = "Java KeyStore" +# Install ca-certificates-java so that the JVM buildpacks can configure Java apps to use the Java certs +# store in the base image instead of the one that ships in each JRE release, allowing certs to be updated +# via base image updates. Generation of the `cacerts` file occurs in a post-install script which only runs +# if a JRE is installed, however, we don't want a JRE in the final image so remove it afterwards. +apt-get install -y --no-install-recommends ca-certificates-java default-jre-headless +apt-get remove -y --purge --auto-remove default-jre-headless +# Check that the certs store (a) still exists after the removal of default-jre-headless, (b) uses the JKS +# format not PKCS12, since in the past there was an upstream regression for this: +# https://github.com/heroku/base-images/pull/103#issuecomment-389544431 +# https://bugs.launchpad.net/ubuntu/+source/ca-certificates-java/+bug/1771363 +test "$(file --brief /etc/ssl/certs/java/cacerts)" = "Java KeyStore" # Ubuntu 24.04 ships with a default user and group named 'ubuntu' (with user+group ID of 1000) # that we have to remove before creating our own (`userdel` will remove the group too).