- 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
166 lines
5.8 KiB
Python
166 lines
5.8 KiB
Python
#!/usr/bin/env python3
|
||
"""管理会计OS数据详情检查"""
|
||
import json, urllib.request
|
||
|
||
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 = "http://127.0.0.1:8010"
|
||
|
||
def login():
|
||
data = json.dumps({"username":ADMIN_USER,"password":ADMIN_PASS}).encode()
|
||
req = urllib.request.Request(BASE + "/api/cma/auth/login", data=data,
|
||
headers={"Content-Type":"application/json"}, method="POST")
|
||
resp = json.loads(urllib.request.urlopen(req).read())
|
||
return resp["token"]
|
||
|
||
def api(path, token):
|
||
auth = "Bearer " + token
|
||
req = urllib.request.Request(BASE + path, headers={"Authorization": auth})
|
||
resp = json.loads(urllib.request.urlopen(req).read())
|
||
return resp
|
||
|
||
token = login()
|
||
|
||
# KPI详情
|
||
print("="*60)
|
||
print("KPI定义(前5条)")
|
||
print("="*60)
|
||
data = api("/api/cma/kpis", token)
|
||
for kpi in data.get("data", data)[:5]:
|
||
print(" [%s] %s" % (kpi.get("code","?"), kpi.get("name","?")))
|
||
print(" 维度:%s | 权重:%s | 单位:%s" % (
|
||
kpi.get("dimension","?"), kpi.get("weight","?"), kpi.get("unit","?")))
|
||
print(" 当前值:%s | 目标值:%s | 实际值:%s" % (
|
||
kpi.get("current_value","-"), kpi.get("target_value","-"), kpi.get("actual_value","-")))
|
||
if kpi.get("threshold_green"):
|
||
print(" 阈值: 绿<%s 黄<%s 红<%s" % (
|
||
kpi.get("threshold_green",""), kpi.get("threshold_yellow",""), kpi.get("threshold_red","")))
|
||
print()
|
||
|
||
# 用户
|
||
print("="*60)
|
||
print("用户列表")
|
||
print("="*60)
|
||
data = api("/api/cma/users", token)
|
||
if isinstance(data, dict):
|
||
# 可能是 {username: {...}} 格式
|
||
users = [data[k] for k in data if isinstance(data[k], dict)]
|
||
else:
|
||
users = data
|
||
for u in users:
|
||
print(" %-12s | %-15s | %-10s | role_code=%s" % (
|
||
u.get("username","?"), u.get("name","?"), u.get("role_name","?"), u.get("role","?")))
|
||
|
||
# 战略地图
|
||
print()
|
||
print("="*60)
|
||
print("战略地图")
|
||
print("="*60)
|
||
data = api("/api/cma/maps", token)
|
||
for m in data.get("data", data):
|
||
print(" [%s] %s - %s, 状态:%s" % (
|
||
m.get("id","?"), m.get("title","?"), m.get("period","?"), m.get("status","?")))
|
||
|
||
# 数据源
|
||
print()
|
||
print("="*60)
|
||
print("数据源配置")
|
||
print("="*60)
|
||
data = api("/api/cma/data/sources", token)
|
||
for s in data.get("data", data):
|
||
print(" %s - 类型:%s, API:%s" % (
|
||
s.get("name","?"), s.get("type","?"), s.get("api_endpoint","?")))
|
||
|
||
# 通知渠道
|
||
print()
|
||
print("="*60)
|
||
print("通知渠道")
|
||
print("="*60)
|
||
data = api("/api/cma/notifications/channels", token)
|
||
for c in data.get("data", data):
|
||
print(" %s - %s, 启用:%s" % (
|
||
c.get("name","?"), c.get("type","?"), c.get("enabled","?")))
|
||
|
||
# 预警规则
|
||
print()
|
||
print("="*60)
|
||
print("预警规则(前8条)")
|
||
print("="*60)
|
||
data = api("/api/cma/alert-rules", token)
|
||
rules = data.get("data", data)
|
||
print(" 共 %d 条规则" % len(rules))
|
||
for r in rules[:8]:
|
||
print(" %s - KPI:%s, 条件:%s %s" % (
|
||
r.get("name","?"), r.get("kpi_code","?"), r.get("condition","?"), r.get("threshold","?")))
|
||
|
||
# 预警记录
|
||
print()
|
||
print("="*60)
|
||
print("预警记录(前6条)")
|
||
print("="*60)
|
||
data = api("/api/cma/alerts", token)
|
||
for a in data.get("data", data)[:6]:
|
||
print(" [%s] %s" % (a.get("severity","?"), a.get("kpi_name","?")))
|
||
print(" 值:%s/%s 阈值:%s 状态:%s 处理人:%s" % (
|
||
a.get("current_value","?"), a.get("target_value","?"),
|
||
a.get("threshold","?"), a.get("status","?"), a.get("resolver","?")))
|
||
|
||
# 行动计划
|
||
print()
|
||
print("="*60)
|
||
print("行动计划")
|
||
print("="*60)
|
||
data = api("/api/cma/action-plans", token)
|
||
for p in data.get("data", data):
|
||
print(" %s - KPI:%s, 状态:%s, 负责人:%s" % (
|
||
p.get("title","?"), p.get("kpi_code","?"), p.get("status","?"), p.get("assignee","?")))
|
||
|
||
# Dashboard summary
|
||
print()
|
||
print("="*60)
|
||
print("Dashboard Summary")
|
||
print("="*60)
|
||
data = api("/api/cma/dashboard/summary", token)
|
||
print(" KPI总数:%s" % data.get("kpi_total"))
|
||
print(" 预警数:%s" % data.get("alert_count"))
|
||
ds = data.get("dimension_stats", {})
|
||
print(" 维度统计: %s" % json.dumps(ds, ensure_ascii=False))
|
||
|
||
# 权限
|
||
print()
|
||
print("="*60)
|
||
print("权限配置")
|
||
print("="*60)
|
||
data = api("/api/cma/permissions/config", token)
|
||
rp = data.get("route_permissions", {})
|
||
print(" 路由权限(每个角色模块数):")
|
||
for role, modules in rp.items():
|
||
print(" %-12s: %d 个模块" % (role, len(modules)))
|
||
ap = data.get("action_permissions", {})
|
||
print(" 操作权限:")
|
||
for role, actions in ap.items():
|
||
print(" %-12s: %s" % (role, actions))
|