82 lines
3.4 KiB
Bash
Executable File
82 lines
3.4 KiB
Bash
Executable File
#!/bin/sh
|
|
set -eu
|
|
|
|
cd "$(dirname "$0")/.."
|
|
|
|
tmp=$(mktemp -d)
|
|
trap 'rm -rf "$tmp"' EXIT HUP INT TERM
|
|
|
|
docker compose config >"$tmp/base.yaml"
|
|
grep -q '^ core:' "$tmp/base.yaml"
|
|
grep -q '^ frontend:' "$tmp/base.yaml"
|
|
grep -q 'host_ip: 127.0.0.1' "$tmp/base.yaml"
|
|
grep -q 'AUTH_MODE: none' "$tmp/base.yaml"
|
|
grep -q 'THOTH_PUBLIC_EXPOSURE: "false"' "$tmp/base.yaml"
|
|
grep -q 'THT_SECRETS_FILE: /run/secrets/thothii.secrets' "$tmp/base.yaml"
|
|
if grep -q 'THT_[A-Z0-9_]*_SECRET_FILE:' "$tmp/base.yaml"; then
|
|
echo "base Compose must not require legacy secret-file variables" >&2
|
|
exit 1
|
|
fi
|
|
|
|
for secret in bootstrap migrator local_reader local_writer; do
|
|
printf '%s' "contract-$secret" >"$tmp/$secret"
|
|
chmod 0600 "$tmp/$secret"
|
|
done
|
|
THT_VECTOR_BOOTSTRAP_PASSWORD_SECRET_FILE="$tmp/bootstrap" \
|
|
THT_VECTOR_MIGRATOR_PASSWORD_SECRET_FILE="$tmp/migrator" \
|
|
THT_VECTOR_READER_PASSWORD_SECRET_FILE="$tmp/local_reader" \
|
|
THT_VECTOR_WRITER_PASSWORD_SECRET_FILE="$tmp/local_writer" \
|
|
docker compose -f compose.yaml -f deploy/compose.local-vector.yaml \
|
|
--profile local-vector config >"$tmp/local-vector.yaml"
|
|
grep -q 'THT_VECTOR_READER_PASSWORD_FILE: /run/secrets/vector_reader_password' "$tmp/local-vector.yaml"
|
|
grep -q 'THT_VECTOR_WRITER_PASSWORD_FILE: /run/secrets/vector_writer_password' "$tmp/local-vector.yaml"
|
|
if grep -q 'contract-local_' "$tmp/local-vector.yaml"; then
|
|
echo "rendered local-vector config leaked a direct database secret" >&2
|
|
exit 1
|
|
fi
|
|
|
|
docker compose -f compose.yaml -f deploy/compose.local.yaml \
|
|
--profile external config >"$tmp/local.yaml"
|
|
if grep -q 'env_file:' "$tmp/local.yaml"; then
|
|
echo "local Compose must use the root .env interpolation file" >&2
|
|
exit 1
|
|
fi
|
|
|
|
printf '%s\n' 'THT_MODEL_API_KEY=test-model' >"$tmp/thothii.secrets"
|
|
chmod 0600 "$tmp/thothii.secrets"
|
|
THT_SECRETS_FILE="$tmp/thothii.secrets" \
|
|
THT_DB_NAME=test THT_DWH_REST_URL=https://dwh.example.test \
|
|
THT_VEC_REST_URL=https://vector.example.test THT_OLLAMA_URL=https://embed.example.test \
|
|
docker compose -f compose.yaml -f deploy/compose.production.yaml \
|
|
--profile external config >"$tmp/production.yaml"
|
|
grep -q 'AUTH_MODE: upstream' "$tmp/production.yaml"
|
|
grep -q 'THOTH_PUBLIC_EXPOSURE: "true"' "$tmp/production.yaml"
|
|
grep -q 'THT_SECRETS_FILE: /run/secrets/thothii.secrets' "$tmp/production.yaml"
|
|
grep -q 'target: thothii.secrets' "$tmp/production.yaml"
|
|
if grep -q 'test-model' "$tmp/production.yaml"; then
|
|
echo "rendered production config leaked the model API key" >&2
|
|
exit 1
|
|
fi
|
|
|
|
if PI_PROVIDER_API_KEY='must-not-leak' ./docker/core-entrypoint.sh doctor 2>"$tmp/legacy-model.err"; then
|
|
echo "legacy generic model credential was accepted" >&2
|
|
exit 1
|
|
fi
|
|
grep -q 'PI_PROVIDER_API_KEY is unsupported' "$tmp/legacy-model.err"
|
|
if grep -q 'must-not-leak' "$tmp/legacy-model.err"; then
|
|
echo "legacy model credential leaked through entrypoint diagnostics" >&2
|
|
exit 1
|
|
fi
|
|
if grep -q 'THT_VECTOR_READER_PASSWORD_FILE\|THT_VECTOR_WRITER_PASSWORD_FILE\|target: vector_reader_password\|target: vector_writer_password\|dwh_api_key\|model_api_key' "$tmp/production.yaml"; then
|
|
echo "production external config contains local direct vector secrets" >&2
|
|
exit 1
|
|
fi
|
|
|
|
if awk '/^FROM / && $2 !~ /@sha256:/ { found=1 } END { exit !found }' \
|
|
docker/core.Dockerfile docker/frontend.Dockerfile; then
|
|
echo "every Dockerfile base must include an immutable digest" >&2
|
|
exit 1
|
|
fi
|
|
|
|
echo "container deployment security contract passed."
|