EC2 Instance Connect Endpoint 以前から確認していく

いろんな方が既にこの話題についてアウトプットしている状態なので
この記事を読む方にとって新しい発見があることはあまりないかもしれません。
が、私個人としてはAWS歴が浅すぎるので最新のアップデート単体でその良さが全部は分からなかったため
背景をきちんと確認したいという趣旨です。

# EC2 Instance Connect Endpointについて
EC2 Instance Connect Endpoint(以下、EIC Endpoint)はプライベートサブネットにあるインスタンスにSSHやRDP接続するにあたって、
パブリック IP、エージェント、踏み台サーバが不要になるというものです。
公式のブログは以下となります。

https://aws.amazon.com/jp/blogs/compute/secure-connectivity-from-public-to-private-introducing-ec2-instance-connect-endpoint-june-13-2023/

## EIC Endpoint以前のインスタンス接続
これまでEC2インスタンスへの接続はSSM Session Managerを使用して接続がメジャーでした。
AWS SummitでもAWSセッションで"インスタンス接続にはSSM Session Managerを使ってますか？"という話が2セッションくらいで出てきた記憶です。
SSM Session Managerでインスタンスへの接続は
* Amazon LinuxではないEC2インスタンスを使用する場合はユーザデータを使用してSSM Agentのインストールを初回起動時に行う必要があった
(MarketPlaceでredmineインストール済のEC2で検証したときが正にそうでした)
* `AmazonSSMManagedInstanceCore`などのポリシーがアタッチされたIAMロールをインスタンスプロファイルに割り当てていないと接続できない
* 踏み台サーバからのSSHではなくSSM Agentベースでログインできるため、SSH鍵の管理は不要になる
* ログイン履歴の発見的統制に工夫がいる
* プライベートサブネットにあるインスタンスに接続する環境維持に料金が発生する

という背景がありました。

### SSM Agentが必要だった
以下のユーザーデータを記載しておくと初回起動時にSSM Agentのインストールができます。
ただし、AmazonLinuxの場合は最初からインストールされているようで特に困らなかったですが
プライベートインスタンスでこのユーザーデータを記載するにはNAT Gateway等意識が必要ですね。
```bash
Content-Type: multipart/mixed; boundary="==BOUNDARY=="
MIME-Version: 1.0

--==BOUNDARY==
Content-Type: text/x-shellscript; charset="us-ascii"

#!/bin/bash
echo "running userdata script"

# SSM Agent のインストール
curl "https://s3.amazonaws.com/ec2-downloads-windows/SSMAgent/latest/debian_amd64/amazon-ssm-agent.deb" -o "amazon-ssm-agent.deb"
dpkg -i amazon-ssm-agent.deb

# SSM Agent の設定
echo "rebooting to start SSM Agent"
nohup sudo systemctl restart amazon-ssm-agent &

--==BOUNDARY==--
```

このAgentのインストールに関しての詳細はこちらです。
MarketPlaceでredmineのEC2インスタンスを選択すると自動でDebian Serverになるので以下のAgentのインストールを行ってます。

https://docs.aws.amazon.com/ja_jp/systems-manager/latest/userguide/agent-install-deb.html

### インスタンスプロファイルにロール割り当てが必要だった
`AmazonSSMManagedInstanceCore`ポリシーをアタッチされたロールをインスタンスプロファイルに割り当てないといけないです。
もし起動後から割り当てる場合は再起動しましょう。

https://docs.aws.amazon.com/systems-manager/latest/userguide/setup-instance-permissions.html

### SSH鍵の管理が不要
キーペアを割り当てずとも上記2つを満たしたパブリックのインスタンスはSessionManagerで接続できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3330185/914aca03-858c-b52d-35c8-533df9c33f9e.png)
接続を押すとブラウザの別タブでコンソールが開かれます。
`ssm-user`で接続していることが確認できますね。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3330185/ec062717-cca4-9a2c-ee1d-bf54664ba541.png)

### SSHのログイン履歴が残らない
CloudTrailでは接続情報が残っています。
* SessionManager
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3330185/5e5fb3cb-9451-6c9c-fb89-497a761edbd6.png)

* EIC Endpoint
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3330185/42629c7a-eb15-37b7-58d5-31284900d933.png)
> トンネルという記載はこちらでWebSocketトンネルの作成とありますね。
> Once you’ve established a tunnel, you point your preferred client at your loopback address (127.0.0.1 or localhost) and connect as usual.
> https://aws.amazon.com/jp/blogs/compute/secure-connectivity-from-public-to-private-introducing-ec2-instance-connect-endpoint-june-13-2023/

が、`journalctl -u sshd`で確認するとSessionManagerで接続した情報は残りません。
これはSessionManagerがAgentベースでの接続のためSSH接続のログが残らないためです。

https://docs.aws.amazon.com/systems-manager/latest/userguide/session-manager.html

なので、セッションアクティビティを残すなどの対処が必要ですね。

https://docs.aws.amazon.com/ja_jp/systems-manager/latest/userguide/session-manager-logging.html

### プライベートサブネットにあるインスタンスに接続する環境維持に料金が発生する
プライベートサブネットにあるインスタンスに接続するにはエンドポイントの作成が必要になります。
0.014 USD/時間 * 3 （VPCエンドポイント数）
* `com.amazonaws.ap-northeast-1.ssm`
* `com.amazonaws.ap-northeast-1.ssmmessages`
* `com.amazonaws.ap-northeast-1.ec2messages`

## EIC Endpointは？
ここまでSessionManagerで接続することの準備や料金に触れてきましたが、それを踏まえEIC Endpointは何がいいのか。
* Agentインストール不要
* インスタンスプロファイルにロールを割り当てる必要がない
* SSM SessionManagerと同様にSSH鍵はこちらで管理せずともSSH接続できる
* SSHのログが残る
* EIC Endpointは料金が発生しない
* VPCに1つしか割り当てることができない

上記のうち、上3つと料金の話を省略して確認します。

### SSHログインのログが残る
`journalctl -u sshd`コマンドを実行するとSSHのログが残っています。
```bash
Jun 18 09:36:51 ip-10-0-10-134.ap-northeast-1.compute.internal sshd[34330]: Accepted publickey for ec2-user from 10.0.6.253 port 53514 ssh2: ED25519 SHA256:略
```
/var/log/secureを見ていないのはAmazon Linux 2023の仕様です。
以下を参考にしています。

https://dev.classmethod.jp/articles/diff-al-2023-and-al-2-packages-and-services/

### VPCにつき1つしか割り当てができない
現状GAの状態だからなのかわかりませんが、"VPCに1つ" かつ "サブネットに1つ" という制限があるようです。

https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/eice-quotas.html

検証済ですが、以下の図の要領で使用するとAZで分かれた各プライベートサブネットに接続することができました。(公式とほぼ同じ図になってしまったのでSecurityGroupを意識して記載しました)
SecurityGroupでPrivate subnet2とEIC Endpointを通せばPrivate subnet1にEIC Endpointを作ってもどちらへもアクセスできます。

EIC Endpoint Serviceの部分でIAM認証の上、WebSocketの通信が行われているんですがどことどこがWebSocketなのか確証がなかったです。
また、きちんとした明記が見つけられなかったので確認しましたが、EIC Endpoint自身が属するSecurityGroupはインバウンドルールの許可設定は要らなかったです。
アウトバウンドはキチンと関係あるので設定が必要です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3330185/e059ee39-885c-7e73-db51-f8a06ea133b5.png)


https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/eice-security-groups.html

パブリックのEC2インスタンスは"EC2 Instance Connect を使用して接続する"、
プライベートのEC2インスタンスは"EC2 Instance Connect エンドポイントを使用して接続する"で接続すると意外とVPCに1つサブネット毎に1つという制限もなんとかなりそうな雰囲気ありますね。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3330185/98e541dc-697e-3d2c-6a5f-5be9da7a0782.png)

気になるのはPrivate Subnet1で障害が起きたときにPrivate Subnet2にアクセスできないかもしれないということですね。

# おわりに
料金的にもEIC Endpointがメリット大きそうな雰囲気は感じますね。
という訳で今回のアップデート検証に出遅れたのでSessionManagerで接続が主流だったころをメインで確認してみました。