Visual Studio Code から SSHポート開放無しでAWSインスタンスに接続する

世はVisual Studio Onlineで湧いていますが、これは通常のCodeのお話。
Visual Studio Code の Remote Development でリモートファイルを編集できる、というのは多く知られていますが（後述）、それには現状SSH接続が必要です。SSH接続となると、ポート開放や踏み台サーバー付きのプライベートサブネットなど、セキュリティ周りで頭を悩ませることも多いですよね。

この投稿では、AWS SSM（Session Manager）を利用して、SSHポート開放無し、プライベートサブネットのままで踏み台サーバーなしで、セキュアに Visual Studo Code Remote Developmentを実行する方法をお話します。

## この投稿で説明すること
- Visual Studio Code Remote Development を利用してAWSに接続する際に、ポート開放や踏み台なしでプライベートサブネット上のサーバーに接続する方法
- Mac / Windows 両対応
    - というかWindowsに大きめの罠が有り〼


## Visual Studio Code Remote Development とは
登場以来、VS Codeのまさにキー機能の一つになった超絶便利拡張。一言でいうと、リモートサーバー上の環境を、まるでローカルマシンのように使うことができます。具体的に言うと、

- ファイル編集
- コンソールの実行
- 特定のポートの共有

など。Cloud9みたいなものといえばそうなんですが、エディタの実態はローカルにあるので操作感はかなり良く、また殆どのVSCodeのプラグインが利用できます。要はほとんどローカルのVSCodeと一緒。

非力なマシンやWindows上でのLinuxアプリケーション開発などをする際にはないと困るし、あとWindowsであればWSLにも接続できるため、ほとんどLinuxマシンのように扱うことができる。

詳しい説明はこの辺を。

https://dev.classmethod.jp/etc/vs-code-remote-development-ec2/

## AWS Systems Manager Session Manager（SSM SessionManager）
これも登場以来、AWS EC2上の面倒くさいポート管理の方法を一気に解決してくれた便利機能です。これも早い話、シェルをAWS EC2サーバーに繋げられる機能なのですが、その際に、セキュリティグループ設定やネットワークACLによる２２番ポートの限定開放を必要としません。更に多くの場合は、踏み台サーバーを使うことも多いでしょうし、その踏み台サーバーのIP制限等に対応するため、SSHプロクシを使う例も多いと思います。（この辺、特に業務で使うなら２２番全開放というのは基本的に許されないはず。）

これを超絶楽にしてくれるのがSSM SessionManager です。SSM SessionManagerは、インスタンスにSSMを許可するロールがアタッチされており、かつSessionManager用のエージェントが入っていれば（Amazon Linuxとかであれば基本的にデフォルトで入っています）、シェルをつなぐことができます。

https://dev.classmethod.jp/cloud/aws/ssm-session-manager-release/

ただしこのとき気をつけないといけないのが、これはあくまでssm-userというユーザーでの接続で、シェルもBashなどではなくshであること。インスタンスログインと全く同じことができるわけでは有りません。

しかし、それもSSM SessionManagerの更新によりSSH接続を張れるようになったため、問題はほぼ解決しています。

https://dev.classmethod.jp/cloud/aws/session-manager-launches-tunneling-support-for-ssh-and-scp/

そう、ここまでたどり着いているなら誰でも思うでしょう。「あれ？これVSCodeとSSM合わせると、セキュアな開発環境が手軽に構築できるのでは？」

はい、できます。

## Mac の場合
Macと書きましたがおそらくLinuxでも同様だとは思います。

基本的には、SSM SessionManagerを介してSSHする設定をちょっといじるだけで、VSCode Remote Development 用になります。
一応前提としては、以下の２要件です。

 1. かなり最近のバージョンのSSMエージェントが接続先インスタンスに入っていること
    - 最新のAmazon Linuxでも更新が必要でした。ただし、この更新は SSM でつないだ状態でもできたので、このプロセスのためだけに一旦ポート開放しないといけない、なんてことはありません。
    - [この辺の手順](https://dev.classmethod.jp/cloud/aws/ssm-session-manager-release/)を参考に、コンソールなりCLIから接続して更新しておきましょう
 2. AWS CLI のSession Managerプラグインをかなり最近のバージョンに更新しておくこと
    - インストールは[こちら](https://docs.aws.amazon.com/ja_jp/systems-manager/latest/userguide/session-manager-working-with-install-plugin.html)を参考に
 

そこまでしていれば、SSH設定ファイルに以下のように記述すればOKです。（サーバー名やインスタンスIDは適宜入れてください。


```
Host %YOUR_SERVER_NAME%
    User ec2-user
    HostName %YOUR_INSTANCE_ID%
    Port 22
    ProxyCommand sh -c "aws ssm start-session --target %h --document-name AWS-StartSSHSession --parameters 'portNumber=%p' --profile %YOUR_AWS_PROFILE%"
    IdentityFile "path/to/your/ssh/key"
```

あとはこれで、VSCode側でRemote接続するサーバーを選択すれば、自動でセッションマネージャを立ち上げ、SSH接続するまでが代行されます。複数のサーバーの管理も楽勝ですね！


## Windowsの場合
Windowsの場合も基本的に同じ、、、と言いたいところですが微妙に違います。ポイントは２つで、 **`sh`をどうするのよ？** という話と、 **VSCode RemoteDevelopment の接続時のパス解決の微妙な不便さ** です。

まずは、Macと同様EC2側、クライアント側ともに最新のSSMのエージェント/プラグイン を入れてください。

まずは簡単な方、 `sh` をどうするか、からです。
これは短い答えとしては `MinGW` 使え、です。なにそれ？と思う人もご心配なく、おそらく普通にWindowsでGit入れた場合には、一緒に入っています。（ちなみに `Cygwin` は最近殆ど触っていないので試していません。もし試した人入れば是非教えて下さい。。。）

というわけで、大体の人は以下のパスに入っているはずなので、使いましょう。だめな人は各自 [MinGWインストールしてください。](https://qiita.com/pengincoalition/items/2bc1e0a80b114d6c49a6)

```
Host %YOUR_SERVER_NAME%
    User ec2-user
    HostName %YOUR_INSTANCE_ID%
    Port 22
    ProxyCommand C:\Program Files\Git\usr\bin\sh.exe -c "aws ssm start-session --target %h --document-name AWS-StartSSHSession --parameters 'portNumber=%p' --profile %YOUR_AWS_PROFILE%"
    IdentityFile "Path\to\Your\SSH\Key"
```

ここで一つ注意点、ファイル名は省略しないでください。どうもWindowsのVSCode Remote Development はPATHを認識しないようで、`Program Files` などにおいていても、なんと読み込んでくれません。なので上記のようなフルパス指定が必要です。

そしてそこでもう一つの罠。AWS CLI のSSM は内部でSSMのプラグインを利用するのですが、これもパスが通っていないと怒られてしまいます。本当に特殊なPATHで動いているようです。。。

こればっかりは、普通の手段ではお手上げです。**普通の手段では。**
まぁ、これも古から続くよくある方法です。`C:\%PROGRAMFILES%\Amazon\SessionManagerPlugin\bin\` の中身を、しれっとシステムパス、すなわち `C:\Windows\System32` にでもコピーしておきましょう。

いいんです、わかった上でやるんですから、いいんです。（自分に言い聞かせる）

## というわけで
ダーティなところはあるんですが、まぁそれに目をつむってもらえれば、使えると思います。
ぶっちゃけ、SSMでEC２につながられれば、コストの問題度外視すればほぼ最強の環境が構築できます。メモリなんかも積みたい放題です。

さらにSSHつないでのテキストエディタではなく、いつものVSCodeが使えます。

Windowｓの方は若干（？）手段に目をつむってもらえれば、かなり良い環境が手に入ると思いますよ！！