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:
@@ -3,6 +3,31 @@
|
||||
"""2026-09-07 预算版本管理UI修复 - 生产API验证"""
|
||||
import json, urllib.request, ssl, sys
|
||||
|
||||
import os # noqa: E402 (凭据加载器需要)
|
||||
# ---- 管理员凭据同源加载(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}(口令不回显)")
|
||||
|
||||
BASE = "https://cma.sxbh.ltd/api/cma"
|
||||
|
||||
def http(url, data=None, headers=None, method=None):
|
||||
@@ -14,7 +39,7 @@ def http(url, data=None, headers=None, method=None):
|
||||
return json.loads(r.read().decode())
|
||||
|
||||
def login(entity_id):
|
||||
body = json.dumps({"username": "admin", "password": "admin123", "entity_id": entity_id}).encode()
|
||||
body = json.dumps({"username": ADMIN_USER, "password": ADMIN_PASS, "entity_id": entity_id}).encode()
|
||||
r = http(BASE + "/auth/login", data=body, headers={"Content-Type": "application/json"}, method="POST")
|
||||
return r["token"]
|
||||
|
||||
|
||||
Reference in New Issue
Block a user