using System.IO; using System.Linq; using System.Text.Json; using System.Threading; using System.Threading.Tasks; using Gott.Services; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Routing; namespace Gott.Endpoints; /// /// Interne API-Endpoints für MCP-Server und andere lokale Integrationen. /// Gesichert über einen internen Token (da Reverse-Proxy den Localhost-Check umgeht). /// public static class InternalEndpoint { /// /// Interner Auth-Token – wird beim Start generiert und an MCP-Server übergeben. /// public static string InternalToken { get; } = System.Guid.NewGuid().ToString("N"); public static void MapInternalEndpoints(this IEndpointRouteBuilder app) { app.MapPost("/api/internal/remote-execute", HandleRemoteExecute); } private static async Task HandleRemoteExecute(HttpContext ctx, RemoteConnectionManager mgr) { try { // Token-Check: Header "X-Internal-Token" muss den internen Token enthalten var token = ctx.Request.Headers["X-Internal-Token"].FirstOrDefault() ?? ""; if (token != InternalToken) return Results.StatusCode(403); using var reader = new StreamReader(ctx.Request.Body); var body = await reader.ReadToEndAsync(); JsonElement json; try { json = JsonSerializer.Deserialize(body); } catch { return Results.BadRequest(new { error = "Invalid JSON" }); } var command = json.TryGetProperty("command", out var cmd) ? cmd.GetString() ?? "" : ""; var sessionId = json.TryGetProperty("sessionId", out var sid) ? sid.GetString() ?? "" : ""; if (string.IsNullOrEmpty(command)) return Results.BadRequest(new { error = "command erforderlich" }); if (string.IsNullOrEmpty(sessionId)) return Results.BadRequest(new { error = "sessionId erforderlich" }); var conn = mgr.GetBySessionId(sessionId); if (conn == null) return Results.NotFound(new { error = "Keine Remote-Verbindung für diese Session" }); using var cts = new CancellationTokenSource(System.TimeSpan.FromSeconds(180)); var result = await mgr.ExecuteCommand(conn.Id, command, 180, cts.Token); return Results.Ok(new { exitCode = result.ExitCode, stdout = result.Output ?? "", stderr = result.Error ?? "" }); } catch (System.Exception ex) { return Results.Json(new { error = ex.Message, stackTrace = ex.StackTrace }, statusCode: 500); } } }