feat(ssh): wire ProxyJump as bastion and ProxyCommand as transport#380
Merged
Conversation
There was a problem hiding this comment.
Pull request overview
This PR extends the SSH protocol implementation to match OpenSSH jump/command semantics by (1) wiring ProxyJump into rig’s existing bastion support and (2) adding ProxyCommand as an alternative transport by running the configured command and bridging its stdin/stdout as a net.Conn.
Changes:
- Auto-populate
Config.Bastionfrom the firstProxyJumphop when no explicit bastion is configured. - Add
ProxyCommandtransport support (subprocess-backednet.Conn+ deadline-aware handshake). - Add unit/integration tests covering
ProxyJumpparsing/bastion wiring andProxyCommandprecedence/end-to-end connect.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 4 comments.
| File | Description |
|---|---|
protocol/ssh/connection.go |
Wires ProxyJump into Config.Bastion, adds ProxyCommand precedence, and reaps proxy subprocesses on disconnect. |
protocol/ssh/proxy.go |
Implements ProxyJump parsing and the ProxyCommand subprocess transport (cmdConn) + handshake flow. |
protocol/ssh/proxy_test.go |
Adds tests for ProxyJump parsing/bastion behavior and ProxyCommand precedence + end-to-end transport bridging. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
6b20940 to
95423ef
Compare
95423ef to
882e1bf
Compare
882e1bf to
a66847c
Compare
a66847c to
886d4e9
Compare
886d4e9 to
c9a2401
Compare
c9a2401 to
8e33437
Compare
8e33437 to
7207ded
Compare
Auto-populate Config.Bastion from the first ProxyJump entry in sshconfig when no explicit Bastion is configured (t-088). Support ProxyCommand as an alternative SSH transport by running the command and bridging its stdin/stdout as a net.Conn (t-099). ProxyCommand takes precedence over ProxyJump when both are set, matching OpenSSH behaviour. Key design decisions: - ProxyCommand process is bound to Connection lifetime (stored in c.proxyCmd, reaped in disconnect()), not the connect context, so the transport survives after Connect() returns. - SSH handshake runs in a goroutine with a select on the connect deadline so stalled handshakes are abortable even though SetDeadline is a no-op on a pipe transport. - cmdConn.RemoteAddr() returns the real dst address so the knownhosts callback can call SplitHostPort on it without error. - Token expansion (%h, %p, %r, etc.) is already handled by sshconfig.Setter.Finalize() called inside ConfigParser.Apply(). Signed-off-by: Kimmo Lehto <klehto@mirantis.com>
3a5315d to
a53cd34
Compare
Signed-off-by: Kimmo Lehto <klehto@mirantis.com>
Signed-off-by: Kimmo Lehto <klehto@mirantis.com>
Signed-off-by: Kimmo Lehto <klehto@mirantis.com>
Signed-off-by: Kimmo Lehto <klehto@mirantis.com>
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.
Auto-populate Config.Bastion from the first ProxyJump entry in sshconfig when no explicit Bastion is configured (t-088). Support ProxyCommand as an alternative SSH transport by running the command and bridging its stdin/stdout as a net.Conn (t-099).
When both ProxyCommand and ProxyJump are set, ProxyCommand takes precedence. This intentionally diverges from OpenSSH's first-match semantics (whichever directive appears first in ssh_config wins): the sshconfig parser does not preserve directive order, so first-match cannot be replicated. In practice, both directives being set simultaneously is rare (they come from different Host blocks), and ProxyCommand-wins is a safe default. An explicitly-configured Config.Bastion (not from ProxyJump) always takes priority over ProxyCommand.
Key design decisions: