Skip to content
Draft
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
126 changes: 108 additions & 18 deletions Earthfile
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,10 @@ ARG IS_UKI=false
ARG INCLUDE_MS_SECUREBOOT_KEYS=true
ARG AUTO_ENROLL_SECUREBOOT_KEYS=false
ARG UKI_BRING_YOUR_OWN_KEYS=false
# When UKI_BRING_YOUR_OWN_KEYS=true, set false to skip merging Spectro extension cert into db
ARG ENROLL_SPECTRO_EXTENSION_CERT=false
# OCI image (scratch) with palette-sysext-cert.pem; merged into UEFI db during +uki-genkey
ARG SPECTRO_EXTENSION_CERT_IMAGE=us-east1-docker.pkg.dev/spectro-images/dev/arun/sysext/palette-sysext-cert:latest

ARG CMDLINE="stylus.registration"
ARG BRANDING="Palette eXtended Kubernetes Edge"
Expand Down Expand Up @@ -118,8 +122,7 @@ IF [ "$OS_DISTRIBUTION" = "ubuntu" ] && [ "$BASE_IMAGE" = "" ]
ELSE IF [ "$OS_DISTRIBUTION" = "opensuse-leap" ] && [ "$BASE_IMAGE" = "" ]
ARG BASE_IMAGE_TAG=kairos-opensuse:leap-$OS_VERSION-core-$ARCH-generic-$KAIROS_VERSION
ARG BASE_IMAGE=$KAIROS_BASE_IMAGE_URL/$BASE_IMAGE_TAG
ELSE IF [ "$OS_DISTRIBUTION" = "rhel" ] || [ "$OS_DISTRIBUTION" = "sles" ]
# Check for default value for rhel
ELSE
ARG BASE_IMAGE
END

Expand Down Expand Up @@ -203,6 +206,24 @@ BASE_ALPINE:
COPY --if-exists certs/ /etc/ssl/certs/
RUN update-ca-certificates


CHECK_SYSTEMD_VERSION:
COMMAND
RUN SYSTEMCTL="" && \
for c in systemctl /usr/bin/systemctl /bin/systemctl /usr/local/bin/systemctl /usr/sbin/systemctl /sbin/systemctl /usr/local/sbin/systemctl; do \
if command -v "$c" >/dev/null 2>&1; then SYSTEMCTL="$c"; break; fi; \
done && \
SYSTEMD_VER=$([ -n "$SYSTEMCTL" ] && "$SYSTEMCTL" --version 2>/dev/null | awk 'NR==1{print $2}') && \
case "$SYSTEMD_VER" in ''|*[!0-9]*) SYSTEMD_VER=0 ;; esac && \
echo "CHECK_SYSTEMD_VERSION: detected systemd version $SYSTEMD_VER (systemctl: ${SYSTEMCTL:-not found})" && \
if [ "$SYSTEMD_VER" -gt "252" ]; then \
mkdir -p /etc/spectrocloud && \
touch /etc/spectrocloud/.support-systemd-extensions && \
echo "CHECK_SYSTEMD_VERSION: systemd > 252 — created /etc/spectrocloud/.support-systemd-extensions"; \
else \
echo "CHECK_SYSTEMD_VERSION: systemd <= 252 — skipping systemd-extensions marker"; \
fi

iso-image-rootfs:
FROM --platform=linux/${ARCH} +iso-image
SAVE ARTIFACT --keep-ts --keep-own /. rootfs
Expand All @@ -224,7 +245,11 @@ uki-provider-image:
COPY (+third-party/luet --binary=luet) /usr/bin/luet
COPY +kairos-agent/kairos-agent /usr/bin/kairos-agent
COPY --platform=linux/${ARCH} +trust-boot-unpack/ /trusted-boot
COPY --keep-ts --platform=linux/${ARCH} +install-k8s/output/ /k8s
DO +CHECK_SYSTEMD_VERSION
IF [ ! -f /etc/spectrocloud/.support-systemd-extensions ]
COPY --keep-ts --platform=linux/${ARCH} +install-k8s/output/ /k8s
END
RUN rm -f /etc/spectrocloud/.support-systemd-extensions
COPY --if-exists "$EDGE_CUSTOM_CONFIG" /oem/.edge_custom_config.yaml
COPY --if-exists +stylus-image/etc/kairos/80_stylus.yaml /etc/kairos/80_stylus.yaml
SAVE IMAGE --push $IMAGE_PATH
Expand Down Expand Up @@ -440,6 +465,10 @@ uki-genkey:
RUN --no-cache mkdir -p /public-keys
RUN --no-cache cd /keys; mv *.key tpm2-pcr-private.pem /private-keys
RUN --no-cache cd /keys; mv *.pem /public-keys
DO +enroll-spectro-extension-cert \
--ENROLLMENT_DIR=/keys \
--KEK_CERT=/public-keys/KEK.pem \
--KEK_KEY=/private-keys/KEK.key
ELSE
COPY +uki-byok/ /keys
END
Expand All @@ -456,6 +485,36 @@ download-sbctl:
RUN curl -Ls https://github.com/Foxboron/sbctl/releases/download/0.13/sbctl-0.13-linux-amd64.tar.gz | tar -xvzf - && mv sbctl/sbctl /usr/bin/sbctl
SAVE ARTIFACT /usr/bin/sbctl

spectro-extension-cert:
FROM --platform=linux/${ARCH} $SPECTRO_EXTENSION_CERT_IMAGE
SAVE ARTIFACT /palette-sysext-cert.pem cert.pem

spectro-extension-cert-esl:
FROM --platform=linux/${ARCH} $ALPINE_IMG
DO +BASE_ALPINE
RUN apk add --no-cache efitools
COPY +spectro-extension-cert/cert.pem /cert/spectro-cert.pem
RUN cert-to-efi-sig-list -g 8be4df61-93ca-11d2-aa0d-00e098032b8c \
/cert/spectro-cert.pem /cert/spectro-db.esl
SAVE ARTIFACT /cert/spectro-db.esl spectro-db.esl

# Self-contained merge of the Spectro extension cert into the UEFI db enrollment
# material. Gated on ENROLL_SPECTRO_EXTENSION_CERT: when true, it fetches the ESL,
# appends it to db.esl and (re)generates db.auth/db.der so the db is fully ready;
# when false it is a no-op.
enroll-spectro-extension-cert:
COMMAND
ARG ENROLLMENT_DIR
ARG KEK_CERT
ARG KEK_KEY
IF [ "$ENROLL_SPECTRO_EXTENSION_CERT" = "true" ]
COPY +spectro-extension-cert-esl/spectro-db.esl /spectro/spectro-db.esl
RUN cat /spectro/spectro-db.esl >> "$ENROLLMENT_DIR/db.esl" && \
sign-efi-sig-list -c "$KEK_CERT" -k "$KEK_KEY" db "$ENROLLMENT_DIR/db.esl" "$ENROLLMENT_DIR/db.auth" && \
cd "$ENROLLMENT_DIR" && sig-list-to-certs 'db.esl' 'db' && \
(cp db-0.der db.der 2>/dev/null || true)
END

uki-byok:
FROM +ubuntu

Expand Down Expand Up @@ -486,6 +545,11 @@ uki-byok:
RUN [ -f /exported-keys/db ] && cat /exported-keys/db >> /output/db.esl || true
RUN [ -f /exported-keys/dbx ] && cat /exported-keys/dbx >> /output/dbx.esl || true

DO +enroll-spectro-extension-cert \
--ENROLLMENT_DIR=/output \
--KEK_CERT=/keys/KEK.pem \
--KEK_KEY=/keys/KEK.key

WORKDIR /output
RUN sign-efi-sig-list -c /keys/PK.pem -k /keys/PK.key PK PK.esl PK.auth
RUN sign-efi-sig-list -c /keys/PK.pem -k /keys/PK.key KEK KEK.esl KEK.auth
Expand Down Expand Up @@ -585,18 +649,22 @@ provider-image:
COPY +stylus-image/etc/elemental/config.yaml /etc/elemental/config.yaml
COPY --if-exists "$EDGE_CUSTOM_CONFIG" /oem/.edge_custom_config.yaml

IF [ "$IS_UKI" = "true" ]
COPY +internal-slink/slink /usr/bin/slink
COPY --keep-ts +install-k8s/output/ /k8s
RUN slink --source /k8s/ --target /opt/k8s
RUN rm -f /usr/bin/slink
RUN rm -rf /k8s
RUN ln -sf /opt/spectrocloud/bin/agent-provider-stylus /usr/local/bin/agent-provider-stylus
ELSE
COPY --keep-ts +install-k8s/output/ /
# As part of PE-8315, kairos-provider binaries are in /usr/local/system/providers instead of earlier /system/providers.
# To avoid breaking existing functionality for non systemd extensions supported paths we move the binary back to original path.
IF [ ! -f /etc/spectrocloud/.support-systemd-extensions ]
IF [ "$IS_UKI" = "true" ]
COPY +internal-slink/slink /usr/bin/slink
COPY --keep-ts +install-k8s/output/ /k8s
RUN slink --source /k8s/ --target /opt/k8s
RUN rm -f /usr/bin/slink
RUN rm -rf /k8s
RUN ln -sf /opt/spectrocloud/bin/agent-provider-stylus /usr/local/bin/agent-provider-stylus
ELSE
COPY --keep-ts +install-k8s/output/ /
END
END

RUN rm -f /etc/ssh/ssh_host_* /etc/ssh/moduli
RUN rm -f /etc/ssh/ssh_host_* /etc/ssh/moduli /etc/spectrocloud/.support-systemd-extensions

COPY (+third-party/etcdctl --binary=etcdctl) /usr/bin/

Expand Down Expand Up @@ -692,6 +760,15 @@ kairos-provider-image:
ARG PROVIDER_BASE=$SPECTRO_PUB_REPO/edge/kairos-io/provider-canonical:$CANONICAL_PROVIDER_VERSION
END
FROM --platform=linux/${ARCH} $PROVIDER_BASE
# Newer kairos providers place agent-provider-* at /usr/local/system/providers/
# instead of /system/providers/. Move to /system/providers/ and remove the new
# path so consumers always find the binary at the legacy location.
RUN PROVIDER_NAME=$(basename /usr/local/system/providers/agent-provider-* 2>/dev/null || true) && \
if [ -n "$PROVIDER_NAME" ] && [ ! -f "/system/providers/$PROVIDER_NAME" ]; then \
mkdir -p /system/providers && \
mv /usr/local/system/providers/$PROVIDER_NAME /system/providers/$PROVIDER_NAME && \
rm -rf /usr/local/system/providers; \
fi
SAVE ARTIFACT ./*

# base build image used to create the base image for all other image types
Expand All @@ -701,6 +778,8 @@ base-image:
--build-arg HTTP_PROXY=$HTTP_PROXY --build-arg HTTPS_PROXY=$HTTPS_PROXY \
--build-arg NO_PROXY=$NO_PROXY --build-arg DRBD_VERSION=$DRBD_VERSION .

DO +CHECK_SYSTEMD_VERSION

IF [ "$IS_JETSON" = "true" ]
COPY cloudconfigs/mount.yaml /etc/kairos/mount.yaml
END
Expand All @@ -716,15 +795,14 @@ base-image:

# OS == Ubuntu
IF [ "$OS_DISTRIBUTION" = "ubuntu" ] && [ "$ARCH" = "amd64" ]
RUN apt-get update && \
DEBIAN_FRONTEND=noninteractive apt-get install --no-install-recommends snapd kbd zstd vim iputils-ping bridge-utils curl tcpdump ethtool rsyslog logrotate -y

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
END

RUN apt-get update && \
DEBIAN_FRONTEND=noninteractive apt-get install --no-install-recommends kbd zstd vim iputils-ping bridge-utils curl tcpdump ethtool rsyslog logrotate -y

LET APT_UPGRADE_FLAGS="-y"
IF [ "$UPDATE_KERNEL" = "false" ]
RUN if dpkg -l "linux-image-generic-hwe-$OS_VERSION" > /dev/null; then apt-mark hold "linux-image-generic-hwe-$OS_VERSION" "linux-headers-generic-hwe-$OS_VERSION" "linux-generic-hwe-$OS_VERSION" ; fi && \
Expand Down Expand Up @@ -940,7 +1018,19 @@ iso-image:
fi
END

RUN rm -f /etc/ssh/ssh_host_* /etc/ssh/moduli
# When systemd >= 252, k8s is delivered via extensions at runtime.
# kubeadm preflight requires linux-headers to load the "configs" kernel module;
# install them in the installer image so kubeadm init succeeds.
IF [ -f /etc/spectrocloud/.support-systemd-extensions ] && \
[ "$OS_DISTRIBUTION" = "ubuntu" ] && \
[ "$ARCH" = "amd64" ]
RUN kernel=$(printf '%s\n' /lib/modules/* | xargs -n1 basename | sort -V | tail -1) && \
if ! ls /usr/src | grep -q "linux-headers-$kernel"; then \
apt-get update && apt-get install -y "linux-headers-${kernel}"; \
fi
END

RUN rm -f /etc/ssh/ssh_host_* /etc/ssh/moduli /etc/spectrocloud/.support-systemd-extensions
RUN touch /etc/machine-id \
&& chmod 444 /etc/machine-id

Expand Down
Empty file added hadron/Dockerfile
Empty file.
74 changes: 74 additions & 0 deletions hadron/Dockerfile.extras
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
ARG HADRON_VERSION=v0.3.3-rc2
ARG ARCH=amd64
ARG HADRON_TOOLCHAIN=ghcr.io/kairos-io/hadron-toolchain:${HADRON_VERSION}

FROM ${HADRON_TOOLCHAIN} AS downloader


WORKDIR /sources

ARG JQ_VERSION=1.8.1
ARG ARCH
RUN curl -fsSL "https://github.com/jqlang/jq/releases/download/jq-${JQ_VERSION}/jq-linux-${ARCH}" -o jq


ARG LIBTIRPC_VERSION=1.3.7
RUN curl -L "https://downloads.sourceforge.net/project/libtirpc/libtirpc/${LIBTIRPC_VERSION}/libtirpc-${LIBTIRPC_VERSION}.tar.bz2" -o libtirpc.tar.bz2

ARG CONNTRACK_VERSION=1.4.9
RUN curl -L "https://www.netfilter.org/pub/conntrack-tools/conntrack-tools-${CONNTRACK_VERSION}.tar.xz" -o conntrack-tools.tar.xz




FROM ${HADRON_TOOLCHAIN} AS libtirpc-builder
ARG TARGET_ARCH=x86-64
ARG BUILD_ARCH=x86_64

RUN mkdir -p /output/usr/include/sys
WORKDIR /sources

RUN mkdir -p /output/usr/include/sys && \
curl -fsSL https://gitlab.alpinelinux.org/alpine/aports/-/raw/master/main/bsd-compat-headers/cdefs.h \
-o /output/usr/include/sys/cdefs.h && \
curl -fsSL https://gitlab.alpinelinux.org/alpine/aports/-/raw/master/main/bsd-compat-headers/queue.h \
-o /output/usr/include/sys/queue.h && \
curl -fsSL https://gitlab.alpinelinux.org/alpine/aports/-/raw/master/main/bsd-compat-headers/tree.h \
-o /output/usr/include/sys/tree.h

COPY --from=downloader /sources/libtirpc.tar.bz2 /sources/libtirpc.tar.bz2

RUN tar -xf libtirpc.tar.bz2 && mv libtirpc-* libtirpc

WORKDIR /sources/libtirpc

## --enable-rpcdb forces libtirpc to ship the BSD RPC database functions
## (getrpcent/getrpcbyname/getrpcbynumber/setrpcent/endrpcent). They are
## OFF by default because glibc ships them in libc, but musl does not and
## nfs-utils' configure requires them. Without this flag, nfs-utils fails:
## configure: error: Neither getrpcbynumber_r nor getrpcbynumber are available
RUN ./configure ${COMMON_CONFIGURE_ARGS} \
--sysconfdir=/etc \
--disable-gssapi \
--disable-authdes \
--enable-rpcdb
RUN make -s -j${JOBS} -l${MAX_LOAD}
RUN make -s -j${JOBS} -l${MAX_LOAD} install DESTDIR=/libtirpc

FROM ${HADRON_TOOLCHAIN} AS conntrack-builder

COPY --from=libtirpc-builder /libtirpc /

WORKDIR /sources
COPY --from=downloader /sources/conntrack-tools.tar.xz /sources/conntrack-tools.tar.xz

RUN tar -xf conntrack-tools.tar.xz && mv conntrack-tools-* conntrack-tools

WORKDIR /sources/conntrack-tools

RUN ./configure --prefix=/output && make && make install


FROM scratch AS export
COPY --from=libtirpc-builder /libtirpc /
# COPY --from=conntrack-builder /output /
17 changes: 17 additions & 0 deletions hadron/build.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#!/usr/bin/env bash
set -euo pipefail

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"


ADDITIONAL_PACKAGES_IMAGE="${1:-us-east1-docker.pkg.dev/spectro-images/dev/arun/hadron/additional-packages:v0.3.3-rc2}"


DOCKER_BUILDKIT=1 docker build \
--progress=plain --no-cache \
-t "${ADDITIONAL_PACKAGES_IMAGE}" \
-f "${SCRIPT_DIR}/Dockerfile.extras" \
--load \
.

echo "Built ${ADDITIONAL_PACKAGES_IMAGE}"
19 changes: 19 additions & 0 deletions hadron/extras/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
ARG HADRON_VERSION=v0.3.3-rc2
ARG JQ_VERSION=1.8.1
ARG ARCH=amd64

FROM ghcr.io/kairos-io/hadron-toolchain:${HADRON_VERSION} AS builder

# Install jq
ARG JQ_VERSION
ARG ARCH
WORKDIR /output
RUN mkdir -p /output/usr/bin && \
curl -fsSL "https://github.com/jqlang/jq/releases/download/jq-${JQ_VERSION}/jq-linux-${ARCH}" -o /output/usr/bin/jq && \
chmod +x /output/usr/bin/jq

# Install rsyslog


FROM scratch AS export
COPY --from=builder /output /
1 change: 1 addition & 0 deletions hadron/extras/build.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

36 changes: 36 additions & 0 deletions hadron/fips/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
ARG EXTRAS_IMAGE=us-east1-docker.pkg.dev/spectro-images/dev/arun/hadron/extras-modules:v0.3.3-rc2
ARG BASE_IMAGE=ghcr.io/kairos-io/hadron-fips:v0.3.5
ARG KAIROS_INIT_VERSION=v0.14.4


FROM quay.io/kairos/kairos-init:${KAIROS_INIT_VERSION} AS kairos-init

FROM ${EXTRAS_IMAGE} AS extras

FROM ${BASE_IMAGE} AS base-kairos
ARG KAIROS_VERSION=v4.1.0

COPY --from=extras / /

RUN --mount=type=bind,from=kairos-init,src=/kairos-init,dst=/kairos-init \
/kairos-init -l debug -s install -m "generic" -t "false" --version "${KAIROS_VERSION}" --fips

RUN --mount=type=bind,from=kairos-init,src=/kairos-init,dst=/kairos-init \
/kairos-init -l debug -s init -m "generic" -t "false" --version "${KAIROS_VERSION}" --fips

# Regenerate the kernel HMAC for the FIPS boot-time integrity self-check.
# kairos-init's init stage (above) rebuilds the initrd and the /boot/vmlinuz +
# /boot/.vmlinuz.hmac symlinks, but leaves /boot/.vmlinuz-<kver>.hmac empty
# (0 bytes). When booted with fips=1, dracut's fips module (fips.sh) reads this
# file as HMAC_SUM_ORIG; an empty value fails the check and dracut aborts with
# "FIPS integrity test failed" / "Refusing to continue", halting boot in the
# initramfs before pivoting to the real root. This MUST be the final build step,
# i.e. after the init stage that re-empties the file, so the stored HMAC matches
# the shipped kernel.
# RUN kver="$(cat /boot/kernel-release 2>/dev/null || ls /lib/modules | sort -V | tail -1)" && \
# sha512hmac "/boot/vmlinuz-${kver}" | sed "s| .*/| /boot/|" > "/boot/.vmlinuz-${kver}.hmac" && \
# ln -sf "/boot/.vmlinuz-${kver}.hmac" /boot/.vmlinuz.hmac && \
# test -s "/boot/.vmlinuz-${kver}.hmac" && \
# echo "kernel HMAC regenerated for ${kver}: $(cat /boot/.vmlinuz-${kver}.hmac)"

# COPY stylus.conf /etc/ssh/sshd_config.d/stylus.conf
17 changes: 17 additions & 0 deletions hadron/fips/build.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#!/usr/bin/env bash
set -euo pipefail

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"

KAIROS_VERSION=v4.1.0
IMAGE="${1:-us-east1-docker.pkg.dev/spectro-images/dev/arun/base/hadron-fips-v0.3.5:${KAIROS_VERSION}}"

DOCKER_BUILDKIT=1 docker build \
--progress=plain \
--build-arg KAIROS_VERSION="${KAIROS_VERSION}" \
-f "${SCRIPT_DIR}/Dockerfile" \
-t "${IMAGE}" \
--push \
"${SCRIPT_DIR}"

echo "Built ${IMAGE}"
9 changes: 9 additions & 0 deletions hadron/fips/stylus.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Default algorithms favoring higher-performance FIPS algorithms
# in most cases.
Ciphers ^aes256-gcm@openssh.com,aes256-ctr,aes128-gcm@openssh.com,aes128-ctr
KexAlgorithms ^ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521
MACs ^hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com,hmac-sha2-256,hmac-sha2-512
HostKeyAlgorithms ^ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521,rsa-sha2-256,rsa-sha2-512

HostKey /etc/ssh/ssh_host_ecdsa_key
HostKey /etc/ssh/ssh_host_rsa_key
Loading