terminal

package
v1.144.0 Latest Latest
Warning

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

Go to latest
Published: Jun 3, 2026 License: MIT Imports: 23 Imported by: 0

Documentation

Overview

internal/terminal/auth.go

internal/terminal/config.go

internal/terminal/errors.go

internal/terminal/mock_server.go

internal/terminal/protocol.go

internal/terminal/ratelimit.go

internal/terminal/server.go

Index

Constants

View Source
const (
	// MessageTypeInput is sent from client to server with terminal input
	MessageTypeInput = "input"

	// MessageTypeOutput is sent from server to client with terminal output
	MessageTypeOutput = "output"

	// MessageTypeResize is sent from client to server to resize the terminal
	MessageTypeResize = "resize"

	// MessageTypeError is sent from server to client to indicate an error
	MessageTypeError = "error"

	// MessageTypePing is sent from either side to check connection health
	MessageTypePing = "ping"

	// MessageTypePong is sent in response to a ping message
	MessageTypePong = "pong"
)

MessageType constants define the types of WebSocket messages

Variables

View Source
var (
	// ErrInvalidPort indicates the port number is out of valid range
	ErrInvalidPort = errors.New("port must be between 1 and 65535")

	// ErrInvalidMaxConnections indicates max connections is too low
	ErrInvalidMaxConnections = errors.New("max connections must be at least 1")

	// ErrInvalidIdleTimeout indicates idle timeout is too short
	ErrInvalidIdleTimeout = errors.New("idle timeout must be at least 1 minute")

	// ErrMissingOrgID indicates the organization ID is required but not set
	ErrMissingOrgID = errors.New("organization ID is required")
)

Configuration errors

View Source
var (
	// ErrInvalidToken indicates the authentication token is invalid
	ErrInvalidToken = errors.New("invalid or expired authentication token")

	// ErrTokenExpired indicates the authentication token has expired
	ErrTokenExpired = errors.New("authentication token has expired")

	// ErrUnauthorized indicates the user is not authorized for this action
	ErrUnauthorized = errors.New("unauthorized")

	// ErrAuthServiceUnavailable indicates the auth service could not be reached
	ErrAuthServiceUnavailable = errors.New("authentication service unavailable")
)

Authentication errors

View Source
var (
	// ErrMaxConnectionsReached indicates the server has reached its connection limit
	ErrMaxConnectionsReached = errors.New("maximum connections reached")

	// ErrConnectionClosed indicates the connection was closed unexpectedly
	ErrConnectionClosed = errors.New("connection closed")

	// ErrIdleTimeout indicates the connection was closed due to inactivity
	ErrIdleTimeout = errors.New("connection closed due to idle timeout")
)

Connection errors

View Source
var (
	// ErrSessionNotFound indicates the requested session does not exist
	ErrSessionNotFound = errors.New("session not found")

	// ErrSessionAlreadyExists indicates a session with that ID already exists
	ErrSessionAlreadyExists = errors.New("session already exists")

	// ErrPTYCreationFailed indicates the PTY could not be created
	ErrPTYCreationFailed = errors.New("failed to create PTY")

	// ErrShellNotFound indicates the configured shell could not be found
	ErrShellNotFound = errors.New("shell not found")
)

Session errors

View Source
var (
	// ErrInvalidMessageType indicates the message type is not recognized
	ErrInvalidMessageType = errors.New("invalid message type")

	// ErrInvalidResize indicates the resize dimensions are invalid
	ErrInvalidResize = errors.New("invalid resize dimensions: cols and rows must be > 0")

	// ErrInvalidMessage indicates the message is malformed
	ErrInvalidMessage = errors.New("invalid message format")
)

Protocol errors

View Source
var (
	// ErrServerNotRunning indicates the server is not currently running
	ErrServerNotRunning = errors.New("server is not running")

	// ErrServerAlreadyRunning indicates the server is already running
	ErrServerAlreadyRunning = errors.New("server is already running")
)

Server errors

View Source
var (
	// ErrRateLimited indicates the client has exceeded the rate limit
	ErrRateLimited = errors.New("rate limit exceeded, please try again later")
)

Rate limiting errors

Functions

This section is empty.

Types

type CachedTokenEntry

type CachedTokenEntry struct {
	Hash      string     // SHA-256 hash of the token
	Info      *TokenInfo // Token metadata
	FetchedAt time.Time  // When this token was fetched
}

CachedTokenEntry represents a cached token with its info

type CachingTokenValidator

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

CachingTokenValidator wraps a token validator with local caching It fetches token hashes from the API periodically and validates locally

func NewCachingTokenValidator

func NewCachingTokenValidator(baseURL, orgID string, refreshInterval time.Duration) *CachingTokenValidator

NewCachingTokenValidator creates a new caching token validator

func (*CachingTokenValidator) CacheSize

func (v *CachingTokenValidator) CacheSize() int

CacheSize returns the number of tokens in the cache (for testing)

func (*CachingTokenValidator) LastRefreshTime

func (v *CachingTokenValidator) LastRefreshTime() time.Time

LastRefreshTime returns when the cache was last refreshed (for testing)

func (*CachingTokenValidator) SetLogFn added in v1.144.0

func (v *CachingTokenValidator) SetLogFn(logFn func(level, msg string))

SetLogFn sets the logging callback. If set, warnings will be routed through this callback instead of printing to stdout. Use this for TUI mode.

func (*CachingTokenValidator) Start

func (v *CachingTokenValidator) Start() error

Start begins the background token refresh goroutine

func (*CachingTokenValidator) Stop

func (v *CachingTokenValidator) Stop()

Stop stops the background refresh goroutine

func (*CachingTokenValidator) ValidateToken

func (v *CachingTokenValidator) ValidateToken(token string, orgID string) (*TokenInfo, error)

ValidateToken validates a token using the local cache

type Config

type Config struct {
	// Host is the address the WebSocket server binds to (default: 0.0.0.0)
	Host string

	// Port is the port the WebSocket server listens on
	Port int

	// Version is the server version string (passed from cmd package)
	Version string

	// Enabled determines whether the terminal service is active
	Enabled bool

	// IdleTimeout is the duration after which idle connections are closed
	IdleTimeout time.Duration

	// MaxConnections is the maximum number of concurrent terminal sessions
	MaxConnections int

	// Shell is the shell to spawn for terminal sessions
	Shell string

	// AuthServiceURL is the URL of the AceTeam auth service for token validation
	AuthServiceURL string

	// OrgID is the organization ID for token validation
	OrgID string

	// RateLimitRPS is the rate limit in requests per second per IP
	RateLimitRPS float64

	// RateLimitBurst is the burst limit for rate limiting
	RateLimitBurst int

	// TokenRefreshInterval is how often to refresh the token cache from the API
	TokenRefreshInterval time.Duration

	// Debug enables verbose debug logging
	Debug bool
}

Config holds the terminal server configuration

func DefaultConfig

func DefaultConfig() *Config

DefaultConfig returns a Config with sensible defaults

func (*Config) Validate

func (c *Config) Validate() error

Validate checks that the configuration is valid

type HTTPTokenValidator

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

HTTPTokenValidator validates tokens against the AceTeam API

func NewHTTPTokenValidator

func NewHTTPTokenValidator(baseURL string) *HTTPTokenValidator

NewHTTPTokenValidator creates a new HTTP-based token validator

func (*HTTPTokenValidator) ValidateToken

func (v *HTTPTokenValidator) ValidateToken(token string, orgID string) (*TokenInfo, error)

ValidateToken validates a token against the AceTeam API

type Logger added in v1.144.0

type Logger interface {
	Printf(format string, v ...interface{})
	Debugf(format string, v ...interface{})
}

Logger is the interface for terminal server logging

type Message

type Message struct {
	// Type indicates the message type (input, output, resize, error, ping, pong)
	Type string `json:"type"`

	// Payload contains the data for input/output messages (base64-encoded for binary safety)
	Payload []byte `json:"payload,omitempty"`

	// Cols is the number of columns for resize messages
	Cols uint16 `json:"cols,omitempty"`

	// Rows is the number of rows for resize messages
	Rows uint16 `json:"rows,omitempty"`

	// Error contains the error message for error type messages
	Error string `json:"error,omitempty"`
}

Message represents a WebSocket message for terminal communication

func NewErrorMessage

func NewErrorMessage(err string) *Message

NewErrorMessage creates a new error message

func NewInputMessage

func NewInputMessage(data []byte) *Message

NewInputMessage creates a new input message

func NewOutputMessage

func NewOutputMessage(data []byte) *Message

NewOutputMessage creates a new output message

func NewPingMessage

func NewPingMessage() *Message

NewPingMessage creates a new ping message

func NewPongMessage

func NewPongMessage() *Message

NewPongMessage creates a new pong message

func NewResizeMessage

func NewResizeMessage(cols, rows uint16) *Message

NewResizeMessage creates a new resize message

func UnmarshalMessage

func UnmarshalMessage(data []byte) (*Message, error)

UnmarshalMessage deserializes a JSON message

func (*Message) Marshal

func (m *Message) Marshal() ([]byte, error)

Marshal serializes the message to JSON

func (*Message) Validate

func (m *Message) Validate() error

Validate checks that the message is well-formed

type MockAuthServer

type MockAuthServer struct {

	// RequestCount tracks the number of validation requests
	RequestCount int

	// ShouldFail causes all requests to return an error
	ShouldFail bool

	// FailStatusCode is the HTTP status code to return when failing
	FailStatusCode int
	// contains filtered or unexported fields
}

MockAuthServer provides a mock HTTP server for testing token validation

func StartMockAuthServer

func StartMockAuthServer() *MockAuthServer

StartMockAuthServer creates and starts a mock auth server

func (*MockAuthServer) AddValidToken

func (m *MockAuthServer) AddValidToken(token string, info *TokenInfo)

AddValidToken adds a valid token to the mock server

func (*MockAuthServer) Clear

func (m *MockAuthServer) Clear()

Clear removes all valid tokens

func (*MockAuthServer) Close

func (m *MockAuthServer) Close()

Close shuts down the mock server

func (*MockAuthServer) GetRequestCount

func (m *MockAuthServer) GetRequestCount() int

GetRequestCount returns the number of requests made

func (*MockAuthServer) RemoveToken

func (m *MockAuthServer) RemoveToken(token string)

RemoveToken removes a token from the mock server

func (*MockAuthServer) ResetRequestCount

func (m *MockAuthServer) ResetRequestCount()

ResetRequestCount resets the request counter

func (*MockAuthServer) SetShouldFail

func (m *MockAuthServer) SetShouldFail(fail bool, statusCode int)

SetShouldFail configures whether the server should fail all requests

func (*MockAuthServer) URL

func (m *MockAuthServer) URL() string

URL returns the base URL of the mock server

type MockTokenValidator

type MockTokenValidator struct {
	// ValidTokens maps tokens to their token info
	ValidTokens map[string]*TokenInfo

	// ShouldFail causes all validations to fail
	ShouldFail bool

	// FailError is the error to return when ShouldFail is true
	FailError error
}

MockTokenValidator is a token validator for testing

func NewMockTokenValidator

func NewMockTokenValidator() *MockTokenValidator

NewMockTokenValidator creates a new mock token validator

func (*MockTokenValidator) AddValidToken

func (v *MockTokenValidator) AddValidToken(token string, info *TokenInfo)

AddValidToken adds a valid token to the mock validator

func (*MockTokenValidator) ValidateToken

func (v *MockTokenValidator) ValidateToken(token string, orgID string) (*TokenInfo, error)

ValidateToken implements TokenValidator for the mock

type RateLimiter

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

RateLimiter provides per-IP rate limiting for connection attempts

func NewRateLimiter

func NewRateLimiter(rps float64, burst int) *RateLimiter

NewRateLimiter creates a new per-IP rate limiter

func (*RateLimiter) Allow

func (rl *RateLimiter) Allow(ip string) bool

Allow checks if a request from the given IP is allowed

func (*RateLimiter) Count

func (rl *RateLimiter) Count() int

Count returns the number of tracked IPs

func (*RateLimiter) Reserve

func (rl *RateLimiter) Reserve(ip string) *rate.Reservation

Reserve reserves a token for the given IP and returns a Reservation

func (*RateLimiter) Reset

func (rl *RateLimiter) Reset()

Reset clears all rate limiter entries

func (*RateLimiter) Stop

func (rl *RateLimiter) Stop()

Stop stops the rate limiter's cleanup goroutine

func (*RateLimiter) Wait

func (rl *RateLimiter) Wait(ip string) error

Wait blocks until a request from the given IP is allowed or returns an error

type Server

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

Server is the WebSocket terminal server

func NewServer

func NewServer(config *Config, auth TokenValidator) *Server

NewServer creates a new terminal server

func NewServerWithDebug added in v1.144.0

func NewServerWithDebug(config *Config, auth TokenValidator) *Server

NewServerWithDebug creates a new terminal server with debug logging enabled

func (*Server) IsRunning

func (s *Server) IsRunning() bool

IsRunning returns whether the server is currently running

func (*Server) Port

func (s *Server) Port() int

Port returns the configured port

func (*Server) SessionCount

func (s *Server) SessionCount() int

SessionCount returns the number of active sessions

func (*Server) SetSilent added in v1.144.0

func (s *Server) SetSilent()

SetSilent switches to a no-op logger to suppress all output. Use this in TUI mode to prevent log messages from corrupting the display.

func (*Server) Start

func (s *Server) Start() error

Start starts the terminal server

func (*Server) Stats added in v1.144.0

func (s *Server) Stats() (total, failed, active int64)

Stats returns the server statistics

func (*Server) Stop

func (s *Server) Stop(ctx context.Context) error

Stop gracefully stops the terminal server

type Session

type Session struct {
	// ID is the unique session identifier
	ID string

	// UserID is the user who owns this session
	UserID string

	// OrgID is the organization this session belongs to
	OrgID string
	// contains filtered or unexported fields
}

Session represents a terminal session with a PTY

func NewSession

func NewSession(config SessionConfig) (*Session, error)

NewSession creates a new terminal session with a PTY

func (*Session) Close

func (s *Session) Close() error

Close terminates the session

func (*Session) IsClosed

func (s *Session) IsClosed() bool

IsClosed returns whether the session is closed

func (*Session) LastActive

func (s *Session) LastActive() time.Time

LastActive returns the last activity timestamp

func (*Session) PTY

func (s *Session) PTY() io.ReadWriter

PTY returns the underlying PTY file (for advanced use)

func (*Session) Read

func (s *Session) Read(p []byte) (n int, err error)

Read reads from the PTY

func (*Session) Resize

func (s *Session) Resize(cols, rows uint16) error

Resize changes the PTY dimensions

func (*Session) Size

func (s *Session) Size() (cols, rows uint16)

Size returns the current PTY dimensions

func (*Session) Write

func (s *Session) Write(p []byte) (n int, err error)

Write writes to the PTY

type SessionConfig

type SessionConfig struct {
	// ID is the unique session identifier
	ID string

	// UserID is the user who owns this session
	UserID string

	// OrgID is the organization this session belongs to
	OrgID string

	// Shell is the shell command to run
	Shell string

	// InitialCols is the initial number of columns (default 80)
	InitialCols uint16

	// InitialRows is the initial number of rows (default 24)
	InitialRows uint16

	// Env is additional environment variables
	Env []string

	// OnClose is called when the session is closed
	OnClose func()
}

SessionConfig holds the configuration for creating a session

type SessionManager

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

SessionManager manages multiple terminal sessions

func NewSessionManager

func NewSessionManager(maxSessions int) *SessionManager

NewSessionManager creates a new session manager

func (*SessionManager) Add

func (m *SessionManager) Add(session *Session) error

Add adds a session to the manager

func (*SessionManager) CloseAll

func (m *SessionManager) CloseAll()

CloseAll closes all sessions

func (*SessionManager) CloseIdle

func (m *SessionManager) CloseIdle(timeout time.Duration) int

CloseIdle closes sessions that have been idle for longer than the timeout

func (*SessionManager) Count

func (m *SessionManager) Count() int

Count returns the number of active sessions

func (*SessionManager) Get

func (m *SessionManager) Get(id string) (*Session, error)

Get retrieves a session by ID

func (*SessionManager) Remove

func (m *SessionManager) Remove(id string)

Remove removes a session from the manager

type TokenHashEntry

type TokenHashEntry struct {
	Hash      string    `json:"hash"`
	UserID    string    `json:"user_id"`
	OrgID     string    `json:"org_id"`
	ExpiresAt time.Time `json:"expires_at"`
}

TokenHashEntry represents a single token entry from the API

type TokenInfo

type TokenInfo struct {
	// UserID is the user's identifier
	UserID string `json:"user_id"`

	// OrgID is the organization identifier
	OrgID string `json:"org_id"`

	// NodeID is the authorized node identifier (optional)
	NodeID string `json:"node_id,omitempty"`

	// ExpiresAt is when the token expires
	ExpiresAt time.Time `json:"expires_at"`

	// Permissions contains the authorized actions
	Permissions []string `json:"permissions,omitempty"`
}

TokenInfo contains the validated token information

type TokenValidator

type TokenValidator interface {
	// ValidateToken validates a token and returns the token info if valid
	ValidateToken(token string, orgID string) (*TokenInfo, error)
}

TokenValidator defines the interface for validating authentication tokens

type TokensResponse

type TokensResponse struct {
	Tokens []TokenHashEntry `json:"tokens"`
}

TokensResponse represents the response from the token list API

Jump to

Keyboard shortcuts

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