【AWS】SSM Session ManagerでローカルからEC2インスタンスに接続する


SSM Session Managerを利用してaws-cliで手軽にローカルからEC2へ接続するためにShell Scriptを書いたので説明していきたいと思います
SSM Session Mangerの設定方法は本記事では説明しませんので公式ドキュメントを参照して下さい

SSM Session Managerだと長いので、以下ではSession Mangerと略します

Shell Script

動作保証しているOSはMacOSです
それ以外のOSでは動作しないことがありますのでご了承下さい

plugin用

Session Managerを利用するためにはローカルにPluginが必要です
以下のスクリプトでサポートしているのはPluginのインストールとアンインストールです
インストールはS3にあるPluginのzipファイルをダウンロードしてローカルのPATHに含まれている/user/local/binにビルドします
アンインストールはビルドしたスクリプトを削除するだけです

plugin.bash
#!/bin/bash

# ------------------------------------------
# SSM Session Manager Plugin
# https://docs.aws.amazon.com/systems-manager/latest/userguide/session-manager-working-with-install-plugin.html
#
# this script features
# - install
# - uninstall
# ------------------------------------------

set -xeu

function install {
  base_dir=$(cd $(dirname $0); pwd)
  download_dir="/tmp/ssm"

  if [ ! -d "$download_dir" ]; then
    mkdir $download_dir
  fi

  pushd "$base_dir" > /dev/null
  pushd "$download_dir" > /dev/null

  curl -o "sessionmanager-bundle.zip" \
    "https://s3.amazonaws.com/session-manager-downloads/plugin/latest/mac/sessionmanager-bundle.zip"

  unzip sessionmanager-bundle.zip

  sudo ./sessionmanager-bundle/install \
    -i /usr/local/sessionmanagerplugin \
    -b /usr/local/bin/session-manager-plugin

  popd > /dev/null
  popd > /dev/null

  read -p "Do you remove the downloaded files ? [y/n] > " flag
  case "$flag" in
    "y")
      rm -rf $download_dir ;;
    "n") ;;
    *)
      echo "Please typing y or n"
      exit 1 ;;
  esac
}

function uninstall {
  sudo rm -rf /usr/local/sessionmanagerplugin
  sudo rm /usr/local/bin/session-manager-plugin
}


cmd="$1"
case "$cmd" in
  "install")
    install ;;
  "uninstall")
    uninstall ;;
  *)
    echo "Please specify install or uninstall in first argument"
    exit 1 ;;
esac

Session用

このスクリプトではSessionのスタートと履歴の確認ができるようになっています
まずSessionをスタートさせるには接続先のEC2のインスタンスIDが必要です
それを自動取得するために接続先のEC2の名前を引数としてもらって、aws ec2 describe-instancesコマンドでインスタンスIDを取得します
なので接続先のEC2の名前さえ覚えておけば接続できます

session.bash
#!/bin/bash

set -xeu

cmd="$1"
target_ec2_name="$2"
profile="$3"

if [ -z "$target_ec2_name" ]; then
  echo "Please specify EC2 name in the second argument"
  exit 1
fi

if [ -z "$profile" ]; then
  echo "Please specify aws profile name in the third argument"
  exit 1
fi

instance_id=$(aws ec2 describe-instances --output text \
                --filters "Name=tag:Name,Values=$target_ec2_name" \
                --query "Reservations[*].Instances[?Instance.State.Name==running].InstanceId" \
                --region ap-northeast-1 --profile "$profile")

function start {
  aws ssm start-session \
    --target "$instance_id" \
    --region ap-northeast-1 --profile "$profile"
}

function list {
  aws ssm describe-sessions \
    --state "History" \
    --filters "key=Target,value=$instance_id" \
    --region ap-northeast-1 --profile "$profile"
}

case "$cmd" in
  "start") start ;;
  "list") list ;;
  *)
    echo "Please specify start or list in the first argument"
    exit 1 ;;
esac

Makefile

上記のShell Scriptを手軽に実行できるようにMakefileを書いてみました

Makefile
.PHONY: session plugin

plugin:
    bash plugin.bash $(cmd)

session:
    bash session.bash $(cmd) $(name) $(profile)

pluginのコマンド引数説明

$(cmd)にはinstalluninstallを指定します
機能は名前通りです

sessionのコマンド引数説明

引数 説明
cmd startlistを指定して下さい
startはSessionの開始します
listはSesisonの履歴をみることができます
name 接続したいEC2インスタンスの名前を指定します
profile AWS profleのことを示しています
適切なIAM Roleが紐づいているIAM Userのprofileを指定して下さい

Session Startを実行

Sessionを開始してみます

make session cmd=start name=qiita profile=test

上記のコマンドを実行してみると以下のようになります

プロンプトがsh-4.2$になっていればEC2に接続できたということです
ちなみにSessionでログインするユーザをSSMSessionRunAsでタグ付したとしてもログインシェルは初期化されないので、sh-4.2$のままです
このIssueでも書かれていますが、ログインシェルを自動で変更したいのであれば以下のようにすればよさそうです

aws ssm start-session --target <INSTANCE_ID> --document-name AWS-StartInteractiveCommand --parameters command="bash -l"

個人的にはSSMSessionRunAsのように手軽にログインシェルを指定できるようにして欲しいですね

参考