【Rails】SSMを使用してRDSのポートフォワーディングをローカルでセットアップする方法

セキュリティに考慮しつつ、Railsアプリケーション上でRDSのデータベースにアクセスしたいなぁ...というケースがあったので、備忘録的に書き残しております。

2024年04月17日

前提条件

  • AWS CLI がインストールされていること
  • 動作中のRDSインスタンスが存在していること
  • 適切な IAM ロールとポリシーが設定されていること(SSMがRDSへのアクセス権限を持っている)
  • Railsアプリがすでにあること

セッションを開始

RailsアプリケーションからリモートのRDSインスタンスにアクセスしたいので、AWS-StartPortForwardingSessionToRemoteHost を指定しましょう。

aws ssm start-session --target instance-id \
  --document-name AWS-StartPortForwardingSessionToRemoteHost \
  --parameters '{"host":["your-rds-endpoint"],"portNumber":["3306"], "localPortNumber":["9999"]}'
  • instance-id: Session Manager 経由で接続する EC2 インスタンスの ID です。
  • parameters.host: RDSインスタンスのエンドポイント(xxxx.ap-northeast-1.rds.amazonaws.com
  • parameters.portNumber: RDS インスタンスのポート番号(MySQL の場合は通常 3306)。
  • parameters.localPortNumber: ローカルマシン上で使用するポート番号

疎通確認(MySQL)

MySQLを例にして疎通確認をしてみます。
パスワードの入力を求められるので、RDSで設定しているものを。

$ mysql -h 127.0.0.1 -P 9999 -u root -p 

疎通確認ができれば大丈夫です。

Rails側の設定

難しいことはなく、先ほどの疎通確認で入力したものを設定していくだけです。

  • database: RDSの対象DB名
  • username: RDSのusername(基本root)
  • port: SSMで入力したlocalPortNumber
  • host: localhostを指定
default: &default
  adapter: mysql2
  encoding: utf8mb4
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>

development:
  <<: *default
  database: database
  username: root
  port: 9999
  password: password
  host: 127.0.0.1

ただ、dockerでは一癖あります。
勘の良い方はお分かりの通り、SSMをホストマシンで動かしているので、少し工夫が必要です。

dockerの場合

まずはdocker用のhostに変えておきます。

database.yml

development:
  <<: *default
  database: database
  username: root
  port: 9999
  password: password
  host: host.docker.internal # ここ

※ Docker 20.04 以降でLinux環境でも host.docker.internal が使用できるようになったみたいです。

あとはネットワークモードをhostに変更。

docker-compose.yml

  # 例です
  mysql:
    environment:
      MYSQL_ALLOW_EMPTY_PASSWORD: "yes"
    network_mode: "host" # この設定をしよう

以上です。

筆者情報
IT業界経験6年目のフルスタックエンジニア。
フロントエンドを軸として技術を研鑽中でございます。