Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Generate an updated ~/.ssh/config when using "advanced" regex in hostnames #122

Closed
6 tasks
moul opened this issue Feb 25, 2016 · 2 comments
Closed
6 tasks
Assignees
Milestone

Comments

@moul
Copy link
Owner

moul commented Feb 25, 2016

Context

Today, assh will generate an Host entry in the ~/.ssh/config for:

  • hosts without regex: vm-5
  • hosts with simple regex (match): vm-*
  • but not for hosts with advanced regex: vm-[0-9]

So basically, assh knows how to proxy to an host, but all options except Host won't be written to ~/.ssh/config.
So there will be absolutely no entry in the ~/.ssh/config file if we call ssh vm-5, and all options except Host will be lost; Port will fallback to 22, IdentifyFile will use the global value, etc.


2 dummy solutions would be:

  • Find a way to generate the wildcard equivalent regex in the ~/.ssh/config file, so if you put vm-[0-9], I will generate vm-*: this will work for basic regex but it will fails as soon as you have advanced regex, i.e an entry with vm-[0-4], and another entry with vm-[5-9].
  • Analyze the ssh command-line parameters, so I can detect if you put a -p 22 manually or if the %p=22 is the default value. This solution will works for Port, but it won't let you use non-network related ssh option, as IdentityFile for instance.

One more promising solution is to a wrapper around ssh that will rebuild the ~/.ssh/config file if it detects an advanced regex in the current host.
The wrapper will just check if ~/.ssh/config needs to be rebuild before running the real ssh binary.

This wrapper won't be configurable everywhere outside of the command-line, for example a GUI program may use an hardcoded /usr/bin/ssh.
For this specific case, the solution is to call the ssh 2 times; One time to generate the ~/.ssh/config file and fail, and a second time to connect using the updated file.

The good point, is that this wrapper will stay optional and will only improve the use of assh in advanced cases.


Todo:

  • create a wrapper script for ssh, scp, ...
  • document how to install the wrapper + the limitation when using applications with hardcoded path to /usr/bin/ssh
  • automatically install the wrapper when installing assh using Homebrew
  • parse ~/.ssh/known-hosts and generate ~/.ssh/config entries for all the known hosts
  • assh proxy needs to continue to build the ~/.ssh/config file when using assh without the wrapper and needs to bypass this step when using the wrapper (the wrapper will do this step before calling ssh)
  • add a debug message at the beginning of assh telling if ssh is wrapped or not (for debugging)

I'm eager to have this wrapper finished, it will ease a lot the creation of new unique features 🍻 !

Some ideas:

  • support raw password input (using pexpect)

  • use alternate ssh binary depending on the assh.yml configuration:

    SSHProgram: docker run -it --rm ssh
    SSHProgram: nice -10 ssh
    SSHProgram: /path/to/alternative/ssh-binary
    SSHProgram: chroot /chrooted-ssh /bin/ssh
    SSHProgram: mosh     # probably a bad idea
    
  • configure custom environment variables

  • equivalent of https://github.com/icefox/git-achievements for ssh

  • dynamically create a new ssh RSA key per new host

  • support a default command to run

    my-server:
      DefaultCommand: tmux a -t work
    $ ssh my-server
    # the wrapper will call "/usr/bin/ssh my-server -- tmux a -t work
    
    $ ssh my-server bash
    # the wrapper will call "/usr/bin/ssh my-server -- bash
  • automatically reconnect

  • automatically call ssh-copy-id on new hosts

  • support assh options directly in the command line

  • sshrc-like features


Related with #121, #39, #41, #127

@rothgar
Copy link

rothgar commented Mar 14, 2016

I'm not too fond of the wrapper idea for a few reasons

  • I don't use brew/OS X
  • Needing to wrap all basics commands that use .ssh/config (scp, rsync, etc.)

I have tried (and seen others) make shell functions to replace ssh but that can get ugly depending on complexity, version of bash, version of ssh, etc. IMO a function is more maintainable than a separate external script that needs to be loaded in $PATH. It also gets hard when people use different shells and if they keep their own .dotfiles repo for configuration.

Also not sure about parsing ~/.ssh/known-hosts. In some situations that file can be very large. I often have hundreds of hosts in mine. Would you also parse /etc/ssh/ssh_known_hosts? In that case the file on my system changes regularly (every ~30 minutes) via config management and has many thousands of entries.

Why not have assh expand the advanced regex into .ssh/config so they are individual entries. Maybe that would expand to a lot (depending on the regex) for for some cases (eg. host[0-9]) it wouldn't be very hard.

As a side note, why is using mosh as a default command a bad idea? I'm assuming because not all flags are compatible with ssh but thought I'd ask. I was going to open an issue for allowing mosh to be used as default instead of ssh depending on what network I'm on. eg. connected via wifi or 3g use mosh instead of ssh but that's probably best for a shell function.

Default commands are probably best to be left to the shell post login. There is too much logic that may need to be considered.

@moul
Copy link
Owner Author

moul commented Mar 14, 2016

Thank you @rothgar for your feedback 🎁 !

I'm not too fond of the wrapper idea for a few reasons

  1. I don't use brew/OS X
  2. Needing to wrap all basics commands that use .ssh/config (scp, rsync, etc.)
    I have tried (and seen others) make shell functions to replace ssh but that can get ugly depending on complexity, version of bash, version of ssh, etc. IMO a function is more maintainable than a separate external script that needs to be loaded in $PATH. It also gets hard when people use different shells and if they keep their own .dotfiles repo for configuration.

👍 for also providing just a *sh function or an alias that people can keep in their own .dotfiles

Also not sure about parsing ~/.ssh/known-hosts. In some situations that file can be very large. I often have hundreds of hosts in mine. Would you also parse /etc/ssh/ssh_known_hosts? In that case the file on my system changes regularly (every ~30 minutes) via config management and has many thousands of entries.

Yes, as an alternative, I can build my own assh-known-hosts file without all the ssh key fingerprint stuff, just a list of hosts that already have been directly called using assh.
This file is already an optimization, if I don't use any caching system, the wrapper will always reload ssh on new hosts.
So we need to find the best approach to get at least .ssh/config regeneration as possible.

Why not have assh expand the advanced regex into .ssh/config so they are individual entries. Maybe that would expand to a lot (depending on the regex) for for some cases (eg. host[0-9]) it wouldn't be very hard.

I like the idea, we need to find a regex expander to give some tries and estimate how big would become a .ssh/config file with the different cases.
If we choose this method, we will probably need to add a new ⚠️ message when the expander detects a too huge regex, so the user can adapt its regex to something smaller.

As a side note, why is using mosh as a default command a bad idea? I'm assuming because not all flags are compatible with ssh but thought I'd ask. I was going to open an issue for allowing mosh to be used as default instead of ssh depending on what network I'm on. eg. connected via wifi or 3g use mosh instead of ssh but that's probably best for a shell function.

I just opened #129, to discuss about this subject

Default commands are probably best to be left to the shell post login. There is too much logic that may need to be considered.

I think this feature makes sense, especially as I'm using Docker on a daily basis, now I love to have "images" that have a default behavior which can super-easily be bypass by specifying a command instead of not providing one.
👍 to document this well in the README.md !

@moul moul added this to the v2.3.0 milestone Mar 21, 2016
moul added a commit that referenced this issue Mar 29, 2016
moul added a commit that referenced this issue Mar 30, 2016
moul added a commit that referenced this issue Mar 30, 2016
@moul moul mentioned this issue Apr 6, 2016
10 tasks
moul added a commit that referenced this issue Apr 6, 2016
moul added a commit that referenced this issue Apr 8, 2016
moul added a commit that referenced this issue Apr 8, 2016
moul added a commit that referenced this issue Apr 8, 2016
moul added a commit that referenced this issue Apr 8, 2016
@moul moul closed this as completed in #141 Apr 27, 2016
moul added a commit that referenced this issue Apr 27, 2016
@moul moul removed the in progress label Apr 27, 2016
moul added a commit that referenced this issue Apr 27, 2016
moul added a commit that referenced this issue Apr 27, 2016
moul added a commit that referenced this issue Apr 27, 2016
moul added a commit that referenced this issue Apr 27, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants