From 5f252b57a7bd6556ebd11da65016f13d36dc5498 Mon Sep 17 00:00:00 2001 From: Paulo Date: Wed, 23 Sep 2026 00:21:08 +0200 Subject: [PATCH] Boot the sandbox image with the drukbox base entrypoint --- .github/workflows/on-pull-request-images.yml | 32 ++++++++------------ deploy/sandbox/Dockerfile | 18 +++++------ deploy/sandbox/entrypoint.sh | 14 --------- deploy/sandbox/goss.yaml | 17 +++++++++++ 4 files changed, 37 insertions(+), 44 deletions(-) delete mode 100755 deploy/sandbox/entrypoint.sh create mode 100644 deploy/sandbox/goss.yaml diff --git a/.github/workflows/on-pull-request-images.yml b/.github/workflows/on-pull-request-images.yml index e5f14163..0a657eab 100644 --- a/.github/workflows/on-pull-request-images.yml +++ b/.github/workflows/on-pull-request-images.yml @@ -36,27 +36,21 @@ jobs: load: true tags: druks-sandbox:pr cache-from: type=gha,scope=sandbox - - name: Boot installs the proxy CA, the git helper, and the druks key + # dgoss boots the image the way the drukbox docker provider does and + # checks deploy/sandbox/goss.yaml inside it. + - name: Validate the sandbox image + env: + GOSS_VERSION: 0.4.10 + GOSS_FILES_PATH: deploy/sandbox + GOSS_OPTS: -r 30s -s 1s --format documentation run: | - ssh-keygen -t ed25519 -f "$RUNNER_TEMP/sandbox" -N '' -q - openssl req -x509 -newkey rsa:2048 -keyout "$RUNNER_TEMP/ca.key" \ - -out "$RUNNER_TEMP/ca.crt" -days 1 -nodes -subj "/CN=drukbox-pr-ca" - SECRETS_PROXY_CA="$(base64 -w0 "$RUNNER_TEMP/ca.crt")" - docker run -d --name sandbox-boot \ - -e "DRUKBOX_AUTHORIZED_KEY=$(cat "$RUNNER_TEMP/sandbox.pub")" \ - -e "SECRETS_PROXY_CA=$SECRETS_PROXY_CA" \ - -e GH_TOKEN=placeholder \ + curl -fsSL "https://github.com/goss-org/goss/releases/download/v$GOSS_VERSION/goss_${GOSS_VERSION}_linux_x86_64.tar.gz" \ + | tar -xz -C "$RUNNER_TEMP" goss + curl -fsSL -o "$RUNNER_TEMP/dgoss" "https://github.com/goss-org/goss/releases/download/v$GOSS_VERSION/dgoss" + chmod +x "$RUNNER_TEMP/dgoss" + GOSS_PATH="$RUNNER_TEMP/goss" "$RUNNER_TEMP/dgoss" run \ + -e DRUKBOX_SSH_USER=druks -e 'DRUKBOX_AUTHORIZED_KEY=ssh-ed25519 AAAA goss' \ druks-sandbox:pr - sleep 5 - docker inspect -f '{{.State.Running}}' sandbox-boot | grep -x true - docker exec -e "SECRETS_PROXY_CA=$SECRETS_PROXY_CA" sandbox-boot sh -ec ' - printf %s "$SECRETS_PROXY_CA" | base64 -d > /tmp/expected.crt - openssl verify -CAfile /etc/ssl/certs/ca-certificates.crt /tmp/expected.crt - ' - docker exec sandbox-boot git config --system --get-all credential.https://github.com.helper \ - | grep -Fx '!gh auth git-credential' - docker exec sandbox-boot cat /home/druks/.ssh/authorized_keys \ - | grep -Fx "$(cat "$RUNNER_TEMP/sandbox.pub")" # The Docker Sandboxes template must keep its base's boot contract after # the toolchain layers: `sbx create` sends no environment variables, drukbox diff --git a/deploy/sandbox/Dockerfile b/deploy/sandbox/Dockerfile index 4cfad9a2..b591ac8a 100644 --- a/deploy/sandbox/Dockerfile +++ b/deploy/sandbox/Dockerfile @@ -5,10 +5,11 @@ # the same tool layers to whichever base ``BASE`` selects: # # - ``sandbox`` (the default target, on ``docker-base``) serves the drukbox -# docker provider, published as ghcr.io/czpython/druks/sandbox. It swaps -# the base entrypoint to seed the non-root ``druks`` user because Claude -# Code refuses ``--permission-mode bypassPermissions`` as root. Point -# DRUKS_SANDBOX_IMAGE at it and run drukbox with DOCKER_SSH_USERNAME=druks. +# docker provider, published as ghcr.io/czpython/druks/sandbox. It adds +# the non-root ``druks`` user because Claude Code refuses +# ``--permission-mode bypassPermissions`` as root; the base entrypoint +# seeds that user's key when drukbox runs with DOCKER_SSH_USERNAME=druks. +# Point DRUKS_SANDBOX_IMAGE at it. # - ``sbx`` (build with ``--build-arg BASE=sbx-base``) serves the drukbox # docker-sbx provider as a Docker Sandboxes template, published as # ghcr.io/czpython/druks/sandbox-sbx. The base's env-free entrypoint and @@ -20,7 +21,7 @@ # Both targets are published by .github/workflows/publish-sandbox-image.yml. ARG BASE=docker-base -FROM ghcr.io/czpython/drukbox/sandbox:latest@sha256:72c6ab246c53481051d8d4ec9ed34e9aff47f539f989f625cf20ba82e9b3f311 AS docker-base +FROM ghcr.io/czpython/drukbox/sandbox:latest@sha256:cccf324cada9c1b0df409858dac8188e0ed2591ed88ee3d5fb59db9055a75244 AS docker-base FROM ghcr.io/czpython/drukbox/sbx-sandbox:latest@sha256:ab08421818ad21ed7a8a9db6f5c184a754c4ab6c85c26877983c245dbcd34bcf AS sbx-base FROM ${BASE} AS toolchain @@ -64,10 +65,5 @@ RUN useradd --create-home --shell /bin/bash druks FROM toolchain AS sbx # Docker provider image, the default target: ``docker build deploy/sandbox`` -# builds this one. +# builds this one. The toolchain as is: the base entrypoint boots it. FROM toolchain AS sandbox - -COPY entrypoint.sh /usr/local/bin/druks-sandbox-entrypoint -RUN chmod +x /usr/local/bin/druks-sandbox-entrypoint - -ENTRYPOINT ["/usr/local/bin/druks-sandbox-entrypoint"] diff --git a/deploy/sandbox/entrypoint.sh b/deploy/sandbox/entrypoint.sh deleted file mode 100755 index 7b99ad9b..00000000 --- a/deploy/sandbox/entrypoint.sh +++ /dev/null @@ -1,14 +0,0 @@ -#!/usr/bin/env bash -# Seeds the non-root ``druks`` user, then the drukbox base entrypoint does the -# boot. Claude Code refuses ``bypassPermissions`` under uid 0, so agents must -# SSH in unprivileged. -set -euo pipefail - -: "${DRUKBOX_AUTHORIZED_KEY:?DRUKBOX_AUTHORIZED_KEY is required}" - -install -d -m 700 -o druks -g druks /home/druks/.ssh -printf '%s\n' "$DRUKBOX_AUTHORIZED_KEY" > /home/druks/.ssh/authorized_keys -chmod 600 /home/druks/.ssh/authorized_keys -chown druks:druks /home/druks/.ssh/authorized_keys - -exec /usr/local/bin/drukbox-entrypoint diff --git a/deploy/sandbox/goss.yaml b/deploy/sandbox/goss.yaml new file mode 100644 index 00000000..7a7fe09f --- /dev/null +++ b/deploy/sandbox/goss.yaml @@ -0,0 +1,17 @@ +# The boot contract of the sandbox image: the drukbox base entrypoint seeds +# the ``druks`` user this image adds. dgoss checks it in CI with +# DRUKBOX_SSH_USER=druks and DRUKBOX_AUTHORIZED_KEY="ssh-ed25519 AAAA goss". +file: + /home/druks/.ssh/authorized_keys: + exists: true + mode: "0600" + owner: druks + group: druks + contents: + - ssh-ed25519 AAAA goss +process: + sshd: + running: true +port: + tcp:22: + listening: true