add session id to notifier plugins/hook

This commit is contained in:
Nicola Murino 2021-12-04 17:27:24 +01:00
parent dc1cc88a46
commit a7c0b07a2a
No known key found for this signature in database
GPG key ID: 2F1FB59433D5A8CB
18 changed files with 120 additions and 91 deletions

View file

@ -51,10 +51,10 @@ func InitializeActionHandler(handler ActionHandler) {
}
// ExecutePreAction executes a pre-* action and returns the result
func ExecutePreAction(user *dataprovider.User, operation, filePath, virtualPath, protocol, ip string, fileSize int64,
openFlags int,
) error {
plugin.Handler.NotifyFsEvent(time.Now().UnixNano(), operation, user.Username, filePath, "", "", protocol, ip, virtualPath, "", fileSize, nil)
func ExecutePreAction(conn *BaseConnection, operation, filePath, virtualPath string, fileSize int64, openFlags int) error {
remoteIP := conn.GetRemoteIP()
plugin.Handler.NotifyFsEvent(time.Now().UnixNano(), operation, conn.User.Username, filePath, "", "", conn.protocol,
remoteIP, virtualPath, "", conn.ID, fileSize, nil)
if !util.IsStringInSlice(operation, Config.Actions.ExecuteOn) {
// for pre-delete we execute the internal handling on error, so we must return errUnconfiguredAction.
// Other pre action will deny the operation on error so if we have no configuration we must return
@ -64,19 +64,20 @@ func ExecutePreAction(user *dataprovider.User, operation, filePath, virtualPath,
}
return nil
}
notification := newActionNotification(user, operation, filePath, virtualPath, "", "", "", protocol, ip, fileSize,
openFlags, nil)
notification := newActionNotification(&conn.User, operation, filePath, virtualPath, "", "", "",
conn.protocol, remoteIP, conn.ID, fileSize, openFlags, nil)
return actionHandler.Handle(notification)
}
// ExecuteActionNotification executes the defined hook, if any, for the specified action
func ExecuteActionNotification(user *dataprovider.User, operation, filePath, virtualPath, target, virtualTarget, sshCmd,
protocol, ip string, fileSize int64, err error,
func ExecuteActionNotification(conn *BaseConnection, operation, filePath, virtualPath, target, virtualTarget, sshCmd string,
fileSize int64, err error,
) {
plugin.Handler.NotifyFsEvent(time.Now().UnixNano(), operation, user.Username, filePath, target, sshCmd, protocol, ip, virtualPath,
virtualTarget, fileSize, err)
notification := newActionNotification(user, operation, filePath, virtualPath, target, virtualTarget, sshCmd, protocol,
ip, fileSize, 0, err)
remoteIP := conn.GetRemoteIP()
plugin.Handler.NotifyFsEvent(time.Now().UnixNano(), operation, conn.User.Username, filePath, target, sshCmd, conn.protocol,
remoteIP, virtualPath, virtualTarget, conn.ID, fileSize, err)
notification := newActionNotification(&conn.User, operation, filePath, virtualPath, target, virtualTarget, sshCmd,
conn.protocol, remoteIP, conn.ID, fileSize, 0, err)
if util.IsStringInSlice(operation, Config.Actions.ExecuteSync) {
actionHandler.Handle(notification) //nolint:errcheck
@ -107,13 +108,14 @@ type ActionNotification struct {
Status int `json:"status"`
Protocol string `json:"protocol"`
IP string `json:"ip"`
SessionID string `json:"session_id"`
Timestamp int64 `json:"timestamp"`
OpenFlags int `json:"open_flags,omitempty"`
}
func newActionNotification(
user *dataprovider.User,
operation, filePath, virtualPath, target, virtualTarget, sshCmd, protocol, ip string,
operation, filePath, virtualPath, target, virtualTarget, sshCmd, protocol, ip, sessionID string,
fileSize int64,
openFlags int,
err error,
@ -159,6 +161,7 @@ func newActionNotification(
Status: status,
Protocol: protocol,
IP: ip,
SessionID: sessionID,
OpenFlags: openFlags,
Timestamp: time.Now().UnixNano(),
}
@ -252,6 +255,7 @@ func notificationAsEnvVars(notification *ActionNotification) []string {
fmt.Sprintf("SFTPGO_ACTION_STATUS=%v", notification.Status),
fmt.Sprintf("SFTPGO_ACTION_PROTOCOL=%v", notification.Protocol),
fmt.Sprintf("SFTPGO_ACTION_IP=%v", notification.IP),
fmt.Sprintf("SFTPGO_ACTION_SESSION_ID=%v", notification.SessionID),
fmt.Sprintf("SFTPGO_ACTION_OPEN_FLAGS=%v", notification.OpenFlags),
fmt.Sprintf("SFTPGO_ACTION_TIMESTAMP=%v", notification.Timestamp),
}

View file

@ -9,6 +9,8 @@ import (
"runtime"
"testing"
"github.com/lithammer/shortuuid/v3"
"github.com/rs/xid"
"github.com/stretchr/testify/assert"
"github.com/drakkan/sftpgo/v2/dataprovider"
@ -45,38 +47,45 @@ func TestNewActionNotification(t *testing.T) {
Endpoint: "sftpendpoint",
},
}
a := newActionNotification(user, operationDownload, "path", "vpath", "target", "", "", ProtocolSFTP, "", 123, 0, errors.New("fake error"))
sessionID := xid.New().String()
a := newActionNotification(user, operationDownload, "path", "vpath", "target", "", "", ProtocolSFTP, "", sessionID,
123, 0, errors.New("fake error"))
assert.Equal(t, user.Username, a.Username)
assert.Equal(t, 0, len(a.Bucket))
assert.Equal(t, 0, len(a.Endpoint))
assert.Equal(t, 2, a.Status)
user.FsConfig.Provider = sdk.S3FilesystemProvider
a = newActionNotification(user, operationDownload, "path", "vpath", "target", "", "", ProtocolSSH, "", 123, 0, nil)
a = newActionNotification(user, operationDownload, "path", "vpath", "target", "", "", ProtocolSSH, "", sessionID,
123, 0, nil)
assert.Equal(t, "s3bucket", a.Bucket)
assert.Equal(t, "endpoint", a.Endpoint)
assert.Equal(t, 1, a.Status)
user.FsConfig.Provider = sdk.GCSFilesystemProvider
a = newActionNotification(user, operationDownload, "path", "vpath", "target", "", "", ProtocolSCP, "", 123, 0, ErrQuotaExceeded)
a = newActionNotification(user, operationDownload, "path", "vpath", "target", "", "", ProtocolSCP, "", sessionID,
123, 0, ErrQuotaExceeded)
assert.Equal(t, "gcsbucket", a.Bucket)
assert.Equal(t, 0, len(a.Endpoint))
assert.Equal(t, 3, a.Status)
user.FsConfig.Provider = sdk.AzureBlobFilesystemProvider
a = newActionNotification(user, operationDownload, "path", "vpath", "target", "", "", ProtocolSCP, "", 123, 0, nil)
a = newActionNotification(user, operationDownload, "path", "vpath", "target", "", "", ProtocolSCP, "", sessionID,
123, 0, nil)
assert.Equal(t, "azcontainer", a.Bucket)
assert.Equal(t, "azendpoint", a.Endpoint)
assert.Equal(t, 1, a.Status)
a = newActionNotification(user, operationDownload, "path", "vpath", "target", "", "", ProtocolSCP, "", 123, os.O_APPEND, nil)
a = newActionNotification(user, operationDownload, "path", "vpath", "target", "", "", ProtocolSCP, "", sessionID,
123, os.O_APPEND, nil)
assert.Equal(t, "azcontainer", a.Bucket)
assert.Equal(t, "azendpoint", a.Endpoint)
assert.Equal(t, 1, a.Status)
assert.Equal(t, os.O_APPEND, a.OpenFlags)
user.FsConfig.Provider = sdk.SFTPFilesystemProvider
a = newActionNotification(user, operationDownload, "path", "vpath", "target", "", "", ProtocolSFTP, "", 123, 0, nil)
a = newActionNotification(user, operationDownload, "path", "vpath", "target", "", "", ProtocolSFTP, "", sessionID,
123, 0, nil)
assert.Equal(t, "sftpendpoint", a.Endpoint)
}
@ -92,7 +101,8 @@ func TestActionHTTP(t *testing.T) {
Username: "username",
},
}
a := newActionNotification(user, operationDownload, "path", "vpath", "target", "", "", ProtocolSFTP, "", 123, 0, nil)
a := newActionNotification(user, operationDownload, "path", "vpath", "target", "", "", ProtocolSFTP, "",
xid.New().String(), 123, 0, nil)
err := actionHandler.Handle(a)
assert.NoError(t, err)
@ -127,11 +137,14 @@ func TestActionCMD(t *testing.T) {
Username: "username",
},
}
a := newActionNotification(user, operationDownload, "path", "vpath", "target", "", "", ProtocolSFTP, "", 123, 0, nil)
sessionID := shortuuid.New()
a := newActionNotification(user, operationDownload, "path", "vpath", "target", "", "", ProtocolSFTP, "", sessionID,
123, 0, nil)
err = actionHandler.Handle(a)
assert.NoError(t, err)
ExecuteActionNotification(user, OperationSSHCmd, "path", "vpath", "target", "vtarget", "sha1sum", ProtocolSSH, "", 0, nil)
c := NewBaseConnection("id", ProtocolSFTP, "", "", *user)
ExecuteActionNotification(c, OperationSSHCmd, "path", "vpath", "target", "vtarget", "sha1sum", 0, nil)
Config.Actions = actionsCopy
}
@ -153,7 +166,8 @@ func TestWrongActions(t *testing.T) {
},
}
a := newActionNotification(user, operationUpload, "", "", "", "", "", ProtocolSFTP, "", 123, 0, nil)
a := newActionNotification(user, operationUpload, "", "", "", "", "", ProtocolSFTP, "", xid.New().String(),
123, 0, nil)
err := actionHandler.Handle(a)
assert.Error(t, err, "action with bad command must fail")

View file

@ -264,7 +264,7 @@ func (c *BaseConnection) CreateDir(virtualPath string) error {
logger.CommandLog(mkdirLogSender, fsPath, "", c.User.Username, "", c.ID, c.protocol, -1, -1, "", "", "", -1,
c.localAddr, c.remoteAddr)
ExecuteActionNotification(&c.User, operationMkdir, fsPath, virtualPath, "", "", "", c.protocol, c.GetRemoteIP(), 0, nil)
ExecuteActionNotification(c, operationMkdir, fsPath, virtualPath, "", "", "", 0, nil)
return nil
}
@ -287,7 +287,7 @@ func (c *BaseConnection) RemoveFile(fs vfs.Fs, fsPath, virtualPath string, info
}
size := info.Size()
actionErr := ExecutePreAction(&c.User, operationPreDelete, fsPath, virtualPath, c.protocol, c.GetRemoteIP(), size, 0)
actionErr := ExecutePreAction(c, operationPreDelete, fsPath, virtualPath, size, 0)
if actionErr == nil {
c.Log(logger.LevelDebug, "remove for path %#v handled by pre-delete action", fsPath)
} else {
@ -311,7 +311,7 @@ func (c *BaseConnection) RemoveFile(fs vfs.Fs, fsPath, virtualPath string, info
}
}
if actionErr != nil {
ExecuteActionNotification(&c.User, operationDelete, fsPath, virtualPath, "", "", "", c.protocol, c.GetRemoteIP(), size, nil)
ExecuteActionNotification(c, operationDelete, fsPath, virtualPath, "", "", "", size, nil)
}
return nil
}
@ -371,7 +371,7 @@ func (c *BaseConnection) RemoveDir(virtualPath string) error {
logger.CommandLog(rmdirLogSender, fsPath, "", c.User.Username, "", c.ID, c.protocol, -1, -1, "", "", "", -1,
c.localAddr, c.remoteAddr)
ExecuteActionNotification(&c.User, operationRmdir, fsPath, virtualPath, "", "", "", c.protocol, c.GetRemoteIP(), 0, nil)
ExecuteActionNotification(c, operationRmdir, fsPath, virtualPath, "", "", "", 0, nil)
return nil
}
@ -432,8 +432,8 @@ func (c *BaseConnection) Rename(virtualSourcePath, virtualTargetPath string) err
c.updateQuotaAfterRename(fsDst, virtualSourcePath, virtualTargetPath, fsTargetPath, initialSize) //nolint:errcheck
logger.CommandLog(renameLogSender, fsSourcePath, fsTargetPath, c.User.Username, "", c.ID, c.protocol, -1, -1,
"", "", "", -1, c.localAddr, c.remoteAddr)
ExecuteActionNotification(&c.User, operationRename, fsSourcePath, virtualSourcePath, fsTargetPath, virtualTargetPath, "",
c.protocol, c.GetRemoteIP(), 0, nil)
ExecuteActionNotification(c, operationRename, fsSourcePath, virtualSourcePath, fsTargetPath, virtualTargetPath,
"", 0, nil)
return nil
}

View file

@ -255,8 +255,8 @@ func (t *BaseTransfer) Close() error {
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.ftpMode)
ExecuteActionNotification(&t.Connection.User, operationDownload, t.fsPath, t.requestPath, "", "", "", t.Connection.protocol,
t.Connection.GetRemoteIP(), atomic.LoadInt64(&t.BytesSent), t.ErrTransfer)
ExecuteActionNotification(t.Connection, operationDownload, t.fsPath, t.requestPath, "", "", "",
atomic.LoadInt64(&t.BytesSent), t.ErrTransfer)
} else {
fileSize := atomic.LoadInt64(&t.BytesReceived) + t.MinWriteOffset
if statSize, err := t.getUploadFileSize(); err == nil {
@ -267,8 +267,7 @@ func (t *BaseTransfer) Close() error {
t.updateTimes()
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.ftpMode)
ExecuteActionNotification(&t.Connection.User, operationUpload, t.fsPath, t.requestPath, "", "", "", t.Connection.protocol,
t.Connection.GetRemoteIP(), fileSize, t.ErrTransfer)
ExecuteActionNotification(t.Connection, operationUpload, t.fsPath, t.requestPath, "", "", "", fileSize, t.ErrTransfer)
}
if t.ErrTransfer != nil {
t.Connection.Log(logger.LevelWarn, "transfer error: %v, path: %#v", t.ErrTransfer, t.fsPath)

View file

@ -43,8 +43,9 @@ If the `hook` defines a path to an external program, then this program can read
- `SFTPGO_ACTION_BUCKET`, non-empty for S3, GCS and Azure backends
- `SFTPGO_ACTION_ENDPOINT`, non-empty for S3, SFTP and Azure backend if configured. For Azure this is the endpoint, if configured
- `SFTPGO_ACTION_STATUS`, integer. Status for `upload`, `download` and `ssh_cmd` actions. 1 means no error, 2 means a generic error occurred, 3 means quota exceeded error
- `SFTPGO_ACTION_PROTOCOL`, string. Possible values are `SSH`, `SFTP`, `SCP`, `FTP`, `DAV`, `HTTP`, `DataRetention`
- `SFTPGO_ACTION_PROTOCOL`, string. Possible values are `SSH`, `SFTP`, `SCP`, `FTP`, `DAV`, `HTTP`, `HTTPShare`, `DataRetention`
- `SFTPGO_ACTION_IP`, the action was executed from this IP address
- `SFTPGO_ACTION_SESSION_ID`, string. Unique protocol session identifier. For stateless protocols such as HTTP the session id will change for each request
- `SFTPGO_ACTION_OPEN_FLAGS`, integer. File open flags, can be non-zero for `pre-upload` action. If `SFTPGO_ACTION_FILE_SIZE` is greater than zero and `SFTPGO_ACTION_OPEN_FLAGS&512 == 0` the target file will not be truncated
- `SFTPGO_ACTION_TIMESTAMP`, int64. Event timestamp as nanoseconds since epoch
@ -65,8 +66,9 @@ If the `hook` defines an HTTP URL then this URL will be invoked as HTTP POST. Th
- `bucket`, string, inlcuded for S3, GCS and Azure backends
- `endpoint`, string, included for S3, SFTP and Azure backend if configured
- `status`, integer. Status for `upload`, `download` and `ssh_cmd` actions. 1 means no error, 2 means a generic error occurred, 3 means quota exceeded error
- `protocol`, string. Possible values are `SSH`, `SFTP`, `SCP`, `FTP`, `DAV`, `HTTP`, `DataRetention`
- `protocol`, string. Possible values are `SSH`, `SFTP`, `SCP`, `FTP`, `DAV`, `HTTP`, `HTTPShare`, `DataRetention`
- `ip`, string. The action was executed from this IP address
- `session_id`, string. Unique protocol session identifier. For stateless protocols such as HTTP the session id will change for each request
- `open_flags`, integer. File open flags, can be non-zero for `pre-upload` action. If `file_size` is greater than zero and `file_size&512 == 0` the target file will not be truncated
- `timestamp`, int64. Event timestamp as nanoseconds since epoch

View file

@ -325,8 +325,7 @@ func (c *Connection) downloadFile(fs vfs.Fs, fsPath, ftpPath string, offset int6
return nil, c.GetPermissionDeniedError()
}
if err := common.ExecutePreAction(&c.User, common.OperationPreDownload, fsPath, ftpPath, c.GetProtocol(), c.GetRemoteIP(),
0, 0); err != nil {
if err := common.ExecutePreAction(c.BaseConnection, common.OperationPreDownload, fsPath, ftpPath, 0, 0); err != nil {
c.Log(logger.LevelDebug, "download for file %#v denied by pre action: %v", ftpPath, err)
return nil, c.GetPermissionDeniedError()
}
@ -388,8 +387,7 @@ func (c *Connection) handleFTPUploadToNewFile(fs vfs.Fs, resolvedPath, filePath,
c.Log(logger.LevelInfo, "denying file write due to quota limits")
return nil, ftpserver.ErrStorageExceeded
}
if err := common.ExecutePreAction(&c.User, common.OperationPreUpload, resolvedPath, requestPath, c.GetProtocol(),
c.GetRemoteIP(), 0, 0); err != nil {
if err := common.ExecutePreAction(c.BaseConnection, common.OperationPreUpload, resolvedPath, requestPath, 0, 0); err != nil {
c.Log(logger.LevelDebug, "upload for file %#v denied by pre action: %v", requestPath, err)
return nil, fmt.Errorf("%w, denied by pre-upload action", ftpserver.ErrFileNameNotAllowed)
}
@ -434,7 +432,7 @@ func (c *Connection) handleFTPUploadToExistingFile(fs vfs.Fs, flags int, resolve
c.Log(logger.LevelDebug, "unable to get max write size: %v", err)
return nil, err
}
if err := common.ExecutePreAction(&c.User, common.OperationPreUpload, resolvedPath, requestPath, c.GetProtocol(), c.GetRemoteIP(), fileSize, flags); err != nil {
if err := common.ExecutePreAction(c.BaseConnection, common.OperationPreUpload, resolvedPath, requestPath, fileSize, flags); err != nil {
c.Log(logger.LevelDebug, "upload for file %#v denied by pre action: %v", requestPath, err)
return nil, fmt.Errorf("%w, denied by pre-upload action", ftpserver.ErrFileNameNotAllowed)
}

View file

@ -101,7 +101,7 @@ func (c *Connection) getFileReader(name string, offset int64, method string) (io
}
if method != http.MethodHead {
if err := common.ExecutePreAction(&c.User, common.OperationPreDownload, p, name, c.GetProtocol(), c.GetRemoteIP(), 0, 0); err != nil {
if err := common.ExecutePreAction(c.BaseConnection, common.OperationPreDownload, p, name, 0, 0); err != nil {
c.Log(logger.LevelDebug, "download for file %#v denied by pre action: %v", name, err)
return nil, c.GetPermissionDeniedError()
}
@ -176,7 +176,7 @@ func (c *Connection) handleUploadFile(fs vfs.Fs, resolvedPath, filePath, request
c.Log(logger.LevelInfo, "denying file write due to quota limits")
return nil, common.ErrQuotaExceeded
}
err := common.ExecutePreAction(&c.User, common.OperationPreUpload, resolvedPath, requestPath, c.GetProtocol(), c.GetRemoteIP(), fileSize, os.O_TRUNC)
err := common.ExecutePreAction(c.BaseConnection, common.OperationPreUpload, resolvedPath, requestPath, fileSize, os.O_TRUNC)
if err != nil {
c.Log(logger.LevelDebug, "upload for file %#v denied by pre action: %v", requestPath, err)
return nil, c.GetPermissionDeniedError()

View file

@ -203,7 +203,7 @@ func (p *notifierPlugin) canQueueEvent(timestamp int64) bool {
}
func (p *notifierPlugin) notifyFsAction(timestamp int64, action, username, fsPath, fsTargetPath, sshCmd,
protocol, ip, virtualPath, virtualTargetPath string, fileSize int64, errAction error) {
protocol, ip, virtualPath, virtualTargetPath, sessionID string, fileSize int64, errAction error) {
if !util.IsStringInSlice(action, p.config.NotifierOptions.FsEvents) {
return
}
@ -214,7 +214,7 @@ func (p *notifierPlugin) notifyFsAction(timestamp int64, action, username, fsPat
status = 0
}
p.sendFsEvent(timestamp, action, username, fsPath, fsTargetPath, sshCmd, protocol, ip, virtualPath, virtualTargetPath,
fileSize, status)
sessionID, fileSize, status)
}()
}
@ -237,9 +237,9 @@ func (p *notifierPlugin) notifyProviderAction(timestamp int64, action, username,
}
func (p *notifierPlugin) sendFsEvent(timestamp int64, action, username, fsPath, fsTargetPath, sshCmd,
protocol, ip, virtualPath, virtualTargetPath string, fileSize int64, status int) {
protocol, ip, virtualPath, virtualTargetPath, sessionID string, fileSize int64, status int) {
if err := p.notifier.NotifyFsEvent(timestamp, action, username, fsPath, fsTargetPath, sshCmd, protocol, ip,
virtualPath, virtualTargetPath, fileSize, status); err != nil {
virtualPath, virtualTargetPath, sessionID, fileSize, status); err != nil {
logger.Warn(logSender, "", "unable to send fs action notification to plugin %v: %v", p.config.Cmd, err)
if p.canQueueEvent(timestamp) {
p.queue.addFsEvent(timestamp, action, username, fsPath, fsTargetPath, sshCmd, protocol, ip, fileSize, status)
@ -267,7 +267,8 @@ func (p *notifierPlugin) sendQueuedEvents() {
fsEv := p.queue.popFsEvent()
for fsEv != nil {
go p.sendFsEvent(fsEv.Timestamp, fsEv.Action, fsEv.Username, fsEv.FsPath, fsEv.FsTargetPath,
fsEv.SshCmd, fsEv.Protocol, fsEv.Ip, fsEv.VirtualPath, fsEv.VirtualTargetPath, fsEv.FileSize, int(fsEv.Status))
fsEv.SshCmd, fsEv.Protocol, fsEv.Ip, fsEv.VirtualPath, fsEv.VirtualTargetPath, fsEv.SessionId,
fsEv.FileSize, int(fsEv.Status))
fsEv = p.queue.popFsEvent()
}

View file

@ -20,7 +20,7 @@ type GRPCClient struct {
// NotifyFsEvent implements the Notifier interface
func (c *GRPCClient) NotifyFsEvent(timestamp int64, action, username, fsPath, fsTargetPath, sshCmd, protocol, ip,
virtualPath, virtualTargetPath string, fileSize int64, status int,
virtualPath, virtualTargetPath, sessionID string, fileSize int64, status int,
) error {
ctx, cancel := context.WithTimeout(context.Background(), rpcTimeout)
defer cancel()
@ -38,6 +38,7 @@ func (c *GRPCClient) NotifyFsEvent(timestamp int64, action, username, fsPath, fs
Status: int32(status),
VirtualPath: virtualPath,
VirtualTargetPath: virtualTargetPath,
SessionId: sessionID,
})
return err
@ -69,7 +70,7 @@ type GRPCServer struct {
// SendFsEvent implements the serve side fs notify method
func (s *GRPCServer) SendFsEvent(ctx context.Context, req *proto.FsEvent) (*emptypb.Empty, error) {
err := s.Impl.NotifyFsEvent(req.Timestamp, req.Action, req.Username, req.FsPath, req.FsTargetPath, req.SshCmd,
req.Protocol, req.Ip, req.VirtualPath, req.VirtualTargetPath, req.FileSize, int(req.Status))
req.Protocol, req.Ip, req.VirtualPath, req.VirtualTargetPath, req.SessionId, req.FileSize, int(req.Status))
return &emptypb.Empty{}, err
}

View file

@ -33,7 +33,7 @@ var PluginMap = map[string]plugin.Plugin{
// Notifier defines the interface for notifiers plugins
type Notifier interface {
NotifyFsEvent(timestamp int64, action, username, fsPath, fsTargetPath, sshCmd, protocol, ip,
virtualPath, virtualTargetPath string, fileSize int64, status int) error
virtualPath, virtualTargetPath, sessionID string, fileSize int64, status int) error
NotifyProviderEvent(timestamp int64, action, username, objectType, objectName, ip string, object []byte) error
}

View file

@ -42,6 +42,7 @@ type FsEvent struct {
Ip string `protobuf:"bytes,10,opt,name=ip,proto3" json:"ip,omitempty"`
VirtualPath string `protobuf:"bytes,11,opt,name=virtual_path,json=virtualPath,proto3" json:"virtual_path,omitempty"`
VirtualTargetPath string `protobuf:"bytes,12,opt,name=virtual_target_path,json=virtualTargetPath,proto3" json:"virtual_target_path,omitempty"`
SessionId string `protobuf:"bytes,13,opt,name=session_id,json=sessionId,proto3" json:"session_id,omitempty"`
}
func (x *FsEvent) Reset() {
@ -160,6 +161,13 @@ func (x *FsEvent) GetVirtualTargetPath() string {
return ""
}
func (x *FsEvent) GetSessionId() string {
if x != nil {
return x.SessionId
}
return ""
}
type ProviderEvent struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
@ -262,7 +270,7 @@ var file_notifier_proto_notifier_proto_rawDesc = []byte{
0x2f, 0x6e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12,
0x05, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1b, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70,
0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x2e, 0x70, 0x72,
0x6f, 0x74, 0x6f, 0x22, 0xe7, 0x02, 0x0a, 0x07, 0x46, 0x73, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12,
0x6f, 0x74, 0x6f, 0x22, 0x86, 0x03, 0x0a, 0x07, 0x46, 0x73, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12,
0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x01, 0x20, 0x01,
0x28, 0x03, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x16, 0x0a,
0x06, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x61,
@ -284,31 +292,33 @@ var file_notifier_proto_notifier_proto_rawDesc = []byte{
0x52, 0x0b, 0x76, 0x69, 0x72, 0x74, 0x75, 0x61, 0x6c, 0x50, 0x61, 0x74, 0x68, 0x12, 0x2e, 0x0a,
0x13, 0x76, 0x69, 0x72, 0x74, 0x75, 0x61, 0x6c, 0x5f, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f,
0x70, 0x61, 0x74, 0x68, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x76, 0x69, 0x72, 0x74,
0x75, 0x61, 0x6c, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x50, 0x61, 0x74, 0x68, 0x22, 0xd4, 0x01,
0x0a, 0x0d, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12,
0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x01, 0x20, 0x01,
0x28, 0x03, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x16, 0x0a,
0x06, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x61,
0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1f, 0x0a, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x5f,
0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x6f, 0x62, 0x6a, 0x65,
0x63, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61,
0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61,
0x6d, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x70, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02,
0x69, 0x70, 0x12, 0x1f, 0x0a, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x6e, 0x61, 0x6d,
0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x4e,
0x61, 0x6d, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x64, 0x61,
0x74, 0x61, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0a, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74,
0x44, 0x61, 0x74, 0x61, 0x32, 0x84, 0x01, 0x0a, 0x08, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x65,
0x72, 0x12, 0x35, 0x0a, 0x0b, 0x53, 0x65, 0x6e, 0x64, 0x46, 0x73, 0x45, 0x76, 0x65, 0x6e, 0x74,
0x12, 0x0e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x46, 0x73, 0x45, 0x76, 0x65, 0x6e, 0x74,
0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62,
0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x41, 0x0a, 0x11, 0x53, 0x65, 0x6e, 0x64,
0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x14, 0x2e,
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x45, 0x76,
0x65, 0x6e, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f,
0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x42, 0x1b, 0x5a, 0x19, 0x73,
0x64, 0x6b, 0x2f, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2f, 0x6e, 0x6f, 0x74, 0x69, 0x66, 0x69,
0x65, 0x72, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
0x75, 0x61, 0x6c, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x50, 0x61, 0x74, 0x68, 0x12, 0x1d, 0x0a,
0x0a, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x0d, 0x20, 0x01, 0x28,
0x09, 0x52, 0x09, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x22, 0xd4, 0x01, 0x0a,
0x0d, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x1c,
0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28,
0x03, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x16, 0x0a, 0x06,
0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x61, 0x63,
0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1f, 0x0a, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x74,
0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x6f, 0x62, 0x6a, 0x65, 0x63,
0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d,
0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d,
0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x70, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69,
0x70, 0x12, 0x1f, 0x0a, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65,
0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x4e, 0x61,
0x6d, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x64, 0x61, 0x74,
0x61, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0a, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x44,
0x61, 0x74, 0x61, 0x32, 0x84, 0x01, 0x0a, 0x08, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72,
0x12, 0x35, 0x0a, 0x0b, 0x53, 0x65, 0x6e, 0x64, 0x46, 0x73, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12,
0x0e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x46, 0x73, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x1a,
0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75,
0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x41, 0x0a, 0x11, 0x53, 0x65, 0x6e, 0x64, 0x50,
0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x14, 0x2e, 0x70,
0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x45, 0x76, 0x65,
0x6e, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74,
0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x42, 0x1b, 0x5a, 0x19, 0x73, 0x64,
0x6b, 0x2f, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2f, 0x6e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x65,
0x72, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (

View file

@ -18,6 +18,7 @@ message FsEvent {
string ip = 10;
string virtual_path = 11;
string virtual_target_path = 12;
string session_id = 13;
}
message ProviderEvent {

View file

@ -187,14 +187,14 @@ func (m *Manager) validateConfigs() error {
// NotifyFsEvent sends the fs event notifications using any defined notifier plugins
func (m *Manager) NotifyFsEvent(timestamp int64, action, username, fsPath, fsTargetPath, sshCmd, protocol, ip,
virtualPath, virtualTargetPath string, fileSize int64, err error,
virtualPath, virtualTargetPath, sessionID string, fileSize int64, err error,
) {
m.notifLock.RLock()
defer m.notifLock.RUnlock()
for _, n := range m.notifiers {
n.notifyFsAction(timestamp, action, username, fsPath, fsTargetPath, sshCmd, protocol, ip, virtualPath, virtualTargetPath,
fileSize, err)
n.notifyFsAction(timestamp, action, username, fsPath, fsTargetPath, sshCmd, protocol, ip, virtualPath,
virtualTargetPath, sessionID, fileSize, err)
}
}

View file

@ -73,7 +73,7 @@ func (c *Connection) Fileread(request *sftp.Request) (io.ReaderAt, error) {
return nil, err
}
if err := common.ExecutePreAction(&c.User, common.OperationPreDownload, p, request.Filepath, c.GetProtocol(), c.GetRemoteIP(), 0, 0); err != nil {
if err := common.ExecutePreAction(c.BaseConnection, common.OperationPreDownload, p, request.Filepath, 0, 0); err != nil {
c.Log(logger.LevelDebug, "download for file %#v denied by pre action: %v", request.Filepath, err)
return nil, c.GetPermissionDeniedError()
}
@ -349,7 +349,7 @@ func (c *Connection) handleSFTPUploadToNewFile(fs vfs.Fs, resolvedPath, filePath
return nil, c.GetQuotaExceededError()
}
if err := common.ExecutePreAction(&c.User, common.OperationPreUpload, resolvedPath, requestPath, c.GetProtocol(), c.GetRemoteIP(), 0, 0); err != nil {
if err := common.ExecutePreAction(c.BaseConnection, common.OperationPreUpload, resolvedPath, requestPath, 0, 0); err != nil {
c.Log(logger.LevelDebug, "upload for file %#v denied by pre action: %v", requestPath, err)
return nil, c.GetPermissionDeniedError()
}
@ -396,7 +396,7 @@ func (c *Connection) handleSFTPUploadToExistingFile(fs vfs.Fs, pflags sftp.FileO
return nil, err
}
if err := common.ExecutePreAction(&c.User, common.OperationPreUpload, resolvedPath, requestPath, c.GetProtocol(), c.GetRemoteIP(), fileSize, osFlags); err != nil {
if err := common.ExecutePreAction(c.BaseConnection, common.OperationPreUpload, resolvedPath, requestPath, fileSize, osFlags); err != nil {
c.Log(logger.LevelDebug, "upload for file %#v denied by pre action: %v", requestPath, err)
return nil, c.GetPermissionDeniedError()
}

View file

@ -219,8 +219,8 @@ func (c *scpCommand) handleUploadFile(fs vfs.Fs, resolvedPath, filePath string,
c.sendErrorMessage(fs, err)
return err
}
err := common.ExecutePreAction(&c.connection.User, common.OperationPreUpload, resolvedPath, requestPath,
c.connection.GetProtocol(), c.connection.GetRemoteIP(), fileSize, os.O_TRUNC)
err := common.ExecutePreAction(c.connection.BaseConnection, common.OperationPreUpload, resolvedPath, requestPath,
fileSize, os.O_TRUNC)
if err != nil {
c.connection.Log(logger.LevelDebug, "upload for file %#v denied by pre action: %v", requestPath, err)
err = c.connection.GetPermissionDeniedError()
@ -515,7 +515,7 @@ func (c *scpCommand) handleDownload(filePath string) error {
return common.ErrPermissionDenied
}
if err := common.ExecutePreAction(&c.connection.User, common.OperationPreDownload, p, filePath, c.connection.GetProtocol(), c.connection.GetRemoteIP(), 0, 0); err != nil {
if err := common.ExecutePreAction(c.connection.BaseConnection, common.OperationPreDownload, p, filePath, 0, 0); err != nil {
c.connection.Log(logger.LevelDebug, "download for file %#v denied by pre action: %v", filePath, err)
c.sendErrorMessage(fs, common.ErrPermissionDenied)
return common.ErrPermissionDenied

View file

@ -751,8 +751,8 @@ func (c *sshCommand) sendExitStatus(err error) {
targetPath = p
}
}
common.ExecuteActionNotification(&c.connection.User, common.OperationSSHCmd, cmdPath, vCmdPath, targetPath,
vTargetPath, c.command, common.ProtocolSSH, c.connection.GetRemoteIP(), 0, err)
common.ExecuteActionNotification(c.connection.BaseConnection, common.OperationSSHCmd, cmdPath, vCmdPath, targetPath,
vTargetPath, c.command, 0, err)
if err == nil {
logger.CommandLog(sshCommandLogSender, cmdPath, targetPath, c.connection.User.Username, "", c.connection.ID,
common.ProtocolSSH, -1, -1, "", "", c.connection.command, -1, c.connection.GetLocalAddress(),

View file

@ -147,8 +147,7 @@ func (f *webDavFile) Read(p []byte) (n int, err error) {
f.Connection.Log(logger.LevelWarn, "reading file %#v is not allowed", f.GetVirtualPath())
return 0, f.Connection.GetPermissionDeniedError()
}
err := common.ExecutePreAction(&f.Connection.User, common.OperationPreDownload, f.GetFsPath(), f.GetVirtualPath(),
f.Connection.GetProtocol(), f.Connection.GetRemoteIP(), 0, 0)
err := common.ExecutePreAction(f.Connection, common.OperationPreDownload, f.GetFsPath(), f.GetVirtualPath(), 0, 0)
if err != nil {
f.Connection.Log(logger.LevelDebug, "download for file %#v denied by pre action: %v", f.GetVirtualPath(), err)
return 0, f.Connection.GetPermissionDeniedError()

View file

@ -199,7 +199,7 @@ func (c *Connection) handleUploadToNewFile(fs vfs.Fs, resolvedPath, filePath, re
c.Log(logger.LevelInfo, "denying file write due to quota limits")
return nil, common.ErrQuotaExceeded
}
if err := common.ExecutePreAction(&c.User, common.OperationPreUpload, resolvedPath, requestPath, c.GetProtocol(), c.GetRemoteIP(), 0, 0); err != nil {
if err := common.ExecutePreAction(c.BaseConnection, common.OperationPreUpload, resolvedPath, requestPath, 0, 0); err != nil {
c.Log(logger.LevelDebug, "upload for file %#v denied by pre action: %v", requestPath, err)
return nil, c.GetPermissionDeniedError()
}
@ -228,7 +228,7 @@ func (c *Connection) handleUploadToExistingFile(fs vfs.Fs, resolvedPath, filePat
c.Log(logger.LevelInfo, "denying file write due to quota limits")
return nil, common.ErrQuotaExceeded
}
if err := common.ExecutePreAction(&c.User, common.OperationPreUpload, resolvedPath, requestPath, c.GetProtocol(), c.GetRemoteIP(),
if err := common.ExecutePreAction(c.BaseConnection, common.OperationPreUpload, resolvedPath, requestPath,
fileSize, os.O_TRUNC); err != nil {
c.Log(logger.LevelDebug, "upload for file %#v denied by pre action: %v", requestPath, err)
return nil, c.GetPermissionDeniedError()