不可变设计:为健康 SaaS 构建防篡改审计日志
Source: Dev.to
说实话:没有人早上醒来会对构建审计日志系统感到兴奋。我们宁愿发布新功能、优化 React 渲染,或者说,直接睡懒觉。
但如果你在 HealthTech 工作,你就懂得其中的套路。HIPAA、GDPR、SOC2……它们不仅仅是缩写;它们是你业务的守门人。
老派的“日志”方式是什么?把 JSON 转储到文本文件或 S3 桶。问题是什么?rm -rf /var/logs。更糟的是:流氓管理员情景——如果拥有 root 权限的数据库管理员执行 UPDATE 命令来掩盖痕迹会怎样?如果你的审计日志只是普通的 SQL 表,你就无法向审计员证明历史记录没有被改写。
问题:可变数据库
在标准的 Postgres 或 MySQL 环境中,数据天生是可变的。这是一项特性,而非缺陷。但在受监管环境中的审计追踪里,可变性就是敌人。
UPDATE audit_logs
SET action = 'authorized_access'
WHERE user_id = 'rogue_admin' AND action = 'access_denied';
实际上几乎没有证据表明历史被更改。审计员会问:“这条记录准确吗?”而你回答:“我想是吧?”这在医疗行业是行不通的。
策略 1:加密链(“DIY 区块链”)
如果你还没有准备好采用专用数据库,也可以在 SQL 数据库中实现一个“链”。这基本上就是区块链的工作原理,只是中心化的。
架构
CREATE TABLE strict_audit_log (
id SERIAL PRIMARY KEY,
user_id INT NOT NULL,
action VARCHAR(255),
payload JSONB,
prev_hash VARCHAR(64), -- The hash of the previous row
curr_hash VARCHAR(64), -- The hash of this row (including prev_hash!)
created_at TIMESTAMP DEFAULT NOW()
);
逻辑
async function logAction(user, action, payload) {
// 1. Get the last record
const lastLog = await db.query(
'SELECT curr_hash FROM strict_audit_log ORDER BY id DESC LIMIT 1'
);
const prevHash = lastLog ? lastLog.curr_hash : '0000000000'; // Genesis block style
// 2. Create the hash for the new record
// We use SHA-256 here. Ensure your serialization is deterministic!
const dataString = `${user.id}${action}${JSON.stringify(payload)}${prevHash}`;
const currHash = crypto.createHash('sha256')
.update(dataString)
.digest('hex');
// 3. Insert
await db.query(
`INSERT INTO strict_audit_log (user_id, action, payload, prev_hash, curr_hash)
VALUES ($1, $2, $3, $4, $5)`,
[user.id, action, payload, prevHash, currHash]
);
}
为什么可行: 如果恶意管理员在表中间(例如 ID 500)修改了一行,ID 500 的哈希会改变。由于 ID 501 保存的是原始的 ID 500 哈希,链条就会断裂。你可以运行一个夜间脚本遍历整条链来验证完整性。
小提示: 这会引入序列化瓶颈(写入无法并行),但对于审计日志来说通常是可以接受的。
我在个人博客 wellally.tech 上写了更多关于这些后端模式的内容。
策略 2:专用账本数据库(QLDB)
如果 DIY 方法感觉维护工作太多(而且处理哈希竞争条件很烦人),可以考虑 账本数据库。Amazon QLDB(Quantum Ledger Database)是此领域的佼佼者。它为您执行加密链式操作,并提供透明、不可变且可验证的事务日志。
它如何改变您的架构
不再向 Postgres 表写入,而是使用 PartiQL(类似 SQL 的语法)将关键审计事件发送到 QLDB。
-- PartiQL looks familiar
INSERT INTO AuditTrail
VALUE {
'userId': '12345',
'action': 'VIEW_PATIENT_RECORDS',
'timestamp': '2025-10-22T10:00:00Z'
}
魔法在于 Digest。您可以在某个时间点下载数据库的加密签名。如果审计员在几个月后进行审计,您可以使用该摘要数学证明公司中没有人——甚至包括 CTO——篡改了数据。
您应该选择哪一个?
- 初创公司 / MVP: 从 SQL 链接 方法(Strategy 1)开始。它保持您的技术栈简洁(无需管理新基础设施),并让您领先于仍在将日志写入文本文件的大多数竞争对手。
- 企业 / 高合规性: 如果您正在与医院签署 BAA(业务关联协议),请考虑 QLDB 或 Oracle/Azure SQL 中的不可变表。可验证的特性在审计期间可节省大量时间。
Conclusion
合规性常被视为负担,但在健康科技领域,它是信任的特性。能够直视客户并说:“即使是我也无法更改这些数据”,是一种强大的销售工具。
无论是自行构建哈希链还是启动 Ledger 数据库,目标都是相同的:设计即不可变。