Documentation ¶
Overview ¶
Package events implements the audit log interface events.IAuditLog using filesystem backend.
Audit logs ----------
Audit logs are events associated with user logins, server access and session log events like session.start.
Example audit log event:
{"addr.local":"172.10.1.20:3022",
"addr.remote":"172.10.1.254:58866", "event":"session.start", "login":"root", "user":"[email protected]" }
Session Logs ------------
Session logs are a series of events and recorded SSH interactive session playback.
Example session log event:
{ "time":"2018-01-04T02:12:40.245Z", "event":"print", "bytes":936, "ms":40962, "offset":16842, "ei":31, "ci":29 }
Print event fields ------------------
Print event specifies session output - PTY io recorded by Teleport node or Proxy based on the configuration.
* "offset" is an offset in bytes from a start of a session * "ms" is a delay in milliseconds from the last event occurred * "ci" is a chunk index ordering only print events * "ei" is an event index ordering events from the first one
As in example of print event above, "ei" - is a session event index - 31, while "ci" is a chunk index - meaning that this event is 29th in a row of print events.
Client streaming session logs ------------------------------
Session related logs are delivered in order defined by clients. Every event is ordered and has a session-local index, every next event has index incremented.
Client delivers session events in batches, where every event in the batch is guaranteed to be in continuous order (e.g. no cases with events delivered in a single batch to have missing event or chunk index).
Disk File format ----------------
On disk file format is designed to be compatible with NFS filesystems and provides guarantee that only one auth server writes to the file at a time.
Main Audit Log Format =====================
The main log files are saved as:
/var/lib/teleport/log/<auth-server-id>/<date>.log
The log file is rotated every 24 hours. The old files must be cleaned up or archived by an external tool.
Log file format: utc_date,action,json_fields
Common JSON fields - user : teleport user - login : server OS login, the user logged in as - addr.local : server address:port - addr.remote: connected client's address:port - sid : session ID (GUID format)
Examples: 2016-04-25 22:37:29 +0000 UTC,session.start,{"addr.local":"127.0.0.1:3022","addr.remote":"127.0.0.1:35732","login":"root","sid":"4a9d97de-0b36-11e6-a0b3-d8cb8ae5080e","user":"vincent"} 2016-04-25 22:54:31 +0000 UTC,exec,{"addr.local":"127.0.0.1:3022","addr.remote":"127.0.0.1:35949","command":"-bash -c ls /","login":"root","user":"vincent"}
Session log file format =======================
Each session has its own session log stored as several files:
Index file contains a list of event files and chunks files associated with a session:
/var/lib/teleport/log/sessions/<auth-server-id>/<session-id>.index
The format of the index file contains of two or more lines with pointers to other files:
{"file_name":"<session-id>-<first-event-in-file-index>.events","type":"events","index":<first-event-in-file-index>} {"file_name":"<session-id>-<first-chunk-in-file-offset>.chunks","type":"chunks","offset":<first-chunk-in-file-offset>}
Files:
/var/lib/teleport/log/<auth-server-id>/<session-id>-<first-event-in-file-index>.events /var/lib/teleport/log/<auth-server-id>/<session-id>-<first-chunk-in-file-offset>.chunks
Where:
- .events (same events as in the main log, but related to the session)
- .chunks (recorded session bytes: PTY IO)
Examples ~~~~~~~~
**Single auth server**
In the simplest case, single auth server a1 log for a single session id s1 will consist of three files:
/var/lib/teleport/a1/s1.index
With contents:
{"file_name":"s1-0.events","type":"events","index":0} {"file_name":"s1-0.chunks","type":"chunks","offset":0}
This means that all session events are located in s1-0.events file starting from the first event with index 0 and all chunks are located in file s1-0.chunks file with the byte offset from the start - 0.
File with session events /var/lib/teleport/a1/s1-0.events will contain:
{"ei":0,"event":"session.start", ...} {"ei":1,"event":"resize",...} {"ei":2,"ci":0, "event":"print","bytes":40,"offset":0} {"ei":3,"event":"session.end", ...}
File with recorded session /var/lib/teleport/a1/s1-0.chunks will contain 40 bytes emitted by print event with chunk index 0
**Multiple Auth Servers**
In high availability mode scenario, multiple auth servers will be
deployed behind a load balancer.
Any auth server can go down during session and clients will retry the delivery to the other auth server.
Both auth servers have mounted /var/lib/teleport/log as a shared NFS folder.
To make sure that only one auth server writes to a file at a time, each auth server writes to it's own file in a sub folder named with host UUID of the server.
Client sends the chunks of events related to the session s1 in order, but load balancer sends first batch of event to the first server a1, and the second batch of event to the second server a2.
Server a1 will produce the following file:
/var/lib/teleport/a1/s1.index
With contents:
{"file_name":"s1-0.events","type":"events","index":0} {"file_name":"s1-0.chunks","type":"chunks","offset":0}
Events file /var/lib/teleport/a1/s1-0.events will contain:
{"ei":0,"event":"session.start", ...} {"ei":1,"event":"resize",...} {"ei":2,"ci":0, "event":"print","bytes":40,"offset":0}
Events file /var/lib/teleport/a1/s1-0.chunks will contain 40 bytes emitted by print event with chunk index.
Server a2 will produce the following file:
/var/lib/teleport/a2/s1.index
With contents:
{"file_name":"s1-3.events","type":"events","index":3} {"file_name":"s1-40.chunks","type":"chunks","offset":40}
Events file /var/lib/teleport/a2/s1-4.events will contain:
{"ei":3,"ci":1, "event":"print","bytes":15,"ms":713,"offset":40} {"ei":4,"event":"session.end", ...}
Events file /var/lib/teleport/a2/s1-40.chunks will contain 15 bytes emitted by print event with chunk index 1 and comes after delay of 713 milliseconds.
Offset 40 indicates that the first chunk stored in the file s1-40.chunks comes at an offset of 40 bytes from the start of the session.
Log Search and Playback -----------------------
Log search and playback is aware of multiple auth servers, merges indexes, event streams stored on multiple auth servers.
Index ¶
- Constants
- Variables
- func NewSessionArchive(dataDir, serverID, namespace string, sessionID session.ID) (io.ReadCloser, error)
- func PrintEventFromChunk(chunk *SessionChunk) printEvent
- func RegisterAuditLogServer(s *grpc.Server, srv AuditLogServer)
- func UpdateEventFields(event Event, fields EventFields, clock clockwork.Clock, uid utils.UID) (err error)
- func ValidateArchive(reader io.Reader, serverID string) error
- func ValidateEvent(f EventFields, serverID string) error
- type AuditLog
- func (l *AuditLog) Close() error
- func (l *AuditLog) EmitAuditEvent(event Event, fields EventFields) error
- func (l *AuditLog) GetSessionChunk(namespace string, sid session.ID, offsetBytes, maxBytes int) ([]byte, error)
- func (l *AuditLog) GetSessionEvents(namespace string, sid session.ID, afterN int, includePrintEvents bool) ([]EventFields, error)
- func (l *AuditLog) PostSessionSlice(slice SessionSlice) error
- func (l *AuditLog) SearchEvents(fromUTC, toUTC time.Time, query string, limit int) ([]EventFields, error)
- func (l *AuditLog) SearchSessionEvents(fromUTC, toUTC time.Time, limit int) ([]EventFields, error)
- func (l *AuditLog) UploadSessionRecording(r SessionRecording) error
- func (l *AuditLog) WaitForDelivery(context.Context) error
- type AuditLogClient
- type AuditLogConfig
- type AuditLogEvent
- type AuditLogServer
- type AuditLog_SubmitSessionSliceClient
- type AuditLog_SubmitSessionSliceServer
- type ByTimeAndIndex
- type DiscardAuditLog
- func (d *DiscardAuditLog) Close() error
- func (d *DiscardAuditLog) EmitAuditEvent(event Event, fields EventFields) error
- func (d *DiscardAuditLog) GetSessionChunk(namespace string, sid session.ID, offsetBytes, maxBytes int) ([]byte, error)
- func (d *DiscardAuditLog) GetSessionEvents(namespace string, sid session.ID, after int, includePrintEvents bool) ([]EventFields, error)
- func (d *DiscardAuditLog) PostSessionSlice(SessionSlice) error
- func (d *DiscardAuditLog) SearchEvents(fromUTC, toUTC time.Time, query string, limit int) ([]EventFields, error)
- func (d *DiscardAuditLog) SearchSessionEvents(fromUTC time.Time, toUTC time.Time, limit int) ([]EventFields, error)
- func (d *DiscardAuditLog) UploadSessionRecording(SessionRecording) error
- func (d *DiscardAuditLog) WaitForDelivery(context.Context) error
- type DiscardRecorder
- type DiskSessionLogger
- type DiskSessionLoggerConfig
- type EmittedEvent
- type Event
- type EventFields
- func (f EventFields) AsString() string
- func (f EventFields) GetCode() string
- func (f EventFields) GetID() string
- func (f EventFields) GetInt(key string) int
- func (f EventFields) GetString(key string) string
- func (f EventFields) GetTime(key string) time.Time
- func (f EventFields) GetTimestamp() time.Time
- func (f EventFields) GetType() string
- func (f EventFields) HasField(key string) bool
- type FileLog
- func (l *FileLog) Close() error
- func (l *FileLog) EmitAuditEvent(event Event, fields EventFields) error
- func (l *FileLog) GetSessionChunk(namespace string, sid session.ID, offsetBytes, maxBytes int) ([]byte, error)
- func (l *FileLog) GetSessionEvents(namespace string, sid session.ID, after int, fetchPrintEvents bool) ([]EventFields, error)
- func (l *FileLog) PostSessionSlice(slice SessionSlice) error
- func (l *FileLog) SearchEvents(fromUTC, toUTC time.Time, query string, limit int) ([]EventFields, error)
- func (l *FileLog) SearchSessionEvents(fromUTC, toUTC time.Time, limit int) ([]EventFields, error)
- func (l *FileLog) UploadSessionRecording(SessionRecording) error
- func (l *FileLog) WaitForDelivery(context.Context) error
- type FileLogConfig
- type ForwardRecorder
- type ForwardRecorderConfig
- type Forwarder
- func (l *Forwarder) Close() error
- func (l *Forwarder) EmitAuditEvent(event Event, fields EventFields) error
- func (l *Forwarder) GetSessionChunk(namespace string, sid session.ID, offsetBytes, maxBytes int) ([]byte, error)
- func (l *Forwarder) GetSessionEvents(namespace string, sid session.ID, after int, includePrintEvents bool) ([]EventFields, error)
- func (l *Forwarder) PostSessionSlice(slice SessionSlice) error
- func (l *Forwarder) SearchEvents(fromUTC, toUTC time.Time, query string, limit int) ([]EventFields, error)
- func (l *Forwarder) SearchSessionEvents(fromUTC time.Time, toUTC time.Time, limit int) ([]EventFields, error)
- func (l *Forwarder) UploadSessionRecording(r SessionRecording) error
- func (l *Forwarder) WaitForDelivery(ctx context.Context) error
- type ForwarderConfig
- type IAuditLog
- type MockAuditLog
- func (d *MockAuditLog) Close() error
- func (d *MockAuditLog) EmitAuditEvent(ev Event, fields EventFields) error
- func (d *MockAuditLog) GetError() error
- func (d *MockAuditLog) GetSessionChunk(namespace string, sid session.ID, offsetBytes, maxBytes int) ([]byte, error)
- func (d *MockAuditLog) GetSessionEvents(namespace string, sid session.ID, after int, fetchPrintEvents bool) ([]EventFields, error)
- func (d *MockAuditLog) PostSessionSlice(slice SessionSlice) error
- func (d *MockAuditLog) Reset()
- func (d *MockAuditLog) SearchEvents(fromUTC, toUTC time.Time, query string, limit int) ([]EventFields, error)
- func (d *MockAuditLog) SearchSessionEvents(fromUTC, toUTC time.Time, limit int) ([]EventFields, error)
- func (d *MockAuditLog) SetError(e error)
- func (d *MockAuditLog) UploadSessionRecording(SessionRecording) error
- func (d *MockAuditLog) WaitForDelivery(context.Context) error
- type MultiLog
- func (m *MultiLog) Close() error
- func (m *MultiLog) EmitAuditEvent(event Event, fields EventFields) error
- func (m *MultiLog) GetSessionChunk(namespace string, sid session.ID, offsetBytes, maxBytes int) (data []byte, err error)
- func (m *MultiLog) GetSessionEvents(namespace string, sid session.ID, after int, fetchPrintEvents bool) (events []EventFields, err error)
- func (m *MultiLog) PostSessionSlice(slice SessionSlice) error
- func (m *MultiLog) SearchEvents(fromUTC, toUTC time.Time, query string, limit int) (events []EventFields, err error)
- func (m *MultiLog) SearchSessionEvents(fromUTC, toUTC time.Time, limit int) (events []EventFields, err error)
- func (m *MultiLog) UploadSessionRecording(rec SessionRecording) error
- func (m *MultiLog) WaitForDelivery(ctx context.Context) error
- type SessionChunk
- func (*SessionChunk) Descriptor() ([]byte, []int)
- func (m *SessionChunk) GetChunkIndex() int64
- func (m *SessionChunk) GetData() []byte
- func (m *SessionChunk) GetDelay() int64
- func (m *SessionChunk) GetEventIndex() int64
- func (m *SessionChunk) GetEventType() string
- func (m *SessionChunk) GetOffset() int64
- func (m *SessionChunk) GetTime() int64
- func (m *SessionChunk) Marshal() (dAtA []byte, err error)
- func (m *SessionChunk) MarshalTo(dAtA []byte) (int, error)
- func (*SessionChunk) ProtoMessage()
- func (m *SessionChunk) Reset()
- func (m *SessionChunk) Size() (n int)
- func (m *SessionChunk) String() string
- func (m *SessionChunk) Unmarshal(dAtA []byte) error
- func (m *SessionChunk) XXX_DiscardUnknown()
- func (m *SessionChunk) XXX_Marshal(b []byte, deterministic bool) ([]byte, error)
- func (dst *SessionChunk) XXX_Merge(src proto.Message)
- func (m *SessionChunk) XXX_Size() int
- func (m *SessionChunk) XXX_Unmarshal(b []byte) error
- type SessionLogger
- type SessionRecorder
- type SessionRecording
- type SessionSlice
- func (*SessionSlice) Descriptor() ([]byte, []int)
- func (m *SessionSlice) GetChunks() []*SessionChunk
- func (m *SessionSlice) GetNamespace() string
- func (m *SessionSlice) GetSessionID() string
- func (m *SessionSlice) GetVersion() int64
- func (m *SessionSlice) Marshal() (dAtA []byte, err error)
- func (m *SessionSlice) MarshalTo(dAtA []byte) (int, error)
- func (*SessionSlice) ProtoMessage()
- func (m *SessionSlice) Reset()
- func (m *SessionSlice) Size() (n int)
- func (m *SessionSlice) String() string
- func (m *SessionSlice) Unmarshal(dAtA []byte) error
- func (m *SessionSlice) XXX_DiscardUnknown()
- func (m *SessionSlice) XXX_Marshal(b []byte, deterministic bool) ([]byte, error)
- func (dst *SessionSlice) XXX_Merge(src proto.Message)
- func (m *SessionSlice) XXX_Size() int
- func (m *SessionSlice) XXX_Unmarshal(b []byte) error
- type UploadEvent
- type UploadHandler
- type Uploader
- type UploaderConfig
- type WriterLog
- func (w *WriterLog) Close() error
- func (w *WriterLog) EmitAuditEvent(event Event, fields EventFields) error
- func (w *WriterLog) GetSessionChunk(namespace string, sid session.ID, offsetBytes, maxBytes int) ([]byte, error)
- func (w *WriterLog) GetSessionEvents(namespace string, sid session.ID, after int, includePrintEvents bool) ([]EventFields, error)
- func (w *WriterLog) PostSessionSlice(SessionSlice) error
- func (w *WriterLog) SearchEvents(fromUTC, toUTC time.Time, query string, limit int) ([]EventFields, error)
- func (w *WriterLog) SearchSessionEvents(fromUTC time.Time, toUTC time.Time, limit int) ([]EventFields, error)
- func (w *WriterLog) UploadSessionRecording(r SessionRecording) error
- func (w *WriterLog) WaitForDelivery(context.Context) error
Constants ¶
const ( // EventType is event type/kind EventType = "event" // EventID is a unique event identifier EventID = "uid" // EventCode is a code that uniquely identifies a particular event type EventCode = "code" // EventTime is event time EventTime = "time" // EventLogin is OS login EventLogin = "login" // EventUser is teleport user name EventUser = "user" // EventProtocol specifies protocol that was captured EventProtocol = "proto" // EventProtocolsSSH specifies SSH as a type of captured protocol EventProtocolSSH = "ssh" // EventProtocolKube specifies kubernetes as a type of captured protocol EventProtocolKube = "kube" // LocalAddr is a target address on the host LocalAddr = "addr.local" // RemoteAddr is a client (user's) address RemoteAddr = "addr.remote" // EventCursor is an event ID (used as cursor value for enumeration, not stored) EventCursor = "id" // EventIndex is an event index as received from the logging server EventIndex = "ei" // EventNamespace is a namespace of the session event EventNamespace = "namespace" // SessionPrintEvent event happens every time a write occurs to // temirnal I/O during a session SessionPrintEvent = "print" // SessionPrintEventBytes says how many bytes have been written into the session // during "print" event SessionPrintEventBytes = "bytes" // SessionEventTimestamp is an offset (in milliseconds) since the beginning of the // session when the terminal IO event happened SessionEventTimestamp = "ms" // SessionEvent indicates that session has been initiated // or updated by a joining party on the server SessionStartEvent = "session.start" // SessionEndEvent indicates that a session has ended SessionEndEvent = "session.end" // SessionUploadEvent indicates that session has been uploaded to the external storage SessionUploadEvent = "session.upload" // URL is used for a session upload URL URL = "url" // SessionEventID is a unique UUID of the session. SessionEventID = "sid" // SessionServerID is the UUID of the server the session occurred on. SessionServerID = "server_id" // SessionServerHostname is the hostname of the server the session occurred on. SessionServerHostname = "server_hostname" // SessionServerAddr is the address of the server the session occurred on. SessionServerAddr = "server_addr" // SessionStartTime is the timestamp at which the session began. SessionStartTime = "session_start" // SessionEndTime is the timestamp at which the session ended. SessionEndTime = "session_stop" // SessionEnhancedRecording is used to indicate if the recording was an // enhanced recording or not. SessionEnhancedRecording = "enhanced_recording" // SessionInteractive is used to indicate if the session was interactive // (has PTY attached) or not (exec session). SessionInteractive = "interactive" // SessionParticipants is a list of participants in the session. SessionParticipants = "participants" // SessionServerLabels are the labels (static and dynamic) of the server the // session occurred on. SessionServerLabels = "server_labels" // SessionByteOffset is the number of bytes written to session stream since // the beginning SessionByteOffset = "offset" // SessionJoinEvent indicates that someone joined a session SessionJoinEvent = "session.join" // SessionLeaveEvent indicates that someone left a session SessionLeaveEvent = "session.leave" // Data transfer events. SessionDataEvent = "session.data" DataTransmitted = "tx" DataReceived = "rx" // ClientDisconnectEvent is emitted when client is disconnected // by the server due to inactivity or any other reason ClientDisconnectEvent = "client.disconnect" // Reason is a field that specifies reason for event, e.g. in disconnect // event it explains why server disconnected the client Reason = "reason" // UserLoginEvent indicates that a user logged into web UI or via tsh UserLoginEvent = "user.login" // LoginMethod is the event field indicating how the login was performed LoginMethod = "method" // LoginMethodLocal represents login with username/password LoginMethodLocal = "local" // LoginMethodClientCert represents login with client certificate LoginMethodClientCert = "client.cert" // LoginMethodOIDC represents login with OIDC LoginMethodOIDC = "oidc" // LoginMethodSAML represents login with SAML LoginMethodSAML = "saml" // LoginMethodGithub represents login with Github LoginMethodGithub = "github" // UserUpdatedEvent is emitted when the user is updated. UserUpdatedEvent = "user.update" // UserDeleteEvent is emitted when the user is deleted. UserDeleteEvent = "user.delete" // UserCreateEvent is emitted when the user is created. UserCreateEvent = "user.create" // UserPasswordChangeEvent is when the user changes their own password. UserPasswordChangeEvent = "user.password_change" // UserExpires is when the user will expire. UserExpires = "expires" // UserRoles is a list of roles for the user. UserRoles = "roles" // IdentityAttributes is a map of user attributes // received from identity provider IdentityAttributes = "attributes" // UserConnector is the connector used to create the user. UserConnector = "connector" // AccessRequestCreateEvent is emitted when a new access request is created. AccessRequestCreateEvent = "access_request.create" // AccessRequestUpdateEvent is emitted when a request's state is updated. AccessRequestUpdateEvent = "access_request.update" // AccessRequestDelegator is used by teleport plugins to indicate the identity // which caused them to update state. AccessRequestDelegator = "delegator" // AccessRequestState is the state of a request. AccessRequestState = "state" // AccessRequestID is the ID of an access request. AccessRequestID = "id" // UpdatedBy indicates the user who modified some resource: // - updating a request state // - updating a user record UpdatedBy = "updated_by" // ResetPasswordTokenCreateEvent is emitted when a new reset password token is created. ResetPasswordTokenCreateEvent = "reset_password_token.create" // ResetPasswordTokenTTL is TTL of reset password token. ResetPasswordTokenTTL = "ttl" // FieldName contains name, e.g. resource name, etc. FieldName = "name" // ExecEvent is an exec command executed by script or user on // the server side ExecEvent = "exec" ExecEventCommand = "command" ExecEventCode = "exitCode" ExecEventError = "exitError" // SubsystemEvent is the result of the execution of a subsystem. SubsystemEvent = "subsystem" SubsystemName = "name" SubsystemError = "exitError" // X11 forwarding event X11ForwardEvent = "x11-forward" X11ForwardSuccess = "success" X11ForwardErr = "error" // Port forwarding event PortForwardEvent = "port" PortForwardAddr = "addr" PortForwardSuccess = "success" PortForwardErr = "error" // AuthAttemptEvent is authentication attempt that either // succeeded or failed based on event status AuthAttemptEvent = "auth" AuthAttemptSuccess = "success" AuthAttemptErr = "error" AuthAttemptMessage = "message" // SCPEvent means data transfer that occurred on the server SCPEvent = "scp" SCPPath = "path" SCPLengh = "len" SCPAction = "action" SCPActionUpload = "upload" SCPActionDownload = "download" // ResizeEvent means that some user resized PTY on the client ResizeEvent = "resize" TerminalSize = "size" // expressed as 'W:H' // SessionUploadIndex is a very large number of the event index // to indicate that this is the last event in the chain // used for the last event of the sesion - session upload SessionUploadIndex = math.MaxInt32 // SessionDataIndex is a very large number of the event index // to indicate one of the last session events, used to report // data transfer SessionDataIndex = math.MaxInt32 - 1 // SessionCommandEvent is emitted when an executable is run within a session. SessionCommandEvent = "session.command" // SessionDiskEvent is emitted when a file is opened within an session. SessionDiskEvent = "session.disk" // SessionNetworkEvent is emitted when a network connection is initated with a // session. SessionNetworkEvent = "session.network" // PID is the ID of the process. PID = "pid" // PPID is the PID of the parent process. PPID = "ppid" // CgroupID is the internal cgroupv2 ID of the event. CgroupID = "cgroup_id" // Program is name of the executable. Program = "program" // Path is the full path to the executable. Path = "path" // Argv is the list of arguments to the program. Note, the first element does // not contain the name of the process. Argv = "argv" // ReturnCode is the return code of execve. ReturnCode = "return_code" // Flags are the flags passed to open. Flags = "flags" // SrcAddr is the source IP address of the connection. SrcAddr = "src_addr" // DstAddr is the destination IP address of the connection. DstAddr = "dst_addr" // DstPort is the destination port of the connection. DstPort = "dst_port" // TCPVersion is the version of TCP (4 or 6). TCPVersion = "version" // RoleCreatedEvent fires when role is created/updated. RoleCreatedEvent = "role.created" // RoleDeletedEvent fires when role is deleted. RoleDeletedEvent = "role.deleted" // TrustedClusterCreateEvent is the event for creating a trusted cluster. TrustedClusterCreateEvent = "trusted_cluster.create" // TrustedClusterDeleteEvent is the event for removing a trusted cluster. TrustedClusterDeleteEvent = "trusted_cluster.delete" // TrustedClusterTokenCreateEvent is the event for // creating new join token for a trusted cluster. TrustedClusterTokenCreateEvent = "trusted_cluster_token.create" // GithubConnectorCreatedEvent fires when a Github connector is created/updated. GithubConnectorCreatedEvent = "github.created" // GithubConnectorDeletedEvent fires when a Github connector is deleted. GithubConnectorDeletedEvent = "github.deleted" // OIDCConnectorCreatedEvent fires when OIDC connector is created/updated. OIDCConnectorCreatedEvent = "oidc.created" // OIDCConnectorDeletedEvent fires when OIDC connector is deleted. OIDCConnectorDeletedEvent = "oidc.deleted" // SAMLConnectorCreatedEvent fires when SAML connector is created/updated. SAMLConnectorCreatedEvent = "saml.created" // SAMLConnectorDeletedEvent fires when SAML connector is deleted. SAMLConnectorDeletedEvent = "saml.deleted" )
const ( // V1 is the V1 version of slice chunks API, // it is 0 because it was not defined before V1 = 0 // V2 is the V2 version of slice chunks API V2 = 2 // V3 is almost like V2, but it assumes // that session recordings are being uploaded // at the end of the session, so it skips writing session event index // on the fly V3 = 3 )
const ( // SessionLogsDir is a subdirectory inside the eventlog data dir // where all session-specific logs and streams are stored, like // in /var/lib/teleport/logs/sessions SessionLogsDir = "sessions" // PlaybacksDir is a directory for playbacks PlaybackDir = "playbacks" // LogfileExt defines the ending of the daily event log file LogfileExt = ".log" // SymlinkFilename is a name of the symlink pointing to the last // current log file SymlinkFilename = "events.log" )
const ( // UserLocalLoginCode is the successful local user login event code. UserLocalLoginCode = "T1000I" // UserLocalLoginFailureCode is the unsuccessful local user login event code. UserLocalLoginFailureCode = "T1000W" // UserSSOLoginCode is the successful SSO user login event code. UserSSOLoginCode = "T1001I" // UserSSOLoginFailureCode is the unsuccessful SSO user login event code. UserSSOLoginFailureCode = "T1001W" // UserCreateCode is the user create event code. UserCreateCode = "T1002I" // UserUpdateCode is the user update event code. UserUpdateCode = "T1003I" // UserDeleteCode is the user delete event code. UserDeleteCode = "T1004I" // UserPasswordChangeCode is an event code for when user changes their own password. UserPasswordChangeCode = "T1005I" // SessionStartCode is the session start event code. SessionStartCode = "T2000I" // SessionJoinCode is the session join event code. SessionJoinCode = "T2001I" // TerminalResizeCode is the terminal resize event code. TerminalResizeCode = "T2002I" // SessionLeaveCode is the session leave event code. SessionLeaveCode = "T2003I" // SessionEndCode is the session end event code. SessionEndCode = "T2004I" // SessionUploadCode is the session upload event code. SessionUploadCode = "T2005I" // SessionDataCode is the session data event code. SessionDataCode = "T2006I" // SubsystemCode is the subsystem event code. SubsystemCode = "T3001I" // SubsystemFailureCode is the subsystem failure event code. SubsystemFailureCode = "T3001E" // ExecCode is the exec event code. ExecCode = "T3002I" // ExecFailureCode is the exec failure event code. ExecFailureCode = "T3002E" // PortForwardCode is the port forward event code. PortForwardCode = "T3003I" // PortForwardFailureCode is the port forward failure event code. PortForwardFailureCode = "T3003E" // SCPDownloadCode is the file download event code. SCPDownloadCode = "T3004I" // SCPDownloadFailureCode is the file download event failure code. SCPDownloadFailureCode = "T3004E" // SCPUploadCode is the file upload event code. SCPUploadCode = "T3005I" // SCPUploadFailureCode is the file upload failure event code. SCPUploadFailureCode = "T3005E" // ClientDisconnectCode is the client disconnect event code. ClientDisconnectCode = "T3006I" // AuthAttemptFailureCode is the auth attempt failure event code. AuthAttemptFailureCode = "T3007W" // X11ForwardCode is the x11 forward event code. X11ForwardCode = "T3008I" // X11ForwardFailureCode is the x11 forward failure event code. X11ForwardFailureCode = "T3008W" // SessionCommandCode is a session command code. SessionCommandCode = "T4000I" // SessionDiskCode is a session disk code. SessionDiskCode = "T4001I" // SessionNetworkCode is a session network code. SessionNetworkCode = "T4002I" // AccessRequestCreateCode is the the access request creation code. AccessRequestCreateCode = "T5000I" // AccessRequestUpdateCode is the access request state update code. AccessRequestUpdateCode = "T5001I" // ResetPasswordTokenCreateCode is the token create event code. ResetPasswordTokenCreateCode = "T6000I" // TrustedClusterCreateCode is the event code for creating a trusted cluster. TrustedClusterCreateCode = "T7000I" // TrustedClusterDeleteCode is the event code for removing a trusted cluster. TrustedClusterDeleteCode = "T7001I" // TrustedClusterTokenCreateCode is the event code for // creating new join token for a trusted cluster. TrustedClusterTokenCreateCode = "T7002I" // GithubConnectorCreatedCode is the Github connector created event code. GithubConnectorCreatedCode = "T8000I" // GithubConnectorDeletedCode is the Github connector deleted event code. GithubConnectorDeletedCode = "T8001I" // OIDCConnectorCreatedCode is the OIDC connector created event code. OIDCConnectorCreatedCode = "T8100I" // OIDCConnectorDeletedCode is the OIDC connector deleted event code. OIDCConnectorDeletedCode = "T8101I" // SAMLConnectorCreatedCode is the SAML connector created event code. SAMLConnectorCreatedCode = "T8200I" // SAMLConnectorDeletedCode is the SAML connector deleted event code. SAMLConnectorDeletedCode = "T8201I" // RoleCreatedCode is the role created event code. RoleCreatedCode = "T9000I" // RoleDeletedCode is the role deleted event code. RoleDeletedCode = "T9001I" )
There is no strict algorithm for picking an event code, however existing event codes are currently loosely categorized as follows:
Teleport event codes start with "T" and belong in this const block.
Related events are grouped starting with the same number. eg: All user related events are grouped under 1xxx.
Suffix code with one of these letters: I (info), W (warn), E (error).
const ( // MaxChunkBytes defines the maximum size of a session stream chunk that // can be requested via AuditLog.GetSessionChunk(). Set to 5MB MaxChunkBytes = 1024 * 1024 * 5 )
Variables ¶
var ( // UserLocalLogin is emitted when a local user successfully logs in. UserLocalLogin = Event{ Name: UserLoginEvent, Code: UserLocalLoginCode, } // UserLocalLoginFailure is emitted when a local user login attempt fails. UserLocalLoginFailure = Event{ Name: UserLoginEvent, Code: UserLocalLoginFailureCode, } // UserSSOLogin is emitted when an SSO user successfully logs in. UserSSOLogin = Event{ Name: UserLoginEvent, Code: UserSSOLoginCode, } // UserSSOLoginFailure is emitted when an SSO user login attempt fails. UserSSOLoginFailure = Event{ Name: UserLoginEvent, Code: UserSSOLoginFailureCode, } // UserUpdate is emitted when a user is updated. UserUpdate = Event{ Name: UserUpdatedEvent, Code: UserUpdateCode, } // UserDelete is emitted when a user is deleted. UserDelete = Event{ Name: UserDeleteEvent, Code: UserDeleteCode, } // UserCreate is emitted when a user is created. UserCreate = Event{ Name: UserCreateEvent, Code: UserCreateCode, } // UserPasswordChange is emitted when a user changes their own password. UserPasswordChange = Event{ Name: UserPasswordChangeEvent, Code: UserPasswordChangeCode, } // SessionStart is emitted when a user starts a new session. SessionStart = Event{ Name: SessionStartEvent, Code: SessionStartCode, } // SessionJoin is emitted when a user joins the session. SessionJoin = Event{ Name: SessionJoinEvent, Code: SessionJoinCode, } // TerminalResize is emitted when a user resizes the terminal. TerminalResize = Event{ Name: ResizeEvent, Code: TerminalResizeCode, } // SessionLeave is emitted when a user leaves the session. SessionLeave = Event{ Name: SessionLeaveEvent, Code: SessionLeaveCode, } // SessionEnd is emitted when a user ends the session. SessionEnd = Event{ Name: SessionEndEvent, Code: SessionEndCode, } // SessionUpload is emitted after a session recording has been uploaded. SessionUpload = Event{ Name: SessionUploadEvent, Code: SessionUploadCode, } // SessionData is emitted to report session data usage. SessionData = Event{ Name: SessionDataEvent, Code: SessionDataCode, } // Subsystem is emitted when a user requests a new subsystem. Subsystem = Event{ Name: SubsystemEvent, Code: SubsystemCode, } // SubsystemFailure is emitted when a user subsystem request fails. SubsystemFailure = Event{ Name: SubsystemEvent, Code: SubsystemFailureCode, } // Exec is emitted when a user executes a command on a node. Exec = Event{ Name: ExecEvent, Code: ExecCode, } // ExecFailure is emitted when a user command execution fails. ExecFailure = Event{ Name: ExecEvent, Code: ExecFailureCode, } // X11Forward is emitted when a user requests X11 forwarding. X11Forward = Event{ Name: X11ForwardEvent, Code: X11ForwardCode, } // X11ForwardFailure is emitted when an X11 forwarding request fails. X11ForwardFailure = Event{ Name: X11ForwardEvent, Code: X11ForwardFailureCode, } // PortForward is emitted when a user requests port forwarding. PortForward = Event{ Name: PortForwardEvent, Code: PortForwardCode, } // PortForwardFailure is emitted when a port forward request fails. PortForwardFailure = Event{ Name: PortForwardEvent, Code: PortForwardFailureCode, } // SCPDownload is emitted when a user downloads a file. SCPDownload = Event{ Name: SCPEvent, Code: SCPDownloadCode, } // SCPDownloadFailure is emitted when a file download fails. SCPDownloadFailure = Event{ Name: SCPEvent, Code: SCPDownloadFailureCode, } // SCPUpload is emitted when a user uploads a file. SCPUpload = Event{ Name: SCPEvent, Code: SCPUploadCode, } // SCPUploadFailure is emitted when a file upload fails. SCPUploadFailure = Event{ Name: SCPEvent, Code: SCPUploadFailureCode, } // ClientDisconnect is emitted when a user session is disconnected. ClientDisconnect = Event{ Name: ClientDisconnectEvent, Code: ClientDisconnectCode, } // AuthAttemptFailure is emitted upon a failed authentication attempt. AuthAttemptFailure = Event{ Name: AuthAttemptEvent, Code: AuthAttemptFailureCode, } // AccessRequestCreated is emitted when an access request is created. AccessRequestCreated = Event{ Name: AccessRequestCreateEvent, Code: AccessRequestCreateCode, } AccessRequestUpdated = Event{ Name: AccessRequestUpdateEvent, Code: AccessRequestUpdateCode, } // SessionCommand is emitted upon execution of a command when using enhanced // session recording. SessionCommand = Event{ Name: SessionCommandEvent, Code: SessionCommandCode, } // SessionDisk is emitted upon open of a file when using enhanced session recording. SessionDisk = Event{ Name: SessionDiskEvent, Code: SessionDiskCode, } // SessionNetwork is emitted when a network requests is is issued when // using enhanced session recording. SessionNetwork = Event{ Name: SessionNetworkEvent, Code: SessionNetworkCode, } // ResetPasswordTokenCreated is emitted when token is created. ResetPasswordTokenCreated = Event{ Name: ResetPasswordTokenCreateEvent, Code: ResetPasswordTokenCreateCode, } // RoleCreated is emitted when a role is created/updated. RoleCreated = Event{ Name: RoleCreatedEvent, Code: RoleCreatedCode, } // RoleDeleted is emitted when a role is deleted. RoleDeleted = Event{ Name: RoleDeletedEvent, Code: RoleDeletedCode, } // TrustedClusterCreate is emitted when a trusted cluster relationship is created. TrustedClusterCreate = Event{ Name: TrustedClusterCreateEvent, Code: TrustedClusterCreateCode, } // TrustedClusterDelete is emitted when a trusted cluster is removed from the root cluster. TrustedClusterDelete = Event{ Name: TrustedClusterDeleteEvent, Code: TrustedClusterDeleteCode, } // TrustedClusterTokenCreate is emitted when a new join // token for trusted cluster is created. TrustedClusterTokenCreate = Event{ Name: TrustedClusterTokenCreateEvent, Code: TrustedClusterTokenCreateCode, } // GithubConnectorCreated is emitted when a Github connector is created/updated. GithubConnectorCreated = Event{ Name: GithubConnectorCreatedEvent, Code: GithubConnectorCreatedCode, } // GithubConnectorDeleted is emitted when a Github connector is deleted. GithubConnectorDeleted = Event{ Name: GithubConnectorDeletedEvent, Code: GithubConnectorDeletedCode, } // OIDCConnectorCreated is emitted when an OIDC connector is created/updated. OIDCConnectorCreated = Event{ Name: OIDCConnectorCreatedEvent, Code: OIDCConnectorCreatedCode, } // OIDCConnectorDeleted is emitted when an OIDC connector is deleted. OIDCConnectorDeleted = Event{ Name: OIDCConnectorDeletedEvent, Code: OIDCConnectorDeletedCode, } // SAMLConnectorCreated is emitted when a SAML connector is created/updated. SAMLConnectorCreated = Event{ Name: SAMLConnectorCreatedEvent, Code: SAMLConnectorCreatedCode, } // SAMLConnectorDeleted is emitted when a SAML connector is deleted. SAMLConnectorDeleted = Event{ Name: SAMLConnectorDeletedEvent, Code: SAMLConnectorDeletedCode, } )
var ( ErrInvalidLengthSlice = fmt.Errorf("proto: negative length found during unmarshaling") ErrIntOverflowSlice = fmt.Errorf("proto: integer overflow") )
Functions ¶
func NewSessionArchive ¶
func NewSessionArchive(dataDir, serverID, namespace string, sessionID session.ID) (io.ReadCloser, error)
NewSessionArchive returns generated tar archive with all components
func PrintEventFromChunk ¶
func PrintEventFromChunk(chunk *SessionChunk) printEvent
PrintEventFromChunk returns a print event converted from session chunk.
func RegisterAuditLogServer ¶
func RegisterAuditLogServer(s *grpc.Server, srv AuditLogServer)
func UpdateEventFields ¶
func UpdateEventFields(event Event, fields EventFields, clock clockwork.Clock, uid utils.UID) (err error)
UpdateEventFields updates passed event fields with additional information common for all event types such as unique IDs, timestamps, codes, etc.
This method is a "final stop" for various audit log implementations for updating event fields before it gets persisted in the backend.
func ValidateArchive ¶
ValidateArchive validates namespace and serverID fields within all events in the archive.
func ValidateEvent ¶
func ValidateEvent(f EventFields, serverID string) error
ValidateEvent checks the the fields within an event match the passed in expected values.
Types ¶
type AuditLog ¶ added in v1.0.0
type AuditLog struct { sync.Mutex *log.Entry AuditLogConfig // contains filtered or unexported fields }
AuditLog is a new combined facility to record Teleport events and sessions. It implements IAuditLog
func NewAuditLog ¶ added in v1.0.0
func NewAuditLog(cfg AuditLogConfig) (*AuditLog, error)
Creates and returns a new Audit Log object whish will store its logfiles in a given directory. Session recording can be disabled by setting recordSessions to false.
func (*AuditLog) Close ¶ added in v1.0.0
Closes the audit log, which inluces closing all file handles and releasing all session loggers
func (*AuditLog) EmitAuditEvent ¶ added in v1.0.0
func (l *AuditLog) EmitAuditEvent(event Event, fields EventFields) error
EmitAuditEvent adds a new event to the log. If emitting fails, a Prometheus counter is incremented.
func (*AuditLog) GetSessionChunk ¶ added in v1.0.0
func (l *AuditLog) GetSessionChunk(namespace string, sid session.ID, offsetBytes, maxBytes int) ([]byte, error)
GetSessionChunk returns a reader which console and web clients request to receive a live stream of a given session. The reader allows access to a session stream range from offsetBytes to offsetBytes+maxBytes
func (*AuditLog) GetSessionEvents ¶ added in v1.0.0
func (l *AuditLog) GetSessionEvents(namespace string, sid session.ID, afterN int, includePrintEvents bool) ([]EventFields, error)
Returns all events that happen during a session sorted by time (oldest first).
Can be filtered by 'after' (cursor value to return events newer than)
This function is usually used in conjunction with GetSessionReader to replay recorded session streams.
func (*AuditLog) PostSessionSlice ¶
func (l *AuditLog) PostSessionSlice(slice SessionSlice) error
PostSessionSlice submits slice of session chunks to the audit log server.
func (*AuditLog) SearchEvents ¶ added in v1.0.0
func (l *AuditLog) SearchEvents(fromUTC, toUTC time.Time, query string, limit int) ([]EventFields, error)
SearchEvents finds events. Results show up sorted by date (newest first), limit is used when set to value > 0
func (*AuditLog) SearchSessionEvents ¶
SearchSessionEvents searches for session related events. Used to find completed sessions.
func (*AuditLog) UploadSessionRecording ¶
func (l *AuditLog) UploadSessionRecording(r SessionRecording) error
UploadSessionRecording persists the session recording locally or to third party storage.
type AuditLogClient ¶
type AuditLogClient interface {
SubmitSessionSlice(ctx context.Context, opts ...grpc.CallOption) (AuditLog_SubmitSessionSliceClient, error)
}
func NewAuditLogClient ¶
func NewAuditLogClient(cc *grpc.ClientConn) AuditLogClient
type AuditLogConfig ¶
type AuditLogConfig struct { // DataDir is the directory where audit log stores the data DataDir string // ServerID is the id of the audit log server ServerID string // RecordSessions controls if sessions are recorded along with audit events. RecordSessions bool // RotationPeriod defines how frequently to rotate the log file RotationPeriod time.Duration // SessionIdlePeriod defines the period after which sessions will be considered // idle (and audit log will free up some resources) SessionIdlePeriod time.Duration // Clock is a clock either real one or used in tests Clock clockwork.Clock // UIDGenerator is used to generate unique IDs for events UIDGenerator utils.UID // GID if provided will be used to set group ownership of the directory // to GID GID *int // UID if provided will be used to set userownership of the directory // to UID UID *int // DirMask if provided will be used to set directory mask access // otherwise set to default value DirMask *os.FileMode // PlaybackRecycleTTL is a time after uncompressed playback files will be // deleted PlaybackRecycleTTL time.Duration // UploadHandler is a pluggable external upload handler, // used to fetch sessions from external sources UploadHandler UploadHandler // ExternalLog is a pluggable external log service ExternalLog IAuditLog // EventC is evnets channel for testing purposes, not used if empty EventsC chan *AuditLogEvent // Context is audit log context Context context.Context }
AuditLogConfig specifies configuration for AuditLog server
func (*AuditLogConfig) CheckAndSetDefaults ¶
func (a *AuditLogConfig) CheckAndSetDefaults() error
CheckAndSetDefaults checks and sets defaults
type AuditLogEvent ¶
type AuditLogEvent struct { // Type is an event type Type string // Error is an event error Error error }
AuditLogEvent is an internal audit log event
type AuditLogServer ¶
type AuditLogServer interface {
SubmitSessionSlice(AuditLog_SubmitSessionSliceServer) error
}
type AuditLog_SubmitSessionSliceClient ¶
type AuditLog_SubmitSessionSliceClient interface { Send(*SessionSlice) error CloseAndRecv() (*empty.Empty, error) grpc.ClientStream }
type AuditLog_SubmitSessionSliceServer ¶
type AuditLog_SubmitSessionSliceServer interface { SendAndClose(*empty.Empty) error Recv() (*SessionSlice, error) grpc.ServerStream }
type ByTimeAndIndex ¶
type ByTimeAndIndex []EventFields
ByTimeAndIndex sorts events by time extracting timestamp from JSON field and if there are several session events with the same session by event index, regardless of the time
func (ByTimeAndIndex) Len ¶
func (f ByTimeAndIndex) Len() int
func (ByTimeAndIndex) Less ¶
func (f ByTimeAndIndex) Less(i, j int) bool
func (ByTimeAndIndex) Swap ¶
func (f ByTimeAndIndex) Swap(i, j int)
type DiscardAuditLog ¶ added in v1.1.0
type DiscardAuditLog struct{}
DiscardAuditLog is do-nothing, discard-everything implementation of IAuditLog interface used for cases when audit is turned off
func NewDiscardAuditLog ¶
func NewDiscardAuditLog() *DiscardAuditLog
NewDiscardAuditLog returns a no-op audit log instance
func (*DiscardAuditLog) Close ¶
func (d *DiscardAuditLog) Close() error
func (*DiscardAuditLog) EmitAuditEvent ¶ added in v1.1.0
func (d *DiscardAuditLog) EmitAuditEvent(event Event, fields EventFields) error
func (*DiscardAuditLog) GetSessionChunk ¶ added in v1.1.0
func (*DiscardAuditLog) GetSessionEvents ¶ added in v1.1.0
func (d *DiscardAuditLog) GetSessionEvents(namespace string, sid session.ID, after int, includePrintEvents bool) ([]EventFields, error)
func (*DiscardAuditLog) PostSessionSlice ¶
func (d *DiscardAuditLog) PostSessionSlice(SessionSlice) error
func (*DiscardAuditLog) SearchEvents ¶ added in v1.1.0
func (d *DiscardAuditLog) SearchEvents(fromUTC, toUTC time.Time, query string, limit int) ([]EventFields, error)
func (*DiscardAuditLog) SearchSessionEvents ¶
func (d *DiscardAuditLog) SearchSessionEvents(fromUTC time.Time, toUTC time.Time, limit int) ([]EventFields, error)
func (*DiscardAuditLog) UploadSessionRecording ¶
func (d *DiscardAuditLog) UploadSessionRecording(SessionRecording) error
func (*DiscardAuditLog) WaitForDelivery ¶
func (d *DiscardAuditLog) WaitForDelivery(context.Context) error
type DiscardRecorder ¶
type DiscardRecorder struct {
DiscardAuditLog
}
DiscardRecorder discards all writes
func (*DiscardRecorder) Close ¶
func (*DiscardRecorder) Close() error
Close does nothing and always succeeds
func (*DiscardRecorder) GetAuditLog ¶
func (d *DiscardRecorder) GetAuditLog() IAuditLog
GetAuditLog returns audit log associated with this recorder
type DiskSessionLogger ¶
type DiskSessionLogger struct { DiskSessionLoggerConfig *log.Entry sync.Mutex // contains filtered or unexported fields }
DiskSessionLogger implements a disk based session logger. The imporant property of the disk based logger is that it never fails and can be used as a fallback implementation behind more sophisticated loggers.
func NewDiskSessionLogger ¶
func NewDiskSessionLogger(cfg DiskSessionLoggerConfig) (*DiskSessionLogger, error)
NewDiskSessionLogger creates new disk based session logger
func (*DiskSessionLogger) Close ¶
func (sl *DiskSessionLogger) Close() error
Close is called when clients close on the requested "session writer". We ignore their requests because this writer (file) should be closed only when the session logger is closed
func (*DiskSessionLogger) Finalize ¶
func (sl *DiskSessionLogger) Finalize() error
Finalize is called by the session when it's closing. This is where we're releasing audit resources associated with the session
func (*DiskSessionLogger) LogEvent ¶
func (sl *DiskSessionLogger) LogEvent(fields EventFields) error
LogEvent logs an event associated with this session
func (*DiskSessionLogger) PostSessionSlice ¶
func (sl *DiskSessionLogger) PostSessionSlice(slice SessionSlice) error
PostSessionSlice takes series of events associated with the session and writes them to events files and data file for future replays
type DiskSessionLoggerConfig ¶
type DiskSessionLoggerConfig struct { // SessionID is the session id of the logger SessionID session.ID // DataDir is data directory for session events files DataDir string // Clock is the clock replacement Clock clockwork.Clock // RecordSessions controls if sessions are recorded along with audit events. RecordSessions bool // Namespace is logger namespace Namespace string // ServerID is a server ID ServerID string }
DiskSessionLoggerConfig sets up parameters for disk session logger associated with the session ID
func (*DiskSessionLoggerConfig) CheckAndSetDefaults ¶
func (cfg *DiskSessionLoggerConfig) CheckAndSetDefaults() error
type EmittedEvent ¶
type EmittedEvent struct { EventType Event Fields EventFields }
EmittedEvent holds the event type and event fields.
type Event ¶
type Event struct { // Name is the event name. Name string // Code is the unique event code. Code string }
Event describes an audit log event.
type EventFields ¶ added in v1.0.0
type EventFields map[string]interface{}
EventFields instance is attached to every logged event
func EventFromChunk ¶
func EventFromChunk(sessionID string, chunk *SessionChunk) (EventFields, error)
EventFromChunk returns event converted from session chunk
func (EventFields) AsString ¶ added in v1.0.0
func (f EventFields) AsString() string
String returns a string representation of an event structure
func (EventFields) GetInt ¶ added in v1.0.0
func (f EventFields) GetInt(key string) int
GetString returns an int representation of a logged field
func (EventFields) GetString ¶ added in v1.0.0
func (f EventFields) GetString(key string) string
GetString returns a string representation of a logged field
func (EventFields) GetTime ¶ added in v1.0.0
func (f EventFields) GetTime(key string) time.Time
GetString returns an int representation of a logged field
func (EventFields) GetTimestamp ¶
func (f EventFields) GetTimestamp() time.Time
GetTimestamp returns the event timestamp (when it was emitted)
func (EventFields) GetType ¶ added in v1.0.0
func (f EventFields) GetType() string
GetType returns the type (string) of the event
func (EventFields) HasField ¶
func (f EventFields) HasField(key string) bool
HasField returns true if the field exists in the event.
type FileLog ¶
type FileLog struct { *log.Entry FileLogConfig sync.Mutex // contains filtered or unexported fields }
FileLog is a file local audit events log, logs all events to the local file in json encoded form
func NewFileLog ¶
func NewFileLog(cfg FileLogConfig) (*FileLog, error)
NewFileLog returns a new instance of a file log
func (*FileLog) Close ¶
Close closes the audit log, which inluces closing all file handles and releasing all session loggers
func (*FileLog) EmitAuditEvent ¶
func (l *FileLog) EmitAuditEvent(event Event, fields EventFields) error
EmitAuditEvent adds a new event to the log. Part of auth.IFileLog interface.
func (*FileLog) GetSessionChunk ¶
func (*FileLog) GetSessionEvents ¶
func (*FileLog) PostSessionSlice ¶
func (l *FileLog) PostSessionSlice(slice SessionSlice) error
func (*FileLog) SearchEvents ¶
func (l *FileLog) SearchEvents(fromUTC, toUTC time.Time, query string, limit int) ([]EventFields, error)
SearchEvents finds events. Results show up sorted by date (newest first), limit is used when set to value > 0
func (*FileLog) SearchSessionEvents ¶
SearchSessionEvents searches for session related events. Used to find completed sessions.
func (*FileLog) UploadSessionRecording ¶
func (l *FileLog) UploadSessionRecording(SessionRecording) error
type FileLogConfig ¶
type FileLogConfig struct { // RotationPeriod defines how frequently to rotate the log file RotationPeriod time.Duration // Dir is a directory where logger puts the files Dir string // SymlinkDir is a directory for symlink pointer to the current log SymlinkDir string // Clock is a clock interface, used in tests Clock clockwork.Clock // UIDGenerator is used to generate unique IDs for events UIDGenerator utils.UID // SearchDirs is a function that returns // search directories, if not set, only Dir is used SearchDirs func() ([]string, error) }
FileLogConfig is a configuration for file log
func (*FileLogConfig) CheckAndSetDefaults ¶
func (cfg *FileLogConfig) CheckAndSetDefaults() error
CheckAndSetDefaults checks and sets config defaults
type ForwardRecorder ¶
type ForwardRecorder struct { // ForwardRecorderConfig specifies session recorder configuration ForwardRecorderConfig // Entry holds the structured logger *logrus.Entry // AuditLog is the audit log to store session chunks AuditLog IAuditLog }
ForwardRecorder implements io.Writer to be plugged into the multi-writer associated with every session. It forwards session stream to the audit log
func NewForwardRecorder ¶
func NewForwardRecorder(cfg ForwardRecorderConfig) (*ForwardRecorder, error)
NewForwardRecorder returns a new instance of session recorder
func (*ForwardRecorder) Close ¶
func (r *ForwardRecorder) Close() error
Close closes audit log session recorder
func (*ForwardRecorder) GetAuditLog ¶
func (r *ForwardRecorder) GetAuditLog() IAuditLog
GetAuditLog returns audit log associated with this recorder
type ForwardRecorderConfig ¶
type ForwardRecorderConfig struct { // DataDir is a data directory to record DataDir string // SessionID defines the session to record. SessionID session.ID // Namespace is the session namespace. Namespace string // RecordSessions stores info on whether to record sessions RecordSessions bool // Component is a component used for logging Component string // ForwardTo is external audit log where events will be forwarded ForwardTo IAuditLog }
ForwardRecorderConfig specifies config for session recording
func (*ForwardRecorderConfig) CheckAndSetDefaults ¶
func (cfg *ForwardRecorderConfig) CheckAndSetDefaults() error
type Forwarder ¶
type Forwarder struct { ForwarderConfig sync.Mutex // contains filtered or unexported fields }
ForwarderConfig forwards session log events to the auth server, and writes the session playback to disk
func NewForwarder ¶
func NewForwarder(cfg ForwarderConfig) (*Forwarder, error)
NewForwarder returns a new instance of session forwarder
func (*Forwarder) EmitAuditEvent ¶
func (l *Forwarder) EmitAuditEvent(event Event, fields EventFields) error
EmitAuditEvent emits audit event
func (*Forwarder) GetSessionChunk ¶
func (l *Forwarder) GetSessionChunk(namespace string, sid session.ID, offsetBytes, maxBytes int) ([]byte, error)
GetSessionChunk returns a reader which can be used to read a byte stream of a recorded session starting from 'offsetBytes' (pass 0 to start from the beginning) up to maxBytes bytes.
If maxBytes > MaxChunkBytes, it gets rounded down to MaxChunkBytes
func (*Forwarder) GetSessionEvents ¶
func (l *Forwarder) GetSessionEvents(namespace string, sid session.ID, after int, includePrintEvents bool) ([]EventFields, error)
Returns all events that happen during a session sorted by time (oldest first).
after tells to use only return events after a specified cursor Id
This function is usually used in conjunction with GetSessionReader to replay recorded session streams.
func (*Forwarder) PostSessionSlice ¶
func (l *Forwarder) PostSessionSlice(slice SessionSlice) error
PostSessionSlice sends chunks of recorded session to the event log
func (*Forwarder) SearchEvents ¶
func (l *Forwarder) SearchEvents(fromUTC, toUTC time.Time, query string, limit int) ([]EventFields, error)
SearchEvents is a flexible way to find The format of a query string depends on the implementing backend. A recommended format is urlencoded (good enough for Lucene/Solr)
Pagination is also defined via backend-specific query format.
The only mandatory requirement is a date range (UTC). Results must always show up sorted by date (newest first)
func (*Forwarder) SearchSessionEvents ¶
func (l *Forwarder) SearchSessionEvents(fromUTC time.Time, toUTC time.Time, limit int) ([]EventFields, error)
SearchSessionEvents returns session related events only. This is used to find completed session.
func (*Forwarder) UploadSessionRecording ¶
func (l *Forwarder) UploadSessionRecording(r SessionRecording) error
UploadSessionRecording uploads session recording to the audit server
type ForwarderConfig ¶
type ForwarderConfig struct { // SessionID is a session id to write SessionID session.ID // ServerID is a serverID data directory ServerID string // DataDir is a data directory DataDir string // RecordSessions is a sessions recording setting RecordSessions bool // Namespace is a namespace of the session Namespace string // ForwardTo is the audit log to forward non-print events to ForwardTo IAuditLog // Clock is a clock to set for tests Clock clockwork.Clock // UID is UID generator UID utils.UID }
ForwarderConfig forwards session log events to the auth server, and writes the session playback to disk
func (*ForwarderConfig) CheckAndSetDefaults ¶
func (s *ForwarderConfig) CheckAndSetDefaults() error
CheckAndSetDefaults checks and sets default values
type IAuditLog ¶ added in v1.0.0
type IAuditLog interface { // Closer releases connection and resources associated with log if any io.Closer // EmitAuditEvent emits audit event EmitAuditEvent(Event, EventFields) error // DELETE IN: 2.7.0 // This method is no longer necessary as nodes and proxies >= 2.7.0 // use UploadSessionRecording method. // PostSessionSlice sends chunks of recorded session to the event log PostSessionSlice(SessionSlice) error // UploadSessionRecording uploads session recording to the audit server UploadSessionRecording(r SessionRecording) error // GetSessionChunk returns a reader which can be used to read a byte stream // of a recorded session starting from 'offsetBytes' (pass 0 to start from the // beginning) up to maxBytes bytes. // // If maxBytes > MaxChunkBytes, it gets rounded down to MaxChunkBytes GetSessionChunk(namespace string, sid session.ID, offsetBytes, maxBytes int) ([]byte, error) // Returns all events that happen during a session sorted by time // (oldest first). // // after tells to use only return events after a specified cursor Id // // This function is usually used in conjunction with GetSessionReader to // replay recorded session streams. GetSessionEvents(namespace string, sid session.ID, after int, includePrintEvents bool) ([]EventFields, error) // SearchEvents is a flexible way to find events. The format of a query string // depends on the implementing backend. A recommended format is urlencoded // (good enough for Lucene/Solr) // // Pagination is also defined via backend-specific query format. // // The only mandatory requirement is a date range (UTC). Results must always // show up sorted by date (newest first) SearchEvents(fromUTC, toUTC time.Time, query string, limit int) ([]EventFields, error) // SearchSessionEvents returns session related events only. This is used to // find completed session. SearchSessionEvents(fromUTC time.Time, toUTC time.Time, limit int) ([]EventFields, error) // WaitForDelivery waits for resources to be released and outstanding requests to // complete after calling Close method WaitForDelivery(context.Context) error }
IAuditLog is the primary (and the only external-facing) interface for AuditLogger. If you wish to implement a different kind of logger (not filesystem-based), you have to implement this interface
type MockAuditLog ¶
type MockAuditLog struct { sync.Mutex FailedAttemptsC chan *SessionSlice SlicesC chan *SessionSlice EmittedEvent *EmittedEvent // contains filtered or unexported fields }
MockAuditLog is audit log used for tests.
func NewMockAuditLog ¶
func NewMockAuditLog(capacity int) *MockAuditLog
NewMockAuditLog returns an instance of MockAuditLog.
func (*MockAuditLog) Close ¶
func (d *MockAuditLog) Close() error
func (*MockAuditLog) EmitAuditEvent ¶
func (d *MockAuditLog) EmitAuditEvent(ev Event, fields EventFields) error
EmitAuditEvent is a mock that records even and fields inside a struct.
func (*MockAuditLog) GetError ¶
func (d *MockAuditLog) GetError() error
func (*MockAuditLog) GetSessionChunk ¶
func (*MockAuditLog) GetSessionEvents ¶
func (d *MockAuditLog) GetSessionEvents(namespace string, sid session.ID, after int, fetchPrintEvents bool) ([]EventFields, error)
func (*MockAuditLog) PostSessionSlice ¶
func (d *MockAuditLog) PostSessionSlice(slice SessionSlice) error
func (*MockAuditLog) SearchEvents ¶
func (d *MockAuditLog) SearchEvents(fromUTC, toUTC time.Time, query string, limit int) ([]EventFields, error)
func (*MockAuditLog) SearchSessionEvents ¶
func (d *MockAuditLog) SearchSessionEvents(fromUTC, toUTC time.Time, limit int) ([]EventFields, error)
func (*MockAuditLog) SetError ¶
func (d *MockAuditLog) SetError(e error)
func (*MockAuditLog) UploadSessionRecording ¶
func (d *MockAuditLog) UploadSessionRecording(SessionRecording) error
func (*MockAuditLog) WaitForDelivery ¶
func (d *MockAuditLog) WaitForDelivery(context.Context) error
type MultiLog ¶
type MultiLog struct {
// contains filtered or unexported fields
}
MultiLog is a logger that fan outs write operations to all loggers, and performs all read and search operations on the first logger that implements the operation
func NewMultiLog ¶
NewMultiLog returns a new instance of a multi logger
func (*MultiLog) EmitAuditEvent ¶
func (m *MultiLog) EmitAuditEvent(event Event, fields EventFields) error
EmitAuditEvent emits audit event
func (*MultiLog) GetSessionChunk ¶
func (m *MultiLog) GetSessionChunk(namespace string, sid session.ID, offsetBytes, maxBytes int) (data []byte, err error)
GetSessionChunk returns a reader which can be used to read a byte stream of a recorded session starting from 'offsetBytes' (pass 0 to start from the beginning) up to maxBytes bytes.
If maxBytes > MaxChunkBytes, it gets rounded down to MaxChunkBytes
func (*MultiLog) GetSessionEvents ¶
func (m *MultiLog) GetSessionEvents(namespace string, sid session.ID, after int, fetchPrintEvents bool) (events []EventFields, err error)
Returns all events that happen during a session sorted by time (oldest first).
after tells to use only return events after a specified cursor Id
This function is usually used in conjunction with GetSessionReader to replay recorded session streams.
func (*MultiLog) PostSessionSlice ¶
func (m *MultiLog) PostSessionSlice(slice SessionSlice) error
DELETE IN: 2.7.0 This method is no longer necessary as nodes and proxies >= 2.7.0 use UploadSessionRecording method. PostSessionSlice sends chunks of recorded session to the event log
func (*MultiLog) SearchEvents ¶
func (m *MultiLog) SearchEvents(fromUTC, toUTC time.Time, query string, limit int) (events []EventFields, err error)
SearchEvents is a flexible way to find events. The format of a query string depends on the implementing backend. A recommended format is urlencoded (good enough for Lucene/Solr)
Pagination is also defined via backend-specific query format.
The only mandatory requirement is a date range (UTC). Results must always show up sorted by date (newest first)
func (*MultiLog) SearchSessionEvents ¶
func (m *MultiLog) SearchSessionEvents(fromUTC, toUTC time.Time, limit int) (events []EventFields, err error)
SearchSessionEvents returns session related events only. This is used to find completed session.
func (*MultiLog) UploadSessionRecording ¶
func (m *MultiLog) UploadSessionRecording(rec SessionRecording) error
UploadSessionRecording uploads session recording to the audit server
type SessionChunk ¶
type SessionChunk struct { // Time is the occurence of this event Time int64 `protobuf:"varint,2,opt,name=Time,proto3" json:"Time,omitempty"` // Data is captured data, contains event fields in case of event, session data // otherwise Data []byte `protobuf:"bytes,3,opt,name=Data,proto3" json:"Data,omitempty"` // EventType is event type EventType string `protobuf:"bytes,4,opt,name=EventType,proto3" json:"EventType,omitempty"` // EventIndex is the event global index EventIndex int64 `protobuf:"varint,5,opt,name=EventIndex,proto3" json:"EventIndex,omitempty"` // Index is the autoincremented chunk index ChunkIndex int64 `protobuf:"varint,6,opt,name=ChunkIndex,proto3" json:"ChunkIndex,omitempty"` // Offset is an offset from the previous chunk in bytes Offset int64 `protobuf:"varint,7,opt,name=Offset,proto3" json:"Offset,omitempty"` // Delay is a delay from the previous event in milliseconds Delay int64 `protobuf:"varint,8,opt,name=Delay,proto3" json:"Delay,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` }
SessionChunk is a chunk to be posted in the context of the session
func (*SessionChunk) Descriptor ¶
func (*SessionChunk) Descriptor() ([]byte, []int)
func (*SessionChunk) GetChunkIndex ¶
func (m *SessionChunk) GetChunkIndex() int64
func (*SessionChunk) GetData ¶
func (m *SessionChunk) GetData() []byte
func (*SessionChunk) GetDelay ¶
func (m *SessionChunk) GetDelay() int64
func (*SessionChunk) GetEventIndex ¶
func (m *SessionChunk) GetEventIndex() int64
func (*SessionChunk) GetEventType ¶
func (m *SessionChunk) GetEventType() string
func (*SessionChunk) GetOffset ¶
func (m *SessionChunk) GetOffset() int64
func (*SessionChunk) GetTime ¶
func (m *SessionChunk) GetTime() int64
func (*SessionChunk) Marshal ¶
func (m *SessionChunk) Marshal() (dAtA []byte, err error)
func (*SessionChunk) ProtoMessage ¶
func (*SessionChunk) ProtoMessage()
func (*SessionChunk) Reset ¶
func (m *SessionChunk) Reset()
func (*SessionChunk) Size ¶
func (m *SessionChunk) Size() (n int)
func (*SessionChunk) String ¶
func (m *SessionChunk) String() string
func (*SessionChunk) Unmarshal ¶
func (m *SessionChunk) Unmarshal(dAtA []byte) error
func (*SessionChunk) XXX_DiscardUnknown ¶
func (m *SessionChunk) XXX_DiscardUnknown()
func (*SessionChunk) XXX_Marshal ¶
func (m *SessionChunk) XXX_Marshal(b []byte, deterministic bool) ([]byte, error)
func (*SessionChunk) XXX_Merge ¶
func (dst *SessionChunk) XXX_Merge(src proto.Message)
func (*SessionChunk) XXX_Size ¶
func (m *SessionChunk) XXX_Size() int
func (*SessionChunk) XXX_Unmarshal ¶
func (m *SessionChunk) XXX_Unmarshal(b []byte) error
type SessionLogger ¶ added in v1.0.0
type SessionLogger interface { // LogEvent logs events associated with this session. LogEvent(fields EventFields) error // Close is called when clients close on the requested "session writer". // We ignore their requests because this writer (file) should be closed only // when the session logger is closed. Close() error // Finalize is called by the session when it's closing. This is where we're // releasing audit resources associated with the session Finalize() error // PostSessionSlice posts session slice PostSessionSlice(slice SessionSlice) error }
sessionLogger is an interface that all session loggers must implement.
type SessionRecorder ¶
type SessionRecorder interface { io.Writer io.Closer // GetAuditLog returns audit log associated with this log GetAuditLog() IAuditLog }
SessionRecorder implements io.Writer to be plugged into the multi-writer associated with every session. It forwards session stream to the audit log
type SessionRecording ¶
type SessionRecording struct { // Namespace is a session namespace Namespace string // SessionID is a session ID SessionID session.ID // Recording is a packaged tarball recording Recording io.Reader }
SessionRecording is a recording of a live session
func (*SessionRecording) CheckAndSetDefaults ¶
func (l *SessionRecording) CheckAndSetDefaults() error
CheckAndSetDefaults checks and sets default parameters
type SessionSlice ¶
type SessionSlice struct { // Namespace is a session namespace Namespace string `protobuf:"bytes,1,opt,name=Namespace,proto3" json:"Namespace,omitempty"` // SessionID is a session ID associated with this chunk SessionID string `protobuf:"bytes,2,opt,name=SessionID,proto3" json:"SessionID,omitempty"` // Chunks is a list of submitted session chunks Chunks []*SessionChunk `protobuf:"bytes,3,rep,name=Chunks" json:"Chunks,omitempty"` // Version specifies session slice version Version int64 `protobuf:"varint,4,opt,name=Version,proto3" json:"Version,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` }
SessionSlice is a slice of submitted chunks
func (*SessionSlice) Descriptor ¶
func (*SessionSlice) Descriptor() ([]byte, []int)
func (*SessionSlice) GetChunks ¶
func (m *SessionSlice) GetChunks() []*SessionChunk
func (*SessionSlice) GetNamespace ¶
func (m *SessionSlice) GetNamespace() string
func (*SessionSlice) GetSessionID ¶
func (m *SessionSlice) GetSessionID() string
func (*SessionSlice) GetVersion ¶
func (m *SessionSlice) GetVersion() int64
func (*SessionSlice) Marshal ¶
func (m *SessionSlice) Marshal() (dAtA []byte, err error)
func (*SessionSlice) ProtoMessage ¶
func (*SessionSlice) ProtoMessage()
func (*SessionSlice) Reset ¶
func (m *SessionSlice) Reset()
func (*SessionSlice) Size ¶
func (m *SessionSlice) Size() (n int)
func (*SessionSlice) String ¶
func (m *SessionSlice) String() string
func (*SessionSlice) Unmarshal ¶
func (m *SessionSlice) Unmarshal(dAtA []byte) error
func (*SessionSlice) XXX_DiscardUnknown ¶
func (m *SessionSlice) XXX_DiscardUnknown()
func (*SessionSlice) XXX_Marshal ¶
func (m *SessionSlice) XXX_Marshal(b []byte, deterministic bool) ([]byte, error)
func (*SessionSlice) XXX_Merge ¶
func (dst *SessionSlice) XXX_Merge(src proto.Message)
func (*SessionSlice) XXX_Size ¶
func (m *SessionSlice) XXX_Size() int
func (*SessionSlice) XXX_Unmarshal ¶
func (m *SessionSlice) XXX_Unmarshal(b []byte) error
type UploadEvent ¶
type UploadEvent struct { // SessionID is a session ID SessionID string // Error is set in case if event resulted in error Error error }
UploadEvent is emitted by uploader and is used in tests
type UploadHandler ¶
type UploadHandler interface { // Upload uploads session tarball and returns URL with uploaded file // in case of success. Upload(ctx context.Context, sessionID session.ID, readCloser io.Reader) (string, error) // Download downloads session tarball and writes it to writer Download(ctx context.Context, sessionID session.ID, writer io.WriterAt) error }
UploadHandler is a function supplied by the user, it will upload the file
type Uploader ¶
type Uploader struct { UploaderConfig *log.Entry // contains filtered or unexported fields }
Uploader implements a disk based session logger. The imporant property of the disk based logger is that it never fails and can be used as a fallback implementation behind more sophisticated loggers.
func NewUploader ¶
func NewUploader(cfg UploaderConfig) (*Uploader, error)
NewUploader creates new disk based session logger
type UploaderConfig ¶
type UploaderConfig struct { // DataDir is data directory for session events files DataDir string // Clock is the clock replacement Clock clockwork.Clock // Namespace is logger namespace Namespace string // ServerID is a server ID ServerID string // Context is an optional context Context context.Context // ScanPeriod is a uploader dir scan period ScanPeriod time.Duration // ConcurrentUploads sets up how many parallel uploads to schedule ConcurrentUploads int // AuditLog is audit log client AuditLog IAuditLog // EventsC is an event channel used to signal events // used in tests EventsC chan *UploadEvent }
UploaderConfig sets up configuration for uploader service
func (*UploaderConfig) CheckAndSetDefaults ¶
func (cfg *UploaderConfig) CheckAndSetDefaults() error
CheckAndSetDefaults checks and sets default values of UploaderConfig
type WriterLog ¶
type WriterLog struct {
// contains filtered or unexported fields
}
WriterLog is an audit log that emits all events to the external writer
func NewWriterLog ¶
func NewWriterLog(w io.WriteCloser) *WriterLog
NewWriterLog returns a new instance of writer log
func (*WriterLog) EmitAuditEvent ¶
func (w *WriterLog) EmitAuditEvent(event Event, fields EventFields) error
EmitAuditEvent emits audit event
func (*WriterLog) GetSessionChunk ¶
func (w *WriterLog) GetSessionChunk(namespace string, sid session.ID, offsetBytes, maxBytes int) ([]byte, error)
GetSessionChunk returns a reader which can be used to read a byte stream of a recorded session starting from 'offsetBytes' (pass 0 to start from the beginning) up to maxBytes bytes.
If maxBytes > MaxChunkBytes, it gets rounded down to MaxChunkBytes
func (*WriterLog) GetSessionEvents ¶
func (w *WriterLog) GetSessionEvents(namespace string, sid session.ID, after int, includePrintEvents bool) ([]EventFields, error)
Returns all events that happen during a session sorted by time (oldest first).
after tells to use only return events after a specified cursor Id
This function is usually used in conjunction with GetSessionReader to replay recorded session streams.
func (*WriterLog) PostSessionSlice ¶
func (w *WriterLog) PostSessionSlice(SessionSlice) error
DELETE IN: 2.7.0 This method is no longer necessary as nodes and proxies >= 2.7.0 use UploadSessionRecording method. PostSessionSlice sends chunks of recorded session to the event log
func (*WriterLog) SearchEvents ¶
func (w *WriterLog) SearchEvents(fromUTC, toUTC time.Time, query string, limit int) ([]EventFields, error)
SearchEvents is a flexible way to find events. The format of a query string depends on the implementing backend. A recommended format is urlencoded (good enough for Lucene/Solr)
Pagination is also defined via backend-specific query format.
The only mandatory requirement is a date range (UTC). Results must always show up sorted by date (newest first)
func (*WriterLog) SearchSessionEvents ¶
func (w *WriterLog) SearchSessionEvents(fromUTC time.Time, toUTC time.Time, limit int) ([]EventFields, error)
SearchSessionEvents returns session related events only. This is used to find completed session.
func (*WriterLog) UploadSessionRecording ¶
func (w *WriterLog) UploadSessionRecording(r SessionRecording) error
UploadSessionRecording uploads session recording to the audit server
Source Files ¶
Directories ¶
Path | Synopsis |
---|---|
Package firestoreeventsLog implements Firestore storage backend for Teleport event storage.
|
Package firestoreeventsLog implements Firestore storage backend for Teleport event storage. |
Package gcssessionsHandler implements GCS storage for Teleport session recording persistence.
|
Package gcssessionsHandler implements GCS storage for Teleport session recording persistence. |