Dev Study
← 出して、戻して、直す — 変更と復旧の実務
レッスン 6 / 12·約 9 分·第24期 出して、戻して、直す

秘密が効くかは、確かめる側が決める — 入れ替えと失効

リクエストがアプリケーションに届くまで
  1. ブラウザURL入力
  2. DNS名前→IP
  3. ルータ経路選択
  4. ロードバランサ振り分け
  5. Nginx受け口
  6. アプリ処理
  7. DB保存今ここ

秘密をどこに置くかの次は、秘密を替えたときに何が止まり、何が止まらないかを見ます。

まず結論

パスワードを替える、ロールを無効にする。どちらも記録を書き換える操作で、効くのは確かめる側が次に確かめたときだけです。

PostgreSQL 18.6 の実演では、パスワード変更と NOLOGIN の後も、変更前に開いた接続は問い合わせに答え続けました。開いた接続を止めるにはセッションの強制終了(`pg_terminate_backend`)が要り、実演では別に開いた接続をこれで切りました。入れ替えは「確かめる側が新旧をいつまで受け付けるか」、失効は「確かめる側へどう届けるか」の設計です。

? 読む前に予測

PostgreSQL で、あるロールのパスワードを替え、さらに NOLOGIN にしました。変更前からそのロールで開いていた接続が次の問い合わせを送ると、どうなるでしょうか。

当てることが目的ではありません。外した予測ほど記憶に残るので、直感で選んでください。

抽象原理

書き換えるのは発行側、効かせるのは確かめる側

秘密が漏れたら、まず無効化かローテーション。これは正しい順序で、GitHub Docs も as a first step you need to revoke and/or rotate that secret と書いています。

では、替えた瞬間に何が止まるのか。答えは確かめる側がいつ確かめるかで決まります。パスワードの変更は、確かめる側が照合に使う記録を書き換える操作です。照合が起きない場面には届きません。

PostgreSQL の CREATE ROLE は LOGIN / NOLOGIN をこう説明します。

These clauses determine whether a role is allowed to log in; that is, whether the role can be given as the initial session authorization name during client connection.

判定は during client connection、接続を開くときです。文書に「パスワード変更は既存のセッションに影響しない」と明示した文は見つけていません。言えるのは、判定が接続時と書かれていることと、次の実演で開いた接続が続いたことまでです。

資格情報を書き換えても、確かめる瞬間を過ぎた接続には届かない
ALTER ROLEPASSWORD を替える / NOLOGIN
照合に使う記録が変わる
新しい接続開くときに確かめる → 拒否
開いた接続もう確かめない → 答え続ける
別の操作が要る
pg_terminate_backendセッションを終わらせる
  • ・PostgreSQL 18.6 の実演(scram-sha-256 の経路)で確かめた範囲
具体実物

本教材の実演の出力(スクリプト非掲載)

Docker 上の PostgreSQL 18.6 で、ロール app を作り、古いパスワードで接続を1本開いたまま(pg_sleep(15) の後に次の問い合わせを送る)変更を加えました。パスワードはダミー値です。同じ手順を2回走らせ、全行同じでした。

PostgreSQL 18.6 / Docker、run 1 の生出力(パスワードはダミー値)コマンド出力
== pg_hba.conf(コメント除く)
local all all trust
host all all 127.0.0.1/32 trust
host all all ::1/128 trust
local replication all trust
host replication all 127.0.0.1/32 trust
host replication all ::1/128 trust
host all all all scram-sha-256
== コンテナIP: 172.17.0.2
== [127.0.0.1] 誤ったパスワードで接続
loggedin-127
== [172.17.0.2] 誤ったパスワードで接続
psql: error: connection to server at "172.17.0.2", port 5432 failed: FATAL: password authentication failed for user "app"
== 開いている app の接続(client_addr)
172.17.0.2|app|active
== 手順1: パスワードだけ変える
== [172.17.0.2] 古いパスワードで新規接続
psql: error: connection to server at "172.17.0.2", port 5432 failed: FATAL: password authentication failed for user "app"
== [172.17.0.2] 新しいパスワードで新規接続
loggedin-new
== 手順2: NOLOGIN
== [172.17.0.2] 新しいパスワードで新規接続
psql: error: connection to server at "172.17.0.2", port 5432 failed: FATAL: role "app" is not permitted to log in
== 手順3: 開いている接続の数
1
== 開いていた接続の出力
 
still-alive|0
== 手順4: 別のセッションを開いて pg_terminate_backend で切る
t
== 切られた接続の出力
FATAL: terminating connection due to administrator command
server closed the connection unexpectedly
This probably means the server terminated abnormally
before or while processing the request.
connection to server was lost
  • 手順1: パスワードを替えると、古いパスワードの新規接続は password authentication failed。新しいパスワードは通ります。
  • 手順2: NOLOGIN にすると、新しいパスワードでも not permitted to log in。
  • 手順3: それでも変更前に開いた接続は、スリープ明けの次の問い合わせに still-alive を返しました。
  • 手順4: いったん LOGIN に戻して新しいパスワードで別の接続を開き、NOLOGIN に戻してから pg_terminate_backend で切ると、その接続は terminating connection due to administrator command で終わりました。

「漏れたら打つ手なし」でもありません。確かめる側が接続時にしか確かめないなら、接続そのものを終わらせればよい。打てる手は、その手があると知っていた分だけです。

✓ ここまでの確認

漏えいした DB パスワードを `ALTER ROLE … PASSWORD` で替えました。本教材の実演から言えることはどれですか。

抽象原理

入れ替えとは、新旧が重なる期間の設計

定期の入れ替えでは、書き換えが確かめる側に届くまでの時間差が問題になります。AWS Secrets Manager は2つの方式を書き分けています。

単一ユーザー方式の節:

When the secret rotates, open database connections are not dropped. While rotation is happening, there is a short period of time between when the password in the database changes and when the secret is updated. During this time, there is a low risk of the database denying calls that use the rotated credentials.

開いた接続が落ちないことは、ここでは性質として書かれています。一方、秘密の更新が追いつくまでの短い間は、新しい接続が拒まれうる。

交互ユーザー方式の節は、入れ替えのたびにどちらのユーザーのパスワードを替えるかを交互にし(alternates which user's password it updates)、こう書きます。

After rotation, both user and user_clone credentials are valid.

新旧が重なる期間を、2人のユーザーで作っています。裏返すと、入れ替え直後もそれまで配っていた資格情報が有効なまま残ります。定期の入れ替えと、漏えい時の失効は別の操作として考える必要があります(教材側の読み)。

鍵でも同じ形です。NIST SP 800-57 Part 1 Rev.5 §5.3.4:

The key pair’s originator and recipient-usage periods typically begin at the same time, but the recipient-usage period may extend beyond the originator-usage period.

署名をやめた後も、検証側はしばらく古い公開鍵で検証してよい。入れ替え後も旧鍵を復号用に保持する、と既存クイズが教えるのと同じ向きです。

具体実物

署名鍵の入れ替えと、トークンの失効

署名付きのトークンでは、確かめる側は署名を検証する鍵の集合を持ちます。RFC 7517 §4.5 は kid をこう説明します。

This is used, for instance, to choose among a set of keys within a JWK Set during key rollover.

新しい鍵で署名を始めても、JWK Set に古い公開鍵を残しておけば、確かめる側は kid で選んで古いトークンも検証できます。重なる期間を、鍵の集合で作る形です。

では、特定のトークンだけを今すぐ止めたいとき。RFC 7009 §3(Implementation Note)は、自己完結型のトークンについてこう書きます。

In the former case, some (currently non-standardized) backend interaction between the authorization server and the resource server may be used when immediate access token revocation is desired.

確かめる側が署名だけを見て判断するなら、発行側で失効を記録しても届きません。同じ節は別の設計として、短命のトークンを発行し impose a limit on the time revoked when access tokens are in use を挙げます。届かない期間に上限を置く手です。currently は2013年時点の言葉である点に注意してください。JWT が期限まで有効なまま残る話は第7期で扱います。

✓ ここまでの確認

RFC 7009 §3 の、自己完結型トークンの即時失効は `currently non-standardized` という記述の扱いとして適切なのはどれですか。

⇄ 2つを見比べる
具体例 A

DB パスワード(PostgreSQL)

確かめるのは接続を開くとき。パスワード変更や NOLOGIN は新しい接続を止めるが、開いた接続は答え続けた。止めるにはセッションを終わらせる。

何が止まったか(実演)表
操作 新しい接続 開いた接続
パスワード変更 古い値では拒否 続く
NOLOGIN 新しい値でも拒否 続く
pg_terminate_backend - 終了(別に開いた接続で確認)
具体例 B

署名付きトークン(JWKS)

確かめるのはトークンを受け取るたびで、照合相手は手元の鍵の集合(JWK Set、JWKS)。古い鍵を集合に残せば入れ替えが重なり、発行済みの1本を止めるには短命化か確かめる側への連携が要る。

何で重ね、何で止めるか(RFC 7517・7009)表
目的 手段
新旧の鍵を重ねる JWK Set に両方の鍵、kid で選ぶ
届かない期間を限る 短命のトークン
即時に止める 確かめる側との連携(2013年時点で非標準)

DB の接続とトークンの検証。何が共通していて、どこに手を打つべきでしょうか。

「誰が、いつ照合しているか」を両方で探してください。

この章のまとめ

  • 秘密を替えるのは発行側の記録の書き換え。効くのは確かめる側が次に照合したときだけ。
  • PostgreSQL 18.6 の実演: パスワード変更と NOLOGIN で新規接続は拒否、開いた接続は still-alive。開いた接続を止める手は pg_terminate_backend(実演では手順4で開いた別の接続を切った)。
  • パスワード認証を試すなら、その経路が本当にパスワードを確かめているか(trust でないか)を先に見る。
  • AWS: open database connections are not dropped は単一ユーザー方式、both … credentials are valid は交互ユーザー方式の節。
  • 入れ替えは新旧が重なる期間の設計(NIST §5.3.4、kid)。失効は照合を過ぎたものに届く手段の設計(短命トークン、接続の終了)。
  • RFC 7009 §3 の currently non-standardized は2013年時点の注記。

自分の現場で確かめる

読んだだけでは身につきません。手元の環境で実際に見てみてください。

理解度チェック

読んだ直後は「分かった」と感じやすいものです。実際に解いて確かめてください。

問題 1 / 3正解: 0

AWS Secrets Manager の文書で `open database connections are not dropped` と書かれているのは、どの入れ替え方式の節ですか。

用語集(4語)
確かめる側 (verifier)
資格情報や署名を照合して受け入れるかを決める側。本教材の用語。PostgreSQL では接続を開くときの認証がこれにあたる。
単一ユーザー方式 / 交互ユーザー方式
AWS Secrets Manager の入れ替え方式。前者は1人のパスワードを替え、後者は2人のユーザーのパスワードを交互に替える。
recipient-usage period
NIST SP 800-57 の用語。署名の検証など、保護された情報を処理する側の鍵の使用期間。署名側より長くてよい。
kid (Key ID)
JWK の欄。鍵の入れ替え中に JWK Set の複数の鍵から1つを選ぶのに使う(RFC 7517 §4.5、使用は OPTIONAL)。