fix(deploy): project server secrets for core uid
This commit is contained in:
@@ -944,7 +944,7 @@ task13_configure_local_authentication() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
task13_configure_server_oidc_authentication() {
|
task13_configure_server_oidc_authentication() {
|
||||||
task13_run_logged "configure fake server OIDC authentication" sudo -n -- "$TASK13_THT" --installation "$TASK13_INSTALLATION" auth configure \
|
task13_run_logged "configure fake server OIDC authentication" task13_server_tht auth configure \
|
||||||
--mode oidc --public-url "https://task13.example.invalid" \
|
--mode oidc --public-url "https://task13.example.invalid" \
|
||||||
--issuer "https://task13-fake-oidc:9443/application/o/task13/" --client-id task13-smoke-client \
|
--issuer "https://task13-fake-oidc:9443/application/o/task13/" --client-id task13-smoke-client \
|
||||||
--authentik-base-url "https://task13-fake-oidc:9443" --user-group task13-users --admin-group task13-admins
|
--authentik-base-url "https://task13-fake-oidc:9443" --user-group task13-users --admin-group task13-admins
|
||||||
@@ -965,6 +965,32 @@ task13_prepare_server_auth_roots() {
|
|||||||
install -d -o 10001 -g 10001 -m 0700 -- "$TASK13_AUTH_RUNTIME_ROOT"
|
install -d -o 10001 -g 10001 -m 0700 -- "$TASK13_AUTH_RUNTIME_ROOT"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
task13_prepare_server_secret_sources() {
|
||||||
|
local path
|
||||||
|
[[ "${TASK13_PROFILE:-}" == server && -n "${TASK13_TMP:-}" ]] \
|
||||||
|
|| task13_fail "refusing to prepare server secret sources outside the server fixture"
|
||||||
|
for path in \
|
||||||
|
"$TASK13_SECRETS" \
|
||||||
|
"$TASK13_PI_AUTH" \
|
||||||
|
"$TASK13_SESSION_RUNTIME_PASSWORD" \
|
||||||
|
"$TASK13_SESSION_MIGRATOR_PASSWORD_FILE" \
|
||||||
|
"$TASK13_SESSION_CA"; do
|
||||||
|
[[ "$path" == "$TASK13_TMP/"* && -f "$path" && ! -L "$path" ]] \
|
||||||
|
|| task13_fail "refusing to prepare an unexpected server secret source"
|
||||||
|
done
|
||||||
|
task13_run_logged "assign server secret sources to the container UID" sudo -n -- \
|
||||||
|
chown 10001:10001 -- "$TASK13_SECRETS" "$TASK13_PI_AUTH" \
|
||||||
|
"$TASK13_SESSION_RUNTIME_PASSWORD" "$TASK13_SESSION_MIGRATOR_PASSWORD_FILE" \
|
||||||
|
"$TASK13_SESSION_CA"
|
||||||
|
task13_run_logged "protect server secret sources" sudo -n -- chmod 0600 -- \
|
||||||
|
"$TASK13_SECRETS" "$TASK13_PI_AUTH" "$TASK13_SESSION_RUNTIME_PASSWORD" \
|
||||||
|
"$TASK13_SESSION_MIGRATOR_PASSWORD_FILE" "$TASK13_SESSION_CA"
|
||||||
|
}
|
||||||
|
|
||||||
|
task13_server_tht() {
|
||||||
|
sudo -n -- "$TASK13_THT" --installation "$TASK13_INSTALLATION" "$@"
|
||||||
|
}
|
||||||
|
|
||||||
task13_prepare_local_auth_runtime() {
|
task13_prepare_local_auth_runtime() {
|
||||||
local owner_label
|
local owner_label
|
||||||
owner_label="$(docker volume inspect --format '{{ index .Labels "io.thothii.task13.run" }}' \
|
owner_label="$(docker volume inspect --format '{{ index .Labels "io.thothii.task13.run" }}' \
|
||||||
@@ -1371,8 +1397,8 @@ task13_assert_server_oidc_restore_verification() {
|
|||||||
task13_compose_logged "stop server stack for OIDC restore" stop
|
task13_compose_logged "stop server stack for OIDC restore" stop
|
||||||
rollback_sentinel="$TASK13_SERVER_DATA/task13-restore-rollback"
|
rollback_sentinel="$TASK13_SERVER_DATA/task13-restore-rollback"
|
||||||
printf 'backup-state\n' >"$rollback_sentinel"
|
printf 'backup-state\n' >"$rollback_sentinel"
|
||||||
task13_run_logged "create real server default-custody backup" "$TASK13_THT" \
|
task13_run_logged "create real server default-custody backup" task13_server_tht \
|
||||||
--installation "$TASK13_INSTALLATION" backup --output "$archive"
|
backup --output "$archive"
|
||||||
printf 'current-state\n' >"$rollback_sentinel"
|
printf 'current-state\n' >"$rollback_sentinel"
|
||||||
|
|
||||||
provider_label="$(docker container inspect --format '{{ index .Config.Labels "io.thothii.task13.run" }}' "$TASK13_OIDC_CONTAINER")"
|
provider_label="$(docker container inspect --format '{{ index .Config.Labels "io.thothii.task13.run" }}' "$TASK13_OIDC_CONTAINER")"
|
||||||
@@ -1380,7 +1406,7 @@ task13_assert_server_oidc_restore_verification() {
|
|||||||
task13_run_logged "inject post-mutation OIDC verification failure" docker stop "$TASK13_OIDC_CONTAINER"
|
task13_run_logged "inject post-mutation OIDC verification failure" docker stop "$TASK13_OIDC_CONTAINER"
|
||||||
rollback_output="$TASK13_TMP/server-oidc-rollback.out"
|
rollback_output="$TASK13_TMP/server-oidc-rollback.out"
|
||||||
set +e
|
set +e
|
||||||
"$TASK13_THT" --installation "$TASK13_INSTALLATION" restore "$archive" --yes \
|
task13_server_tht restore "$archive" --yes \
|
||||||
>"$rollback_output" 2>&1
|
>"$rollback_output" 2>&1
|
||||||
rollback_rc=$?
|
rollback_rc=$?
|
||||||
set -e
|
set -e
|
||||||
@@ -1435,7 +1461,7 @@ task13_assert_server_oidc_restore_verification() {
|
|||||||
|
|
||||||
restore_output="$TASK13_TMP/server-oidc-restore.out"
|
restore_output="$TASK13_TMP/server-oidc-restore.out"
|
||||||
set +e
|
set +e
|
||||||
"$TASK13_THT" --installation "$TASK13_INSTALLATION" restore "$archive" --yes \
|
task13_server_tht restore "$archive" --yes \
|
||||||
>"$restore_output" 2>&1
|
>"$restore_output" 2>&1
|
||||||
restore_rc=$?
|
restore_rc=$?
|
||||||
set -e
|
set -e
|
||||||
@@ -1470,7 +1496,7 @@ task13_assert_server_oidc_restore_verification() {
|
|||||||
test -z "$(find /data/auth/sessions /data/auth/oidc -mindepth 1 -print -quit)"
|
test -z "$(find /data/auth/sessions /data/auth/oidc -mindepth 1 -print -quit)"
|
||||||
'
|
'
|
||||||
diagnostics="$TASK13_TMP/server-auth-diagnostics-after-restore.json"
|
diagnostics="$TASK13_TMP/server-auth-diagnostics-after-restore.json"
|
||||||
"$TASK13_THT" --installation "$TASK13_INSTALLATION" auth check --json >"$diagnostics"
|
task13_server_tht auth check --json >"$diagnostics"
|
||||||
node -e 'const value=JSON.parse(require("fs").readFileSync(process.argv[1], "utf8")); if(value.mode!=="oidc"||value.ready!==true||value.checks.length!==1||value.checks[0].code!=="auth_ready") process.exit(1)' "$diagnostics" \
|
node -e 'const value=JSON.parse(require("fs").readFileSync(process.argv[1], "utf8")); if(value.mode!=="oidc"||value.ready!==true||value.checks.length!==1||value.checks[0].code!=="auth_ready") process.exit(1)' "$diagnostics" \
|
||||||
|| task13_fail "restored server did not retain strict fake-provider OIDC diagnostics"
|
|| task13_fail "restored server did not retain strict fake-provider OIDC diagnostics"
|
||||||
}
|
}
|
||||||
@@ -1565,14 +1591,15 @@ task13_assert_server_runtime() {
|
|||||||
[[ "$(docker inspect --format '{{.Image}}' "$frontend_id")" == "$expected_frontend_image" ]] \
|
[[ "$(docker inspect --format '{{.Image}}' "$frontend_id")" == "$expected_frontend_image" ]] \
|
||||||
|| task13_fail "server frontend did not use the smoke-built frontend image"
|
|| task13_fail "server frontend did not use the smoke-built frontend image"
|
||||||
task13_compose_logged "verify server runtime configuration and secret readability" exec -T core sh -ceu '
|
task13_compose_logged "verify server runtime configuration and secret readability" exec -T core sh -ceu '
|
||||||
test -r /run/thothii-auth/auth.yaml
|
check_readable() { test -r "$1" || { printf "server precondition failed: unreadable %s\n" "$1" >&2; exit 1; }; }
|
||||||
test -d /data/auth
|
check_readable /run/thothii-auth/auth.yaml
|
||||||
test -z "${AUTH_MODE+x}"
|
test -d /data/auth || { printf "server precondition failed: missing /data/auth\n" >&2; exit 1; }
|
||||||
test "$THT_SESSION_STORAGE" = postgres
|
test -z "${AUTH_MODE+x}" || { printf "server precondition failed: AUTH_MODE must be unset\n" >&2; exit 1; }
|
||||||
test -r /run/secrets/thothii.secrets
|
test "$THT_SESSION_STORAGE" = postgres || { printf "server precondition failed: session storage\n" >&2; exit 1; }
|
||||||
test -r /run/secrets/session_runtime_password
|
check_readable /run/secrets/thothii.secrets
|
||||||
test -r /run/secrets/session_ca.pem
|
check_readable /run/secrets/session_runtime_password
|
||||||
test -r /app/harness/workspaces/server-sessions.yaml
|
check_readable /run/secrets/session_ca.pem
|
||||||
|
check_readable /app/harness/workspaces/server-sessions.yaml
|
||||||
'
|
'
|
||||||
task13_mount_fingerprint | grep -Fq '/data = bind :' \
|
task13_mount_fingerprint | grep -Fq '/data = bind :' \
|
||||||
|| task13_fail "server profile did not bind the disposable data root"
|
|| task13_fail "server profile did not bind the disposable data root"
|
||||||
@@ -1605,13 +1632,13 @@ task13_assert_server_runtime() {
|
|||||||
task13_fail "server session failure exposed the fixture secret"
|
task13_fail "server session failure exposed the fixture secret"
|
||||||
fi
|
fi
|
||||||
status="$TASK13_TMP/server-auth-status.json"
|
status="$TASK13_TMP/server-auth-status.json"
|
||||||
task13_run_logged "server static OIDC status" "$TASK13_THT" --installation "$TASK13_INSTALLATION" auth status --json
|
task13_run_logged "server static OIDC status" task13_server_tht auth status --json
|
||||||
"$TASK13_THT" --installation "$TASK13_INSTALLATION" auth status --json >"$status"
|
task13_server_tht auth status --json >"$status"
|
||||||
node -e 'const value=JSON.parse(require("fs").readFileSync(process.argv[1], "utf8")); if(value.mode!=="oidc"||!/^sha256:[0-9a-f]{64}$/.test(value.configRevision)) process.exit(1)' "$status" \
|
node -e 'const value=JSON.parse(require("fs").readFileSync(process.argv[1], "utf8")); if(value.mode!=="oidc"||!/^sha256:[0-9a-f]{64}$/.test(value.configRevision)) process.exit(1)' "$status" \
|
||||||
|| task13_fail "server static OIDC status was not valid"
|
|| task13_fail "server static OIDC status was not valid"
|
||||||
diagnostics="$TASK13_TMP/server-auth-diagnostics.json"
|
diagnostics="$TASK13_TMP/server-auth-diagnostics.json"
|
||||||
task13_run_logged "server live OIDC diagnostics" "$TASK13_THT" --installation "$TASK13_INSTALLATION" auth check --json
|
task13_run_logged "server live OIDC diagnostics" task13_server_tht auth check --json
|
||||||
"$TASK13_THT" --installation "$TASK13_INSTALLATION" auth check --json >"$diagnostics"
|
task13_server_tht auth check --json >"$diagnostics"
|
||||||
node -e 'const value=JSON.parse(require("fs").readFileSync(process.argv[1], "utf8")); if(value.mode!=="oidc"||value.ready!==true||value.checks.length!==1||value.checks[0].code!=="auth_ready") process.exit(1)' "$diagnostics" \
|
node -e 'const value=JSON.parse(require("fs").readFileSync(process.argv[1], "utf8")); if(value.mode!=="oidc"||value.ready!==true||value.checks.length!==1||value.checks[0].code!=="auth_ready") process.exit(1)' "$diagnostics" \
|
||||||
|| task13_fail "scoped fake OIDC provider did not pass live production diagnostics"
|
|| task13_fail "scoped fake OIDC provider did not pass live production diagnostics"
|
||||||
provider_requests="$(docker logs "$TASK13_OIDC_CONTAINER" 2>>"$TASK13_LOG")"
|
provider_requests="$(docker logs "$TASK13_OIDC_CONTAINER" 2>>"$TASK13_LOG")"
|
||||||
@@ -2530,6 +2557,7 @@ task13_self_test_source_contract() {
|
|||||||
local server_auth_projection_override server_auth_projection_descriptor
|
local server_auth_projection_override server_auth_projection_descriptor
|
||||||
local server_auth_projection_environment server_auth_privileged_configure
|
local server_auth_projection_environment server_auth_privileged_configure
|
||||||
local server_fixture_reclamation server_runtime_config_probe server_workspace_config_permission
|
local server_fixture_reclamation server_runtime_config_probe server_workspace_config_permission
|
||||||
|
local server_secret_source_owner server_secret_source_preparation server_tht_wrapper
|
||||||
root="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd -P)"
|
root="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd -P)"
|
||||||
workflow="$root/.github/workflows/deployment.yml"
|
workflow="$root/.github/workflows/deployment.yml"
|
||||||
runner_preparation="$root/scripts/prepare-linux-docker-runner.sh"
|
runner_preparation="$root/scripts/prepare-linux-docker-runner.sh"
|
||||||
@@ -2561,6 +2589,9 @@ task13_self_test_source_contract() {
|
|||||||
server_auth_privileged_configure='sudo -n -- "$TASK13_''THT"'
|
server_auth_privileged_configure='sudo -n -- "$TASK13_''THT"'
|
||||||
server_fixture_reclamation='task13_reclaim_server_fixture_''ownership'
|
server_fixture_reclamation='task13_reclaim_server_fixture_''ownership'
|
||||||
server_runtime_config_probe='task13_compose_''logged "verify server runtime configuration and secret readability"'
|
server_runtime_config_probe='task13_compose_''logged "verify server runtime configuration and secret readability"'
|
||||||
|
server_secret_source_preparation='task13_prepare_server_secret_''sources'
|
||||||
|
server_secret_source_owner='chown 10001:''10001 -- "$TASK13_SECRETS" "$TASK13_PI_AUTH"'
|
||||||
|
server_tht_wrapper='task13_server_''tht'
|
||||||
server_workspace_config_permission='chmod 0644 "$TASK13_SERVER_''WORKSPACE_CONFIG"'
|
server_workspace_config_permission='chmod 0644 "$TASK13_SERVER_''WORKSPACE_CONFIG"'
|
||||||
if rg -n 'docker[[:space:]]+(system[[:space:]]+)?prune' \
|
if rg -n 'docker[[:space:]]+(system[[:space:]]+)?prune' \
|
||||||
"$root/scripts/unified-deployment-smoke.sh" \
|
"$root/scripts/unified-deployment-smoke.sh" \
|
||||||
@@ -2641,6 +2672,13 @@ task13_self_test_source_contract() {
|
|||||||
|| task13_fail "the server runtime preconditions must emit a named diagnostic"
|
|| task13_fail "the server runtime preconditions must emit a named diagnostic"
|
||||||
grep -Fq -- "$server_workspace_config_permission" "$root/scripts/unified-deployment-smoke.sh" \
|
grep -Fq -- "$server_workspace_config_permission" "$root/scripts/unified-deployment-smoke.sh" \
|
||||||
|| task13_fail "the server workspace fixture must be readable by the container UID"
|
|| task13_fail "the server workspace fixture must be readable by the container UID"
|
||||||
|
[[ "$(grep -Ec "^${server_secret_source_preparation}\\(\\)|^[[:space:]]+${server_secret_source_preparation}$" \
|
||||||
|
"$root/scripts/unified-deployment-smoke.sh")" -eq 2 ]] \
|
||||||
|
|| task13_fail "the server secret source preparation must be defined and invoked once"
|
||||||
|
grep -Fq -- "$server_secret_source_owner" "$root/scripts/unified-deployment-smoke.sh" \
|
||||||
|
|| task13_fail "the server secret sources must be private and owned by the container UID"
|
||||||
|
[[ "$(grep -Fc -- "$server_tht_wrapper" "$root/scripts/unified-deployment-smoke.sh")" -eq 10 ]] \
|
||||||
|
|| task13_fail "server operator commands must use the privileged canonical-auth wrapper"
|
||||||
[[ -x "$runner_preparation" ]] \
|
[[ -x "$runner_preparation" ]] \
|
||||||
|| task13_fail "the Linux Docker runner preparation must be executable"
|
|| task13_fail "the Linux Docker runner preparation must be executable"
|
||||||
for path in /usr/local/lib/android /usr/share/dotnet /opt/ghc /usr/local/.ghcup; do
|
for path in /usr/local/lib/android /usr/share/dotnet /opt/ghc /usr/local/.ghcup; do
|
||||||
@@ -2888,6 +2926,7 @@ task13_server_smoke_main() {
|
|||||||
task13_seed_registry
|
task13_seed_registry
|
||||||
task13_build_tht
|
task13_build_tht
|
||||||
task13_prepare_server_auth_roots
|
task13_prepare_server_auth_roots
|
||||||
|
task13_prepare_server_secret_sources
|
||||||
task13_configure_server_oidc_authentication
|
task13_configure_server_oidc_authentication
|
||||||
task13_start_server_stack
|
task13_start_server_stack
|
||||||
task13_record_project_image_evidence
|
task13_record_project_image_evidence
|
||||||
|
|||||||
Reference in New Issue
Block a user