mirror of
https://github.com/GNS3/gns3-server.git
synced 2026-11-03 05:51:15 +02:00
fix: issue short-lived console tickets instead of JWTs in node_console MCP tool
LLM clients transcribing the console WebSocket URL into shell commands
reliably corrupted the ~200-char JWT embedded in it (dropped header
segment -> "MissingAlgorithmError: Missing 'alg' value in header" on
every connection attempt). The node_console tool now mints a short
random ticket ("gns3t_" + 16 urlsafe chars, 10 min TTL, multi-use)
stored server-side and bound to the node's console endpoints:
- new ConsoleTicketService (gns3server/services/console_tickets.py),
in-memory store with lazy expiry sweeps
- get_current_active_user_from_websocket redeems tickets through the
existing "token" query parameter, gated on websocket.path_params so a
ticket only authenticates the console/ws and console/vnc routes of
the node it was minted for; the JWT path is unchanged
- redemption reuses the existing user lookup, token_version revocation
and is_active checks, so logging out invalidates outstanding tickets
- vnc_url no longer embeds the full session JWT
- the tool docstring now tells clients to run the returned command
verbatim instead of reconstructing the URL
This commit is contained in:
9 files changed
+431
-30
No files matched your search
@@ -439,7 +439,7 @@ sequenceDiagram
|
||||
|
||||
### Console WebSocket
|
||||
|
||||
The `node_console` tool returns a WebSocket URL for connecting to a node's console. The URL includes a short-lived JWT (10 min) — reconnect if it expires. This endpoint is protocol-agnostic — it works for **telnet**, **ssh**, and **vnc** console types alike. The WebSocket simply proxies raw byte streams between the client and the compute node; protocol negotiation (e.g. SSH key exchange) happens on the compute side.
|
||||
The `node_console` tool returns a WebSocket URL for connecting to a node's console. The URL includes a short-lived **console ticket** (10 min) — a short random string (`gns3t_…`, 22 chars) minted server-side and bound to that node's console endpoints. Tickets replaced the long JWT previously embedded here: LLM clients retyping the URL into shell commands reliably corrupted a ~200-char JWT, while a short ticket survives copying. Re-request the URL when the ticket expires (logging out also invalidates outstanding tickets). This endpoint is protocol-agnostic — it works for **telnet**, **ssh**, and **vnc** console types alike. The WebSocket simply proxies raw byte streams between the client and the compute node; protocol negotiation (e.g. SSH key exchange) happens on the compute side.
|
||||
|
||||
The WebSocket URL is constructed using the server's `_server_url()`, which resolves the host as follows:
|
||||
|
||||
@@ -454,11 +454,11 @@ When `Server.host` is `0.0.0.0` (listen on all interfaces), the MCP server disco
|
||||
|
||||
If the configured host is already a specific IP or hostname (not `0.0.0.0`), it is used directly in the URL without modification.
|
||||
|
||||
Use `websocat` to connect from the command line:
|
||||
Use `websocat` to connect from the command line (use the `command` returned by `node_console` verbatim — never reconstruct the URL by hand):
|
||||
|
||||
```bash
|
||||
# The host in the URL is automatically resolved to a reachable address
|
||||
websocat ws://192.168.1.3:3080/v3/projects/{project_id}/nodes/{node_id}/console/ws?token=<jwt>
|
||||
websocat ws://192.168.1.3:3080/v3/projects/{project_id}/nodes/{node_id}/console/ws?token=<console_ticket>
|
||||
```
|
||||
|
||||
### Source Files
|
||||
|
||||
@@ -58,7 +58,7 @@ graph LR
|
||||
**URL**: `ws://{controller_host}:{port}/v3/projects/{project_id}/nodes/{node_id}/console/vnc?token={jwt_token}`
|
||||
|
||||
**Authentication**:
|
||||
- JWT token via query parameter
|
||||
- JWT token via query parameter, **or** a short-lived console ticket (`gns3t_…`, minted per node by the `node_console` MCP tool, valid 10 min, bound to this node's console endpoints)
|
||||
- User must have `Node.Console` privilege
|
||||
|
||||
**WebSocket Subprotocols**:
|
||||
@@ -179,7 +179,7 @@ sequenceDiagram
|
||||
|
||||
1. **Authentication**:
|
||||
- JWT token validation via `has_privilege_on_websocket("Node.Console")` dependency
|
||||
- Token passed as query parameter: `?token={jwt}`
|
||||
- Token passed as query parameter: `?token={jwt}`, or a console ticket (`gns3t_…`) redeemable only on the node it was minted for
|
||||
|
||||
2. **Authorization**:
|
||||
- RBAC privilege check: `Node.Console`
|
||||
|
||||
Reference in new issue
Block a user