Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 24 additions & 2 deletions .arg.template
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,30 @@ FORCE_INTERACTIVE_INSTALL=false
# Interactive Install Configuration
# FORCE_INTERACTIVE_INSTALL=true # Set to true to choose interactive install as the default boot option and launch the Interactive Install TUI

# If you have Ubuntu Pro, use the UBUNTU_PRO_KEY variable to activate it as part of the image build
# UBUNTU_PRO_KEY=your-key
# Ubuntu Pro (optional)
# Do NOT put your Pro token in this file or in any build arg - it would end up
# in `docker history`, the Earthly build cache, and shell history.
#
# Recommended flow (use the earthly.sh wrapper):
# 1. Uncomment the toggle below:
# UBUNTU_PRO_ATTACH=true
# 2. Run the build as usual:
# ./earthly.sh +iso # or +base-image, +build-all-images, etc.
# The script will prompt for the token (input hidden, no echo) and forward
# it to Earthly as a secret. The token never lands in `.arg`, on the
# earthly command line, in `docker history`, or in shell history.
# 3. For non-interactive runs (CI), export UBUNTU_PRO_KEY before invoking the
# script and the prompt is skipped:
# read -rs UBUNTU_PRO_KEY && export UBUNTU_PRO_KEY
# ./earthly.sh +iso
# unset UBUNTU_PRO_KEY
#
# Note: `earthly secret set ...` requires Earthly Cloud (`earthly account login`)
# and is NOT available on a stock CLI install - use the earthly.sh flow above.
# Avoid `earthly --secret UBUNTU_PRO_KEY=<token>` on the command line: the token
# lands in your shell history and /proc/<pid>/cmdline.
#
# UBUNTU_PRO_ATTACH=true

# For enabling Secure Boot with Full Disk Encryption
# IS_UKI=true
Expand Down
47 changes: 40 additions & 7 deletions Earthfile
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,20 @@ ARG EDGE_CUSTOM_CONFIG=.edge-custom-config.yaml
ARG ARCH
ARG DISABLE_SELINUX=true
ARG CIS_HARDENING=false
ARG UBUNTU_PRO_KEY
# Ubuntu Pro toggle. The token itself is NEVER passed as a build arg.
# Recommended flow: use the earthly.sh wrapper. Set UBUNTU_PRO_ATTACH=true in
# .arg (or pass --UBUNTU_PRO_ATTACH=true on the CLI), then run e.g.
# ./earthly.sh +iso
# The wrapper prompts for the token without echoing it and forwards it as an
# Earthly --secret, so the value never lands in .arg, in `docker history`,
# in build-arg metadata, in the build cache, or in shell history.
# For non-interactive (CI) runs, export UBUNTU_PRO_KEY before invoking the
# script and the prompt is skipped:
# read -rs UBUNTU_PRO_KEY && export UBUNTU_PRO_KEY
# ./earthly.sh +iso
# Note: `earthly secret set ...` requires Earthly Cloud (earthly account login)
# and is not available on a stock CLI install - use the earthly.sh flow above.
ARG UBUNTU_PRO_ATTACH=false

# DRBD version for Piraeus pack
ARG DRBD_VERSION="9.2.13"
Expand Down Expand Up @@ -710,10 +723,23 @@ base-image:

# OS == Ubuntu
IF [ "$OS_DISTRIBUTION" = "ubuntu" ] && [ "$ARCH" = "amd64" ]
IF [ ! -z "$UBUNTU_PRO_KEY" ]
RUN sed -i '/^[[:space:]]*$/d' /etc/os-release && \
apt update && apt-get install -y snapd && \
pro attach $UBUNTU_PRO_KEY
IF [ "$UBUNTU_PRO_ATTACH" = "true" ]
# The token is mounted via Earthly's secret store as an env var
# that lives only for the duration of this RUN. It is materialized
# into an attach-config file using the shell builtin `printf`, so
# the value never appears in any process argv (/proc/<pid>/cmdline)
# or in docker build history. The env var is unset and the temp
# file removed before the RUN exits, so nothing about the token
# survives in the resulting layer. If `--secret UBUNTU_PRO_KEY`
# is not supplied, Earthly aborts before this RUN is invoked.
RUN --secret UBUNTU_PRO_KEY \
sed -i '/^[[:space:]]*$/d' /etc/os-release && \
apt-get update && apt-get install -y snapd && \
umask 077 && \
printf 'token: %s\n' "$UBUNTU_PRO_KEY" > /tmp/.pro-attach.yaml && \
unset UBUNTU_PRO_KEY && \
pro attach --attach-config /tmp/.pro-attach.yaml && \
rm -f /tmp/.pro-attach.yaml
END

RUN apt-get update && \
Expand Down Expand Up @@ -785,8 +811,15 @@ base-image:
RUN /tmp/harden.sh && rm /tmp/harden.sh
END

IF [ ! -z "$UBUNTU_PRO_KEY" ]
RUN pro detach --assume-yes
IF [ "$UBUNTU_PRO_ATTACH" = "true" ]
# Detach the entitlement, then scrub any on-disk traces. `pro` may
# echo or log token fragments under /var/log/ubuntu-advantage* and
# leave private state under /var/lib/ubuntu-advantage/private; we
# truncate those so the resulting image carries no residue.
RUN pro detach --assume-yes && \
find /var/log -maxdepth 3 -name 'ubuntu-advantage*' -type f -exec sh -c ': > "$1"' _ {} \; 2>/dev/null || true && \
rm -rf /var/lib/ubuntu-advantage/private 2>/dev/null || true && \
rm -f /tmp/.pro-attach.yaml 2>/dev/null || true
END

# OS == Opensuse
Expand Down
65 changes: 63 additions & 2 deletions earthly.sh
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,11 @@ function build_with_proxy() {
-e HTTP_PROXY="$HTTP_PROXY" \
-e NO_PROXY="$NO_PROXY" \
-e no_proxy="$NO_PROXY" \
"${DOCKER_SECRET_ENV[@]}" \
-v "$(pwd)":/workspace \
-v "$(pwd)/certs:/usr/local/share/ca-certificates:ro" \
--entrypoint /workspace/earthly-entrypoint.sh \
"$SPECTRO_PUB_REPO"/third-party/edge/earthly/earthly:"$EARTHLY_VERSION" --allow-privileged "$@"
"$SPECTRO_PUB_REPO"/third-party/edge/earthly/earthly:"$EARTHLY_VERSION" --allow-privileged "${EARTHLY_SECRET_ARGS[@]}" "$@"
}

function build_without_proxy() {
Expand All @@ -67,7 +68,7 @@ function build_without_proxy() {
fi

# Run Earthly in Docker to create artifacts Variables are passed from the .arg file
docker run --privileged ${DOCKER_CONFIG_MOUNT:+"$DOCKER_CONFIG_MOUNT"} -v /var/run/docker.sock:/var/run/docker.sock --rm --env EARTHLY_BUILD_ARGS -t -e GLOBAL_CONFIG="$global_config" -v "$(pwd)":/workspace "$SPECTRO_PUB_REPO"/third-party/edge/earthly/earthly:"$EARTHLY_VERSION" --allow-privileged "$@"
docker run --privileged ${DOCKER_CONFIG_MOUNT:+"$DOCKER_CONFIG_MOUNT"} -v /var/run/docker.sock:/var/run/docker.sock --rm --env EARTHLY_BUILD_ARGS -t -e GLOBAL_CONFIG="$global_config" "${DOCKER_SECRET_ENV[@]}" -v "$(pwd)":/workspace "$SPECTRO_PUB_REPO"/third-party/edge/earthly/earthly:"$EARTHLY_VERSION" --allow-privileged "${EARTHLY_SECRET_ARGS[@]}" "$@"
}

function print_os_pack() {
Expand Down Expand Up @@ -108,6 +109,66 @@ SPECTRO_PUB_REPO=us-docker.pkg.dev/palette-images
EARTHLY_VERSION=v0.8.15
source .arg

# ---------------------------------------------------------------------------
# Secret handling
#
# Some build inputs (currently only the Ubuntu Pro token) must NEVER appear in
# `docker history`, Earthly build-arg metadata, the build cache, shell history,
# or any process argv. We collect them here, prompt for any that aren't
# pre-exported, and forward them into the build via:
# - `docker run -e NAME` (no =value) -> passthrough into the earthly
# container's env
# - `earthly --secret NAME` (no =value) -> Earthly reads the value from
# its env and hands it to
# BuildKit as a secret, which
# the Earthfile consumes via
# `RUN --secret NAME ...`
# Both forms keep the value off the command line.
# ---------------------------------------------------------------------------
EARTHLY_SECRET_ARGS=()
DOCKER_SECRET_ENV=()

if [ "${UBUNTU_PRO_ATTACH:-false}" = "true" ]; then
# Catch the legacy pattern (token sitting in `.arg`) early - that's the
# exact thing we're trying to avoid.
if [ -f .arg ] && grep -qE '^[[:space:]]*UBUNTU_PRO_KEY[[:space:]]*=' .arg; then
echo >&2 "WARNING: UBUNTU_PRO_KEY is set in .arg. Remove it - tokens placed there"
echo >&2 " leak via the build cache and process listings. Provide it via"
echo >&2 " the UBUNTU_PRO_KEY env var or the interactive prompt instead."
fi

if [ -z "${UBUNTU_PRO_KEY:-}" ]; then
# Prompt without echoing. Prefer /dev/tty so the prompt works even when
# stdin has been redirected (common in CI wrappers).
if [ -r /dev/tty ] && [ -w /dev/tty ]; then
printf "Enter Ubuntu Pro token (input hidden): " >/dev/tty
stty -echo </dev/tty
IFS= read -r UBUNTU_PRO_KEY </dev/tty
stty echo </dev/tty
printf "\n" >/dev/tty
elif [ -t 0 ]; then
read -rs -p "Enter Ubuntu Pro token (input hidden): " UBUNTU_PRO_KEY
echo
else
echo >&2 "Error: UBUNTU_PRO_ATTACH=true but UBUNTU_PRO_KEY is not set and"
echo >&2 " no terminal is available to prompt for it. Export"
echo >&2 " UBUNTU_PRO_KEY before invoking earthly.sh, e.g.:"
echo >&2 " read -rs UBUNTU_PRO_KEY && export UBUNTU_PRO_KEY"
echo >&2 " ./earthly.sh +iso"
exit 1
fi
fi

if [ -z "${UBUNTU_PRO_KEY:-}" ]; then
echo >&2 "Error: Empty Ubuntu Pro token. Aborting."
exit 1
fi

export UBUNTU_PRO_KEY
DOCKER_SECRET_ENV=(-e UBUNTU_PRO_KEY)
EARTHLY_SECRET_ARGS=(--secret UBUNTU_PRO_KEY)
fi

# Workaround to support deprecated field PROXY_CERT_PATH
if [ -n "$PROXY_CERT_PATH" ]; then
echo "PROXY_CERT_PATH is deprecated. Please place your certificates in the certs directory."
Expand Down