Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 44 additions & 3 deletions agent/app/api/v2/ssh.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@ package v2

import (
"encoding/base64"
"net/http"
"net/url"
"os"
"strconv"

"github.com/1Panel-dev/1Panel/agent/app/api/v2/helper"
"github.com/1Panel-dev/1Panel/agent/app/dto"
Expand Down Expand Up @@ -201,7 +205,7 @@ func (b *BaseApi) DeleteRootCert(c *gin.Context) {
// @Summary Load host SSH logs
// @Accept json
// @Param request body dto.SearchSSHLog true "request"
// @Success 200 {object} dto.SSHLog
// @Success 200 {object} dto.PageResult
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /hosts/ssh/log [post]
Expand All @@ -211,12 +215,49 @@ func (b *BaseApi) LoadSSHLogs(c *gin.Context) {
return
}

data, err := sshService.LoadLog(c, req)
total, data, err := sshService.LoadLog(c, req)
if err != nil {
helper.InternalServer(c, err)
return
}
helper.SuccessWithData(c, data)

helper.SuccessWithData(c, dto.PageResult{
Total: total,
Items: data,
})
}

// @Tags SSH
// @Summary Export host SSH logs
// @Accept json
// @Param request body dto.SearchSSHLog true "request"
// @Success 200 {object} dto.PageResult
// @Security ApiKeyAuth
// @Security Timestamp
// @Router /hosts/ssh/log/export [post]
func (b *BaseApi) ExportSSHLogs(c *gin.Context) {
var req dto.SearchSSHLog
if err := helper.CheckBindAndValidate(&req, c); err != nil {
return
}
tmpFile, err := sshService.ExportLog(c, req)
if err != nil {
helper.InternalServer(c, err)
return
}
file, err := os.Open(tmpFile)
if err != nil {
helper.InternalServer(c, err)
return
}
defer func() {
_ = file.Close()
_ = os.RemoveAll(tmpFile)
}()
info, _ := file.Stat()
c.Header("Content-Length", strconv.FormatInt(info.Size(), 10))
c.Header("Content-Disposition", "attachment; filename*=utf-8''"+url.PathEscape(info.Name()))
http.ServeContent(c.Writer, c.Request, info.Name(), info.ModTime(), file)
}

// @Tags SSH
Expand Down
6 changes: 0 additions & 6 deletions agent/app/dto/ssh.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,12 +54,6 @@ type SearchSSHLog struct {
Info string `json:"info"`
Status string `json:"Status" validate:"required,oneof=Success Failed All"`
}
type SSHLog struct {
Logs []SSHHistory `json:"logs"`
TotalCount int `json:"totalCount"`
SuccessfulCount int `json:"successfulCount"`
FailedCount int `json:"failedCount"`
}

type SSHHistory struct {
Date time.Time `json:"date"`
Expand Down
53 changes: 40 additions & 13 deletions agent/app/service/ssh.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
"time"

"github.com/1Panel-dev/1Panel/agent/utils/copier"
csvexport "github.com/1Panel-dev/1Panel/agent/utils/csv_export"
"github.com/1Panel-dev/1Panel/agent/utils/encrypt"
"github.com/1Panel-dev/1Panel/agent/utils/geo"
"github.com/gin-gonic/gin"
Expand All @@ -38,9 +39,11 @@ type ISSHService interface {
OperateSSH(operation string) error
UpdateByFile(value string) error
Update(req dto.SSHUpdate) error
LoadLog(ctx *gin.Context, req dto.SearchSSHLog) (*dto.SSHLog, error)
LoadSSHConf() (string, error)

LoadLog(ctx *gin.Context, req dto.SearchSSHLog) (int64, []dto.SSHHistory, error)
ExportLog(ctx *gin.Context, req dto.SearchSSHLog) (string, error)

SyncRootCert() error
CreateRootCert(req dto.CreateRootCert) error
SearchRootCerts(req dto.SearchWithPage) (int64, interface{}, error)
Expand Down Expand Up @@ -392,13 +395,13 @@ type sshFileItem struct {
Year int
}

func (u *SSHService) LoadLog(ctx *gin.Context, req dto.SearchSSHLog) (*dto.SSHLog, error) {
func (u *SSHService) LoadLog(ctx *gin.Context, req dto.SearchSSHLog) (int64, []dto.SSHHistory, error) {
var fileList []sshFileItem
var data dto.SSHLog
var data []dto.SSHHistory
baseDir := "/var/log"
fileItems, err := os.ReadDir(baseDir)
if err != nil {
return &data, err
return 0, data, err
}
for _, item := range fileItems {
if item.IsDir() || (!strings.HasPrefix(item.Name(), "secure") && !strings.HasPrefix(item.Name(), "auth")) {
Expand Down Expand Up @@ -427,6 +430,7 @@ func (u *SSHService) LoadLog(ctx *gin.Context, req dto.SearchSSHLog) (*dto.SSHLo
showCountFrom := (req.Page - 1) * req.PageSize
showCountTo := req.Page * req.PageSize
nyc, _ := time.LoadLocation(common.LoadTimeZoneByCmd())
itemFailed, itemTotal := 0, 0
for _, file := range fileList {
commandItem := ""
if strings.HasPrefix(path.Base(file.Name), "secure") {
Expand All @@ -450,15 +454,38 @@ func (u *SSHService) LoadLog(ctx *gin.Context, req dto.SearchSSHLog) (*dto.SSHLo
}
}
dataItem, successCount, failedCount := loadSSHData(ctx, commandItem, showCountFrom, showCountTo, file.Year, nyc)
data.FailedCount += failedCount
data.TotalCount += successCount + failedCount
itemFailed += failedCount
itemTotal += successCount + failedCount
showCountFrom = showCountFrom - (successCount + failedCount)
showCountTo = showCountTo - (successCount + failedCount)
data.Logs = append(data.Logs, dataItem...)
if showCountTo != -1 {
showCountTo = showCountTo - (successCount + failedCount)
}
data = append(data, dataItem...)
}

data.SuccessfulCount = data.TotalCount - data.FailedCount
return &data, nil
total := itemTotal
if req.Status == constant.StatusFailed {
total = itemFailed
}
if req.Status == constant.StatusSuccess {
total = itemTotal - itemFailed
}
return int64(total), data, nil
}

func (u *SSHService) ExportLog(ctx *gin.Context, req dto.SearchSSHLog) (string, error) {
_, logs, err := u.LoadLog(ctx, req)
if err != nil {
return "", err
}
tmpFileName := path.Join(global.Dir.TmpDir, "export/ssh-log", fmt.Sprintf("1panel-ssh-log-%s.csv", time.Now().Format(constant.DateTimeSlimLayout)))
if _, err := os.Stat(path.Dir(tmpFileName)); err != nil {
_ = os.MkdirAll(path.Dir(tmpFileName), constant.DirPerm)
}
if err := csvexport.ExportSSHLogs(tmpFileName, logs); err != nil {
return "", err
}
return tmpFileName, nil
}

func (u *SSHService) LoadSSHConf() (string, error) {
Expand Down Expand Up @@ -543,7 +570,7 @@ func loadSSHData(ctx *gin.Context, command string, showCountFrom, showCountTo, c
case strings.Contains(lines[i], "Failed password for"):
itemData = loadFailedSecureDatas(lines[i])
if checkIsStandard(itemData) {
if successCount+failedCount >= showCountFrom && successCount+failedCount < showCountTo {
if successCount+failedCount >= showCountFrom && (showCountTo == -1 || successCount+failedCount < showCountTo) {
itemData.Area, _ = geo.GetIPLocation(getLoc, itemData.Address, common.GetLang(ctx))
itemData.Date = loadDate(currentYear, itemData.DateStr, nyc)
datas = append(datas, itemData)
Expand All @@ -553,7 +580,7 @@ func loadSSHData(ctx *gin.Context, command string, showCountFrom, showCountTo, c
case strings.Contains(lines[i], "Connection closed by authenticating user"):
itemData = loadFailedAuthDatas(lines[i])
if checkIsStandard(itemData) {
if successCount+failedCount >= showCountFrom && successCount+failedCount < showCountTo {
if successCount+failedCount >= showCountFrom && (showCountTo == -1 || successCount+failedCount < showCountTo) {
itemData.Area, _ = geo.GetIPLocation(getLoc, itemData.Address, common.GetLang(ctx))
itemData.Date = loadDate(currentYear, itemData.DateStr, nyc)
datas = append(datas, itemData)
Expand All @@ -563,7 +590,7 @@ func loadSSHData(ctx *gin.Context, command string, showCountFrom, showCountTo, c
case strings.Contains(lines[i], "Accepted "):
itemData = loadSuccessDatas(lines[i])
if checkIsStandard(itemData) {
if successCount+failedCount >= showCountFrom && successCount+failedCount < showCountTo {
if successCount+failedCount >= showCountFrom && (showCountTo == -1 || successCount+failedCount < showCountTo) {
itemData.Area, _ = geo.GetIPLocation(getLoc, itemData.Address, common.GetLang(ctx))
itemData.Date = loadDate(currentYear, itemData.DateStr, nyc)
datas = append(datas, itemData)
Expand Down
1 change: 1 addition & 0 deletions agent/router/ro_host.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ func (s *HostRouter) InitRouter(Router *gin.RouterGroup) {
hostRouter.POST("/ssh/search", baseApi.GetSSHInfo)
hostRouter.POST("/ssh/update", baseApi.UpdateSSH)
hostRouter.POST("/ssh/log", baseApi.LoadSSHLogs)
hostRouter.POST("/ssh/log/export", baseApi.ExportSSHLogs)
hostRouter.POST("/ssh/conffile/update", baseApi.UpdateSSHByfile)
hostRouter.POST("/ssh/operate", baseApi.OperateSSH)

Expand Down
41 changes: 41 additions & 0 deletions agent/utils/csv_export/ssh_log.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package csvexport

import (
"encoding/csv"
"os"

"github.com/1Panel-dev/1Panel/agent/app/dto"
"github.com/1Panel-dev/1Panel/agent/constant"
)

func ExportSSHLogs(filename string, logs []dto.SSHHistory) error {
file, err := os.Create(filename)
if err != nil {
return err
}
defer file.Close()

writer := csv.NewWriter(file)
defer writer.Flush()

if err := writer.Write([]string{"IP", "Area", "Port", "AuthMode", "User", "Status", "Date"}); err != nil {
return err
}

for _, log := range logs {
record := []string{
log.Address,
log.Area,
log.Port,
log.AuthMode,
log.User,
log.Status,
log.Date.Format(constant.DateTimeLayout),
}
if err := writer.Write(record); err != nil {
return err
}
}

return nil
}
18 changes: 0 additions & 18 deletions frontend/src/api/interface/host.ts
Original file line number Diff line number Diff line change
Expand Up @@ -194,24 +194,6 @@ export namespace Host {
export interface analysisSSHLog extends ReqPage {
orderBy: string;
}
export interface logAnalysisRes {
total: number;
items: Array<logAnalysis>;
successfulCount: number;
failedCount: number;
}
export interface sshLog {
logs: Array<sshHistory>;
successfulCount: number;
failedCount: number;
}
export interface logAnalysis {
address: string;
area: string;
successfulCount: number;
failedCount: number;
status: string;
}
export interface sshHistory {
date: Date;
area: string;
Expand Down
8 changes: 7 additions & 1 deletion frontend/src/api/modules/host.ts
Original file line number Diff line number Diff line change
Expand Up @@ -96,5 +96,11 @@ export const syncCert = () => {
return http.post(`/hosts/ssh/cert/sync`);
};
export const loadSSHLogs = (params: Host.searchSSHLog) => {
return http.post<Host.sshLog>(`/hosts/ssh/log`, params);
return http.post<ResPage<Host.sshHistory>>(`/hosts/ssh/log`, params);
};
export const exportSSHLogs = (params: Host.searchSSHLog) => {
return http.download<BlobPart>('/hosts/ssh/log/export', params, {
responseType: 'blob',
timeout: TimeoutEnum.T_40S,
});
};
Loading
Loading