diff --git a/config/golden-image-container-integration.yaml b/config/golden-image-container-integration.yaml index 653ad3fd..bc03c9cd 100644 --- a/config/golden-image-container-integration.yaml +++ b/config/golden-image-container-integration.yaml @@ -2,7 +2,7 @@ schema_version: 1 image: type: container - alias: nddev-u24-amd64-ctr-docker-runner-2.336.0-r20260801-b12 + alias: nddev-u24-amd64-ctr-docker-runner-2.336.0-r20260801-b13 current_alias: nddev-ubuntu-24.04-amd64-container-docker-current previous_alias: nddev-ubuntu-24.04-amd64-container-docker-previous source_alias: nddev-source-ubuntu-24.04-amd64-container-r20260801 diff --git a/config/golden-image-container.yaml b/config/golden-image-container.yaml index f3757efb..7018e098 100644 --- a/config/golden-image-container.yaml +++ b/config/golden-image-container.yaml @@ -2,7 +2,7 @@ schema_version: 1 image: type: container - alias: nddev-ubuntu-24.04-amd64-container-runner-2.336.0-r20260801-b19 + alias: nddev-ubuntu-24.04-amd64-container-runner-2.336.0-r20260801-b20 current_alias: nddev-ubuntu-24.04-amd64-container-current previous_alias: nddev-ubuntu-24.04-amd64-container-previous source_alias: nddev-source-ubuntu-24.04-amd64-container-r20260801 diff --git a/config/golden-image-integration.yaml b/config/golden-image-integration.yaml index bbd78eba..0c12a31d 100644 --- a/config/golden-image-integration.yaml +++ b/config/golden-image-integration.yaml @@ -1,7 +1,7 @@ schema_version: 1 image: - alias: nddev-ubuntu-24.04-amd64-docker-runner-2.336.0-r20260801-b15 + alias: nddev-ubuntu-24.04-amd64-docker-runner-2.336.0-r20260801-b16 current_alias: nddev-ubuntu-24.04-amd64-docker-current previous_alias: nddev-ubuntu-24.04-amd64-docker-previous source_alias: nddev-source-ubuntu-24.04-amd64-r20260801 diff --git a/config/golden-image.yaml b/config/golden-image.yaml index 7c7a7e78..160e6c0a 100644 --- a/config/golden-image.yaml +++ b/config/golden-image.yaml @@ -1,7 +1,7 @@ schema_version: 1 image: - alias: nddev-ubuntu-24.04-amd64-runner-2.336.0-r20260801-b16 + alias: nddev-ubuntu-24.04-amd64-runner-2.336.0-r20260801-b17 current_alias: nddev-ubuntu-24.04-amd64-current previous_alias: nddev-ubuntu-24.04-amd64-previous source_alias: nddev-source-ubuntu-24.04-amd64-r20260801 diff --git a/internal/garmbootstrap/types.go b/internal/garmbootstrap/types.go index 6469b6d0..d07f701b 100644 --- a/internal/garmbootstrap/types.go +++ b/internal/garmbootstrap/types.go @@ -36,17 +36,17 @@ const ( DefaultPoolBalancerType = "roundrobin" DefaultProviderName = "nddev-incus" DefaultImage = "nddev-ubuntu-24.04-amd64-container-current" - IntegrationImage = "nddev-u24-amd64-ctr-docker-runner-2.336.0-r20260801-b11" - PriorityStandardImage = "nddev-ubuntu-24.04-amd64-container-runner-2.336.0-r20260801-b18" - PriorityIntegrationImage = "nddev-u24-amd64-ctr-docker-runner-2.336.0-r20260801-b11" + IntegrationImage = "nddev-u24-amd64-ctr-docker-runner-2.336.0-r20260801-b13" + PriorityStandardImage = "nddev-ubuntu-24.04-amd64-container-runner-2.336.0-r20260801-b20" + PriorityIntegrationImage = "nddev-u24-amd64-ctr-docker-runner-2.336.0-r20260801-b13" // Every Linux class is an ephemeral Incus container. Docker-capable classes // use their nested-runtime image; release uses a separately stage-smoked // standard image so OIDC authority does not inherit Docker/nesting. FastImage = ContainerCanaryImage UntrustedImage = IntegrationImage - ReleaseImage = "nddev-ubuntu-24.04-amd64-container-runner-2.336.0-r20260801-b18" + ReleaseImage = "nddev-ubuntu-24.04-amd64-container-runner-2.336.0-r20260801-b20" ContainerCanaryImage = "nddev-ubuntu-24.04-amd64-container-current" - DockerContainerCanaryImage = "nddev-u24-amd64-ctr-docker-runner-2.336.0-r20260801-b11" + DockerContainerCanaryImage = "nddev-u24-amd64-ctr-docker-runner-2.336.0-r20260801-b13" DefaultFlavor = "nddev-linux-standard" IntegrationFlavor = "nddev-linux-integration" FastFlavor = "nddev-linux-fast" diff --git a/internal/imagebuild/assets/provision.sh b/internal/imagebuild/assets/provision.sh index 4a281ac6..b122f4dd 100644 --- a/internal/imagebuild/assets/provision.sh +++ b/internal/imagebuild/assets/provision.sh @@ -44,6 +44,24 @@ ln -sfn /usr/bin/pip3 /usr/local/bin/pip3 python --version >/dev/null pip --version >/dev/null +# bubblewrap is on the image for consumers that need a network isolator, but +# a binary on disk is not a capability: Ubuntu 24.04 ships +# kernel.apparmor_restrict_unprivileged_userns=1, and without an AppArmor +# profile granting userns, bwrap dies at "setting up uid map" for every +# unprivileged caller -- measured on a live worker while the conformance +# consumer read it as "no isolator". This is Ubuntu's own mechanism for +# exactly this case; the restriction stays in force for everything else. +cat > /etc/apparmor.d/bwrap-userns <<'APPARMOR' +abi , +include +profile bwrap /usr/bin/bwrap flags=(unconfined) { + userns, +} +APPARMOR +chmod 0644 /etc/apparmor.d/bwrap-userns +apparmor_parser --replace /etc/apparmor.d/bwrap-userns +runuser -u runner -- env HOME=/home/runner bwrap --ro-bind / / true + systemctl disable --now apt-daily.timer apt-daily-upgrade.timer unattended-upgrades.service 2>/dev/null || true git lfs install --system groupadd --force docker diff --git a/internal/imagebuild/assets/smoke-integration.sh b/internal/imagebuild/assets/smoke-integration.sh index 8dbaafe2..d139f643 100644 --- a/internal/imagebuild/assets/smoke-integration.sh +++ b/internal/imagebuild/assets/smoke-integration.sh @@ -160,6 +160,11 @@ for smoke_toolchain in "${smoke_toolchain_names[@]}"; do esac done +# bubblewrap must be able to actually create its sandbox as the job user; the +# binary being present has already lied about this once. +test -f /etc/apparmor.d/bwrap-userns +runuser -u runner -- env HOME=/home/runner bwrap --ro-bind / / true + # Browser bytes are qualification input, not image content. Launch the pinned # Chrome-for-Testing archive against the baked OS libraries as the unprivileged # runner, then let cleanup delete the entire extracted tree and profile. diff --git a/internal/imagebuild/assets/smoke.sh b/internal/imagebuild/assets/smoke.sh index 95b3bac0..26a573b6 100644 --- a/internal/imagebuild/assets/smoke.sh +++ b/internal/imagebuild/assets/smoke.sh @@ -147,6 +147,11 @@ for smoke_toolchain in "${smoke_toolchain_names[@]}"; do esac done +# bubblewrap must be able to actually create its sandbox as the job user; the +# binary being present has already lied about this once. +test -f /etc/apparmor.d/bwrap-userns +runuser -u runner -- env HOME=/home/runner bwrap --ro-bind / / true + python --version >/dev/null python3 --version >/dev/null python3 -m pip --version >/dev/null diff --git a/internal/imagebuild/orchestrator_test.go b/internal/imagebuild/orchestrator_test.go index af4bd095..ede8f26d 100644 --- a/internal/imagebuild/orchestrator_test.go +++ b/internal/imagebuild/orchestrator_test.go @@ -164,7 +164,7 @@ func TestRecipeFingerprintIsDeterministic(t *testing.T) { // alias is part of the recipe, so a manifest whose contents changed under an // unchanged alias would otherwise ask the builder to produce different bytes // for a name that is already promoted. - if first != "sha256:522a61fbf8567198ac81be2a0b6ffe5cdbc1a7cdf5e8beec13d415db470ab83e" { + if first != "sha256:835c7ed10be62b3ac1cca36572c08b8661b0df5451f1b594bbb4ce7cf19f9ebf" { t.Fatalf("deployed standard recipe fingerprint drifted: %q", first) } smoke, err := SmokeFingerprint(plan) diff --git a/internal/imagemanifest/manifest_test.go b/internal/imagemanifest/manifest_test.go index c05f1c03..fbfefeef 100644 --- a/internal/imagemanifest/manifest_test.go +++ b/internal/imagemanifest/manifest_test.go @@ -42,7 +42,7 @@ func TestRepositoryManifestIsValidAndPinned(t *testing.T) { if !strings.HasPrefix(fingerprint, "sha256:") || len(fingerprint) != len("sha256:")+64 { t.Fatalf("unexpected fingerprint %q", fingerprint) } - if fingerprint != "sha256:d7fdc01a61f2afc9991ef658511ea3cf73f73c251d0043c04c392f06b6397d1a" { + if fingerprint != "sha256:4c76a6c764a529923aa4dcd0327863aa43a4700b3a5e5d99aa30426a7db96217" { t.Fatalf("standard manifest fingerprint drifted: %q", fingerprint) } }