介绍
结算报表运行时需要数据库访问权限。任务结束后,保存的凭据应无法再打开新连接。秘密服务返回“已接受”的消息,不足以证明这一结果。
这个独立的 MarketLedger 环境从正确的视图权限开始。你将运行报表、撤销其精确 OpenBao 租约,观察另一租约自然到期,并通过获取新登录账户恢复。商店及其独立库存报表必须仍可使用。前一个引导实验教授了凭据字段和受限报表策略;这里不继承文件或会话状态。
从正常商店和正确报表策略开始
本步骤在启动任何一个租约计时前,先认识正常业务和两个报表角色。全程使用 Terminal。进入独立工作区:
cd /home/labex/project/market-report
cat 显示准备好的正常示例:
cat demo.tsv
结算涵盖 2026-10-28:Birch 有两笔已付款订单,共 4700 分;Elm 一笔,共 2000 分;Maple 一笔,共 2700 分。已取消订单不在其中。报表使用 reporting.daily_settlement;私有客户邮箱和银行参考信息不在范围内。
预置商店客户端访问真实商店服务。其参数标识新订单、商户和以分为单位的金额。为下一个合成交易日期 2026-10-29 下一笔正常订单:
python3 shop.py place --order O201 --vendor V101 --cents 600
这笔较晚的订单不属于昨天的结算。重复命令时,服务拒绝重复订单;使用 python3 shop.py list 查看已有订单,不要删除它。
提供的 env.sh 包含本地服务地址,并从私有文件读取受限操作员令牌。source 将这些赋值加载到当前 shell;export 让子命令可用。新终端必须重新加载:
source env.sh
操作员令牌授权 OpenBao 请求;它不是数据库密码。此令牌可以获取 settlement-report 和 settlement-short 角色的凭据并撤销它们的精确租约。它不能管理独立库存报表或读取数据库管理员连接。
读取正确的账户创建语句:
cat role.sql
这些语句创建具有指定密码到期时间的生成登录账户,授予模式查找和结算视图读取权限,并保留原生 SQL 审计。本实验中保持这些语句和两个角色配置不变。
正常报表角色默认为十分钟。另一个准备好的 settlement-short 角色持续三十秒,视图权限相同。两者都只有在请求凭据后才开始计时。你无需赶在 setup 创建的凭据到期前匆忙完成教程。
你可以签发这些角色的凭据、运行所提供的报表查询、保存报表和私有凭据响应,并撤销自己取得的精确报表租约。保留原始数据库记录、商店、独立库存角色和租约、提供的查询、环境、操作员令牌和预置运行程序。绝不撤销整个租约前缀。
路径拼写错误时,用上面的绝对路径 cd 返回,运行 ls,使用实际文件名重试。无需重置环境即可这样恢复。
使用新的临时登录账户运行结算
本步骤在结束任务访问之前生成真实报表。留在已加载 env.sh 的 Terminal 中。
umask 077 使新文件仅供你的账户使用。bao read -format=json 请求真实动态凭据并输出 JSON;> 将其保存到文件,而不打印密码。本次签发启动十分钟租约计时:
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 命令。询问真实连接使用的身份:
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
预期包含全部三行商户数据,已付款订单数和合计与正常示例相同。运行只读结果检查:
sudo python3 /opt/labex-report/verify.py result
预置检查器使用 sudo 读取受保护的原生证据,并在隔离普通账户测试环境中验证策略 SQL。它不签发线上凭据,也不生成报表。仅复制示例而没有以签发身份执行真实报表查询,无法通过。
如果阅读较慢,登录账户在报表运行前已到期,只请求一次替代凭据,重新加载两个数据库变量,再运行身份和报表命令。如果仍打算显式结束已有签发,在请求另一个之前将其响应另存文件。每个用于运行报表的替代凭据也必须结束自己的精确租约;完成检查使用最新的真实报表执行。
撤销已完成任务的精确租约
本步骤结束报表任务的访问,并使用保存的旧凭据测试新连接。留在 Terminal。
bao lease revoke 请求撤销一次签发。带引号的 $(jq -r .lease_id lease.json) 替换提供保存的完整租约 ID。使用该精确 ID,而非数据库用户名,也非包含其他租约的前缀。如果十分钟签发在阅读期间已到期,撤销操作可能报告找不到租约。为了完成显式撤销练习,保留旧响应,将替代正常角色凭据保存到新文件,重新加载两个数据库变量,重新运行报表,并在下面的命令和探测中使用替代凭据文件名。已到期的签发不能证明你显式撤销了它:
bao lease revoke "$(jq -r .lease_id lease.json)"
CLI 可能报告撤销操作已排队。单凭这个响应不能证明 PostgreSQL 已拒绝旧登录账户。
准备好的 access.py 探测读取保存的凭据,并打开使用密码认证的新 TCP 连接。--wait-denied 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 登录账户实际不可用。同时保持完整报表和独立商店/报表功能完整。它不会替你撤销任何内容。
本练习测试短时客户端命令创建的新连接。密码到期不会强制关闭所有已打开连接;本教程不声称清空所有生产连接池。
观察另一个租约自然到期
本步骤区分自然到期和显式撤销。使用 Terminal 和同一个受限 OpenBao 操作员。
准备好的 settlement-short 角色 TTL 为三十秒。你将在一个操作中请求凭据并立即测试真实的获准读取,因此阅读下方说明不会消耗其可用时间。&& 仅在凭据签发成功时运行探测:
bao read -format=json database/creds/settlement-short > short-lease.json && python3 /opt/labex-report/access.py short-lease.json
预期看到生成的用户名、实际三行结算视图,以及 Native psql exit: 0。其用户名和租约 ID 与显式撤销的任务不同。只读探测不创建你的报表文件,也不替你完成报表任务。
现在让租约自行到期。不要撤销或续租 short-lease.json。 以下探测反复打开新连接,最多等待四十秒以观察真实密码认证拒绝:
python3 /opt/labex-report/access.py short-lease.json --wait-denied 40
如果运行命令前阅读已超过三十秒,拒绝可能立即出现。这仍是自然到期:前面的组合操作已经证明凭据最初可用。否则探测会等到到期。预期与之前一样,出现原生 PostgreSQL 失败和探测确认。
报告服务器不可用的连接错误不能证明到期。如果最初签发或立即读取失败,在重试组合操作前检查错误。不要把从未使用且无效的密码当作有效凭据已到期的证据。最终检查要求短期角色真实读取成功、原生到期事件,以及之后的认证拒绝。
租约计时由你的请求启动,而非 setup;没有步骤要求你在偶然的启动时间窗口内输入。
使用新登录账户恢复并结束其访问
本步骤在旧凭据失效后完成后续报表尝试。留在 Terminal。恢复意味着通过授权服务获取新凭据;编辑旧响应不会续期其数据库身份。
将新的正常角色签发保存为不同文件名,保留之前的证据:
bao read -format=json database/creds/settlement-report > recovery-lease.json
加载新身份并运行相同的真实报表:
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
如果用另一个替代登录账户重新运行报表,也要结束其精确租约。完成检查使用最新真实报表执行背后的身份,因此较早撤销的账户无法证明较晚任务已结束。
预置商店客户端使用独立写入身份。确认今天的正常订单仍在:
python3 shop.py list
运行最终生命周期检查:
sudo python3 /opt/labex-report/verify.py lifecycle
它先读取已有的原生签发、查询、撤销和认证事件,再进行只读保留探测。预期确认存在互相区分的显式撤销、自然到期和替代登录恢复证据,且所测试旧凭据无法打开新连接。原始报表数据、商店和独立库存凭据必须保持完整。
如果替代凭据在阅读期间到期而导致报表命令失败,保留该响应,以新文件名请求另一个替代凭据,重新加载其数据库变量,重新运行报表,并结束新凭据的精确租约。使用已教命令并替换为该文件名。不要延长旧用户名的到期时间,也不要撤销整个角色前缀。
总结
你运行了真实报表,结束其精确租约,观察另一凭据自然到期,并使用新签发身份恢复后也结束了该任务的访问权限。你区分了排队请求与实际数据库拒绝,也区分了服务停止与密码被拒绝。
此结果刻意限定于预置环境中使用密码认证的新连接。它不声明终止了所有已打开会话或生产连接池。挑战会将权限策略和已完成任务的生命周期组合起来,用于另一个报表视图。


