CloudFormationで作成したキーペアをダウンロードせずにSSHログインするスクリプトを作りました

記事タイトルとURLをコピーする

技術 1 課の水本です。最近は通常の業務の合間でスクリプトを書いたり、社内の品質管理等を進めたりしています。

さて、今回は CloudFormation で作成したキーペアをファイルとして保存することなく SSH コマンドに受け渡す方法を案内します。

CloudFormation でキーペアの作成がサポートされた話は弊社の木谷が別記事で解説しておりますのでご覧ください。

blog.serverworks.co.jp

CloudFormation で生成したキーペアの仕様

これは仕様のおさらいになりますので、不要な方は読み飛ばしてください。

  1. CloudFormaion で作成するのはキーペアだが、内容が SSM パラメーターストアに格納されるという特殊な仕様
  2. 1 の CloudFormation で設定したタグはキーペアに付与されるもので、当該のパラメーターストアには付与されない
  3. キーペアの情報は Systems Manager(以下、SSM)パラメーターストアの /ec2/keypair/{key_pair_id}SecureString として格納される
  4. 3 の{key_pair_id}は EC2 のキーペアのキー ID と同一
  5. キー ID が特定できれば CLI でキーペアの文字列は取得可能(公式ドキュメント参照)

検討したこと

実装にあたって以下を検討しました。絶対に守りたいのは「鍵ファイルをダウンロードしてローカルに置かない」です。

鍵ファイルは慎重な取り扱いが必要ですし、なるべく保存したくないという気持ちがありました。

今回の CloudFormation 対応化により、それが実現できそうだということで、この実装を検討しています。

  1. キー ID が特定できれば SSM パラメーターストアから直接キーペア文字列が取得できるので、これを直接 SSH コマンドに渡してしまいたい
  2. キーペアの一覧からキー名をトリガーにキー ID が拾えるのではないか
  3. 踏み台サーバーも多いので、踏み台サーバーも対応させたい
  4. 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で書いた方が楽だなと思いました。

最後までお読み頂きありがとうございました。

水本 正敏(執筆記事の一覧)

クラウドインテグレーション2部 技術1課

国内ITベンダーのカスタマーエンジニアからAWSに魅了されサーバーワークスへ。