Documentation
¶
Overview ¶
Package sessionkit implements the capkit Session contract (docs §5.1) and the openers for it. A new transport only implements Session's three methods plus SessionManager plumbing; every downstream kit (privesc, lat, persist, cleanup, internalnet, container) then works against it unchanged.
SessionManager is a port owned by the host. This package supplies a default implementation plus an SSH adapter (real connections, host-injected key material) and a CLI adapter (local command execution) so the contract is exercised end to end without a host-side implementation.
Index ¶
- type CLIOpener
- type CLISession
- type Manager
- func (m *Manager) Close(id string) error
- func (m *Manager) CloseAll() error
- func (m *Manager) Get(id string) (core.Session, bool)
- func (m *Manager) List() []core.SessionInfo
- func (m *Manager) Open(ctx context.Context, spec core.SessionSpec) (core.SessionInfo, error)
- func (m *Manager) RegisterOpener(kind string, opener core.SessionOpener)
- type SMBOpener
- type SMBSession
- func (s *SMBSession) CanUpload() bool
- func (s *SMBSession) Close() error
- func (s *SMBSession) Download(ctx context.Context, remote string) (io.ReadCloser, error)
- func (s *SMBSession) Exec(ctx context.Context, cmd string, opts core.ExecOpts) (core.Output, error)
- func (s *SMBSession) Info() core.SessionInfo
- func (s *SMBSession) Upload(ctx context.Context, src io.Reader, remote string) error
- type SSHOwner
- type SSHSession
- func (s *SSHSession) Close() error
- func (s *SSHSession) Download(ctx context.Context, remote string) (io.ReadCloser, error)
- func (s *SSHSession) Exec(ctx context.Context, cmd string, opts core.ExecOpts) (core.Output, error)
- func (s *SSHSession) Info() core.SessionInfo
- func (s *SSHSession) Tunnel(ctx context.Context, spec core.TunnelSpec) (core.Tunnel, error)
- func (s *SSHSession) Upload(ctx context.Context, src io.Reader, remote string) error
- type WinRMOpener
- type WinRMSession
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type CLIOpener ¶
type CLIOpener struct {
// Runner is required: CLIOpener holds no execution path of its own.
Runner core.ProcessRunner
// AllowedCommands, when non-empty, restricts the first token of every
// command. Empty means unrestricted (host's responsibility).
AllowedCommands []string
// DefaultShell overrides the detected shell interpreter.
DefaultShell string
}
CLIOpener runs commands as a local process through the host's ProcessRunner port. It is the reference adapter: it needs no credentials and no network, so it makes the Session contract testable end to end and is useful for local agent-side tasks.
Routing through ProcessRunner (never os/exec) keeps the "kits never spawn a subprocess themselves" boundary intact (docs §6.4): the host decides whether local execution is gated, audited and sandboxed. A host that wants a fully gated local transport passes adapters/exec.New(scope, limiter, audit); one that only needs host-side local commands passes adapters/exec.NewLocal().
type CLISession ¶
type CLISession struct {
// contains filtered or unexported fields
}
CLISession is a local-process Session.
func (*CLISession) Close ¶
func (s *CLISession) Close() error
func (*CLISession) Info ¶
func (s *CLISession) Info() core.SessionInfo
type Manager ¶
type Manager struct {
// contains filtered or unexported fields
}
Manager is the default SessionManager. Openers are registered per kind ("ssh", "winrm", "smb", "cli", "webshell", ...) by the host; the manager tracks live sessions by ID and hands out Sessions to callers.
func NewManager ¶
NewManager builds a Manager. idFn/nowFn are optional (defaults: random-ish counter id, time.Now).
func (*Manager) Close ¶
Close closes and untracks one session. Closing an unknown ID is not an error (idempotent: agents retry after timeouts).
func (*Manager) List ¶
func (m *Manager) List() []core.SessionInfo
List returns metadata for all live sessions, ordered by ID.
func (*Manager) Open ¶
func (m *Manager) Open(ctx context.Context, spec core.SessionSpec) (core.SessionInfo, error)
Open creates and tracks a session.
func (*Manager) RegisterOpener ¶
func (m *Manager) RegisterOpener(kind string, opener core.SessionOpener)
RegisterOpener installs an opener for a session kind.
type SMBOpener ¶
type SMBOpener struct {
// Runner is required.
Runner core.ProcessRunner
// Binary overrides the smbclient path; default "smbclient".
Binary string
// Options["share"].
Share string
// Artifacts stages uploads locally (smbclient needs a real file path).
// Upload stays unavailable when it is nil.
Artifacts core.ArtifactStore
// Timeout bounds one smbclient invocation; default 60s.
Timeout time.Duration
}
SMBOpener opens an SMB share session. SMB is not an HTTP protocol and capkit has no raw-TCP port, so the transport is the sanctioned ProcessRunner route (docs §6.4: every external tool is a subprocess): commands are driven through smbclient, its password carried in the environment rather than the command line so it never lands in the process list or the audit trail.
The session is stateless per command — SMB has no remote shell here, so Exec runs smbclient subcommands (ls/get/put/del/mkdir …). An authentication failure surfaces on the first Exec, not at Open, because Open issues no traffic.
type SMBSession ¶
type SMBSession struct {
// contains filtered or unexported fields
}
SMBSession is an SMB share foothold driven through smbclient.
func (*SMBSession) CanUpload ¶
func (s *SMBSession) CanUpload() bool
CanUpload reports whether uploads are possible (an ArtifactStore is wired).
func (*SMBSession) Close ¶
func (s *SMBSession) Close() error
Close is a no-op: smbclient connections live for one invocation.
func (*SMBSession) Download ¶
func (s *SMBSession) Download(ctx context.Context, remote string) (io.ReadCloser, error)
Download reads a remote file with smbclient's cat command, so no local staging is needed.
func (*SMBSession) Info ¶
func (s *SMBSession) Info() core.SessionInfo
type SSHOwner ¶
type SSHOwner struct {
// HostKeyCallback defaults to ssh.InsecureIgnoreHostKey when nil. Hosts
// should inject a pinned callback.
HostKeyCallback ssh.HostKeyCallback
// Dialer overrides the TCP dialer (hosts route through proxies here).
Dialer func(ctx context.Context, network, addr string) (net.Conn, error)
}
SSHOwner opens a real SSH foothold. It implements Session (Exec/Info/Close) plus the optional Uploader/Downloader/Tunneler capabilities from §5.1, so downstream kits get file transfer and port forwarding for free.
The opener authenticates with a password or a PEM private key supplied in SessionSpec.Secret; the host is responsible for resolving that secret from the Sealer at the edge and for scope approval before calling Open.
type SSHSession ¶
type SSHSession struct {
// contains filtered or unexported fields
}
SSHSession is a live SSH foothold.
func (*SSHSession) Close ¶
func (s *SSHSession) Close() error
func (*SSHSession) Download ¶
func (s *SSHSession) Download(ctx context.Context, remote string) (io.ReadCloser, error)
Download reads remote via cat (stdout streamed back).
func (*SSHSession) Info ¶
func (s *SSHSession) Info() core.SessionInfo
func (*SSHSession) Tunnel ¶
func (s *SSHSession) Tunnel(ctx context.Context, spec core.TunnelSpec) (core.Tunnel, error)
Tunnel opens a remote dial through the SSH connection.
type WinRMOpener ¶
type WinRMOpener struct {
// HTTP is required and must be the gate-aware client.
HTTP core.HTTPDoer
// TLS selects https (5986) over http (5985).
TLS bool
// Port overrides the default for the chosen scheme.
Port int
// OperationTimeoutMS bounds one WSMan call; default 60000.
OperationTimeoutMS int
}
WinRMOpener opens a Windows Remote Management foothold. WinRM is a SOAP protocol over HTTP(S), so it rides the host's core.HTTPDoer port: scope, rate limiting and audit apply to every WSMan call exactly as they do to any other HTTP request (docs §3.1: sessionkit owns SSH/WinRM/SMB/CLI transports).
Authentication is HTTP Basic over a TLS endpoint by default, which is the documented "unencrypted on 5986/TLS" setup. Hosts that need NTLM/Kerberos terminate the auth in their HTTPDoer (a proxying Doer) and pass the target URL through unchanged.
func (*WinRMOpener) Open ¶
func (o *WinRMOpener) Open(ctx context.Context, spec core.SessionSpec) (core.Session, error)
Open creates a remote shell on the target and returns a session bound to it.
type WinRMSession ¶
type WinRMSession struct {
// contains filtered or unexported fields
}
WinRMSession is a live WinRM foothold. Each Exec runs cmd.exe /c through the remote shell.
func (*WinRMSession) Close ¶
func (s *WinRMSession) Close() error
Close deletes the remote shell; the WinRM protocol has no connection to drop.
func (*WinRMSession) Exec ¶
func (s *WinRMSession) Exec(ctx context.Context, cmd string, opts core.ExecOpts) (core.Output, error)
Exec runs a command line through cmd.exe /c and returns its output.
func (*WinRMSession) Info ¶
func (s *WinRMSession) Info() core.SessionInfo