- CI pipeline & Dockerfile hardening: env var rename, extended logging, POSIX shell, privilege drop #5

Merged
GuillaumeHemmen merged 5 commits from 4-script-is-not-found into master 2025-05-19 11:31:46 +00:00
3 changed files with 58 additions and 50 deletions

View file

@ -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"]

View file

@ -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` |

View file

@ -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