"""#215(feat-arch-converge)接口对齐层,CHV 本地实现。 背景:#215 未合并,本基线里没有 cloud/timeouts.py、 cloud/gates.py、cloud/quota.py、cloud/sandbox_policy.py。 本模块绝不复制 #215 的文件,只把 CHV 真正能映射的 接口写成与 #215 相同的签名,#215 合并后替换为 import 即是机械的(见 docs/chv-architecture.md ADR-8)。 映射表(逐个核对过 #215 远程分支的真实函数,不是凭空编的): - gates.resolve_inside(base, rel):目录门,CHV 快照/磁盘 路径白名单正好需要它——本模块实现同语义并已在 hardening.validate_snapshot_url 里使用,#215 合并后 改为 from cloud.gates import resolve_inside 即可。 - sandbox_policy.tmpfs_isolated(executor_kind, path):CHV 客机 /tmp 落在客机磁盘上,不是宿主 tmpfs,故对 cloud-hypervisor 一律返回 (False, ...)——fail-closed, 绝不宣称隔离。未知执行器同样 fail-closed。 - timeouts.resolve_module_timeout / quota.decide:无映射。 前者是审批/队列超时(None=不过期、0=不过期),CHV 的 api/ready 超时是秒数且 0 无效,语义不同,硬套会 改行为;后者是按月美元配额,CHV 的配额是 VM 数/磁盘 GB/快照数,单位不同。两者在本模块里 deliberately 不提供,测试钉住“CHV 不 import 它们”。 本模块只依赖标准库,是叶子模块,不 import cloud.sandbox。 合并后替换清单(REPLACEMENT_POINTS,本轨从“接口形状” 推进到可机械执行的清单;#215 未合并前一律不 import cloud.gates / cloud.sandbox_policy / cloud.timeouts / cloud.quota,测试钉住这些模块在本基线里不存在): - R1 gates.resolve_inside:唯一生产调用方是 hardening._is_within(快照 URL 白名单)。合并后两步: ① hardening 改为 `from cloud.gates import resolve_inside`; ② 删本模块 resolve_inside。语义必须逐字一致,改完 重跑快照白名单测试(逃逸/符号链接/绝对路径三例)。 - R2 sandbox_policy.tmpfs_isolated:形状占位,当前无 生产调用方(只有测试)。合并后一步:删本模块 tmpfs_isolated;将来有调用方时直接 import #215 版, 不得再本地复刻。CHV 语义是“一律不隔离(fail-closed)”, 若 #215 版对 cloud-hypervisor 返回 True,替换即改行为, 必须先停下来核对,不得机械替换。 - R3 timeouts / quota:永不替换。#215 的 timeouts 是 审批/队列超时(None/0 = 不过期),quota 是按月美元 配额;CHV 的 api/ready 超时是秒数(0 无效)、配额是 VM 数/磁盘 GB/快照数,单位与语义都不同。清单里明写 “不替换”,防止合并时有人按名字硬套。 """ import os # 合并后替换清单:每项的 local/replacement/test 字段由测试 # 逐项核对(local 函数真实存在、#215 模块当前不存在、 # test 命名的测试类真实存在),清单本身不得漂移。 REPLACEMENT_POINTS = ( { "id": "R1", "upstream": "cloud.gates.resolve_inside", "local": "cloud.chv.compat215.resolve_inside", "caller": "cloud.chv.hardening._is_within", "replacement": "hardening 改为 from cloud.gates import " "resolve_inside,并删除本地 resolve_inside", "test": "Compat215Test + 快照白名单测试", }, { "id": "R2", "upstream": "cloud.sandbox_policy.tmpfs_isolated", "local": "cloud.chv.compat215.tmpfs_isolated", "caller": None, "replacement": "删除本地 tmpfs_isolated;有调用方时" "直接 import #215 版(先核对 CHV 一律 False 语义)", "test": "Compat215Test.test_tmpfs_isolated_chv_and_unknown_" "fail_closed", }, { "id": "R3", "upstream": "cloud.timeouts / cloud.quota", "local": None, "caller": None, "replacement": None, "test": "Compat215Test.test_no_timeout_or_quota_map", }, ) def resolve_inside(base: str, rel: str) -> str | None: """目录门:base 内的相对路径安全解析,越界回 None。 空串回 base 本身;绝对路径、.. 逃逸、符号链接逃逸、 commonpath 跨盘符 ValueError 一律 None。签名与 #215 的 gates.resolve_inside 一致,合并后可直接替换为 import。""" if not rel: return base if os.path.isabs(rel): return None real_base = os.path.realpath(base) target = os.path.realpath(os.path.join(real_base, rel)) try: if os.path.commonpath([real_base, target]) != real_base: return None except ValueError: return None return target def tmpfs_isolated(executor_kind: str, path: str) -> tuple[bool, str]: """某执行器下某路径是否走 tmpfs 隔离:(isolated, reason)。 cloud-hypervisor:客机 /tmp 落在客机磁盘上,不走宿主 tmpfs,一律 (False, ...);未知执行器 fail-closed 同样 False。签名与 #215 的 sandbox_policy.tmpfs_isolated 一致。""" if executor_kind == "cloud-hypervisor": return False, "CHV 客机 /tmp 落在客机磁盘上,不走宿主 tmpfs" return False, "未知执行器,按不隔离处理(fail-closed 口径)"