There is a saying that something is more than sum of it’s parts, meaning it is the specific combination of things that makes it useful or valuable. But it can also be that one those parts is especially useful on it’s own too.

I did post earlier how you can (and should) get rid of bad habbit of using bastion hosts.

The Essense of those can be summarized into one-liner in .ssh/config

Host i-*.* mi-*.*
  ProxyCommand bash -c "aws ssm start-session --target $(echo %h|/usr/bin/cut -d'.' -f1) --region $(echo %h|/usr/bin/cut -d'.' -f2) --document-name AWS-StartSSHSession --parameters 'portNumber=%p'"

Let’s dissect above letter by letter

Host i-*.* mi-*.*

This applies following configuration when remote hostname matches one of the patterns. i-* is for regular EC2 instances and mi-* will match for any managed instances if you have some. Remember you can manage also non-EC2 VMs from other clouds or data center with SSM, and the same trick works for them too.

ProxyCommand bash -c "aws ssm start-session --target $(echo %h|cut -d'.' -f1) --region $(echo %h|/usr/bin/cut -d'.' -f2) --document-name AWS-StartSSHSession --parameters 'portNumber=%p'"

ProxyCommand is what ssh will run to open a connection to target host. Command can be almost anything as long as it reads from stdin and writes to stdout. Here you will be using aws ssm start-session to open a pipe to remote host. Interesting part is how arguments of start-session are constructed.

---target $(echo %h|/usr/bin/cut -d'.' -f1)

Here echo %h will send the remote hostname you specified on command line, and it will be cut at the first dot (.) leaving just the instance ID of it.

--region $(echo %h|/usr/bin/cut -d'.' -f2)

Using the same way the remaining part after the first dot (.) is extracted and passed as region to aws-cli. Calling your hosts by InstanceID.Region is just a clever way to make this work for multiple regions without you having to change AWS_DEFAULT_REGION environment variable to jump from one region to another.

Another small but important detail is calling cut with full path. Leaving the path off could cause problems when ProxyCommand is run with a shell that doesn’t it’s PATH set properly. This is also a bit of added security so you can be sure what commands are run.

---parameters 'portNumber=%p'

And finally just another parameter substitution where %p is replaced with port number of remote host. Please refer to manual for complete list of configuration options in .ssh/config and tokens available for ProxyCommand

Now you can, not just ssh to instance without having a network connectivity between your laptop and VPC, but also use scp and other ssh-tools. This has proven itself extermely useful during ad-hoc troubleshooting for clients I don’t work with on daily basis. All I need is access to AWS API with key/secret/token, instance-id and region.

% ssh
Last login: Wed Dec 30 08:23:41 2020 from localhost

       __|  __|_  )
       _|  (     /   Amazon Linux 2 AMI
[username@ip-10-0-0-91 ~]$

I learned this valuable one-liner from Jim Lamb’s blog.

Edit 19/10/2022; AWS blog has a more visual version of the same use-case with EC2 Instance Connect deploying temporary SSH keys