AWS Session Managerを使ってプライベートサブネット内のEC2インスタンスに接続する

こんにちは、開発本部インフラチームテックリードの櫻井です。

今回は先日導入した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_changetrue になっているとユーザーデータを変更したときにEC2インスタンスを削除してから再作成してしまうので注意が必要です。

https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/instance#user_data_replace_on_change

接続先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

https://docs.aws.amazon.com/ja_jp/systems-manager/latest/userguide/session-manager-working-with-install-plugin.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公式ドキュメントを参照してください。

https://docs.aws.amazon.com/ja_jp/systems-manager/latest/userguide/session-manager-working-with-sessions-start.html

(任意) 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の導入を検討してみてはいかがでしょうか?

この記事を書いた人

2018年に京都大学を卒業後、PR TIMESに新卒入社。
現在は開発チームのサーバーサイドエンジニア兼インフラチームのテックリードを担当しています。

目次
閉じる