fix(security): retire default-credential surface (yanxue-20260914-cma-defaultcred-code-fix)

- Login.vue: no prefilled default creds; no anonymous entity enumeration on mount

- deploy.sh: readiness polling (0.5s/30s cap) replaces fixed sleep 3; login smoke reads same-source 600 secret file, missing file = explicit abort

- 19 verify/check/gen_report scripts: shared _admin_creds() loader (CMA_ADMIN_ENV -> ops .secrets -> profile copy); no hardcoded creds

- tests: single TEST_USER_PASSWORD fixture constant; docs: pointer to 600 secret file; removed 4 legacy .bak + pycache residue
This commit is contained in:
Hermes CI Fix
2026-09-14 17:39:53 +08:00
parent 8adc783501
commit 40d522cd34
39 changed files with 602 additions and 71 deletions
@@ -26,6 +26,32 @@ import urllib.request
import pymysql
# 2026-09-14 凭据面收口(cma-defaultcred-code-fix):原快照里的硬编码默认账号/口令改为同源加载,
# 快照的期/阈值断言一字未动(历史原文仍在 git 历史里)。
# ---- 管理员凭据同源加载(2026-09-14 cma-defaultcred-code-fix)----
# 生产凭据只存 600 密钥文件;禁止在脚本/文档/日志里硬编码口令。
# 顺序:$CMA_ADMIN_ENV → wecom-ops 主副本(ops 轮换落点,权威) → 本 profile 副本。
def _admin_creds():
"""返回 (user, password, 来源文件);未找到 → 显式报错退出(不静默退回默认口令)"""
for p in (os.environ.get("CMA_ADMIN_ENV"),
"/root/.hermes/profiles/wecom-ops/.secrets/cma-admin.env",
"/root/.hermes/profiles/wecom-fullstack/.secrets/cma-admin.env"):
if p and os.path.isfile(p):
kv = {}
for line in open(p, encoding="utf-8"):
line = line.strip()
if "=" in line and not line.startswith("#"):
k, v = line.split("=", 1)
kv[k.strip()] = v.strip().strip('"').strip("'")
if kv.get("CMA_ADMIN_USER") and kv.get("CMA_ADMIN_PASS"):
return kv["CMA_ADMIN_USER"], kv["CMA_ADMIN_PASS"], p
raise SystemExit("[错误] 未找到 CMA 管理员凭据:请设 $CMA_ADMIN_ENV,或准备 600 权限密钥文件 "
".secrets/cma-admin.env(键名 CMA_ADMIN_USER / CMA_ADMIN_PASS)")
ADMIN_USER, ADMIN_PASS, CRED_SRC = _admin_creds()
print(f"[creds] 来源={CRED_SRC} 账号={ADMIN_USER}(口令不回显)")
if os.environ.get("FORCE_SNAPSHOT") != "1":
print("⛔ 这是 20260908 的历史验收快照,不是活检查;复跑结果不代表当前回归。")
print(" 现行活检查:python3 backend/scripts/verify_bep_threshold_fix.py")
@@ -120,7 +146,7 @@ check("576 GAP red pending", alerts.get(576) == ("red", "pending"), str(alerts.g
check("577 COVER_CASH yellow pending", alerts.get(577) == ("yellow", "pending"), str(alerts.get(577)))
print("== 5. bep-card 端点 ==")
login = http_json("/api/cma/auth/login", "POST", {"username": "admin", "password": "admin123", "entity_id": 1})
login = http_json("/api/cma/auth/login", "POST", {"username": ADMIN_USER, "password": ADMIN_PASS, "entity_id": 1})
card = http_json("/api/cma/dashboard/bep-card", token=login["token"])
check("available", card.get("available") is True)
check("book red", card["book"]["cover_level"] == "red", str(card["book"]))