feat(auth): integrate authentication with installation lifecycle

This commit is contained in:
2026-08-17 23:33:51 +02:00
parent 0d0c15b4b8
commit e8b9995ed0
21 changed files with 672 additions and 234 deletions
+61 -7
View File
@@ -226,7 +226,7 @@ task13_write_fixture_files() {
printf '%s' "task13-runtime-password-$TASK13_RUN_ID" >"$TASK13_SESSION_RUNTIME_PASSWORD"
printf '%s' "$TASK13_AUTH_PASSWORD" >"$TASK13_AUTH_PASSWORD_FILE"
mkdir -p "$TASK13_AUTH_ROOT"
chmod 0644 "$TASK13_PI_AUTH"
chmod 0600 "$TASK13_PI_AUTH"
chmod 0700 "$TASK13_AUTH_ROOT"
chmod 0600 "$TASK13_SECRETS" "$TASK13_SESSION_RUNTIME_PASSWORD" "$TASK13_AUTH_PASSWORD_FILE"
@@ -417,7 +417,7 @@ task13_write_server_fixture_files() {
VEFTSzEzLURJU1BPU0FCTEUtU0VTU0lPTi1DQQ==
-----END CERTIFICATE-----
EOF
chmod 0644 "$TASK13_PI_AUTH" "$TASK13_SESSION_CA"
chmod 0600 "$TASK13_PI_AUTH" "$TASK13_SESSION_CA"
chmod 0600 "$TASK13_SECRETS" "$TASK13_SESSION_RUNTIME_PASSWORD" \
"$TASK13_SESSION_MIGRATOR_PASSWORD_FILE"
@@ -949,13 +949,23 @@ PY
--fail --silent --show-error --cookie "$cookie_after" "http://$frontend/api/me")"
node -e 'const value=JSON.parse(process.argv[1]); if(value.issuer!=="local"||value.session?.remembered!==true) process.exit(1)' "$me" \
|| task13_fail "post-backup browser session was not authenticated"
task13_compose_logged "seed pending OIDC state excluded from restore" exec -T core sh -ceu \
'printf %s "{}" > /data/auth/oidc/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.json && chmod 0600 /data/auth/oidc/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.json && test "$(find /data/auth/sessions -type f | wc -l | tr -d " ")" -ge 2'
task13_compose_logged "seed valid pending OIDC state excluded from restore" exec -T core node --input-type=module -e '
const { loadConfig } = await import("/app/backend/dist/config.js");
const { createFileAuthSessionStore } = await import("/app/backend/dist/auth/session-store.js");
const config = loadConfig(process.env);
const revision = config.authentication.current().revision;
const store = createFileAuthSessionStore(config.authStateRoot);
await store.createOidcState({
nonce: "n".repeat(43), codeVerifier: "v".repeat(43), returnTo: "/",
authConfigRevision: revision, issuer: "https://pending.task13.invalid",
browserTransactionDigest: "d".repeat(64), browserTransactionTransport: "loopback_http",
});
'
task13_compose_logged "verify pre-restore authentication runtime population" exec -T core sh -ceu \
'test "$(find /data/auth/sessions -type f | wc -l | tr -d " ")" -ge 2 && test -n "$(find /data/auth/oidc -type f -name "*.json" -print -quit)"'
task13_compose_logged "stop local stack for restore" stop
task13_run_logged "perform real production restore" "$TASK13_THT" \
task13_run_logged "perform real running local production restore" "$TASK13_THT" \
--installation "$TASK13_INSTALLATION" restore "$archive" --yes
task13_compose_start_logged "start restored local stack" up --detach --wait --wait-timeout 120
status_before="$(curl --connect-timeout "$TASK13_CURL_CONNECT_TIMEOUT" --max-time "$TASK13_CURL_MAX_TIME" \
--silent --output /dev/null --write-out '%{http_code}' --cookie "$cookie_before" "http://$frontend/api/me")"
status_after="$(curl --connect-timeout "$TASK13_CURL_CONNECT_TIMEOUT" --max-time "$TASK13_CURL_MAX_TIME" \
@@ -972,6 +982,49 @@ PY
task13_create_admin_session
}
task13_assert_server_oidc_restore_verification() {
local archive frontend status diagnostics
archive="$TASK13_TMP/server-oidc-restore-source.zip"
frontend="$(task13_frontend_address)"
task13_compose_logged "seed valid server authentication runtime excluded from restore" exec -T core node --input-type=module -e '
const { loadConfig } = await import("/app/backend/dist/config.js");
const { createFileAuthSessionStore } = await import("/app/backend/dist/auth/session-store.js");
const config = loadConfig(process.env);
const revision = config.authentication.current().revision;
const store = createFileAuthSessionStore(config.authStateRoot);
await store.create({
principal: { issuer: "https://task13-fake-oidc:9443/application/o/task13/", subject: "restore-browser", roles: ["user"], permissions: ["session.use"], isAdmin: false },
method: "oidc", remembered: false, authConfigRevision: revision,
idleTtlMs: 60_000, absoluteTtlMs: 120_000,
});
await store.createOidcState({
nonce: "n".repeat(43), codeVerifier: "v".repeat(43), returnTo: "/",
authConfigRevision: revision, issuer: "https://task13-fake-oidc:9443/application/o/task13/",
browserTransactionDigest: "d".repeat(64), browserTransactionTransport: "https",
});
'
task13_compose_logged "stop server stack for OIDC restore" stop
task13_run_logged "create real server default-custody backup" "$TASK13_THT" \
--installation "$TASK13_INSTALLATION" backup --output "$archive"
task13_run_logged "perform real stopped OIDC production restore verification" "$TASK13_THT" \
--installation "$TASK13_INSTALLATION" restore "$archive" --yes
task13_compose_start_logged "start restored server stack" up --detach --wait --wait-timeout 120 core frontend
status="$(curl --connect-timeout "$TASK13_CURL_CONNECT_TIMEOUT" --max-time "$TASK13_CURL_MAX_TIME" \
--silent --output /dev/null --write-out '%{http_code}' "http://$frontend/api/me")"
[[ "$status" == 401 ]] || task13_fail "OIDC restore did not require browser reauthentication"
task13_compose_logged "verify private empty server authentication state" exec -T core sh -ceu '
test "$(stat -c %a /data/auth)" = 700
test "$(stat -c %a /data/auth/sessions)" = 700
test "$(stat -c %a /data/auth/oidc)" = 700
test "$(stat -c %u /data/auth)" = "$(id -u)"
test -z "$(find /data/auth/sessions /data/auth/oidc -mindepth 1 -print -quit)"
'
diagnostics="$TASK13_TMP/server-auth-diagnostics-after-restore.json"
"$TASK13_THT" --installation "$TASK13_INSTALLATION" 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" \
|| task13_fail "restored server did not retain strict fake-provider OIDC diagnostics"
}
task13_assert_runtime() {
local frontend expected_pi actual_pi core_id
frontend="$(task13_frontend_address)"
@@ -2137,6 +2190,7 @@ task13_server_smoke_main() {
task13_assert_project_ownership
task13_assert_built_image_ownership
task13_assert_server_runtime
task13_assert_server_oidc_restore_verification
printf 'Task 13 Linux server deployment smoke passed.\n'
}