fix(deploy): validate session migrator TLS mode
This commit is contained in:
@@ -66,3 +66,14 @@ An operator must still choose the three reviewed legacy IDs, materialize real ru
|
||||
secrets, deploy Task 4 and Task 5 together in a maintenance window, apply the one-shot migrator,
|
||||
and run the documented authenticated smoke. The guarded helper has not been invoked with
|
||||
`--delete`.
|
||||
|
||||
## P1 correction — migrator TLS validation
|
||||
|
||||
The original migrator Compose command interpolated `THT_SESSION_DB_SSLMODE` into its URL without
|
||||
checking it. `docker/session-migrate.sh` now rejects every value except `verify-ca` and
|
||||
`verify-full` before reading the password file or building that URL; the Compose service invokes
|
||||
this helper. `docker/session-migrate.test.sh` first established RED because the helper did not
|
||||
exist, then verified that `prefer` is rejected before `tht` can run and that `verify-full` reaches
|
||||
a fake `tht` binary with the expected TLS URL. The helper and test pass `bash -n`; the focused
|
||||
backend config/health suite remains green, and the base-plus-overlay Compose configuration renders
|
||||
with temporary empty secret files.
|
||||
|
||||
@@ -230,6 +230,8 @@ The overlay mounts the runtime password at `/run/secrets/session_runtime_passwor
|
||||
It mounts `session_migrator_password` only to `session-migrate`. The backend refuses a server
|
||||
session store without upstream authentication, direct DB host/name/runtime user/password-file,
|
||||
`verify-ca` or `verify-full`, and an absolute CA path.
|
||||
The migrator independently rejects every other TLS mode before reading its password secret or
|
||||
constructing a database URL.
|
||||
|
||||
Perform the cutover in one maintenance window, with the Task 4 portal proxy headers and Task 5
|
||||
backend principal parser deployed together. Neither change is safe to deploy independently: Task
|
||||
|
||||
@@ -27,18 +27,15 @@ services:
|
||||
session-migrate:
|
||||
image: thothii-core:local
|
||||
profiles: [session-migrate]
|
||||
entrypoint: [/bin/sh, -ec]
|
||||
command: >-
|
||||
export PGPASSWORD="$$(cat /run/secrets/session_migrator_password)";
|
||||
exec /opt/venv/bin/tht session migrate --database-url
|
||||
"postgresql+psycopg2://$${THT_SESSION_MIGRATOR_USER}@$${THT_SESSION_DB_HOST}:$${THT_SESSION_DB_PORT}/$${THT_SESSION_DB_NAME}?sslmode=$${THT_SESSION_DB_SSLMODE}&sslrootcert=/run/secrets/session_ca.pem"
|
||||
--json
|
||||
entrypoint: [/app/docker/session-migrate.sh]
|
||||
environment:
|
||||
THT_SESSION_DB_HOST: ${THT_SESSION_DB_HOST:?set THT_SESSION_DB_HOST}
|
||||
THT_SESSION_DB_PORT: ${THT_SESSION_DB_PORT:-5432}
|
||||
THT_SESSION_DB_NAME: ${THT_SESSION_DB_NAME:?set THT_SESSION_DB_NAME}
|
||||
THT_SESSION_MIGRATOR_USER: ${THT_SESSION_MIGRATOR_USER:?set THT_SESSION_MIGRATOR_USER}
|
||||
THT_SESSION_MIGRATOR_PASSWORD_FILE: /run/secrets/session_migrator_password
|
||||
THT_SESSION_DB_SSLMODE: ${THT_SESSION_DB_SSLMODE:-verify-full}
|
||||
THT_SESSION_DB_SSLROOTCERT: /run/secrets/session_ca.pem
|
||||
secrets:
|
||||
- source: session_migrator_password
|
||||
target: session_migrator_password
|
||||
|
||||
@@ -63,8 +63,8 @@ ENV PATH="/opt/venv/bin:/usr/local/bin:$PATH" \
|
||||
PI_BIN=pi \
|
||||
HOME=/home/thoth
|
||||
|
||||
COPY docker/core-entrypoint.sh docker/ensure-pi-trust.mjs /app/docker/
|
||||
RUN chmod +x /app/docker/core-entrypoint.sh
|
||||
COPY docker/core-entrypoint.sh docker/session-migrate.sh docker/ensure-pi-trust.mjs /app/docker/
|
||||
RUN chmod +x /app/docker/core-entrypoint.sh /app/docker/session-migrate.sh
|
||||
|
||||
WORKDIR /app/backend
|
||||
USER thoth
|
||||
|
||||
Executable
+40
@@ -0,0 +1,40 @@
|
||||
#!/bin/sh
|
||||
# One-shot schema migration only. Validate TLS before reading a secret or composing a URL.
|
||||
set -eu
|
||||
|
||||
case "${THT_SESSION_DB_SSLMODE:-}" in
|
||||
verify-ca|verify-full) ;;
|
||||
*)
|
||||
echo "THT_SESSION_DB_SSLMODE must be verify-ca or verify-full" >&2
|
||||
exit 2
|
||||
;;
|
||||
esac
|
||||
|
||||
require_env() {
|
||||
eval "value=\${$1:-}"
|
||||
if [ -z "$value" ]; then
|
||||
echo "missing required session migrator configuration" >&2
|
||||
exit 2
|
||||
fi
|
||||
}
|
||||
|
||||
require_env THT_SESSION_DB_HOST
|
||||
require_env THT_SESSION_DB_PORT
|
||||
require_env THT_SESSION_DB_NAME
|
||||
require_env THT_SESSION_MIGRATOR_USER
|
||||
require_env THT_SESSION_MIGRATOR_PASSWORD_FILE
|
||||
require_env THT_SESSION_DB_SSLROOTCERT
|
||||
|
||||
if [ ! -r "$THT_SESSION_MIGRATOR_PASSWORD_FILE" ]; then
|
||||
echo "session migrator credential is unavailable" >&2
|
||||
exit 2
|
||||
fi
|
||||
export PGPASSWORD="$(cat "$THT_SESSION_MIGRATOR_PASSWORD_FILE")"
|
||||
if [ -z "$PGPASSWORD" ]; then
|
||||
echo "session migrator credential is unavailable" >&2
|
||||
exit 2
|
||||
fi
|
||||
|
||||
exec "${THT_BIN:-/opt/venv/bin/tht}" session migrate --database-url \
|
||||
"postgresql+psycopg2://${THT_SESSION_MIGRATOR_USER}@${THT_SESSION_DB_HOST}:${THT_SESSION_DB_PORT}/${THT_SESSION_DB_NAME}?sslmode=${THT_SESSION_DB_SSLMODE}&sslrootcert=${THT_SESSION_DB_SSLROOTCERT}" \
|
||||
--json
|
||||
Executable
+38
@@ -0,0 +1,38 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
root=$(cd "$(dirname "$0")/.." && pwd)
|
||||
helper="$root/docker/session-migrate.sh"
|
||||
tmp=$(mktemp -d)
|
||||
trap 'rm -rf "$tmp"' EXIT HUP INT TERM
|
||||
|
||||
if THT_SESSION_DB_SSLMODE=prefer sh "$helper" >"$tmp/invalid.out" 2>&1; then
|
||||
echo "session migrator accepted an unverified TLS mode" >&2
|
||||
exit 1
|
||||
fi
|
||||
grep -qx 'THT_SESSION_DB_SSLMODE must be verify-ca or verify-full' "$tmp/invalid.out"
|
||||
|
||||
printf '%s' password >"$tmp/password"
|
||||
cat >"$tmp/tht" <<'EOF'
|
||||
#!/bin/sh
|
||||
printf '%s\n' "$@" >"$ARGS_FILE"
|
||||
EOF
|
||||
chmod +x "$tmp/tht"
|
||||
|
||||
ARGS_FILE="$tmp/args" \
|
||||
THT_BIN="$tmp/tht" \
|
||||
THT_SESSION_DB_HOST=sessions-db.internal \
|
||||
THT_SESSION_DB_PORT=5432 \
|
||||
THT_SESSION_DB_NAME=thoth \
|
||||
THT_SESSION_MIGRATOR_USER=thoth_sessions_migrate \
|
||||
THT_SESSION_MIGRATOR_PASSWORD_FILE="$tmp/password" \
|
||||
THT_SESSION_DB_SSLMODE=verify-full \
|
||||
THT_SESSION_DB_SSLROOTCERT=/run/secrets/session_ca.pem \
|
||||
sh "$helper"
|
||||
|
||||
grep -qx 'session' "$tmp/args"
|
||||
grep -qx 'migrate' "$tmp/args"
|
||||
grep -qx -- '--database-url' "$tmp/args"
|
||||
grep -Fxq 'postgresql+psycopg2://thoth_sessions_migrate@sessions-db.internal:5432/thoth?sslmode=verify-full&sslrootcert=/run/secrets/session_ca.pem' "$tmp/args"
|
||||
|
||||
echo "session migrator TLS contract passed."
|
||||
Reference in New Issue
Block a user