#!/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))