From 692c066015a698d45eb11f18132cb1cb7809fd24 Mon Sep 17 00:00:00 2001 From: Malte Sander <malte.sander.it@gmail.com> Date: Mon, 7 Apr 2025 10:45:37 +0200 Subject: [PATCH 1/5] consolidate docker image with fix image size PRs --- airflow/Dockerfile | 99 ++++++++++++++++++++++++++-------------------- 1 file changed, 56 insertions(+), 43 deletions(-) diff --git a/airflow/Dockerfile b/airflow/Dockerfile index b0723fd73..41deca85a 100644 --- a/airflow/Dockerfile +++ b/airflow/Dockerfile @@ -28,6 +28,7 @@ ARG PRODUCT ARG STATSD_EXPORTER ARG PYTHON ARG TARGETARCH +ARG STACKABLE_USER_UID COPY airflow/constraints-${PRODUCT}-python${PYTHON}.txt /tmp/constraints.txt COPY --from=opa-auth-manager-builder /tmp/opa-auth-manager/dist/opa_auth_manager-0.1.0-py3-none-any.whl /tmp/ @@ -38,24 +39,24 @@ ENV AIRFLOW_EXTRAS=async,amazon,celery,cncf.kubernetes,docker,dask,elasticsearch RUN microdnf update && \ microdnf install \ - cyrus-sasl-devel \ - # Needed by ./configure to build gevent, see snippet [1] at the end of file - diffutils \ - # Needed to build gevent, see snippet [1] at the end of file - make \ - gcc \ - gcc-c++ \ - libpq-devel \ - openldap-devel \ - openssl-devel \ - python${PYTHON} \ - python${PYTHON}-devel \ - python${PYTHON}-pip \ - python${PYTHON}-wheel \ - # The airflow odbc provider can compile without the development files (headers and libraries) (see https://github.com/stackabletech/docker-images/pull/683) - unixODBC \ - # Needed to modify the SBOM - jq && \ + cyrus-sasl-devel \ + # Needed by ./configure to build gevent, see snippet [1] at the end of file + diffutils \ + # Needed to build gevent, see snippet [1] at the end of file + make \ + gcc \ + gcc-c++ \ + libpq-devel \ + openldap-devel \ + openssl-devel \ + python${PYTHON} \ + python${PYTHON}-devel \ + python${PYTHON}-pip \ + python${PYTHON}-wheel \ + # The airflow odbc provider can compile without the development files (headers and libraries) (see https://github.com/stackabletech/docker-images/pull/683) + unixODBC \ + # Needed to modify the SBOM + jq && \ microdnf clean all && \ rm -rf /var/cache/yum @@ -85,9 +86,17 @@ else end)' /tmp/sbom.json > /stackable/app/airflow-${PRODUCT}.cdx.json EOF -WORKDIR /stackable COPY --from=statsd_exporter-builder /statsd_exporter/statsd_exporter /stackable/statsd_exporter COPY --from=statsd_exporter-builder /statsd_exporter/statsd_exporter-${STATSD_EXPORTER}.cdx.json /stackable/statsd_exporter-${STATSD_EXPORTER}.cdx.json +COPY --from=gitsync-image --chown=${STACKABLE_USER_UID}:0 /git-sync /stackable/git-sync + +RUN <<EOF +mkdir -pv /stackable/airflow +mkdir -pv /stackable/airflow/dags +mkdir -pv /stackable/airflow/logs +chmod --recursive g=u /stackable +EOF + FROM stackable/image/vector AS airflow-main-image @@ -99,22 +108,26 @@ ARG TARGETARCH ARG STACKABLE_USER_UID LABEL name="Apache Airflow" \ - maintainer="info@stackable.tech" \ - vendor="Stackable GmbH" \ - version="${PRODUCT}" \ - release="${RELEASE}" \ - summary="The Stackable image for Apache Airflow." \ - description="This image is deployed by the Stackable Operator for Apache Airflow." - -COPY airflow/licenses /licenses -COPY --chown=${STACKABLE_USER_UID}:0 airflow/stackable/utils/entrypoint.sh /entrypoint.sh -COPY --chown=${STACKABLE_USER_UID}:0 airflow/stackable/utils/run-airflow.sh /run-airflow.sh + maintainer="info@stackable.tech" \ + vendor="Stackable GmbH" \ + version="${PRODUCT}" \ + release="${RELEASE}" \ + summary="The Stackable image for Apache Airflow." \ + description="This image is deployed by the Stackable Operator for Apache Airflow." ENV HOME=/stackable ENV AIRFLOW_USER_HOME_DIR=/stackable ENV PATH=$PATH:/bin:$HOME/app/bin ENV AIRFLOW_HOME=$HOME/airflow +COPY --from=airflow-build-image --chown=${STACKABLE_USER_UID}:0 /stackable/ ${HOME}/ +COPY --from=airflow-build-image --chown=${STACKABLE_USER_UID}:0 /stackable/git-sync ${HOME}/git-sync + +COPY --chown=${STACKABLE_USER_UID}:0 airflow/stackable/utils/entrypoint.sh /entrypoint.sh +COPY --chown=${STACKABLE_USER_UID}:0 airflow/stackable/utils/run-airflow.sh /run-airflow.sh + +COPY airflow/licenses /licenses + # Update image and install needed packages RUN <<EOF microdnf update @@ -142,33 +155,33 @@ rm -rf /var/cache/yum # Get the correct `tini` binary for our architecture. # It is used as an init alternative in the entrypoint curl -o /usr/bin/tini "https://repo.stackable.tech/repository/packages/tini/tini-${TINI}-${TARGETARCH}" + +# fix missing permissions chmod a+x /entrypoint.sh chmod a+x /run-airflow.sh chmod +x /usr/bin/tini +EOF -mkdir -pv ${AIRFLOW_HOME} -mkdir -pv ${AIRFLOW_HOME}/dags -mkdir -pv ${AIRFLOW_HOME}/logs +# ---------------------------------------- +# Checks +# This section is to run final checks to ensure the created final images +# adhere to several minimal requirements like: +# - check file permissions and ownerships +# ---------------------------------------- -# All files and folders owned by root to support running as arbitrary users -# This is best practice as all container users will belong to the root group (0) -chown -R ${STACKABLE_USER_UID}:0 /stackable -chmod -R g=u /stackable +# Check that permissions and ownership in /stackable are set correctly +# This will fail and stop the build if any mismatches are found. +RUN <<EOF +/bin/check-permissions-ownership.sh ${HOME} ${STACKABLE_USER_UID} 0 EOF # ---------------------------------------- -# Attention: We are changing the group of all files in /stackable directly above -# If you do any file based actions (copying / creating etc.) below this comment you -# absolutely need to make sure that the correct permissions are applied! -# chown ${STACKABLE_USER_UID}:0 +# Attention: Do not perform any file based actions (copying/creating etc.) below this comment because the permissions would not be checked. # ---------------------------------------- USER ${STACKABLE_USER_UID} WORKDIR /stackable -COPY --from=airflow-build-image --chown=${STACKABLE_USER_UID}:0 /stackable/ ${HOME}/ -COPY --from=gitsync-image --chown=${STACKABLE_USER_UID}:0 /git-sync /stackable/git-sync - ENTRYPOINT ["/usr/bin/tini", "--", "/run-airflow.sh"] CMD [] From b1fcb9d9525c7ed92d8d8ccfdeb041bd7018ec2b Mon Sep 17 00:00:00 2001 From: Malte Sander <malte.sander.it@gmail.com> Date: Mon, 7 Apr 2025 10:47:05 +0200 Subject: [PATCH 2/5] adapted changelog --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6a75fa8f5..c2b071f6b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,8 @@ All notable changes to this project will be documented in this file. ### Added +- airflow: check for correct permissions and ownerships in /stackable folder via + `check-permissions-ownership.sh` provided in stackable-base image ([#1054]). - spark-connect-client: A new image for Spark connect tests and demos ([#1034]) - nifi: check for correct permissions and ownerships in /stackable folder via `check-permissions-ownership.sh` provided in stackable-base image ([#1027]). @@ -26,6 +28,7 @@ All notable changes to this project will be documented in this file. [#1042]: https://github.com/stackabletech/docker-images/pull/1042 [#1044]: https://github.com/stackabletech/docker-images/pull/1044 [#1050]: https://github.com/stackabletech/docker-images/pull/1050 +[#1054]: https://github.com/stackabletech/docker-images/pull/1054 ## [25.3.0] - 2025-03-21 From 9c8db9d54839cc2093a51f7b0386656477bd6048 Mon Sep 17 00:00:00 2001 From: Malte Sander <malte.sander.it@gmail.com> Date: Mon, 7 Apr 2025 10:48:05 +0200 Subject: [PATCH 3/5] fix comment --- airflow/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/airflow/Dockerfile b/airflow/Dockerfile index 41deca85a..84c67067e 100644 --- a/airflow/Dockerfile +++ b/airflow/Dockerfile @@ -169,7 +169,7 @@ EOF # - check file permissions and ownerships # ---------------------------------------- -# Check that permissions and ownership in /stackable are set correctly +# Check that permissions and ownership in ${HOME} are set correctly # This will fail and stop the build if any mismatches are found. RUN <<EOF /bin/check-permissions-ownership.sh ${HOME} ${STACKABLE_USER_UID} 0 From 970d43e5d8957437201051157cefaac26852843a Mon Sep 17 00:00:00 2001 From: Malte Sander <malte.sander.it@gmail.com> Date: Mon, 7 Apr 2025 15:08:29 +0200 Subject: [PATCH 4/5] fix intendation --- airflow/Dockerfile | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/airflow/Dockerfile b/airflow/Dockerfile index 84c67067e..951f07ea9 100644 --- a/airflow/Dockerfile +++ b/airflow/Dockerfile @@ -39,24 +39,24 @@ ENV AIRFLOW_EXTRAS=async,amazon,celery,cncf.kubernetes,docker,dask,elasticsearch RUN microdnf update && \ microdnf install \ - cyrus-sasl-devel \ - # Needed by ./configure to build gevent, see snippet [1] at the end of file - diffutils \ - # Needed to build gevent, see snippet [1] at the end of file - make \ - gcc \ - gcc-c++ \ - libpq-devel \ - openldap-devel \ - openssl-devel \ - python${PYTHON} \ - python${PYTHON}-devel \ - python${PYTHON}-pip \ - python${PYTHON}-wheel \ - # The airflow odbc provider can compile without the development files (headers and libraries) (see https://github.com/stackabletech/docker-images/pull/683) - unixODBC \ - # Needed to modify the SBOM - jq && \ + cyrus-sasl-devel \ + # Needed by ./configure to build gevent, see snippet [1] at the end of file + diffutils \ + # Needed to build gevent, see snippet [1] at the end of file + make \ + gcc \ + gcc-c++ \ + libpq-devel \ + openldap-devel \ + openssl-devel \ + python${PYTHON} \ + python${PYTHON}-devel \ + python${PYTHON}-pip \ + python${PYTHON}-wheel \ + # The airflow odbc provider can compile without the development files (headers and libraries) (see https://github.com/stackabletech/docker-images/pull/683) + unixODBC \ + # Needed to modify the SBOM + jq && \ microdnf clean all && \ rm -rf /var/cache/yum From b5c03340fc661d68d15f7abb1ee6c1a31a0e3bcc Mon Sep 17 00:00:00 2001 From: Malte Sander <malte.sander.it@gmail.com> Date: Wed, 9 Apr 2025 08:47:36 +0200 Subject: [PATCH 5/5] improve check permissions script performance (@siggi) --- shared/checks/check-permissions-ownership.sh | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/shared/checks/check-permissions-ownership.sh b/shared/checks/check-permissions-ownership.sh index 7b34009f7..f5cff9e71 100755 --- a/shared/checks/check-permissions-ownership.sh +++ b/shared/checks/check-permissions-ownership.sh @@ -29,27 +29,29 @@ EXPECTED_GID=$3 error_flag=0 # Check ownership -while IFS= read -r -d '' file; do - uid=$(stat -c "%u" "$file") - gid=$(stat -c "%g" "$file") +while IFS= read -r -d '' entry; do + uid=${entry%% *} + remainder=${entry#* } + gid=${remainder%% *} if [[ "$uid" -ne "$EXPECTED_UID" || "$gid" -ne "$EXPECTED_GID" ]]; then + file=${remainder#* } echo "Ownership mismatch: $file (Expected: $EXPECTED_UID:$EXPECTED_GID, Found: $uid:$gid)" error_flag=1 fi -done < <(find "$DIRECTORY" -print0) +done < <(find "$DIRECTORY" -printf "%U %G %p\0") # Check permissions -while IFS= read -r -d '' file; do - perms=$(stat -c "%A" "$file") - owner_perms="${perms:1:3}" - group_perms="${perms:4:3}" +while IFS= read -r -d '' entry; do + owner_perms="${entry:1:3}" + group_perms="${entry:4:3}" if [[ "$owner_perms" != "$group_perms" ]]; then + file="${entry:11}" echo "Permission mismatch: $file (Owner: $owner_perms, Group: $group_perms)" error_flag=1 fi -done < <(find "$DIRECTORY" -print0) +done < <(find "$DIRECTORY" -printf "%M %p\0") if [[ $error_flag -ne 0 ]]; then echo "Permission and Ownership checks failed for $DIRECTORY!"