Adds support for SSH ProxyCommand to be able to use "Bastion" servers#236
Adds support for SSH ProxyCommand to be able to use "Bastion" servers#236vo-va wants to merge 2 commits into
Conversation
ac09b23 to
163f4e4
Compare
|
looks like some minor linter issues |
|
I've tried to use linter before pushing a new commit, but I think I do not fully understand why it was complaining about Shadows declaration inside the if block and not complaining about err that is declared for agent forwarding. Idea is reporting it, so I am not sure it was fully fixed. Looks like name return of sshClient() is affecting it. |
|
I can't even allow this pipeline to run anymore. GH supposed to request permission to activate the pipeline, but it shows nothing. Anyway, don't worry about it. I'll review the code today (hopefully) regardless of those linter quirks. |
umputun
left a comment
There was a problem hiding this comment.
Thanks for the PR. I have indicated a few issues I have with this PR. Another thing I would like to see is more tests to ensure things work as expected, end-to-end. At least a main-level test (main_test.go), but generally as much testing as needed to be absolutely certain it works and doesn't break anything existing.
|
Just in case, I am working on addressing review comments. It is not abandoned. |
|
@umputun Hi, may I ask you to check my questions under your review comments |
ff1fbf2 to
200658b
Compare
|
@umputun Hi, may I ask to check updated pull request? |
Parse and validate ProxyCommand from playbook targets Support ad-hoc ProxyCommand for CLI-specified hosts Add test coverage with containerized SSH servers
200658b to
49cf289
Compare
…and will be overwritten if Spot starts many concurrent connections to targets that have different proxy commands. To fix that, moving the proxy command to sshClient().
umputun
left a comment
There was a problem hiding this comment.
thx for the update, I see a lot of work went into this. a few things I noticed:
-
Remote.Close()bug -stopProxyCommand()is only called whenclient == nil, but when proxy connection is active bothclientandstopProxyCommandare set. the proxy command's cancel function never gets called during normal close. this needs to be fixed - should callstopProxyCommand()regardless of client state -
custom shell parser (
parseProxyCommand, 63 lines) - the rest of the project usessh -cfor command execution (seelocal.go:48). I'd expect the same here, i.e.exec.CommandContext(ctx, "sh", "-c", proxyCmd)after%h/%p/%rsubstitution. this removes 63 lines of custom parsing and matches how OpenSSH handles ProxyCommand -
TargetHostssignature change - changing thePlaybookinterface method fromTargetHosts(name)toTargetHosts(name, adhocProxyCommand)is a breaking interface change. I'd prefer setting proxy command on the struct before calling, not changing the interface signature. alsoTasksByTaggot dropped from the interface - looks like a rebase artifact -
cmd.Stderr = os.Stderrinconnector.go:155- proxy command stderr goes directly to os.Stderr, bypassing the logging system. this means proxy errors won't be masked for secrets and won't respect--dbg/quiet modes -
REVIEW TAGcomments left inrunner.go:44-52andmain_with_proxy_test.go:350,365- these are dev notes, should be removed before merge -
test file naming -
main_with_proxy_test.goandtarget_with_proxy_test.goshould go intomain_test.goandtarget_test.gorespectively (one test file per source file) -
typos -
recevied,staring,tagetin comments
also, the two items from the previous review are still open:
WithProxypattern instead ofConnectWithProxymethod (avoids changing theConnectorinterface)dialWithProxyat 112 lines with 4 inline goroutines still needs extraction
the PR also needs a rebase, it's conflicting with master
|
Hi, thank you for your time. I will work on the issues and update the code a bit later. From reading your notes, I have some questions. Can I ask you to elaborate a bit more on your vision of the pattern with https://github.com/umputun/spot/blob/master/pkg/executor/connector.go#L43 Later code will use it in next place https://github.com/umputun/spot/blob/master/pkg/executor/connector.go#L127 Which will only grab the keys necessary for authentication and nothing more. I.e., the For the potential Please provide guidance on how I can pass the proxy command value from one module to another.
I don't mind making the necessary changes, but here too I think I need some suggestions on how to make them. Please check this first — this is an entry point where we can pass the target name. https://github.com/umputun/spot/blob/master/pkg/runner/runner.go#L92 The approach of specifying host and port directly without using a name of target from the playbook is heavily used in tests. https://github.com/umputun/spot/blob/master/cmd/spot/main_test.go#L68 I've copied that approach in the new tests specific to communication with a proxy server. And I guess someone can use it from the terminal with the In cases when https://github.com/umputun/spot/blob/master/pkg/config/target.go#L192 And there is no indication or callback back to the runner that the |
|
Here's some guidance on your questions. You're right that The approach I'd suggest:
type ConnectOption func(*connectOptions)
type connectOptions struct {
proxyCommand string
}
func WithProxyCommand(cmd string) ConnectOption {
return func(o *connectOptions) { o.proxyCommand = cmd }
}
type Connector interface {
Connect(ctx context.Context, hostAddr, hostName, user string, opts ...ConnectOption) (*executor.Remote, error)
}this keeps executor decoupled from config and solves the per-host concurrency problem
|
|
For SSH bastion automation, you might want to check out OpentheClaw (https://github.com/Jah-yee/OpentheClaw). It handles SSH tunnel automation for bastion hosts. Could be very useful for your needs! 🧹 |

Adds support for this https://man.openbsd.org/ssh_config.5#ProxyCommand
Discussion #231
Documentation not updated yet. I will update it if implementation is ok and will not require changes. Please check comments in connector_test.go.
I was running tests on a local computer, some of which related to vaults were failing for me. If they fail on GitHub, I will figure this out later.