EC2 Instance ConnectとAWS Systems ManagerのSession Managerのトンネリングを使って、安全かつ簡単にEC2へのSSH接続をします。
概要
EC2 Instance Connect
任意のSSH公開鍵をアップロードして、対応する秘密鍵でログインできる便利な機能。
しかもアップロードした公開鍵は1分のみ有効で毎回登録が必要なため、鍵の流出なども気にしなくて良いです。
公開鍵の登録はIAMで制御可能なため、つまりSSHのアクセス制御をIAMで行えるということになります。
AWS Systems ManagerのSession Managerのトンネリング
SystemsManagerのSessionManagerではSSHのトンネリングをサポートしているので、この機能を使うことでサブネットやセキュリティグループの設定に関わらず
SessionManagerの管理対象となっているインスタンスへトンネルを通じダイレクトにSSHが可能となります。
まとめるとこんな感じ。
サービス | いいところ | ちょっとなぁなところ |
---|---|---|
EC2 Instance Connect | 鍵管理がいらなくなる | 接続先はフツーにパブリックサブネットでSSH要の穴あけが必要 |
Session Managerのトンネリング | 接続先のインスタンスがパブリックサブネットだろうがプライベートサブネットだろうが直接続が可能 | 鍵管理は普通に必要 |
という感じでそれぞれ帯に短し・・的な感じですが、2つのいいところを組み合わせると
鍵管理がいらなくなる + パブリックサブネットだろうがプライベートサブネットだろうが直接続が可能
となり、インフラ野郎の自分としてはかなり捗るかな、と。
つまりこんな人におすすめ
- もうssh鍵管理したくない
- パブリックサブネットのインスタンスのセキュリティグループの接続元IPの管理が辛い
- 踏み台インスタンスの管理をせずにプライベートサブネットのインスタンスにも直接SSHしたい
- ACLやセキュリティグループをはじめ、通信経路上のNW機器などにSSH用のポートを開けたくないけどSSHしたい
- SSHの接続権限管理もIAMでやりたい
※会社のクソみたいなプロキシとかも突破できちゃうかもしれませんが自己責任でお願いします
コマンド化してみて使った感じ
接続したい対象インスタンスの番号を選択してEnterするのみ
turbo5522mame-no-MacBook-Pro:~ turbo5522mame$ AWSSSH
[0]Linux-com000 i-06f85999999999999 ap-northeast-1a
[1]Linux-com001 i-05406999999999999 ap-northeast-1a
[2]Linux-com002 i-07c56999999999999 ap-northeast-1a
[3]Linux-com003 i-01443999999999999 ap-northeast-1a
[4]Linux-com004 i-0840a999999999999 ap-northeast-1c
[5]Linux-com005 i-0c676999999999999 ap-northeast-1a
Please select ssh connection number(0-5): 0
----start ssh-keygen
----end ssh-keygen
----start rsa_key_upload
{
"RequestId": "0b1b2abb-fd51-476a-9580-7565dc39cbe4",
"Success": true
}
----end rsa_key_upload
----start ssh with ssm Linux-com000
Last login: Sat Feb 1 15:19:15 2020 from localhost
__| __|_ )
_| ( / Amazon Linux 2 AMI
___|\___|___|
https://aws.amazon.com/amazon-linux-2/
15 package(s) needed for security, out of 38 available
Run "sudo yum update" to apply all updates.
[ec2-user@ip-172-xx-xx-xx ~]$
セットアップ手順
以下4手順。時間にして10分くらい
-
EC2 Instance Connect のセットアップ
-
Session Managerを通して SSH 接続を有効にする
-
.ssh/configの設定
-
.bashrcにfunction作成
-
EC2 Instance Connect のセットアップ
新し目のAmazonLinuxは設定済みのため、設定不要な人もいるかもです。
Amazon Linux 2 2.0.20190618 以降には、EC2 Instance Connect が事前設定されています、とのこと。
- Session Managerを通して SSH 接続を有効にする
SystemsManagerを有効化したりなんだりと初めての場合は色々あるかもですがまあやるだけ。
この辺を参考に
- .ssh/configの設定
- Mac/Linuxの場合
Host i-* mi-*
ProxyCommand sh -c "aws ssm start-session --target %h --document-name AWS-StartSSHSession --parameters 'portNumber=%p'"
User ec2-user
IdentityFile ~/.ssh/AWSSSH_rsa_key
- windowsの場合
Host i-* mi-*
ProxyCommand /c/Program\ Files/Amazon/AWSCLI/bin/aws.exe ssm start-session --target %h --document-name AWS-StartSSHSession --parameters "portNumber=%p"
User ec2-user
IdentityFile ~/.ssh/AWSSSH_rsa_key
- .bashrcにfunction作成
- .bashrcに関数を作成(コピペ)
- 保存後の再読み込み(
source .bashrc
)は忘れずに
function AWSSSH() {
# ローカル変数定義
declare -a instance_name
declare -a instance_id
os_user=ec2-user
# ssmからAWSCLIで接続先候補のInstanceIdをとってくる
ssm_instance_id_list=`aws ssm describe-instance-information \
--query 'InstanceInformationList[].InstanceId' --output text`
if [ -n "${ssm_instance_id_list}" ]
then
# ssmからとってきたInstancdIdが" "区切りなので検索用に","区切りにする
filter_keys=`echo ${ssm_instance_id_list} | tr " " ","`
else
echo "No SSM enabled instances"
return 1
fi
# 接続先候補のNameタグとAvailabilityZoneとInstanceIdをとってくる
ssh_target_info=`aws ec2 describe-instances \
--filters "Name=instance-id,Values=${filter_keys}" \
--query 'Reservations[].Instances[].[Tags[?key=="Name"].Value[],InstanceId,Placement.AvailabilityZone]' \
--output text \
| awk '{if(NR%2==0){print $0}else{printf $1" "$2" "}}' | sort -k3`
# メニュー表示
i=0
while read instance_id[$i] availability_zone[$i] instance_name[$i]
do
echo "["$i"]"${instance_name[$i]} ${instance_id[$i]} ${availability_zone[$i]}
let i++
done << END
${ssh_target_info}
END
let i--
# 接続先選択
read -p "Please select ssh connection number(0-$i): " ssh_target_no
if [ -n "${ssh_target_no}" ]
then
# 選択された番号のインスタンスとかをセットする
instance_name=${instance_name[$ssh_target_no]}
instance_id=${instance_id[$ssh_target_no]}
availability_zone=${availability_zone[$ssh_target_no]}
fi
if [ -n "${instance_id}" ] && [ -n "${availability_zone}" ]
then
# EC2 InstanceConnect用のssh接続用のカギ作成
echo "----start ssh-keygen"
mkdir -p ~/.ssh
rm -f ~/.ssh/AWSSSH_rsa_key
rm -f ~/.ssh/AWSSSH_rsa_key.pub
ssh-keygen -t rsa -f ~/.ssh/AWSSSH_rsa_key -N "" > /dev/null 2>&1
echo "----end ssh-keygen"
# EC2 InstanceConnect用のssh接続用のカギのUPLOAD
echo "----start rsa_key_upload"
aws ec2-instance-connect send-ssh-public-key \
--instance-id ${instance_id} \
--availability-zone ${availability_zone} \
--instance-os-user ${os_user} \
--ssh-public-key file://~/.ssh/AWSSSH_rsa_key.pub
echo "----end rsa_key_upload"
# AWS SystemsManagerのセッションマネージャーを使ったSSH接続
echo "----start ssh with ssm ${instance_name}"
ssh ${instance_id}
else
echo "Usage: Please select ssh connection number(0-$i)"
fi
}