外部からVPC内に接続するまでの経路が途切れてしまったときの緊急対処法

# はじめに
今回、AWS環境で業務を行っていた時、ある問題に直面したときに(暫定的に)回避した対応について説明させて頂きます。

# 背景
業務でAWSを検証環境として使っていたのですが、セキュリティ保持のため、以下の構成を取っていました。(構成の1部のみを記載しています。)

* VPC内でPublicセグメントとPrivateセグメントに分ける。
* インターネット接続できるのはPublicセグメントのみ。
* インスタンスは必ずPrivateセグメントに配置。
* インスタンスからインターネットに接続するときは、Proxyサーバを経由する。
* インスタンスにログインするときは、VPN接続された社内セグメントからのみ。
* (更に)社内セグメントからインターネット経由でSSH接続が禁止
![構成図1.png](https://qiita-image-store.s3.amazonaws.com/0/192426/fe179ecc-4021-51f1-45f5-997e5954aa6f.png)

# 直面した問題
障害により、VPN接続が切断されてしまいVPC内のインスタンスにログインできなくなってしまいました。

![構成図2.png](https://qiita-image-store.s3.amazonaws.com/0/192426/73732196-a477-deae-de67-ad1b58e0f25f.png)

# (緊急)対処法
VPN接続が復旧させることが1番の対応策となりますが、復旧まで時間がかかることから
以下のAWSサービスを利用してインスタンスにログインしていました。
それは**「AWS Systems Mangerのセッションマネージャー」**です。
簡単に説明すると、SSH接続することなくインスタンスにログインする機能です。
※セッションマネージャーの詳細は以下URLをご参照ください。当ブログでの説明は割愛させて頂きます。
https://dev.classmethod.jp/cloud/aws/ssm-session-manager-release/

# セッションマネージャを利用するまでの障壁
セッションマネージャーの機能を利用すれば、SSHせずともEC2にログインできるのですが
ある問題が発生しました。セッションマネージャーの機能を有効化する方法を検討したところ
以下の壁にぶつかりました。(①～④までは機能を有効化するまでに思考した過程となります。)

①セッションマネージャーを利用するためには、Privateサブネットに配置されている
　インスタンス内のSSMエージェントからインターネット上にある
　SSMのエンドポイントに接続する必要がある。
↓
②SSMのエンドポイントに接続するためにはProxyサーバに接続する必要がある。
↓
③SSMエージェントのConfigにProxyの設定をする必要がある。
↓
④SSMエージェントのConfigを編集するためにはSSH接続する必要がある(!?)

④に結論に辿り着いたとき、やはり無理かと諦めかけたのですが、、そこで１つの
案が浮かびました。それはインスタンス作成時に設定できる**「ユーザーデータ」**です。
「ユーザーデータ」で③の設定をすれば、インスタンス起動時には③の設定がされた状態で
起動させることができます。では、次の章で具体的な手順について説明します。

# 手順

####1．インスタンスの新規作成

以下の表に従ってインスタンスを作成します。

|   項目    | 選択する項目 |
|:-----------------|------------------:|
|  Amazon マシンイメージ (AMI)            |  Amazon Linux 2※1 |
| インスタンスタイプ            |   任意 |
| サブネット             |  Privateサブネット |
| IAM ロール             | AmazonEC2RoleforSSM※2|
| ユーザーデータ             |  <後述のユーザーデータ>※3 |
| ストレージ            |   任意 |
※1 後述のProxyの設定手順がAmazon Linux2専用のため、必ずAmazon Linux2を選択してください。
※2 セッションマネージャで操作するためにロールを追加する必要があります。
   「AmazonEC2RoleforSSM」はAWS側で用意されているため、今回はこちらを使用します。
    同等の権限のロールを別途用意しても構いません。
※3 以下の内容をユーザーデータに記載します。

```
#!/bin/bash
sudo systemctl stop amazon-ssm-agent
PROXY=<ProxyサーバのIPアドレス>
PORT=<Proxyサーバのポート番号>
sed -i -e "s/\[Service\]/\[Service\]\nEnvironment=\"http_proxy=http:\/\/$PROXY:$PORT\"\nEnvironment=\"http_proxy=https:\/\/$PROXY:$PORT\"\nEnvironment=\"no_proxy=169.254.169.254\"/g" /usr/lib/systemd/system/amazon-ssm-agent.service
sudo systemctl daemon-reload
sudo systemctl start amazon-ssm-agent
```
##### ユーザーデータの説明
ユーザーデータで設定している内容を説明します。
設定内容は、SSMエージェントのUnitファイルをsedコマンドを使用して、Proxyの設定を追加しています。併せてUnitファイルの書き換えの事前事後でプロセスの停止と起動を行っています。
※赤字部分がsedコマンドで置換した箇所です。
![構成図3.png](https://qiita-image-store.s3.amazonaws.com/0/192426/38a04f2a-7589-faa7-4a86-cd58569f9cdc.png)

SSM エージェントのプロキシ設定についての詳細は以下URLをご参照ください。
https://docs.aws.amazon.com/ja_jp/systems-manager/latest/userguide/sysman-proxy-with-ssm-agent.html

####2．セッションマネージャの起動

1. Systems Managerの画面からセッションマネージャを開きます。

2. [セッション開始]を押下します。

3. 出力されたセッションIDをクリックします。

4. ターミナル画面が表示され、コマンドプロンプトが出力されることを確認します。→これでログインできたことになります。

####3．他のインスタンスへのログイン方法

1. ターミナル上で空ファイルを作成します。(例：secretkey)

2. ファイルをviなどのエディタで開きます。

3. ファイルに、手元にあるインスタンスにログインするときに使用する秘密鍵の内容を上書きします。
★セッションマネージャで開いたコンソールは、コピー＆ペーストが有効なので、
　ローカルでコピーした内容をコンソール上で貼り付ける事が可能です。

4. 保存したファイルの権限を600に変更します。これで秘密鍵の代わりに利用することが可能になります。

5. 新しく作成した秘密鍵を利用してインスタンスにログインします。


####　プロキシのホワイトリストで許可するURL
プロキシ配下のインスタンスをセッションマネージャから使用するためには、プロキシを設定する以外にも、プロキシのホワイトリストで特定のURLを事前に許可する必要があります。
理由は、セッションマネージャを利用するためには、以下の図のオレンジ線の様にセッションマネージャのエンドポイントまでの通信が確立していなくては利用できません。許可するURLはこちらです。

* https://ssm.<リージョン名>.amazonaws.com
* https://ec2messages.<リージョン名>.amazonaws.com

![構成図4.png](https://qiita-image-store.s3.amazonaws.com/0/192426/9767467b-6c9f-3a67-4ea9-7fa9968ac20f.png)

# さいごに

今回は、とある制約がある環境下で、外部からの接続経路が途切れてしまった場合に、「セッションマネージャ」と「ユーザーデータ」を利用しての緊急対処法について説明させて頂きました。わたしと全く同じ条件に当てはまる事はないかもしれませんが、何かのときにお役に立てれば幸いです。