remotessh

package
v0.182.2 Latest Latest
Warning

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

Go to latest
Published: Oct 5, 2026 License: Apache-2.0 Imports: 14 Imported by: 0

Documentation

Overview

Package remotessh is WB's single remote-call boundary: it builds the OpenSSH invocation, resolves the local ssh executable, and bounds what a remote response can make WB hold in memory.

Every element of a built argument list is either fixed or comes from validated WB configuration. Caller data never becomes part of the remote command, because OpenSSH joins the remote arguments into one string that the remote login shell then parses; the only safe channel for a request is standard input, which the remote WB entry point reads and validates exactly as it validates its own command line.

Index

Constants

View Source
const (
	// ExecutableName is the local SSH client WB invokes.
	ExecutableName = "ssh"
	// ConnectTimeoutSeconds is the default bound of connection establishment, so
	// an unreachable host fails in seconds rather than hanging a supervisor.
	ConnectTimeoutSeconds = 10
	// DefaultWBCommand is the remote command name used when a target configures
	// no exact path.
	DefaultWBCommand = "wb"
	// MaxDiagnosticBytes bounds the remote stderr WB is willing to quote back.
	MaxDiagnosticBytes = 1024
)
View Source
const SystemExecutable = "/usr/bin/ssh"

SystemExecutable is where the operating system's own ssh client is on the platforms that ship one.

Variables

This section is empty.

Functions

func Build

func Build(host, user string, remote []string) []string

Build returns the argv for one remote WB call with the default options. host and user must already have passed the caller's validation; remote is the fixed remote command line, whose first element is the remote wb executable.

func BuildWith added in v0.175.0

func BuildWith(options Options, host, user string, remote []string) []string

BuildWith is Build with the given options. The call never has a terminal (-T) and never prompts (BatchMode=yes). Host key checking is left to the user's ssh configuration and is never switched off here. The user is passed as a fixed `-l` pair and the host after `--`, so neither can be read as an option.

func Resolve

func Resolve(lookPath func(string) (string, error)) (string, error)

Resolve looks up and validates the local ssh executable. A result that is not an absolute, clean, regular, executable file is refused rather than handed to exec, so a PATH entry cannot substitute something else.

func ResolveTrusted added in v0.175.0

func ResolveTrusted(lookPath func(string) (string, error), preferred, home string) (string, error)

ResolveTrusted finds the ssh a background caller runs without anyone watching. It is the system's own (preferred, normally SystemExecutable) when that is a regular executable file. Otherwise it is what lookPath finds, held to Resolve's rule, followed through every symbolic link to the file itself, and held to two more rules: the file and its directory are owned by root or by this user and are not writable by their group or by everyone, and the file is not under home (the user's home directory; empty means unknown and is not checked). So a program that a less trusted process could have put on the PATH is never run in the user's name. Windows has no such owner or mode bits and no system path; there the result is held to Resolve's rule and the home rule.

func SanitizeDiagnostic

func SanitizeDiagnostic(raw []byte, truncated bool) string

SanitizeDiagnostic renders remote stderr as one bounded line safe to include in a local error message or log: every character that is not printable (a control, a format character such as a bidirectional override or a zero-width space, a line or paragraph separator, an invalid byte) becomes a space.

Types

type ExecRunner

type ExecRunner struct{}

ExecRunner is the production runner.

func (ExecRunner) Run

func (ExecRunner) Run(ctx context.Context, executable string, args []string, stdin []byte, stdout, stderr io.Writer) error

Run executes the command with the caller's context, so a caller-supplied deadline reaches the SSH process itself and not just its output readers.

type GroupRunner added in v0.175.0

type GroupRunner struct{}

GroupRunner is the runner for a background caller, such as a daemon. It runs the command in a process group of its own and, when ctx ends, kills the whole group (ssh and any helper it started, a ProxyCommand say), not ssh alone. Run returns only after the process has been waited for, so no call leaves a zombie, and a helper that survives with the output pipes open cannot hold Run for longer than groupWaitDelay. The command is given an allow-listed environment (allowedEnvironment), not the caller's, and a session of its own, so that neither ssh nor anything it starts has a terminal to prompt on. On Windows there is no process group to signal: only the process itself (ssh.exe) is killed, and a helper it started (a ProxyCommand, say) may outlive it.

func (GroupRunner) Run added in v0.175.0

func (GroupRunner) Run(ctx context.Context, executable string, args []string, stdin []byte, stdout, stderr io.Writer) error

Run executes the command as ExecRunner does, in its own session and group.

type LimitedBuffer

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

LimitedBuffer accumulates output up to a byte limit and records whether the limit was reached, so a remote response can never make WB hold unbounded memory and an over-limit response is reported rather than truncated silently.

func NewLimitedBuffer

func NewLimitedBuffer(limit int) *LimitedBuffer

NewLimitedBuffer returns a buffer that accepts up to limit bytes and reports every write as successful, so the writer is never blocked or failed by the bound itself.

func (*LimitedBuffer) Bytes

func (b *LimitedBuffer) Bytes() []byte

Bytes returns what was retained.

func (*LimitedBuffer) Exceeded

func (b *LimitedBuffer) Exceeded() bool

Exceeded reports whether output past the limit was discarded.

func (*LimitedBuffer) Write

func (b *LimitedBuffer) Write(value []byte) (int, error)

type Options added in v0.175.0

type Options struct {
	// ConnectTimeoutSeconds bounds connection establishment; zero or less means
	// ConnectTimeoutSeconds, the package's default.
	ConnectTimeoutSeconds int
	// NoForwarding refuses agent and X11 forwarding and every port forward the
	// user's ssh configuration names for the host, whatever that configuration
	// says: a background call carries no credential to the remote and opens no
	// listener.
	NoForwarding bool
	// Unattended is for a call no person watches, such as a daemon's. It
	// neutralises the directives of the user's ssh configuration that would
	// change what such a call does: the call never becomes a connection-sharing
	// master (ControlMaster=no; a master that already exists is still used
	// through the configured ControlPath), so killing it at its timeout cannot
	// drop a session of the user's that shares it; a RemoteCommand configured for
	// the host does not replace the remote words (RemoteCommand=none); a
	// LocalCommand is not run on this machine (PermitLocalCommand=no); and ssh
	// writes only errors to stderr, not banners (LogLevel=ERROR).
	Unattended bool
}

Options are the fixed OpenSSH options of one call. None of them is caller data: they are constants of the calling package.

type Runner

type Runner interface {
	Run(ctx context.Context, executable string, args []string, stdin []byte, stdout, stderr io.Writer) error
}

Runner runs one local command with exact stdin bytes and captured output. It is an interface so the SSH boundary can be exercised without a real host.

type TailBuffer added in v0.175.0

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

TailBuffer keeps the last limit bytes written to it and records whether anything before them was discarded. It is for output whose end matters: a long banner cannot push the line that says why a call failed out of it. Like LimitedBuffer it reports every write as successful.

func NewTailBuffer added in v0.175.0

func NewTailBuffer(limit int) *TailBuffer

NewTailBuffer returns a buffer that keeps the last limit bytes.

func (*TailBuffer) Bytes added in v0.175.0

func (b *TailBuffer) Bytes() []byte

Bytes returns the bytes that were kept.

func (*TailBuffer) Discarded added in v0.175.0

func (b *TailBuffer) Discarded() bool

Discarded reports whether earlier output was dropped.

func (*TailBuffer) Write added in v0.175.0

func (b *TailBuffer) Write(value []byte) (int, error)

Jump to

Keyboard shortcuts

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