うっかりrdsproxyadminのパスワードを変更してもRDS Proxyが正常動作するのか確認してみた

うっかりrdsproxyadminユーザーのパスワードを変更しても自動復旧してくれるみたいです
2022.05.21

MAD事業部@大阪の岩田です。

RDS Proxyを作成するとRDS側にrdsproxyadminというDBユーザーが作成されます。RDS Proxyを構築したRDSに対してクエリを発行すると、このrdsoroxyadminユーザーがバックエンドで何をしているのかが想像できます。例えば、以下はRDS for PostgreSQLに対してクエリを実行した結果です。

postgres=> select * from pg_stat_activity where usename = 'rdsproxyadmin';
-[ RECORD 1 ]----+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
datid            | 14301
datname          | postgres
pid              | 31648
leader_pid       |
usesysid         | 16418
usename          | rdsproxyadmin
application_name |
client_addr      | 172.31.25.179
client_hostname  |
client_port      | 60973
backend_start    | 2022-05-21 08:49:00.251829+00
xact_start       |
query_start      | 2022-05-21 08:58:12.352717+00
state_change     | 2022-05-21 08:58:12.352914+00
wait_event_type  | Client
wait_event       | ClientRead
state            | idle
backend_xid      |
backend_xmin     |
query            | SELECT current_setting('transaction_read_only') AS transaction_read_only, current_setting('max_connections') AS max_connections, EXTRACT(EPOCH FROM now() - pg_postmaster_start_time()) AS uptime;
backend_type     | client backend
-[ RECORD 2 ]----+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
datid            | 14301
datname          | postgres
pid              | 31668
leader_pid       |
usesysid         | 16418
usename          | rdsproxyadmin
application_name |
client_addr      | 172.31.14.233
client_hostname  |
client_port      | 51371
backend_start    | 2022-05-21 08:49:00.604766+00
xact_start       |
query_start      | 2022-05-21 08:58:12.472398+00
state_change     | 2022-05-21 08:58:12.472623+00
wait_event_type  | Client
wait_event       | ClientRead
state            | idle
backend_xid      |
backend_xmin     |
query            | SELECT current_setting('transaction_read_only') AS transaction_read_only, current_setting('max_connections') AS max_connections, EXTRACT(EPOCH FROM now() - pg_postmaster_start_time()) AS uptime;
backend_type     | client backend

max_connectionsのような設定値を取得しているのが分かります。これはRDS Proxyのターゲットグループに設定値できる「接続プールの最大接続数」の割合に応じて、コネクションプールで管理するDB接続数を計算するためだと推測できます。

ここで1つ疑問が生まれます。rdsoroxyadminユーザーがRDSに接続できなくなり、max_connectionsのような設定値が取得できなくなるとRDS Proxyはどうなるのでしょうか?正常に利用できなくなってしまうのでしょうか?ということでrdsoroxyadminユーザーのパスワードを変更するとどうなるか試してみました。

環境

今回利用したRDSの環境です

  • RDS for PostgreSQL
  • エンジンバージョン 13.6
  • インスタンスクラス db.t3.micro

やってみる

軽く事前準備と確認

まずはRDS & RDS Proxyの環境を構築します。手順の詳細は割愛しますが、今回はuser01というDBユーザーを作成し、このDBユーザー用のシークレットをRDS Proxyに設定しました。また、user01が接続可能なdb1というデータベースも作成しています。

適当なEC2からpsqlでRDS Proxy経由でRDSに接続してクエリを発行してみます

[ec2-user@ip-172-31-9-117 ~]$ psql -h <RDSプロキシのエンドポイント> -U user01 db1
Password for user user01:
psql (13.3, server 13.6)
SSL connection (protocol: TLSv1.2, cipher: ECDHE-RSA-AES256-GCM-SHA384, bits: 256, compression: off)
Type "help" for help.

db1=> select now();
              now
-------------------------------
 2022-05-21 09:18:55.341477+00
(1 row)

OKです。

これでRDS Proxyのコネクションプールにuser01用のDB接続がプーリングされたので、別のpsqlセッションからRDSに直接接続し、RDS <-> RDS Proxy間の接続をクローズしておきます。

postgres=> select pid from pg_stat_activity where usename = 'user01';
  pid
-------
 30349
  2604
(2 rows)

postgres=> select pg_terminate_backend(2604);
 pg_terminate_backend
----------------------
 t
(1 row)

postgres=> select pg_terminate_backend(30349);
 pg_terminate_backend
----------------------
 t
(1 row)

postgres=> select pid from pg_stat_activity where usename = 'user01';
 pid
-----
(0 rows)

rdsproxyadminのパスワードを変更してみる

ここからが本題です。RDSのマスターユーザーを使ってrdsproxyadminのパスワードを変更してみましょう。psqlからRDSに直接接続し、以下のSQLを発行します。

postgres=> alter role rdsproxyadmin with password 'hogehogehogehoge';
ALTER ROLE

特にエラーなくパスワードが変更できてしまいました。続いてすでに確立済みのRDS Proxy <-> RDS間の接続を全てクローズします。これで、以後RDS Proxyはrdsproxyadminユーザーを使ってRDSに接続できなくなり、max_connectionsのような情報が取得できなくなるはずです。

postgres=> select pid from pg_stat_activity where usename = 'rdsproxyadmin';
  pid
-------
 12636
 12640
(2 rows)

postgres=> select pg_terminate_backend(12636);
 pg_terminate_backend
----------------------
 t
(1 row)

postgres=> select pg_terminate_backend(12640);
 pg_terminate_backend
----------------------
 t
(1 row)

準備が整ったので、EC2からRDS Proxyに接続します

psql -h <RDSプロキシのエンドポイント> -U user01 db1
Password for user user01:
psql (13.3, server 13.6)
SSL connection (protocol: TLSv1.2, cipher: ECDHE-RSA-AES256-GCM-SHA384, bits: 256, compression: off)
Type "help" for help.

接続に成功しました。この時点ではあくまでpsql <-> RDS Proxy間の接続に成功しただけで、RDS <-> RDS Proxy間の接続は確立していません。

実際にクエリを発行してみます。本来であればこれでRDS <-> RDS Proxy間の接続が確立し、RDS Proxy経由でRDSにクエリが発行されるはずです。

db1=> select now();

一瞬で実行完了しそうなクエリですが、なかなか応答が返ってきません。やはりrdsproxyadminのパスワードを変更したことでRDS PRoxyが壊れてしまったのでしょうか??と思いきや、、、

db1=> select now();
             now
------------------------------
 2022-05-21 09:28:29.46803+00
(1 row)

20秒ほど待った時点で応答が返ってきました!この約20秒の間にRDS Proxyが管理しているrdsproxyadminユーザーのパスワードが再設定されたということでしょうか?

ログを分析してみる

こんなこともあろうかとlog_statement=allの設定を入れていたので、裏側で何が起こっていたのかログを見ながら分析してみましょう。ノイズになりそうな部分は省略して主要なログだけ抜粋しています。

まずはrdsproxyadminユーザーのパスワードを変更したログです

2022-05-21 09:23:41 UTC:172.31.9.117(42870):postgres@postgres:[2245]:LOG:  statement: alter role rdsproxyadmin with password 'hogehogehogehoge';

すでに確立済のDBセッションはパスワード変更の影響を受けないので、引き続きrdsproxyadminユーザーからクエリが発行されています。

2022-05-21 09:23:41 UTC:172.31.25.179(42465):rdsproxyadmin@postgres:[12636]:LOG:  statement: SELECT current_setting('transaction_read_only') AS transaction_read_only, current_setting('max_connections') AS max_connections, EXTRACT(EPOCH FROM now() - pg_postmaster_start_time()) AS uptime;
2022-05-21 09:23:41 UTC:172.31.14.233(26535):rdsproxyadmin@postgres:[12640]:LOG:  statement: SELECT current_setting('transaction_read_only') AS transaction_read_only, current_setting('max_connections') AS max_connections, EXTRACT(EPOCH FROM now() - pg_postmaster_start_time()) AS uptime;
2022-05-21 09:23:42 UTC:172.31.25.179(42465):rdsproxyadmin@postgres:[12636]:LOG:  statement: SELECT current_setting('transaction_read_only') AS transaction_read_only, current_setting('max_connections') AS max_connections, EXTRACT(EPOCH FROM now() - pg_postmaster_start_time()) AS uptime;

確立済のDBセッションをクローズしたログです

2022-05-21 09:27:27 UTC:172.31.9.117(42870):postgres@postgres:[2245]:LOG:  statement: select pg_terminate_backend(12636);
2022-05-21 09:27:27 UTC:172.31.25.179(42465):rdsproxyadmin@postgres:[12636]:FATAL:  terminating connection due to administrator command

多少順番が前後してしまいますがpid12640の方もクローズしています

2022-05-21 09:27:29 UTC:172.31.9.117(42870):postgres@postgres:[2245]:LOG:  statement: select pg_terminate_backend(12640);
2022-05-21 09:27:29 UTC:172.31.14.233(26535):rdsproxyadmin@postgres:[12640]:FATAL:  terminating connection due to administrator command

その後新たにrdsproxyadmin用のセッションを確立すべくRDS ProxyからRDSに接続を試行しているログが確認できます。パスワードはRDS Proxyが認識していないhogehogehogehogeに変更されているので、接続に失敗していることが分かります。

2022-05-21 09:27:28 UTC:172.31.25.179(24407):rdsproxyadmin@postgres:[12780]:FATAL:  password authentication failed for user "rdsproxyadmin"
2022-05-21 09:27:28 UTC:172.31.25.179(24407):rdsproxyadmin@postgres:[12780]:DETAIL:  Password does not match for user "rdsproxyadmin".
        Connection matched pg_hba.conf line 13: "host   all                             all                     all                     md5"
2022-05-21 09:27:29 UTC:172.31.25.179(4727):rdsproxyadmin@postgres:[12804]:FATAL:  password authentication failed for user "rdsproxyadmin"
2022-05-21 09:27:29 UTC:172.31.25.179(4727):rdsproxyadmin@postgres:[12804]:DETAIL:  Password does not match for user "rdsproxyadmin".
        Connection matched pg_hba.conf line 13: "host   all                             all                     all                     md5"
2022-05-21 09:27:30 UTC:172.31.14.233(48579):rdsproxyadmin@postgres:[12860]:FATAL:  password authentication failed for user "rdsproxyadmin"
2022-05-21 09:27:30 UTC:172.31.14.233(48579):rdsproxyadmin@postgres:[12860]:DETAIL:  Password does not match for user "rdsproxyadmin".
        Connection matched pg_hba.conf line 13: "host   all                             all                     all                     md5"

psqlからselect now()を実行したあたりのログです。接続失敗のログが止まり、max_connections等の設定値を取得するクエリのログが確認できます。その後select now()に成功したログが確認できます。

2022-05-21 09:28:28 UTC:172.31.25.179(61119):rdsproxyadmin@postgres:[13979]:FATAL:  password authentication failed for user "rdsproxyadmin"
2022-05-21 09:28:28 UTC:172.31.25.179(61119):rdsproxyadmin@postgres:[13979]:DETAIL:  Password does not match for user "rdsproxyadmin".
        Connection matched pg_hba.conf line 13: "host   all                             all                     all                     md5"
2022-05-21 09:28:28 UTC:172.31.14.233(22933):rdsproxyadmin@postgres:[13991]:LOG:  statement: SELECT current_setting('transaction_read_only') AS transaction_read_only, current_setting('max_connections') AS max_connections, EXTRACT(EPOCH FROM now() - pg_postmaster_start_time()) AS uptime;
2022-05-21 09:28:29 UTC:172.31.25.179(31605):rdsproxyadmin@postgres:[14006]:LOG:  statement: SELECT current_setting('transaction_read_only') AS transaction_read_only, current_setting('max_connections') AS max_connections, EXTRACT(EPOCH FROM now() - pg_postmaster_start_time()) AS uptime;
2022-05-21 09:28:29 UTC:172.31.25.179(14657):user01@db1:[14007]:LOG:  statement: select now();
2022-05-21 09:28:29 UTC:172.31.14.233(22933):rdsproxyadmin@postgres:[13991]:LOG:  statement: SELECT current_setting('transaction_read_only') AS transaction_read_only, current_setting('max_connections') AS max_connections, EXTRACT(EPOCH FROM now() - pg_postmaster_start_time()) AS uptime;

rdsproxyadminユーザーのパスワードを変更する(元に戻す?)ログこそ確認できませんでしたが、上記のログから考えるとユーザー側で無理矢理rdsproxyadminユーザーのパスワードを変更しても、RDS Proxyの基盤側でrdsproxyadminのパスワードを再設定するため、最小限のダウンタイムで復旧できると考えて良さそうです。

まとめ

まあ普通はやらないと思いますが、うっかりrdsproxyadminユーザーのパスワードを変更しても安心です!