Protect RCON diagnostics and redact player addresses (Refs #61)

This commit is contained in:
2026-10-08 16:47:34 -04:00
parent 29d2d9634c
commit 0cc4498b53
36 changed files with 280 additions and 83 deletions
@@ -4,6 +4,7 @@ import { rconStatusResult } from '$lib/server/integrations/rcon.js';
import { getServer, setServerField } from '$lib/server/fleet/servers.js';
import { latestGameSubmission } from '$lib/server/fleet/status-evidence.js';
import { isProvisioning } from '$lib/server/fleet/provisioning.js';
import { failureReplySnippet } from '$lib/server/integrations/rcon-diagnostics.js';
/**
* On-demand RCON probe for a specific server. Same code path as the periodic
@@ -39,14 +40,14 @@ export const POST: RequestHandler = async ({ params }) => {
setServerField(name, 'last_checked_at', now);
setServerField(name, 'last_error', null);
setServerField(name, 'rcon_failures', 0);
setServerField(name, 'last_reply_snippet', result.rawReply);
setServerField(name, 'last_reply_snippet', null);
} else {
const encoded = `${result.reason}:${result.detail}`;
setServerField(name, 'last_checked_at', now);
setServerField(name, 'last_error', encoded);
// An explicitly requested diagnostic failure takes effect immediately.
setServerField(name, 'rcon_failures', 2);
setServerField(name, 'last_reply_snippet', result.rawReply ?? null);
setServerField(name, 'last_reply_snippet', failureReplySnippet(result));
}
return json(result);
@@ -0,0 +1,11 @@
import { json } from '@sveltejs/kit';
import { getServer } from '$lib/server/fleet/servers.js';
import { redactRconAddresses } from '$lib/server/integrations/rcon-diagnostics.js';
/** Saved failure evidence; the authentication guard restricts this route to operators. */
export function GET({ params }: { params: { name: string } }) {
const server = getServer(params.name);
if (!server || server.destroyed_at) return json({ error: 'No such server.' }, { status: 404 });
return json({ replySnippet: server.last_error && server.last_reply_snippet
? redactRconAddresses(server.last_reply_snippet) : null }, { headers: { 'Cache-Control': 'no-store' } });
}