Keep same-RC secure-runtime canary inside isolated lab

Create the non-loopback veth canary only inside the no-network disposable systemd container before running the immutable release lab. Preserve packet authentication and fail closed when the local interface or no-default-route assertion is absent. Bind the workflow, source contract and installtests guard in one reviewed candidate.

Change-source: pulse-maintainer
This commit is contained in:
pulse-triage[bot]
2026-09-29 10:37:15 +01:00
parent 70acab1703
commit c54d361acf
3 changed files with 36 additions and 3 deletions
@@ -224,7 +224,7 @@ jobs:
COPY --from=dind /usr/local/bin/ /usr/local/bin/
COPY pulse-qualification-docker.service /etc/systemd/system/pulse-qualification-docker.service
RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
ca-certificates curl dbus systemd systemd-sysv util-linux && \
ca-certificates curl dbus systemd systemd-sysv util-linux iproute2 && \
apt-get clean && \
systemctl mask dev-hugepages.mount sys-fs-fuse-connections.mount systemd-remount-fs.service docker.service docker.socket && \
systemctl enable pulse-qualification-docker.service
@@ -269,7 +269,19 @@ jobs:
sleep 2
done
docker exec "${container}" sh -c \
'for command in curl docker dockerd id nsenter runuser systemctl; do command -v "$command" >/dev/null || exit 1; done'
'for command in curl docker dockerd id ip nsenter runuser systemctl; do command -v "$command" >/dev/null || exit 1; done'
# The immutable RC test needs a reachable non-loopback host-interface
# canary to prove that the helper's private network cannot reach it.
# Both veth ends stay inside this --network none namespace; neither
# endpoint is attached to the runner or an egress bridge.
docker exec "${container}" sh -ceu '
ip link add pulse-can0 type veth peer name pulse-can1
ip address add 192.0.2.1/32 dev pulse-can0
ip link set pulse-can1 up
ip link set pulse-can0 up
test -z "$(ip -4 route show default)"
ip -4 address show dev pulse-can0 | grep -F "192.0.2.1/32"
'
docker exec "${container}" systemctl start pulse-qualification-docker.service
for attempt in $(seq 1 60); do
if docker exec "${container}" docker info >/dev/null 2>&1; then
@@ -1239,6 +1239,14 @@ artifact-selection behaviour.
privileged systemd container must mount that exact snapshot read-only and
must never execute directly from the download directory. The post-run
attester must consume the same snapshot paths.
The outer systemd qualification container must retain `--network none`:
it may create a non-loopback host-interface canary only as a veth pair
wholly inside that container's network namespace, with no runner bridge,
egress attachment, or default IPv4 route. The immutable RC lab uses this
reachable local canary to distinguish host-network access from the typed
helper's private network isolation. Canary setup and the no-default-route
check must fail qualification before that lab if the boundary is absent;
they must not skip the lab or change the release packet under test.
PVE jobs must consume their runner users' persistent local Go and npm caches
directly; disposable-runner Actions cache restore/save phases must remain
disabled because archiving those same caches adds network work after the
@@ -2847,12 +2847,15 @@ func TestSecureRuntimeQualificationPacketIsHostedAndReleaseBound(t *testing.T) {
`git remote set-url origin https://github.com/rcourtman/Pulse.git`,
"ca-certificates curl dbus systemd systemd-sysv util-linux",
`docker:27.5.1-dind@sha256:f649ef046008ca7f926a2571c32b0ac22e5c59eb61b959617f9acc2a4c638cf5`,
`for command in curl docker dockerd id nsenter runuser systemctl`,
`for command in curl docker dockerd id ip nsenter runuser systemctl`,
`--host=unix:///var/run/docker.sock`,
`--storage-driver=vfs`,
`--bridge=none`,
`--iptables=false`,
`--network none`,
`ip link add pulse-can0 type veth peer name pulse-can1`,
`ip address add 192.0.2.1/32 dev pulse-can0`,
`test -z "$(ip -4 route show default)"`,
`pulse-secure-runtime-fixture:v7`,
"--verify-release-packet-only",
"--verified-packet-dir",
@@ -2870,6 +2873,16 @@ func TestSecureRuntimeQualificationPacketIsHostedAndReleaseBound(t *testing.T) {
t.Fatalf("post-publication secure-runtime qualification missing %q", required)
}
}
canaryIndex := strings.Index(qualificationWorkflow, `ip link add pulse-can0 type veth peer name pulse-can1`)
labIndex := strings.Index(qualificationWorkflow, `--env PULSE_SECURE_RUNTIME_SYSTEMD_LAB=1`)
if canaryIndex <= privilegedExecutionIndex || labIndex <= canaryIndex {
t.Fatal("the isolated host-interface canary must be configured before running the immutable RC lab")
}
if !strings.Contains(qualificationWorkflow, `--privileged \
--network none \
--cgroupns=host`) {
t.Fatal("the outer systemd lab must retain its no-network namespace")
}
for _, forbidden := range []string{
`/var/run/docker.sock:/var/run/docker.sock`,
`--host=tcp://`,