From 76c7ea948d7c0e0dde018972e2d32ccceda3bcbf Mon Sep 17 00:00:00 2001 From: Ed Morley <501702+edmorley@users.noreply.github.com> Date: Wed, 27 Mar 2024 14:34:59 +0000 Subject: [PATCH] Heroku-24: Use the same user for the run and build images (#281) The upstream CNB spec recently changed to say that build and run images `SHOULD` use a separate Linux user for each image: https://github.com/buildpacks/rfcs/blob/main/text/0085-run-uid.md https://github.com/buildpacks/spec/blob/platform/0.13/platform.md#run-image However, this causes a number of compatibility issues with existing apps and parts of the ecosystem (see #268). Whilst we can (and will) adjust our own buildpacks to do the right thing (not write to `/layers/` or the app source directory at runtime), it's going to be some time before existing apps/frameworks/... make similar changes. In addition, the failure modes are not easy for users to debug or solve (they will have to know that seeing access denied errors means needing to use `chmod` to make directories group writeable in an inline buildpack step or similar). As such, we're deferring making this switch for now, and will revisit in the future (either for Heroku-26, or as an opt-in feature for Heroku-24), when the various third party language ecosystems are more ready for this. We will still be in compliance with the spec, since it says `SHOULD` not `MUST`. We will also add integration testing to our own CNBs to ensure that they operate correctly in environments that do run split build/run users. As part of this change, I've also switched the `heroku` user's ID back to 1000, for consistency with the Heroku-20/22 CNB base images. I've also switched back to the `USER ` syntax instead of `USER `, since both are permitted by the OCI and CNB specs, and the former is (a) IMO more intuitive (eg for users needing to switch to `root` and back in their own `Dockerfile`), (b) matches what Heroku-20/22 do. See also: https://manpages.ubuntu.com/manpages/noble/en/man8/userdel.8.html https://manpages.ubuntu.com/manpages/noble/en/man8/groupadd.8.html Closes #268. GUS-W-15342842. --- heroku-20-cnb-build/Dockerfile | 3 +-- heroku-22-cnb-build/Dockerfile | 3 +-- heroku-24-build/Dockerfile | 6 +++--- heroku-24/Dockerfile | 2 +- heroku-24/setup.sh | 10 ++++++---- 5 files changed, 12 insertions(+), 12 deletions(-) diff --git a/heroku-20-cnb-build/Dockerfile b/heroku-20-cnb-build/Dockerfile index 33928801..c5a62f7c 100644 --- a/heroku-20-cnb-build/Dockerfile +++ b/heroku-20-cnb-build/Dockerfile @@ -7,6 +7,7 @@ RUN groupadd heroku --gid 1000 \ && chown heroku:heroku /app # https://github.com/buildpacks/spec/blob/platform/0.13/platform.md#build-image +USER heroku ENV CNB_USER_ID=1000 ENV CNB_GROUP_ID=1000 # Note: This image doesn't inherit from the CNB run image variant so we have @@ -20,5 +21,3 @@ LABEL io.buildpacks.base.maintainer="Heroku" # https://github.com/buildpacks/spec/blob/platform/0.13/platform.md#iobuildpacksstack-labels ENV CNB_STACK_ID="heroku-20" LABEL io.buildpacks.stack.id="heroku-20" - -USER heroku diff --git a/heroku-22-cnb-build/Dockerfile b/heroku-22-cnb-build/Dockerfile index f1e6b502..b1c018ac 100644 --- a/heroku-22-cnb-build/Dockerfile +++ b/heroku-22-cnb-build/Dockerfile @@ -7,6 +7,7 @@ RUN groupadd heroku --gid 1000 \ && chown heroku:heroku /app # https://github.com/buildpacks/spec/blob/platform/0.13/platform.md#build-image +USER heroku ENV CNB_USER_ID=1000 ENV CNB_GROUP_ID=1000 # Note: This image doesn't inherit from the CNB run image variant so we have @@ -20,5 +21,3 @@ LABEL io.buildpacks.base.maintainer="Heroku" # https://github.com/buildpacks/spec/blob/platform/0.13/platform.md#iobuildpacksstack-labels ENV CNB_STACK_ID="heroku-22" LABEL io.buildpacks.stack.id="heroku-22" - -USER heroku diff --git a/heroku-24-build/Dockerfile b/heroku-24-build/Dockerfile index 3f19763c..a965f590 100644 --- a/heroku-24-build/Dockerfile +++ b/heroku-24-build/Dockerfile @@ -1,14 +1,14 @@ ARG BASE_IMAGE=heroku/heroku:24 FROM $BASE_IMAGE -# We have to temporarily switch back to root, since the run image sets a non-root default USER. +# We have to temporarily switch back to root, since the run image sets a non-root default `USER`. USER root RUN --mount=target=/build /build/setup.sh # https://github.com/buildpacks/spec/blob/platform/0.13/platform.md#build-image # The `io.buildpacks.base.*` labels are inherited from the run image, so don't need to be repeated here. -USER 1002 -ENV CNB_USER_ID=1002 +USER heroku +ENV CNB_USER_ID=1000 ENV CNB_GROUP_ID=1000 # Stack IDs are deprecated, but we still set this for backwards compatibility: diff --git a/heroku-24/Dockerfile b/heroku-24/Dockerfile index fd896b6f..476e6549 100644 --- a/heroku-24/Dockerfile +++ b/heroku-24/Dockerfile @@ -3,7 +3,7 @@ FROM ubuntu:24.04 RUN --mount=target=/build /build/setup.sh # https://github.com/buildpacks/spec/blob/platform/0.13/platform.md#run-image -USER 1001 +USER heroku LABEL io.buildpacks.base.distro.name="ubuntu" LABEL io.buildpacks.base.distro.version="24.04" LABEL io.buildpacks.base.homepage="https://github.com/heroku/base-images" diff --git a/heroku-24/setup.sh b/heroku-24/setup.sh index b80d3538..fc460ca2 100755 --- a/heroku-24/setup.sh +++ b/heroku-24/setup.sh @@ -189,10 +189,12 @@ apt-get purge -y openjdk-8-jre-headless apt-get autoremove -y --purge test "$(file -b /etc/ssl/certs/java/cacerts)" = "Java KeyStore" -useradd heroku --uid 1001 --gid 1000 --shell /bin/bash --create-home -useradd heroku-build --uid 1002 --gid 1000 --shell /bin/bash --create-home -groupmod --new-name heroku ubuntu -deluser --remove-home ubuntu +# 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). +userdel ubuntu --remove + +groupadd heroku --gid 1000 +useradd heroku --uid 1000 --gid 1000 --shell /bin/bash --create-home rm -rf /root/* rm -rf /tmp/*