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
45 changes: 45 additions & 0 deletions .github/workflows/build-pkcs11-image.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
name: Build and Push Docker Image to GHCR

on:
# Allows you to run this workflow manually from the Actions tab.
workflow_dispatch:

# Schedules the workflow to run at 03:00 UTC on every Sunday.
schedule:
- cron: "0 3 * * 0"

jobs:
build-and-push-image:
runs-on: ubuntu-latest

# Sets the permissions for the GITHUB_TOKEN to allow pushing to GHCR.
permissions:
contents: read
packages: write

steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Log in to the Container registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: "Extract metadata for Docker"
id: meta
uses: docker/metadata-action@v5
with:
images: ghcr.io/${{ github.repository_owner }}/ubuntu-keyvault-pkcs11-token

- name: Build and push Docker image
uses: docker/build-push-action@v5
with:
context: .
file: lib/Dockerfile.keyvault-pkcs11
push: true
# The tags and labels are generated by the metadata-action in the previous step.
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
21 changes: 20 additions & 1 deletion .github/workflows/release.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,19 @@ jobs:
continue-on-error: true

runs-on: ubuntu-24.04
container:
image: ghcr.io/flatcar/ubuntu-keyvault-pkcs11-token:main
options: >-
--privileged
-v ${{ github.workspace }}:${{ github.workspace }}
-v /tmp:/tmp
-w ${{ github.workspace }}
volumes:
- /var/run/docker.sock:/var/run/docker.sock
permissions:
# allow the action to create a release
contents: write
id-token: write
steps:
- name: Set up qemu / binmft misc for cross-platform builds
uses: docker/setup-qemu-action@v3
Expand All @@ -80,12 +90,21 @@ jobs:
xz-utils \
erofs-utils

- name: Azure Login
uses: azure/login@v1
with:
client-id: ${{ secrets.AZURE_CLIENT_ID }}
tenant-id: ${{ secrets.AZURE_TENANT_ID }}
subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}

- name: build
id: build
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
KEYVAULT_NAME: ${{ secrets.KEYVAULT_NAME }}
KEYVAULT_CERT_NAME: ${{ secrets.KEYVAULT_CERT_NAME }}
run: |
pushd bakery
cd bakery
./release.sh ${{ matrix.release }}

- name: create a new release
Expand Down
87 changes: 87 additions & 0 deletions lib/Dockerfile.keyvault-pkcs11
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
ARG IMAGE=ubuntu:24.10
FROM ${IMAGE} AS development

ENV OPENSSL_LIB_DIR=/usr/lib/x86_64-linux-gnu/
ENV DEBIAN_FRONTEND=noninteractive

# gcc throws some warnings during SDK build that are treated as errors in Release build
ENV CC=clang
ENV CXX=clang++

RUN apt-get update && \
apt-get install -y \
libcurl4-openssl-dev libssl-dev libxml2-dev git \
make gcc g++ cmake vim p11-kit libp11-kit-dev \
gnutls-bin ninja-build pkg-config curl zip unzip \
tar libjson-c-dev clang rustc cargo

# install rustc for Azure SDK
# RUN rustup toolchain install stable

RUN git clone https://github.com/Azure/azure-sdk-for-cpp /tmp/sdk && \
git -C /tmp/sdk checkout -f 800b05fc3022395d4243833a1087963300da36e9 && \
AZURE_SDK_DISABLE_AUTO_VCPKG=1 cmake -S /tmp/sdk -B /tmp/build \
-GNinja \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_POSITION_INDEPENDENT_CODE=ON \
-DDISABLE_AZURE_CORE_OPENTELEMETRY=1 \
-DBUILD_WINDOWS_UWP=1 && \
cmake --build /tmp/build -- -v && \
cmake --install /tmp/build && \
rm -rf /tmp/sdk /tmp/build

FROM development AS final
RUN git clone https://github.com/jepio/azure-keyvault-pkcs11.git /tmp/pkcs11 && \
git -C /tmp/pkcs11 checkout -f 126ae2bc714f2867b6628b49962f388c4b314f5f && \
cmake -S /tmp/pkcs11 -B /build -GNinja -DCMAKE_BUILD_TYPE=Release && \
cmake --build /build -- -v && \
cmake --install /build && \
rm -rf /work /build

FROM ${IMAGE}
# dependencies for signing (PKCS11) and building sysexts
RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y \
apt-transport-https build-essential ca-certificates curl g++ gcc \
gnupg libcurl4 libengine-pkcs11-openssl libjson-c5 lsb-release make \
p11-kit pkg-config software-properties-common sudo systemd-repart \
unzip

# preinstall sysext-bakery dependencies to speed up jobs
RUN DEBIAN_FRONTEND=noninteractive apt-get install -y \
curl jq squashfs-tools xz-utils erofs-utils

COPY --from=final /usr/local/lib/pkcs11 /usr/local/lib/pkcs11
ENV PKCS11_MODULE_PATH="/usr/local/lib/pkcs11/azure-keyvault-pkcs11.so"

# move root home to /github/home as is expected by GitHub Actions
# (otherwise az CLI would look for configuration in /root)
RUN cd /tmp && \
mkdir /github && \
mv /root/ /github/home && \
sed -i 's/:\/root:/:\/github\/home:/' /etc/passwd

# install Azure CLI
# TODO: Change noble to $(lsb_release -cs) as there currently isn't a releae
# for Ubuntu 24.10
RUN curl -fsSL https://packages.microsoft.com/keys/microsoft.asc | \
gpg --dearmor -o /etc/apt/trusted.gpg.d/microsoft.gpg && \
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/trusted.gpg.d/microsoft.gpg] https://packages.microsoft.com/repos/azure-cli/ noble main" > \
/etc/apt/sources.list.d/azure-cli.list && \
DEBIAN_FRONTEND=noninteractive apt update && \
DEBIAN_FRONTEND=noninteractive apt install azure-cli

# install Docker (for qemu GH action)
RUN curl -fsSL https://download.docker.com/linux/ubuntu/gpg | \
gpg --dearmor -o /etc/apt/keyrings/docker-archive-keyring.gpg && \
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" > \
/etc/apt/sources.list.d/docker.list && \
DEBIAN_FRONTEND=noninteractive apt update && \
DEBIAN_FRONTEND=noninteractive apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

# RUN (curl --proto '=https' --tlsv1.2 -sSLf https://aka.ms/InstallAzureCLIDeb | bash)
# RUN (curl --proto '=https' --tlsv1.2 -sSLf https://get.docker.com | bash)

RUN mkdir -p /etc/pkcs11/modules && \
touch /etc/pkcs11/pkcs11.conf && \
echo "module: /usr/local/lib/pkcs11/azure-keyvault-pkcs11.so" > /etc/pkcs11/modules/azure-keyvault-pkcs11.module && \
echo "critical: yes" >> /etc/pkcs11/modules/azure-keyvault-pkcs11.module
129 changes: 102 additions & 27 deletions lib/generate.sh
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,43 @@ function _create_sysupdate() {
function _version_ge() {
test "$(printf '%s\n' "$@" | sort -rV | head -n 1)" == "$1";
}

function _generate_signed_sysext() {
BASEDIR="$1"
OUTPUT_IMAGE="$2"
FS_FORMAT="$3"

# Create temporary working directory
WORKDIR=$(mktemp -d)
trap 'rm -rf "$WORKDIR"' RETURN

cp -r "${libroot}/sysext.repart.d/" "$WORKDIR"
sed -Ei "s/^Format=erofs/Format=${FS_FORMAT}/" "$WORKDIR/sysext.repart.d/10-root.conf"

PKCS_TOKEN_NAME="pkcs11:token=${KEYVAULT_CERT_NAME}"
PKCS11_ENV=(
AZURE_KEYVAULT_URL="https://${KEYVAULT_NAME}.vault.azure.net/"
PKCS11_MODULE_PATH="${PKCS11_MODULE_PATH:-/usr/local/lib/pkcs11/azure-keyvault-pkcs11.so}"
AZURE_KEYVAULT_PKCS11_DEBUG=1
)

CERT_CONTENT=$(az keyvault certificate download \
--vault-name "$KEYVAULT_NAME" \
--name "${KEYVAULT_CERT_NAME}" \
--file /dev/stdout)

env "${PKCS11_ENV[@]}" systemd-repart \
--empty=create \
--size=auto \
--private-key-source=engine:pkcs11 \
--private-key="$PKCS_TOKEN_NAME" \
--certificate=<(echo "$CERT_CONTENT") \
--definitions="${WORKDIR}/sysext.repart.d" \
--copy-source="$BASEDIR" \
"$OUTPUT_IMAGE"

echo "Signed sysext created: $OUTPUT_IMAGE"
}
# --

function _generate_sysext() {
Expand All @@ -110,33 +147,58 @@ function _generate_sysext() {
local format="$3"
local ext_fs_size="$4"
local fname="$5"
local signed_ddi="$6"

if [[ ${signed_ddi} == true ]] ; then
extname="${extname}-signed-ddi"
fi

announce "Creating extension image '${fname}' and generating SHA256SUM"
case "$format" in
btrfs)
# Note: We didn't chown to root:root, meaning that the file ownership is left as is
mkfs.btrfs --mixed -m single -d single --shrink --compress zstd --rootdir "${basedir}" "${fname}"
;;
ext2|ext4)
truncate -s "${ext_fs_size}" "${fname}"
mkfs."${format}" -E root_owner=0:0 -d "${basedir}" "${fname}"
resize2fs -M "${fname}"
;;
squashfs)
VERSION=$({ mksquashfs -version || true ; } | head -n1 | cut -d " " -f 3)
ARG=(-all-root -noappend)
if _version_ge "${VERSION}" "4.6.1"; then
ARG+=('-xattrs-exclude' '^btrfs.')
fi
mksquashfs "${basedir}" "${fname}" "${ARG[@]}"
;;
erofs)
# Compression recommendations from https://erofs.docs.kernel.org/en/latest/mkfs.html
# and forcing a zero UUID for reproducibility (maybe we could also hash the name and version)
mkfs.erofs -zlz4hc,12 -C65536 -Efragments,ztailpacking -Uclear --all-root "${fname}" "${basedir}"
;;

esac
VERSION=$({ mksquashfs -version || true ; } | head -n1 | cut -d " " -f 3)
SQUASHFS_ARG=(-all-root -noappend)
if _version_ge "${VERSION}" "4.6.1"; then
SQUASHFS_ARG+=('-xattrs-exclude' "'^btrfs.'")
fi

# Note: We didn't chown to root:root, meaning that the file ownership is left as is
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
# Note: We didn't chown to root:root, meaning that the file ownership is left as is
# Note: We didn't chown to root:root, meaning that the file ownership is left as is with btrfs

SYSTEMD_REPART_MKFS_OPTIONS_BTRFS="--mixed -m single -d single --shrink --compress zstd"
SYSTEMD_REPART_MKFS_OPTIONS_EXT2="-E root_owner=0:0"
SYSTEMD_REPART_MKFS_OPTIONS_EXT4="$SYSTEMD_REPART_MKFS_OPTIONS_EXT2"
SYSTEMD_REPART_MKFS_OPTIONS_SQUASHFS="${SQUASHFS_ARG[*]}"
# Compression recommendations from https://erofs.docs.kernel.org/en/latest/mkfs.html
# and forcing a zero UUID for reproducibility (maybe we could also hash the name and version)
SYSTEMD_REPART_MKFS_OPTIONS_EROFS="-zlz4hc,12 -C65536 -Efragments,ztailpacking -Uclear --all-root"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
SYSTEMD_REPART_MKFS_OPTIONS_EROFS="-zlz4hc,12 -C65536 -Efragments,ztailpacking -Uclear --all-root"
SYSTEMD_REPART_MKFS_OPTIONS_EROFS="-zlz4hc,12 -C65536 -Efragments,ztailpacking -U00000000-0000-0000-0000-000000000000 --all-root"

From #181


if [[ ${signed_ddi} == true ]] ; then
(
export SYSTEMD_REPART_MKFS_OPTIONS_BTRFS
export SYSTEMD_REPART_MKFS_OPTIONS_EXT2
export SYSTEMD_REPART_MKFS_OPTIONS_EXT4
export SYSTEMD_REPART_MKFS_OPTIONS_SQUASHFS
export SYSTEMD_REPART_MKFS_OPTIONS_EROFS
_generate_signed_sysext "${basedir}" "${fname}" "$format"
)
else
options_varname="SYSTEMD_REPART_MKFS_OPTIONS_${format^^}"
case "$format" in
btrfs)
mkfs.btrfs ${!options_varname} --rootdir "${basedir}" "${fname}"
;;
ext2|ext4)
truncate -s "${ext_fs_size}" "${fname}"
mkfs."${format}" ${!options_varname} -d "${basedir}" "${fname}"
resize2fs -M "${fname}"
;;
squashfs)
mksquashfs "${basedir}" "${fname}" ${!options_varname}
;;
erofs)
mkfs.erofs "${fname}" "${basedir}" ${!options_varname}
;;
esac
fi

sha256sum "${fname}" > "SHA256SUMS.${extname}"
announce "'${fname}' is now ready"
}
Expand Down Expand Up @@ -196,6 +258,8 @@ function generate_sysext() {
local basedir="$(get_positional_param "1" "${@}")"
local arch="$(get_positional_param "2" "${@}")"

local signed_ddi="$(get_optional_param "signed-ddi" "false" "${@}")"

if [[ -z ${basedir} ]] || [[ ${basedir} == help ]] ; then
_generate_sysext_help
exit
Expand All @@ -208,17 +272,28 @@ function generate_sysext() {

local name="$(get_optional_param "name" "$(cd "$basedir"; basename "$(pwd)")" "${@}")"
local fname="$(get_optional_param "output-file" "${name}" "${@}")"
fname="${fname%%.raw}.raw"
fname="${fname%%.raw}"
if [[ ${signed_ddi} == true ]] ; then
fname="${fname}-signed-ddi"
fi
fname="${fname}.raw"
rm -f "${fname}"

export SOURCE_DATE_EPOCH

_create_metadata "$name" "$basedir" "$os" "$arch" "$reload_services"
_generate_sysext "$name" "$basedir" "$format" "$ext_fs_size" "${fname}"
_generate_sysext "$name" "$basedir" "$format" "$ext_fs_size" "${fname}" "$signed_ddi"

local sysupdate="$(get_optional_param "sysupdate" "false" "${@}")"
if [[ ${sysupdate} == true ]] ; then
_create_sysupdate "${name}"
local config_name=""
local match_pattern=""
if [[ ${signed_ddi} == true ]] ; then
config_name="${name}-signed-ddi.conf"
match_pattern="${name}-@v-%a-signed-ddi.raw"
fi

_create_sysupdate "${name}" "$match_pattern" "" "" "${config_name}"
fi
}
# --
Loading