plugins: improve notifier and searcher

This commit is contained in:
Nicola Murino 2021-10-20 19:39:49 +02:00
parent 3bbe67571f
commit 97d0a48557
No known key found for this signature in database
GPG key ID: 2F1FB59433D5A8CB
18 changed files with 861 additions and 388 deletions

View file

@ -54,7 +54,7 @@ func InitializeActionHandler(handler ActionHandler) {
func ExecutePreAction(user *dataprovider.User, operation, filePath, virtualPath, protocol, ip string, fileSize int64, func ExecutePreAction(user *dataprovider.User, operation, filePath, virtualPath, protocol, ip string, fileSize int64,
openFlags int, openFlags int,
) error { ) error {
plugin.Handler.NotifyFsEvent(time.Now(), operation, user.Username, filePath, "", "", protocol, ip, virtualPath, "", fileSize, nil) plugin.Handler.NotifyFsEvent(time.Now().UnixNano(), operation, user.Username, filePath, "", "", protocol, ip, virtualPath, "", fileSize, nil)
if !util.IsStringInSlice(operation, Config.Actions.ExecuteOn) { if !util.IsStringInSlice(operation, Config.Actions.ExecuteOn) {
// for pre-delete we execute the internal handling on error, so we must return errUnconfiguredAction. // 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 // Other pre action will deny the operation on error so if we have no configuration we must return
@ -73,7 +73,7 @@ func ExecutePreAction(user *dataprovider.User, operation, filePath, virtualPath,
func ExecuteActionNotification(user *dataprovider.User, operation, filePath, virtualPath, target, virtualTarget, sshCmd, func ExecuteActionNotification(user *dataprovider.User, operation, filePath, virtualPath, target, virtualTarget, sshCmd,
protocol, ip string, fileSize int64, err error, protocol, ip string, fileSize int64, err error,
) { ) {
plugin.Handler.NotifyFsEvent(time.Now(), operation, user.Username, filePath, target, sshCmd, protocol, ip, virtualPath, plugin.Handler.NotifyFsEvent(time.Now().UnixNano(), operation, user.Username, filePath, target, sshCmd, protocol, ip, virtualPath,
virtualTarget, fileSize, err) virtualTarget, fileSize, err)
notification := newActionNotification(user, operation, filePath, virtualPath, target, virtualTarget, sshCmd, protocol, notification := newActionNotification(user, operation, filePath, virtualPath, target, virtualTarget, sshCmd, protocol,
ip, fileSize, 0, err) ip, fileSize, 0, err)
@ -139,9 +139,9 @@ func newActionNotification(
} }
if err == ErrQuotaExceeded { if err == ErrQuotaExceeded {
status = 2 status = 3
} else if err != nil { } else if err != nil {
status = 0 status = 2
} }
return &ActionNotification{ return &ActionNotification{
@ -160,7 +160,7 @@ func newActionNotification(
Protocol: protocol, Protocol: protocol,
IP: ip, IP: ip,
OpenFlags: openFlags, OpenFlags: openFlags,
Timestamp: util.GetTimeAsMsSinceEpoch(time.Now()), Timestamp: time.Now().UnixNano(),
} }
} }

View file

@ -49,7 +49,7 @@ func TestNewActionNotification(t *testing.T) {
assert.Equal(t, user.Username, a.Username) assert.Equal(t, user.Username, a.Username)
assert.Equal(t, 0, len(a.Bucket)) assert.Equal(t, 0, len(a.Bucket))
assert.Equal(t, 0, len(a.Endpoint)) assert.Equal(t, 0, len(a.Endpoint))
assert.Equal(t, 0, a.Status) assert.Equal(t, 2, a.Status)
user.FsConfig.Provider = sdk.S3FilesystemProvider user.FsConfig.Provider = sdk.S3FilesystemProvider
a = newActionNotification(user, operationDownload, "path", "vpath", "target", "", "", ProtocolSSH, "", 123, 0, nil) a = newActionNotification(user, operationDownload, "path", "vpath", "target", "", "", ProtocolSSH, "", 123, 0, nil)
@ -61,7 +61,7 @@ func TestNewActionNotification(t *testing.T) {
a = newActionNotification(user, operationDownload, "path", "vpath", "target", "", "", ProtocolSCP, "", 123, 0, ErrQuotaExceeded) a = newActionNotification(user, operationDownload, "path", "vpath", "target", "", "", ProtocolSCP, "", 123, 0, ErrQuotaExceeded)
assert.Equal(t, "gcsbucket", a.Bucket) assert.Equal(t, "gcsbucket", a.Bucket)
assert.Equal(t, 0, len(a.Endpoint)) assert.Equal(t, 0, len(a.Endpoint))
assert.Equal(t, 2, a.Status) assert.Equal(t, 3, a.Status)
user.FsConfig.Provider = sdk.AzureBlobFilesystemProvider user.FsConfig.Provider = sdk.AzureBlobFilesystemProvider
a = newActionNotification(user, operationDownload, "path", "vpath", "target", "", "", ProtocolSCP, "", 123, 0, nil) a = newActionNotification(user, operationDownload, "path", "vpath", "target", "", "", ProtocolSCP, "", 123, 0, nil)

View file

@ -32,7 +32,7 @@ const (
) )
func executeAction(operation, executor, ip, objectType, objectName string, object plugin.Renderer) { func executeAction(operation, executor, ip, objectType, objectName string, object plugin.Renderer) {
plugin.Handler.NotifyProviderEvent(time.Now(), operation, executor, objectType, objectName, ip, object) plugin.Handler.NotifyProviderEvent(time.Now().UnixNano(), operation, executor, objectType, objectName, ip, object)
if config.Actions.Hook == "" { if config.Actions.Hook == "" {
return return
} }
@ -60,7 +60,7 @@ func executeAction(operation, executor, ip, objectType, objectName string, objec
q.Add("ip", ip) q.Add("ip", ip)
q.Add("object_type", objectType) q.Add("object_type", objectType)
q.Add("object_name", objectName) q.Add("object_name", objectName)
q.Add("timestamp", fmt.Sprintf("%v", util.GetTimeAsMsSinceEpoch(time.Now()))) q.Add("timestamp", fmt.Sprintf("%v", time.Now().UnixNano()))
url.RawQuery = q.Encode() url.RawQuery = q.Encode()
startTime := time.Now() startTime := time.Now()
resp, err := httpclient.RetryablePost(url.String(), "application/json", bytes.NewBuffer(dataAsJSON)) resp, err := httpclient.RetryablePost(url.String(), "application/json", bytes.NewBuffer(dataAsJSON))

View file

@ -105,7 +105,7 @@ func getMySQLConnectionString(redactedPwd bool) string {
if redactedPwd { if redactedPwd {
password = "[redacted]" password = "[redacted]"
} }
connectionString = fmt.Sprintf("%v:%v@tcp([%v]:%v)/%v?charset=utf8&interpolateParams=true&timeout=10s&tls=%v&writeTimeout=10s&readTimeout=10s", connectionString = fmt.Sprintf("%v:%v@tcp([%v]:%v)/%v?charset=utf8mb4&interpolateParams=true&timeout=10s&parseTime=true&tls=%v&writeTimeout=10s&readTimeout=10s",
config.Username, password, config.Host, config.Port, config.Name, getSSLMode()) config.Username, password, config.Host, config.Port, config.Name, getSSLMode())
} else { } else {
connectionString = config.ConnectionString connectionString = config.ConnectionString

View file

@ -42,11 +42,11 @@ If the `hook` defines a path to an external program, then this program can read
- `SFTPGO_ACTION_FS_PROVIDER`, `0` for local filesystem, `1` for S3 backend, `2` for Google Cloud Storage (GCS) backend, `3` for Azure Blob Storage backend, `4` for local encrypted backend, `5` for SFTP backend - `SFTPGO_ACTION_FS_PROVIDER`, `0` for local filesystem, `1` for S3 backend, `2` for Google Cloud Storage (GCS) backend, `3` for Azure Blob Storage backend, `4` for local encrypted backend, `5` for SFTP backend
- `SFTPGO_ACTION_BUCKET`, non-empty for S3, GCS and Azure backends - `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_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. 0 means a generic error occurred. 1 means no error, 2 means quota exceeded error - `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`, `DataRetention`
- `SFTPGO_ACTION_IP`, the action was executed from this IP address - `SFTPGO_ACTION_IP`, the action was executed from this IP address
- `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_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 milliseconds since epoch - `SFTPGO_ACTION_TIMESTAMP`, int64. Event timestamp as nanoseconds since epoch
Previous global environment variables aren't cleared when the script is called. Previous global environment variables aren't cleared when the script is called.
The program must finish within 30 seconds. The program must finish within 30 seconds.
@ -64,11 +64,11 @@ If the `hook` defines an HTTP URL then this URL will be invoked as HTTP POST. Th
- `fs_provider`, integer, `0` for local filesystem, `1` for S3 backend, `2` for Google Cloud Storage (GCS) backend, `3` for Azure Blob Storage backend, `4` for local encrypted backend, `5` for SFTP backend - `fs_provider`, integer, `0` for local filesystem, `1` for S3 backend, `2` for Google Cloud Storage (GCS) backend, `3` for Azure Blob Storage backend, `4` for local encrypted backend, `5` for SFTP backend
- `bucket`, string, inlcuded for S3, GCS and Azure backends - `bucket`, string, inlcuded for S3, GCS and Azure backends
- `endpoint`, string, included for S3, SFTP and Azure backend if configured - `endpoint`, string, included for S3, SFTP and Azure backend if configured
- `status`, integer. Status for `upload`, `download` and `ssh_cmd` actions. 0 means a generic error occurred. 1 means no error, 2 means quota exceeded error - `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`, `DataRetention`
- `ip`, string. The action was executed from this IP address - `ip`, string. The action was executed from this IP address
- `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 - `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 milliseconds since epoch - `timestamp`, int64. Event timestamp as nanoseconds since epoch
The HTTP hook will use the global configuration for HTTP clients and will respect the retry configurations. The HTTP hook will use the global configuration for HTTP clients and will respect the retry configurations.
@ -93,7 +93,7 @@ If the `hook` defines a path to an external program, then this program can read
- `SFTPGO_PROVIDER_OBJECT_NAME`, unique identifier for the affected object, for example username or key id - `SFTPGO_PROVIDER_OBJECT_NAME`, unique identifier for the affected object, for example username or key id
- `SFTPGO_PROVIDER_USERNAME`, the username that executed the action. There are two special usernames: `__self__` identifies a user/admin that updates itself and `__system__` identifies an action that does not have an explicit executor associated with it, for example users/admins can be added/updated by loading them from initial data - `SFTPGO_PROVIDER_USERNAME`, the username that executed the action. There are two special usernames: `__self__` identifies a user/admin that updates itself and `__system__` identifies an action that does not have an explicit executor associated with it, for example users/admins can be added/updated by loading them from initial data
- `SFTPGO_PROVIDER_IP`, the action was executed from this IP address - `SFTPGO_PROVIDER_IP`, the action was executed from this IP address
- `SFTPGO_PROVIDER_TIMESTAMP`, event timestamp as milliseconds since epoch - `SFTPGO_PROVIDER_TIMESTAMP`, event timestamp as nanoseconds since epoch
- `SFTPGO_PROVIDER_OBJECT`, object serialized as JSON with sensitive fields removed - `SFTPGO_PROVIDER_OBJECT`, object serialized as JSON with sensitive fields removed
Previous global environment variables aren't cleared when the script is called. Previous global environment variables aren't cleared when the script is called.

14
go.mod
View file

@ -3,11 +3,11 @@ module github.com/drakkan/sftpgo/v2
go 1.17 go 1.17
require ( require (
cloud.google.com/go/storage v1.18.1 cloud.google.com/go/storage v1.18.2
github.com/Azure/azure-storage-blob-go v0.14.0 github.com/Azure/azure-storage-blob-go v0.14.0
github.com/GehirnInc/crypt v0.0.0-20200316065508-bb7000b8a962 github.com/GehirnInc/crypt v0.0.0-20200316065508-bb7000b8a962
github.com/alexedwards/argon2id v0.0.0-20210511081203-7d35d68092b8 github.com/alexedwards/argon2id v0.0.0-20210511081203-7d35d68092b8
github.com/aws/aws-sdk-go v1.41.4 github.com/aws/aws-sdk-go v1.41.6
github.com/cockroachdb/cockroach-go/v2 v2.2.1 github.com/cockroachdb/cockroach-go/v2 v2.2.1
github.com/eikenb/pipeat v0.0.0-20210603033007-44fc3ffce52b github.com/eikenb/pipeat v0.0.0-20210603033007-44fc3ffce52b
github.com/fatih/color v1.13.0 // indirect github.com/fatih/color v1.13.0 // indirect
@ -33,7 +33,7 @@ require (
github.com/lib/pq v1.10.3 github.com/lib/pq v1.10.3
github.com/lithammer/shortuuid/v3 v3.0.7 github.com/lithammer/shortuuid/v3 v3.0.7
github.com/mattn/go-isatty v0.0.14 // indirect github.com/mattn/go-isatty v0.0.14 // indirect
github.com/mattn/go-sqlite3 v1.14.8 github.com/mattn/go-sqlite3 v1.14.9
github.com/mhale/smtpd v0.8.0 github.com/mhale/smtpd v0.8.0
github.com/miekg/dns v1.1.43 // indirect github.com/miekg/dns v1.1.43 // indirect
github.com/minio/sio v0.3.0 github.com/minio/sio v0.3.0
@ -44,7 +44,7 @@ require (
github.com/pkg/sftp v1.13.4 github.com/pkg/sftp v1.13.4
github.com/pquerna/otp v1.3.0 github.com/pquerna/otp v1.3.0
github.com/prometheus/client_golang v1.11.0 github.com/prometheus/client_golang v1.11.0
github.com/prometheus/common v0.31.1 // indirect github.com/prometheus/common v0.32.0 // indirect
github.com/rs/cors v1.8.0 github.com/rs/cors v1.8.0
github.com/rs/xid v1.3.0 github.com/rs/xid v1.3.0
github.com/rs/zerolog v1.25.0 github.com/rs/zerolog v1.25.0
@ -63,10 +63,10 @@ require (
gocloud.dev v0.24.0 gocloud.dev v0.24.0
golang.org/x/crypto v0.0.0-20210915214749-c084706c2272 golang.org/x/crypto v0.0.0-20210915214749-c084706c2272
golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f
golang.org/x/sys v0.0.0-20211015200801-69063c4bb744 golang.org/x/sys v0.0.0-20211020154033-fcb26fe61c20
golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac
google.golang.org/api v0.58.0 google.golang.org/api v0.59.0
google.golang.org/genproto v0.0.0-20211013025323-ce878158c4d4 // indirect google.golang.org/genproto v0.0.0-20211020151524-b7c3a969101a // indirect
google.golang.org/grpc v1.41.0 google.golang.org/grpc v1.41.0
google.golang.org/protobuf v1.27.1 google.golang.org/protobuf v1.27.1
gopkg.in/natefinch/lumberjack.v2 v2.0.0 gopkg.in/natefinch/lumberjack.v2 v2.0.0

30
go.sum
View file

@ -60,8 +60,8 @@ cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohl
cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs=
cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
cloud.google.com/go/storage v1.16.1/go.mod h1:LaNorbty3ehnU3rEjXSNV/NRgQA0O8Y+uh6bPe5UOk4= cloud.google.com/go/storage v1.16.1/go.mod h1:LaNorbty3ehnU3rEjXSNV/NRgQA0O8Y+uh6bPe5UOk4=
cloud.google.com/go/storage v1.18.1 h1:hfXX1gE2mvuwoS/weBfgH1Vr+efX0uLdxX2ETJ9g1JQ= cloud.google.com/go/storage v1.18.2 h1:5NQw6tOn3eMm0oE8vTkfjau18kjL79FlMjy/CHTpmoY=
cloud.google.com/go/storage v1.18.1/go.mod h1:FPalGc7eWSCKf26f2JwjrZhVibDE6pCDP19d1Pe2lB8= cloud.google.com/go/storage v1.18.2/go.mod h1:AiIj7BWXyhO5gGVmYJ+S8tbkCx3yb0IMjua8Aw4naVM=
cloud.google.com/go/trace v0.1.0/go.mod h1:wxEwsoeRVPbeSkt7ZC9nWCgmoKQRAoySN7XHW2AmI7g= cloud.google.com/go/trace v0.1.0/go.mod h1:wxEwsoeRVPbeSkt7ZC9nWCgmoKQRAoySN7XHW2AmI7g=
contrib.go.opencensus.io/exporter/aws v0.0.0-20200617204711-c478e41e60e9/go.mod h1:uu1P0UCM/6RbsMrgPa98ll8ZcHM858i/AD06a9aLRCA= contrib.go.opencensus.io/exporter/aws v0.0.0-20200617204711-c478e41e60e9/go.mod h1:uu1P0UCM/6RbsMrgPa98ll8ZcHM858i/AD06a9aLRCA=
contrib.go.opencensus.io/exporter/stackdriver v0.13.8/go.mod h1:huNtlWx75MwO7qMs0KrMxPZXzNNWebav1Sq/pm02JdQ= contrib.go.opencensus.io/exporter/stackdriver v0.13.8/go.mod h1:huNtlWx75MwO7qMs0KrMxPZXzNNWebav1Sq/pm02JdQ=
@ -137,8 +137,8 @@ github.com/aws/aws-sdk-go v1.15.27/go.mod h1:mFuSZ37Z9YOHbQEwBWztmVzqXrEkub65tZo
github.com/aws/aws-sdk-go v1.37.0/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro= github.com/aws/aws-sdk-go v1.37.0/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro=
github.com/aws/aws-sdk-go v1.38.68/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro= github.com/aws/aws-sdk-go v1.38.68/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro=
github.com/aws/aws-sdk-go v1.40.34/go.mod h1:585smgzpB/KqRA+K3y/NL/oYRqQvpNJYvLm+LY1U59Q= github.com/aws/aws-sdk-go v1.40.34/go.mod h1:585smgzpB/KqRA+K3y/NL/oYRqQvpNJYvLm+LY1U59Q=
github.com/aws/aws-sdk-go v1.41.4 h1:5xRzZp8LfBFfowMPxmoNsxLBZOY/NTH4EeI7q2F5eWE= github.com/aws/aws-sdk-go v1.41.6 h1:ojO1jWhE3lkJlTFQOq0rlWZ11q18LIdsZNtGJ07FFEA=
github.com/aws/aws-sdk-go v1.41.4/go.mod h1:585smgzpB/KqRA+K3y/NL/oYRqQvpNJYvLm+LY1U59Q= github.com/aws/aws-sdk-go v1.41.6/go.mod h1:585smgzpB/KqRA+K3y/NL/oYRqQvpNJYvLm+LY1U59Q=
github.com/aws/aws-sdk-go-v2 v1.7.0/go.mod h1:tb9wi5s61kTDA5qCkcDbt3KRVV74GGslQkl/DRdX/P4= github.com/aws/aws-sdk-go-v2 v1.7.0/go.mod h1:tb9wi5s61kTDA5qCkcDbt3KRVV74GGslQkl/DRdX/P4=
github.com/aws/aws-sdk-go-v2 v1.9.0/go.mod h1:cK/D0BBs0b/oWPIcX/Z/obahJK1TT7IPVjy53i/mX/4= github.com/aws/aws-sdk-go-v2 v1.9.0/go.mod h1:cK/D0BBs0b/oWPIcX/Z/obahJK1TT7IPVjy53i/mX/4=
github.com/aws/aws-sdk-go-v2/config v1.7.0/go.mod h1:w9+nMZ7soXCe5nT46Ri354SNhXDQ6v+V5wqDjnZE+GY= github.com/aws/aws-sdk-go-v2/config v1.7.0/go.mod h1:w9+nMZ7soXCe5nT46Ri354SNhXDQ6v+V5wqDjnZE+GY=
@ -592,8 +592,8 @@ github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Ky
github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y= github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y=
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
github.com/mattn/go-sqlite3 v1.14.8 h1:gDp86IdQsN/xWjIEmr9MF6o9mpksUgh0fu+9ByFxzIU= github.com/mattn/go-sqlite3 v1.14.9 h1:10HX2Td0ocZpYEjhilsuo6WWtUqttj2Kb0KtD86/KYA=
github.com/mattn/go-sqlite3 v1.14.8/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= github.com/mattn/go-sqlite3 v1.14.9/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/mhale/smtpd v0.8.0 h1:5JvdsehCg33PQrZBvFyDMMUDQmvbzVpZgKob7eYBJc0= github.com/mhale/smtpd v0.8.0 h1:5JvdsehCg33PQrZBvFyDMMUDQmvbzVpZgKob7eYBJc0=
@ -688,8 +688,8 @@ github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6T
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo=
github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc=
github.com/prometheus/common v0.31.1 h1:d18hG4PkHnNAKNMOmFuXFaiY8Us0nird/2m60uS1AMs= github.com/prometheus/common v0.32.0 h1:HRmM4uANZDAjdvbsdfOoqI5UDbjz0faKeMs/cGPKKI0=
github.com/prometheus/common v0.31.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= github.com/prometheus/common v0.32.0/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls=
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
@ -964,8 +964,9 @@ golang.org/x/sys v0.0.0-20210831042530-f4d43177bf5e/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210917161153-d61c044b1678/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210917161153-d61c044b1678/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211015200801-69063c4bb744 h1:KzbpndAYEM+4oHRp9JmB2ewj0NHHxO3Z0g7Gus2O1kk= golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211015200801-69063c4bb744/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211020154033-fcb26fe61c20 h1:NPtIbR2t8Mhg6UCbkTQMNMejkPpH6IvV4PdZnh1Mqpk=
golang.org/x/sys v0.0.0-20211020154033-fcb26fe61c20/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 h1:v+OssWQX+hTHEmOBgwxdZxK4zHq3yOs8F9J7mk0PY8E= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 h1:v+OssWQX+hTHEmOBgwxdZxK4zHq3yOs8F9J7mk0PY8E=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@ -1090,8 +1091,9 @@ google.golang.org/api v0.54.0/go.mod h1:7C4bFFOvVDGXjfDTAsgGwDgAxRDeQ4X8NvUedIt6
google.golang.org/api v0.55.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE= google.golang.org/api v0.55.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE=
google.golang.org/api v0.56.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE= google.golang.org/api v0.56.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE=
google.golang.org/api v0.57.0/go.mod h1:dVPlbZyBo2/OjBpmvNdpn2GRm6rPy75jyU7bmhdrMgI= google.golang.org/api v0.57.0/go.mod h1:dVPlbZyBo2/OjBpmvNdpn2GRm6rPy75jyU7bmhdrMgI=
google.golang.org/api v0.58.0 h1:MDkAbYIB1JpSgCTOCYYoIec/coMlKK4oVbpnBLLcyT0=
google.golang.org/api v0.58.0/go.mod h1:cAbP2FsxoGVNwtgNAmmn3y5G1TWAiVYRmg4yku3lv+E= google.golang.org/api v0.58.0/go.mod h1:cAbP2FsxoGVNwtgNAmmn3y5G1TWAiVYRmg4yku3lv+E=
google.golang.org/api v0.59.0 h1:fPfFO7gttlXYo2ALuD3HxJzh8vaF++4youI0BkFL6GE=
google.golang.org/api v0.59.0/go.mod h1:sT2boj7M9YJxZzgeZqXogmhfmRWDtPzT31xkieUbuZU=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
@ -1165,8 +1167,10 @@ google.golang.org/genproto v0.0.0-20210903162649-d08c68adba83/go.mod h1:eFjDcFEc
google.golang.org/genproto v0.0.0-20210909211513-a8c4777a87af/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= google.golang.org/genproto v0.0.0-20210909211513-a8c4777a87af/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
google.golang.org/genproto v0.0.0-20210917145530-b395a37504d4/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= google.golang.org/genproto v0.0.0-20210917145530-b395a37504d4/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
google.golang.org/genproto v0.0.0-20210924002016-3dee208752a0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/genproto v0.0.0-20210924002016-3dee208752a0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
google.golang.org/genproto v0.0.0-20211013025323-ce878158c4d4 h1:NBxB1XxiWpGqkPUiJ9PoBXkHV5A9+GohMOA+EmWoPbU= google.golang.org/genproto v0.0.0-20211008145708-270636b82663/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
google.golang.org/genproto v0.0.0-20211013025323-ce878158c4d4/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/genproto v0.0.0-20211016002631-37fc39342514/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
google.golang.org/genproto v0.0.0-20211020151524-b7c3a969101a h1:8maMHMQp9NroHXhc3HelFX9Ay2lWlXLcdH5mw5Biz0s=
google.golang.org/genproto v0.0.0-20211020151524-b7c3a969101a/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
google.golang.org/grpc v1.8.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.8.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=

View file

@ -10,12 +10,13 @@ tags:
- name: quota - name: quota
- name: folders - name: folders
- name: users - name: users
- name: users API
- name: data retention - name: data retention
- name: events
- name: users API
info: info:
title: SFTPGo title: SFTPGo
description: | description: |
SFTPGo allows to securely share your files over SFTP and optionally FTP/S and WebDAV too. SFTPGo allows to securely share your files over SFTP and optionally FTP/S and WebDAV as well.
Several storage backends are supported and they are configurable per user, so you can serve a local directory for a user and an S3 bucket (or part of it) for another one. Several storage backends are supported and they are configurable per user, so you can serve a local directory for a user and an S3 bucket (or part of it) for another one.
SFTPGo also supports virtual folders, a virtual folder can use any of the supported storage backends. So you can have, for example, an S3 user that exposes a GCS bucket (or part of it) on a specified path and an encrypted local filesystem on another one. SFTPGo also supports virtual folders, a virtual folder can use any of the supported storage backends. So you can have, for example, an S3 user that exposes a GCS bucket (or part of it) on a specified path and an encrypted local filesystem on another one.
Virtual folders can be private or shared among multiple users, for shared virtual folders you can define different quota limits for each user. Virtual folders can be private or shared among multiple users, for shared virtual folders you can define different quota limits for each user.
@ -1485,6 +1486,251 @@ paths:
$ref: '#/components/responses/InternalServerError' $ref: '#/components/responses/InternalServerError'
default: default:
$ref: '#/components/responses/DefaultResponse' $ref: '#/components/responses/DefaultResponse'
/events/fs:
get:
tags:
- events
summary: Get filesystem events
description: 'Returns an array with one or more filesystem events applying the specified filters. This API is only available if you configure an "eventsearcher" plugin'
operationId: get_fs_events
parameters:
- in: query
name: start_timestamp
schema:
type: integer
format: int64
minimum: 0
default: 0
required: false
description: 'the event timestamp, unix timestamp in nanoseconds, must be greater than or equal to the specified one. 0 or missing means omit this filter'
- in: query
name: end_timestamp
schema:
type: integer
format: int64
minimum: 0
default: 0
required: false
description: 'the event timestamp, unix timestamp in nanoseconds, must be less than or equal to the specified one. 0 or missing means omit this filter'
- in: query
name: actions
schema:
type: array
items:
$ref: '#/components/schemas/FsEventAction'
description: 'the event action must be included among those specified. Empty or missing means omit this filter. Actions must be specified comma separated'
explode: false
required: false
- in: query
name: username
schema:
type: string
description: 'the event username must be the same as the one specified. Empty or missing means omit this filter'
required: false
- in: query
name: ip
schema:
type: string
description: 'the event IP must be the same as the one specified. Empty or missing means omit this filter'
required: false
- in: query
name: ssh_cmd
schema:
type: string
description: 'the event SSH command must be the same as the one specified. Empty or missing means omit this filter'
required: false
- in: query
name: protocols
schema:
type: array
items:
$ref: '#/components/schemas/EventProtocols'
description: 'the event protocol must be included among those specified. Empty or missing means omit this filter. Values must be specified comma separated'
explode: false
required: false
- in: query
name: statuses
schema:
type: array
items:
$ref: '#/components/schemas/FsEventStatus'
description: 'the event status must be included among those specified. Empty or missing means omit this filter. Values must be specified comma separated'
explode: false
required: false
- in: query
name: instance_ids
schema:
type: array
items:
type: string
description: 'the event instance id must be included among those specified. Empty or missing means omit this filter. Values must be specified comma separated'
explode: false
required: false
- in: query
name: exclude_ids
schema:
type: array
items:
type: string
description: 'the event id must not be included among those specified. This is useful for cursor based pagination. Empty or missing means omit this filter. Values must be specified comma separated'
explode: false
required: false
- in: query
name: limit
schema:
type: integer
minimum: 1
maximum: 1000
default: 100
required: false
description: 'The maximum number of items to return. Max value is 500, default is 100'
- in: query
name: order
required: false
description: Ordering events by timestamp. Default DESC
schema:
type: string
enum:
- ASC
- DESC
example: DESC
responses:
'200':
description: successful operation
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/FsEvent'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'500':
$ref: '#/components/responses/InternalServerError'
default:
$ref: '#/components/responses/DefaultResponse'
/events/provider:
get:
tags:
- events
summary: Get provider events
description: 'Returns an array with one or more provider events applying the specified filters. This API is only available if you configure an "eventsearcher" plugin'
operationId: get_provider_events
parameters:
- in: query
name: start_timestamp
schema:
type: integer
format: int64
minimum: 0
default: 0
required: false
description: 'the event timestamp, unix timestamp in nanoseconds, must be greater than or equal to the specified one. 0 or missing means omit this filter'
- in: query
name: end_timestamp
schema:
type: integer
format: int64
minimum: 0
default: 0
required: false
description: 'the event timestamp, unix timestamp in nanoseconds, must be less than or equal to the specified one. 0 or missing means omit this filter'
- in: query
name: actions
schema:
type: array
items:
$ref: '#/components/schemas/ProviderEventAction'
description: 'the event action must be included among those specified. Empty or missing means omit this filter. Actions must be specified comma separated'
explode: false
required: false
- in: query
name: username
schema:
type: string
description: 'the event username must be the same as the one specified. Empty or missing means omit this filter'
required: false
- in: query
name: ip
schema:
type: string
description: 'the event IP must be the same as the one specified. Empty or missing means omit this filter'
required: false
- in: query
name: object_name
schema:
type: string
description: 'the event object name must be the same as the one specified. Empty or missing means omit this filter'
required: false
- in: query
name: object_types
schema:
type: array
items:
$ref: '#/components/schemas/ProviderEventObjectType'
description: 'the event object type must be included among those specified. Empty or missing means omit this filter. Values must be specified comma separated'
explode: false
required: false
- in: query
name: instance_ids
schema:
type: array
items:
type: string
description: 'the event instance id must be included among those specified. Empty or missing means omit this filter. Values must be specified comma separated'
explode: false
required: false
- in: query
name: exclude_ids
schema:
type: array
items:
type: string
description: 'the event id must not be included among those specified. This is useful for cursor based pagination. Empty or missing means omit this filter. Values must be specified comma separated'
explode: false
required: false
- in: query
name: limit
schema:
type: integer
minimum: 1
maximum: 1000
default: 100
required: false
description: 'The maximum number of items to return. Max value is 500, default is 100'
- in: query
name: order
required: false
description: Ordering events by timestamp. Default DESC
schema:
type: string
enum:
- ASC
- DESC
example: DESC
responses:
'200':
description: successful operation
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/ProviderEvent'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'500':
$ref: '#/components/responses/InternalServerError'
default:
$ref: '#/components/responses/DefaultResponse'
/apikeys: /apikeys:
get: get:
security: security:
@ -3214,6 +3460,24 @@ components:
* `SSH` - includes both SFTP and SSH commands * `SSH` - includes both SFTP and SSH commands
* `FTP` - plain FTP and FTPES/FTPS * `FTP` - plain FTP and FTPES/FTPS
* `HTTP` - WebClient/REST API * `HTTP` - WebClient/REST API
EventProtocols:
type: string
enum:
- SSH
- SFTP
- SCP
- FTP
- DAV
- HTTP
- DataRetention
description: |
Protocols:
* `SSH` - SSH commands
* `SFTP` - SFTP protocol
* `FTP` - plain FTP and FTPES/FTPS
* `DAV` - WebDAV
* `HTTP` - WebClient/REST API
* `DataRetention` - the event is generated by a data retention check
WebClientOptions: WebClientOptions:
type: string type: string
enum: enum:
@ -3263,6 +3527,39 @@ components:
- LDAPUser - LDAPUser
- OSUser - OSUser
description: This is an hint for authentication plugins. It is ignored when using SFTPGo internal authentication description: This is an hint for authentication plugins. It is ignored when using SFTPGo internal authentication
FsEventStatus:
type: integer
enum:
- 1
- 2
- 3
description: >
Event status:
* `1` - no error
* `2` - generic error
* `3` - quota exceeded error
FsEventAction:
type: string
enum:
- download
- upload
- delete
- rename
- mkdir
- rmdir
- ssh_cmd
ProviderEventAction:
type: string
enum:
- add
- update
- delete
ProviderEventObjectType:
type: string
enum:
- user
- admin
- api_key
TOTPConfig: TOTPConfig:
type: object type: object
properties: properties:
@ -4254,6 +4551,61 @@ components:
last_modified: last_modified:
type: string type: string
format: date-time format: date-time
FsEvent:
type: object
properties:
id:
type: string
timestamp:
type: integer
format: int64
description: 'unix timestamp in nanoseconds'
action:
$ref: '#/components/schemas/FsEventAction'
username:
type: string
fs_path:
type: string
fs_target_path:
type: string
virtual_path:
type: string
virtual_target_path:
type: string
ssh_cmd:
type: string
file_size:
type: integer
format: int64
status:
$ref: '#/components/schemas/FsEventStatus'
protocol:
$ref: '#/components/schemas/EventProtocols'
ip:
type: string
instance_id:
type: string
ProviderEvent:
type: object
properties:
id:
type: string
timestamp:
type: integer
format: int64
description: 'unix timestamp in nanoseconds'
action:
$ref: '#/components/schemas/ProviderEventAction'
username:
type: string
ip:
type: string
object_type:
$ref: '#/components/schemas/ProviderEventObjectType'
object_name:
type: string
instance_id:
type: string
ApiResponse: ApiResponse:
type: object type: object
properties: properties:

View file

@ -4,7 +4,6 @@ package eventsearcher
import ( import (
"context" "context"
"time"
"github.com/hashicorp/go-plugin" "github.com/hashicorp/go-plugin"
"google.golang.org/grpc" "google.golang.org/grpc"
@ -31,10 +30,10 @@ var PluginMap = map[string]plugin.Plugin{
// Searcher defines the interface for events search plugins // Searcher defines the interface for events search plugins
type Searcher interface { type Searcher interface {
SearchFsEvents(startTimestamp, endTimestamp time.Time, action, username, ip, sshCmd, protocol, SearchFsEvents(startTimestamp, endTimestamp int64, username, ip, sshCmd string, actions, protocols,
instanceID, continuationToken string, status, limit int) (string, []byte, error) instanceIDs, excludeIDs []string, statuses []int32, limit, order int) ([]byte, []string, []string, error)
SearchProviderEvents(startTimestamp, endTimestamp time.Time, action, username, ip, objectType, SearchProviderEvents(startTimestamp, endTimestamp int64, username, ip, objectName string,
objectName, instanceID, continuationToken string, limit int) (string, []byte, error) limit, order int, actions, objectTypes, instanceIDs, excludeIDs []string) ([]byte, []string, []string, error)
} }
// Plugin defines the implementation to serve/connect to a notifier plugin // Plugin defines the implementation to serve/connect to a notifier plugin

View file

@ -4,13 +4,11 @@ import (
"context" "context"
"time" "time"
"google.golang.org/protobuf/types/known/timestamppb"
"github.com/drakkan/sftpgo/v2/sdk/plugin/eventsearcher/proto" "github.com/drakkan/sftpgo/v2/sdk/plugin/eventsearcher/proto"
) )
const ( const (
rpcTimeout = 30 * time.Second rpcTimeout = 20 * time.Second
) )
// GRPCClient is an implementation of Notifier interface that talks over RPC. // GRPCClient is an implementation of Notifier interface that talks over RPC.
@ -19,54 +17,58 @@ type GRPCClient struct {
} }
// SearchFsEvents implements the Searcher interface // SearchFsEvents implements the Searcher interface
func (c *GRPCClient) SearchFsEvents(startTimestamp, endTimestamp time.Time, action, username, ip, sshCmd, protocol, func (c *GRPCClient) SearchFsEvents(startTimestamp, endTimestamp int64, username, ip, sshCmd string, actions,
instanceID, continuationToken string, status, limit int) (string, []byte, error) { protocols, instanceIDs, excludeIDs []string, statuses []int32, limit, order int,
) ([]byte, error) {
ctx, cancel := context.WithTimeout(context.Background(), rpcTimeout) ctx, cancel := context.WithTimeout(context.Background(), rpcTimeout)
defer cancel() defer cancel()
resp, err := c.client.SearchFsEvents(ctx, &proto.FsEventsFilter{ resp, err := c.client.SearchFsEvents(ctx, &proto.FsEventsFilter{
StartTimestamp: timestamppb.New(startTimestamp), StartTimestamp: startTimestamp,
EndTimestamp: timestamppb.New(endTimestamp), EndTimestamp: endTimestamp,
Action: action, Actions: actions,
Username: username, Username: username,
Ip: ip, Ip: ip,
SshCmd: sshCmd, SshCmd: sshCmd,
Protocol: protocol, Protocols: protocols,
InstanceId: instanceID, InstanceIds: instanceIDs,
ContinuationToken: continuationToken, Statuses: statuses,
Status: int32(status), Limit: int32(limit),
Limit: int32(limit), Order: proto.FsEventsFilter_Order(order),
ExcludeIds: excludeIDs,
}) })
if err != nil { if err != nil {
return "", nil, err return nil, err
} }
return resp.ContinuationToken, resp.ResponseData, nil return resp.Data, nil
} }
// SearchProviderEvents implements the Searcher interface // SearchProviderEvents implements the Searcher interface
func (c *GRPCClient) SearchProviderEvents(startTimestamp, endTimestamp time.Time, action, username, ip, objectType, func (c *GRPCClient) SearchProviderEvents(startTimestamp, endTimestamp int64, username, ip, objectName string,
objectName, instanceID, continuationToken string, limit int) (string, []byte, error) { limit, order int, actions, objectTypes, instanceIDs, excludeIDs []string,
) ([]byte, error) {
ctx, cancel := context.WithTimeout(context.Background(), rpcTimeout) ctx, cancel := context.WithTimeout(context.Background(), rpcTimeout)
defer cancel() defer cancel()
resp, err := c.client.SearchProviderEvents(ctx, &proto.ProviderEventsFilter{ resp, err := c.client.SearchProviderEvents(ctx, &proto.ProviderEventsFilter{
StartTimestamp: timestamppb.New(startTimestamp), StartTimestamp: startTimestamp,
EndTimestamp: timestamppb.New(endTimestamp), EndTimestamp: endTimestamp,
Action: action, Actions: actions,
Username: username, Username: username,
Ip: ip, Ip: ip,
ObjectType: objectType, ObjectTypes: objectTypes,
ObjectName: objectName, ObjectName: objectName,
InstanceId: instanceID, InstanceIds: instanceIDs,
ContinuationToken: continuationToken, Limit: int32(limit),
Limit: int32(limit), Order: proto.ProviderEventsFilter_Order(order),
ExcludeIds: excludeIDs,
}) })
if err != nil { if err != nil {
return "", nil, err return nil, err
} }
return resp.ContinuationToken, resp.ResponseData, nil return resp.Data, nil
} }
// GRPCServer defines the gRPC server that GRPCClient talks to. // GRPCServer defines the gRPC server that GRPCClient talks to.
@ -76,24 +78,26 @@ type GRPCServer struct {
// SearchFsEvents implement the server side fs events search method // SearchFsEvents implement the server side fs events search method
func (s *GRPCServer) SearchFsEvents(ctx context.Context, req *proto.FsEventsFilter) (*proto.SearchResponse, error) { func (s *GRPCServer) SearchFsEvents(ctx context.Context, req *proto.FsEventsFilter) (*proto.SearchResponse, error) {
continuationToken, responseData, err := s.Impl.SearchFsEvents(req.StartTimestamp.AsTime(), responseData, sameTsAtStart, sameTsAtEnd, err := s.Impl.SearchFsEvents(req.StartTimestamp,
req.EndTimestamp.AsTime(), req.Action, req.Username, req.Ip, req.SshCmd, req.Protocol, req.InstanceId, req.EndTimestamp, req.Username, req.Ip, req.SshCmd, req.Actions, req.Protocols, req.InstanceIds,
req.ContinuationToken, int(req.Status), int(req.Limit)) req.ExcludeIds, req.Statuses, int(req.Limit), int(req.Order))
return &proto.SearchResponse{ return &proto.SearchResponse{
ContinuationToken: continuationToken, Data: responseData,
ResponseData: responseData, SameTsAtStart: sameTsAtStart,
SameTsAtEnd: sameTsAtEnd,
}, err }, err
} }
// SearchProviderEvents implement the server side provider events search method // SearchProviderEvents implement the server side provider events search method
func (s *GRPCServer) SearchProviderEvents(ctx context.Context, req *proto.ProviderEventsFilter) (*proto.SearchResponse, error) { func (s *GRPCServer) SearchProviderEvents(ctx context.Context, req *proto.ProviderEventsFilter) (*proto.SearchResponse, error) {
continuationToken, responseData, err := s.Impl.SearchProviderEvents(req.StartTimestamp.AsTime(), responseData, sameTsAtStart, sameTsAtEnd, err := s.Impl.SearchProviderEvents(req.StartTimestamp,
req.EndTimestamp.AsTime(), req.Action, req.Username, req.Ip, req.ObjectType, req.ObjectName, req.EndTimestamp, req.Username, req.Ip, req.ObjectName, int(req.Limit),
req.InstanceId, req.ContinuationToken, int(req.Limit)) int(req.Order), req.Actions, req.ObjectTypes, req.InstanceIds, req.ExcludeIds)
return &proto.SearchResponse{ return &proto.SearchResponse{
ContinuationToken: continuationToken, Data: responseData,
ResponseData: responseData, SameTsAtStart: sameTsAtStart,
SameTsAtEnd: sameTsAtEnd,
}, err }, err
} }

View file

@ -13,7 +13,6 @@ import (
status "google.golang.org/grpc/status" status "google.golang.org/grpc/status"
protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl" protoimpl "google.golang.org/protobuf/runtime/protoimpl"
timestamppb "google.golang.org/protobuf/types/known/timestamppb"
reflect "reflect" reflect "reflect"
sync "sync" sync "sync"
) )
@ -25,22 +24,115 @@ const (
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
) )
type FsEventsFilter_Order int32
const (
FsEventsFilter_DESC FsEventsFilter_Order = 0
FsEventsFilter_ASC FsEventsFilter_Order = 1
)
// Enum value maps for FsEventsFilter_Order.
var (
FsEventsFilter_Order_name = map[int32]string{
0: "DESC",
1: "ASC",
}
FsEventsFilter_Order_value = map[string]int32{
"DESC": 0,
"ASC": 1,
}
)
func (x FsEventsFilter_Order) Enum() *FsEventsFilter_Order {
p := new(FsEventsFilter_Order)
*p = x
return p
}
func (x FsEventsFilter_Order) String() string {
return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
}
func (FsEventsFilter_Order) Descriptor() protoreflect.EnumDescriptor {
return file_eventsearcher_proto_search_proto_enumTypes[0].Descriptor()
}
func (FsEventsFilter_Order) Type() protoreflect.EnumType {
return &file_eventsearcher_proto_search_proto_enumTypes[0]
}
func (x FsEventsFilter_Order) Number() protoreflect.EnumNumber {
return protoreflect.EnumNumber(x)
}
// Deprecated: Use FsEventsFilter_Order.Descriptor instead.
func (FsEventsFilter_Order) EnumDescriptor() ([]byte, []int) {
return file_eventsearcher_proto_search_proto_rawDescGZIP(), []int{0, 0}
}
type ProviderEventsFilter_Order int32
const (
ProviderEventsFilter_DESC ProviderEventsFilter_Order = 0
ProviderEventsFilter_ASC ProviderEventsFilter_Order = 1
)
// Enum value maps for ProviderEventsFilter_Order.
var (
ProviderEventsFilter_Order_name = map[int32]string{
0: "DESC",
1: "ASC",
}
ProviderEventsFilter_Order_value = map[string]int32{
"DESC": 0,
"ASC": 1,
}
)
func (x ProviderEventsFilter_Order) Enum() *ProviderEventsFilter_Order {
p := new(ProviderEventsFilter_Order)
*p = x
return p
}
func (x ProviderEventsFilter_Order) String() string {
return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
}
func (ProviderEventsFilter_Order) Descriptor() protoreflect.EnumDescriptor {
return file_eventsearcher_proto_search_proto_enumTypes[1].Descriptor()
}
func (ProviderEventsFilter_Order) Type() protoreflect.EnumType {
return &file_eventsearcher_proto_search_proto_enumTypes[1]
}
func (x ProviderEventsFilter_Order) Number() protoreflect.EnumNumber {
return protoreflect.EnumNumber(x)
}
// Deprecated: Use ProviderEventsFilter_Order.Descriptor instead.
func (ProviderEventsFilter_Order) EnumDescriptor() ([]byte, []int) {
return file_eventsearcher_proto_search_proto_rawDescGZIP(), []int{1, 0}
}
type FsEventsFilter struct { type FsEventsFilter struct {
state protoimpl.MessageState state protoimpl.MessageState
sizeCache protoimpl.SizeCache sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields unknownFields protoimpl.UnknownFields
StartTimestamp *timestamppb.Timestamp `protobuf:"bytes,1,opt,name=start_timestamp,json=startTimestamp,proto3" json:"start_timestamp,omitempty"` StartTimestamp int64 `protobuf:"varint,1,opt,name=start_timestamp,json=startTimestamp,proto3" json:"start_timestamp,omitempty"`
EndTimestamp *timestamppb.Timestamp `protobuf:"bytes,2,opt,name=end_timestamp,json=endTimestamp,proto3" json:"end_timestamp,omitempty"` EndTimestamp int64 `protobuf:"varint,2,opt,name=end_timestamp,json=endTimestamp,proto3" json:"end_timestamp,omitempty"`
Action string `protobuf:"bytes,3,opt,name=action,proto3" json:"action,omitempty"` Actions []string `protobuf:"bytes,3,rep,name=actions,proto3" json:"actions,omitempty"`
Username string `protobuf:"bytes,4,opt,name=username,proto3" json:"username,omitempty"` Username string `protobuf:"bytes,4,opt,name=username,proto3" json:"username,omitempty"`
Ip string `protobuf:"bytes,5,opt,name=ip,proto3" json:"ip,omitempty"` Ip string `protobuf:"bytes,5,opt,name=ip,proto3" json:"ip,omitempty"`
SshCmd string `protobuf:"bytes,6,opt,name=ssh_cmd,json=sshCmd,proto3" json:"ssh_cmd,omitempty"` SshCmd string `protobuf:"bytes,6,opt,name=ssh_cmd,json=sshCmd,proto3" json:"ssh_cmd,omitempty"`
Protocol string `protobuf:"bytes,7,opt,name=protocol,proto3" json:"protocol,omitempty"` Protocols []string `protobuf:"bytes,7,rep,name=protocols,proto3" json:"protocols,omitempty"`
Status int32 `protobuf:"varint,8,opt,name=status,proto3" json:"status,omitempty"` Statuses []int32 `protobuf:"varint,8,rep,packed,name=statuses,proto3" json:"statuses,omitempty"`
InstanceId string `protobuf:"bytes,9,opt,name=instance_id,json=instanceId,proto3" json:"instance_id,omitempty"` InstanceIds []string `protobuf:"bytes,9,rep,name=instance_ids,json=instanceIds,proto3" json:"instance_ids,omitempty"`
Limit int32 `protobuf:"varint,10,opt,name=limit,proto3" json:"limit,omitempty"` Limit int32 `protobuf:"varint,10,opt,name=limit,proto3" json:"limit,omitempty"`
ContinuationToken string `protobuf:"bytes,11,opt,name=continuation_token,json=continuationToken,proto3" json:"continuation_token,omitempty"` ExcludeIds []string `protobuf:"bytes,11,rep,name=exclude_ids,json=excludeIds,proto3" json:"exclude_ids,omitempty"`
Order FsEventsFilter_Order `protobuf:"varint,12,opt,name=order,proto3,enum=proto.FsEventsFilter_Order" json:"order,omitempty"`
} }
func (x *FsEventsFilter) Reset() { func (x *FsEventsFilter) Reset() {
@ -75,25 +167,25 @@ func (*FsEventsFilter) Descriptor() ([]byte, []int) {
return file_eventsearcher_proto_search_proto_rawDescGZIP(), []int{0} return file_eventsearcher_proto_search_proto_rawDescGZIP(), []int{0}
} }
func (x *FsEventsFilter) GetStartTimestamp() *timestamppb.Timestamp { func (x *FsEventsFilter) GetStartTimestamp() int64 {
if x != nil { if x != nil {
return x.StartTimestamp return x.StartTimestamp
} }
return nil return 0
} }
func (x *FsEventsFilter) GetEndTimestamp() *timestamppb.Timestamp { func (x *FsEventsFilter) GetEndTimestamp() int64 {
if x != nil { if x != nil {
return x.EndTimestamp return x.EndTimestamp
} }
return nil return 0
} }
func (x *FsEventsFilter) GetAction() string { func (x *FsEventsFilter) GetActions() []string {
if x != nil { if x != nil {
return x.Action return x.Actions
} }
return "" return nil
} }
func (x *FsEventsFilter) GetUsername() string { func (x *FsEventsFilter) GetUsername() string {
@ -117,25 +209,25 @@ func (x *FsEventsFilter) GetSshCmd() string {
return "" return ""
} }
func (x *FsEventsFilter) GetProtocol() string { func (x *FsEventsFilter) GetProtocols() []string {
if x != nil { if x != nil {
return x.Protocol return x.Protocols
} }
return "" return nil
} }
func (x *FsEventsFilter) GetStatus() int32 { func (x *FsEventsFilter) GetStatuses() []int32 {
if x != nil { if x != nil {
return x.Status return x.Statuses
} }
return 0 return nil
} }
func (x *FsEventsFilter) GetInstanceId() string { func (x *FsEventsFilter) GetInstanceIds() []string {
if x != nil { if x != nil {
return x.InstanceId return x.InstanceIds
} }
return "" return nil
} }
func (x *FsEventsFilter) GetLimit() int32 { func (x *FsEventsFilter) GetLimit() int32 {
@ -145,11 +237,18 @@ func (x *FsEventsFilter) GetLimit() int32 {
return 0 return 0
} }
func (x *FsEventsFilter) GetContinuationToken() string { func (x *FsEventsFilter) GetExcludeIds() []string {
if x != nil { if x != nil {
return x.ContinuationToken return x.ExcludeIds
} }
return "" return nil
}
func (x *FsEventsFilter) GetOrder() FsEventsFilter_Order {
if x != nil {
return x.Order
}
return FsEventsFilter_DESC
} }
type ProviderEventsFilter struct { type ProviderEventsFilter struct {
@ -157,16 +256,17 @@ type ProviderEventsFilter struct {
sizeCache protoimpl.SizeCache sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields unknownFields protoimpl.UnknownFields
StartTimestamp *timestamppb.Timestamp `protobuf:"bytes,1,opt,name=start_timestamp,json=startTimestamp,proto3" json:"start_timestamp,omitempty"` StartTimestamp int64 `protobuf:"varint,1,opt,name=start_timestamp,json=startTimestamp,proto3" json:"start_timestamp,omitempty"`
EndTimestamp *timestamppb.Timestamp `protobuf:"bytes,2,opt,name=end_timestamp,json=endTimestamp,proto3" json:"end_timestamp,omitempty"` EndTimestamp int64 `protobuf:"varint,2,opt,name=end_timestamp,json=endTimestamp,proto3" json:"end_timestamp,omitempty"`
Action string `protobuf:"bytes,3,opt,name=action,proto3" json:"action,omitempty"` Actions []string `protobuf:"bytes,3,rep,name=actions,proto3" json:"actions,omitempty"`
Username string `protobuf:"bytes,4,opt,name=username,proto3" json:"username,omitempty"` Username string `protobuf:"bytes,4,opt,name=username,proto3" json:"username,omitempty"`
Ip string `protobuf:"bytes,5,opt,name=ip,proto3" json:"ip,omitempty"` Ip string `protobuf:"bytes,5,opt,name=ip,proto3" json:"ip,omitempty"`
ObjectType string `protobuf:"bytes,6,opt,name=object_type,json=objectType,proto3" json:"object_type,omitempty"` ObjectTypes []string `protobuf:"bytes,6,rep,name=object_types,json=objectTypes,proto3" json:"object_types,omitempty"`
ObjectName string `protobuf:"bytes,7,opt,name=object_name,json=objectName,proto3" json:"object_name,omitempty"` ObjectName string `protobuf:"bytes,7,opt,name=object_name,json=objectName,proto3" json:"object_name,omitempty"`
InstanceId string `protobuf:"bytes,8,opt,name=instance_id,json=instanceId,proto3" json:"instance_id,omitempty"` InstanceIds []string `protobuf:"bytes,8,rep,name=instance_ids,json=instanceIds,proto3" json:"instance_ids,omitempty"`
Limit int32 `protobuf:"varint,9,opt,name=limit,proto3" json:"limit,omitempty"` Limit int32 `protobuf:"varint,9,opt,name=limit,proto3" json:"limit,omitempty"`
ContinuationToken string `protobuf:"bytes,10,opt,name=continuation_token,json=continuationToken,proto3" json:"continuation_token,omitempty"` Order ProviderEventsFilter_Order `protobuf:"varint,10,opt,name=order,proto3,enum=proto.ProviderEventsFilter_Order" json:"order,omitempty"`
ExcludeIds []string `protobuf:"bytes,11,rep,name=exclude_ids,json=excludeIds,proto3" json:"exclude_ids,omitempty"`
} }
func (x *ProviderEventsFilter) Reset() { func (x *ProviderEventsFilter) Reset() {
@ -201,25 +301,25 @@ func (*ProviderEventsFilter) Descriptor() ([]byte, []int) {
return file_eventsearcher_proto_search_proto_rawDescGZIP(), []int{1} return file_eventsearcher_proto_search_proto_rawDescGZIP(), []int{1}
} }
func (x *ProviderEventsFilter) GetStartTimestamp() *timestamppb.Timestamp { func (x *ProviderEventsFilter) GetStartTimestamp() int64 {
if x != nil { if x != nil {
return x.StartTimestamp return x.StartTimestamp
} }
return nil return 0
} }
func (x *ProviderEventsFilter) GetEndTimestamp() *timestamppb.Timestamp { func (x *ProviderEventsFilter) GetEndTimestamp() int64 {
if x != nil { if x != nil {
return x.EndTimestamp return x.EndTimestamp
} }
return nil return 0
} }
func (x *ProviderEventsFilter) GetAction() string { func (x *ProviderEventsFilter) GetActions() []string {
if x != nil { if x != nil {
return x.Action return x.Actions
} }
return "" return nil
} }
func (x *ProviderEventsFilter) GetUsername() string { func (x *ProviderEventsFilter) GetUsername() string {
@ -236,11 +336,11 @@ func (x *ProviderEventsFilter) GetIp() string {
return "" return ""
} }
func (x *ProviderEventsFilter) GetObjectType() string { func (x *ProviderEventsFilter) GetObjectTypes() []string {
if x != nil { if x != nil {
return x.ObjectType return x.ObjectTypes
} }
return "" return nil
} }
func (x *ProviderEventsFilter) GetObjectName() string { func (x *ProviderEventsFilter) GetObjectName() string {
@ -250,11 +350,11 @@ func (x *ProviderEventsFilter) GetObjectName() string {
return "" return ""
} }
func (x *ProviderEventsFilter) GetInstanceId() string { func (x *ProviderEventsFilter) GetInstanceIds() []string {
if x != nil { if x != nil {
return x.InstanceId return x.InstanceIds
} }
return "" return nil
} }
func (x *ProviderEventsFilter) GetLimit() int32 { func (x *ProviderEventsFilter) GetLimit() int32 {
@ -264,11 +364,18 @@ func (x *ProviderEventsFilter) GetLimit() int32 {
return 0 return 0
} }
func (x *ProviderEventsFilter) GetContinuationToken() string { func (x *ProviderEventsFilter) GetOrder() ProviderEventsFilter_Order {
if x != nil { if x != nil {
return x.ContinuationToken return x.Order
} }
return "" return ProviderEventsFilter_DESC
}
func (x *ProviderEventsFilter) GetExcludeIds() []string {
if x != nil {
return x.ExcludeIds
}
return nil
} }
type SearchResponse struct { type SearchResponse struct {
@ -276,8 +383,9 @@ type SearchResponse struct {
sizeCache protoimpl.SizeCache sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields unknownFields protoimpl.UnknownFields
ContinuationToken string `protobuf:"bytes,1,opt,name=continuation_token,json=continuationToken,proto3" json:"continuation_token,omitempty"` Data []byte `protobuf:"bytes,1,opt,name=data,proto3" json:"data,omitempty"` // JSON serialized response to return
ResponseData []byte `protobuf:"bytes,2,opt,name=response_data,json=responseData,proto3" json:"response_data,omitempty"` // JSON serialized response to return SameTsAtStart []string `protobuf:"bytes,2,rep,name=same_ts_at_start,json=sameTsAtStart,proto3" json:"same_ts_at_start,omitempty"`
SameTsAtEnd []string `protobuf:"bytes,3,rep,name=same_ts_at_end,json=sameTsAtEnd,proto3" json:"same_ts_at_end,omitempty"`
} }
func (x *SearchResponse) Reset() { func (x *SearchResponse) Reset() {
@ -312,16 +420,23 @@ func (*SearchResponse) Descriptor() ([]byte, []int) {
return file_eventsearcher_proto_search_proto_rawDescGZIP(), []int{2} return file_eventsearcher_proto_search_proto_rawDescGZIP(), []int{2}
} }
func (x *SearchResponse) GetContinuationToken() string { func (x *SearchResponse) GetData() []byte {
if x != nil { if x != nil {
return x.ContinuationToken return x.Data
} }
return "" return nil
} }
func (x *SearchResponse) GetResponseData() []byte { func (x *SearchResponse) GetSameTsAtStart() []string {
if x != nil { if x != nil {
return x.ResponseData return x.SameTsAtStart
}
return nil
}
func (x *SearchResponse) GetSameTsAtEnd() []string {
if x != nil {
return x.SameTsAtEnd
} }
return nil return nil
} }
@ -331,77 +446,79 @@ var File_eventsearcher_proto_search_proto protoreflect.FileDescriptor
var file_eventsearcher_proto_search_proto_rawDesc = []byte{ var file_eventsearcher_proto_search_proto_rawDesc = []byte{
0x0a, 0x20, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x65, 0x72, 0x2f, 0x0a, 0x20, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x65, 0x72, 0x2f,
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x2e, 0x70, 0x72, 0x6f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x2e, 0x70, 0x72, 0x6f,
0x74, 0x6f, 0x12, 0x05, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x74, 0x6f, 0x12, 0x05, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xa0, 0x03, 0x0a, 0x0e, 0x46, 0x73,
0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x12, 0x27, 0x0a, 0x0f,
0x74, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x8d, 0x03, 0x0a, 0x0e, 0x46, 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18,
0x73, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x12, 0x43, 0x0a, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, 0x73, 0x74, 0x61, 0x72, 0x74, 0x54, 0x69, 0x6d, 0x65,
0x0f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x23, 0x0a, 0x0d, 0x65, 0x6e, 0x64, 0x5f, 0x74, 0x69, 0x6d,
0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x65, 0x6e,
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x64, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x63,
0x6d, 0x70, 0x52, 0x0e, 0x73, 0x74, 0x61, 0x72, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, 0x61, 0x63, 0x74,
0x6d, 0x70, 0x12, 0x3f, 0x0a, 0x0d, 0x65, 0x6e, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65,
0x61, 0x6d, 0x70, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65,
0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x70, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x70,
0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0c, 0x65, 0x6e, 0x64, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x12, 0x17, 0x0a, 0x07, 0x73, 0x73, 0x68, 0x5f, 0x63, 0x6d, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28,
0x61, 0x6d, 0x70, 0x12, 0x16, 0x0a, 0x06, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x09, 0x52, 0x06, 0x73, 0x73, 0x68, 0x43, 0x6d, 0x64, 0x12, 0x1c, 0x0a, 0x09, 0x70, 0x72, 0x6f,
0x01, 0x28, 0x09, 0x52, 0x06, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1a, 0x0a, 0x08, 0x75, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, 0x70, 0x72,
0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x75, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x73, 0x74, 0x61, 0x74, 0x75,
0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x70, 0x18, 0x05, 0x20, 0x73, 0x65, 0x73, 0x18, 0x08, 0x20, 0x03, 0x28, 0x05, 0x52, 0x08, 0x73, 0x74, 0x61, 0x74, 0x75,
0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x70, 0x12, 0x17, 0x0a, 0x07, 0x73, 0x73, 0x68, 0x5f, 0x63, 0x73, 0x65, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x5f,
0x6d, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x73, 0x68, 0x43, 0x6d, 0x64, 0x69, 0x64, 0x73, 0x18, 0x09, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0b, 0x69, 0x6e, 0x73, 0x74, 0x61,
0x12, 0x1a, 0x0a, 0x08, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x18, 0x07, 0x20, 0x01, 0x6e, 0x63, 0x65, 0x49, 0x64, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x18,
0x28, 0x09, 0x52, 0x08, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x12, 0x16, 0x0a, 0x06, 0x0a, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x12, 0x1f, 0x0a, 0x0b,
0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x73, 0x74, 0x65, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x0b, 0x20, 0x03, 0x28,
0x61, 0x74, 0x75, 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x09, 0x52, 0x0a, 0x65, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x49, 0x64, 0x73, 0x12, 0x31, 0x0a,
0x5f, 0x69, 0x64, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x05, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1b, 0x2e, 0x70,
0x6e, 0x63, 0x65, 0x49, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x18, 0x0a, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x46, 0x73, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x46, 0x69, 0x6c,
0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x12, 0x2d, 0x0a, 0x12, 0x63, 0x74, 0x65, 0x72, 0x2e, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x52, 0x05, 0x6f, 0x72, 0x64, 0x65, 0x72,
0x6f, 0x6e, 0x74, 0x69, 0x6e, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x22, 0x1a, 0x0a, 0x05, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x12, 0x08, 0x0a, 0x04, 0x44, 0x45, 0x53,
0x6e, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x63, 0x6f, 0x6e, 0x74, 0x69, 0x6e, 0x75, 0x43, 0x10, 0x00, 0x12, 0x07, 0x0a, 0x03, 0x41, 0x53, 0x43, 0x10, 0x01, 0x22, 0x9d, 0x03, 0x0a,
0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x22, 0x88, 0x03, 0x0a, 0x14, 0x50, 0x14, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x46,
0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x46, 0x69, 0x6c, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x12, 0x27, 0x0a, 0x0f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, 0x74,
0x74, 0x65, 0x72, 0x12, 0x43, 0x0a, 0x0f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e,
0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x73, 0x74, 0x61, 0x72, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x23,
0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x0a, 0x0d, 0x65, 0x6e, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18,
0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0e, 0x73, 0x74, 0x61, 0x72, 0x74, 0x54, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x65, 0x6e, 0x64, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74,
0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x3f, 0x0a, 0x0d, 0x65, 0x6e, 0x64, 0x5f, 0x61, 0x6d, 0x70, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x03,
0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x1a, 0x0a,
0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52,
0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0c, 0x65, 0x6e, 0x64, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x70, 0x18,
0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x16, 0x0a, 0x06, 0x61, 0x63, 0x74, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x70, 0x12, 0x21, 0x0a, 0x0c, 0x6f, 0x62, 0x6a,
0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x65, 0x63, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x09, 0x52,
0x6e, 0x12, 0x1a, 0x0a, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x54, 0x79, 0x70, 0x65, 0x73, 0x12, 0x1f, 0x0a, 0x0b,
0x01, 0x28, 0x09, 0x52, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x0e, 0x0a, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28,
0x02, 0x69, 0x70, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x70, 0x12, 0x1f, 0x0a, 0x09, 0x52, 0x0a, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x21, 0x0a,
0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x06, 0x20, 0x01, 0x0c, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x08, 0x20,
0x28, 0x09, 0x52, 0x0a, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1f, 0x03, 0x28, 0x09, 0x52, 0x0b, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x49, 0x64, 0x73,
0x0a, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x07, 0x20,
0x01, 0x28, 0x09, 0x52, 0x0a, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x12,
0x1f, 0x0a, 0x0b, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x08,
0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x49, 0x64,
0x12, 0x14, 0x0a, 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x18, 0x09, 0x20, 0x01, 0x28, 0x05, 0x52, 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x18, 0x09, 0x20, 0x01, 0x28, 0x05, 0x52,
0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x12, 0x2d, 0x0a, 0x12, 0x63, 0x6f, 0x6e, 0x74, 0x69, 0x6e, 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x12, 0x37, 0x0a, 0x05, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x18,
0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x0a, 0x20, 0x01, 0x0a, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x21, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50, 0x72,
0x28, 0x09, 0x52, 0x11, 0x63, 0x6f, 0x6e, 0x74, 0x69, 0x6e, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x46, 0x69, 0x6c, 0x74,
0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x22, 0x64, 0x0a, 0x0e, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x52, 0x65, 0x72, 0x2e, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x52, 0x05, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x12,
0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2d, 0x0a, 0x12, 0x63, 0x6f, 0x6e, 0x74, 0x69, 0x1f, 0x0a, 0x0b, 0x65, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x0b,
0x6e, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x01, 0x20, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x65, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x49, 0x64, 0x73,
0x01, 0x28, 0x09, 0x52, 0x11, 0x63, 0x6f, 0x6e, 0x74, 0x69, 0x6e, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x22, 0x1a, 0x0a, 0x05, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x12, 0x08, 0x0a, 0x04, 0x44, 0x45, 0x53,
0x6e, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x23, 0x0a, 0x0d, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x43, 0x10, 0x00, 0x12, 0x07, 0x0a, 0x03, 0x41, 0x53, 0x43, 0x10, 0x01, 0x22, 0x72, 0x0a, 0x0e,
0x73, 0x65, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0c, 0x72, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x12,
0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x44, 0x61, 0x74, 0x61, 0x32, 0x96, 0x01, 0x0a, 0x08, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x64, 0x61,
0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x65, 0x72, 0x12, 0x3e, 0x0a, 0x0e, 0x53, 0x65, 0x61, 0x72, 0x74, 0x61, 0x12, 0x27, 0x0a, 0x10, 0x73, 0x61, 0x6d, 0x65, 0x5f, 0x74, 0x73, 0x5f, 0x61, 0x74,
0x63, 0x68, 0x46, 0x73, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x15, 0x2e, 0x70, 0x72, 0x6f, 0x5f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0d, 0x73, 0x61,
0x74, 0x6f, 0x2e, 0x46, 0x73, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x6d, 0x65, 0x54, 0x73, 0x41, 0x74, 0x53, 0x74, 0x61, 0x72, 0x74, 0x12, 0x23, 0x0a, 0x0e, 0x73,
0x72, 0x1a, 0x15, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x61, 0x6d, 0x65, 0x5f, 0x74, 0x73, 0x5f, 0x61, 0x74, 0x5f, 0x65, 0x6e, 0x64, 0x18, 0x03, 0x20,
0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4a, 0x0a, 0x14, 0x53, 0x65, 0x61, 0x72, 0x03, 0x28, 0x09, 0x52, 0x0b, 0x73, 0x61, 0x6d, 0x65, 0x54, 0x73, 0x41, 0x74, 0x45, 0x6e, 0x64,
0x63, 0x68, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x32, 0x96, 0x01, 0x0a, 0x08, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x65, 0x72, 0x12, 0x3e, 0x0a,
0x12, 0x1b, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x0e, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x46, 0x73, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x12,
0x72, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x1a, 0x15, 0x2e, 0x15, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x46, 0x73, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73,
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x1a, 0x15, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x53,
0x6f, 0x6e, 0x73, 0x65, 0x42, 0x20, 0x5a, 0x1e, 0x73, 0x64, 0x6b, 0x2f, 0x70, 0x6c, 0x75, 0x67, 0x65, 0x61, 0x72, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4a, 0x0a,
0x69, 0x6e, 0x2f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x65, 0x72, 0x14, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x45,
0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x1b, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50, 0x72,
0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x46, 0x69, 0x6c, 0x74,
0x65, 0x72, 0x1a, 0x15, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x53, 0x65, 0x61, 0x72, 0x63,
0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x20, 0x5a, 0x1e, 0x73, 0x64, 0x6b,
0x2f, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x65, 0x61,
0x72, 0x63, 0x68, 0x65, 0x72, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f,
0x74, 0x6f, 0x33,
} }
var ( var (
@ -416,27 +533,27 @@ func file_eventsearcher_proto_search_proto_rawDescGZIP() []byte {
return file_eventsearcher_proto_search_proto_rawDescData return file_eventsearcher_proto_search_proto_rawDescData
} }
var file_eventsearcher_proto_search_proto_enumTypes = make([]protoimpl.EnumInfo, 2)
var file_eventsearcher_proto_search_proto_msgTypes = make([]protoimpl.MessageInfo, 3) var file_eventsearcher_proto_search_proto_msgTypes = make([]protoimpl.MessageInfo, 3)
var file_eventsearcher_proto_search_proto_goTypes = []interface{}{ var file_eventsearcher_proto_search_proto_goTypes = []interface{}{
(*FsEventsFilter)(nil), // 0: proto.FsEventsFilter (FsEventsFilter_Order)(0), // 0: proto.FsEventsFilter.Order
(*ProviderEventsFilter)(nil), // 1: proto.ProviderEventsFilter (ProviderEventsFilter_Order)(0), // 1: proto.ProviderEventsFilter.Order
(*SearchResponse)(nil), // 2: proto.SearchResponse (*FsEventsFilter)(nil), // 2: proto.FsEventsFilter
(*timestamppb.Timestamp)(nil), // 3: google.protobuf.Timestamp (*ProviderEventsFilter)(nil), // 3: proto.ProviderEventsFilter
(*SearchResponse)(nil), // 4: proto.SearchResponse
} }
var file_eventsearcher_proto_search_proto_depIdxs = []int32{ var file_eventsearcher_proto_search_proto_depIdxs = []int32{
3, // 0: proto.FsEventsFilter.start_timestamp:type_name -> google.protobuf.Timestamp 0, // 0: proto.FsEventsFilter.order:type_name -> proto.FsEventsFilter.Order
3, // 1: proto.FsEventsFilter.end_timestamp:type_name -> google.protobuf.Timestamp 1, // 1: proto.ProviderEventsFilter.order:type_name -> proto.ProviderEventsFilter.Order
3, // 2: proto.ProviderEventsFilter.start_timestamp:type_name -> google.protobuf.Timestamp 2, // 2: proto.Searcher.SearchFsEvents:input_type -> proto.FsEventsFilter
3, // 3: proto.ProviderEventsFilter.end_timestamp:type_name -> google.protobuf.Timestamp 3, // 3: proto.Searcher.SearchProviderEvents:input_type -> proto.ProviderEventsFilter
0, // 4: proto.Searcher.SearchFsEvents:input_type -> proto.FsEventsFilter 4, // 4: proto.Searcher.SearchFsEvents:output_type -> proto.SearchResponse
1, // 5: proto.Searcher.SearchProviderEvents:input_type -> proto.ProviderEventsFilter 4, // 5: proto.Searcher.SearchProviderEvents:output_type -> proto.SearchResponse
2, // 6: proto.Searcher.SearchFsEvents:output_type -> proto.SearchResponse 4, // [4:6] is the sub-list for method output_type
2, // 7: proto.Searcher.SearchProviderEvents:output_type -> proto.SearchResponse 2, // [2:4] is the sub-list for method input_type
6, // [6:8] is the sub-list for method output_type 2, // [2:2] is the sub-list for extension type_name
4, // [4:6] is the sub-list for method input_type 2, // [2:2] is the sub-list for extension extendee
4, // [4:4] is the sub-list for extension type_name 0, // [0:2] is the sub-list for field type_name
4, // [4:4] is the sub-list for extension extendee
0, // [0:4] is the sub-list for field type_name
} }
func init() { file_eventsearcher_proto_search_proto_init() } func init() { file_eventsearcher_proto_search_proto_init() }
@ -487,13 +604,14 @@ func file_eventsearcher_proto_search_proto_init() {
File: protoimpl.DescBuilder{ File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(), GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_eventsearcher_proto_search_proto_rawDesc, RawDescriptor: file_eventsearcher_proto_search_proto_rawDesc,
NumEnums: 0, NumEnums: 2,
NumMessages: 3, NumMessages: 3,
NumExtensions: 0, NumExtensions: 0,
NumServices: 1, NumServices: 1,
}, },
GoTypes: file_eventsearcher_proto_search_proto_goTypes, GoTypes: file_eventsearcher_proto_search_proto_goTypes,
DependencyIndexes: file_eventsearcher_proto_search_proto_depIdxs, DependencyIndexes: file_eventsearcher_proto_search_proto_depIdxs,
EnumInfos: file_eventsearcher_proto_search_proto_enumTypes,
MessageInfos: file_eventsearcher_proto_search_proto_msgTypes, MessageInfos: file_eventsearcher_proto_search_proto_msgTypes,
}.Build() }.Build()
File_eventsearcher_proto_search_proto = out.File File_eventsearcher_proto_search_proto = out.File

View file

@ -1,40 +1,49 @@
syntax = "proto3"; syntax = "proto3";
package proto; package proto;
import "google/protobuf/timestamp.proto";
option go_package = "sdk/plugin/eventsearcher/proto"; option go_package = "sdk/plugin/eventsearcher/proto";
message FsEventsFilter { message FsEventsFilter {
google.protobuf.Timestamp start_timestamp = 1; int64 start_timestamp = 1;
google.protobuf.Timestamp end_timestamp = 2; int64 end_timestamp = 2;
string action = 3; repeated string actions = 3;
string username = 4; string username = 4;
string ip = 5; string ip = 5;
string ssh_cmd = 6; string ssh_cmd = 6;
string protocol = 7; repeated string protocols = 7;
int32 status = 8; repeated int32 statuses = 8;
string instance_id = 9; repeated string instance_ids = 9;
int32 limit = 10; int32 limit = 10;
string continuation_token = 11; repeated string exclude_ids = 11;
enum Order {
DESC = 0;
ASC = 1;
}
Order order = 12;
} }
message ProviderEventsFilter { message ProviderEventsFilter {
google.protobuf.Timestamp start_timestamp = 1; int64 start_timestamp = 1;
google.protobuf.Timestamp end_timestamp = 2; int64 end_timestamp = 2;
string action = 3; repeated string actions = 3;
string username = 4; string username = 4;
string ip = 5; string ip = 5;
string object_type = 6; repeated string object_types = 6;
string object_name = 7; string object_name = 7;
string instance_id = 8; repeated string instance_ids = 8;
int32 limit = 9; int32 limit = 9;
string continuation_token = 10; enum Order {
DESC = 0;
ASC = 1;
}
Order order = 10;
repeated string exclude_ids = 11;
} }
message SearchResponse { message SearchResponse {
string continuation_token = 1; bytes data = 1; // JSON serialized response to return
bytes response_data = 2; // JSON serialized response to return repeated string same_ts_at_start = 2;
repeated string same_ts_at_end = 3;
} }
service Searcher { service Searcher {

View file

@ -10,7 +10,6 @@ import (
"github.com/hashicorp/go-hclog" "github.com/hashicorp/go-hclog"
"github.com/hashicorp/go-plugin" "github.com/hashicorp/go-plugin"
"google.golang.org/protobuf/types/known/timestamppb"
"github.com/drakkan/sftpgo/v2/logger" "github.com/drakkan/sftpgo/v2/logger"
"github.com/drakkan/sftpgo/v2/sdk/plugin/notifier" "github.com/drakkan/sftpgo/v2/sdk/plugin/notifier"
@ -43,14 +42,14 @@ type eventsQueue struct {
providerEvents []*proto.ProviderEvent providerEvents []*proto.ProviderEvent
} }
func (q *eventsQueue) addFsEvent(timestamp time.Time, action, username, fsPath, fsTargetPath, sshCmd, protocol, ip string, func (q *eventsQueue) addFsEvent(timestamp int64, action, username, fsPath, fsTargetPath, sshCmd, protocol, ip string,
fileSize int64, status int, fileSize int64, status int,
) { ) {
q.Lock() q.Lock()
defer q.Unlock() defer q.Unlock()
q.fsEvents = append(q.fsEvents, &proto.FsEvent{ q.fsEvents = append(q.fsEvents, &proto.FsEvent{
Timestamp: timestamppb.New(timestamp), Timestamp: timestamp,
Action: action, Action: action,
Username: username, Username: username,
FsPath: fsPath, FsPath: fsPath,
@ -63,14 +62,14 @@ func (q *eventsQueue) addFsEvent(timestamp time.Time, action, username, fsPath,
}) })
} }
func (q *eventsQueue) addProviderEvent(timestamp time.Time, action, username, objectType, objectName, ip string, func (q *eventsQueue) addProviderEvent(timestamp int64, action, username, objectType, objectName, ip string,
objectAsJSON []byte, objectAsJSON []byte,
) { ) {
q.Lock() q.Lock()
defer q.Unlock() defer q.Unlock()
q.providerEvents = append(q.providerEvents, &proto.ProviderEvent{ q.providerEvents = append(q.providerEvents, &proto.ProviderEvent{
Timestamp: timestamppb.New(timestamp), Timestamp: timestamp,
Action: action, Action: action,
ObjectType: objectType, ObjectType: objectType,
Username: username, Username: username,
@ -191,11 +190,11 @@ func (p *notifierPlugin) initialize() error {
return nil return nil
} }
func (p *notifierPlugin) canQueueEvent(timestamp time.Time) bool { func (p *notifierPlugin) canQueueEvent(timestamp int64) bool {
if p.config.NotifierOptions.RetryMaxTime == 0 { if p.config.NotifierOptions.RetryMaxTime == 0 {
return false return false
} }
if time.Now().After(timestamp.Add(time.Duration(p.config.NotifierOptions.RetryMaxTime) * time.Second)) { if time.Now().After(util.GetTimeFromMsecSinceEpoch(timestamp).Add(time.Duration(p.config.NotifierOptions.RetryMaxTime) * time.Second)) {
return false return false
} }
if p.config.NotifierOptions.RetryQueueMaxSize > 0 { if p.config.NotifierOptions.RetryQueueMaxSize > 0 {
@ -204,7 +203,7 @@ func (p *notifierPlugin) canQueueEvent(timestamp time.Time) bool {
return true return true
} }
func (p *notifierPlugin) notifyFsAction(timestamp time.Time, action, username, fsPath, fsTargetPath, sshCmd, func (p *notifierPlugin) notifyFsAction(timestamp int64, action, username, fsPath, fsTargetPath, sshCmd,
protocol, ip, virtualPath, virtualTargetPath string, fileSize int64, errAction error) { protocol, ip, virtualPath, virtualTargetPath string, fileSize int64, errAction error) {
if !util.IsStringInSlice(action, p.config.NotifierOptions.FsEvents) { if !util.IsStringInSlice(action, p.config.NotifierOptions.FsEvents) {
return return
@ -220,7 +219,7 @@ func (p *notifierPlugin) notifyFsAction(timestamp time.Time, action, username, f
}() }()
} }
func (p *notifierPlugin) notifyProviderAction(timestamp time.Time, action, username, objectType, objectName, ip string, func (p *notifierPlugin) notifyProviderAction(timestamp int64, action, username, objectType, objectName, ip string,
object Renderer, object Renderer,
) { ) {
if !util.IsStringInSlice(action, p.config.NotifierOptions.ProviderEvents) || if !util.IsStringInSlice(action, p.config.NotifierOptions.ProviderEvents) ||
@ -238,7 +237,7 @@ func (p *notifierPlugin) notifyProviderAction(timestamp time.Time, action, usern
}() }()
} }
func (p *notifierPlugin) sendFsEvent(timestamp time.Time, action, username, fsPath, fsTargetPath, sshCmd, func (p *notifierPlugin) sendFsEvent(timestamp int64, action, username, fsPath, fsTargetPath, sshCmd,
protocol, ip, virtualPath, virtualTargetPath string, fileSize int64, status int) { protocol, ip, virtualPath, virtualTargetPath string, fileSize int64, status int) {
if err := p.notifier.NotifyFsEvent(timestamp, action, username, fsPath, fsTargetPath, sshCmd, protocol, ip, if err := p.notifier.NotifyFsEvent(timestamp, action, username, fsPath, fsTargetPath, sshCmd, protocol, ip,
virtualPath, virtualTargetPath, fileSize, status); err != nil { virtualPath, virtualTargetPath, fileSize, status); err != nil {
@ -249,7 +248,7 @@ func (p *notifierPlugin) sendFsEvent(timestamp time.Time, action, username, fsPa
} }
} }
func (p *notifierPlugin) sendProviderEvent(timestamp time.Time, action, username, objectType, objectName, ip string, func (p *notifierPlugin) sendProviderEvent(timestamp int64, action, username, objectType, objectName, ip string,
objectAsJSON []byte, objectAsJSON []byte,
) { ) {
if err := p.notifier.NotifyProviderEvent(timestamp, action, username, objectType, objectName, ip, objectAsJSON); err != nil { if err := p.notifier.NotifyProviderEvent(timestamp, action, username, objectType, objectName, ip, objectAsJSON); err != nil {
@ -268,14 +267,14 @@ func (p *notifierPlugin) sendQueuedEvents() {
logger.Debug(logSender, "", "check queued events for notifier %#v, events size: %v", p.config.Cmd, queueSize) logger.Debug(logSender, "", "check queued events for notifier %#v, events size: %v", p.config.Cmd, queueSize)
fsEv := p.queue.popFsEvent() fsEv := p.queue.popFsEvent()
for fsEv != nil { for fsEv != nil {
go p.sendFsEvent(fsEv.Timestamp.AsTime(), fsEv.Action, fsEv.Username, fsEv.FsPath, fsEv.FsTargetPath, 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.FileSize, int(fsEv.Status))
fsEv = p.queue.popFsEvent() fsEv = p.queue.popFsEvent()
} }
providerEv := p.queue.popProviderEvent() providerEv := p.queue.popProviderEvent()
for providerEv != nil { for providerEv != nil {
go p.sendProviderEvent(providerEv.Timestamp.AsTime(), providerEv.Action, providerEv.Username, providerEv.ObjectType, go p.sendProviderEvent(providerEv.Timestamp, providerEv.Action, providerEv.Username, providerEv.ObjectType,
providerEv.ObjectName, providerEv.Ip, providerEv.ObjectData) providerEv.ObjectName, providerEv.Ip, providerEv.ObjectData)
providerEv = p.queue.popProviderEvent() providerEv = p.queue.popProviderEvent()
} }

View file

@ -5,7 +5,6 @@ import (
"time" "time"
"google.golang.org/protobuf/types/known/emptypb" "google.golang.org/protobuf/types/known/emptypb"
"google.golang.org/protobuf/types/known/timestamppb"
"github.com/drakkan/sftpgo/v2/sdk/plugin/notifier/proto" "github.com/drakkan/sftpgo/v2/sdk/plugin/notifier/proto"
) )
@ -20,14 +19,14 @@ type GRPCClient struct {
} }
// NotifyFsEvent implements the Notifier interface // NotifyFsEvent implements the Notifier interface
func (c *GRPCClient) NotifyFsEvent(timestamp time.Time, action, username, fsPath, fsTargetPath, sshCmd, protocol, ip, func (c *GRPCClient) NotifyFsEvent(timestamp int64, action, username, fsPath, fsTargetPath, sshCmd, protocol, ip,
virtualPath, virtualTargetPath string, fileSize int64, status int, virtualPath, virtualTargetPath string, fileSize int64, status int,
) error { ) error {
ctx, cancel := context.WithTimeout(context.Background(), rpcTimeout) ctx, cancel := context.WithTimeout(context.Background(), rpcTimeout)
defer cancel() defer cancel()
_, err := c.client.SendFsEvent(ctx, &proto.FsEvent{ _, err := c.client.SendFsEvent(ctx, &proto.FsEvent{
Timestamp: timestamppb.New(timestamp), Timestamp: timestamp,
Action: action, Action: action,
Username: username, Username: username,
FsPath: fsPath, FsPath: fsPath,
@ -45,12 +44,12 @@ func (c *GRPCClient) NotifyFsEvent(timestamp time.Time, action, username, fsPath
} }
// NotifyProviderEvent implements the Notifier interface // NotifyProviderEvent implements the Notifier interface
func (c *GRPCClient) NotifyProviderEvent(timestamp time.Time, action, username, objectType, objectName, ip string, object []byte) error { func (c *GRPCClient) NotifyProviderEvent(timestamp int64, action, username, objectType, objectName, ip string, object []byte) error {
ctx, cancel := context.WithTimeout(context.Background(), rpcTimeout) ctx, cancel := context.WithTimeout(context.Background(), rpcTimeout)
defer cancel() defer cancel()
_, err := c.client.SendProviderEvent(ctx, &proto.ProviderEvent{ _, err := c.client.SendProviderEvent(ctx, &proto.ProviderEvent{
Timestamp: timestamppb.New(timestamp), Timestamp: timestamp,
Action: action, Action: action,
ObjectType: objectType, ObjectType: objectType,
Username: username, Username: username,
@ -69,14 +68,14 @@ type GRPCServer struct {
// SendFsEvent implements the serve side fs notify method // SendFsEvent implements the serve side fs notify method
func (s *GRPCServer) SendFsEvent(ctx context.Context, req *proto.FsEvent) (*emptypb.Empty, error) { func (s *GRPCServer) SendFsEvent(ctx context.Context, req *proto.FsEvent) (*emptypb.Empty, error) {
err := s.Impl.NotifyFsEvent(req.Timestamp.AsTime(), req.Action, req.Username, req.FsPath, req.FsTargetPath, req.SshCmd, 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.FileSize, int(req.Status))
return &emptypb.Empty{}, err return &emptypb.Empty{}, err
} }
// SendProviderEvent implements the serve side provider event notify method // SendProviderEvent implements the serve side provider event notify method
func (s *GRPCServer) SendProviderEvent(ctx context.Context, req *proto.ProviderEvent) (*emptypb.Empty, error) { func (s *GRPCServer) SendProviderEvent(ctx context.Context, req *proto.ProviderEvent) (*emptypb.Empty, error) {
err := s.Impl.NotifyProviderEvent(req.Timestamp.AsTime(), req.Action, req.Username, req.ObjectType, req.ObjectName, err := s.Impl.NotifyProviderEvent(req.Timestamp, req.Action, req.Username, req.ObjectType, req.ObjectName,
req.Ip, req.ObjectData) req.Ip, req.ObjectData)
return &emptypb.Empty{}, err return &emptypb.Empty{}, err
} }

View file

@ -6,7 +6,6 @@ package notifier
import ( import (
"context" "context"
"time"
"github.com/hashicorp/go-plugin" "github.com/hashicorp/go-plugin"
"google.golang.org/grpc" "google.golang.org/grpc"
@ -33,9 +32,9 @@ var PluginMap = map[string]plugin.Plugin{
// Notifier defines the interface for notifiers plugins // Notifier defines the interface for notifiers plugins
type Notifier interface { type Notifier interface {
NotifyFsEvent(timestamp time.Time, action, username, fsPath, fsTargetPath, sshCmd, protocol, ip, NotifyFsEvent(timestamp int64, action, username, fsPath, fsTargetPath, sshCmd, protocol, ip,
virtualPath, virtualTargetPath string, fileSize int64, status int) error virtualPath, virtualTargetPath string, fileSize int64, status int) error
NotifyProviderEvent(timestamp time.Time, action, username, objectType, objectName, ip string, object []byte) error NotifyProviderEvent(timestamp int64, action, username, objectType, objectName, ip string, object []byte) error
} }
// Plugin defines the implementation to serve/connect to a notifier plugin // Plugin defines the implementation to serve/connect to a notifier plugin

View file

@ -14,7 +14,6 @@ import (
protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl" protoimpl "google.golang.org/protobuf/runtime/protoimpl"
emptypb "google.golang.org/protobuf/types/known/emptypb" emptypb "google.golang.org/protobuf/types/known/emptypb"
timestamppb "google.golang.org/protobuf/types/known/timestamppb"
reflect "reflect" reflect "reflect"
sync "sync" sync "sync"
) )
@ -31,18 +30,18 @@ type FsEvent struct {
sizeCache protoimpl.SizeCache sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields unknownFields protoimpl.UnknownFields
Timestamp *timestamppb.Timestamp `protobuf:"bytes,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` Timestamp int64 `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
Action string `protobuf:"bytes,2,opt,name=action,proto3" json:"action,omitempty"` Action string `protobuf:"bytes,2,opt,name=action,proto3" json:"action,omitempty"`
Username string `protobuf:"bytes,3,opt,name=username,proto3" json:"username,omitempty"` Username string `protobuf:"bytes,3,opt,name=username,proto3" json:"username,omitempty"`
FsPath string `protobuf:"bytes,4,opt,name=fs_path,json=fsPath,proto3" json:"fs_path,omitempty"` FsPath string `protobuf:"bytes,4,opt,name=fs_path,json=fsPath,proto3" json:"fs_path,omitempty"`
FsTargetPath string `protobuf:"bytes,5,opt,name=fs_target_path,json=fsTargetPath,proto3" json:"fs_target_path,omitempty"` FsTargetPath string `protobuf:"bytes,5,opt,name=fs_target_path,json=fsTargetPath,proto3" json:"fs_target_path,omitempty"`
SshCmd string `protobuf:"bytes,6,opt,name=ssh_cmd,json=sshCmd,proto3" json:"ssh_cmd,omitempty"` SshCmd string `protobuf:"bytes,6,opt,name=ssh_cmd,json=sshCmd,proto3" json:"ssh_cmd,omitempty"`
FileSize int64 `protobuf:"varint,7,opt,name=file_size,json=fileSize,proto3" json:"file_size,omitempty"` FileSize int64 `protobuf:"varint,7,opt,name=file_size,json=fileSize,proto3" json:"file_size,omitempty"`
Protocol string `protobuf:"bytes,8,opt,name=protocol,proto3" json:"protocol,omitempty"` Protocol string `protobuf:"bytes,8,opt,name=protocol,proto3" json:"protocol,omitempty"`
Status int32 `protobuf:"varint,9,opt,name=status,proto3" json:"status,omitempty"` Status int32 `protobuf:"varint,9,opt,name=status,proto3" json:"status,omitempty"`
Ip string `protobuf:"bytes,10,opt,name=ip,proto3" json:"ip,omitempty"` 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"` 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"` VirtualTargetPath string `protobuf:"bytes,12,opt,name=virtual_target_path,json=virtualTargetPath,proto3" json:"virtual_target_path,omitempty"`
} }
func (x *FsEvent) Reset() { func (x *FsEvent) Reset() {
@ -77,11 +76,11 @@ func (*FsEvent) Descriptor() ([]byte, []int) {
return file_notifier_proto_notifier_proto_rawDescGZIP(), []int{0} return file_notifier_proto_notifier_proto_rawDescGZIP(), []int{0}
} }
func (x *FsEvent) GetTimestamp() *timestamppb.Timestamp { func (x *FsEvent) GetTimestamp() int64 {
if x != nil { if x != nil {
return x.Timestamp return x.Timestamp
} }
return nil return 0
} }
func (x *FsEvent) GetAction() string { func (x *FsEvent) GetAction() string {
@ -166,13 +165,13 @@ type ProviderEvent struct {
sizeCache protoimpl.SizeCache sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields unknownFields protoimpl.UnknownFields
Timestamp *timestamppb.Timestamp `protobuf:"bytes,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"` Timestamp int64 `protobuf:"varint,1,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
Action string `protobuf:"bytes,2,opt,name=action,proto3" json:"action,omitempty"` Action string `protobuf:"bytes,2,opt,name=action,proto3" json:"action,omitempty"`
ObjectType string `protobuf:"bytes,3,opt,name=object_type,json=objectType,proto3" json:"object_type,omitempty"` ObjectType string `protobuf:"bytes,3,opt,name=object_type,json=objectType,proto3" json:"object_type,omitempty"`
Username string `protobuf:"bytes,4,opt,name=username,proto3" json:"username,omitempty"` Username string `protobuf:"bytes,4,opt,name=username,proto3" json:"username,omitempty"`
Ip string `protobuf:"bytes,5,opt,name=ip,proto3" json:"ip,omitempty"` Ip string `protobuf:"bytes,5,opt,name=ip,proto3" json:"ip,omitempty"`
ObjectName string `protobuf:"bytes,6,opt,name=object_name,json=objectName,proto3" json:"object_name,omitempty"` ObjectName string `protobuf:"bytes,6,opt,name=object_name,json=objectName,proto3" json:"object_name,omitempty"`
ObjectData []byte `protobuf:"bytes,7,opt,name=object_data,json=objectData,proto3" json:"object_data,omitempty"` // object JSON serialized ObjectData []byte `protobuf:"bytes,7,opt,name=object_data,json=objectData,proto3" json:"object_data,omitempty"` // object JSON serialized
} }
func (x *ProviderEvent) Reset() { func (x *ProviderEvent) Reset() {
@ -207,11 +206,11 @@ func (*ProviderEvent) Descriptor() ([]byte, []int) {
return file_notifier_proto_notifier_proto_rawDescGZIP(), []int{1} return file_notifier_proto_notifier_proto_rawDescGZIP(), []int{1}
} }
func (x *ProviderEvent) GetTimestamp() *timestamppb.Timestamp { func (x *ProviderEvent) GetTimestamp() int64 {
if x != nil { if x != nil {
return x.Timestamp return x.Timestamp
} }
return nil return 0
} }
func (x *ProviderEvent) GetAction() string { func (x *ProviderEvent) GetAction() string {
@ -261,61 +260,55 @@ var File_notifier_proto_notifier_proto protoreflect.FileDescriptor
var file_notifier_proto_notifier_proto_rawDesc = []byte{ var file_notifier_proto_notifier_proto_rawDesc = []byte{
0x0a, 0x1d, 0x6e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x0a, 0x1d, 0x6e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f,
0x2f, 0x6e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x2f, 0x6e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12,
0x05, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x05, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1b, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70,
0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x2e, 0x70, 0x72,
0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1b, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x6f, 0x74, 0x6f, 0x22, 0xe7, 0x02, 0x0a, 0x07, 0x46, 0x73, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12,
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x2e, 0x70, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x01, 0x20, 0x01,
0x72, 0x6f, 0x74, 0x6f, 0x22, 0x83, 0x03, 0x0a, 0x07, 0x46, 0x73, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x28, 0x03, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x16, 0x0a,
0x12, 0x38, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x01, 0x20, 0x06, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x61,
0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1a, 0x0a, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d,
0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d,
0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x16, 0x0a, 0x06, 0x61, 0x63, 0x65, 0x12, 0x17, 0x0a, 0x07, 0x66, 0x73, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, 0x04, 0x20, 0x01,
0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x61, 0x63, 0x74, 0x69, 0x28, 0x09, 0x52, 0x06, 0x66, 0x73, 0x50, 0x61, 0x74, 0x68, 0x12, 0x24, 0x0a, 0x0e, 0x66, 0x73,
0x6f, 0x6e, 0x12, 0x1a, 0x0a, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x5f, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, 0x05, 0x20, 0x01,
0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x17, 0x28, 0x09, 0x52, 0x0c, 0x66, 0x73, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x50, 0x61, 0x74, 0x68,
0x0a, 0x07, 0x66, 0x73, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x12, 0x17, 0x0a, 0x07, 0x73, 0x73, 0x68, 0x5f, 0x63, 0x6d, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28,
0x06, 0x66, 0x73, 0x50, 0x61, 0x74, 0x68, 0x12, 0x24, 0x0a, 0x0e, 0x66, 0x73, 0x5f, 0x74, 0x61, 0x09, 0x52, 0x06, 0x73, 0x73, 0x68, 0x43, 0x6d, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x66, 0x69, 0x6c,
0x72, 0x67, 0x65, 0x74, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x65, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x66, 0x69,
0x0c, 0x66, 0x73, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x50, 0x61, 0x74, 0x68, 0x12, 0x17, 0x0a, 0x6c, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63,
0x07, 0x73, 0x73, 0x68, 0x5f, 0x63, 0x6d, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6f, 0x6c, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63,
0x73, 0x73, 0x68, 0x43, 0x6d, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x73, 0x6f, 0x6c, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x09, 0x20, 0x01,
0x69, 0x7a, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x66, 0x69, 0x6c, 0x65, 0x53, 0x28, 0x05, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x70,
0x69, 0x7a, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x18, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x70, 0x12, 0x21, 0x0a, 0x0c, 0x76, 0x69,
0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x12, 0x72, 0x74, 0x75, 0x61, 0x6c, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09,
0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x09, 0x20, 0x01, 0x28, 0x05, 0x52, 0x52, 0x0b, 0x76, 0x69, 0x72, 0x74, 0x75, 0x61, 0x6c, 0x50, 0x61, 0x74, 0x68, 0x12, 0x2e, 0x0a,
0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x70, 0x18, 0x0a, 0x20, 0x13, 0x76, 0x69, 0x72, 0x74, 0x75, 0x61, 0x6c, 0x5f, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f,
0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x70, 0x12, 0x21, 0x0a, 0x0c, 0x76, 0x69, 0x72, 0x74, 0x75, 0x70, 0x61, 0x74, 0x68, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x76, 0x69, 0x72, 0x74,
0x61, 0x6c, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x76, 0x75, 0x61, 0x6c, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x50, 0x61, 0x74, 0x68, 0x22, 0xd4, 0x01,
0x69, 0x72, 0x74, 0x75, 0x61, 0x6c, 0x50, 0x61, 0x74, 0x68, 0x12, 0x2e, 0x0a, 0x13, 0x76, 0x69, 0x0a, 0x0d, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12,
0x72, 0x74, 0x75, 0x61, 0x6c, 0x5f, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x70, 0x61, 0x74, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x01, 0x20, 0x01,
0x68, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x76, 0x69, 0x72, 0x74, 0x75, 0x61, 0x6c, 0x28, 0x03, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x16, 0x0a,
0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x50, 0x61, 0x74, 0x68, 0x22, 0xf0, 0x01, 0x0a, 0x0d, 0x50, 0x06, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x61,
0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x38, 0x0a, 0x09, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1f, 0x0a, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x5f,
0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x6f, 0x62, 0x6a, 0x65,
0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x63, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61,
0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61,
0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x16, 0x0a, 0x06, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x6d, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x70, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02,
0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1f, 0x69, 0x70, 0x12, 0x1f, 0x0a, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x6e, 0x61, 0x6d,
0x0a, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x4e,
0x01, 0x28, 0x09, 0x52, 0x0a, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x61, 0x6d, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x64, 0x61,
0x1a, 0x0a, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x74, 0x61, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0a, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74,
0x09, 0x52, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x44, 0x61, 0x74, 0x61, 0x32, 0x84, 0x01, 0x0a, 0x08, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x65,
0x70, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x70, 0x12, 0x1f, 0x0a, 0x0b, 0x6f, 0x72, 0x12, 0x35, 0x0a, 0x0b, 0x53, 0x65, 0x6e, 0x64, 0x46, 0x73, 0x45, 0x76, 0x65, 0x6e, 0x74,
0x62, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x12, 0x0e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x46, 0x73, 0x45, 0x76, 0x65, 0x6e, 0x74,
0x52, 0x0a, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62,
0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x18, 0x07, 0x20, 0x01, 0x28, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x41, 0x0a, 0x11, 0x53, 0x65, 0x6e, 0x64,
0x0c, 0x52, 0x0a, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x44, 0x61, 0x74, 0x61, 0x32, 0x84, 0x01, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x14, 0x2e,
0x0a, 0x08, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x12, 0x35, 0x0a, 0x0b, 0x53, 0x65, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x45, 0x76,
0x6e, 0x64, 0x46, 0x73, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x0e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x65, 0x6e, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f,
0x6f, 0x2e, 0x46, 0x73, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x42, 0x1b, 0x5a, 0x19, 0x73,
0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x64, 0x6b, 0x2f, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2f, 0x6e, 0x6f, 0x74, 0x69, 0x66, 0x69,
0x79, 0x12, 0x41, 0x0a, 0x11, 0x53, 0x65, 0x6e, 0x64, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x65, 0x72, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
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 ( var (
@ -332,23 +325,20 @@ func file_notifier_proto_notifier_proto_rawDescGZIP() []byte {
var file_notifier_proto_notifier_proto_msgTypes = make([]protoimpl.MessageInfo, 2) var file_notifier_proto_notifier_proto_msgTypes = make([]protoimpl.MessageInfo, 2)
var file_notifier_proto_notifier_proto_goTypes = []interface{}{ var file_notifier_proto_notifier_proto_goTypes = []interface{}{
(*FsEvent)(nil), // 0: proto.FsEvent (*FsEvent)(nil), // 0: proto.FsEvent
(*ProviderEvent)(nil), // 1: proto.ProviderEvent (*ProviderEvent)(nil), // 1: proto.ProviderEvent
(*timestamppb.Timestamp)(nil), // 2: google.protobuf.Timestamp (*emptypb.Empty)(nil), // 2: google.protobuf.Empty
(*emptypb.Empty)(nil), // 3: google.protobuf.Empty
} }
var file_notifier_proto_notifier_proto_depIdxs = []int32{ var file_notifier_proto_notifier_proto_depIdxs = []int32{
2, // 0: proto.FsEvent.timestamp:type_name -> google.protobuf.Timestamp 0, // 0: proto.Notifier.SendFsEvent:input_type -> proto.FsEvent
2, // 1: proto.ProviderEvent.timestamp:type_name -> google.protobuf.Timestamp 1, // 1: proto.Notifier.SendProviderEvent:input_type -> proto.ProviderEvent
0, // 2: proto.Notifier.SendFsEvent:input_type -> proto.FsEvent 2, // 2: proto.Notifier.SendFsEvent:output_type -> google.protobuf.Empty
1, // 3: proto.Notifier.SendProviderEvent:input_type -> proto.ProviderEvent 2, // 3: proto.Notifier.SendProviderEvent:output_type -> google.protobuf.Empty
3, // 4: proto.Notifier.SendFsEvent:output_type -> google.protobuf.Empty 2, // [2:4] is the sub-list for method output_type
3, // 5: proto.Notifier.SendProviderEvent:output_type -> google.protobuf.Empty 0, // [0:2] is the sub-list for method input_type
4, // [4:6] is the sub-list for method output_type 0, // [0:0] is the sub-list for extension type_name
2, // [2:4] is the sub-list for method input_type 0, // [0:0] is the sub-list for extension extendee
2, // [2:2] is the sub-list for extension type_name 0, // [0:0] is the sub-list for field type_name
2, // [2:2] is the sub-list for extension extendee
0, // [0:2] is the sub-list for field type_name
} }
func init() { file_notifier_proto_notifier_proto_init() } func init() { file_notifier_proto_notifier_proto_init() }

View file

@ -1,13 +1,12 @@
syntax = "proto3"; syntax = "proto3";
package proto; package proto;
import "google/protobuf/timestamp.proto";
import "google/protobuf/empty.proto"; import "google/protobuf/empty.proto";
option go_package = "sdk/plugin/notifier/proto"; option go_package = "sdk/plugin/notifier/proto";
message FsEvent { message FsEvent {
google.protobuf.Timestamp timestamp = 1; int64 timestamp = 1;
string action = 2; string action = 2;
string username = 3; string username = 3;
string fs_path = 4; string fs_path = 4;
@ -22,7 +21,7 @@ message FsEvent {
} }
message ProviderEvent { message ProviderEvent {
google.protobuf.Timestamp timestamp = 1; int64 timestamp = 1;
string action = 2; string action = 2;
string object_type = 3; string object_type = 3;
string username = 4; string username = 4;

View file

@ -28,7 +28,8 @@ var (
// Handler defines the plugins manager // Handler defines the plugins manager
Handler Manager Handler Manager
pluginsLogLevel = hclog.Debug pluginsLogLevel = hclog.Debug
errNoSearcher = errors.New("no events searcher plugin defined") // ErrNoSearcher defines the error to return for events searches if no plugin is configured
ErrNoSearcher = errors.New("no events searcher plugin defined")
) )
// Renderer defines the interface for generic objects rendering // Renderer defines the interface for generic objects rendering
@ -184,7 +185,7 @@ func (m *Manager) validateConfigs() error {
} }
// NotifyFsEvent sends the fs event notifications using any defined notifier plugins // NotifyFsEvent sends the fs event notifications using any defined notifier plugins
func (m *Manager) NotifyFsEvent(timestamp time.Time, action, username, fsPath, fsTargetPath, sshCmd, protocol, ip, func (m *Manager) NotifyFsEvent(timestamp int64, action, username, fsPath, fsTargetPath, sshCmd, protocol, ip,
virtualPath, virtualTargetPath string, fileSize int64, err error, virtualPath, virtualTargetPath string, fileSize int64, err error,
) { ) {
m.notifLock.RLock() m.notifLock.RLock()
@ -197,7 +198,7 @@ func (m *Manager) NotifyFsEvent(timestamp time.Time, action, username, fsPath, f
} }
// NotifyProviderEvent sends the provider event notifications using any defined notifier plugins // NotifyProviderEvent sends the provider event notifications using any defined notifier plugins
func (m *Manager) NotifyProviderEvent(timestamp time.Time, action, username, objectType, objectName, ip string, func (m *Manager) NotifyProviderEvent(timestamp int64, action, username, objectType, objectName, ip string,
object Renderer, object Renderer,
) { ) {
m.notifLock.RLock() m.notifLock.RLock()
@ -210,34 +211,34 @@ func (m *Manager) NotifyProviderEvent(timestamp time.Time, action, username, obj
// SearchFsEvents returns the filesystem events matching the specified filter and a continuation token // SearchFsEvents returns the filesystem events matching the specified filter and a continuation token
// to use for cursor based pagination // to use for cursor based pagination
func (m *Manager) SearchFsEvents(startTimestamp, endTimestamp time.Time, action, username, ip, sshCmd, protocol, func (m *Manager) SearchFsEvents(startTimestamp, endTimestamp int64, username, ip, sshCmd string, actions,
instanceID, continuationToken string, status, limit int) (string, []byte, error, protocols, instanceIDs, excludeIDs []string, statuses []int32, limit, order int,
) { ) ([]byte, []string, []string, error) {
if !m.hasSearcher { if !m.hasSearcher {
return "", nil, errNoSearcher return nil, nil, nil, ErrNoSearcher
} }
m.searcherLock.RLock() m.searcherLock.RLock()
plugin := m.searcher plugin := m.searcher
m.searcherLock.RUnlock() m.searcherLock.RUnlock()
return plugin.searchear.SearchFsEvents(startTimestamp, endTimestamp, action, username, ip, sshCmd, protocol, return plugin.searchear.SearchFsEvents(startTimestamp, endTimestamp, username, ip, sshCmd, actions, protocols,
instanceID, continuationToken, status, limit) instanceIDs, excludeIDs, statuses, limit, order)
} }
// SearchProviderEvents returns the provider events matching the specified filter and a continuation token // SearchProviderEvents returns the provider events matching the specified filter and a continuation token
// to use for cursor based pagination // to use for cursor based pagination
func (m *Manager) SearchProviderEvents(startTimestamp, endTimestamp time.Time, action, username, ip, objectType, func (m *Manager) SearchProviderEvents(startTimestamp, endTimestamp int64, username, ip, objectName string,
objectName, instanceID, continuationToken string, limit int, limit, order int, actions, objectTypes, instanceIDs, excludeIDs []string,
) (string, []byte, error) { ) ([]byte, []string, []string, error) {
if !m.hasSearcher { if !m.hasSearcher {
return "", nil, errNoSearcher return nil, nil, nil, ErrNoSearcher
} }
m.searcherLock.RLock() m.searcherLock.RLock()
plugin := m.searcher plugin := m.searcher
m.searcherLock.RUnlock() m.searcherLock.RUnlock()
return plugin.searchear.SearchProviderEvents(startTimestamp, endTimestamp, action, username, ip, objectType, objectName, return plugin.searchear.SearchProviderEvents(startTimestamp, endTimestamp, username, ip, objectName, limit,
instanceID, continuationToken, limit) order, actions, objectTypes, instanceIDs, excludeIDs)
} }
func (m *Manager) kmsEncrypt(secret kms.BaseSecret, url string, masterKey string, kmsID int) (string, string, int32, error) { func (m *Manager) kmsEncrypt(secret kms.BaseSecret, url string, masterKey string, kmsID int) (string, string, int32, error) {