技術 1 課の水本です。最近は通常の業務の合間でスクリプトを書いたり、社内の品質管理等を進めたりしています。
さて、今回は CloudFormation で作成したキーペアをファイルとして保存することなく SSH コマンドに受け渡す方法を案内します。
CloudFormation でキーペアの作成がサポートされた話は弊社の木谷が別記事で解説しておりますのでご覧ください。
CloudFormation で生成したキーペアの仕様
これは仕様のおさらいになりますので、不要な方は読み飛ばしてください。
- CloudFormaion で作成するのはキーペアだが、内容が SSM パラメーターストアに格納されるという特殊な仕様
- 1 の CloudFormation で設定したタグはキーペアに付与されるもので、当該のパラメーターストアには付与されない
- キーペアの情報は Systems Manager(以下、SSM)パラメーターストアの
/ec2/keypair/{key_pair_id}
にSecureString
として格納される - 3 の
{key_pair_id}
は EC2 のキーペアのキー ID と同一 - キー ID が特定できれば CLI でキーペアの文字列は取得可能(公式ドキュメント参照)
検討したこと
実装にあたって以下を検討しました。絶対に守りたいのは「鍵ファイルをダウンロードしてローカルに置かない」です。
鍵ファイルは慎重な取り扱いが必要ですし、なるべく保存したくないという気持ちがありました。
今回の CloudFormation 対応化により、それが実現できそうだということで、この実装を検討しています。
- キー ID が特定できれば SSM パラメーターストアから直接キーペア文字列が取得できるので、これを直接 SSH コマンドに渡してしまいたい
- キーペアの一覧からキー名をトリガーにキー ID が拾えるのではないか
- 踏み台サーバーも多いので、踏み台サーバーも対応させたい
- AWS CLI 以外の追加プログラムは使いたくない
結果
- 1 以外は成功した(1 は他の対応策で成功した)
スクリプト
こちらが実際のスクリプトです。
#!/bin/sh if [ -z "$1" ]; then echo """ Usage: login-ec2.sh <keyname> <target_ip> <aws_profile> <bastion_ip> """ exit 1 fi # Vars KeyName=$1 TargetIp=$2 Profile=$3 BastionIp=$4 # find keypair id KeyPairID=$(aws ec2 describe-key-pairs --key-names ${KeyName} --profile ${Profile} --query 'KeyPairs[].KeyPairId' --output text) echo "KeyPairID: ${KeyPairID}" if [ -z "$KeyPairID" ]; then echo "Can't find Keypair SecureStrings. Check if keyname is correct." exit 1 fi # ssh-add echo "$(aws ssm get-parameter --name /ec2/keypair/${KeyPairID} --with-decryption --profile ${Profile} --query Parameter.Value --output text)" | ssh-add - # connect if [ -z "$4" ]; then ssh ec2-user@${TargetIp} else ssh -v -oProxyCommand="ssh -W %h:%p ec2-user@${BastionIp}" ec2-user@${TargetIp} fi
使い方
- こんな感じで使います。
- AWSプロファイルが特に無い場合は第三引数を
default
とする形でOKなはずです。 - 第四引数がある場合、踏み台経由の接続として処理します。
- ユーザー名はec2-user固定としています。必要に応じて変数化するなり変更してください。
sh login-ec2.sh <keyname> <target_ip> <aws_profile> <bastion_ip>
おわりに
踏み台サーバーなしならシンプルで良いと思いますが、多数の条件を付けていくなら、Pythonで書いた方が楽だなと思いました。
最後までお読み頂きありがとうございました。