介绍
一个临时调试设置在新版 DeskLite 服务中再次出现。请求仍然成功,但运行日志现在包含虚构凭据。仅检查功能成功,没有发现这次回归。
你将追踪真实请求证据,停止新的泄漏,替换已泄漏凭据,并添加能阻止真实泄漏候选版本的断言。历史日志保留为证据;无需调查文档。本地签发工具、客户端、服务、对照实现和产物辅助程序均已准备好。
定位真实事件记录
在本步骤中,你将把请求与当前日志版本和配置关联起来。
cd /srv/ticket-regression
tail -n 5 读取最后五行,让查看范围保持较小。使用已获授权的管理员读取权限,查看预置服务日志:
sudo tail -n 5 /opt/labex-ticket-regression/requests.log
找到 request_id=initial-001、version=logging-v2、path=/tickets 和 status=200。这个历史请求成功了,但同一行还包含 Authorization 和旧虚构令牌。所有值仅属于本隔离实验。
grep 打印包含指定文本模式的行。单引号将这个字面模式保持为一个整体:
sudo grep 'request_id=initial-001' /opt/labex-ticket-regression/requests.log
cat logging.conf
include_authorization = true 解释了敏感字段为何出现。事件时间、请求 ID、版本和状态将观察到的行为与生效配置联系起来。保留原始日志;抹去它会移除证据,而不能防止未来泄漏。
停止新事件中的敏感字段记录
在本步骤中,你将修改日志策略,同时保留有用的审计字段。
nano logging.conf
使用:
[logging]
include_authorization = false
使用 Ctrl+O、Enter、Ctrl+X 保存并退出。通过预置重启入口应用保存的配置:
bash restart.sh
为新的健康检查请求指定已知 ID。X-Request-ID 是用于关联新事件的请求头:
curl -H 'X-Request-ID: after-policy-fix' http://127.0.0.1:8080/health
sudo grep 'request_id=after-policy-fix' /opt/labex-ticket-regression/requests.log
预期包含时间、版本、ID、路径和 status=200,但没有 Authorization 字段。旧的 initial-001 事件仍然存在。应根据各自 ID 判断新事件,而不是要求所有历史行都不含机密信息。
撤销并替换已泄漏凭据
在本步骤中,你将使用已学过的签发工具流程,撤销旧令牌的访问能力。
修改日志策略不会让已泄漏值失效。撤销其管理 ID:
course-token revoke legacy
curl -i -H 'Authorization: Bearer labex_012345abcdefghijklmnopqrstuvwxyz' http://127.0.0.1:8080/tickets
预期返回 401。现在签发新凭据,但不打印其值:
course-token issue /srv/ticket-regression/api.token
使用权限和令牌实验中的管理员/客户端组模式保护它:
sudo chown root:deskclient api.token
sudo chmod 640 api.token
凭据值由签发工具创建;你只设置访问权限。不要将它复制到测试源码、客户端脚本或书面报告中。
恢复从文件读取凭据的客户端
在本步骤中,你将让现有客户端使用受保护的新凭据。
nano sender.sh
保存前面介绍过的相同文件读取形式:
#!/bin/bash
exec sudo -u deskclient /usr/bin/python3 /opt/labex-ticket-regression/send.py --token-file /srv/ticket-regression/api.token
使用 Ctrl+O、Enter、Ctrl+X。
bash sender.sh
预期显示 HTTP 200 和原始的 Printer offline 工单。读取最近的运行事件:
sudo tail -n 5 /opt/labex-ticket-regression/requests.log
新的成功请求保留审计字段,但不含凭据值。旧泄漏值可以留在保留的事件历史中,同时其访问能力已被撤销。区分二者,既避免删除证据,也避免把旧泄漏误当作仍能成功认证的访问路径。
理解现有测试为何漏掉泄漏
在本步骤中,你将在添加新要求前检查小型测试模板。
cat test_security.py
正向测试使用测试编写实验中的请求模板。预置 api 辅助模块从目标凭据来源提供 token,并返回真实 HTTP 状态、响应体,以及该请求的实际日志事件。"Bearer " + token 将两个字符串连接为请求头值;凭据值不会被复制到源码中。
两个独立对照使用公开虚构测试令牌:good 省略敏感日志字段,而 logging-regression 故意记录测试令牌。它们不会使用或暴露你新的运行凭据。
course-regression-tests good
course-regression-tests logging-regression
目前二者都通过 test_valid_token:两种实现的状态和业务数据都仍然正确。缺失的要求涉及 response["log"] 中的真实事件。辅助模块的每次请求都使用唯一 ID,因此返回的日志属于该次新请求,而非无关历史事件。
添加真实日志脱敏断言
在本步骤中,你将为新事件同时添加内容必须缺失和必须存在的测试要求。
Python 的 in 检查一个字符串是否出现在另一个字符串中。not in 要求其不存在。这些断言针对实际返回的日志文本,而非手动提供的证据文件。
nano test_security.py
保留正向测试,并使用以下完整文件:
from api import request, token
def test_valid_token():
response = request("/tickets", {"Authorization": "Bearer " + token})
assert response["status"] == 200
assert response["body"] == {"tickets": [{"id": 1, "title": "Printer offline"}]}
def test_log_is_redacted():
response = request("/tickets", {"Authorization": "Bearer " + token})
assert response["status"] == 200
assert "Authorization" not in response["log"]
assert token not in response["log"]
assert "request_id=" in response["log"]
assert "path=/tickets" in response["log"]
assert "status=200" in response["log"]
使用 Ctrl+O、Enter、Ctrl+X 保存并退出。新测试拒绝敏感字段和凭据值,同时要求请求 ID、业务路径和成功状态存在。清空日志会无法满足这些正向要求。
辅助模块在内部提供目标专用令牌。正常服务测试读取受保护的新凭据;对照实现使用公开虚构测试值。两个值都不应出现在此测试文件中。
证实测试能检测已知回归
在本步骤中,你将针对安全行为和故意泄漏的行为验证新断言。
course-regression-tests good
预期两个测试都通过。
course-regression-tests logging-regression
预期只有 test_log_is_redacted 以 AssertionError 失败,退出状态为 1。这是有意的检测,不意味着应弱化断言。正向业务测试必须继续通过。
course-regression-tests live
两个测试都应在实际修复后的服务上通过。这些测试仅检查各自的新请求事件;原始泄漏历史事件被有意保留。语法错误、连接错误或无条件失败都不能证明脱敏测试覆盖有效。
将新测试接入候选版本交付
在本步骤中,你将阻止未来候选版本在新断言失败时被交付。
预置关卡使用与前面关卡实验相同的检查/构建/测试/部署结构。build.sh 打包原始服务器和当前日志策略,然后在独立本地端口启动这个实际候选版本。现有 test.sh 检查其有效/缺失/错误令牌行为,但不检查日志。
nano gate.sh
在构建后、现有功能测试前添加回归调用。使用:
#!/bin/bash
bash checks.sh
status=$?
if [ "$status" -eq 1 ]; then
exit 1
fi
if [ "$status" -ne 0 ]; then
exit 2
fi
bash build.sh || exit 2
bash regression.sh candidate || exit 2
bash test.sh || exit 2
bash deploy.sh
使用 Ctrl+O、Enter、Ctrl+X 保存并退出。candidate 选择刚构建的实际应用,因此新增断言保护的是即将部署的产物。|| exit 2 会在其测试失败时停止交付。
bash gate.sh
预期完成凭据预检、实际候选版本构建、新回归测试通过、功能测试通过,以及将该候选版本部署到本地运行端口。仅保留未被使用的测试文件无法提供这种预防能力。
确认新事件和保留的历史
在本步骤中,你将验证交付后的行为,并思考证据,无需编写报告文件。
bash sender.sh
sudo tail -n 5 /opt/labex-ticket-regression/requests.log
新的运行事件必须保留时间、实际交付版本、请求 ID、路径和状态,且不含凭据。交付版本现在是产物哈希,而非原始 logging-v2 标签。
sudo grep 'request_id=initial-001' /opt/labex-ticket-regression/requests.log
原始事件记录仍然存在。其旧令牌已撤销;受保护的新凭据正常工作。独立的故意回归对照是教学比较对象,不是已部署服务。
请自行思考:哪个事件暴露了问题、哪个设置导致问题、为什么仅修复策略还不够,以及新候选版本断言如何防止再次发生。课程检查会测试一个确实发生回归的候选版本,确认关卡阻止它,并验证先前安全运行的产物保持正常。无需固定格式的调查文档。
总结
你将真实事件与其日志策略联系起来,停止新泄漏,撤销并替换已泄漏凭据,并保留历史证据。新断言能检测故意设置的回归,并在交付关卡内针对实际候选版本运行,从而在未来候选版本失败时保留安全的运行行为。



