From 53bcdafe91757b719da07b60d60d6ee4500fc8f6 Mon Sep 17 00:00:00 2001 From: Shrikant Sharat Kandula Date: Fri, 6 Oct 2023 19:38:19 +0530 Subject: [PATCH] fix: Get Java from GitHub release artifacts directly (#27862) What are we solving here? 1. Installing Java in the `Dockerfile` by using Adoptium's package repositories is fragile since they've started blocking some IP addresses used by GitHub Actions runners. We see a message like this: ``` Failed to fetch https://packages.adoptium.net/artifactory/deb/pool/main/t/temurin-17/temurin-17-jdk_17.0.8.1.0+1_amd64.deb 403 Forbidden [IP: 146.75.107.42 443] ``` We're seeing more and more cases of these and PRs are getting blocked. 2. Installing Java via `apt` also installs other packages like X11 libraries, that aren't really relevant to our usage of Java. Yet, these packages are present in our Docker image, and are the source of several CVEs to be reported by scanners on our Docker image. 3. This will give us control over trusted CA certificates, which we can now perform under `$TMP`, which aligns with our move towards supporting readonly root filesystem. Which is essentially not write to anything in the Docker image at runtime, except for under `/tmp` and `/appsmith-stacks`. This will help us move in that direction. --- Dockerfile | 17 +++++---- deploy/docker/fs/opt/appsmith/entrypoint.sh | 40 ++++++++++++++++++--- deploy/docker/fs/opt/appsmith/run-java.sh | 22 +++++++----- 3 files changed, 60 insertions(+), 19 deletions(-) diff --git a/Dockerfile b/Dockerfile index ac00f440db..cf0f664378 100644 --- a/Dockerfile +++ b/Dockerfile @@ -15,10 +15,7 @@ RUN apt-get update \ && DEBIAN_FRONTEND=noninteractive apt-get install --no-install-recommends --yes \ supervisor curl cron nfs-common nginx nginx-extras gnupg wget netcat openssh-client \ gettext \ - python3-pip python3-venv git ca-certificates-java \ - && wget -O - https://packages.adoptium.net/artifactory/api/gpg/key/public | apt-key add - \ - && echo "deb https://packages.adoptium.net/artifactory/deb $(awk -F= '/^VERSION_CODENAME/{print$2}' /etc/os-release) main" | tee /etc/apt/sources.list.d/adoptium.list \ - && apt-get update && apt-get install --no-install-recommends --yes temurin-17-jdk \ + python3-pip python3-venv git ca-certificates \ && pip install --no-cache-dir git+https://github.com/coderanger/supervisor-stdout@973ba19967cdaf46d9c1634d1675fc65b9574f6e \ && python3 -m venv --prompt certbot /opt/certbot/venv \ && /opt/certbot/venv/bin/pip install --upgrade certbot setuptools pip \ @@ -38,6 +35,14 @@ RUN curl --silent --show-error --location https://www.mongodb.org/static/pgp/ser # This is to get semver 7.5.2, for a CVE fix, might be able to remove it with later versions on NodeJS. && npm install -g npm@9.7.2 +# Install Java +RUN set -o xtrace \ + && mkdir -p /opt/java \ + # Assets from https://github.com/adoptium/temurin17-binaries/releases + && version="$(curl --write-out '%{redirect_url}' 'https://github.com/adoptium/temurin17-binaries/releases/latest' | sed 's,.*jdk-,,')" \ + && curl --location --output /tmp/java.tar.gz "https://github.com/adoptium/temurin17-binaries/releases/download/jdk-$version/OpenJDK17U-jdk_$(uname -m | sed s/x86_64/x64/)_linux_hotspot_$(echo $version | tr + _).tar.gz" \ + && tar -xzf /tmp/java.tar.gz -C /opt/java --strip-components 1 + # Clean up cache file - Service layer RUN rm -rf \ /root/.cache \ @@ -87,8 +92,8 @@ RUN cd ./utils && npm install --only=prod && npm install --only=prod -g . && cd && find / \( -path /proc -prune \) -o \( \( -perm -2000 -o -perm -4000 \) -print -exec chmod -s '{}' + \) || true \ && node prepare-image.mjs -# Update path to load appsmith utils tool as default -ENV PATH /opt/appsmith/utils/node_modules/.bin:$PATH +ENV PATH /opt/appsmith/utils/node_modules/.bin:/opt/java/bin:$PATH + LABEL com.centurylinklabs.watchtower.lifecycle.pre-check=/watchtower-hooks/pre-check.sh LABEL com.centurylinklabs.watchtower.lifecycle.pre-update=/watchtower-hooks/pre-update.sh diff --git a/deploy/docker/fs/opt/appsmith/entrypoint.sh b/deploy/docker/fs/opt/appsmith/entrypoint.sh index e10a810ceb..0e104b0319 100644 --- a/deploy/docker/fs/opt/appsmith/entrypoint.sh +++ b/deploy/docker/fs/opt/appsmith/entrypoint.sh @@ -255,6 +255,7 @@ is_empty_directory() { } check_setup_custom_ca_certificates() { + # old, deprecated, should be removed. local stacks_ca_certs_path stacks_ca_certs_path="$stacks_path/ca-certs" @@ -279,13 +280,42 @@ check_setup_custom_ca_certificates() { fi - if [[ -n "$(ls "$stacks_ca_certs_path"/*.pem 2>/dev/null)" ]]; then - echo "Looks like you have some '.pem' files in your 'ca-certs' folder. Please rename them to '.crt' to be picked up autatically.". - fi - update-ca-certificates --fresh } +setup-custom-ca-certificates() ( + local stacks_ca_certs_path="$stacks_path/ca-certs" + local store="$TMP/cacerts" + local opts_file="$TMP/java-cacerts-opts" + + rm -f "$store" "$opts_file" + + if [[ -n "$(ls "$stacks_ca_certs_path"/*.pem 2>/dev/null)" ]]; then + echo "Looks like you have some '.pem' files in your 'ca-certs' folder. Please rename them to '.crt' to be picked up automatically.". + fi + + if ! [[ -d "$stacks_ca_certs_path" && "$(find "$stacks_ca_certs_path" -maxdepth 1 -type f -name '*.crt' | wc -l)" -gt 0 ]]; then + echo "No custom CA certificates found." + return + fi + + # Import the system CA certificates into the store. + keytool -importkeystore \ + -srckeystore /opt/java/lib/security/cacerts \ + -destkeystore "$store" \ + -srcstorepass changeit \ + -deststorepass changeit + + # Add the custom CA certificates to the store. + find "$stacks_ca_certs_path" -maxdepth 1 -type f -name '*.crt' \ + -exec keytool -import -noprompt -keystore "$store" -file '{}' -storepass changeit ';' + + { + echo "-Djavax.net.ssl.trustStore=$store" + echo "-Djavax.net.ssl.trustStorePassword=changeit" + } > "$opts_file" +) + configure_supervisord() { local supervisord_conf_source="/opt/appsmith/templates/supervisord" if [[ -n "$(ls -A "$SUPERVISORD_CONF_TARGET")" ]]; then @@ -438,6 +468,8 @@ else fi check_setup_custom_ca_certificates +setup-custom-ca-certificates + mount_letsencrypt_directory check_redis_compatible_page_size diff --git a/deploy/docker/fs/opt/appsmith/run-java.sh b/deploy/docker/fs/opt/appsmith/run-java.sh index 99ec07dde0..9f310c21e8 100755 --- a/deploy/docker/fs/opt/appsmith/run-java.sh +++ b/deploy/docker/fs/opt/appsmith/run-java.sh @@ -5,7 +5,7 @@ set -o pipefail set -o nounset set -o noglob -declare -a proxy_args +declare -a extra_args proxy_configured=0 match-proxy-url() { @@ -22,23 +22,23 @@ match-proxy-url() { } if match-proxy-url "${HTTP_PROXY-}"; then - proxy_args+=(-Dhttp.proxyHost="$proxy_host" -Dhttp.proxyPort="$proxy_port") + extra_args+=(-Dhttp.proxyHost="$proxy_host" -Dhttp.proxyPort="$proxy_port") if [[ -n $proxy_user ]]; then - proxy_args+=(-Dhttp.proxyUser="$proxy_user") + extra_args+=(-Dhttp.proxyUser="$proxy_user") fi if [[ -n $proxy_pass ]]; then - proxy_args+=(-Dhttp.proxyPassword="$proxy_pass") + extra_args+=(-Dhttp.proxyPassword="$proxy_pass") fi proxy_configured=1 fi if match-proxy-url "${HTTPS_PROXY-}"; then - proxy_args+=(-Dhttps.proxyHost="$proxy_host" -Dhttps.proxyPort="$proxy_port") + extra_args+=(-Dhttps.proxyHost="$proxy_host" -Dhttps.proxyPort="$proxy_port") if [[ -n $proxy_user ]]; then - proxy_args+=(-Dhttps.proxyUser="$proxy_user") + extra_args+=(-Dhttps.proxyUser="$proxy_user") fi if [[ -n $proxy_pass ]]; then - proxy_args+=(-Dhttps.proxyPassword="$proxy_pass") + extra_args+=(-Dhttps.proxyPassword="$proxy_pass") fi proxy_configured=1 fi @@ -50,7 +50,11 @@ if [[ -z "${NO_PROXY-}" ]]; then fi if [[ $proxy_configured == 1 ]]; then - proxy_args+=(-Djava.net.useSystemProxies=true -Dhttp.nonProxyHosts="${NO_PROXY//,/|}") + extra_args+=(-Djava.net.useSystemProxies=true -Dhttp.nonProxyHosts="${NO_PROXY//,/|}") +fi + +if [[ -f "$TMP/java-cacerts-opts" ]]; then + extra_args+=("@$TMP/java-cacerts-opts") fi # Wait until RTS started and listens on port 8091 @@ -69,5 +73,5 @@ exec java ${APPSMITH_JAVA_ARGS:-} ${APPSMITH_JAVA_HEAP_ARG:-} \ -XX:+ShowCodeDetailsInExceptionMessages \ -Djava.security.egd=file:/dev/./urandom \ -Dlog4j2.formatMsgNoLookups=true \ - "${proxy_args[@]}" \ + "${extra_args[@]}" \ -jar server.jar