OpenSearch DashboardにVPC外からSSM経由でアクセスする

[SSMのポートフォワーディングがリモートホストに対応した](https://aws.amazon.com/jp/about-aws/whats-new/2022/05/aws-systems-manager-support-port-forwarding-remote-hosts-using-session-manager/)ので、これを使ってVPC内OpenSearchドメインのOpenSearch Dashboardに、VPC外から接続してみる。

## やりたいこと
最小限のリソース構成でVPC内ドメインのDashboardにアクセスしたい。

## ステップバイステップ

### 1. AWS CLIをアップグレード（手元端末）

```bash
> brew upgrade awscli
```

### 2. Session Managerプラグインをインストール（手元端末）

[こちら](http://docs.aws.amazon.com/console/systems-manager/session-manager-plugin-not-found)を参照。

### 3. Foxy ProxyをFireFoxにインストール、設定（手元端末）

[こちら](https://aws.amazon.com/jp/premiumsupport/knowledge-center/opensearch-outside-vpc-ssh/)を参照。

こんな感じになればOK。
![スクリーンショット 2022-06-01 午前11.25.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/609876/a83c6efc-f93a-75c0-4acc-cf7f7407d960.png)
Edit。ポートは任意。
![スクリーンショット 2022-06-01 午前11.25.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/609876/fd0a8866-2f45-b0e7-cfe0-471950d66971.png)
Pattern。"http://"や"/_dashboards"を含まないFQDN部を書く。
![スクリーンショット 2022-06-01 午前11.26.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/609876/1b1cbcba-5a67-ce61-300d-dff90b35c70b.png)

ここまでで、端末側の準備は完了。Foxy Proxyはまだ有効化しなくてよい。
続いて、ポートフォワーディングのための中継EC2を準備する。

### 4. 中継EC2を立てる

プライベートサブネットで構わない。
留意点は以下の三つ。
- SSM Agent 3.1.1374.0以降が必要。
    - 既存インスタンスを使う場合はSSM Agentをアップデートしておく。最新のAmazon Linux2であれば問題ない（2022年6月1日現在では、3.1.1476.0がプリインストールされていた）。
    - yumでアップデートしてもいいが、SSM Run Commandで`UpdateSSMAgent`を更新する手もある。
- IAMポリシー`AmazonSSMManagedInstanceCore`が必要。
    - インスタンスプロファイルに、上記ポリシーを含むIAMロールを指定すること。
- OpenSearchドメインにアクセス可能なセキュリティグループが必要
    - 一番簡単なのは、自らをソースとするIngressを許可するセキュリティグループを作り、EC2とOpenSearchドメインの双方に貼っておくこと。ポートは80/tcpが空いていれば今回の範囲ではOK。

![スクリーンショット 2022-06-01 午前11.56.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/609876/fdcb7ea7-14f5-26a1-ce50-b271156210db.png)

### 5. VPCベースのOpenSearchドメインを用意する

これもプライベートサブネットに置けばよい。
ノードタイプやドメイン構成は任意だが、一点留意点として、HTTPS必須にしてしまうとcurlやブラウザでのアクセス時にエラーになってしまうということがある。
ここではチェックを外して、ＨTTPを許容しておく。
![スクリーンショット 2022-06-01 午前11.59.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/609876/4202eaa7-4c77-5f7c-bd63-a519b0f87e34.png)

前述の通り、中継EC2からの80/tcpを許容する必要があるため、セキュリティグループには先程作成のものをOpenSearchドメインにも貼っておく。

これでクラウド側の準備も完了。

### 6. SSMポートフォワーディングを実行する（手元端末）

コンソールを開き、以下を実行する。

```bash
> aws ssm start-session --target i-00a8209ea0a39cfb2 \
--document-name AWS-StartPortForwardingSessionToRemoteHost \
--parameters '{"host":["<OpenSearchドメイン名>-<文字列>.ap-northeast-1.es.amazonaws.com"],"portNumber":["80"],"localPortNumber":["8157"]}'

Starting session with SessionId: xxxx-aaaabbbbccccdddd
Port 8157 opened for sessionId xxxx-aaaabbbbccccdddd.
Waiting for connections...
```

### 7. APIをテスト（手元端末）

別のコンソールウィンドウを開いて、まずAPIエンドポイントをテストする。
ローカルホストと指定ポートに接続すること、およびHTTPを使用しているのがポイント。

```bash
> curl -XGET http://localhost:8157/_cat/indices
green open .kibana_2 y-kg8WrFTfebCwq4xmPR1g 1 0 5 0 11.5kb 11.5kb
green open .kibana_1 ENzsA_19TqaUTNORy2EMUQ 1 0 4 0 17.2kb 17.2kb
```

ここでタイムアウトする場合は、セキュリティグループの設定を見直してみることをお勧めする。
また、疲れているとついlocalhostではなく宛先のFQDNを指定してしまったり、:8157を付け忘れたりして、時間を溶かすことがあるので注意（自分だけか。。。）。

### 8. Foxy Proxyを有効化（手元端末）
FireFoxの右上にあるFoxy Proxyのアイコンから、"Use Enabled Proxies by Patterns and Order"を選ぶ。
![スクリーンショット 2022-06-01 午前11.26.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/609876/c02eed4d-1519-c58c-d99d-9e76c9857f8a.png)

### 9. OpenSearch Dashboadに接続（手元端末）
URLに http://localhost:8157/_dashboards/ を入力する。
![スクリーンショット 2022-06-01 午後12.31.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/609876/3d4a13f0-389b-6278-27ee-0a6eff39e5b8.png)

無事成功。

## まとめ
SSHの併用なしで、シンプルに構成できるようになったのはありがたい。
注意点としては、**何も制限をかけないと「誰でも・どこからでも」プライベートサブネットのリソースにアクセスできるようになってしまう**ので（これはOpenSearch/OpenSearch Dashboardに限らず、SSMのポートフォワーディング、もっというとSSMセッションマネージャ自身が以前から持っている特性ではある）、タグを用いてEC2やSSMドキュメントに適切に縛りをかけることが必須という点。便利機能がただのセキュリティホールになってしまわないよう、注意深く設計する必要がある。

また、ポートフォワーディングでローカルホストに接続する関係上、HTTPS接続がサーバー証明書エラーになってしまう。curlなら--insecureで片付くが、ブラウザは何度もクリックが必要だったり、そもそも受け付けてくれなかったりと使用感にだいぶ影響が出る。セキュリティルール上、HTTPS接続を必須としている場合は注意が必要かも。