fix: --encrypt/--license 构建链修复(网关收集项、[license] 注入点、契约测试)
- config.toml:--encrypt 会先 PyArmor 混淆 main.py / server.py,PyInstaller 静态 分析跟不到里面的 `from chongming.app import app`,网关包整个漏收(打包"成功"、 产物启动即报 No module named 'chongming')—— 收集清单显式列出 chongming / chongming.app 等入口包,注释也从"静态分析可跟到"改准; - public/config.toml:补 [license] 段(public_key 留空),--license 的注入点, 缺了会在 prepare 阶段报"未找到 [license] 段的 public_key"; - README:补 --license 的公钥前置条件(keygen → license_public.key 或环境变量); - test_build_flags.py:4 条契约守卫 —— 真实模板/骨架可注入 [license]、收集清单含 网关入口包、加密包密钥写进包内且按运行端口径(get_key())可导入。此前用例都 自造 config.toml,这两类模板漂移测不出来。 实测(device-hub):修复前 --encrypt --license 产物启动报错;修复后网关启动、 授权校验通过、插件从加密 mbank 正常加载、HTTP 正常返回。
This commit is contained in:
@@ -20,6 +20,7 @@ import os
|
||||
import shutil
|
||||
import sys
|
||||
import tempfile
|
||||
import tomllib
|
||||
from pathlib import Path
|
||||
|
||||
SRC = Path(__file__).parent
|
||||
@@ -158,10 +159,59 @@ mod, err = import_from_bank(encrypted_bank, "demo", key=encrypted_bank.with_suff
|
||||
check("加密包用 .key 里的密钥可导入", mod is not None, str(err))
|
||||
|
||||
mod, err = import_from_bank(encrypted_bank, "demo", key=None)
|
||||
check("加密包缺密钥无法导入(说明 .key 必须随包提供给加载端)", mod is None and isinstance(err, ImportError), str(err))
|
||||
check("加密包不主动取密钥无法导入(install_importer 不会自己读包内密钥)",
|
||||
mod is None and isinstance(err, ImportError), str(err))
|
||||
|
||||
# 运行端取密钥的口径:public/utils/launch.py 的 init_module_bank 用 packer.get_key()
|
||||
# 从**包内**取(它不读旁挂 .key 文件)。打包时没写进包内,加密产物启动就是
|
||||
# "模块 'plugins' 的字节码是加密的,但没有提供解密密钥" —— 插件全加载失败、
|
||||
# 契约校验不过,网关直接起不来(实测踩过)
|
||||
embedded = b.PythonToSQLite(str(encrypted_bank)).get_key()
|
||||
check("加密包把密钥写进包内(运行端 get_key() 取得到)", embedded == key, f"embedded={embedded!r}")
|
||||
|
||||
mod, err = import_from_bank(encrypted_bank, "demo", key=embedded)
|
||||
check("加密包按运行端口径(get_key() 取出的密钥)可导入", mod is not None, str(err))
|
||||
|
||||
|
||||
# ========== 3. 授权构建:烘焙标记 / 公钥注入 ==========
|
||||
# 3.0 先验真实模板/骨架的构建契约:下面的用例(含 make_project)都自造 config.toml,
|
||||
# 所以"模板漏了 [license] 段 / 漏了网关收集项"这类漂移测不出来 —— 而两种漏法都不好在
|
||||
# 构建期发现(前者首报是"缺少厂商授权公钥",要补完公钥才暴露"未找到 [license] 段的
|
||||
# public_key";后者更隐蔽:打包"成功",产物启动才报 No module named 'chongming')。
|
||||
# 两处契约都在模板(生成新项目用)与根骨架(本仓打包用)的配置里,一起验。
|
||||
GATEWAY_ENTRY_MODULES = ("chongming", "chongming.app") # --encrypt 时静态分析看不到
|
||||
for label, proj_root in (
|
||||
("模板", SRC.parent / "utils" / "template"),
|
||||
("根骨架", SRC.parent),
|
||||
):
|
||||
try:
|
||||
injected = b._set_license_pubkey(
|
||||
(proj_root / "public" / "config.toml").read_text(encoding="utf-8"), "TESTKEY"
|
||||
)
|
||||
check(
|
||||
f"{label} public/config.toml 可注入 [license] public_key",
|
||||
'public_key = "TESTKEY"' in injected,
|
||||
)
|
||||
except Exception as exc: # noqa: BLE001 - 缺段/缺键都算契约破坏
|
||||
check(f"{label} public/config.toml 可注入 [license] public_key", False, str(exc)[:60])
|
||||
|
||||
# 收集清单要给 --encrypt 兜底:PyArmor 混淆 main.py/server.py 后,打包器跟不到
|
||||
# 里面的 `from chongming.app import app`,网关入口包只能靠这里显式声明
|
||||
with open(proj_root / "config.toml", "rb") as f:
|
||||
pack_list = tomllib.load(f)["pyinstaller_build_import"]
|
||||
listed = (
|
||||
set(pack_list.get("base", []))
|
||||
| set(pack_list.get("linux", []))
|
||||
| set(pack_list.get("windows", []))
|
||||
)
|
||||
missing = [m for m in GATEWAY_ENTRY_MODULES if m not in listed]
|
||||
check(
|
||||
f"{label} config.toml 收集清单含网关入口包",
|
||||
not missing,
|
||||
f"缺 {missing}" if missing else "",
|
||||
)
|
||||
|
||||
|
||||
def make_project(root: Path) -> Path:
|
||||
"""造一个最小构建现场:public/{main.py,server.py,config.toml}"""
|
||||
(root / "public" / "utils").mkdir(parents=True)
|
||||
|
||||
Reference in New Issue
Block a user