The hash chain (each entry contains the hash of the previous one) shows whether someone modified or deleted an entry.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | # ====================================================================== # Q: Write an audit log that cannot easily be tampered with. # # The hash chain (each entry contains the hash of the previous one) shows # whether someone modified or deleted an entry. For strict compliance, keep a # copy in WORM storage (e.g. S3 Object Lock). Entries are written from a single # place, in order, so the chain does not break. # ====================================================================== class AuditLog(Base): __tablename__ = 'audit_log' id: Mapped[int] = mapped_column(BigInteger, primary_key=True) at: Mapped[datetime] = mapped_column(server_default=func.now()) tenant_id: Mapped[int] actor_id: Mapped[int | None] action: Mapped[str] # 'reports:export' target: Mapped[str] # 'report:123' ip: Mapped[str | None] details: Mapped[dict] = mapped_column(JSONB, default=dict) prev_hash: Mapped[str] hash: Mapped[str] # sha256(prev_hash + entry) -- In the database: the application can only write REVOKE UPDATE, DELETE ON audit_log FROM app_user; |