sessionrecording

package
v1.92.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Dec 10, 2025 License: BSD-3-Clause Imports: 15 Imported by: 6

Documentation

Overview

Package sessionrecording contains session recording utils shared amongst Tailscale SSH and Kubernetes API server proxy session recording.

Index

Constants

View Source
const (
	KubernetesAPIEventType = "kubernetes-api-request"
)

Variables

This section is empty.

Functions

func ConnectToRecorder

func ConnectToRecorder(ctx context.Context, recs []netip.AddrPort, dial netx.DialFunc) (io.WriteCloser, []*tailcfg.SSHRecordingAttempt, <-chan error, error)

ConnectToRecorder connects to the recorder at any of the provided addresses. It returns the first successful response, or a multierr if all attempts fail.

On success, it returns a WriteCloser that can be used to upload the recording, and a channel that will be sent an error (or nil) when the upload fails or completes.

In both cases, a slice of SSHRecordingAttempts is returned which detail the attempted recorder IP and the error message, if the attempt failed. The attempts are in order the recorder(s) was attempted. If successful a successful connection is made, the last attempt in the slice is the attempt for connected recorder.

func SendEvent added in v1.90.0

func SendEvent(ap netip.AddrPort, event io.Reader, dial netx.DialFunc) (retErr error)

SendEvent sends an event the tsrecorders /v2/event endpoint.

Types

type CastHeader

type CastHeader struct {
	// Version is the asciinema file format version.
	Version int `json:"version"`

	// Width is the terminal width in characters.
	// It is non-zero for Pty sessions.
	Width int `json:"width"`

	// Height is the terminal height in characters.
	// It is non-zero for Pty sessions.
	Height int `json:"height"`

	// Timestamp is the unix timestamp of when the recording started.
	Timestamp int64 `json:"timestamp"`

	// Command is the command that was executed.
	// Typically empty for shell sessions.
	Command string `json:"command,omitempty"`

	// SrcNode is the FQDN of the node originating the connection.
	// It is also the MagicDNS name for the node.
	// It does not have a trailing dot.
	// e.g. "host.tail-scale.ts.net"
	SrcNode string `json:"srcNode"`

	// SrcNodeID is the node ID of the node originating the connection.
	SrcNodeID tailcfg.StableNodeID `json:"srcNodeID"`

	// Tailscale-specific fields:
	// SrcNodeTags is the list of tags on the node originating the connection (if any).
	SrcNodeTags []string `json:"srcNodeTags,omitempty"`

	// SrcNodeUserID is the user ID of the node originating the connection (if not tagged).
	SrcNodeUserID tailcfg.UserID `json:"srcNodeUserID,omitempty"` // if not tagged

	// SrcNodeUser is the LoginName of the node originating the connection (if not tagged).
	SrcNodeUser string `json:"srcNodeUser,omitempty"`

	// Env is the environment variables of the session.
	// Only "TERM" is set (2023-03-22).
	Env map[string]string `json:"env"`

	// SSHUser is the username as presented by the client.
	SSHUser string `json:"sshUser"` // as presented by the client

	// LocalUser is the effective username on the server.
	LocalUser string `json:"localUser"`

	// ConnectionID uniquely identifies a connection made to the SSH server.
	// It may be shared across multiple sessions over the same connection in
	// case of SSH multiplexing.
	ConnectionID string `json:"connectionID"`

	// Fields that are only set for Kubernetes API server proxy session recordings:
	Kubernetes *Kubernetes `json:"kubernetes,omitempty"`
}

CastHeader is the header of an asciinema file.

type Destination added in v1.90.0

type Destination struct {
	// Node is the FQDN of the node receiving the connection.
	// It is also the MagicDNS name for the node.
	// It does not have a trailing dot.
	// e.g. "host.tail-scale.ts.net"
	Node string `json:"node"`

	// NodeID is the node ID of the node receiving the connection.
	NodeID tailcfg.StableNodeID `json:"nodeID"`
}

type Event added in v1.90.0

type Event struct {
	// Type specifies the kind of event being recorded (e.g., "kubernetes-api-request").
	Type string `json:"type"`

	// ID is a reference of the path that this event is stored at in tsrecorder
	ID string `json:"id"`

	// Timestamp is the time when the event was recorded represented as a unix timestamp.
	Timestamp int64 `json:"timestamp"`

	// UserAgent is the UerAgent specified in the request, which helps identify
	// the client software that initiated the request.
	UserAgent string `json:"userAgent"`

	// Request holds details of the HTTP request.
	Request Request `json:"request"`

	// Kubernetes contains Kubernetes-specific information about the request (if
	// the type is `kubernetes-api-request`)
	Kubernetes KubernetesRequestInfo `json:"kubernetes"`

	// Source provides details about the client that initiated the request.
	Source Source `json:"source"`

	// Destination provides details about the node receiving the request.
	Destination Destination `json:"destination"`
}

Event represents the top-level structure of a tsrecorder event.

type EventAPINotSupportedErr added in v1.90.0

type EventAPINotSupportedErr struct {
	// contains filtered or unexported fields
}

func (EventAPINotSupportedErr) Error added in v1.90.0

func (e EventAPINotSupportedErr) Error() string

type Kubernetes

type Kubernetes struct {
	// PodName is the name of the Pod the session was recorded for.
	PodName string
	// Namespace is the namespace in which the Pod the session was recorded for exists in.
	Namespace string
	// Container is the container the session was recorded for.
	Container string
	// SessionType is the type of session that was executed (e.g., exec, attach)
	SessionType string
}

Kubernetes contains 'kubectl exec/attach' session specific information for tsrecorder.

type KubernetesRequestInfo added in v1.90.0

type KubernetesRequestInfo struct {
	// IsResourceRequest indicates whether or not the request is for an API resource or subresource
	IsResourceRequest bool
	// Path is the URL path of the request
	Path string
	// Verb is the kube verb associated with the request for API requests, not the http verb.  This includes things like list and watch.
	// for non-resource requests, this is the lowercase http verb
	Verb string

	APIPrefix  string
	APIGroup   string
	APIVersion string

	Namespace string
	// Resource is the name of the resource being requested.  This is not the kind.  For example: pods
	Resource string
	// Subresource is the name of the subresource being requested.  This is a different resource, scoped to the parent resource, but it may have a different kind.
	// For instance, /pods has the resource "pods" and the kind "Pod", while /pods/foo/status has the resource "pods", the sub resource "status", and the kind "Pod"
	// (because status operates on pods). The binding resource for a pod though may be /pods/foo/binding, which has resource "pods", subresource "binding", and kind "Binding".
	Subresource string
	// Name is empty for some verbs, but if the request directly indicates a name (not in body content) then this field is filled in.
	Name string
	// Parts are the path parts for the request, always starting with /{resource}/{name}
	Parts []string

	// FieldSelector contains the unparsed field selector from a request.  It is only present if the apiserver
	// honors field selectors for the verb this request is associated with.
	FieldSelector string
	// LabelSelector contains the unparsed field selector from a request.  It is only present if the apiserver
	// honors field selectors for the verb this request is associated with.
	LabelSelector string
}

copied from https://github.com/kubernetes/kubernetes/blob/11ade2f7dd264c2f52a4a1342458abbbaa3cb2b1/staging/src/k8s.io/apiserver/pkg/endpoints/request/requestinfo.go#L44 KubernetesRequestInfo contains Kubernetes specific information in the request (if the type is `kubernetes-api-request`)

type Request added in v1.90.0

type Request struct {
	Method          string     `json:"method"`
	Path            string     `json:"path"`
	Body            []byte     `json:"body"`
	QueryParameters url.Values `json:"queryParameters"`
}

Request holds information about a request.

type Source added in v1.90.0

type Source struct {
	// Node is the FQDN of the node originating the connection.
	// It is also the MagicDNS name for the node.
	// It does not have a trailing dot.
	// e.g. "host.tail-scale.ts.net"
	Node string `json:"node"`

	// NodeID is the node ID of the node originating the connection.
	NodeID tailcfg.StableNodeID `json:"nodeID"`

	// Tailscale-specific fields:
	// NodeTags is the list of tags on the node originating the connection (if any).
	NodeTags []string `json:"nodeTags,omitempty"`

	// NodeUserID is the user ID of the node originating the connection (if not tagged).
	NodeUserID tailcfg.UserID `json:"nodeUserID,omitempty"` // if not tagged

	// NodeUser is the LoginName of the node originating the connection (if not tagged).
	NodeUser string `json:"nodeUser,omitempty"`
}

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL