forked from EduCraft/curriculum-project-hub
fix: prove Linux Agent sandbox boundary
This commit is contained in:
@@ -1,8 +1,8 @@
|
||||
# Hub service installation
|
||||
|
||||
The initial production target is a supported Linux host with systemd,
|
||||
PostgreSQL, Node.js 20 or newer, `pg_isready`, `runuser`, `setpriv`, bubblewrap
|
||||
and `cph`. The Hub runs as the dedicated non-login `cph-hub` user; do not
|
||||
PostgreSQL, Node.js 20 or newer, `pg_isready`, `runuser`, `setpriv`, bubblewrap,
|
||||
`socat` and `cph`. The Hub runs as the dedicated non-login `cph-hub` user; do not
|
||||
create or run the unit as root.
|
||||
|
||||
Build or deploy the Hub under `/srv/curriculum-project-hub`, then run:
|
||||
@@ -18,13 +18,13 @@ On a clean host the first invocation creates
|
||||
production key and exits with status 78. Fill every required blank, set
|
||||
`CPH_BIN` to an executable compatible `cph`, keep the file mode at `0600`, and
|
||||
run the same command again. No systemd unit is installed until configuration,
|
||||
paths, Node, bubblewrap, `cph --version`, PostgreSQL connectivity and directory
|
||||
paths, Node, bubblewrap, `socat`, `cph --version`, PostgreSQL connectivity and directory
|
||||
ownership all pass preflight.
|
||||
|
||||
An existing service account is accepted only when its primary group, home and
|
||||
non-login shell match the requested configuration and it has no supplementary
|
||||
groups. After provisioning, the installer executes path-access, built Hub,
|
||||
Prisma, an authenticated database query, `cph` and bubblewrap namespace probes
|
||||
Prisma, an authenticated database query, `cph`, `socat` and bubblewrap namespace probes
|
||||
as that account with `no_new_privs` set. Inaccessible parents, UID-specific
|
||||
database/network policy, or a host that forbids unprivileged user namespaces
|
||||
therefore fail before unit installation.
|
||||
|
||||
@@ -6,6 +6,7 @@ Wants=network-online.target
|
||||
# after installation. Deployment preflight validates the executable itself;
|
||||
# this start-time assertion keeps later package/host changes fail-closed.
|
||||
AssertPathExists=__BWRAP_BIN__
|
||||
AssertPathExists=__SOCAT_BIN__
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
# PLATFORM_DEPLOY_BASE optional, defaults to /srv/curriculum-project-hub
|
||||
# PLATFORM_DEPLOY_HEALTH_URL optional, defaults to http://127.0.0.1:8788/api/healthz
|
||||
# The target host must have Node.js 20+, npm, rsync, PostgreSQL client tools
|
||||
# (`pg_isready`), systemd, bubblewrap (`bwrap`, for the ADR-0018 agent sandbox),
|
||||
# (`pg_isready`), systemd, bubblewrap (`bwrap`) and `socat` (for the ADR-0018 agent sandbox),
|
||||
# and a compatible `cph` binary named by platform.env. The service installer
|
||||
# provisions the dedicated non-root identity and persistent directories.
|
||||
# Use a dedicated `deploy` user that has passwordless sudo for systemctl and
|
||||
|
||||
@@ -24,13 +24,14 @@ ENV_FILE="${ENV_FILE:-$BASE/.secrets/platform.env}"
|
||||
SYSTEMD_UNIT_DIR="${SYSTEMD_UNIT_DIR:-/etc/systemd/system}"
|
||||
NODE_BIN="${NODE_BIN:-$(command -v node || true)}"
|
||||
BWRAP_BIN="${BWRAP_BIN:-$(command -v bwrap || true)}"
|
||||
SOCAT_BIN="${SOCAT_BIN:-$(command -v socat || true)}"
|
||||
PG_ISREADY_BIN="${PG_ISREADY_BIN:-$(command -v pg_isready || true)}"
|
||||
RUNUSER_BIN="${RUNUSER_BIN:-$(command -v runuser || true)}"
|
||||
SETPRIV_BIN="${SETPRIV_BIN:-$(command -v setpriv || true)}"
|
||||
CPH_BIN_DEFAULT="${CPH_BIN_DEFAULT:-/usr/local/bin/cph}"
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
PREFLIGHT_JS="$HUB_DIR/dist/deployment/preflight-cli.js"
|
||||
RUNTIME_PATH="$(dirname "$NODE_BIN"):$(dirname "$BWRAP_BIN"):$(dirname "$SETPRIV_BIN"):/usr/local/bin:/usr/bin:/bin"
|
||||
RUNTIME_PATH="$(dirname "$NODE_BIN"):$(dirname "$BWRAP_BIN"):$(dirname "$SOCAT_BIN"):$(dirname "$SETPRIV_BIN"):/usr/local/bin:/usr/bin:/bin"
|
||||
|
||||
fail() {
|
||||
echo "[install] error: $*" >&2
|
||||
@@ -68,6 +69,7 @@ done
|
||||
for pair in \
|
||||
"NODE_BIN:$NODE_BIN" \
|
||||
"BWRAP_BIN:$BWRAP_BIN" \
|
||||
"SOCAT_BIN:$SOCAT_BIN" \
|
||||
"PG_ISREADY_BIN:$PG_ISREADY_BIN"; do
|
||||
label="${pair%%:*}"
|
||||
value="${pair#*:}"
|
||||
@@ -98,6 +100,7 @@ for pair in \
|
||||
"SYSTEMD_UNIT_DIR:$SYSTEMD_UNIT_DIR" \
|
||||
"NODE_BIN:$NODE_BIN" \
|
||||
"BWRAP_BIN:$BWRAP_BIN" \
|
||||
"SOCAT_BIN:$SOCAT_BIN" \
|
||||
"RUNUSER_BIN:$RUNUSER_BIN" \
|
||||
"SETPRIV_BIN:$SETPRIV_BIN" \
|
||||
"RUNTIME_PATH:$RUNTIME_PATH"; do
|
||||
@@ -152,6 +155,7 @@ PREFLIGHT_ARGS=(
|
||||
--cache-dir "$CACHE_DIR"
|
||||
--workspace-root "$WORKSPACE_ROOT"
|
||||
--bwrap-bin "$BWRAP_BIN"
|
||||
--socat-bin "$SOCAT_BIN"
|
||||
--pg-isready-bin "$PG_ISREADY_BIN"
|
||||
)
|
||||
|
||||
@@ -247,6 +251,7 @@ sed \
|
||||
-e "s|__ENV_FILE__|$ENV_FILE|g" \
|
||||
-e "s|__NODE_BIN__|$NODE_BIN|g" \
|
||||
-e "s|__BWRAP_BIN__|$BWRAP_BIN|g" \
|
||||
-e "s|__SOCAT_BIN__|$SOCAT_BIN|g" \
|
||||
-e "s|__RUNTIME_PATH__|$RUNTIME_PATH|g" \
|
||||
"$SCRIPT_DIR/cph-hub.service" >"$TMP_UNIT"
|
||||
install -o root -g root -m 0644 "$TMP_UNIT" "$UNIT"
|
||||
|
||||
Reference in New Issue
Block a user