はじめに
普段の業務でAmazon RDS / Aurora(psql) へ接続する際に、AWS Systems Manager(SSM)のポートフォワーディング機能を利用しています。
SSMのポートフォワーディングは運用手順として当たり前のように利用していましたが、今回あらためて仕組みや設定方法について調べる機会があったため、SSMポートフォワーディングを利用してRDS/Auroraへ接続する方法と、その仕組みについて本記事で整理したいと思います。
なぜ SSM ポートフォワーディングなのか
VPC 内のプライベートな RDS/Aurora に外部から接続する方法として以下のような手法が考えられます。
- 踏み台(bastion)EC2 に SSH で入り、そこから psql を叩く
- SSH ローカルフォワーディングでトンネルを張る
しかし、上記のような従来の手法は、いずれもSSH の22番ポートを開ける必要があり、鍵管理や運用上の面倒さがあります。
SSM ポートフォワーディングを使うと、次の利点があります。
- インバウンドポートを一切開けない(SSH不要)。通信は SSM エージェント経由
- 接続は IAM 権限で制御でき、セッションの開始が CloudTrail に記録される(※トンネル内を流れるDB通信の中身までは記録されません)
- 踏み台の公開鍵配布・管理が不要
接続イメージ
localhost:15432
↓ SSM トンネル(インバウンドポート開放なし)
EC2(SSM管理下・DBと同一VPC)
↓
RDS / Aurora PostgreSQL:5432
手元の localhost:15432 に来た通信が、SSM 経由で EC2 に渡り、そこから RDS の 5432 に転送されます。
想定環境: AWS CLI v2 / Session Manager Plugin 導入済み。DBは VPC 内のプライベートサブネットにあり、同一VPC内に SSM 管理下の EC2 インスタンスが1台ある構成を前提にします。
前提となるライブラリのインストール
# AWS CLI v2 の確認
aws --version
# Session Manager Plugin の確認(未導入ならインストールが必要)
session-manager-plugin --version
Session Manager Plugin が入っていない場合は、公式ドキュメントの手順で導入してください。
対象の EC2 には SSM エージェントが稼働し、AmazonSSMManagedInstanceCore 相当の権限(インスタンスプロファイル)が付いている必要があります。また、操作する側の IAM に ssm:StartSession 権限が必要です。
手順
1. SSO ログイン(SSOを使う場合)
aws sso login --profile <YOUR_PROFILE>
認証が通っているかを確認します。
aws sts get-caller-identity --profile <YOUR_PROFILE>
2. ポートフォワーディングを開始する
AWS-StartPortForwardingSessionToRemoteHost ドキュメントを使うと、EC2 を経由してその先のホスト(RDS)へ転送できます。
aws ssm start-session \
--target <INSTANCE_ID> \
--document-name AWS-StartPortForwardingSessionToRemoteHost \
--parameters '{"portNumber":["5432"],"localPortNumber":["15432"],"host":["<RDS_ENDPOINT>"]}' \
--profile <YOUR_PROFILE> \
--region ap-northeast-1
| パラメータ | 意味 |
|---|---|
--target |
経由する EC2 のインスタンスID |
host |
転送先(RDS/Aurora のエンドポイント) |
portNumber |
転送先ポート(PostgreSQL は 5432) |
localPortNumber |
手元で待ち受けるポート(任意。例では 15432) |
以下が表示されれば接続成功です。このターミナルは作業中は閉じないでください。
Starting session with SessionId: ...
Port 15432 opened for sessionId ...
Waiting for connections...
3. 別ターミナルから psql で接続する
トンネルが張れたら、別ターミナルで localhost:15432 に接続します。
psql -h 127.0.0.1 -p 15432 -U <DB_USER> -d <DB_NAME>
接続に成功するとプロンプトが表示されます。
my_db=>
よくあるハマりどころ
複数環境で同じローカルポートを使い回さない
本番と検証で同じ localPortNumber(例では 15432)を使う運用は明快ですが、両方のトンネルを同時に張ると衝突します。片方の作業を終えてからもう片方を開始するか、環境ごとにポートを分けましょう。
トンネルが接続できない
以下を順に確認します。
# 1. SSO の再ログイン
aws sso login --profile <YOUR_PROFILE>
# 2. プラグインの確認
session-manager-plugin --version
# 3. EC2 の状態確認
aws ec2 describe-instances \
--instance-ids <INSTANCE_ID> \
--query 'Reservations[].Instances[].State.Name' \
--profile <YOUR_PROFILE>
それでも繋がらない場合は、EC2 に SSM エージェントが動いているか(マネージドインスタンス一覧に出るか)、RDS 側のセキュリティグループが EC2 からの 5432 を許可しているかを確認します。
注意すべき点
手軽で強力な反面、いくつか気をつける点があります。
- CloudTrail に記録されるのは「セッションの開始」までで、トンネル内を流れるDBクエリの内容は記録されません。監査要件がある場合はDB側の監査ログ(PostgreSQLの
pgaudit等)を併用してください。 -
AWS-StartPortForwardingSessionToRemoteHostは、経由するEC2から到達できる任意のホスト:ポートへ転送できます。ssm:StartSessionを持つ人はRDS以外のVPC内エンドポイントにも同じEC2経由で到達できるため、付与は必要最小限にし、IAM のConditionで対象インスタンスや転送先を絞ることを検討してください。(RDSにだけ繋がせたいつもりなのに、そのEC2がアクセスできる他の内部リソースにも到達できちゃうのでアブナイです) - 本番DBへ接続する際は read-only 等の最小権限のDBユーザを使い、承認フローに従ってください。踏み台を廃した分、作業端末側の安全性(ディスク暗号化・画面ロック)が相対的に重要になります。
- DBパスワードは
~/.pgpassか対話入力で渡します。PGPASSWORD=xxx psql ...のようにコマンドへ平文で書くと、シェル履歴等に残ってしまいます。 - 作業完了後は、ポートフォワーディングのターミナルを
Ctrl+Cで終了してトンネルを閉じてください。
まとめ
- SSM ポートフォワーディングなら、SSH ポートを開けずにプライベートDBへ手元から接続できる
-
AWS-StartPortForwardingSessionToRemoteHostで EC2 の先の RDS まで転送できる - 接続は
localhost:<任意ポート>に対して psql/DBクライアントで行う - 複数環境で同じローカルポートを同時使用しないよう注意する
- 作業が終わったら
Ctrl+Cでセッションを終了する
踏み台の鍵管理から解放され、IAM で一元的にアクセス制御できるのが最大のメリットと言えますね。
参考
- AWS 公式: Session Manager でのポート転送: https://docs.aws.amazon.com/systems-manager/latest/userguide/session-manager-working-with-sessions-start.html
- Session Manager Plugin のインストール: https://docs.aws.amazon.com/systems-manager/latest/userguide/session-manager-working-with-install-plugin.html