レポート完了時にデータベースアクセスを終了する

PostgreSQLBeginner
オンラインで実践に進む

はじめに

精算レポートには、実行中のデータベースアクセスが必要です。仕事が終わったら、保存された資格情報では新しい接続を開けなくなるべきです。シークレットサービスからの受け付けメッセージだけでは、その結果の証拠として不十分です。

この独立した MarketLedger 環境は、正しいビュー権限から始まります。レポートを実行し、対象の OpenBao リースを正確に指定して失効させ、別のリースが自然に期限切れになる様子を観察し、新しいログインの取得で復旧します。店舗と独立した在庫レポートは使えるままにする必要があります。前のガイド付き実習では、資格情報のフィールドと制限付きレポートポリシーを学びました。ファイルやセッション状態は引き継ぎません。

稼働中の店舗と正しいレポートポリシーから始める

このステップでは、どちらのリースの時計も開始する前に、通常の業務と 2 つのレポートロールを確認します。一貫して Terminal を使います。独立したワークスペースへ移動します。

cd /home/labex/project/market-report

cat で準備済みの正常な例を表示します。

cat demo.tsv

精算の対象は 2026-10-28 です。Birch は支払い済み注文 2 件で計 4700 セント、Elm は 1 件で計 2000 セント、Maple は 1 件で計 2700 セントです。キャンセルされた注文は除外されます。レポートは reporting.daily_settlement を使い、非公開の顧客メールアドレスと銀行参照情報は対象外です。

準備済み店舗クライアントは実際の店舗サービスと通信します。引数は新しい注文、出店者、セント単位の金額を指定します。次の合成取引日 2026-10-29 に、通常の注文を作成します。

python3 shop.py place --order O201 --vendor V101 --cents 600

この後日の注文は昨日の精算に含まれません。コマンドを繰り返すと、サービスは重複を拒否します。削除せず、python3 shop.py list で既存の注文を確認してください。

付属の env.sh はローカルサービスのアドレスを持ち、非公開ファイルから制限付きオペレータートークンを読みます。source はその代入を現在のシェルに読み込み、export は子コマンドでも使えるようにします。新しいターミナルでは再読込が必要です。

source env.sh

オペレータートークンは OpenBao の要求を認可するもので、データベースのパスワードではありません。このトークンでは、settlement-report と settlement-short ロールの資格情報取得と、対象リースの個別失効ができます。独立した在庫レポートの管理や、データベース管理者接続の読み取りはできません。

正しいアカウント作成文を読みます。

cat role.sql

これらは、指定されたパスワード有効期限を持つログインを生成し、スキーマ参照と精算ビューの読み取り権限を付与し、ネイティブ SQL 監査を保持します。この実習では、これらの文と両ロールの設定は変更しないでください。

通常のレポートロールの既定期間は 10 分です。別途準備された settlement-short ロールは 30 秒間で、同じビュー権限を持ちます。どちらの時計も、資格情報を要求するまで開始しません。セットアップで作られた資格情報が切れる前に急いで教材を進める必要はありません。

これらのロールの資格情報発行、付属レポートクエリの実行、レポートと非公開の資格情報応答の保存、自分で取得した対象レポートリースの個別失効は可能です。元のデータベースレコード、店舗、独立した在庫ロールとリース、付属クエリ、環境、オペレータートークン、準備済みランタイムを保持してください。リース接頭辞全体を決して失効させないでください。

パスを入力し間違えたら、上の絶対パスの cd で戻り、ls を実行して、実際のファイル名で再実行します。環境をリセットせず、この方法で復旧できます。

新しい一時ログインで精算を実行する

このステップでは、その仕事のアクセスを終了する前に実際のレポートを作成します。env.sh を読み込んだ Terminal を使い続けてください。

umask 077 は、新規作成ファイルを自分のアカウントだけに公開します。bao read -format=json は実際の動的資格情報を要求し、JSON を出力します。> はパスワードを表示せず、ファイルに保存します。この発行で 10 分のリースの時計が開始します。

umask 077
bao read -format=json database/creds/settlement-report > lease.json

jq は JSON フィールドを選びます。秘密ではないリース ID、期間、生成されたデータベースユーザー名を読みます。

jq '.lease_id, .lease_duration, .data.username' lease.json

リース ID は OpenBao 内の今回の発行を識別し、ユーザー名はその PostgreSQL ログインを識別します。どちらもオペレータートークンではありません。もう一度見るだけのためにこの応答を上書きしないでください。アクセスを終了するときに、そのリース ID が必要です。

-r は JSON の引用符を取り除きます。引用したコマンド置換で、パスワードを表示せず、生成されたユーザー名とパスワードをデータベースクライアントの環境に読み込みます。

export PGUSER="$(jq -r .data.username lease.json)"
export PGPASSWORD="$(jq -r .data.password lease.json)"

psql -X は個人の psql 起動ファイルを無視し、-v ON_ERROR_STOP=1 は SQL エラーで停止し、-c は SQL コマンドを指定します。実際の接続に、使っている ID を問い合わせます。

psql -X -v ON_ERROR_STOP=1 -c 'SELECT current_user;'

新しく生成されたユーザー名になるはずです。-f report.sql は準備済みクエリを読み、> は実際のタブ区切り出力を保存します。

psql -X -v ON_ERROR_STOP=1 -f report.sql > settlement.tsv
cat settlement.tsv

出店者 3 行すべてについて、支払い済み注文数と合計が正常な例と一致するはずです。読み取り専用の結果チェックを実行します。

sudo python3 /opt/labex-report/verify.py result

準備済みチェックは、sudo で保護されたネイティブ証拠を読み、隔離した通常アカウントの検証環境でポリシー SQL を試します。実際の資格情報を発行したり、レポートを生成したりはしません。発行された ID による実際のレポートクエリがなければ、デモのコピーだけでは合格しません。

ゆっくり読んでいて、レポート実行前にログインが期限切れになった場合は、代わりの資格情報を 1 回だけ要求し、データベース変数を両方再読込して、ID とレポートのコマンドを再実行してください。まだ明示的に終了するつもりの既存の発行分は、別のファイル名で応答を保持してから、次を要求します。レポート実行に使った代替ログインも、それぞれのリースを正確に指定して終了する必要があります。完了判定は、実際の最新レポート実行を使います。

完了した仕事のリースを正確に指定して失効させる

このステップでは、レポートのアクセスを終了し、保存した古い資格情報で新しい接続を試します。Terminal を使い続けてください。

bao lease revoke は、1 回の発行分の失効を要求します。引用した $(jq -r .lease_id lease.json) 置換で、保存した完全なリース ID を渡します。データベースユーザー名や、ほかのリースを含む接頭辞ではなく、その ID を使います。読んでいる間にこの 10 分の発行分が期限切れになった場合、失効要求はリースが見つからないと報告することがあります。明示的な失効の演習では、その古い応答を保持し、新しいファイル名で通常ロールの代替資格情報を取得し、データベース変数を両方再読込してレポートを再実行し、以下のコマンドとプローブで代替分のファイル名を使います。すでに期限切れの発行分は、自分で明示的に失効させた証拠にはなりません。

bao lease revoke "$(jq -r .lease_id lease.json)"

CLI は、失効処理がキューに入ったと表示する場合があります。その応答だけでは、PostgreSQL が古いログインを拒否したことは証明できません。

準備済みの access.py プローブは、保存した資格情報を読み、新しいパスワード認証 TCP 接続を開きます。--wait-denied 10 は、パスワード拒否を最大 10 秒待ちます。データベースが利用できない状態や SQL クエリ拒否とは区別します。サーバーを止めても、この条件は満たせません。

python3 /opt/labex-report/access.py lease.json --wait-denied 10

PostgreSQL の password authentication failed メッセージに続き、この保存済み資格情報では新しい接続を開けないという確認が表示されるはずです。プローブは、psql 本来のステータス 2 を報告します。プローブ自体は、想定する拒否を確認した後にだけ成功を返します。

echo $? は、直前のコマンドの終了ステータスを表示します。ここでは 0 になるはずです。psql が接続に成功したのではなく、プローブが意図した失敗の確認に成功したという意味です。

echo $?

完了した仕事を確認します。

sudo python3 /opt/labex-report/verify.py finished

チェックには、対象リースを正確に指定した失効のネイティブな成功記録、対応する失効完了イベント、その後の新規認証失敗、実際に利用不能な PostgreSQL ログインが必要です。さらに、完全なレポートと独立した店舗・レポート機能が保たれていることも確認します。代わりに何かを失効させることはありません。

この演習で試すのは、短命のクライアントコマンドによる新規接続です。パスワードの期限切れは、すでに開いたすべての接続を強制的に閉じるものではありません。この教材は、本番の接続プールをすべて解消すると主張しません。

別のリースが自然に期限切れになる様子を観察する

このステップでは、自然な期限切れと明示的な失効を区別します。同じ制限付き OpenBao オペレーターを設定した Terminal を使います。

準備済みの settlement-short ロールの TTL は 30 秒です。資格情報の要求と、許可された実際の読み取りの即時テストを 1 回の操作で行います。これにより、次の説明を読む時間が利用可能時間を消費しません。&& は、資格情報の発行が成功した場合だけプローブを実行します。

bao read -format=json database/creds/settlement-short > short-lease.json && python3 /opt/labex-report/access.py short-lease.json

生成されたユーザー名、実際の 3 行の精算ビュー、Native psql exit: 0 が表示されるはずです。明示的に失効させた仕事とは、ユーザー名もリース ID も異なります。この読み取り専用プローブは、レポートファイルを作成したり、代わりにレポートの仕事を完了したりはしません。

次に、このリースを自然に期限切れにします。**short-lease.json を失効または更新しないでください。** 次のプローブは、新しい接続を繰り返し開き、実際のパスワード認証拒否を最大 40 秒待ちます。

python3 /opt/labex-report/access.py short-lease.json --wait-denied 40

このコマンドの前に 30 秒以上読んでいた場合、拒否はすぐに表示されることがあります。それでも自然な期限切れです。先ほどの一体化した操作で、資格情報が最初は機能したことを証明済みだからです。それ以外の場合、プローブは期限切れまで待ちます。先ほどと同じく、PostgreSQL 本来の失敗とプローブの確認が表示されるはずです。

サーバーが利用できないという接続エラーは、期限切れの証拠ではありません。最初の発行または直後の読み取りが失敗した場合は、一体化した操作を再実行する前に、そのエラーを調べてください。未使用の無効なパスワードを、機能していた資格情報が期限切れになった証拠にしないでください。最終チェックには、短期ロールによる実際の読み取り成功、ネイティブな期限切れイベント、その後の認証拒否が必要です。

リースの時計はセットアップではなく、あなたの要求で開始しました。偶然の起動直後の時間枠に合わせて入力しなければならないステップはありません。

新しいログインで復旧し、そのアクセスも終了する

このステップでは、古い資格情報が使えなくなった後のレポート実行を完了します。Terminal を使い続けてください。復旧とは、認可されたサービスを通じて新しい資格情報を取得することです。古い応答を編集しても、データベース ID は更新されません。

以前の証拠を保持できるよう、新しい通常ロールの発行分は別名で保存します。

bao read -format=json database/creds/settlement-report > recovery-lease.json

新しい ID を読み込み、同じ実際のレポートを実行します。

export PGUSER="$(jq -r .data.username recovery-lease.json)"
export PGPASSWORD="$(jq -r .data.password recovery-lease.json)"
psql -X -v ON_ERROR_STOP=1 -f report.sql > settlement.tsv
cat settlement.tsv

完全な業務結果は変わりません。データベースユーザー名は新しくなります。これが古い発行分の終了後に想定される復旧方法です。

この代替の仕事についても、リースを正確に指定して終了します。

bao lease revoke "$(jq -r .lease_id recovery-lease.json)"
python3 /opt/labex-report/access.py recovery-lease.json --wait-denied 10

さらに別の代替ログインでレポートを再実行した場合は、そのリースも正確に指定して終了してください。完了チェックは、実際の最新レポート実行の ID を使います。以前のアカウントが失効済みでも、その後の仕事が終了した証拠にはなりません。

準備済み店舗クライアントは、独立した書き込み ID を使います。今日の通常の注文が残っていることを確認します。

python3 shop.py list

最終ライフサイクルチェックを実行します。

sudo python3 /opt/labex-report/verify.py lifecycle

このチェックは、既存のネイティブな発行、クエリ、失効、認証イベントを読んでから、読み取り専用の保全プローブを実行します。明示的失効、自然な期限切れ、代替ログインでの復旧という別々の証拠が確認され、テストした古い資格情報では新しい接続ができないことが確認されるはずです。元のレポートデータ、店舗、独立した在庫資格情報を保持しなければいけません。

読んでいる間に代替分が期限切れとなってレポートコマンドが失敗した場合は、その応答を保持し、新しいファイル名で別の代替分を要求し、データベース変数を再読込し、レポートを再実行して、その新しいリースを正確に指定して終了します。同じ学習済みコマンドで、そのファイル名を使ってください。古いユーザー名の有効期限を延長したり、ロールの接頭辞全体を失効させたりしないでください。

まとめ

実際のレポートを実行し、そのリースを正確に指定して終了し、別の資格情報が自然に期限切れになる様子を観察しました。その後、新しく発行された ID で復旧し、その仕事のアクセスも終了しました。キューに入った要求と実際のデータベース拒否、停止したサービスと拒否されたパスワードを区別しました。

結果の範囲は意図的に、この準備済み環境におけるパスワード認証の新規接続に限定しています。すでに開かれたすべてのセッションや本番の接続プールが終了したと主張するものではありません。チャレンジでは、別のレポートビューに対して、権限ポリシーと仕事完了時のライフサイクルを組み合わせます。