AWS Systems Manager Session Manager を使ってSSHポートを開けずにVSCode のRemote - SSHで開発する

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

AWS Systems Manager ロゴ こんにちは、サービス開発の丸山です。 今回は(も?)小ネタの紹介です。

私は VSCode の Remote - SSH という機能を使ってAWSのEC2にSSHして開発を行うことがたまにあります。
Remote - SSH とはその名の通りVSCodeでリモートのサーバーにSSH接続することで、ローカルにあるファイルと同じインターフェースでリモートサーバー上のファイルやターミナルを操作できる機能です。
VSCodeの Remote - SSHについてはこちらのブログをご覧下さい。

blog.serverworks.co.jp

この時に、普通にSSH接続を行うのではなくAWS Systems Manager Session Manager の機能を使うことで、EC2インスタンスのセキュリティグループのインバウンド SSH ポートを解放することなく Remote - SSH を利用する方法を紹介します。

これによってインバウンド SSH ポートを開放せずに済むので、よりセキュアになるというメリットがあります。

加えて、セキュリティグループのSSHインバウンドの設定を管理する必要がなくなるので環境のセキュリティレベルを落とさずに設定の手間を減らすことができるというメリットもあります。
私はテザリングのような頻繁にIPが変わってしまう環境からEC2に接続することが多かったので、IPが変わるたびにセキュリティグループの設定を更新することがよくあったのですが、この方法を利用することでセキュリティグループの設定を管理する手間も減らすことができました。

AWS Systems Manager Session Manager とは

AWS Systems Manager Session Manager とはAWSのサービスの一つで、 EC2インスタンスのシェルにセキュアに接続する機能を提供しています。
接続はSSHではなくHTTPSを利用するため、SSHのポート解放が不要だったり、IAMポリシーを使って認証や権限の管理を行えたりすることが一般的なSSHによるシェルアクセスとの違いです。

Session ManagerはAWSマネジメントコンソールから使うこともできますし、以下のようにAWS CLIからも実行することができます。

$ aws ssm start-session --target i-06c************

Starting session with SessionId: aws-cli-0ffa**********

sh-4.2$ whoami
ssm-user
sh-4.2$ pwd
/usr/bin
sh-4.2$ exit

Exiting session with sessionId: aws-cli-0ffa**********.

さらにSession ManagerはSSHトンネリング機能も備えており、 HTTPS接続を経由してインスタンスにSSH接続をすることもできます。
よくある使い方は以下のように ~/.ssh/configProxyCommandを使って多段SSH風の設定を記載しておくことで、

# SSH over Session Manager
host i-* mi-*
ProxyCommand sh -c "aws ssm start-session --target %h --document-name AWS-StartSSHSession --parameters 'portNumber=%p'"

ホストの代わりにインスタンスIDを使って <ユーザー名>@<インスタンスID> でSSHできるようになります。

$ ssh  -i ~/path/to/key.pem ec2-user@i-06c**************
Last login: Wed Oct  6 01:31:50 2021 from localhost

       __|  __|_  )
       _|  (     /   Amazon Linux 2 AMI
      ___|\___|___|

https://aws.amazon.com/amazon-linux-2/
No packages needed for security; 4 packages available
Run "sudo yum update" to apply all updates.
ec2-user@ip-172-31-31-18:~$ whoami
ec2-user
ec2-user@ip-172-31-31-18:~$ pwd
/home/ec2-user
ec2-user@ip-172-31-31-18:~$ exit
ログアウト
Connection to i-06ca1388cb3f2c084 closed.

今回はこの機能を使って VSCodeに Remote - SSHで接続し、リモート開発を行います。

AWS Systems Manager Session Manager を設定する

ここまでざっと説明しましたが、Session Manager の設定はいくつかステップがあり若干大変です。
EC2にSession ManagerでSSHするためには、以下のような条件が必要です。

  • リモートサーバー側
    • SSM Agent がインストールされている
    • Session Manager へアクセスする権限を持ったIAMロールがEC2インスタンスにアタッチされている
  • ローカルマシン側
    • AWS CLI がインストールされ、セットアップされている
    • Session Manager Plugin がインストールされている

この記事でも設定手順を簡単に紹介しますが、詳しくは 公式ドキュメントを確認してみてください。

docs.aws.amazon.com

具体的な設定方法の説明の前に、なぜこのような設定が必要なのかについての説明をします。
SSM Agentは EC2インスタンス 内部で動作し、定期的にSSMのエンドポイントに対してポーリングをして指示を待つような動作をします。
SSMからなんらかの指示があればSSH接続やコマンド実行などの具体的な操作をSSM AgentがEC2の内部で行います。
SSM AgentはSSMのエンドポイントと通信してAWS上の操作を行うので、SSMに関する操作を行うためのIAMロールも必要になるという理屈になります。
ちなみに、上記の条件には明記していませんが、このような理屈で動作する都合上、EC2はインターネットなどを通じてSSMのエンドポイントに通信できるようになっている必要があります。

SSMのエンドポイントを経由した通信のイメージ

SSM Agent (バージョン 2.3.672.0 以降)

実はAWSで提供されている標準的なAMI(Amazon Linux, Amazon Linux 2, Ubuntu)を使ってEC2を作成すると最初からSSM Agentがインストールされているので、多くの場合設定不要かもしれません。
2021年10月08日時点で、AWSウィザードで提案されるの標準的なAMI(amazon/amzn2-ami-hvm-2.0.20211001.1-x86_64-gp2)を使って Amazon Linux 2のEC2インスタンスを起動したところ、バージョン3.0.1124.0のSSM Agentがインストール済みで動作していました。

一応トラブルシューティング用途や他のOSを利用する場合を想定して、コマンドやドキュメントを紹介します。
以下のコマンド(Amazon Linux 2の場合)でSSM Agentが起動しているか確認できます。

$ sudo systemctl status amazon-ssm-agent

さらに以下のコマンドで SSM Agentのバージョンを確認できます。

$ yum info amazon-ssm-agent

起動、またはインストールされていなければこちらのマニュアルを参考に操作を行ってください。

docs.aws.amazon.com

docs.aws.amazon.com

Session Manager へアクセスする権限を持ったIAMロールのアタッチ

これはデフォルトではアタッチされていないので、基本的には自分で操作する必要があります。
ただし最低限必要なIAMポリシーは AmazonSSMManagedInstanceCore というAWS管理ポリシーに含まれているため、自分で必要なポリシーを調べたりする必要はありません。
新しく作成したIAMロールに AmazonSSMManagedInstanceCore をアタッチし、それをEC2インスタンスにアタッチすればOKです。

AWS CLI (バージョン 1.16.12 以降)

こちらはいろいろな方法がありえるので、公式ドキュメントをご確認ください。

docs.aws.amazon.com

AWS CLIのセットアップにはこちらの記事も参考になります。
blog.serverworks.co.jp

Session Manager プラグイン (バージョン 1.1.23.0 以降)

こちらもOSによって方法はいろいろですが、MacOSの場合は次のコマンドでインストール可能です。

$ curl "https://s3.amazonaws.com/session-manager-downloads/plugin/latest/mac/sessionmanager-bundle.zip" -o "sessionmanager-bundle.zip"
$ unzip sessionmanager-bundle.zip
$ sudo ./sessionmanager-bundle/install -i /usr/local/sessionmanagerplugin -b /usr/local/$ bin/session-manager-plugin
$ ./sessionmanager-bundle/install -h

ほかのOSの場合はこちらのドキュメントをご確認ください。

docs.aws.amazon.com

ちなみに、もしかしたら既に入っているかも? という場合にはこちらのコマンドで確認できます。

session-manager-plugin --version

VSCode からSession Managerを使ってSSHしてみる

さて、ここまででようやく準備が整ったので、VSCodeから接続してみます。

SSHの設定ファイル(~/.ssh/configなど)に次のように記述します。

Host ec2 # この部分は自由に決めてOK
    User ec2-user
    ProxyCommand sh -c "aws ssm start-session --target %h --document-name AWS-StartSSHSession"
    HostName <インスタンス ID>
    IdentityFile <インスタンス 作成時に指定した公開鍵に対応する秘密鍵>

するとSSH TARGETS のタブにHostに指定した名前の接続先が表示されるので、ウィンドウアイコンをクリックして接続します。
f:id:swx-rei-maruyama:20211008193930p:plain f:id:swx-rei-maruyama:20211008193948p:plain

これで無事セキュリティグループのインバウンドの開放なしで リモートサーバーに接続してVSCodeで開発できるようになりました。めでたしめでたし。