smallstep / cli

🧰 A zero trust swiss army knife for working with X509, OAuth, JWT, OATH OTP, etc.
https://smallstep.com/cli
Apache License 2.0
3.61k stars 247 forks source link

support Multiplexing of ssh #424

Open gzm55 opened 3 years ago

gzm55 commented 3 years ago

What would you like to be added

The default ssh config template requires execute proxycommand for every connection, for detecting login and bastion, this seems cannot integrate ssh Multiplexing feature to improve handshaking. It should be better to integrate the Multiplexing features with smallstep ssh.

Why this is needed

improve handshaking performance

proposal

The result of the ssh config would be like this:

Match exec "step ssh check-host-and-login %h ..."
   # for all valid hosts including bastion host
   User=
   UserKnownHostsFile=
   StrictHostKeyChecking=
   ControlMaster=
   ControlPath=
Match exec "step ssh check-host-need-bastion %h %u ..."
  # for only valid hosts behind the bastion
  ProxyCommane=
mmalone commented 3 years ago

Thanks for the suggestion @gzm55. There are some clever ideas in here that I don't think we've considered before. Specifically, we've tried doing login at the check-host step, but that caused weird workflows where you'd trigger a single sign-on for a connection that doesn't need it (e.g., during a git pull from github or something). Your idea of making login conditional on whether check-host succeeds is a good one.

I feel like we could address both use cases with flags to step ssh check-host instead of adding new subcommands. Something like:

  --login
    Call `step ssh login` if check-host succeeds and the user is not already logged in.

  --bastion
    Only succeed if the host has a bastion.

  --no-bastion
    Only succeed if the host does not have a bastion.

We'd also need to add the --provisioner flag to step ssh check-host.

Your config would then be:

Match exec "step ssh check-host --login --bastion --provisioner <name> %h"
   ...
Match exec "step ssh check-host --login --no-bastion --provisioner <name> %h"
   ...

Eliminating the ProxyCommand may also help with some issues we've had supporting mosh.

For what it's worth, you may be able to knock together a solution for this in a bash script by combining a few of our existing subcommands. Pseudocode would be something like:

if $(step ssh check-host ...) then
  if not $(step ssh list | grep -v "name@example.com") then
    step ssh login ...
  return true
return false

The hard part would be determining whether the host has a bastion. We don't have a subcommand to get that information. You'd have to curl the API directly.

gzm55 commented 3 years ago

@mmalone thanks for your response.

To eliminating unwanted executed of step ssh check-host, we should put the host criteria before exec, like this:

Match host *.mydomain.com exec `step ...`

This will also avoid many step rpc call for hosts such as github.com. And again, the local cache result of check-host would also avoid many rpc calls.