Skip to content

Commit

Permalink
emit an audit event with file transfer statistics when an SFTP sessio…
Browse files Browse the repository at this point in the history
…n 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
  • Loading branch information
capnspacehook authored Oct 30, 2024
1 parent 6160a3d commit 1589413
Show file tree
Hide file tree
Showing 13 changed files with 2,663 additions and 1,971 deletions.
49 changes: 49 additions & 0 deletions api/proto/teleport/legacy/types/events/events.proto
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -4615,6 +4663,7 @@ message OneOf {
events.UserTaskCreate UserTaskCreate = 188;
events.UserTaskUpdate UserTaskUpdate = 189;
events.UserTaskDelete UserTaskDelete = 190;
events.SFTPSummary SFTPSummary = 191;
}
}

Expand Down
26 changes: 26 additions & 0 deletions api/types/events/events.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Loading

0 comments on commit 1589413

Please sign in to comment.