|
1 | | -# The official Canonical Ubuntu Bionic image is ideal from a security perspective, |
| 1 | +# |
| 2 | +# NOTE: THIS DOCKERFILE IS GENERATED VIA "apply-templates.sh" |
| 3 | +# |
| 4 | +# PLEASE DO NOT EDIT IT DIRECTLY. |
| 5 | +# |
| 6 | + |
| 7 | +# The official Canonical Ubuntu Focal image is ideal from a security perspective, |
2 | 8 | # especially for the enterprises that we, the RabbitMQ team, have to deal with |
3 | | -FROM ubuntu:20.04 |
4 | | - |
5 | | -RUN set -eux; \ |
6 | | - apt-get update; \ |
7 | | - apt-get install -y lsb-release ubuntu-dbgsym-keyring; \ |
8 | | - echo "deb http://ddebs.ubuntu.com $(lsb_release -cs) main restricted universe multiverse" > /etc/apt/sources.list.d/ddebs.list; \ |
9 | | - echo "deb http://ddebs.ubuntu.com $(lsb_release -cs)-updates main restricted universe multiverse" >> /etc/apt/sources.list.d/ddebs.list; \ |
10 | | - echo "deb http://ddebs.ubuntu.com $(lsb_release -cs)-proposed main restricted universe multiverse" >> /etc/apt/sources.list.d/ddebs.list; \ |
11 | | - apt-get update; \ |
12 | | - apt-get install -y --no-install-recommends \ |
13 | | - libc6-dbg \ |
14 | | - libtinfo6-dbgsym |
| 9 | + |
| 10 | +FROM ubuntu:22.04 as build-base |
| 11 | + |
| 12 | +ARG BUILDKIT_SBOM_SCAN_STAGE=true |
| 13 | + |
| 14 | +RUN set -eux; \ |
| 15 | + apt-get update; \ |
| 16 | + apt-get install -y --no-install-recommends \ |
| 17 | + build-essential \ |
| 18 | + ca-certificates \ |
| 19 | + gnupg \ |
| 20 | + libncurses5-dev \ |
| 21 | + wget |
| 22 | + |
| 23 | +FROM build-base as openssl-builder |
| 24 | + |
| 25 | +ARG BUILDKIT_SBOM_SCAN_STAGE=true |
| 26 | + |
| 27 | +# Default to a PGP keyserver that pgp-happy-eyeballs recognizes, but allow for substitutions locally |
| 28 | +ARG PGP_KEYSERVER=keyserver.ubuntu.com |
| 29 | +# If you are building this image locally and are getting `gpg: keyserver receive failed: No data` errors, |
| 30 | +# run the build with a different PGP_KEYSERVER, e.g. docker build --tag rabbitmq:3.13 --build-arg PGP_KEYSERVER=pgpkeys.eu 3.13/ubuntu |
| 31 | +# For context, see https://github.com/docker-library/official-images/issues/4252 |
| 32 | + |
| 33 | +ENV OPENSSL_VERSION 3.1.5 |
| 34 | +ENV OPENSSL_SOURCE_SHA256="6ae015467dabf0469b139ada93319327be24b98251ffaeceda0221848dc09262" |
| 35 | +# https://www.openssl.org/community/otc.html |
| 36 | +# https://www.openssl.org/source/ |
| 37 | +ENV OPENSSL_PGP_KEY_IDS="0x8657ABB260F056B1E5190839D9C4D26D0E604491 0xB7C1C14360F353A36862E4D5231C84CDDCC69C45 0xC1F33DD8CE1D4CC613AF14DA9195C48241FBF7DD 0x95A9908DDFA16830BE9FB9003D30A3A9FF1360DC 0x7953AC1FBC3DC8B3B292393ED5E9E43F7DF9EE8C 0xA21FAB74B0088AA361152586B8EF1A6BA9DA2D5C 0xE5E52560DD91C556DDBDA5D02064C53641C25E5D 0xEFC0A467D613CB83C7ED6D30D894E2CE8B3D79F5" |
| 38 | + |
| 39 | +ENV OTP_VERSION 26.2.2 |
| 40 | +# TODO add PGP checking when the feature will be added to Erlang/OTP's build system |
| 41 | +# https://erlang.org/pipermail/erlang-questions/2019-January/097067.html |
| 42 | +ENV OTP_SOURCE_SHA256="d537ff4ac5d8c1cb507aedaf7198fc1f155ea8aa65a8d83edb35c2802763cc28" |
| 43 | + |
| 44 | +# install openssl & erlang to a path that isn't auto-checked for libs to prevent accidental use by system packages |
| 45 | +ENV ERLANG_INSTALL_PATH_PREFIX /opt/erlang |
| 46 | +ENV OPENSSL_INSTALL_PATH_PREFIX /opt/openssl |
| 47 | + |
| 48 | +# Install dependencies required to build Erlang/OTP from source |
| 49 | +# https://erlang.org/doc/installation_guide/INSTALL.html |
| 50 | +# dpkg-dev: Required to set up host & build type when compiling Erlang/OTP |
| 51 | +# gnupg: Required to verify OpenSSL artefacts |
| 52 | +# libncurses5-dev: Required for Erlang/OTP new shell & observer_cli - https://github.com/zhongwencool/observer_cli |
| 53 | +RUN set -eux; \ |
| 54 | + OPENSSL_SOURCE_URL="https://www.openssl.org/source/openssl-$OPENSSL_VERSION.tar.gz"; \ |
| 55 | + OPENSSL_PATH="/usr/local/src/openssl-$OPENSSL_VERSION"; \ |
| 56 | + OPENSSL_CONFIG_DIR="$OPENSSL_INSTALL_PATH_PREFIX/etc/ssl"; \ |
| 57 | + \ |
| 58 | +# Required by the crypto & ssl Erlang/OTP applications |
| 59 | + wget --progress dot:giga --output-document "$OPENSSL_PATH.tar.gz.asc" "$OPENSSL_SOURCE_URL.asc"; \ |
| 60 | + wget --progress dot:giga --output-document "$OPENSSL_PATH.tar.gz" "$OPENSSL_SOURCE_URL"; \ |
| 61 | + export GNUPGHOME="$(mktemp -d)"; \ |
| 62 | + for key in $OPENSSL_PGP_KEY_IDS; do \ |
| 63 | + gpg --batch --keyserver "$PGP_KEYSERVER" --recv-keys "$key"; \ |
| 64 | + done; \ |
| 65 | + gpg --batch --verify "$OPENSSL_PATH.tar.gz.asc" "$OPENSSL_PATH.tar.gz"; \ |
| 66 | + gpgconf --kill all; \ |
| 67 | + rm -rf "$GNUPGHOME"; \ |
| 68 | + echo "$OPENSSL_SOURCE_SHA256 *$OPENSSL_PATH.tar.gz" | sha256sum --check --strict -; \ |
| 69 | + mkdir -p "$OPENSSL_PATH"; \ |
| 70 | + tar --extract --file "$OPENSSL_PATH.tar.gz" --directory "$OPENSSL_PATH" --strip-components 1; \ |
| 71 | + \ |
| 72 | +# Configure OpenSSL for compilation |
| 73 | + cd "$OPENSSL_PATH"; \ |
| 74 | +# without specifying "--libdir", Erlang will fail during "crypto:supports()" looking for a "pthread_atfork" function that doesn't exist (but only on arm32v7/armhf??) |
| 75 | +# OpenSSL's "config" script uses a lot of "uname"-based target detection... |
| 76 | + dpkgArch="$(dpkg --print-architecture)"; dpkgArch="${dpkgArch##*-}"; \ |
| 77 | +# https://deb.debian.org/debian/dists/unstable/main/ |
| 78 | + case "$dpkgArch" in \ |
| 79 | +# https://github.com/openssl/openssl/blob/openssl-3.1.1/Configurations/10-main.conf#L860 (look for "linux-" and "linux64-" keys) |
| 80 | + amd64) opensslMachine='linux-x86_64' ;; \ |
| 81 | + arm64) opensslMachine='linux-aarch64' ;; \ |
| 82 | +# https://github.com/openssl/openssl/blob/openssl-3.1.1/Configurations/10-main.conf#L736-L766 |
| 83 | +# https://wiki.debian.org/ArchitectureSpecificsMemo#Architecture_baselines |
| 84 | +# https://gcc.gnu.org/onlinedocs/gcc/ARM-Options.html |
| 85 | + armhf) opensslMachine='linux-armv4'; opensslExtraConfig='-march=armv7-a+fp' ;; \ |
| 86 | + i386) opensslMachine='linux-x86' ;; \ |
| 87 | + ppc64el) opensslMachine='linux-ppc64le' ;; \ |
| 88 | + riscv64) opensslMachine='linux64-riscv64' ;; \ |
| 89 | + s390x) opensslMachine='linux64-s390x' ;; \ |
| 90 | + *) echo >&2 "error: unsupported arch: '$apkArch'"; exit 1 ;; \ |
| 91 | + esac; \ |
| 92 | + MACHINE="$opensslMachine" \ |
| 93 | + RELEASE="4.x.y-z" \ |
| 94 | + SYSTEM='Linux' \ |
| 95 | + BUILD='???' \ |
| 96 | + ./Configure \ |
| 97 | + "$opensslMachine" \ |
| 98 | + enable-fips \ |
| 99 | + --prefix="$OPENSSL_INSTALL_PATH_PREFIX" \ |
| 100 | + --openssldir="$OPENSSL_CONFIG_DIR" \ |
| 101 | + --libdir="$OPENSSL_INSTALL_PATH_PREFIX/lib" \ |
| 102 | +# add -rpath to avoid conflicts between our OpenSSL's "libssl.so" and the libssl package by making sure "$INSTALL_PATH_PREFIX/lib" is searched first (but only for Erlang/OpenSSL to avoid issues with other tools using libssl; https://github.com/docker-library/rabbitmq/issues/364) |
| 103 | + -Wl,-rpath="$OPENSSL_INSTALL_PATH_PREFIX/lib" \ |
| 104 | + ${opensslExtraConfig:-} \ |
| 105 | + ; \ |
| 106 | +# Compile, install OpenSSL, verify that the command-line works & development headers are present |
| 107 | + make -j "$(getconf _NPROCESSORS_ONLN)"; \ |
| 108 | + make install_sw install_ssldirs install_fips; \ |
| 109 | + ldconfig; \ |
| 110 | +# use Debian's CA certificates |
| 111 | + rmdir "$OPENSSL_CONFIG_DIR/certs" "$OPENSSL_CONFIG_DIR/private"; \ |
| 112 | + ln -sf /etc/ssl/certs /etc/ssl/private "$OPENSSL_CONFIG_DIR" |
| 113 | + |
| 114 | +# smoke test |
| 115 | +RUN $OPENSSL_INSTALL_PATH_PREFIX/bin/openssl version |
| 116 | + |
| 117 | +FROM openssl-builder as erlang-builder |
| 118 | + |
| 119 | +ARG BUILDKIT_SBOM_SCAN_STAGE=true |
| 120 | + |
| 121 | +RUN set -eux; \ |
| 122 | + OTP_SOURCE_URL="https://github.com/erlang/otp/releases/download/OTP-$OTP_VERSION/otp_src_$OTP_VERSION.tar.gz"; \ |
| 123 | + OTP_PATH="/usr/local/src/otp-$OTP_VERSION"; \ |
| 124 | + \ |
| 125 | +# Download, verify & extract OTP_SOURCE |
| 126 | + mkdir -p "$OTP_PATH"; \ |
| 127 | + wget --progress dot:giga --output-document "$OTP_PATH.tar.gz" "$OTP_SOURCE_URL"; \ |
| 128 | + echo "$OTP_SOURCE_SHA256 *$OTP_PATH.tar.gz" | sha256sum --check --strict -; \ |
| 129 | + tar --extract --file "$OTP_PATH.tar.gz" --directory "$OTP_PATH" --strip-components 1; \ |
| 130 | + \ |
| 131 | +# Configure Erlang/OTP for compilation, disable unused features & applications |
| 132 | +# https://erlang.org/doc/applications.html |
| 133 | +# ERL_TOP is required for Erlang/OTP makefiles to find the absolute path for the installation |
| 134 | + cd "$OTP_PATH"; \ |
| 135 | + export ERL_TOP="$OTP_PATH"; \ |
| 136 | + CFLAGS="$(dpkg-buildflags --get CFLAGS)"; export CFLAGS; \ |
| 137 | +# add -rpath to avoid conflicts between our OpenSSL's "libssl.so" and the libssl package by making sure "$OPENSSL_INSTALL_PATH_PREFIX/lib" is searched first (but only for Erlang/OpenSSL to avoid issues with other tools using libssl; https://github.com/docker-library/rabbitmq/issues/364) |
| 138 | + export CFLAGS="$CFLAGS -Wl,-rpath=$OPENSSL_INSTALL_PATH_PREFIX/lib"; \ |
| 139 | + hostArch="$(dpkg-architecture --query DEB_HOST_GNU_TYPE)"; \ |
| 140 | + buildArch="$(dpkg-architecture --query DEB_BUILD_GNU_TYPE)"; \ |
| 141 | + dpkgArch="$(dpkg --print-architecture)"; dpkgArch="${dpkgArch##*-}"; \ |
| 142 | +# JIT is only supported on amd64 + arm64; https://github.com/erlang/otp/blob/OTP-25.3.2.2/erts/configure#L24306-L24347 |
| 143 | + jitFlag=; \ |
| 144 | + case "$dpkgArch" in \ |
| 145 | + amd64 | arm64) jitFlag='--enable-jit' ;; \ |
| 146 | + esac; \ |
| 147 | + ./configure \ |
| 148 | + --prefix="$ERLANG_INSTALL_PATH_PREFIX" \ |
| 149 | + --host="$hostArch" \ |
| 150 | + --build="$buildArch" \ |
| 151 | + --disable-hipe \ |
| 152 | + --disable-sctp \ |
| 153 | + --disable-silent-rules \ |
| 154 | + --enable-builtin-zlib \ |
| 155 | + --enable-clock-gettime \ |
| 156 | + --enable-hybrid-heap \ |
| 157 | + --enable-kernel-poll \ |
| 158 | + --enable-smp-support \ |
| 159 | + --enable-threads \ |
| 160 | + --with-microstate-accounting=extra \ |
| 161 | + --with-ssl="$OPENSSL_INSTALL_PATH_PREFIX" \ |
| 162 | + --without-common_test \ |
| 163 | + --without-debugger \ |
| 164 | + --without-dialyzer \ |
| 165 | + --without-diameter \ |
| 166 | + --without-edoc \ |
| 167 | + --without-erl_docgen \ |
| 168 | + --without-et \ |
| 169 | + --without-eunit \ |
| 170 | + --without-ftp \ |
| 171 | + --without-hipe \ |
| 172 | + --without-jinterface \ |
| 173 | + --without-megaco \ |
| 174 | + --without-observer \ |
| 175 | + --without-odbc \ |
| 176 | + --without-reltool \ |
| 177 | + --without-ssh \ |
| 178 | + --without-tftp \ |
| 179 | + --without-wx \ |
| 180 | + $jitFlag \ |
| 181 | + ; \ |
| 182 | + \ |
| 183 | +# Compile & install Erlang/OTP |
| 184 | + make -j "$(getconf _NPROCESSORS_ONLN)" GEN_OPT_FLGS="-O2 -fno-strict-aliasing"; \ |
| 185 | + make install; \ |
| 186 | + \ |
| 187 | +# Remove unnecessary files |
| 188 | + find "$ERLANG_INSTALL_PATH_PREFIX/lib/erlang" -type d -name examples -exec rm -rf '{}' +; \ |
| 189 | + find "$ERLANG_INSTALL_PATH_PREFIX/lib/erlang" -type d -name src -exec rm -rf '{}' +; \ |
| 190 | + find "$ERLANG_INSTALL_PATH_PREFIX/lib/erlang" -type d -name include -exec rm -rf '{}' + |
| 191 | + |
| 192 | +# Check that Erlang/OTP crypto & ssl were compiled against OpenSSL correctly |
| 193 | +ENV PATH $ERLANG_INSTALL_PATH_PREFIX/bin:$PATH |
| 194 | +RUN find $ERLANG_INSTALL_PATH_PREFIX -type f -name 'crypto.so' -exec ldd {} \; | awk '/libcrypto\.so/ { if (!index($3,ENVIRON["OPENSSL_INSTALL_PATH_PREFIX"])) exit 1 }' |
| 195 | +RUN erl -noshell -eval 'ok = crypto:start(), ok = io:format("~p~n~n~p~n~n", [crypto:supports(), ssl:versions()]), init:stop().' |
| 196 | + |
| 197 | +FROM ubuntu:22.04 |
| 198 | + |
| 199 | +# OPENSSL/ERLANG_INSTALL_PATH_PREFIX are defined in a different stage, so define them again |
| 200 | +ENV ERLANG_INSTALL_PATH_PREFIX /opt/erlang |
| 201 | +ENV OPENSSL_INSTALL_PATH_PREFIX /opt/openssl |
| 202 | +COPY --from=erlang-builder $ERLANG_INSTALL_PATH_PREFIX $ERLANG_INSTALL_PATH_PREFIX |
| 203 | +RUN echo '{"spdxVersion":"SPDX-2.3","SPDXID":"SPDXRef-DOCUMENT","name":"erlang-sbom","packages":[{"name":"erlang","versionInfo":"26.2.2","SPDXID":"SPDXRef-Package--erlang","externalRefs":[{"referenceCategory":"PACKAGE-MANAGER","referenceType":"purl","referenceLocator":"pkg:generic/[email protected]?os_name=ubuntu&os_version=22.04"}],"licenseDeclared":"Apache-2.0"}]}' > $ERLANG_INSTALL_PATH_PREFIX/erlang.spdx.json |
| 204 | + |
| 205 | +COPY --from=openssl-builder $OPENSSL_INSTALL_PATH_PREFIX $OPENSSL_INSTALL_PATH_PREFIX |
| 206 | +RUN echo '{"spdxVersion":"SPDX-2.3","SPDXID":"SPDXRef-DOCUMENT","name":"openssl-sbom","packages":[{"name":"openssl","versionInfo":"3.1.5","SPDXID":"SPDXRef-Package--openssl","externalRefs":[{"referenceCategory":"PACKAGE-MANAGER","referenceType":"purl","referenceLocator":"pkg:generic/[email protected]?os_name=ubuntu&os_version=22.04"}],"licenseDeclared":"Apache-2.0"}]}' > $OPENSSL_INSTALL_PATH_PREFIX/openssl.spdx.json |
| 207 | + |
| 208 | +ENV PATH $ERLANG_INSTALL_PATH_PREFIX/bin:$OPENSSL_INSTALL_PATH_PREFIX/bin:$PATH |
| 209 | + |
| 210 | +ENV RABBITMQ_DATA_DIR /var/lib/rabbitmq |
| 211 | + |
| 212 | +RUN set -eux; \ |
| 213 | +# Configure OpenSSL to use system certs |
| 214 | + ln -vsf /etc/ssl/certs /etc/ssl/private "$OPENSSL_INSTALL_PATH_PREFIX/etc/ssl"; \ |
| 215 | + \ |
| 216 | +# Check that OpenSSL still works after copying from previous builder |
| 217 | + ldconfig; \ |
| 218 | + sed -i.ORIG -e "/\.include.*fips/ s!.*!.include $OPENSSL_INSTALL_PATH_PREFIX/etc/ssl/fipsmodule.cnf!" \ |
| 219 | + -e '/# fips =/s/.*/fips = fips_sect/' "$OPENSSL_INSTALL_PATH_PREFIX/etc/ssl/openssl.cnf"; \ |
| 220 | + sed -i.ORIG -e '/^activate/s/^/#/' "$OPENSSL_INSTALL_PATH_PREFIX/etc/ssl/fipsmodule.cnf"; \ |
| 221 | + [ "$(command -v openssl)" = "$OPENSSL_INSTALL_PATH_PREFIX/bin/openssl" ]; \ |
| 222 | + openssl version; \ |
| 223 | + openssl version -d; \ |
| 224 | + \ |
| 225 | +# Check that Erlang/OTP crypto & ssl were compiled against OpenSSL correctly |
| 226 | + erl -noshell -eval 'ok = crypto:start(), ok = io:format("~p~n~n~p~n~n", [crypto:supports(), ssl:versions()]), init:stop().'; \ |
| 227 | + \ |
| 228 | +# Create rabbitmq system user & group, fix permissions & allow root user to connect to the RabbitMQ Erlang VM |
| 229 | + groupadd --gid 999 --system rabbitmq; \ |
| 230 | + useradd --uid 999 --system --home-dir "$RABBITMQ_DATA_DIR" --gid rabbitmq rabbitmq; \ |
| 231 | + mkdir -p "$RABBITMQ_DATA_DIR" /etc/rabbitmq /etc/rabbitmq/conf.d /tmp/rabbitmq-ssl /var/log/rabbitmq; \ |
| 232 | + chown -fR rabbitmq:rabbitmq "$RABBITMQ_DATA_DIR" /etc/rabbitmq /etc/rabbitmq/conf.d /tmp/rabbitmq-ssl /var/log/rabbitmq; \ |
| 233 | + chmod 1777 "$RABBITMQ_DATA_DIR" /etc/rabbitmq /etc/rabbitmq/conf.d /tmp/rabbitmq-ssl /var/log/rabbitmq; \ |
| 234 | + ln -sf "$RABBITMQ_DATA_DIR/.erlang.cookie" /root/.erlang.cookie |
0 commit comments