0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【AWS SSM】パスワードは合っているのに28P01が出るときはポート競合を疑う

0
Posted at

はじめに

AWS Systems Manager のポートフォワーディングで、ローカルの 5432 を開発環境の RDS(PostgreSQL)に転送して作業していたときの話です。

接続情報は正しいはずなのに認証エラーになる、という状況にハマりました。原因は、ローカルPCの PostgreSQL が 5432 を先に占有していて、SSM トンネルがバインドできていなかったことでした。

同じ踏み方をする人がいそうなので残しておきます。

問題

以下のようにトンネルを張ります。

aws ssm start-session --target i-0xxxxxxxxxxxxxxxx `
  --document-name AWS-StartPortForwardingSessionToRemoteHost `
  --parameters "portNumber=5432,localPortNumber=5432,host=db.example.cloud.local" `
  --profile MyProfile

その上で localhost:5432 に接続すると、認証エラーになります。

28P01: ユーザー"appuser"のパスワード認証に失敗しました
  Severity: FATAL
  SqlState: 28P01
  File: auth.c
  Line: 326
  Routine: auth_failed

28P01 は PostgreSQL のエラーコードで、パスワード認証の失敗を意味します。

しかし、ユーザー名もパスワードも間違っていません。Secrets Manager(AWS の機密情報管理サービス)に保存されている値と照合しても完全に一致していました。

aws secretsmanager get-secret-value --secret-id /dev-app/db/app-common/authentication `
  --profile MyProfile --query "SecretString" --output text
{"password":"xxxxxxxxxxxxxxxx","username":"appuser"}

RDS のステータスも AWS コンソール上で「利用可能」。

そもそも 28P01 は、PostgreSQL サーバー自身が認証処理を行った上で返すエラーです。サーバーが停止していれば認証まで到達せず、接続タイムアウトや接続拒否になるはずなので、「どこかの PostgreSQL は確かに応答している」ことになります。

引っかかったのはエラーメッセージの言語

ここでヒントになったのが、エラーメッセージが日本語だったことです。

RDS は既定でメッセージが英語で返ります。日本語で返ってくるということは、日本語ロケールでインストールされた別の PostgreSQL が応答しているのではないか、と疑いました。

解決方法

5432 を Listen しているプロセスを確認します。

Get-NetTCPConnection -LocalPort 5432 -State Listen |
  Select-Object LocalAddress,LocalPort,OwningProcess
LocalAddress LocalPort OwningProcess
------------ --------- -------------
::                5432          8176
0.0.0.0           5432          8176

PID から実体を辿ります。

Get-Process -Id 8176
Handles  NPM(K)    PM(K)      WS(K)     CPU(s)     Id  SI ProcessName
-------  ------    -----      -----     ------     --  -- -----------
    420      16     7796      23716              8176   0 postgres

犯人は postgres。ローカルにインストールされていた PostgreSQL が 5432 を掴んでおり、SSM トンネルはこのポートにバインドできていませんでした。

その結果、localhost:5432 への接続はすべてローカルの PostgreSQL に向かい、そこには該当ユーザーが存在しない(またはパスワードが異なる)ため 28P01 を返していた、というわけです。

対処A: ローカルの PostgreSQL を停止する

services.msc を開き、postgresql-x64-16 サービスを停止します。スタートアップの種類が「自動」だとPC再起動のたびに復活するので、「手動」に変えておくと安心です。

PowerShell(管理者権限)からでも停止できます。

Get-Service | Where-Object { $_.Name -like "*postgre*" }
Stop-Service -Name postgresql-x64-16

停止後にトンネルを張り直せば、5432 で RDS に接続できます。

対処B: 別ポートでトンネルを張る

ローカルの PostgreSQL を止めたくない場合は、競合しないポートを使います。

aws ssm start-session --target i-0xxxxxxxxxxxxxxxx `
  --document-name AWS-StartPortForwardingSessionToRemoteHost `
  --parameters "portNumber=5432,localPortNumber=15432,host=db.example.cloud.local" `
  --profile MyProfile

接続側も 15432 に向けます。

psql "postgresql://appuser@localhost:15432/app_common"

こちらのほうが、ローカル環境を壊さず切り分けもできるので個人的にはおすすめです。

正常な状態を確認する

ローカルの PostgreSQL を停止してトンネルを張り直したあと、もう一度 5432 の持ち主を確認します。

Get-NetTCPConnection -LocalPort 5432 -State Listen |
  Select-Object LocalAddress,LocalPort,OwningProcess
LocalAddress LocalPort OwningProcess
------------ --------- -------------
127.0.0.1         5432         38344
Get-Process -Id 38344
Handles  NPM(K)    PM(K)      WS(K)     CPU(s)     Id  SI ProcessName
-------  ------    -----      -----     ------     --  -- -----------
    358      23    56464      24932       0.27  38344   2 session-manager-plugin

session-manager-plugin が 5432 を掴んでいれば、トンネルが正しくバインドできている状態です。これで RDS に接続できるようになりました。

ちなみに LocalAddress の違いも見分けるポイントになります。

状態 LocalAddress
ローカルの PostgreSQL 0.0.0.0::
SSM トンネル 127.0.0.1 のみ

SSM のポートフォワーディングはループバックアドレスにのみバインドするため、0.0.0.0:: が並んでいたらトンネル以外のプロセスを疑ってよさそうです。

おわりに

厄介なのは、SSM トンネルがバインドに失敗しても接続自体は成立してしまう点です。エラーで止まってくれれば気づけるのですが、静かに別の DB に繋がるため「設定は合っているのに認証だけ通らない」という紛らわしい状態になります。

今回の教訓は以下です。

  • 28P01 はサーバーに到達している証拠。ネットワーク経路や RDS の死活を疑う前に、どのサーバーが応答しているかを考える
  • エラーメッセージの言語やフォーマットは有力なヒントになる
  • 「設定は正しいのに繋がらない」ときは、まず Get-NetTCPConnection でポートの持ち主を確認する

そもそもローカルの開発用ポートと、トンネル用のポートは最初から分けておくのが無難かもしれません。

参考

JISOUのメンバー募集中!

プログラミングコーチングJISOUでは、新たなメンバーを募集しています。
日本一のアウトプットコミュニティでキャリアアップしませんか?
興味のある方は、ぜひホームページをのぞいてみてください!
▼▼▼
https://projisou.jp

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?