こんにちは、開発本部インフラチームテックリードの櫻井です。
今回は先日導入したAWS Session Managerについて紹介します。
AWS Session Managerとは
AWS Session ManagerとはAWSのリソースを管理するための機能であるAWS Systems Manager(旧SSM)の中の機能の一部です。
Session Managerを使うとパブリックサブネット内に踏み台サーバーを構築したりユーザーごとに秘密鍵を作成したりセキュリティグループで22番ポートを解放したりすることなく、プライベートサブネット内のEC2インスタンスに対して安全に接続することができるようになります。
また、Session Managerを使うことで接続中のセッションの一覧表示や強制切断、サーバー上で実行されたコマンドの記録なども簡単にできるようになります。

Session Managerを使うための準備
Session Managerを使うためには以下の準備を行う必要があります。
接続先EC2インスタンスからインターネットへのアウトバウンド通信ができるようにする
まずEC2インスタンスがインターネットへのアウトバウンド通信ができるかどうかを確認します。
主に確認が必要な場所は”セキュリティグループのアウトバウンド設定でHTTPS通信が許可されているか”と”NATゲートウェイが正しく設定されているか”の2点です。
インターネットへのアウトバウンドHTTPS通信が許可されているかどうかは、例えばEC2インスタンス内で以下のようにcurlコマンドを実行して確認することができます。
$ curl --head 'https://example.com'
またVPCエンドポイントを使えばインターネットへのアウトバウンド通信なしでSession Managerを使うこともできるようなので、インターネットへのアウトバウンド通信を許可したくないという場合は以下のドキュメントを参照してください。
https://aws.amazon.com/jp/premiumsupport/knowledge-center/ec2-systems-manager-vpc-endpoints/
接続先EC2インスタンスにSSM Agentをインストールする
次に接続先のEC2インスタンスにSSM Agentをインストールします。
ただしAMIの種類によっては最初からSSM Agentがインストールされている場合もあるので、その場合はこの手順は不要です。
使用しているAMIにSSM Agentがインストールされているかどうかは以下のページを参照してください。
https://docs.aws.amazon.com/ja_jp/systems-manager/latest/userguide/ami-preinstalled-agent.html
自分でSSM Agentをインストールする場合は、例えばCentOS 7なら以下のようなコマンドを実行することでSSM Agentをインストールして起動することができます。
#!/bin/bash
cd /tmp
yum install -y https://s3.ap-northeast-1.amazonaws.com/amazon-ssm-ap-northeast-1/latest/linux_amd64/amazon-ssm-agent.rpm
systemctl start amazon-ssm-agent
systemctl enable amazon-ssm-agent
CentOS 7以外のOSの場合は以下のページを参照してください。
https://docs.aws.amazon.com/ja_jp/systems-manager/latest/userguide/sysman-manual-agent-install.html
これを見ていて「あれ、新しくインスタンスを立ち上げる場合はどうするんだ?インスタンスに接続するためにSSM Agentをインストールしないといけないのに、SSM Agentをインストールするにはインスタンスに接続する必要がある…」と思った方もいるかもしれませんが、大丈夫です。
新しくインスタンスを立ち上げる場合は上記のコマンドをEC2インスタンスの”ユーザーデータ”に記述することでインスタンスの起動時にSSM Agentをインストールして起動することができます。
ユーザーデータはコンソールからEC2インスタンスを立ち上げる場合は少し分かりづらいですが、一番下にある”高度な詳細”を展開してさらに一番下までスクロールしたところにあります。


TerraformからEC2インスタンスを作成する場合はaws_instance内で以下のように記述します。
user_data = <<-EOT
#!/bin/bash
cd /tmp
yum install -y https://s3.ap-northeast-1.amazonaws.com/amazon-ssm-ap-northeast-1/latest/linux_amd64/amazon-ssm-agent.rpm
systemctl start amazon-ssm-agent
systemctl enable amazon-ssm-agent
EOT
このときユーザーデータにインデントが入ってしまうとユーザーデータが実行できないことがあるので、上記のように <<
の後ろに -
をつけることでインデントされずに反映することができます。
また、このとき user_data_replace_on_change
が true
になっているとユーザーデータを変更したときにEC2インスタンスを削除してから再作成してしまうので注意が必要です。
接続先EC2インスタンスのIAMロールにAmazonSSMManagedInstanceCoreポリシーを追加する
次にSession Managerを使うために必要な権限をEC2インスタンスのIAMロールに付与します。
Session Managerを使うためにはAmazonSSMManagedInstanceCoreポリシーが必要なので、このIAMポリシーを許可されたIAMロールをEC2インスタンスにアタッチするか、既にEC2インスタンスにアタッチ済みのIAMロールにAmazonSSMManagedInstanceCoreポリシーの許可を追加します。
AWS CLIとSession Managerプラグインをインストールする
次にローカルマシンにAWS CLIとSession Managerプラグインをインストールします。
詳しいインストール方法は以下のAWS公式ドキュメントを参照してください。
https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/getting-started-install.html
なお、AWSのコンソールにログインすればAWS CLIやSession Managerプラグインをインストールせずにブラウザから直接EC2インスタンスに接続することもできます。
必要な権限を持ったIAMユーザーのCredentialを設定する
次にローカルからEC2インスタンスに接続するために必要な権限(接続先インスタンスに対する ssm:startSession
権限)を持ったIAMユーザーのCredentialをAWS CLIに設定します。
Credentialの設定方法は以下のAWS公式ドキュメントを参照してください。
https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/cli-configure-files.html
ちなみに弊社ではAWSへのログインにOneloginを使ったAssumeRoleを採用しており、アクセスキーやIAMユーザーの管理が非常に楽になったのでおすすめです。
https://dev.classmethod.jp/articles/aws-assume-role-with-onelogin/
aws ssm start-sessionコマンドを使ってインスタンスに接続する
ここまでの設定ができたら以下のコマンドを実行してEC2インスタンスに接続できます。
$ aws ssm start-session --target [EC2インスタンスID]
ちなみにこの aws ssm start-session
コマンドは他にも色々なオプションがあり、ポートフォワーディングなどもできるので詳しく知りたい方は以下のAWS公式ドキュメントを参照してください。
(任意) Session Manager経由でSSH接続できるようにする
上記のように aws ssm start-session
コマンドを直接実行してインスタンスに接続する場合、scpコマンドやsftpコマンドのようにSSHプロトコルを使用しているコマンドをローカルマシンから実行することができません。
この対策としてSession Manager経由でSSH接続できるように設定することでscpコマンドやsftpコマンドが実行できるようになります。
具体的には ~/.ssh/config
で以下のように設定することでSSH接続できるようになります。
Host aws-some-server
ProxyCommand aws ssm start-session --target %h --document-name AWS-StartSSHSession --parameters '{"portNumber":["%p"]}'
HostName [EC2インスタンスID]
User [ユーザー名]
IdentityFile [秘密鍵のパス]
このときインスタンスの作成時に指定した秘密鍵のパスをIdentityFileで設定する必要がありますが、実際の認証はSession Managerを使って行われるためユーザーごとに秘密鍵を作成する必要はありません。
ここで設定したサーバー名を使うことでSession Manager経由でscpコマンドやsftpコマンドが実行できるようになります。
また ~/.ssh/config
にEC2インスタンスIDを記載しておくことで、今回の aws-some-server
のように自分にとって分かりやすい名前を使って接続できるようになります。
最後に
今回はAWS Session Managerを使ってプライベートサブネット内のEC2インスタンスに接続する方法を紹介しました。
もし踏み台サーバーの構築や秘密鍵の管理が煩わしいと感じていたら、今回紹介したSession Managerの導入を検討してみてはいかがでしょうか?