linux

Linux Golang日志如何实现安全审计

小樊
42
2025-12-15 06:38:56
栏目: 编程语言

Linux Golang 日志安全审计落地方案

一 核心原则与采集范围

二 Go 代码落地示例

package main

import (
	"context"
	"fmt"
	"io"
	"net/http"
	"os"
	"strings"
	"time"

	"go.uber.org/zap"
	"go.uber.org/zap/zapcore"
)

// AuditEvent 审计事件模型(可按需扩展)
type AuditEvent struct {
	Timestamp time.Time              `json:"ts"`
	UserID    string                 `json:"uid,omitempty"`
	Username  string                 `json:"user,omitempty"`
	IP        string                 `json:"ip"`
	Method    string                 `json:"method"`
	Path      string                 `json:"path"`
	Status    int                    `json:"status"`
	UA        string                 `json:"ua,omitempty"`
	Err       string                 `json:"err,omitempty"`
	Latency   time.Duration          `json:"latency_ms"`
	Extra     map[string]interface{} `json:"extra,omitempty"`
}

var auditLogger *zap.Logger

func initLogger(logPath string) error {
	// 生产环境建议使用 JSON 编码
	encCfg := zap.NewProductionEncoderConfig()
	encCfg.TimeKey = "ts"
	encCfg.EncodeTime = zapcore.ISO8601TimeEncoder

	cfg := zap.NewProductionConfig()
	cfg.OutputPaths = []string{logPath}
	cfg.EncoderConfig = encCfg

	l, err := cfg.Build()
	if err != nil {
		return err
	}
	auditLogger = l.Named("audit")
	return nil
}

// Mask 对敏感字段做掩码
func Mask(s string) string {
	if len(s) <= 6 {
		return strings.Repeat("*", len(s))
	}
	return s[:3] + strings.Repeat("*", len(s)-6) + s[len(s)-3:]
}

// WriteAudit 写入审计事件
func WriteAudit(ctx context.Context, ev AuditEvent) {
	fields := []zap.Field{
		zap.Time("ts", ev.Timestamp),
		zap.String("uid", ev.UserID),
		zap.String("user", ev.Username),
		zap.String("ip", ev.IP),
		zap.String("method", ev.Method),
		zap.String("path", ev.Path),
		zap.Int("status", ev.Status),
		zap.String("ua", ev.UA),
		zap.Duration("latency_ms", ev.Latency),
	}
	if ev.Err != "" {
		fields = append(fields, zap.String("err", ev.Err))
	}
	if len(ev.Extra) > 0 {
		fields = append(fields, zap.Any("extra", ev.Extra))
	}
	auditLogger.Info("audit", fields...)
}

// AuditMiddleware HTTP 审计中间件
func AuditMiddleware(next http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		start := time.Now()
		ww := &responseWriter{ResponseWriter: w, status: http.StatusOK}
		defer func() {
			ev := AuditEvent{
				Timestamp: start,
				IP:        r.RemoteAddr,
				Method:    r.Method,
				Path:      r.URL.Path,
				Status:    ww.status,
				UA:        r.UserAgent(),
				Latency:   time.Since(start),
			}
			// 示例:从请求头或上下文获取用户(实际项目替换为你的鉴权逻辑)
			if uid := r.Header.Get("X-User-Id"); uid != "" {
				ev.UserID = uid
			}
			if user := r.Header.Get("X-User-Name"); user != "" {
				ev.Username = Mask(user) // 脱敏
			}
			WriteAudit(r.Context(), ev)
		}()
		next.ServeHTTP(ww, r)
	})
}

type responseWriter struct {
	http.ResponseWriter
	status int
}

func (rw *responseWriter) WriteHeader(code int) {
	rw.status = code
	rw.ResponseWriter.WriteHeader(code)
}

func main() {
	if err := initLogger("/var/log/myapp/audit.log"); err != nil {
		panic(err)
	}
	defer auditLogger.Sync() // 尽量确保落盘

	mux := http.NewServeMux()
	mux.HandleFunc("/login", func(w http.ResponseWriter, r *http.Request) {
		// 示例登录逻辑
		user := r.FormValue("user")
		pass := r.FormValue("pass")
		// 校验省略
		w.WriteHeader(http.StatusOK)
		fmt.Fprintf(w, "ok")
	})

	handler := AuditMiddleware(mux)
	http.ListenAndServe(":8080", handler)
}

三 Linux 侧安全与合规配置

四 集中化、监控与合规

0
看了该问题的人还看了