Created
February 25, 2025 14:36
-
-
Save pdehlke/182974a79623b91c08b41a501a230c36 to your computer and use it in GitHub Desktop.
Use https://www.granted.dev/ to manage aws credentials. awssh and ssh-ssm.sh to run ssh over ssm without a vpn. Instructions are in ssh-ssm.sh
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env zsh | |
set -o pipefail -o errexit | |
die() { | |
echo "$1" >&2 | |
exit 1 | |
} | |
[[ -z ${AWS_PROFILE} ]] && die "[FATAL]: no AWS_PROFILE set. Assume an indentity please." | |
aws sts get-caller-identity >/dev/null 2>&1 || die "[FATAL]: You do not seem to have a valid AWS session credential" | |
# If we're using zsh4humans like God intended, use the builtins for ssh teleportation | |
[[ ! -z $_Z4H_EXE ]] && SSH_PRE='z4h' | |
echo "finding instance-id for ${1}" | |
if [[ $1 =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$ ]]; then | |
INSTANCE=$(aws ec2 describe-network-interfaces --filter Name=private-ip-address,Values=${1} --query 'NetworkInterfaces[].Attachment[].InstanceId' --output text) | |
else | |
INSTANCE_IP=$(dig +short ${1}) | |
[[ -z ${INSTANCE_IP} ]] && die "[FATAL]: could not find an IP address for ${1}" | |
INSTANCE=$(aws ec2 describe-instances --filter Name=private-ip-address,Values=${INSTANCE_IP} --query 'Reservations[].Instances[].InstanceId' --output text) | |
if [[ -z $INSTANCE ]]; then | |
INSTANCE=$(aws ec2 describe-network-interfaces --filter Name=private-ip-address,Values=${INSTANCE_IP} --query 'NetworkInterfaces[].Attachment[].InstanceId' --output text) | |
fi | |
fi | |
[[ -z ${INSTANCE} ]] && die "[FATAL]: could not find instance-id for ${1}" | |
echo "connecting to $INSTANCE" | |
${SSH_PRE} ssh ${INSTANCE} || die "[FATAL]: failed to ssh to instance ${INSTANCE}, identified by ${1}" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env bash | |
# | |
# Use ssm to start an ssh session on an ec2 instance using a short-lived temporary | |
# key injected into the instance metadata. No long term ssh keys are used or needed. | |
# | |
# You should use this with a block in your .ssh/config that looks roughly like this: | |
# | |
# Match host i-* | |
# User pete | |
# ProxyCommand ssh-ssm.sh %h %r | |
# IdentityFile ~/.ssh/ssm-ssh-tmp | |
# StrictHostKeyChecking no | |
# PasswordAuthentication no | |
# KbdInteractiveAuthentication no | |
# ChallengeResponseAuthentication no | |
# ControlPath ~/.ssh/master-%r@%h:%p | |
# ControlMaster auto | |
# ConnectTimeout 10 | |
# ServerAliveInterval 45 | |
# AddKeysToAgent yes | |
# HostKeyAlgorithms ssh-ed25519 | |
# | |
# See also the awssh script, which works out an instance ID based on either hostname | |
# or ip address and calls ssh with the appropriate target, which invokes this script | |
# | |
# set -x | |
export PS4='+(${BASH_SOURCE}:${LINENO}): ${FUNCNAME[0]:+${FUNCNAME[0]}(): }' | |
set -o nounset -o pipefail -o errexit | |
function main { | |
local ssh_pubkey ssm_cmd | |
local ssh_authkeys='.ssh/authorized_keys' | |
ssh_dir=~/.ssh | |
checks "$@" && ssh_pubkey=$(ssh-add -L 2>/dev/null | head -1) || mktmpkey | |
ssm_cmd=$( | |
cat <<EOF | |
"u=\$(getent passwd ${2}) && x=\$(echo \$u |cut -d: -f6) || exit 1 | |
install -d -m700 -o${2} \${x}/.ssh; grep '${ssh_pubkey}' \${x}/${ssh_authkeys} && exit 1 | |
printf '${ssh_pubkey}'|tee -a \${x}/${ssh_authkeys} && sleep 15 | |
sed -i s,'${ssh_pubkey}',, \${x}/${ssh_authkeys}" | |
EOF | |
) | |
# put our public key on the remote server | |
aws ssm send-command \ | |
--instance-ids "$1" \ | |
--document-name "AWS-RunShellScript" \ | |
--parameters commands="${ssm_cmd}" \ | |
--comment "temporary ssm ssh access" #--debug | |
# start ssh session over ssm | |
aws ssm start-session --document-name AWS-StartSSHSession --target "$1" #--debug | |
} | |
function checks { | |
[[ $# -ne 2 ]] && die "Usage: ${0##*/} <instance-id> <ssh user>" | |
[[ ! $1 =~ ^i-([0-9a-f]{8,})$ ]] && die "ERROR: invalid instance-id" | |
if [[ $(basename -- $(ps -o comm= -p $PPID)) != "ssh" ]]; then | |
ssh -o IdentityFile="~/.ssh/ssm-ssh-tmp" -o ProxyCommand="${0} ${1} ${2}" "${2}@${1}" | |
exit 0 | |
fi | |
pr="$(grep -sl --exclude='*tool-env' "$1" "${ssh_dir}"/ssmtool-*)" && | |
export AWS_PROFILE=${AWS_PROFILE:-${pr##*ssmtool-}} | |
} | |
function mktmpkey { | |
trap cleanup EXIT | |
ssh-keygen -t ed25519 -N '' -f "${ssh_dir}"/ssm-ssh-tmp -C ssm-ssh-session | |
ssh_pubkey="$(<"${ssh_dir}"/ssm-ssh-tmp.pub)" | |
} | |
function cleanup { rm -f "${ssh_dir}"/ssm-ssh-tmp{,.pub}; } | |
function die { | |
echo "[${0##*/}] $*" >&2 | |
exit 1 | |
} | |
main "$@" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment