Documentation
¶
Overview ¶
Package dockerssh reads a remote Docker host over an SSH login without running anything on it: SSH is only a transport to the Docker socket, and a client-side allowlist lets nothing but read-only Engine API GETs out.
Index ¶
- Constants
- Variables
- func KindOf(err error) string
- type Config
- type Error
- type ExtractStats
- type ForbiddenRequestError
- type HostKey
- type Limits
- type Overview
- type ReadOnlyTransport
- type Saver
- type Session
- func (s *Session) Close()
- func (s *Session) ContainerArchive(ctx context.Context, containerID, mountPath string) (io.ReadCloser, error)
- func (s *Session) CopyMount(ctx context.Context, containerID, mountPath, dstDir string, lim Limits) (ExtractStats, error)
- func (s *Session) ImageSave(ctx context.Context, ref string) (io.ReadCloser, error)
- func (s *Session) InspectAll(ctx context.Context) ([]byte, error)
- func (s *Session) Ping(ctx context.Context) error
- func (s *Session) Probe(ctx context.Context) (Overview, error)
- func (s *Session) SwarmServices(ctx context.Context) ([]byte, error)
- func (s *Session) Warnings() []string
Constants ¶
const ( KindAuth = "auth_failed" KindHostKey = "host_key_mismatch" KindHostKeyRequired = "host_key_required" KindSocketPermission = "socket_permission" KindSocketPath = "socket_path" KindSocketForbidden = "socket_forbidden" KindUnreachable = "unreachable" KindBlockedAddress = "blocked_address" KindOther = "other" )
Failure kinds the API turns into a typed fix.
const DefaultSocketPath = "/var/run/docker.sock"
DefaultSocketPath is the Docker socket opened when none is given.
Variables ¶
var ErrBlockedAddress = errors.New("dockerssh: ssh address is not allowed")
ErrBlockedAddress means the SSH target resolved to an address the network policy forbids.
var ErrLimit = errors.New("dockerssh: archive passes the configured limit")
ErrLimit is returned when an archive passes a size or file count cap.
var ErrRequestForbidden = errors.New("dockerssh: request is not on the read-only allowlist")
ErrRequestForbidden is wrapped by every refusal of the read-only transport.
Functions ¶
Types ¶
type Config ¶
type Config struct {
Host string
Port int
User string
// PrivateKey is a PEM private key, Passphrase unlocks it, Password is an
// alternative or additional login. Wipe zeroes all three.
PrivateKey []byte
Passphrase []byte
Password []byte
// Fingerprint is the pinned host key, SHA256:... as ssh-keygen -l prints it.
Fingerprint string
// InsecureHostKey skips host key verification, an explicit opt in.
InsecureHostKey bool
SocketPath string
DialTimeout time.Duration
// CheckAddr vets every dialed IP, including after DNS resolution.
CheckAddr func(netip.Addr) error
}
Config is one SSH login to a Docker host. The secrets are held in memory for the life of the session and are never written anywhere.
type ExtractStats ¶
type ExtractStats struct {
Files int `json:"files"`
Dirs int `json:"dirs"`
Bytes int64 `json:"bytes"`
Skipped int `json:"skipped"`
// Warnings names entries that were left out and why, capped.
Warnings []string `json:"warnings,omitempty"`
}
ExtractStats reports what an extraction wrote.
func ExtractArchive ¶
ExtractArchive unpacks a container archive of one directory into dst. The archive's first path component (the directory's own name) is stripped. Names that leave dst, symlinks that could leave it, hard links and device nodes are never created, and no entry is written through a symlink.
type ForbiddenRequestError ¶
ForbiddenRequestError says which request the allowlist refused and why.
func (*ForbiddenRequestError) Error ¶
func (e *ForbiddenRequestError) Error() string
func (*ForbiddenRequestError) Unwrap ¶
func (e *ForbiddenRequestError) Unwrap() error
type Overview ¶
type Overview struct {
DockerVersion string `json:"docker_version"`
OS string `json:"os,omitempty"`
Swarm bool `json:"swarm"`
Containers int `json:"containers"`
Running int `json:"running"`
Volumes int `json:"volumes"`
Images int `json:"images"`
}
Overview is what a connection test reports it can read.
type ReadOnlyTransport ¶
type ReadOnlyTransport struct {
// contains filtered or unexported fields
}
ReadOnlyTransport is an http.RoundTripper that refuses every request that is not an allowlisted read-only Docker Engine API GET, before it is sent.
func NewReadOnlyTransport ¶
func NewReadOnlyTransport(inner http.RoundTripper) *ReadOnlyTransport
NewReadOnlyTransport wraps inner with the read-only allowlist.
type Saver ¶
type Saver struct {
Cfg Config
}
Saver streams an image from the source host through the socket tunnel, the read-only replacement for running a save command there.
type Session ¶
type Session struct {
// contains filtered or unexported fields
}
Session is one open SSH connection used only as a transport to the Docker socket. It has no shell, no command execution and no other forwarding.
func (*Session) ContainerArchive ¶
func (s *Session) ContainerArchive(ctx context.Context, containerID, mountPath string) (io.ReadCloser, error)
ContainerArchive streams a tar of one of the container's own mount destinations. The container is inspected first so the allowlist learns which destinations it may ask for.
func (*Session) CopyMount ¶
func (s *Session) CopyMount(ctx context.Context, containerID, mountPath, dstDir string, lim Limits) (ExtractStats, error)
CopyMount streams one of a container's own mount destinations through the tunnel and unpacks it into dstDir with the extraction safeguards applied.
func (*Session) InspectAll ¶
InspectAll returns the inspect JSON of every container as one array, the same shape `docker inspect` prints.
func (*Session) SwarmServices ¶
SwarmServices lists swarm services on a manager node, for Swarm sources.