Commit c5f287bb authored by Eric's avatar Eric

[Update] add ftp audit log

parent 2c841304
...@@ -3,6 +3,7 @@ package handler ...@@ -3,6 +3,7 @@ package handler
import ( import (
"fmt" "fmt"
"io" "io"
"net"
"os" "os"
"strings" "strings"
"sync" "sync"
...@@ -24,8 +25,8 @@ import ( ...@@ -24,8 +25,8 @@ import (
func SftpHandler(sess ssh.Session) { func SftpHandler(sess ssh.Session) {
ctx, cancel := cctx.NewContext(sess) ctx, cancel := cctx.NewContext(sess)
defer cancel() defer cancel()
host, _, _ := net.SplitHostPort(sess.RemoteAddr().String())
handler := &sftpHandler{user: ctx.User()} handler := &sftpHandler{user: ctx.User(), addr: host}
handler.initial() handler.initial()
handlers := sftp.Handlers{ handlers := sftp.Handlers{
FileGet: handler, FileGet: handler,
...@@ -37,14 +38,7 @@ func SftpHandler(sess ssh.Session) { ...@@ -37,14 +38,7 @@ func SftpHandler(sess ssh.Session) {
req := sftp.NewRequestServer(sess, handlers) req := sftp.NewRequestServer(sess, handlers)
if err := req.Serve(); err == io.EOF { if err := req.Serve(); err == io.EOF {
_ = req.Close() _ = req.Close()
hosts := handler.hosts handler.Close()
for hostname, dir := range hosts {
for name, d := range dir.suMaps {
srvconn.RecycleClient(d.conn)
delete(dir.suMaps, name)
}
delete(hosts, hostname)
}
logger.Info("sftp client exited session.") logger.Info("sftp client exited session.")
} else if err != nil { } else if err != nil {
logger.Error("sftp server completed with error:", err) logger.Error("sftp server completed with error:", err)
...@@ -53,6 +47,7 @@ func SftpHandler(sess ssh.Session) { ...@@ -53,6 +47,7 @@ func SftpHandler(sess ssh.Session) {
type sftpHandler struct { type sftpHandler struct {
user *model.User user *model.User
addr string
assets model.AssetList assets model.AssetList
rootPath string // tmp || home || ~ rootPath string // tmp || home || ~
hosts map[string]*HostNameDir hosts map[string]*HostNameDir
...@@ -152,7 +147,7 @@ func (fs *sftpHandler) Filelist(r *sftp.Request) (sftp.ListerAt, error) { ...@@ -152,7 +147,7 @@ func (fs *sftpHandler) Filelist(r *sftp.Request) (sftp.ListerAt, error) {
return fileInfos, err return fileInfos, err
} }
func (fs *sftpHandler) Filecmd(r *sftp.Request) error { func (fs *sftpHandler) Filecmd(r *sftp.Request) (err error) {
logger.Debug("File cmd: ", r.Filepath) logger.Debug("File cmd: ", r.Filepath)
pathNames := strings.Split(strings.TrimPrefix(r.Filepath, "/"), "/") pathNames := strings.Split(strings.TrimPrefix(r.Filepath, "/"), "/")
if len(pathNames) <= 2 { if len(pathNames) <= 2 {
...@@ -169,23 +164,42 @@ func (fs *sftpHandler) Filecmd(r *sftp.Request) error { ...@@ -169,23 +164,42 @@ func (fs *sftpHandler) Filecmd(r *sftp.Request) error {
suDir.conn = conn suDir.conn = conn
} }
realPathName := suDir.ParsePath(r.Filepath) realPathName := suDir.ParsePath(r.Filepath)
logData := &model.FTPLog{
User: fs.user.Username,
Hostname: hostDir.asset.Hostname,
OrgID: hostDir.asset.OrgID,
SystemUser: suDir.systemUser.Name,
RemoteAddr: fs.addr,
Operate: r.Method,
Path: realPathName,
DataStart: time.Now().UTC().Format("2006-01-02 15:04:05 +0000"),
IsSuccess: false,
}
defer fs.CreateFTPLog(logData)
switch r.Method { switch r.Method {
case "Setstat": case "Setstat":
return nil return
case "Rename": case "Rename":
realNewName := suDir.ParsePath(r.Target) realNewName := suDir.ParsePath(r.Target)
return suDir.client.Rename(realPathName, realNewName) logData.Path = fmt.Sprintf("%s=>%s", realPathName, realNewName)
err = suDir.client.Rename(realPathName, realNewName)
case "Rmdir": case "Rmdir":
return suDir.client.RemoveDirectory(realPathName) err = suDir.client.RemoveDirectory(realPathName)
case "Remove": case "Remove":
return suDir.client.Remove(realPathName) err = suDir.client.Remove(realPathName)
case "Mkdir": case "Mkdir":
return suDir.client.MkdirAll(realPathName) err = suDir.client.MkdirAll(realPathName)
case "Symlink": case "Symlink":
realNewName := suDir.ParsePath(r.Target) realNewName := suDir.ParsePath(r.Target)
return suDir.client.Symlink(realPathName, realNewName) logData.Path = fmt.Sprintf("%s=>%s", realPathName, realNewName)
err = suDir.client.Symlink(realPathName, realNewName)
default:
return
}
if err == nil {
logData.IsSuccess = true
} }
return nil return
} }
func (fs *sftpHandler) Filewrite(r *sftp.Request) (io.WriterAt, error) { func (fs *sftpHandler) Filewrite(r *sftp.Request) (io.WriterAt, error) {
...@@ -205,7 +219,22 @@ func (fs *sftpHandler) Filewrite(r *sftp.Request) (io.WriterAt, error) { ...@@ -205,7 +219,22 @@ func (fs *sftpHandler) Filewrite(r *sftp.Request) (io.WriterAt, error) {
suDir.conn = conn suDir.conn = conn
} }
realPathName := suDir.ParsePath(r.Filepath) realPathName := suDir.ParsePath(r.Filepath)
logData := &model.FTPLog{
User: fs.user.Username,
Hostname: hostDir.asset.Hostname,
OrgID: hostDir.asset.OrgID,
SystemUser: suDir.systemUser.Name,
RemoteAddr: fs.addr,
Operate: "Upload",
Path: realPathName,
DataStart: time.Now().UTC().Format("2006-01-02 15:04:05 +0000"),
IsSuccess: false,
}
defer fs.CreateFTPLog(logData)
f, err := suDir.client.Create(realPathName) f, err := suDir.client.Create(realPathName)
if err == nil {
logData.IsSuccess = true
}
return NewWriterAt(f), err return NewWriterAt(f), err
} }
...@@ -226,10 +255,23 @@ func (fs *sftpHandler) Fileread(r *sftp.Request) (io.ReaderAt, error) { ...@@ -226,10 +255,23 @@ func (fs *sftpHandler) Fileread(r *sftp.Request) (io.ReaderAt, error) {
suDir.conn = client suDir.conn = client
} }
realPathName := suDir.ParsePath(r.Filepath) realPathName := suDir.ParsePath(r.Filepath)
logData := &model.FTPLog{
User: fs.user.Username,
Hostname: hostDir.asset.Hostname,
OrgID: hostDir.asset.OrgID,
SystemUser: suDir.systemUser.Name,
RemoteAddr: fs.addr,
Operate: "Download",
Path: realPathName,
DataStart: time.Now().UTC().Format("2006-01-02 15:04:05 +0000"),
IsSuccess: false,
}
defer fs.CreateFTPLog(logData)
f, err := suDir.client.Open(realPathName) f, err := suDir.client.Open(realPathName)
if err != nil { if err != nil {
return nil, err return nil, err
} }
logData.IsSuccess = true
return NewReaderAt(f), err return NewReaderAt(f), err
} }
...@@ -245,6 +287,31 @@ func (fs *sftpHandler) GetSftpClient(asset *model.Asset, sysUser *model.SystemUs ...@@ -245,6 +287,31 @@ func (fs *sftpHandler) GetSftpClient(asset *model.Asset, sysUser *model.SystemUs
return sftpClient, sshClient, nil return sftpClient, sshClient, nil
} }
func (fs *sftpHandler) CreateFTPLog(data *model.FTPLog) {
for i := 0; i < 4; i++ {
err := service.PushFTPLog(data)
if err == nil {
break
}
logger.Debugf("create FTP log err: %s", err.Error())
time.Sleep(500 * time.Millisecond)
}
}
func (fs *sftpHandler) Close() {
for _, dir := range fs.hosts {
if dir.suMaps == nil {
continue
}
for _, d := range dir.suMaps {
if d.client != nil {
_ = d.client.Close()
srvconn.RecycleClient(d.conn)
}
}
}
}
type HostNameDir struct { type HostNameDir struct {
rootPath string rootPath string
hostname string hostname string
......
...@@ -28,6 +28,7 @@ func NewUserVolume(user *model.User, addr string) *UserVolume { ...@@ -28,6 +28,7 @@ func NewUserVolume(user *model.User, addr string) *UserVolume {
rawID := fmt.Sprintf("'%s@%s", user.Username, addr) rawID := fmt.Sprintf("'%s@%s", user.Username, addr)
uVolume := &UserVolume{ uVolume := &UserVolume{
Uuid: elfinder.GenerateID(rawID), Uuid: elfinder.GenerateID(rawID),
Addr: addr,
user: user, user: user,
Name: defaultHomeName, Name: defaultHomeName,
basePath: fmt.Sprintf("/%s", defaultHomeName), basePath: fmt.Sprintf("/%s", defaultHomeName),
...@@ -38,6 +39,7 @@ func NewUserVolume(user *model.User, addr string) *UserVolume { ...@@ -38,6 +39,7 @@ func NewUserVolume(user *model.User, addr string) *UserVolume {
type UserVolume struct { type UserVolume struct {
Uuid string Uuid string
Addr string
Name string Name string
basePath string basePath string
user *model.User user *model.User
...@@ -269,7 +271,24 @@ func (u *UserVolume) GetFile(path string) (reader io.ReadCloser, err error) { ...@@ -269,7 +271,24 @@ func (u *UserVolume) GetFile(path string) (reader io.ReadCloser, err error) {
sysUserVol.conn = conn sysUserVol.conn = conn
} }
return sysUserVol.client.Open(realPath) logData := &model.FTPLog{
User: u.user.Username,
Hostname: hostVol.asset.Hostname,
OrgID: hostVol.asset.OrgID,
SystemUser: sysUserVol.systemUser.Name,
RemoteAddr: u.Addr,
Operate: "Download",
Path: realPath,
DataStart: time.Now().UTC().Format("2006-01-02 15:04:05 +0000"),
IsSuccess: false,
}
defer u.CreateFTPLog(logData)
reader, err = sysUserVol.client.Open(realPath)
if err != nil {
return
}
logData.IsSuccess = true
return
} }
func (u *UserVolume) UploadFile(dir, filename string, reader io.Reader) (elfinder.FileDir, error) { func (u *UserVolume) UploadFile(dir, filename string, reader io.Reader) (elfinder.FileDir, error) {
...@@ -324,10 +343,24 @@ func (u *UserVolume) UploadFile(dir, filename string, reader io.Reader) (elfinde ...@@ -324,10 +343,24 @@ func (u *UserVolume) UploadFile(dir, filename string, reader io.Reader) (elfinde
return rest, err return rest, err
} }
defer fd.Close() defer fd.Close()
logData := &model.FTPLog{
User: u.user.Username,
Hostname: hostVol.asset.Hostname,
OrgID: hostVol.asset.OrgID,
SystemUser: sysUserVol.systemUser.Name,
RemoteAddr: u.Addr,
Operate: "Upload",
Path: realFilenamePath,
DataStart: time.Now().UTC().Format("2006-01-02 15:04:05 +0000"),
IsSuccess: false,
}
defer u.CreateFTPLog(logData)
_, err = io.Copy(fd, reader) _, err = io.Copy(fd, reader)
if err != nil { if err != nil {
return rest, err return rest, err
} }
logData.IsSuccess = true
return u.Info(filepath.Join(dir, filename)) return u.Info(filepath.Join(dir, filename))
} }
...@@ -394,11 +427,24 @@ func (u *UserVolume) MergeChunk(cid, total int, dirPath, filename string) (elfin ...@@ -394,11 +427,24 @@ func (u *UserVolume) MergeChunk(cid, total int, dirPath, filename string) (elfin
} }
filenamePath := filepath.Join(realDirPath, filename) filenamePath := filepath.Join(realDirPath, filename)
logData := &model.FTPLog{
User: u.user.Username,
Hostname: hostVol.asset.Hostname,
OrgID: hostVol.asset.OrgID,
SystemUser: sysUserVol.systemUser.Name,
RemoteAddr: u.Addr,
Operate: "Upload",
Path: filenamePath,
DataStart: time.Now().UTC().Format("2006-01-02 15:04:05 +0000"),
IsSuccess: false,
}
defer u.CreateFTPLog(logData)
fd, err := sysUserVol.client.OpenFile(filenamePath, os.O_WRONLY|os.O_APPEND|os.O_CREATE|os.O_TRUNC) fd, err := sysUserVol.client.OpenFile(filenamePath, os.O_WRONLY|os.O_APPEND|os.O_CREATE|os.O_TRUNC)
if err != nil { if err != nil {
return rest, err return rest, err
} }
defer fd.Close() defer fd.Close()
for i := 0; i <= total; i++ { for i := 0; i <= total; i++ {
partPath := fmt.Sprintf("%s.%d_%d.part_%d", partPath := fmt.Sprintf("%s.%d_%d.part_%d",
filepath.Join(u.localTmpPath, dirPath, filename), i, total, cid) filepath.Join(u.localTmpPath, dirPath, filename), i, total, cid)
...@@ -414,9 +460,9 @@ func (u *UserVolume) MergeChunk(cid, total int, dirPath, filename string) (elfin ...@@ -414,9 +460,9 @@ func (u *UserVolume) MergeChunk(cid, total int, dirPath, filename string) (elfin
return rest, os.ErrNotExist return rest, os.ErrNotExist
} }
_ = partFD.Close() _ = partFD.Close()
err = os.Remove(partPath) _ = os.Remove(partPath)
} }
logData.IsSuccess = true
return u.Info(filepath.Join(dirPath, filename)) return u.Info(filepath.Join(dirPath, filename))
} }
...@@ -476,9 +522,22 @@ func (u *UserVolume) MakeDir(dir, newDirname string) (elfinder.FileDir, error) { ...@@ -476,9 +522,22 @@ func (u *UserVolume) MakeDir(dir, newDirname string) (elfinder.FileDir, error) {
} }
realDirPath := filepath.Join(realPath, newDirname) realDirPath := filepath.Join(realPath, newDirname)
err := sysUserVol.client.MkdirAll(realDirPath) err := sysUserVol.client.MkdirAll(realDirPath)
logData := &model.FTPLog{
User: u.user.Username,
Hostname: hostVol.asset.Hostname,
OrgID: hostVol.asset.OrgID,
SystemUser: sysUserVol.systemUser.Name,
RemoteAddr: u.Addr,
Operate: "Mkdir",
Path: realDirPath,
DataStart: time.Now().UTC().Format("2006-01-02 15:04:05 +0000"),
IsSuccess: false,
}
defer u.CreateFTPLog(logData)
if err != nil { if err != nil {
return rest, err return rest, err
} }
logData.IsSuccess = true
return u.Info(filepath.Join(dir, newDirname)) return u.Info(filepath.Join(dir, newDirname))
} }
...@@ -527,14 +586,26 @@ func (u *UserVolume) MakeFile(dir, newFilename string) (elfinder.FileDir, error) ...@@ -527,14 +586,26 @@ func (u *UserVolume) MakeFile(dir, newFilename string) (elfinder.FileDir, error)
} }
realFilePath := filepath.Join(realPath, newFilename) realFilePath := filepath.Join(realPath, newFilename)
_, err := sysUserVol.client.Create(realFilePath) _, err := sysUserVol.client.Create(realFilePath)
logData := &model.FTPLog{
User: u.user.Username,
Hostname: hostVol.asset.Hostname,
OrgID: hostVol.asset.OrgID,
SystemUser: sysUserVol.systemUser.Name,
RemoteAddr: u.Addr,
Operate: "Append",
Path: realFilePath,
DataStart: time.Now().UTC().Format("2006-01-02 15:04:05 +0000"),
IsSuccess: false,
}
defer u.CreateFTPLog(logData)
if err != nil { if err != nil {
return rest, err return rest, err
} }
logData.IsSuccess = true
return u.Info(filepath.Join(dir, newFilename)) return u.Info(filepath.Join(dir, newFilename))
} }
func (u *UserVolume) Rename(oldNamePath, newname string) (elfinder.FileDir, error) { func (u *UserVolume) Rename(oldNamePath, newName string) (elfinder.FileDir, error) {
var rest elfinder.FileDir var rest elfinder.FileDir
pathNames := strings.Split(strings.TrimPrefix(oldNamePath, "/"), "/") pathNames := strings.Split(strings.TrimPrefix(oldNamePath, "/"), "/")
hostVol, ok := u.hosts[pathNames[1]] hostVol, ok := u.hosts[pathNames[1]]
...@@ -573,12 +644,25 @@ func (u *UserVolume) Rename(oldNamePath, newname string) (elfinder.FileDir, erro ...@@ -573,12 +644,25 @@ func (u *UserVolume) Rename(oldNamePath, newname string) (elfinder.FileDir, erro
} }
dirpath := filepath.Dir(realPath) dirpath := filepath.Dir(realPath)
newFilePath := filepath.Join(dirpath, newname) newFilePath := filepath.Join(dirpath, newName)
err := sysUserVol.client.Rename(oldNamePath, newFilePath) err := sysUserVol.client.Rename(oldNamePath, newFilePath)
logData := &model.FTPLog{
User: u.user.Username,
Hostname: hostVol.asset.Hostname,
OrgID: hostVol.asset.OrgID,
SystemUser: sysUserVol.systemUser.Name,
RemoteAddr: u.Addr,
Operate: "Rename",
Path: fmt.Sprintf("%s=>%s", oldNamePath, newFilePath),
DataStart: time.Now().UTC().Format("2006-01-02 15:04:05 +0000"),
IsSuccess: false,
}
defer u.CreateFTPLog(logData)
if err != nil { if err != nil {
return rest, err return rest, err
} }
logData.IsSuccess = true
return u.Info(newFilePath) return u.Info(newFilePath)
} }
...@@ -624,7 +708,23 @@ func (u *UserVolume) Remove(path string) error { ...@@ -624,7 +708,23 @@ func (u *UserVolume) Remove(path string) error {
sysUserVol.conn = conn sysUserVol.conn = conn
} }
return sysUserVol.client.Remove(realPath) logData := &model.FTPLog{
User: u.user.Username,
Hostname: hostVol.asset.Hostname,
OrgID: hostVol.asset.OrgID,
SystemUser: sysUserVol.systemUser.Name,
RemoteAddr: u.Addr,
Operate: "Delete",
Path: realPath,
DataStart: time.Now().UTC().Format("2006-01-02 15:04:05 +0000"),
IsSuccess: false,
}
defer u.CreateFTPLog(logData)
err := sysUserVol.client.Remove(realPath)
if err == nil {
logData.IsSuccess = true
}
return err
} }
func (u *UserVolume) Paste(dir, filename, suffix string, reader io.ReadCloser) (elfinder.FileDir, error) { func (u *UserVolume) Paste(dir, filename, suffix string, reader io.ReadCloser) (elfinder.FileDir, error) {
...@@ -672,9 +772,21 @@ func (u *UserVolume) Paste(dir, filename, suffix string, reader io.ReadCloser) ( ...@@ -672,9 +772,21 @@ func (u *UserVolume) Paste(dir, filename, suffix string, reader io.ReadCloser) (
realFilePath := filepath.Join(realPath, filename) realFilePath := filepath.Join(realPath, filename)
_, err := sysUserVol.client.Stat(realFilePath) _, err := sysUserVol.client.Stat(realFilePath)
if err == nil { if err != nil {
realPath += suffix realFilePath += suffix
} }
logData := &model.FTPLog{
User: u.user.Username,
Hostname: hostVol.asset.Hostname,
OrgID: hostVol.asset.OrgID,
SystemUser: sysUserVol.systemUser.Name,
RemoteAddr: u.Addr,
Operate: "Append",
Path: realFilePath,
DataStart: time.Now().UTC().Format("2006-01-02 15:04:05 +0000"),
IsSuccess: false,
}
defer u.CreateFTPLog(logData)
fd, err := sysUserVol.client.OpenFile(realPath, os.O_RDWR|os.O_CREATE) fd, err := sysUserVol.client.OpenFile(realPath, os.O_RDWR|os.O_CREATE)
if err != nil { if err != nil {
return rest, err return rest, err
...@@ -684,6 +796,7 @@ func (u *UserVolume) Paste(dir, filename, suffix string, reader io.ReadCloser) ( ...@@ -684,6 +796,7 @@ func (u *UserVolume) Paste(dir, filename, suffix string, reader io.ReadCloser) (
if err != nil { if err != nil {
return rest, err return rest, err
} }
logData.IsSuccess = true
return u.Info(realPath) return u.Info(realPath)
} }
...@@ -722,6 +835,17 @@ func (u *UserVolume) Close() { ...@@ -722,6 +835,17 @@ func (u *UserVolume) Close() {
} }
} }
func (u *UserVolume) CreateFTPLog(data *model.FTPLog) {
for i := 0; i < 4; i++ {
err := service.PushFTPLog(data)
if err == nil {
break
}
logger.Debugf("create FTP log err: %s", err.Error())
time.Sleep(500 * time.Millisecond)
}
}
type hostnameVolume struct { type hostnameVolume struct {
VID string VID string
homePath string homePath string
...@@ -775,7 +899,6 @@ func (su *sysUserVolume) ParsePath(path string) string { ...@@ -775,7 +899,6 @@ func (su *sysUserVolume) ParsePath(path string) string {
func (su *sysUserVolume) Close() { func (su *sysUserVolume) Close() {
if su.client != nil { if su.client != nil {
_ = su.client.Close() _ = su.client.Close()
su.client = nil
} }
srvconn.RecycleClient(su.conn) srvconn.RecycleClient(su.conn)
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment