feat(coderd): log tailnet tunnels to the connection log #27423
Draft
sreya wants to merge 5 commits into
Draft
Conversation
Agent-reported SSH/VSCode/JetBrains connection_log rows have no user_id
because the agent does not know which Coder user connected (see the
comment in coderd/agentapi/connectionlog.go). This makes it impossible
to attribute SSH/IDE sessions to a Coder user from the connection log.
Every such session is carried over a tailnet tunnel that the client
opens via /api/v2/workspaceagents/{id}/coordinate using the user's API
key, so coderd knows the user at that point.
Add a new connection_type 'tailnet' and write one connection_log row
from workspaceAgentClientCoordinate whenever an authenticated user
successfully upgrades the coordinate WebSocket. The row carries
user_id, ip, user_agent, workspace_id and agent_name, and is rendered
via WebInfo alongside workspace_app / port_forwarding.
Address review feedback on the original changeset: - Rebase onto main and renumber the migration to 000551 to resolve the collision with 000539_ai_provider_icons. - Rename the connection_type value tailnet to tunnel across the migration, codersdk, enterprise converter, and frontend, since the enum value is permanent API surface and should name the event rather than the transport. - Implement a real down migration that recreates connection_type without the tunnel value, following the pattern in 000533_nats_ca_crypto_key_feature.down.sql. - Update the remaining connection_logs column comments (slug_or_port, disconnect_time, disconnect_reason) to the agent-reported vs coderd-reported taxonomy. - Extract the connection log write into api.logTunnelConnection and bound it with a 3s timeout so connection log backpressure cannot stall tunnel establishment. - Cover the status-filter exclusion with a tunnel fixture in TestConnectionLogsOffsetFilters and the WebInfo mapping with a WebInfoTunnel subtest. - Harden the coordinate test: testutil.Context, AwaitReachable assertion, Code/ConnectionStatus expectations, and a second dial asserting each handshake produces its own row. - Document tunnel connections and their semantics in docs/admin/monitoring/connection-logs.md. - Clarify the connectionTypeIsWeb helper and replace the unreachable Unauthenticated user copy in the tunnel description branch. Co-authored-by: Chris DiGiamo <cdigiamo@anthropic.com>
Reuse the workspace_app_audit_sessions mechanism to collapse tunnel reconnections into one connection log row per active session. Clients automatically re-dial the coordinate endpoint after network blips, load balancer timeouts, and coderd restarts, so logging every handshake would flood the connection log with reconnect noise that is indistinguishable from genuine user activity. Tunnel sessions are keyed on (agent, user, IP, user agent) with app_id = uuid.Nil and an empty slug, matching how port forwarding uses the table; status code 101 keeps them from colliding with app sessions. A new row is logged only when no session exists for the key or the session has been idle past the stale interval (1 hour by default, sliding). On dedup failure the log write is skipped, matching the workspace app precedent of not spamming the connection log during database problems.
Removing an enum value requires recreating connection_type and rewriting the connection_logs type column, which takes an exclusive lock on the table and would have to delete all tunnel rows because they cannot exist in the old type. Leaving the value in place is harmless and matches the precedent of other enum-value additions.
Explain how the status code keeps tunnel audit sessions from colliding with app and port forwarding sessions: the status code is part of the session unique key, and app sessions record the token authorization status (200, 4xx) while tunnel sessions always record 101, so the keys can never conflict. Drop the redundant 'failed' suffix from the error log messages; the Error level already implies failure.
Docs previewCheck off each page once it's been reviewed. If a page changes in a later push, its checkbox clears automatically so it gets a fresh look. Pages not yet wired into the docs navigation aren't listed here. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.