thzinc

Quality of life improvements for SSH via AWS EC2 Instance Connect

While doing some work in AWS with EC2 instances through Systems Manager, I needed to be able to connect via SSH in a reasonable way. The AWS docs for Session Manager show off SSH’s ProxyCommand, but I also needed to use EC2 Instance Connect to send my public key ahead of trying to connect, so I wrote a small script to combine the two operations.

aws_ssm_proxy.sh:

Ensure this script is only executable by your own user. (e.g., chmod 744 aws_ssm_proxy.sh) Treat it with the same protections you’d use for ~/.ssh/config.

#!/bin/bash
set -euo pipefail

REMOTE_USERNAME=$1
REMOTE_HOSTNAME=$2
PORT_NUMBER=$3
shift 3

PREFERRED_PUBLIC_KEY="ssh-rsa AAAAA....." # Replace with what makes sense for your environment
echo "Sending SSH public key for EC2 Instance Connect..."
aws ec2-instance-connect send-ssh-public-key --instance-id "$REMOTE_HOSTNAME" --instance-os-user "$REMOTE_USERNAME" --ssh-public-key "$PREFERRED_PUBLIC_KEY" --no-cli-pager &&
    aws ssm start-session --target "$REMOTE_HOSTNAME" --document-name AWS-StartSSHSession --parameters "portNumber=$PORT_NUMBER" "$@"

Take note of PREFERRED_PUBLIC_KEY above. This should be set to your public key to use.

Then, update your ~/.ssh/config to use aws_ssm_proxy.sh:

# SSH over Session Manager
host i-* mi-*
	ProxyCommand ~/.ssh/aws_ssm_proxy.sh %r %h %p

Make sure this host line is above any default host * configuration!

For reference, the tokens used in ProxyCommand are:

Token Description
%h The remote hostname.
%p The remote port.
%r The remote username.

With this config in place, I can now use normal SSH tools (ssh, scp, etc.)

ssh ubuntu@i-xxxxxxxxxxxxxxxx # Use my default AWS profile to connect to an instance
AWS_PROFILE=my_other_profile ssh ubuntu@i-xxxxxxxxxxxxxxxx # Use a particular AWS profile to connect to an instance