Session Manager を使用してローカル環境から ポートフォワードで RDS へ接続する

# はじめに
DB サーバーはプライベートサブネットに配置するのが通常のため、ローカル環境から直接アクセスはできないので踏み台となる bastion サーバーを経由してポートフォワードなどを行うことが一般的かなと思います。
ただ、最近のセキュリティ事情で踏み台サーバーに対しても ssh 接続が禁止になって来ていることが多いです。
Session Manager を利用するそのような状況でも対応できます。

# 前提構成
ネットワーク構成は Public, Private, DB の3つに分けています。
![sessionmanager001.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/82090/d47f69ae-1c46-44a6-a1aa-38851874c70d.png)
Public Subnet には NAT ゲートウェイを配置し、踏み台となる EC2 インスタンスは Private Subnet に配置しています。
これは ssm エージェントが外へ出る必要があるためです。そのため、ルートテーブルのデフォルトは NAT ゲートウェイを指定しています。
もし NAT ゲートウェイを配置できない環境の場合は VPC エンドポイントを用意してください。
DB Subnet は外部通信を完全に遮断したいためルートテーブルのデフォルトは設定していません。
また、EC2 インスタンスには ssm エージェントがインストールされていて、ロール権限も与えられている状態です。つまり、Session Manager で EC2 インスタンスへ接続ができる状態です。

# 事前準備
ローカル環境は Mac になります。
事前準備として AWS CLI と DB へ接続するための PostgreSQL クライアントをインストールします。
## AWS CLI インストール
以下のリンクを参考にインストールを行ってください。

https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/getting-started-install.html

## PostgreSQLクライアント インストール
Mac のパッケージマネージャーの Homebrew を利用してインストールを行います。
```zsh:postgresql チェック
% brew search postgresql
==> Formulae
postgresql@11        postgresql@12        postgresql@13        postgresql@14        postgresql@15        postgresql@16        postgresql@17        qt-postgresql        postgrest

==> Casks
navicat-for-postgresql                                                                          posture-pal

If you meant "postgresql" specifically:
postgresql breaks existing databases on upgrade without human intervention.

See a more specific version to install with:
  brew formulae | grep postgresql@
```

```zsh:postgresql インストール
% brew install postgresql
==> Auto-updating Homebrew...
Adjust how often this is run with HOMEBREW_AUTO_UPDATE_SECS or disable with
HOMEBREW_NO_AUTO_UPDATE. Hide these hints with HOMEBREW_NO_ENV_HINTS (see `man brew`).
==> Downloading https://ghcr.io/v2/homebrew/portable-ruby/portable-ruby/blobs/sha256:d9faa506c014dedc0b034a68103ba75c9a58242f4d6c67b6ca0f649c39602bcf
######################################################################################################################################################################################## 100.0%
==> Pouring portable-ruby-3.3.7.arm64_big_sur.bottle.tar.gz
==> Auto-updated Homebrew!
Updated 4 taps (hashicorp/tap, weaveworks/tap, homebrew/core and homebrew/cask).
==> New Formulae

~~~ 省略 ~~~

==> Caveats
==> postgresql@14
This formula has created a default database cluster with:
  initdb --locale=C -E UTF-8 /opt/homebrew/var/postgresql@14

To start postgresql@14 now and restart at login:
  brew services start postgresql@14
Or, if you don't want/need a background service you can just run:
  /opt/homebrew/opt/postgresql@14/bin/postgres -D /opt/homebrew/var/postgresql@14
==> python@3.12
Python is installed as
  /opt/homebrew/bin/python3.12

Unversioned and major-versioned symlinks `python`, `python3`, `python-config`, `python3-config`, `pip`, `pip3`, etc. pointing to
`python3.12`, `python3.12-config`, `pip3.12` etc., respectively, are installed into
  /opt/homebrew/opt/python@3.12/libexec/bin

If you do not need a specific version of Python, and always want Homebrew's `python3` in your PATH:
  brew install python3

See: https://docs.brew.sh/Homebrew-and-Python
```

# 設定
start-session コマンドのオプションを利用することでポートフォワードが行えます。
```zsh:ポートフォワード
% aws ssm start-session \
    --target インスタンスID \
    --document-name AWS-StartPortForwardingSessionToRemoteHost \
    --parameters '{"portNumber":["5432"],"localPortNumber":["15432"],"host":["エンドポイント"]}'
```

```zsh:DB アクセス
% psql -h 127.0.0.1 -p 15432 -U ユーザー名 -d データベース名
Password for user ユーザー名: 
psql (14.16 (Homebrew), server 16.4)
WARNING: psql major version 14, server major version 16.
         Some psql features might not work.
SSL connection (protocol: TLSv1.3, cipher: TLS_AES_256_GCM_SHA384, bits: 256, compression: off)
Type "help" for help.

データベース名=> exit
```

# おわりに
Session Manager をうまく活用することでプライベートネットワークにあるインスタンスに対してもローカル環境からアクセスできるためとても便利だと思います。

### 参考
https://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/UserGuide/custom-creating.ssm.html