"""Postgres 审计账本只追加护栏:唯一受控执行入口(A2,代码侧)。 本模块是 ``cloud/ledger.py`` 的 ``PG_GUARD_SQL`` 常量在 Postgres 上的唯一执行入口——二选一里选的是“显式运维命令”,不是迁移脚本: - 函数入口:``apply_pg_guard(conn)``,逐条执行且仅执行 ``PG_GUARD_SQL``(从常量引用,不另写、不复制、不拼接 SQL)。 入口本身不 commit:调用方在自己的事务边界提交(与 ``ledger.ensure_schema`` 的约定一致)。 - 命令入口:``python3 -m cloud.ledger_pg_guard``(``main``), 连接参数只走 ``CLOUD_DB_*`` 环境变量(经 ``cloud.db.PostgresDatabase``),不接受命令行密码参数。 受控含义(grep 可证,全仓库除本模块外无其它执行路径): - ``ledger.ensure_schema`` 在 PG 适配连接上跳过触发器建; ``cloud/db.py`` 的 POSTGRES_SCHEMA 只建 audit_ledger 表, 不建触发器;迁移脚本不执行本常量。 - 入口先验连接类型:不是 ``PgConnection``(按类名判定,与 ``ledger._is_pg_conn`` 同款)即拒绝执行,绝不把 PG 方言 SQL 发往 SQLite 连接。 - 无 PG 环境下入口不得 claim 已加固:``main`` 在 ``CLOUD_DB_BACKEND`` 不是 postgres/postgresql 时直接以 exit 2 拒绝(不连接、不执行、不打印“已应用”);``--dry-run`` 只打印将执行的常量语句,不连接、不执行。 诚实边界(A2 只做代码侧,真实 PG 验证待 B5): - 本机无真实 PG,``PG_GUARD_SQL`` 的语法与 UPDATE/DELETE 阻挡 均未在真实 PG 上验证;B5 环境到齐后须在真实 PG 上跑本命令 并实测 UPDATE/DELETE 被拒绝,之后才可认“已加固”。在此之前, 任何“PG 已加固”的表述都是冒充。 - 本模块不打印、不返回任何密码或密钥:输出只有语句计数与 DDL 常量本身。 只用标准库 + cloud.db / cloud.ledger,不引第三方。 """ import argparse import json import os import sys try: from cloud.db import PostgresDatabase from cloud.ledger import PG_GUARD_SQL except ImportError: # 直接以脚本方式从仓库根外运行时的回退。 sys.path.insert(0, os.path.dirname(os.path.dirname( os.path.abspath(__file__)))) from cloud.db import PostgresDatabase from cloud.ledger import PG_GUARD_SQL def apply_pg_guard(conn): """在给定 PG 适配连接上执行只追加护栏(唯一执行入口)。 conn 须是 PgConnection(按类名判定);其它连接一律拒绝, 绝不把 PG 方言发往 SQLite。按 PG_GUARD_SQL 原顺序逐条执行, 返回执行过的语句元组(即常量本身,供调用方/测试比对)。 不 commit:调用方提交。 """ if type(conn).__name__ != "PgConnection": raise TypeError( "apply_pg_guard requires a PgConnection, got %s; " "refusing to run Postgres guard SQL on a non-PG connection" % type(conn).__name__) for statement in PG_GUARD_SQL: conn.execute(statement) return tuple(PG_GUARD_SQL) def main(argv=None): """运维命令:``python3 -m cloud.ledger_pg_guard [--dry-run]``。 返回进程退出码:0 已应用(或 dry-run 展示完毕),1 执行失败, 2 用法/环境错误(非 PG 后端、非 PG 连接——一律不 claim 已应用)。 """ parser = argparse.ArgumentParser( description="Apply the audit_ledger append-only guard " "(PG_GUARD_SQL) to Postgres. Single controlled " "entry point; see module docstring.") parser.add_argument( "--dry-run", action="store_true", help="Print the statements that would run, without " "connecting or executing anything.") args = parser.parse_args(argv) if args.dry_run: print(json.dumps({"applied": False, "dry_run": True, "statements": list(PG_GUARD_SQL)}, ensure_ascii=False, indent=2)) return 0 backend = (os.environ.get("CLOUD_DB_BACKEND") or "").strip().lower() if backend not in ("postgres", "postgresql"): print("refused: CLOUD_DB_BACKEND is not postgres " "(got %r); nothing applied, nothing claimed" % backend, file=sys.stderr) return 2 try: conn = PostgresDatabase().connect() except Exception as exc: print("failed to connect to Postgres: %s" % exc, file=sys.stderr) return 1 try: if type(conn).__name__ != "PgConnection": print("refused: connection is not a PgConnection " "(got %s); nothing applied" % type(conn).__name__, file=sys.stderr) return 2 statements = apply_pg_guard(conn) conn.commit() except Exception as exc: try: conn.rollback() except Exception: pass print("failed to apply PG guard: %s" % exc, file=sys.stderr) return 1 finally: try: conn.close() except Exception: pass print(json.dumps({"applied": True, "dry_run": False, "statements": list(statements)}, ensure_ascii=False, indent=2)) return 0 if __name__ == "__main__": raise SystemExit(main())