From a719e4dfbc20814f8bfe67c04d1434fe5fa32c11 Mon Sep 17 00:00:00 2001
From: "Guillaume B.B. Van Hemmen" <GuillaumeHemmen@noreply.git.van-hemmen.com>
Date: Mon, 19 May 2025 11:31:45 +0000
Subject: [PATCH] #4 - CI pipeline & Dockerfile hardening: env var rename,
 extended logging, POSIX shell, privilege drop (#5)

This PR closes #4 by renaming the GitHub Actions variable from GITHUB_REF_NAME to GIT_REF_NAME, fixing secrets and artifact destination paths, and adding detailed logging of environment variables and build actions for easier troubleshooting. It also updates the Dockerfile to run installation steps as root but switches to a non-root user for runtime, and replaces the shell with a strictly POSIX-compliant variant to improve portability and security.

Reviewed-on: https://git.van-hemmen.com/actions/kaniko/pulls/5
Co-authored-by: Guillaume B.B. Van Hemmen <GuillaumeHemmen@noreply.git.van-hemmen.com>
Co-committed-by: Guillaume B.B. Van Hemmen <GuillaumeHemmen@noreply.git.van-hemmen.com>
---
 Dockerfile |  9 ++++--
 README.md  | 14 ++++-----
 build.sh   | 85 +++++++++++++++++++++++++++++-------------------------
 3 files changed, 58 insertions(+), 50 deletions(-)

diff --git a/Dockerfile b/Dockerfile
index 848d6f9..64e7e13 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -34,11 +34,14 @@ LABEL \
 #-----------------------------------------------------------------------------
 # Copy artefacts & make the wrapper executable
 #-----------------------------------------------------------------------------
-COPY build.sh /usr/local/bin/build.sh
+COPY --chmod=0755 build.sh /bin/build.sh
 COPY LICENSE  /LICENSE
-RUN chmod +x /usr/local/bin/build.sh
+RUN chmod +x /bin/build.sh
+
+# Drop root privileges (UID 1000 exists in the base image)
+USER 0
 
 #-----------------------------------------------------------------------------
 # Runtime entrypoint
 #-----------------------------------------------------------------------------
-ENTRYPOINT ["/usr/local/bin/build.sh"]
+ENTRYPOINT ["/bin/build.sh"]
diff --git a/README.md b/README.md
index c31fdab..f9e8ebf 100644
--- a/README.md
+++ b/README.md
@@ -47,15 +47,15 @@ jobs:
         env:
           # --- mandatory --------------------------------------------------------
           KANIKO_CONTEXT: git://git.van-hemmen.com/actions/kaniko.git
-          GITHUB_REF_NAME: ${{ github.ref_name }}
-          GIT_USERNAME:    ${{ secrets.GIT_USERNAME }}
-          GIT_PASSWORD:    ${{ secrets.GIT_PASSWORD }}
+          GIT_REF_NAME:    ${{ github.ref_name }}
+          GIT_USERNAME:    ${{ secrets.docker_username }}
+          GIT_PASSWORD:    ${{ secrets.access_token }}
     
           # --- optional (only needed when you plan to push) ---------------------
           REGISTRY_HOST:   ghcr.io
-          REGISTRY_USER:   ${{ secrets.REGISTRY_USER }}
-          REGISTRY_PASS:   ${{ secrets.REGISTRY_PASS }}
-          KANIKO_DESTINATION: ghcr.io/myorg/myapp:${{ github.sha }}
+          REGISTRY_USER:   ${{ secrets.docker_username }}
+          REGISTRY_PASS:   ${{ secrets.access_token }}
+          KANIKO_DESTINATION: git.van-hemmen.com/myorg/myapp:${GITHUB_SHA}
     
           # --- fine-tuning ------------------------------------------------------
           KANIKO_DOCKERFILE: ./Dockerfile
@@ -68,7 +68,7 @@ jobs:
 | Variable | Required | Purpose | Example value                                                  |
 |----------|----------|---------|----------------------------------------------------------------|
 | `KANIKO_CONTEXT`  | **Yes** | Build context (`git://`). | `git://git.van-hemmen.com/actions/kaniko.git`                  |
-| `GITHUB_REF_NAME` | **Yes** | Branch or tag that is being built. | `${{ github.ref_name }}`                                                       |
+| `GIT_REF_NAME` | **Yes** | Branch or tag that is being built. | `${{ github.ref_name }}`                                                       |
 | `GIT_USERNAME`    | **Yes** | Username with access to `KANIKO_CONTEXT` when it is private. | `${{ secrets.GIT_USERNAME }}`                                  |
 | `GIT_PASSWORD`    | **Yes** | Token/password paired with `GIT_USERNAME`. | `${{ secrets.GIT_PASSWORD }}`                                  |
 | `REGISTRY_HOST`   | No (default `git.van-hemmen.com`) | Target registry hostname. | `ghcr.io`                                                      |
diff --git a/build.sh b/build.sh
index aa80200..ef16afb 100644
--- a/build.sh
+++ b/build.sh
@@ -1,28 +1,17 @@
-#!/usr/bin/env bash
-set -euo pipefail
+#!/bin/sh
+# BusyBox/dash-friendly: no “pipefail”, no “[[ … ]]”, no “+=”
+
+set -eu   # BusyBox ash does not support “pipefail”
 
 ###############################################################################
 # Mandatory variables – abort if not provided
 ###############################################################################
-if [[ -z "${KANIKO_CONTEXT:-}" ]]; then
-  echo "Error: KANIKO_CONTEXT environment variable is required but not set." >&2
-  exit 1
-fi
-
-if [[ -z "${GITHUB_REF_NAME:-}" ]]; then
-  echo "Error: GITHUB_REF_NAME environment variable is required but not set." >&2
-  exit 1
-fi
-
-if [[ -z "${GIT_USERNAME:-}" ]]; then
-  echo "Error: GIT_USERNAME environment variable is required but not set." >&2
-  exit 1
-fi
-
-if [[ -z "${GIT_PASSWORD:-}" ]]; then
-  echo "Error: GIT_PASSWORD environment variable is required but not set." >&2
-  exit 1
-fi
+for var in KANIKO_CONTEXT GIT_REF_NAME GIT_USERNAME GIT_PASSWORD; do
+  eval [ -z \"\${$var:-}\" ] && {
+    echo "Error: $var environment variable is required but not set." >&2
+    exit 1
+  }
+done
 
 ###############################################################################
 # Optional / defaulted variables
@@ -39,7 +28,7 @@ KANIKO_DOCKERFILE="${KANIKO_DOCKERFILE:-./Dockerfile}"
 # Handle registry authentication (only if credentials are present)
 ###############################################################################
 AUTH_ENABLED=false
-if [[ -n "${REGISTRY_USER}" && -n "${REGISTRY_PASS}" ]]; then
+if [ -n "${REGISTRY_USER}" ] && [ -n "${REGISTRY_PASS}" ]; then
   echo "Registry credentials supplied – configuring authentication for ${REGISTRY_HOST}"
   mkdir -p /kaniko/.docker
   cat > /kaniko/.docker/config.json <<EOF
@@ -62,35 +51,51 @@ fi
 ###############################################################################
 DEST_FLAGS=""
 
-# Push is only possible if we have BOTH credentials and at least one destination
-if $AUTH_ENABLED && [[ -n "${KANIKO_DESTINATION// }" ]]; then
+if $AUTH_ENABLED && [ -n "${KANIKO_DESTINATION## }" ]; then
   echo "Building list of --destination flags"
-  OLD_IFS="$IFS"; IFS=','
-
+  old_ifs="$IFS"; IFS=','
   for raw in $KANIKO_DESTINATION; do
-    raw="$(echo "$raw" | xargs)"           # trim whitespace
-    expanded="$(eval echo "$raw")"         # expand variables
-    [[ -n "$expanded" ]] && DEST_FLAGS+=" --destination=${expanded}"
+    raw=$(echo "$raw" | xargs)            # trim
+    expanded=$(eval echo "$raw")          # env-var expansion if any
+    [ -n "$expanded" ] && DEST_FLAGS="$DEST_FLAGS --destination=$expanded"
   done
-
-  IFS="$OLD_IFS"
+  IFS="$old_ifs"
   echo "Image(s) will be pushed to the registry."
 else
   DEST_FLAGS="--no-push"
-  if ! $AUTH_ENABLED; then
-    echo "Image(s) will NOT be pushed because registry credentials are missing."
-  elif [[ -z "${KANIKO_DESTINATION// }" ]]; then
-    echo "KANIKO_DESTINATION not provided – image(s) will be built with --no-push."
-  fi
+  $AUTH_ENABLED  || echo "Registry credentials are missing – image(s) will not be pushed."
+  [ -n "${KANIKO_DESTINATION## }" ] || echo "KANIKO_DESTINATION not provided – using --no-push."
 fi
 
-echo "Kaniko will be called with: ${DEST_FLAGS}"
+echo "Kaniko will be called with:${DEST_FLAGS}"
+
+###############################################################################
+# resume what will be done
+###############################################################################
+echo "Environment Variables:"
+echo "KANIKO_CONTEXT=${KANIKO_CONTEXT}"
+echo "GIT_REF_NAME=${GIT_REF_NAME}"
+echo "GIT_USERNAME=${GIT_USERNAME}"
+echo "GIT_PASSWORD=$(echo "${GIT_PASSWORD}" | sed 's/\(^..\).*\(..$\)/\1...\2/')"
+echo "REGISTRY_HOST=${REGISTRY_HOST}"
+echo "REGISTRY_USER=${REGISTRY_USER}"
+[ -n "${REGISTRY_PASS}" ] && echo "REGISTRY_PASS=$(echo "${REGISTRY_PASS}" | sed 's/\(^..\).*\(..$\)/\1...\2/')"
+echo "KANIKO_DESTINATION=${KANIKO_DESTINATION}"
+echo "KANIKO_VERBOSITY=${KANIKO_VERBOSITY}"
+echo "KANIKO_DOCKERFILE=${KANIKO_DOCKERFILE}"
+echo ""
+if [ "${DEST_FLAGS}" = "--no-push" ]; then
+  echo "Action: Build only (no push)"
+else
+  echo "Action: Build and push"
+fi
+echo ""
 
 ###############################################################################
 # Invoke Kaniko
 ###############################################################################
-/kaniko/executor \
+exec /kaniko/executor \
   --verbosity="${KANIKO_VERBOSITY}" \
-  --context="${KANIKO_CONTEXT}#${GITHUB_REF_NAME}" \
+  --context="${KANIKO_CONTEXT}#${GIT_REF_NAME}" \
   --dockerfile="${KANIKO_DOCKERFILE}" \
-  ${DEST_FLAGS}
+  $DEST_FLAGS