attach

package
v0.5.1 Latest Latest
Warning

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

Go to latest
Published: Mar 30, 2026 License: MIT Imports: 21 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func DiscoverAuthMethods

func DiscoverAuthMethods() ([]ssh.AuthMethod, error)

DiscoverAuthMethods returns all available SSH authentication methods. It checks the SSH agent first, then tries local private key files.

func Run

func Run(cfg Config) error

Run is the main entry point for the attach session. It establishes an SSH connection, starts the remote command, and runs the CC/egress mode loop.

Types

type Config

type Config struct {
	Host      string
	Port      int
	Username  string
	Command   string
	VMID      string
	AgentName string
	Client    *api.Client
}

Config holds everything needed to run an attach session.

type DomainEntry

type DomainEntry struct {
	Host         string
	RequestCount int
	LastSeen     time.Time
	Verdict      string // "allowed", "blocked", "warn"
	Protocol     string
	RuleID       string // non-empty if an allow rule exists for this host
	Events       []api.EgressAuditEvent
}

DomainEntry holds aggregated egress data for a single domain/host.

type EgressModel

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

EgressModel is the bubbletea model for the egress monitor TUI.

func NewEgressModel

func NewEgressModel(cfg EgressModelConfig) *EgressModel

NewEgressModel creates a new egress monitor model.

func (*EgressModel) Init

func (m *EgressModel) Init() tea.Cmd

func (*EgressModel) Quitting

func (m *EgressModel) Quitting() bool

Quitting returns true if the user pressed q to quit entirely.

func (*EgressModel) Update

func (m *EgressModel) Update(msg tea.Msg) (tea.Model, tea.Cmd)

func (*EgressModel) View

func (m *EgressModel) View() string

type EgressModelConfig

type EgressModelConfig struct {
	Store     *EgressStore
	Client    *api.Client
	Poller    *Poller
	VMID      string
	AgentName string
	SwitchCh  chan<- int32
	PollSub   <-chan struct{}
}

EgressModelConfig holds the configuration for creating an EgressModel.

type EgressStore

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

EgressStore is a thread-safe store of aggregated egress data.

func NewEgressStore

func NewEgressStore() *EgressStore

NewEgressStore creates an empty store.

func (*EgressStore) Ingest

func (s *EgressStore) Ingest(events []api.EgressAuditEvent)

Ingest adds audit events to the store, updating counts and timestamps.

func (*EgressStore) RuleIDForHost

func (s *EgressStore) RuleIDForHost(host string) string

RuleIDForHost returns the egress rule ID for a host, or empty string.

func (*EgressStore) Snapshot

func (s *EgressStore) Snapshot() []DomainEntry

Snapshot returns a sorted copy of all domain entries (most recent first).

func (*EgressStore) UpdateRules

func (s *EgressStore) UpdateRules(rules []api.EgressRule)

UpdateRules replaces the rule index, updating domain entries with rule IDs.

type InputMux

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

InputMux owns os.Stdin reads and routes bytes to either the SSH channel (CC mode) or a pipe feeding bubbletea (egress mode).

func NewInputMux

func NewInputMux(sshStdin io.Writer) *InputMux

NewInputMux creates an InputMux. The returned PipeReader should be passed to bubbletea via tea.WithInput().

func (*InputMux) Close

func (m *InputMux) Close()

Close cleans up the pipe.

func (*InputMux) Done

func (m *InputMux) Done() <-chan struct{}

Done returns a channel that is closed when stdin reading stops.

func (*InputMux) EgressReader

func (m *InputMux) EgressReader() *io.PipeReader

EgressReader returns the read end of the pipe for bubbletea input.

func (*InputMux) QuitCh

func (m *InputMux) QuitCh() <-chan struct{}

QuitCh returns a channel that signals the user wants to exit (double Ctrl-C).

func (*InputMux) Run

func (m *InputMux) Run()

Run reads from os.Stdin in a loop, routing bytes based on the current mode. It blocks until stdin returns an error (EOF, closed, etc).

In CC mode, Ctrl-] (0x1d) is intercepted and triggers a mode switch signal. In egress mode, all bytes (including Ctrl-]) pass through to bubbletea's input pipe so the TUI can handle keys natively.

func (*InputMux) SetMode

func (m *InputMux) SetMode(mode int32)

SetMode changes the current routing mode.

func (*InputMux) SwitchCh

func (m *InputMux) SwitchCh() <-chan int32

SwitchCh returns the channel that signals mode switches.

type OutputProxy

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

OutputProxy copies SSH stdout to os.Stdout, respecting a pause flag. When paused (egress mode), it discards output to prevent SSH channel backpressure. After each write in CC mode, it re-renders the status bar.

func NewOutputProxy

func NewOutputProxy(source io.Reader, mode *atomic.Int32, statusBar *StatusBar) *OutputProxy

NewOutputProxy creates an OutputProxy.

func (*OutputProxy) Done

func (o *OutputProxy) Done() <-chan struct{}

Done returns a channel closed when the output proxy stops (remote EOF).

func (*OutputProxy) Run

func (o *OutputProxy) Run()

Run copies from source to os.Stdout. In egress mode, bytes are discarded. Blocks until source returns an error.

type Poller

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

Poller periodically fetches egress audit data and rules from the API. It uses the `since` parameter to limit events to those from the session start, and drains all pages before waiting for the next poll interval.

func NewPoller

func NewPoller(client *api.Client, vmID string, store *EgressStore) *Poller

NewPoller creates a new egress poller scoped to events from now onward.

func (*Poller) Refresh

func (p *Poller) Refresh()

Refresh triggers an immediate poll cycle (non-blocking).

func (*Poller) Start

func (p *Poller) Start(ctx context.Context)

Start begins polling in a loop until the context is cancelled.

func (*Poller) Subscribe

func (p *Poller) Subscribe() <-chan struct{}

Subscribe returns a channel that receives a signal when new data is available.

type SSHConn

type SSHConn struct {
	Stdin  io.WriteCloser
	Stdout io.Reader
	// contains filtered or unexported fields
}

SSHConn wraps a Go SSH client, session, and the session's stdin/stdout pipes.

func Dial

func Dial(host string, port int, username string, authMethods []ssh.AuthMethod) (*SSHConn, error)

Dial establishes an SSH connection and opens a session.

func (*SSHConn) Close

func (c *SSHConn) Close()

Close tears down the session and connection.

func (*SSHConn) RequestPTY

func (c *SSHConn) RequestPTY(rows, cols int) error

RequestPTY requests a pseudo-terminal on the remote side.

func (*SSHConn) Resize

func (c *SSHConn) Resize(rows, cols int) error

Resize sends a window-change request to update the remote PTY size.

func (*SSHConn) Start

func (c *SSHConn) Start(command string) error

Start starts the given command on the remote side.

func (*SSHConn) Wait

func (c *SSHConn) Wait() error

Wait waits for the remote command to exit.

type StatusBar

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

StatusBar renders a persistent status line on the bottom row of the terminal during CC (SSH) mode. It uses ANSI escape sequences to position itself without disturbing the SSH output above.

func NewStatusBar

func NewStatusBar(rows, cols int, mode *atomic.Int32) *StatusBar

NewStatusBar creates a status bar. rows/cols are the full terminal dimensions.

func (*StatusBar) AckAlert

func (s *StatusBar) AckAlert()

AckAlert clears the new-denied alert state (e.g. after the user toggles to the egress monitor and sees the denied hosts).

func (*StatusBar) Clear

func (s *StatusBar) Clear()

Clear removes the status bar from the terminal.

func (*StatusBar) Render

func (s *StatusBar) Render()

Render writes the status bar to stdout using ANSI escape sequences. Safe to call from any goroutine; only renders in CC mode.

func (*StatusBar) Resize

func (s *StatusBar) Resize(rows, cols int)

Resize updates the terminal dimensions.

func (*StatusBar) Update

func (s *StatusBar) Update(domains []DomainEntry)

Update refreshes the status bar's data from an egress store snapshot.

Jump to

Keyboard shortcuts

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