mirror of
https://github.com/gravitational/teleport.git
synced 2026-10-11 22:49:54 +00:00
emit an audit event with file transfer statistics when an SFTP session is completed (#48051)
* emit an audit event with file transfer statistics when an SFTP session is completed * remove unused SFTP event codes, don't embed os.File * send oneof events to parent process to make event unmarshaling easier to reason about * protect tracked files with mutex
This commit is contained in:
@@ -1892,6 +1892,54 @@ message SFTP {
|
||||
string Error = 12 [(gogoproto.jsontag) = "error,omitempty"];
|
||||
}
|
||||
|
||||
// SFTPSummary is emitted at the end of an SFTP transfer
|
||||
message SFTPSummary {
|
||||
// Metadata is a common event metadata
|
||||
Metadata Metadata = 1 [
|
||||
(gogoproto.nullable) = false,
|
||||
(gogoproto.embed) = true,
|
||||
(gogoproto.jsontag) = ""
|
||||
];
|
||||
|
||||
// User is a common user event metadata
|
||||
UserMetadata User = 2 [
|
||||
(gogoproto.nullable) = false,
|
||||
(gogoproto.embed) = true,
|
||||
(gogoproto.jsontag) = ""
|
||||
];
|
||||
|
||||
// ConnectionMetadata holds information about the connection
|
||||
ConnectionMetadata Connection = 3 [
|
||||
(gogoproto.nullable) = false,
|
||||
(gogoproto.embed) = true,
|
||||
(gogoproto.jsontag) = ""
|
||||
];
|
||||
|
||||
// SessionMetadata is a common event session metadata
|
||||
SessionMetadata Session = 4 [
|
||||
(gogoproto.nullable) = false,
|
||||
(gogoproto.embed) = true,
|
||||
(gogoproto.jsontag) = ""
|
||||
];
|
||||
|
||||
// ServerMetadata is a common server metadata
|
||||
ServerMetadata Server = 5 [
|
||||
(gogoproto.nullable) = false,
|
||||
(gogoproto.embed) = true,
|
||||
(gogoproto.jsontag) = ""
|
||||
];
|
||||
|
||||
// FileTransferStats contains statistics about transferred files
|
||||
repeated FileTransferStat FileTransferStats = 6 [(gogoproto.jsontag) = "file_transfer_stats"];
|
||||
}
|
||||
|
||||
// FileTransferStat is statistics about a transferred file
|
||||
message FileTransferStat {
|
||||
string Path = 1 [(gogoproto.jsontag) = "path"];
|
||||
uint64 BytesRead = 2 [(gogoproto.jsontag) = "bytes_read"];
|
||||
uint64 BytesWritten = 3 [(gogoproto.jsontag) = "bytes_written"];
|
||||
}
|
||||
|
||||
// Subsystem is emitted when a user requests a new subsystem.
|
||||
message Subsystem {
|
||||
// Metadata is a common event metadata
|
||||
@@ -4615,6 +4663,7 @@ message OneOf {
|
||||
events.UserTaskCreate UserTaskCreate = 188;
|
||||
events.UserTaskUpdate UserTaskUpdate = 189;
|
||||
events.UserTaskDelete UserTaskDelete = 190;
|
||||
events.SFTPSummary SFTPSummary = 191;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2302,3 +2302,29 @@ func (m *UserTaskUpdate) TrimToMaxSize(_ int) AuditEvent {
|
||||
func (m *UserTaskDelete) TrimToMaxSize(_ int) AuditEvent {
|
||||
return m
|
||||
}
|
||||
|
||||
func (m *SFTPSummary) TrimToMaxSize(maxSize int) AuditEvent {
|
||||
size := m.Size()
|
||||
if size <= maxSize {
|
||||
return m
|
||||
}
|
||||
|
||||
out := utils.CloneProtoMsg(m)
|
||||
|
||||
var customFieldsCount int
|
||||
for i := range out.FileTransferStats {
|
||||
if out.FileTransferStats[i].Path != "" {
|
||||
customFieldsCount++
|
||||
out.FileTransferStats[i].Path = ""
|
||||
}
|
||||
}
|
||||
|
||||
maxSize = adjustedMaxSize(out, maxSize)
|
||||
maxFieldsSize := maxSizePerField(maxSize, customFieldsCount)
|
||||
|
||||
for i := range out.FileTransferStats {
|
||||
out.FileTransferStats[i].Path = trimStr(out.FileTransferStats[i].Path, maxFieldsSize)
|
||||
}
|
||||
|
||||
return out
|
||||
}
|
||||
|
||||
+2002
-1257
File diff suppressed because it is too large
Load Diff
@@ -761,6 +761,10 @@ func ToOneOf(in AuditEvent) (*OneOf, error) {
|
||||
out.Event = &OneOf_UserTaskDelete{
|
||||
UserTaskDelete: e,
|
||||
}
|
||||
case *SFTPSummary:
|
||||
out.Event = &OneOf_SFTPSummary{
|
||||
SFTPSummary: e,
|
||||
}
|
||||
default:
|
||||
slog.ErrorContext(context.Background(), "Attempted to convert dynamic event of unknown type into protobuf event.", "event_type", in.GetType())
|
||||
unknown := &Unknown{}
|
||||
|
||||
@@ -285,6 +285,8 @@ const (
|
||||
// SFTPEvent means a user attempted a file operation
|
||||
SFTPEvent = "sftp"
|
||||
SFTPPath = "path"
|
||||
// SFTPSummaryEvent is emitted at the end of an SFTP transfer.
|
||||
SFTPSummaryEvent = "sftp_summary"
|
||||
|
||||
// ResizeEvent means that some user resized PTY on the client
|
||||
ResizeEvent = "resize"
|
||||
|
||||
+27
-39
@@ -320,45 +320,29 @@ const (
|
||||
KubernetesClusterDeleteCode = "T3012I"
|
||||
|
||||
// The following codes correspond to SFTP file operations.
|
||||
SFTPOpenCode = "TS001I"
|
||||
SFTPOpenFailureCode = "TS001E"
|
||||
SFTPCloseCode = "TS002I"
|
||||
SFTPCloseFailureCode = "TS002E"
|
||||
SFTPReadCode = "TS003I"
|
||||
SFTPReadFailureCode = "TS003E"
|
||||
SFTPWriteCode = "TS004I"
|
||||
SFTPWriteFailureCode = "TS004E"
|
||||
SFTPLstatCode = "TS005I"
|
||||
SFTPLstatFailureCode = "TS005E"
|
||||
SFTPFstatCode = "TS006I"
|
||||
SFTPFstatFailureCode = "TS006E"
|
||||
SFTPSetstatCode = "TS007I"
|
||||
SFTPSetstatFailureCode = "TS007E"
|
||||
SFTPFsetstatCode = "TS008I"
|
||||
SFTPFsetstatFailureCode = "TS008E"
|
||||
SFTPOpendirCode = "TS009I"
|
||||
SFTPOpendirFailureCode = "TS009E"
|
||||
SFTPReaddirCode = "TS010I"
|
||||
SFTPReaddirFailureCode = "TS010E"
|
||||
SFTPRemoveCode = "TS011I"
|
||||
SFTPRemoveFailureCode = "TS011E"
|
||||
SFTPMkdirCode = "TS012I"
|
||||
SFTPMkdirFailureCode = "TS012E"
|
||||
SFTPRmdirCode = "TS013I"
|
||||
SFTPRmdirFailureCode = "TS013E"
|
||||
SFTPRealpathCode = "TS014I"
|
||||
SFTPRealpathFailureCode = "TS014E"
|
||||
SFTPStatCode = "TS015I"
|
||||
SFTPStatFailureCode = "TS015E"
|
||||
SFTPRenameCode = "TS016I"
|
||||
SFTPRenameFailureCode = "TS016E"
|
||||
SFTPReadlinkCode = "TS017I"
|
||||
SFTPReadlinkFailureCode = "TS017E"
|
||||
SFTPSymlinkCode = "TS018I"
|
||||
SFTPSymlinkFailureCode = "TS018E"
|
||||
SFTPLinkCode = "TS019I"
|
||||
SFTPLinkFailureCode = "TS019E"
|
||||
SFTPDisallowedCode = "TS020E"
|
||||
SFTPOpenCode = "TS001I"
|
||||
SFTPOpenFailureCode = "TS001E"
|
||||
SFTPSetstatCode = "TS007I"
|
||||
SFTPSetstatFailureCode = "TS007E"
|
||||
SFTPOpendirCode = "TS009I"
|
||||
SFTPOpendirFailureCode = "TS009E"
|
||||
SFTPReaddirCode = "TS010I"
|
||||
SFTPReaddirFailureCode = "TS010E"
|
||||
SFTPRemoveCode = "TS011I"
|
||||
SFTPRemoveFailureCode = "TS011E"
|
||||
SFTPMkdirCode = "TS012I"
|
||||
SFTPMkdirFailureCode = "TS012E"
|
||||
SFTPRmdirCode = "TS013I"
|
||||
SFTPRmdirFailureCode = "TS013E"
|
||||
SFTPRenameCode = "TS016I"
|
||||
SFTPRenameFailureCode = "TS016E"
|
||||
SFTPSymlinkCode = "TS018I"
|
||||
SFTPSymlinkFailureCode = "TS018E"
|
||||
SFTPLinkCode = "TS019I"
|
||||
SFTPLinkFailureCode = "TS019E"
|
||||
SFTPDisallowedCode = "TS020E"
|
||||
// SFTPSummaryCode is the SFTP summary code.
|
||||
SFTPSummaryCode = "TS021I"
|
||||
|
||||
// SessionCommandCode is a session command code.
|
||||
SessionCommandCode = "T4000I"
|
||||
@@ -674,3 +658,7 @@ const (
|
||||
// UnknownCode is used when an event of unknown type is encountered.
|
||||
UnknownCode = apievents.UnknownCode
|
||||
)
|
||||
|
||||
// After defining an event code, make sure to keep
|
||||
// `web/packages/teleport/src/services/audit/types.ts` in sync and add an
|
||||
// entry in the `eventsMap` in `lib/events/events_test.go`.
|
||||
|
||||
@@ -445,6 +445,9 @@ func FromEventFields(fields EventFields) (events.AuditEvent, error) {
|
||||
e = &events.UserTaskUpdate{}
|
||||
case UserTaskDeleteEvent:
|
||||
e = &events.UserTaskDelete{}
|
||||
|
||||
case SFTPSummaryEvent:
|
||||
e = &events.SFTPSummary{}
|
||||
default:
|
||||
slog.ErrorContext(context.Background(), "Attempted to convert dynamic event of unknown type into protobuf event.", "event_type", eventType)
|
||||
unknown := &events.Unknown{}
|
||||
|
||||
@@ -235,6 +235,7 @@ var eventsMap = map[string]apievents.AuditEvent{
|
||||
UserTaskCreateEvent: &apievents.UserTaskCreate{},
|
||||
UserTaskUpdateEvent: &apievents.UserTaskUpdate{},
|
||||
UserTaskDeleteEvent: &apievents.UserTaskDelete{},
|
||||
SFTPSummaryEvent: &apievents.SFTPSummary{},
|
||||
}
|
||||
|
||||
// TestJSON tests JSON marshal events
|
||||
|
||||
+23
-8
@@ -189,20 +189,35 @@ func (s *sftpSubsys) Start(ctx context.Context,
|
||||
return
|
||||
}
|
||||
|
||||
var sftpEvent apievents.SFTP
|
||||
err = jsonpb.UnmarshalString(eventStr[:len(eventStr)-1], &sftpEvent)
|
||||
var oneOfEvent apievents.OneOf
|
||||
err = jsonpb.UnmarshalString(eventStr[:len(eventStr)-1], &oneOfEvent)
|
||||
if err != nil {
|
||||
s.log.WithError(err).Warn("Failed to unmarshal SFTP event.")
|
||||
continue
|
||||
}
|
||||
event, err := apievents.FromOneOf(oneOfEvent)
|
||||
if err != nil {
|
||||
s.log.WithError(err).Warn("Failed to convert SFTP event from OneOf.")
|
||||
continue
|
||||
}
|
||||
|
||||
sftpEvent.Metadata.ClusterName = serverCtx.ClusterName
|
||||
sftpEvent.ServerMetadata = serverMeta
|
||||
sftpEvent.SessionMetadata = sessionMeta
|
||||
sftpEvent.UserMetadata = userMeta
|
||||
sftpEvent.ConnectionMetadata = connectionMeta
|
||||
event.SetClusterName(serverCtx.ClusterName)
|
||||
switch e := event.(type) {
|
||||
case *apievents.SFTP:
|
||||
e.ServerMetadata = serverMeta
|
||||
e.SessionMetadata = sessionMeta
|
||||
e.UserMetadata = userMeta
|
||||
e.ConnectionMetadata = connectionMeta
|
||||
case *apievents.SFTPSummary:
|
||||
e.ServerMetadata = serverMeta
|
||||
e.SessionMetadata = sessionMeta
|
||||
e.UserMetadata = userMeta
|
||||
e.ConnectionMetadata = connectionMeta
|
||||
default:
|
||||
s.log.WithError(err).Warnf("Unknown event type received from SFTP server process: %q", event.GetType())
|
||||
}
|
||||
|
||||
if err := serverCtx.GetServer().EmitAuditEvent(ctx, &sftpEvent); err != nil {
|
||||
if err := serverCtx.GetServer().EmitAuditEvent(ctx, event); err != nil {
|
||||
log.WithError(err).Warn("Failed to emit SFTP event.")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,6 +30,8 @@ import (
|
||||
"os/user"
|
||||
"path"
|
||||
"strings"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"github.com/gogo/protobuf/jsonpb"
|
||||
@@ -89,10 +91,37 @@ type allowedOps struct {
|
||||
type sftpHandler struct {
|
||||
logger *log.Entry
|
||||
allowed *allowedOps
|
||||
events chan<- *apievents.SFTP
|
||||
|
||||
// mtx protects files
|
||||
mtx sync.Mutex
|
||||
files []*trackedFile
|
||||
|
||||
events chan<- apievents.AuditEvent
|
||||
}
|
||||
|
||||
func newSFTPHandler(logger *log.Entry, req *srv.FileTransferRequest, events chan<- *apievents.SFTP) (*sftpHandler, error) {
|
||||
type trackedFile struct {
|
||||
file *os.File
|
||||
bytesRead atomic.Uint64
|
||||
bytesWritten atomic.Uint64
|
||||
}
|
||||
|
||||
func (t *trackedFile) ReadAt(b []byte, off int64) (int, error) {
|
||||
n, err := t.file.ReadAt(b, off)
|
||||
t.bytesRead.Add(uint64(n))
|
||||
return n, err
|
||||
}
|
||||
|
||||
func (t *trackedFile) WriteAt(b []byte, off int64) (int, error) {
|
||||
n, err := t.file.WriteAt(b, off)
|
||||
t.bytesWritten.Add(uint64(n))
|
||||
return n, err
|
||||
}
|
||||
|
||||
func (t *trackedFile) Close() error {
|
||||
return t.file.Close()
|
||||
}
|
||||
|
||||
func newSFTPHandler(logger *log.Entry, req *srv.FileTransferRequest, events chan<- apievents.AuditEvent) (*sftpHandler, error) {
|
||||
var allowed *allowedOps
|
||||
if req != nil {
|
||||
allowed = &allowedOps{
|
||||
@@ -188,7 +217,7 @@ func (s *sftpHandler) Filewrite(req *sftp.Request) (_ io.WriterAt, retErr error)
|
||||
return s.openFile(req)
|
||||
}
|
||||
|
||||
func (s *sftpHandler) openFile(req *sftp.Request) (*os.File, error) {
|
||||
func (s *sftpHandler) openFile(req *sftp.Request) (sftp.WriterAtReaderAt, error) {
|
||||
if err := s.ensureReqIsAllowed(req); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -220,8 +249,12 @@ func (s *sftpHandler) openFile(req *sftp.Request) (*os.File, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
trackFile := &trackedFile{file: f}
|
||||
s.mtx.Lock()
|
||||
s.files = append(s.files, trackFile)
|
||||
s.mtx.Unlock()
|
||||
|
||||
return f, nil
|
||||
return trackFile, nil
|
||||
}
|
||||
|
||||
// Filecmd handles file modification requests.
|
||||
@@ -607,7 +640,7 @@ func onSFTP() error {
|
||||
}
|
||||
ch := compositeCh{io.NopCloser(bufferedReader), chw}
|
||||
|
||||
sftpEvents := make(chan *apievents.SFTP, 1)
|
||||
sftpEvents := make(chan apievents.AuditEvent, 1)
|
||||
h, err := newSFTPHandler(logger, fileTransferReq, sftpEvents)
|
||||
if err != nil {
|
||||
return trace.Wrap(err)
|
||||
@@ -627,17 +660,24 @@ func onSFTP() error {
|
||||
var m jsonpb.Marshaler
|
||||
var buf bytes.Buffer
|
||||
for event := range sftpEvents {
|
||||
oneOfEvent, err := apievents.ToOneOf(event)
|
||||
if err != nil {
|
||||
logger.WithError(err).Warn("Failed to convert SFTP event to OneOf.")
|
||||
continue
|
||||
}
|
||||
|
||||
buf.Reset()
|
||||
if err := m.Marshal(&buf, event); err != nil {
|
||||
if err := m.Marshal(&buf, oneOfEvent); err != nil {
|
||||
logger.WithError(err).Warn("Failed to marshal SFTP event.")
|
||||
} else {
|
||||
// Append a NULL byte so the parent process will know where
|
||||
// this event ends
|
||||
buf.WriteByte(0x0)
|
||||
_, err = io.Copy(auditFile, &buf)
|
||||
if err != nil {
|
||||
logger.WithError(err).Warn("Failed to send SFTP event to parent.")
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
// Append a NULL byte so the parent process will know where
|
||||
// this event ends
|
||||
buf.WriteByte(0x0)
|
||||
_, err = io.Copy(auditFile, &buf)
|
||||
if err != nil {
|
||||
logger.WithError(err).Warn("Failed to send SFTP event to parent.")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -651,6 +691,25 @@ func onSFTP() error {
|
||||
serveErr = trace.Wrap(serveErr)
|
||||
}
|
||||
|
||||
// Send a summary event last
|
||||
summaryEvent := &apievents.SFTPSummary{
|
||||
Metadata: apievents.Metadata{
|
||||
Type: events.SFTPSummaryEvent,
|
||||
Code: events.SFTPSummaryCode,
|
||||
Time: time.Now(),
|
||||
},
|
||||
}
|
||||
// We don't need to worry about closing these files, handler will
|
||||
// take care of that for us
|
||||
for _, f := range h.files {
|
||||
summaryEvent.FileTransferStats = append(summaryEvent.FileTransferStats, &apievents.FileTransferStat{
|
||||
Path: f.file.Name(),
|
||||
BytesRead: f.bytesRead.Load(),
|
||||
BytesWritten: f.bytesWritten.Load(),
|
||||
})
|
||||
}
|
||||
sftpEvents <- summaryEvent
|
||||
|
||||
// Wait until event marshaling goroutine is finished
|
||||
close(sftpEvents)
|
||||
<-done
|
||||
|
||||
@@ -50,20 +50,8 @@ const EventIconMap: Record<EventCode, any> = {
|
||||
[eventCodes.SCP_DISALLOWED]: Icons.FolderPlus,
|
||||
[eventCodes.SFTP_OPEN_FAILURE]: Icons.FolderPlus,
|
||||
[eventCodes.SFTP_OPEN]: Icons.FolderPlus,
|
||||
[eventCodes.SFTP_CLOSE_FAILURE]: Icons.FolderPlus,
|
||||
[eventCodes.SFTP_CLOSE]: Icons.FolderPlus,
|
||||
[eventCodes.SFTP_READ_FAILURE]: Icons.FolderPlus,
|
||||
[eventCodes.SFTP_READ]: Icons.FolderPlus,
|
||||
[eventCodes.SFTP_WRITE_FAILURE]: Icons.FolderPlus,
|
||||
[eventCodes.SFTP_WRITE]: Icons.FolderPlus,
|
||||
[eventCodes.SFTP_LSTAT_FAILURE]: Icons.FolderPlus,
|
||||
[eventCodes.SFTP_LSTAT]: Icons.FolderPlus,
|
||||
[eventCodes.SFTP_FSTAT_FAILURE]: Icons.FolderPlus,
|
||||
[eventCodes.SFTP_FSTAT]: Icons.FolderPlus,
|
||||
[eventCodes.SFTP_SETSTAT_FAILURE]: Icons.FolderPlus,
|
||||
[eventCodes.SFTP_SETSTAT]: Icons.FolderPlus,
|
||||
[eventCodes.SFTP_FSETSTAT_FAILURE]: Icons.FolderPlus,
|
||||
[eventCodes.SFTP_FSETSTAT]: Icons.FolderPlus,
|
||||
[eventCodes.SFTP_OPENDIR_FAILURE]: Icons.FolderPlus,
|
||||
[eventCodes.SFTP_OPENDIR]: Icons.FolderPlus,
|
||||
[eventCodes.SFTP_READDIR_FAILURE]: Icons.FolderPlus,
|
||||
@@ -74,14 +62,8 @@ const EventIconMap: Record<EventCode, any> = {
|
||||
[eventCodes.SFTP_MKDIR]: Icons.FolderPlus,
|
||||
[eventCodes.SFTP_RMDIR_FAILURE]: Icons.FolderPlus,
|
||||
[eventCodes.SFTP_RMDIR]: Icons.FolderPlus,
|
||||
[eventCodes.SFTP_REALPATH_FAILURE]: Icons.FolderPlus,
|
||||
[eventCodes.SFTP_REALPATH]: Icons.FolderPlus,
|
||||
[eventCodes.SFTP_STAT_FAILURE]: Icons.FolderPlus,
|
||||
[eventCodes.SFTP_STAT]: Icons.FolderPlus,
|
||||
[eventCodes.SFTP_RENAME_FAILURE]: Icons.FolderPlus,
|
||||
[eventCodes.SFTP_RENAME]: Icons.FolderPlus,
|
||||
[eventCodes.SFTP_READLINK_FAILURE]: Icons.FolderPlus,
|
||||
[eventCodes.SFTP_READLINK]: Icons.FolderPlus,
|
||||
[eventCodes.SFTP_SYMLINK_FAILURE]: Icons.FolderPlus,
|
||||
[eventCodes.SFTP_SYMLINK]: Icons.FolderPlus,
|
||||
[eventCodes.SFTP_LINK]: Icons.FolderPlus,
|
||||
@@ -297,6 +279,7 @@ const EventIconMap: Record<EventCode, any> = {
|
||||
[eventCodes.USER_TASK_CREATE]: Icons.Info,
|
||||
[eventCodes.USER_TASK_UPDATE]: Icons.Info,
|
||||
[eventCodes.USER_TASK_DELETE]: Icons.Info,
|
||||
[eventCodes.SFTP_SUMMARY]: Icons.FolderPlus,
|
||||
[eventCodes.UNKNOWN]: Icons.Question,
|
||||
};
|
||||
|
||||
|
||||
@@ -305,86 +305,6 @@ export const formatters: Formatters = {
|
||||
rest['server_hostname'] || rest['addr.local']
|
||||
}]: [${error}]`,
|
||||
},
|
||||
[eventCodes.SFTP_CLOSE]: {
|
||||
type: 'sftp',
|
||||
desc: 'SFTP Close',
|
||||
format: ({ user, path, ...rest }) =>
|
||||
`User [${user}] closed file [${path}] on node [${
|
||||
rest['server_hostname'] || rest['addr.local']
|
||||
}]`,
|
||||
},
|
||||
[eventCodes.SFTP_CLOSE_FAILURE]: {
|
||||
type: 'sftp',
|
||||
desc: 'SFTP Close Failed',
|
||||
format: ({ user, path, error, ...rest }) =>
|
||||
`User [${user}] failed to close file [${path}] on node [${
|
||||
rest['server_hostname'] || rest['addr.local']
|
||||
}]: [${error}]`,
|
||||
},
|
||||
[eventCodes.SFTP_READ]: {
|
||||
type: 'sftp',
|
||||
desc: 'SFTP Read',
|
||||
format: ({ user, path, ...rest }) =>
|
||||
`User [${user}] read from file [${path}] on node [${
|
||||
rest['server_hostname'] || rest['addr.local']
|
||||
}]`,
|
||||
},
|
||||
[eventCodes.SFTP_READ_FAILURE]: {
|
||||
type: 'sftp',
|
||||
desc: 'SFTP Read Failed',
|
||||
format: ({ user, path, error, ...rest }) =>
|
||||
`User [${user}] failed to read from file [${path}] on node [${
|
||||
rest['server_hostname'] || rest['addr.local']
|
||||
}]: [${error}]`,
|
||||
},
|
||||
[eventCodes.SFTP_WRITE]: {
|
||||
type: 'sftp',
|
||||
desc: 'SFTP Write',
|
||||
format: ({ user, path, ...rest }) =>
|
||||
`User [${user}] wrote to file [${path}] on node [${
|
||||
rest['server_hostname'] || rest['addr.local']
|
||||
}]`,
|
||||
},
|
||||
[eventCodes.SFTP_WRITE_FAILURE]: {
|
||||
type: 'sftp',
|
||||
desc: 'SFTP Write Failed',
|
||||
format: ({ user, path, error, ...rest }) =>
|
||||
`User [${user}] failed to write to file [${path}] on node [${
|
||||
rest['server_hostname'] || rest['addr.local']
|
||||
}]: [${error}]`,
|
||||
},
|
||||
[eventCodes.SFTP_LSTAT]: {
|
||||
type: 'sftp',
|
||||
desc: 'SFTP Lstat',
|
||||
format: ({ user, path, ...rest }) =>
|
||||
`User [${user}] queried attributes of file [${path}] on node [${
|
||||
rest['server_hostname'] || rest['addr.local']
|
||||
}]`,
|
||||
},
|
||||
[eventCodes.SFTP_LSTAT_FAILURE]: {
|
||||
type: 'sftp',
|
||||
desc: 'SFTP Lstat Failed',
|
||||
format: ({ user, path, error, ...rest }) =>
|
||||
`User [${user}] failed to query attributes of file [${path}] on node [${
|
||||
rest['server_hostname'] || rest['addr.local']
|
||||
}]: [${error}]`,
|
||||
},
|
||||
[eventCodes.SFTP_FSTAT]: {
|
||||
type: 'sftp',
|
||||
desc: 'SFTP Fstat',
|
||||
format: ({ user, path, ...rest }) =>
|
||||
`User [${user}] queried attributes of file [${path}] on node [${
|
||||
rest['server_hostname'] || rest['addr.local']
|
||||
}]`,
|
||||
},
|
||||
[eventCodes.SFTP_FSTAT_FAILURE]: {
|
||||
type: 'sftp',
|
||||
desc: 'SFTP Fstat Failed',
|
||||
format: ({ user, path, error, ...rest }) =>
|
||||
`User [${user}] failed to query attributes of file [${path}] on node [${
|
||||
rest['server_hostname'] || rest['addr.local']
|
||||
}]: [${error}]`,
|
||||
},
|
||||
[eventCodes.SFTP_SETSTAT]: {
|
||||
type: 'sftp',
|
||||
desc: 'SFTP Setstat',
|
||||
@@ -401,22 +321,6 @@ export const formatters: Formatters = {
|
||||
rest['server_hostname'] || rest['addr.local']
|
||||
}]: [${error}]`,
|
||||
},
|
||||
[eventCodes.SFTP_FSETSTAT]: {
|
||||
type: 'sftp',
|
||||
desc: 'SFTP Fsetstat',
|
||||
format: ({ user, path, ...rest }) =>
|
||||
`User [${user}] changed attributes of file [${path}] on node [${
|
||||
rest['server_hostname'] || rest['addr.local']
|
||||
}]`,
|
||||
},
|
||||
[eventCodes.SFTP_FSETSTAT_FAILURE]: {
|
||||
type: 'sftp',
|
||||
desc: 'SFTP Fsetstat Failed',
|
||||
format: ({ user, path, error, ...rest }) =>
|
||||
`User [${user}] failed to change attributes of file [${path}] on node [${
|
||||
rest['server_hostname'] || rest['addr.local']
|
||||
}]: [${error}]`,
|
||||
},
|
||||
[eventCodes.SFTP_OPENDIR]: {
|
||||
type: 'sftp',
|
||||
desc: 'SFTP Opendir',
|
||||
@@ -497,38 +401,6 @@ export const formatters: Formatters = {
|
||||
rest['server_hostname'] || rest['addr.local']
|
||||
}]: [${error}]`,
|
||||
},
|
||||
[eventCodes.SFTP_REALPATH]: {
|
||||
type: 'sftp',
|
||||
desc: 'SFTP Realpath',
|
||||
format: ({ user, path, ...rest }) =>
|
||||
`User [${user}] queried absolute path of file [${path}] on node [${
|
||||
rest['server_hostname'] || rest['addr.local']
|
||||
}]`,
|
||||
},
|
||||
[eventCodes.SFTP_REALPATH_FAILURE]: {
|
||||
type: 'sftp',
|
||||
desc: 'SFTP Realpath Failed',
|
||||
format: ({ user, path, error, ...rest }) =>
|
||||
`User [${user}] failed to query absolute path of file [${path}] on node [${
|
||||
rest['server_hostname'] || rest['addr.local']
|
||||
}]: [${error}]`,
|
||||
},
|
||||
[eventCodes.SFTP_STAT]: {
|
||||
type: 'sftp',
|
||||
desc: 'SFTP Stat',
|
||||
format: ({ user, path, ...rest }) =>
|
||||
`User [${user}] queried attributes of file [${path}] on node [${
|
||||
rest['server_hostname'] || rest['addr.local']
|
||||
}]`,
|
||||
},
|
||||
[eventCodes.SFTP_STAT_FAILURE]: {
|
||||
type: 'sftp',
|
||||
desc: 'SFTP Stat Failed',
|
||||
format: ({ user, path, error, ...rest }) =>
|
||||
`User [${user}] failed to query attributes of file [${path}] on node [${
|
||||
rest['server_hostname'] || rest['addr.local']
|
||||
}]: [${error}]`,
|
||||
},
|
||||
[eventCodes.SFTP_RENAME]: {
|
||||
type: 'sftp',
|
||||
desc: 'SFTP Rename',
|
||||
@@ -545,22 +417,6 @@ export const formatters: Formatters = {
|
||||
rest['server_hostname'] || rest['addr.local']
|
||||
}]: [${error}]`,
|
||||
},
|
||||
[eventCodes.SFTP_READLINK]: {
|
||||
type: 'sftp',
|
||||
desc: 'SFTP Readlink',
|
||||
format: ({ user, path, ...rest }) =>
|
||||
`User [${user}] read symbolic link [${path}] on node [${
|
||||
rest['server_hostname'] || rest['addr.local']
|
||||
}]`,
|
||||
},
|
||||
[eventCodes.SFTP_READLINK_FAILURE]: {
|
||||
type: 'sftp',
|
||||
desc: 'SFTP Readlink Failed',
|
||||
format: ({ user, path, error, ...rest }) =>
|
||||
`User [${user}] failed to read symbolic link [${path}] on node [${
|
||||
rest['server_hostname'] || rest['addr.local']
|
||||
}]: [${error}]`,
|
||||
},
|
||||
[eventCodes.SFTP_SYMLINK]: {
|
||||
type: 'sftp',
|
||||
desc: 'SFTP Symlink',
|
||||
@@ -1971,6 +1827,13 @@ export const formatters: Formatters = {
|
||||
return `User [${user}] deleted a user task [${name}]`;
|
||||
},
|
||||
},
|
||||
[eventCodes.SFTP_SUMMARY]: {
|
||||
type: 'sftp_summary',
|
||||
desc: 'File Transfer Completed',
|
||||
format: ({ user, server_hostname }) => {
|
||||
return `User [${user}] completed a file transfer on [${server_hostname}]`;
|
||||
},
|
||||
},
|
||||
[eventCodes.UNKNOWN]: {
|
||||
type: 'unknown',
|
||||
desc: 'Unknown Event',
|
||||
|
||||
@@ -163,20 +163,8 @@ export const eventCodes = {
|
||||
SCP_DISALLOWED: 'T3010E',
|
||||
SFTP_OPEN_FAILURE: 'TS001E',
|
||||
SFTP_OPEN: 'TS001I',
|
||||
SFTP_CLOSE_FAILURE: 'TS002E',
|
||||
SFTP_CLOSE: 'TS002I',
|
||||
SFTP_READ_FAILURE: 'TS003E',
|
||||
SFTP_READ: 'TS003I',
|
||||
SFTP_WRITE_FAILURE: 'TS004E',
|
||||
SFTP_WRITE: 'TS004I',
|
||||
SFTP_LSTAT_FAILURE: 'TS005E',
|
||||
SFTP_LSTAT: 'TS005I',
|
||||
SFTP_FSTAT_FAILURE: 'TS006E',
|
||||
SFTP_FSTAT: 'TS006I',
|
||||
SFTP_SETSTAT_FAILURE: 'TS007E',
|
||||
SFTP_SETSTAT: 'TS007I',
|
||||
SFTP_FSETSTAT_FAILURE: 'TS008E',
|
||||
SFTP_FSETSTAT: 'TS008I',
|
||||
SFTP_OPENDIR_FAILURE: 'TS009E',
|
||||
SFTP_OPENDIR: 'TS009I',
|
||||
SFTP_READDIR_FAILURE: 'TS010E',
|
||||
@@ -187,19 +175,14 @@ export const eventCodes = {
|
||||
SFTP_MKDIR: 'TS012I',
|
||||
SFTP_RMDIR_FAILURE: 'TS013E',
|
||||
SFTP_RMDIR: 'TS013I',
|
||||
SFTP_REALPATH_FAILURE: 'TS014E',
|
||||
SFTP_REALPATH: 'TS014I',
|
||||
SFTP_STAT_FAILURE: 'TS015E',
|
||||
SFTP_STAT: 'TS015I',
|
||||
SFTP_RENAME_FAILURE: 'TS016E',
|
||||
SFTP_RENAME: 'TS016I',
|
||||
SFTP_READLINK_FAILURE: 'TS017E',
|
||||
SFTP_READLINK: 'TS017I',
|
||||
SFTP_SYMLINK_FAILURE: 'TS018E',
|
||||
SFTP_SYMLINK: 'TS018I',
|
||||
SFTP_LINK: 'TS019I',
|
||||
SFTP_LINK_FAILURE: 'TS019E',
|
||||
SFTP_DISALLOWED: 'TS020E',
|
||||
SFTP_SUMMARY: 'TS021I',
|
||||
SESSION_COMMAND: 'T4000I',
|
||||
SESSION_DATA: 'T2006I',
|
||||
SESSION_DISK: 'T4001I',
|
||||
@@ -457,34 +440,10 @@ export type RawEvents = {
|
||||
[eventCodes.SFTP_OPEN_FAILURE]: RawEventSFTP<
|
||||
typeof eventCodes.SFTP_OPEN_FAILURE
|
||||
>;
|
||||
[eventCodes.SFTP_CLOSE]: RawEventSFTP<typeof eventCodes.SFTP_CLOSE>;
|
||||
[eventCodes.SFTP_CLOSE_FAILURE]: RawEventSFTP<
|
||||
typeof eventCodes.SFTP_CLOSE_FAILURE
|
||||
>;
|
||||
[eventCodes.SFTP_READ]: RawEventSFTP<typeof eventCodes.SFTP_READ>;
|
||||
[eventCodes.SFTP_READ_FAILURE]: RawEventSFTP<
|
||||
typeof eventCodes.SFTP_READ_FAILURE
|
||||
>;
|
||||
[eventCodes.SFTP_WRITE]: RawEventSFTP<typeof eventCodes.SFTP_WRITE>;
|
||||
[eventCodes.SFTP_WRITE_FAILURE]: RawEventSFTP<
|
||||
typeof eventCodes.SFTP_WRITE_FAILURE
|
||||
>;
|
||||
[eventCodes.SFTP_LSTAT]: RawEventSFTP<typeof eventCodes.SFTP_LSTAT>;
|
||||
[eventCodes.SFTP_LSTAT_FAILURE]: RawEventSFTP<
|
||||
typeof eventCodes.SFTP_LSTAT_FAILURE
|
||||
>;
|
||||
[eventCodes.SFTP_FSTAT]: RawEventSFTP<typeof eventCodes.SFTP_FSTAT>;
|
||||
[eventCodes.SFTP_FSTAT_FAILURE]: RawEventSFTP<
|
||||
typeof eventCodes.SFTP_FSTAT_FAILURE
|
||||
>;
|
||||
[eventCodes.SFTP_SETSTAT]: RawEventSFTP<typeof eventCodes.SFTP_SETSTAT>;
|
||||
[eventCodes.SFTP_SETSTAT_FAILURE]: RawEventSFTP<
|
||||
typeof eventCodes.SFTP_SETSTAT_FAILURE
|
||||
>;
|
||||
[eventCodes.SFTP_FSETSTAT]: RawEventSFTP<typeof eventCodes.SFTP_FSETSTAT>;
|
||||
[eventCodes.SFTP_FSETSTAT_FAILURE]: RawEventSFTP<
|
||||
typeof eventCodes.SFTP_FSETSTAT_FAILURE
|
||||
>;
|
||||
[eventCodes.SFTP_OPENDIR]: RawEventSFTP<typeof eventCodes.SFTP_OPENDIR>;
|
||||
[eventCodes.SFTP_OPENDIR_FAILURE]: RawEventSFTP<
|
||||
typeof eventCodes.SFTP_OPENDIR_FAILURE
|
||||
@@ -505,22 +464,10 @@ export type RawEvents = {
|
||||
[eventCodes.SFTP_RMDIR_FAILURE]: RawEventSFTP<
|
||||
typeof eventCodes.SFTP_RMDIR_FAILURE
|
||||
>;
|
||||
[eventCodes.SFTP_REALPATH]: RawEventSFTP<typeof eventCodes.SFTP_REALPATH>;
|
||||
[eventCodes.SFTP_REALPATH_FAILURE]: RawEventSFTP<
|
||||
typeof eventCodes.SFTP_REALPATH_FAILURE
|
||||
>;
|
||||
[eventCodes.SFTP_STAT]: RawEventSFTP<typeof eventCodes.SFTP_STAT>;
|
||||
[eventCodes.SFTP_STAT_FAILURE]: RawEventSFTP<
|
||||
typeof eventCodes.SFTP_STAT_FAILURE
|
||||
>;
|
||||
[eventCodes.SFTP_RENAME]: RawEventSFTP<typeof eventCodes.SFTP_RENAME>;
|
||||
[eventCodes.SFTP_RENAME_FAILURE]: RawEventSFTP<
|
||||
typeof eventCodes.SFTP_RENAME_FAILURE
|
||||
>;
|
||||
[eventCodes.SFTP_READLINK]: RawEventSFTP<typeof eventCodes.SFTP_READLINK>;
|
||||
[eventCodes.SFTP_READLINK_FAILURE]: RawEventSFTP<
|
||||
typeof eventCodes.SFTP_READLINK_FAILURE
|
||||
>;
|
||||
[eventCodes.SFTP_SYMLINK]: RawEventSFTP<typeof eventCodes.SFTP_SYMLINK>;
|
||||
[eventCodes.SFTP_SYMLINK_FAILURE]: RawEventSFTP<
|
||||
typeof eventCodes.SFTP_SYMLINK_FAILURE
|
||||
@@ -1746,6 +1693,13 @@ export type RawEvents = {
|
||||
typeof eventCodes.USER_TASK_DELETE,
|
||||
HasName
|
||||
>;
|
||||
[eventCodes.SFTP_SUMMARY]: RawEvent<
|
||||
typeof eventCodes.SFTP_SUMMARY,
|
||||
{
|
||||
user: string;
|
||||
server_hostname: string;
|
||||
}
|
||||
>;
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user