fix: 独立审计日志并补齐令牌身份与失败记录
This commit is contained in:
+81
-7
@@ -1,12 +1,86 @@
|
||||
package admin
|
||||
|
||||
import (
|
||||
"log/slog"
|
||||
"os"
|
||||
)
|
||||
|
||||
const importAuditIDCap = 20
|
||||
|
||||
func defaultAuditLogger() *slog.Logger {
|
||||
return slog.New(slog.NewJSONHandler(os.Stderr, &slog.HandlerOptions{Level: slog.LevelInfo}))
|
||||
}
|
||||
|
||||
type auditRec struct {
|
||||
Actor string
|
||||
TokenID string
|
||||
Action string
|
||||
Object string
|
||||
Result string
|
||||
IP string
|
||||
Detail any
|
||||
}
|
||||
|
||||
// audit 写结构化操作日志;不写密码、令牌和正文。
|
||||
func (h *Handler) audit(actor, action, object, result, ip string) {
|
||||
h.log.Info("admin_audit",
|
||||
"actor", actor,
|
||||
"action", action,
|
||||
"object", object,
|
||||
"result", result,
|
||||
"ip", ip,
|
||||
)
|
||||
h.auditRec(auditRec{Actor: actor, Action: action, Object: object, Result: result, IP: ip})
|
||||
}
|
||||
|
||||
func (h *Handler) auditP(p principal, action, object, result, ip string) {
|
||||
h.auditPD(p, action, object, result, ip, nil)
|
||||
}
|
||||
|
||||
func (h *Handler) auditPD(p principal, action, object, result, ip string, detail any) {
|
||||
rec := auditRec{
|
||||
Actor: actorString(p),
|
||||
Action: action,
|
||||
Object: object,
|
||||
Result: result,
|
||||
IP: ip,
|
||||
Detail: detail,
|
||||
}
|
||||
if p.Kind == authToken && p.TokenID != "" {
|
||||
rec.TokenID = p.TokenID
|
||||
}
|
||||
h.auditRec(rec)
|
||||
}
|
||||
|
||||
func (h *Handler) auditRec(rec auditRec) {
|
||||
args := []any{
|
||||
"actor", rec.Actor,
|
||||
"action", rec.Action,
|
||||
"object", rec.Object,
|
||||
"result", rec.Result,
|
||||
"ip", rec.IP,
|
||||
}
|
||||
if rec.TokenID != "" {
|
||||
args = append(args, "token_id", rec.TokenID)
|
||||
}
|
||||
if rec.Detail != nil {
|
||||
args = append(args, "detail", rec.Detail)
|
||||
}
|
||||
h.auditLog.Info("admin_audit", args...)
|
||||
}
|
||||
|
||||
func (h *Handler) auditAuthFail(ip, reason string) {
|
||||
h.auditLog.Info("admin_auth_fail", "ip", ip, "reason", reason)
|
||||
}
|
||||
|
||||
func batchAuditResult(okN, failN int) string {
|
||||
switch {
|
||||
case failN == 0:
|
||||
return "ok"
|
||||
case okN == 0:
|
||||
return "failed"
|
||||
default:
|
||||
return "partial"
|
||||
}
|
||||
}
|
||||
|
||||
func importAuditDetail(ids []string) map[string]any {
|
||||
shown := ids
|
||||
if len(ids) > importAuditIDCap {
|
||||
shown = ids[:importAuditIDCap]
|
||||
}
|
||||
return map[string]any{"ids": shown, "total": len(ids)}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user