transfer logs: add FTP mode

This commit is contained in:
Nicola Murino 2021-08-10 13:07:38 +02:00
parent 0de0d3308c
commit 555dc3b0c0
No known key found for this signature in database
GPG key ID: 2F1FB59433D5A8CB
6 changed files with 63 additions and 8 deletions

View file

@ -30,6 +30,7 @@ type BaseTransfer struct { //nolint:maligned
fsPath string
effectiveFsPath string
requestPath string
ftpMode string
start time.Time
MaxWriteSize int64
MinWriteOffset int64
@ -68,6 +69,11 @@ func NewBaseTransfer(file vfs.File, conn *BaseConnection, cancelFn func(), fsPat
return t
}
// SetFtpMode sets the FTP mode for the current transfer
func (t *BaseTransfer) SetFtpMode(mode string) {
t.ftpMode = mode
}
// GetID returns the transfer ID
func (t *BaseTransfer) GetID() uint64 {
return t.ID
@ -236,7 +242,7 @@ func (t *BaseTransfer) Close() error {
elapsed := time.Since(t.start).Nanoseconds() / 1000000
if t.transferType == TransferDownload {
logger.TransferLog(downloadLogSender, t.fsPath, elapsed, atomic.LoadInt64(&t.BytesSent), t.Connection.User.Username,
t.Connection.ID, t.Connection.protocol, t.Connection.localAddr, t.Connection.remoteAddr)
t.Connection.ID, t.Connection.protocol, t.Connection.localAddr, t.Connection.remoteAddr, t.ftpMode)
ExecuteActionNotification(&t.Connection.User, operationDownload, t.fsPath, t.requestPath, "", "", t.Connection.protocol,
atomic.LoadInt64(&t.BytesSent), t.ErrTransfer)
} else {
@ -247,7 +253,7 @@ func (t *BaseTransfer) Close() error {
t.Connection.Log(logger.LevelDebug, "uploaded file size %v", fileSize)
t.updateQuota(numFiles, fileSize)
logger.TransferLog(uploadLogSender, t.fsPath, elapsed, atomic.LoadInt64(&t.BytesReceived), t.Connection.User.Username,
t.Connection.ID, t.Connection.protocol, t.Connection.localAddr, t.Connection.remoteAddr)
t.Connection.ID, t.Connection.protocol, t.Connection.localAddr, t.Connection.remoteAddr, t.ftpMode)
ExecuteActionNotification(&t.Connection.User, operationUpload, t.fsPath, t.requestPath, "", "", t.Connection.protocol, fileSize,
t.ErrTransfer)
}

View file

@ -284,3 +284,16 @@ func TestRemovePartialCryptoFile(t *testing.T) {
assert.Equal(t, int64(9), size)
assert.NoFileExists(t, testFile)
}
func TestFTPMode(t *testing.T) {
conn := NewBaseConnection("", ProtocolFTP, "", "", dataprovider.User{})
transfer := BaseTransfer{
Connection: conn,
transferType: TransferUpload,
BytesReceived: 123,
Fs: vfs.NewOsFs("", os.TempDir(), ""),
}
assert.Empty(t, transfer.ftpMode)
transfer.SetFtpMode("active")
assert.Equal(t, "active", transfer.ftpMode)
}

View file

@ -20,7 +20,8 @@ The logs can be divided into the following categories:
- `username`, string
- `file_path` string
- `connection_id` string. Unique connection identifier
- `protocol` string. `SFTP` or `SCP`
- `protocol` string. `SFTP`, `SCP`, `SSH`, `FTP`, `HTTP`, `DAV`
- `ftp_mode`, string. `active` or `passive`. Included only for `FTP` protocol
- **"command logs"**, SFTP/SCP command logs:
- `sender` string. `Rename`, `Rmdir`, `Mkdir`, `Symlink`, `Remove`, `Chmod`, `Chown`, `Chtimes`, `Truncate`, `SSHCommand`
- `level` string

View file

@ -30,6 +30,19 @@ type Connection struct {
clientContext ftpserver.ClientContext
}
func (c *Connection) getFTPMode() string {
if c.clientContext == nil {
return ""
}
switch c.clientContext.GetLastDataChannel() {
case ftpserver.DataChannelActive:
return "active"
case ftpserver.DataChannelPassive:
return "passive"
}
return ""
}
// GetClientVersion returns the connected client's version.
// It returns "Unknown" if the client does not advertise its
// version
@ -325,6 +338,7 @@ func (c *Connection) downloadFile(fs vfs.Fs, fsPath, ftpPath string, offset int6
baseTransfer := common.NewBaseTransfer(file, c.BaseConnection, cancelFn, fsPath, fsPath, ftpPath, common.TransferDownload,
0, 0, 0, false, fs)
baseTransfer.SetFtpMode(c.getFTPMode())
t := newTransfer(baseTransfer, nil, r, offset)
return t, nil
@ -390,6 +404,7 @@ func (c *Connection) handleFTPUploadToNewFile(fs vfs.Fs, resolvedPath, filePath,
baseTransfer := common.NewBaseTransfer(file, c.BaseConnection, cancelFn, resolvedPath, filePath, requestPath,
common.TransferUpload, 0, 0, maxWriteSize, true, fs)
baseTransfer.SetFtpMode(c.getFTPMode())
t := newTransfer(baseTransfer, w, nil, 0)
return t, nil
@ -466,6 +481,7 @@ func (c *Connection) handleFTPUploadToExistingFile(fs vfs.Fs, flags int, resolve
baseTransfer := common.NewBaseTransfer(file, c.BaseConnection, cancelFn, resolvedPath, filePath, requestPath,
common.TransferUpload, minWriteOffset, initialSize, maxWriteSize, false, fs)
baseTransfer.SetFtpMode(c.getFTPMode())
t := newTransfer(baseTransfer, w, nil, 0)
return t, nil

View file

@ -253,6 +253,7 @@ xr5cb9VBRBtB9aOKVfuRhpatAfS2Pzm2Htae9lFn7slGPUmu2hkjDw==
)
type mockFTPClientContext struct {
lastDataChannel ftpserver.DataChannel
}
func (cc mockFTPClientContext) Path() string {
@ -298,7 +299,7 @@ func (cc mockFTPClientContext) GetLastCommand() string {
}
func (cc mockFTPClientContext) GetLastDataChannel() ftpserver.DataChannel {
return ftpserver.DataChannelPassive
return cc.lastDataChannel
}
// MockOsFs mockable OsFs
@ -559,6 +560,19 @@ func TestUserInvalidParams(t *testing.T) {
assert.Error(t, err)
}
func TestFTPMode(t *testing.T) {
connection := &Connection{
BaseConnection: common.NewBaseConnection("", common.ProtocolFTP, "", "", dataprovider.User{}),
}
assert.Empty(t, connection.getFTPMode())
connection.clientContext = mockFTPClientContext{lastDataChannel: ftpserver.DataChannelActive}
assert.Equal(t, "active", connection.getFTPMode())
connection.clientContext = mockFTPClientContext{lastDataChannel: ftpserver.DataChannelPassive}
assert.Equal(t, "passive", connection.getFTPMode())
connection.clientContext = mockFTPClientContext{lastDataChannel: 0}
assert.Empty(t, connection.getFTPMode())
}
func TestClientVersion(t *testing.T) {
mockCC := mockFTPClientContext{}
connID := fmt.Sprintf("2_%v", mockCC.ID())

View file

@ -259,8 +259,10 @@ func ErrorToConsole(format string, v ...interface{}) {
}
// TransferLog logs uploads or downloads
func TransferLog(operation, path string, elapsed int64, size int64, user, connectionID, protocol, localAddr, remoteAddr string) {
logger.Info().
func TransferLog(operation, path string, elapsed int64, size int64, user, connectionID, protocol, localAddr,
remoteAddr, ftpMode string,
) {
ev := logger.Info().
Timestamp().
Str("sender", operation).
Str("local_addr", localAddr).
@ -270,8 +272,11 @@ func TransferLog(operation, path string, elapsed int64, size int64, user, connec
Str("username", user).
Str("file_path", path).
Str("connection_id", connectionID).
Str("protocol", protocol).
Send()
Str("protocol", protocol)
if ftpMode != "" {
ev.Str("ftp_mode", ftpMode)
}
ev.Send()
}
// CommandLog logs an SFTP/SCP/SSH command