はじめに
セッションマネージャー、めっちゃくちゃ便利ですよね?
今更言うまでもないですが従来の煩雑なSSHの設定が不要となり、なおかつセキュリティーグループのSSH用ポートの穴あけも不要、
またアクセス権限をIAMに集約できるなど、優秀な点を挙げればきりがないです。
ただし唯一気に入らない点があるとすれば、
AWS CLIで接続する際にインスタンスID
を指定する必要があるという点です。
「インスタンスIDをいちいち調べるのも面倒くさいし、再作成したらID変わるし面倒くさすぎるだろ...。」
と、思ったAWSユーザは全国に1億2000万人はいるでしょう。
そんなわけで、EC2のNameタグを指定してセッションマネージャーで接続するシェルスクリプトを共有します。
1.シェルスクリプト
結論ですが、以下のスクリプトを丸コピして実行してください。
使い方は後述の項目を参照してください。
#!/bin/bash
# get InstanceID function
get_instance_id_by_name() {
aws ec2 describe-instances \
--filter "Name=tag-key,Values=Name" \
"Name=tag-value,Values=$1" \
--query 'Reservations[*].Instances[*].InstanceId' \
--output text
}
# get all InstanceID and NameTag function
get_all_instances() {
aws ssm describe-instance-information \
--query 'InstanceInformationList[*].[InstanceId]' \
--output text | while read -r id; do
name=$(aws ec2 describe-instances \
--instance-ids "$id" \
--query 'Reservations[*].Instances[].Tags[?Key==`Name`].Value' \
--output text)
echo "$name ($id)"
done
}
# main
case $# in
1)
InstanceID=$(get_instance_id_by_name "$1")
aws ssm start-session --target "$InstanceID"
;;
0)
mapfile -t instances < <(get_all_instances)
PS3='Select Instance: '
select instance in "${instances[@]}"; do
[[ -n $instance ]] || continue
InstanceID=$(echo "$instance" | awk '{print $2}')
aws ssm start-session --target "$InstanceID"
break
done
;;
*)
echo "Error: Invalid number of arguments."
echo "Usage1 Specify Name tag: $0 <NameTag>"
echo "Usage2 Select from list: $0"
exit 1
;;
esac
2.使用例
引数にNameタグを指定して実行した場合は、対象にそのまま接続します。
$ select-session.sh <NameTag>
Starting session with SessionId: XXXXXXX-XXXXXXXXXXXXX
sh-4.2$
引き数なしで実行した場合は、
セッションマネージャーで接続可能なEC2が表示されるので、接続したいEC2の番号を入力してください。
$ select-session.sh
1) ec2-web-A i-AAAAAAAAAAAAAAAAA
2) ec2-ap-B i-BBBBBBBBBBBBBBBBB
3) ec2-db-C i-CCCCCCCCCCCCCCCCC
Select Instance: 3
Starting session with SessionId: XXXXXXX-XXXXXXXXXXXXX
sh-4.2$
3.解説
引き数でNameタグを指定した場合は、
Nameタグをもとにaws ec2 describe-instances
を実行して、Nameタグに紐づくインスタンスIDを取得します。
その後、取得したインスタンスIDを指定してaws ssm start-session
を実行します。
# get InstanceID function
get_instance_id_by_name() {
aws ec2 describe-instances \
--filter "Name=tag-key,Values=Name" \
"Name=tag-value,Values=$1" \
--query 'Reservations[*].Instances[*].InstanceId' \
--output text
}
---------------------------------------------------------
1)
InstanceID=$(get_instance_id_by_name "$1")
aws ssm start-session --target "$InstanceID"
;;
次にNameタグを指定しない場合ですが、
aws ssm describe-instance-information
でSSMセッションマネージャーで接続可能なインスタンスIDを取得します。
取得したインスタンスIDをもとにaws ec2 describe-instances
を実行して、NameタグとインスタンスIDを出力します。
その後NameタグとインスタンスIDを配列に格納して、
select
で任意のEC2を選択できるようにしています。
# get all InstanceID and NameTag function
get_all_instances() {
aws ssm describe-instance-information \
--query 'InstanceInformationList[*].[InstanceId]' \
--output text | while read -r id; do
name=$(aws ec2 describe-instances \
--instance-ids "$id" \
--query 'Reservations[*].Instances[].Tags[?Key==`Name`].Value' \
--output text)
echo "$name ($id)"
done
}
---------------------------------------------------------
0)
mapfile -t instances < <(get_all_instances)
PS3='Select Instance: '
select instance in "${instances[@]}"; do
[[ -n $instance ]] || continue
InstanceID=$(echo "$instance" | awk '{print $2}')
aws ssm start-session --target "$InstanceID"
break
done
;;
ただし上記はインスタンスIDごとにaws ec2 describe-instances
を実行しているため、
実行時間がめちゃ遅いです...。
具体的にはコマンドの実行結果を取得できるまで約1秒かかるので、
単純計算でアカウント内にEC2が10台あればselect
できるまで10秒かかります。
というわけで、何か改良案があればご連絡ください...。
2024/2/29更新
よくよく考えたらaws ec2 describe-instances
をバックグラウンドジョブで実行すればいいだけでした...。
という訳で更新版を載せておきます。
更新した箇所は少ないですが、
元と比べてselectが表示されるまで2~3倍は早くなっています。
更新箇所を表示
#!/bin/bash
# Get InstanceID
get_instance_id_by_name() {
+ local instance_name="$1"
aws ec2 describe-instances \
--filter "Name=tag-key,Values=Name" \
+ "Name=tag-value,Values=$instance_name" \
--query 'Reservations[*].Instances[*].InstanceId' \
--output text
}
+ # Get Instance Name
+ get_instance_name_by_id() {
+ local instance_id="$1"
+ aws ec2 describe-instances \
+ --instance-ids "$instance_id" \
+ --query 'Reservations[*].Instances[].Tags[?Key==`Name`].Value' \
+ --output text
+ }
# Get all InstanceID and NameTag
get_all_instances() {
aws ssm describe-instance-information \
--query 'InstanceInformationList[*].[InstanceId]' \
--output text | while read -r id; do
+ {
+ name=$(get_instance_name_by_id "$id")
+ echo "$name $id"
+ } &
done
}
# main
case $# in
1)
InstanceID=$(get_instance_id_by_name "$1")
aws ssm start-session --target "$InstanceID"
;;
0)
+ mapfile -t instances < <(get_all_instances | sort)
PS3='Select Instance: '
select instance in "${instances[@]}"; do
[[ -n $instance ]] || continue
InstanceID=$(echo "$instance" | awk '{print $2}')
aws ssm start-session --target "$InstanceID"
break
done
;;
*)
echo "Error: Invalid number of arguments."
echo "Usage1 Specify Name tag: $0 <NameTag>"
echo "Usage2 Select from list: $0"
exit 1
;;
esac
#!/bin/bash
# Get InstanceID
get_instance_id_by_name() {
local instance_name="$1"
aws ec2 describe-instances \
--filter "Name=tag-key,Values=Name" \
"Name=tag-value,Values=$instance_name" \
--query 'Reservations[*].Instances[*].InstanceId' \
--output text
}
# Get Instance Name
get_instance_name_by_id() {
local instance_id="$1"
aws ec2 describe-instances \
--instance-ids "$instance_id" \
--query 'Reservations[*].Instances[].Tags[?Key==`Name`].Value' \
--output text
}
# Get all InstanceID and NameTag
get_all_instances() {
aws ssm describe-instance-information \
--query 'InstanceInformationList[*].[InstanceId]' \
--output text | while read -r id; do
{
name=$(get_instance_name_by_id "$id")
echo "$name $id"
} &
done
}
# main
case $# in
1)
InstanceID=$(get_instance_id_by_name "$1")
aws ssm start-session --target "$InstanceID"
;;
0)
mapfile -t instances < <(get_all_instances | sort)
PS3='Select Instance: '
select instance in "${instances[@]}"; do
[[ -n $instance ]] || continue
InstanceID=$(echo "$instance" | awk '{print $2}')
aws ssm start-session --target "$InstanceID"
break
done
;;
*)
echo "Error: Invalid number of arguments."
echo "Usage1 Specify Name tag: $0 <NameTag>"
echo "Usage2 Select from list: $0"
exit 1
;;
esac