AWSで踏み台サーバーからプライベートサブネットのEC2にpecoを使って一発SSHする


以下の図のように、パブリックサブネットとプライベートサブネットを分けて、踏み台サーバー以外はプライベートサブネットに配置する構成はよくあると思います。
踏み台サーバーはEIPでグローバルIPを割り振ればいいのですが、プライベートサブネットに配置したEC2たち、しかもAutoScalingによってIPが不定のものに簡単にSSHしたかったので、少しスクリプトを組んでみました。

想定しているAWSの構成

プライベートサブネットのEC2には直接SSHは不可能

一発で2段SSHするためのコマンド

以下のfunctionを ~/.config/fish/config.fish に追加してください。

fishシェルのfunctionを定義しているので、bashやzshの方は適宜読みかえて下さい。
awsコマンドは--profile--region を明示しているので、ここも適宜変更して下さい。
踏み台サーバーと対象サーバーでSSH鍵が異なる場合、1つ目の$keyに踏み台用の鍵、 2つ目の$keyに対象サーバーのSSH鍵を指定するように書き換えて下さい。

function ec2-ssh-myaws
  echo "ec2-user" | read -l user
  echo "~/.ssh/myaws.pem" | read -l key
  aws --profile myaws ec2 describe-instances --region ap-northeast-1 --output json --filters "Name=network-interface.group-name,Values=Bastion" | jq -r '.Reservations[].Instances[] | .PublicIpAddress' | read -l bastion
  echo "bastion server $bastion"
  aws --profile myaws ec2 describe-instances --region ap-northeast-1 --output json --filters "Name=instance-state-code,Values=16" | jq -r '.Reservations[].Instances[] | [.Tags[] | select(.Key == "Name").Value][] + "\t" +  .InstanceType + "\t" + .PrivateIpAddress + "\t" + .Platform' | awk '{if ($4 != "windows") printf "%-45s %-15s %-10s\n",$1,$2,$3}' | sort | peco | command awk '{print $3}' | read -l host
  echo "target server $host"
  ssh -o ProxyCommand="ssh -i $key -p 22 $user@$bastion -W $host:22" -i $key -p 22 $user@$host
end

追加し終えたら、次のようにfunctionを呼び出すだけで、プライベートサブネットにいるEC2の一覧が表示されて、選択したサーバーに繋がります。

ec2-ssh-myaws

functionがやっていることの説明

  1. 踏み台サーバーにEIPを割り振っていなくても対応できるように、踏み台サーバーのPublic IPをawsコマンドで取得
  2. 起動中EC2の一覧を取得して、選択しやすいように整形してからpecoに渡す
  3. 踏み台サーバーと選択した対象サーバーの情報でSSH

終わりに

この設定を使って楽をし始めた矢先に次の様な記事が公開されました。

SSH不要時代がくるか!?AWS Systems Manager セッションマネージャーがリリースされました!

AWS Systems Manager セッションマネージャーがあれば今回の設定は不要かもしれないですね。

参考リンク