feat: 完善日志审计功能
- 实现文件系统日志(FilesystemLog)记录文件管理器操作 - 实现操作日志(OperationLog)记录用户操作行为 - 实现数据库SQL日志(DatabaseSQLLog)模型和API - 实现SSH会话命令记录(SessionCommand)含命令输出和风险等级 - 添加IP提取服务支持X-Real-IP和X-Forwarded-For - 添加日志自动清理功能 - 修复ProFormSwitch required验证问题 - 修复设置页面默认值问题 - 修复文件上传错误检测逻辑 - 修复资产树key前缀问题 - 添加VNC/RDP设置默认值 - 修复文件管理标题翻译
This commit is contained in:
@@ -0,0 +1,47 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"next-terminal/server/common"
|
||||
"next-terminal/server/model"
|
||||
"next-terminal/server/repository"
|
||||
"next-terminal/server/utils"
|
||||
)
|
||||
|
||||
var DatabaseSQLLogService = new(databaseSQLLogService)
|
||||
|
||||
type databaseSQLLogService struct {
|
||||
baseService
|
||||
}
|
||||
|
||||
type DatabaseSQLLogParams struct {
|
||||
AssetId string
|
||||
Database string
|
||||
UserId string
|
||||
ClientIP string
|
||||
SQL string
|
||||
DurationMs int
|
||||
RowsAffected int
|
||||
Status string
|
||||
ErrorMessage string
|
||||
Source string
|
||||
}
|
||||
|
||||
func (s databaseSQLLogService) Record(ctx context.Context, params DatabaseSQLLogParams) error {
|
||||
log := &model.DatabaseSQLLog{
|
||||
ID: utils.UUID(),
|
||||
AssetId: params.AssetId,
|
||||
Database: params.Database,
|
||||
UserId: params.UserId,
|
||||
ClientIP: params.ClientIP,
|
||||
SQL: params.SQL,
|
||||
DurationMs: params.DurationMs,
|
||||
RowsAffected: params.RowsAffected,
|
||||
Status: params.Status,
|
||||
ErrorMessage: params.ErrorMessage,
|
||||
Source: params.Source,
|
||||
Created: common.NowJsonTime(),
|
||||
}
|
||||
return repository.DatabaseSQLLogRepository.Create(ctx, log)
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"next-terminal/server/common"
|
||||
"next-terminal/server/model"
|
||||
"next-terminal/server/repository"
|
||||
"next-terminal/server/utils"
|
||||
)
|
||||
|
||||
var OperationLogService = new(operationLogService)
|
||||
|
||||
type operationLogService struct {
|
||||
baseService
|
||||
}
|
||||
|
||||
type OperationLogParams struct {
|
||||
AccountId string
|
||||
AccountName string
|
||||
Action string
|
||||
Content string
|
||||
IP string
|
||||
Region string
|
||||
UserAgent string
|
||||
Status string
|
||||
ErrorMessage string
|
||||
Remark string
|
||||
}
|
||||
|
||||
func (s operationLogService) Record(ctx context.Context, params OperationLogParams) error {
|
||||
log := &model.OperationLog{
|
||||
ID: utils.UUID(),
|
||||
AccountId: params.AccountId,
|
||||
AccountName: params.AccountName,
|
||||
Action: params.Action,
|
||||
Content: params.Content,
|
||||
IP: params.IP,
|
||||
Region: params.Region,
|
||||
UserAgent: params.UserAgent,
|
||||
Status: params.Status,
|
||||
ErrorMessage: params.ErrorMessage,
|
||||
Remark: params.Remark,
|
||||
Created: common.NowJsonTime(),
|
||||
}
|
||||
return repository.OperationLogRepository.Create(ctx, log)
|
||||
}
|
||||
@@ -4,12 +4,15 @@ import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
"strings"
|
||||
|
||||
"next-terminal/server/common/guacamole"
|
||||
"next-terminal/server/env"
|
||||
"next-terminal/server/model"
|
||||
"next-terminal/server/repository"
|
||||
|
||||
"github.com/labstack/echo/v4"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
@@ -40,10 +43,19 @@ var defaultProperties = map[string]string{
|
||||
guacamole.EnableMenuAnimations: "true",
|
||||
guacamole.DisableBitmapCaching: "false",
|
||||
guacamole.DisableOffscreenCaching: "false",
|
||||
guacamole.ColorDepth: "",
|
||||
guacamole.Cursor: "",
|
||||
guacamole.SwapRedBlue: "false",
|
||||
"cron-log-saved-limit": "360",
|
||||
"login-log-saved-limit": "360",
|
||||
"session-saved-limit": "360",
|
||||
"access-log-saved-limit": "30",
|
||||
"filesystem-log-saved-limit": "30",
|
||||
"operation-log-saved-limit": "30",
|
||||
"database-sql-log-saved-limit": "30",
|
||||
"user-default-storage-size": "5120",
|
||||
"ip-extractor": "direct",
|
||||
"ip-trust-list": "",
|
||||
}
|
||||
|
||||
func (service propertyService) InitProperties() error {
|
||||
@@ -60,6 +72,9 @@ func (service propertyService) InitProperties() error {
|
||||
|
||||
func (service propertyService) CreateIfAbsent(propertyMap map[string]string, name, value string) error {
|
||||
if len(propertyMap[name]) == 0 {
|
||||
if value == "" {
|
||||
value = "-"
|
||||
}
|
||||
property := model.Property{
|
||||
Name: name,
|
||||
Value: value,
|
||||
@@ -117,3 +132,76 @@ func (service propertyService) Update(item map[string]interface{}) error {
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
func (service propertyService) GetClientIP(c echo.Context) string {
|
||||
propertyMap := repository.PropertyRepository.FindAllMap(context.TODO())
|
||||
extractor := propertyMap["ip-extractor"]
|
||||
trustList := propertyMap["ip-trust-list"]
|
||||
|
||||
directIP := c.RealIP()
|
||||
|
||||
if extractor == "" || extractor == "direct" {
|
||||
return directIP
|
||||
}
|
||||
|
||||
if !service.isTrustedIP(directIP, trustList) {
|
||||
return directIP
|
||||
}
|
||||
|
||||
switch extractor {
|
||||
case "x-real-ip":
|
||||
xRealIP := c.Request().Header.Get("X-Real-IP")
|
||||
if xRealIP != "" {
|
||||
return xRealIP
|
||||
}
|
||||
case "x-forwarded-for":
|
||||
xForwardedFor := c.Request().Header.Get("X-Forwarded-For")
|
||||
if xForwardedFor != "" {
|
||||
ips := strings.Split(xForwardedFor, ",")
|
||||
if len(ips) > 0 {
|
||||
ip := strings.TrimSpace(ips[0])
|
||||
if ip != "" {
|
||||
return ip
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return directIP
|
||||
}
|
||||
|
||||
func (service propertyService) isTrustedIP(clientIP string, trustList string) bool {
|
||||
if trustList == "" {
|
||||
return false
|
||||
}
|
||||
|
||||
trustIPs := strings.Split(trustList, ",")
|
||||
clientIPAddr := net.ParseIP(clientIP)
|
||||
if clientIPAddr == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
for _, trustIP := range trustIPs {
|
||||
trustIP = strings.TrimSpace(trustIP)
|
||||
if trustIP == "" {
|
||||
continue
|
||||
}
|
||||
|
||||
if strings.Contains(trustIP, "/") {
|
||||
_, ipNet, err := net.ParseCIDR(trustIP)
|
||||
if err == nil && ipNet.Contains(clientIPAddr) {
|
||||
return true
|
||||
}
|
||||
} else {
|
||||
if trustIP == clientIP {
|
||||
return true
|
||||
}
|
||||
trustIPAddr := net.ParseIP(trustIP)
|
||||
if trustIPAddr != nil && trustIPAddr.Equal(clientIPAddr) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user