fix: support native package verifier scratch
CI / verify (pull_request) Successful in 1m10s
CI / infrastructure-smoke (pull_request) Successful in 37s
CI / migration-smoke (pull_request) Successful in 1m54s
CI / package-release (pull_request) Successful in 36s
CI / image-build (pull_request) Successful in 52s
CI / deploy-smoke (same-origin) (pull_request) Successful in 51s
CI / deploy-smoke (split) (pull_request) Successful in 1m31s
CI / package-publication (pull_request) Successful in 51s
CI / verify (pull_request) Successful in 1m10s
CI / infrastructure-smoke (pull_request) Successful in 37s
CI / migration-smoke (pull_request) Successful in 1m54s
CI / package-release (pull_request) Successful in 36s
CI / image-build (pull_request) Successful in 52s
CI / deploy-smoke (same-origin) (pull_request) Successful in 51s
CI / deploy-smoke (split) (pull_request) Successful in 1m31s
CI / package-publication (pull_request) Successful in 51s
This commit is contained in:
+67
-1
@@ -6,7 +6,9 @@
|
||||
# - its module storage mount point, /var/lib/ekklesia/modules, exists, is root-owned, and is empty;
|
||||
# - EKKLESIA_MODULES_DIR names that directory, in the image configuration and in a running process;
|
||||
# - a checkout with a populated modules/ directory builds the same image: the runtime file system
|
||||
# of both builds is identical, and no module from that directory enters it.
|
||||
# of both builds is identical, and no module from that directory enters it;
|
||||
# - the hardened verifier keeps /tmp noexec while a dedicated bounded execution scratch loads and
|
||||
# runs the real sharp 0.35.5/libvips 1.3.4 native proof package.
|
||||
#
|
||||
# bash scripts/check-image.sh builds both images from this checkout
|
||||
# EKKLESIA_CHECK_IMAGE=<image> bash scripts/check-image.sh checks one existing image's contents
|
||||
@@ -103,6 +105,7 @@ context_copy() {
|
||||
tag_base="ekklesia-ci:${GITHUB_SHA:-local}-${GITHUB_RUN_ID:-0}-${GITHUB_RUN_ATTEMPT:-1}-"
|
||||
generic_image="${tag_base}generic-$$"
|
||||
populated_image="${tag_base}populated-$$"
|
||||
builder_image="${tag_base}native-proof-builder-$$"
|
||||
|
||||
# build_image <context> <tag>
|
||||
build_image() {
|
||||
@@ -143,4 +146,67 @@ else
|
||||
echo "note the two builds' layers differ (a cold build cache); their file systems do not"
|
||||
fi
|
||||
|
||||
step "Proving native package verification with /tmp noexec and a dedicated execution scratch"
|
||||
built_images+=("$builder_image")
|
||||
DOCKER_BUILDKIT=1 docker build --quiet --file "$work/generic/deploy/Dockerfile" \
|
||||
--target build --label "${EKKLESIA_CI_LABEL}=${project}" \
|
||||
--label "${EKKLESIA_CI_CREATED_LABEL}=$(date +%s)" \
|
||||
--tag "$builder_image" "$work/generic" >/dev/null || fail "the native proof builder did not build."
|
||||
mkdir "$work/native-package"
|
||||
package_archive="$({
|
||||
docker run --rm --network none --user "$(id -u):$(id -g)" \
|
||||
-v "$work/native-package:/proof" --entrypoint node "$builder_image" \
|
||||
packages/module-pack/tests/support/pack-native-verifier-proof.mjs /proof
|
||||
} | tail -1)" || fail "the real native proof package did not build."
|
||||
[[ "$package_archive" == native-proof-0.1.0-linux-x64-glibc.tar.gz ]] ||
|
||||
fail "the native proof builder returned an unexpected archive."
|
||||
|
||||
docker run --rm --network none --read-only \
|
||||
--tmpfs /tmp:rw,nosuid,nodev,noexec,size=64m \
|
||||
--tmpfs /run/ekklesia-verifier:rw,nosuid,nodev,exec,size=1100m,mode=0700,uid=1000,gid=1000 \
|
||||
--cap-drop ALL --security-opt no-new-privileges \
|
||||
-e "PROOF_ARCHIVE=$package_archive" -v "$work/native-package:/package:ro" \
|
||||
--entrypoint sh "$generic_image" -ec '
|
||||
fail() { echo "check-image: $*" >&2; exit 1; }
|
||||
verifier() {
|
||||
EKKLESIA_MODULE_VERIFIER_SCRATCH_DIR=/run/ekklesia-verifier \
|
||||
node core/dist/cli/verify-module-package.js "/package/$PROOF_ARCHIVE" \
|
||||
--sha256-file "/package/$PROOF_ARCHIVE.sha256" "$@"
|
||||
}
|
||||
scratch_failure() {
|
||||
if output="$(EKKLESIA_MODULE_VERIFIER_SCRATCH_DIR="$1" \
|
||||
node core/dist/cli/verify-module-package.js "/package/$PROOF_ARCHIVE" \
|
||||
--sha256-file "/package/$PROOF_ARCHIVE.sha256" 2>&1)"; then
|
||||
fail "the verifier accepted unusable execution scratch $1."
|
||||
fi
|
||||
printf "%s\n" "$output" | grep -Fq "[MODULE_PACKAGE_VERIFIER_SCRATCH_UNAVAILABLE]" ||
|
||||
fail "the verifier did not identify unusable execution scratch $1."
|
||||
}
|
||||
|
||||
grep -Eq " /tmp .*noexec" /proc/mounts || fail "/tmp is not mounted noexec."
|
||||
verifier --extract-to /tmp/noexec-installed >/tmp/noexec-verify.log
|
||||
if env -i /usr/local/bin/node --input-type=module --eval \
|
||||
"await import(\"file:///tmp/noexec-installed/server/index.js\");" \
|
||||
>/tmp/noexec-load.log 2>&1; then
|
||||
fail "the native addon unexpectedly loaded from noexec /tmp."
|
||||
fi
|
||||
rm -rf /tmp/noexec-installed
|
||||
scratch_failure /tmp
|
||||
scratch_failure /missing-verifier-scratch
|
||||
scratch_failure /package
|
||||
|
||||
verifier --extract-to /run/ekklesia-verifier/installed >/tmp/native-verify.log
|
||||
env -i /usr/local/bin/node --input-type=module --eval \
|
||||
"const m=await import(\"file:///run/ekklesia-verifier/installed/server/index.js\"); const actual=await m.proof(); const expected={pixels:[255,0,0,255,0,0,255,0,0,255,0,0],png:{format:\"png\",height:3,width:5},resized:{channels:3,height:2,width:2}}; if(JSON.stringify(actual)!==JSON.stringify(expected)) throw new Error(\"sharp proof mismatch\");"
|
||||
rm -rf /run/ekklesia-verifier/installed
|
||||
|
||||
verifier >/tmp/native-verify-a.log 2>&1 & first=$!
|
||||
verifier >/tmp/native-verify-b.log 2>&1 & second=$!
|
||||
wait "$first" || { cat /tmp/native-verify-a.log >&2; fail "first concurrent verification failed."; }
|
||||
wait "$second" || { cat /tmp/native-verify-b.log >&2; fail "second concurrent verification failed."; }
|
||||
[ -z "$(find /run/ekklesia-verifier -mindepth 1 -print -quit)" ] ||
|
||||
fail "the verifier left execution scratch behind."
|
||||
' || fail "the hardened native verifier proof failed."
|
||||
echo "ok /tmp stayed noexec; native verification, sharp execution, rejection, concurrency, and cleanup passed"
|
||||
|
||||
echo "Generic platform image check passed."
|
||||
|
||||
Reference in New Issue
Block a user