migrationmode

package
v0.8.3 Latest Latest
Warning

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

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

Documentation

Overview

Package migrationmode is the read-only agent that runs on a source host being migrated away from. It may only read Docker state and count files; there is no code path in it that creates, changes, execs into or deletes anything.

Index

Constants

This section is empty.

Variables

View Source
var ErrDenied = errors.New("migrationmode: docker call is not on the allowlist")

ErrDenied wraps every refusal of the Docker allowlist.

View Source
var ErrGoAway = errors.New("migrationmode: control plane closed the session")

ErrGoAway ends a session the control plane closed on purpose.

View Source
var ErrNoPin = errors.New("migrationmode: a CA fingerprint is required")

ErrNoPin means the install command carried no CA fingerprint. Migration enrollment never falls back to trust on first use.

View Source
var ErrUnknownControl = errors.New("migrationmode: control message outside the migration set")

ErrUnknownControl ends a session that received a message outside the migration set.

View Source
var ErrUnknownTarget = errors.New("migrationmode: scan target was not in the last inventory")

ErrUnknownTarget means a scan named something the last inventory did not list.

Functions

func Allowed

func Allowed(method string, u *url.URL) error

Allowed reports whether method and u may be sent to the Docker socket.

func Connect

func Connect(ctx context.Context, addr string, id *Identity, h *Handler, version string, heartbeat time.Duration) error

Connect opens the mTLS Session stream and serves it until it ends.

func Discover

func Discover(ctx context.Context, d *Docker, requestID string, now time.Time) (*migrationpb.Inventory, error)

Discover reads the host's containers, volumes and networks. It never reads environment values, only their names.

func EngineOf

func EngineOf(image string) (engine, version string)

EngineOf returns the database engine and tag for an image reference, or "" when it is not a known database image.

func NewGuard

func NewGuard(next http.RoundTripper, onDeny DenyFunc) http.RoundTripper

NewGuard wraps next so only allowlisted calls leave the process. A request carrying a body is refused as well: every allowed call is a bodiless GET.

func SaveIdentity

func SaveIdentity(path string, id *Identity) error

SaveIdentity writes id to path with owner-only permissions, atomically.

func Serve

func Serve(ctx context.Context, st Stream, h *Handler, version, goos, arch string, heartbeat time.Duration) error

Serve runs the session loop until the stream ends, the context is canceled or the control plane sends something outside the migration set.

Types

type DenyFunc

type DenyFunc func(method, path, reason string)

DenyFunc is told about every refused call so it can be audited.

type Docker

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

Docker is a read-only Engine API client. Every request goes through the allowlist guard, so even a bug in this file cannot reach a write endpoint.

func NewDocker

func NewDocker(socket string, maxResponse int64, onDeny DenyFunc) *Docker

NewDocker connects to the Docker unix socket at socket. maxResponse caps the bytes read from any single response.

func NewDockerWithTransport

func NewDockerWithTransport(next http.RoundTripper, maxResponse int64, onDeny DenyFunc) *Docker

NewDockerWithTransport is NewDocker over an arbitrary transport, for tests.

type Handler

type Handler struct {
	Docker      *Docker
	Scanner     *Scanner
	ScanTimeout time.Duration
	Now         func() time.Time
	Log         *slog.Logger
}

Handler answers the three control messages a migration source understands.

func (*Handler) Handle

Handle answers one control message. Any payload other than discover, scan or go_away, including one added to the proto later, is a protocol violation.

type Identity

type Identity struct {
	SessionID     string    `json:"session_id"`
	ClientCertPEM []byte    `json:"client_cert_pem"`
	ClientKeyPEM  []byte    `json:"client_key_pem"`
	CACertPEM     []byte    `json:"ca_cert_pem"`
	NotAfter      time.Time `json:"not_after"`
	ExpiresAt     time.Time `json:"session_expires_at"`
}

Identity is the short-lived credential persisted between restarts.

func Enroll

func Enroll(ctx context.Context, addr, token, caFingerprint, version string) (*Identity, error)

Enroll exchanges a single-use token for an Identity. The control plane CA must match caFingerprint before the token is sent.

func LoadIdentity

func LoadIdentity(path string) (*Identity, error)

LoadIdentity reads an identity file, or returns os.ErrNotExist.

type ScanLimits

type ScanLimits struct {
	MaxTargets int
	MaxEntries int64
	MaxDepth   int
}

ScanLimits bound one scan request; a zero field means unlimited.

type Scanner

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

Scanner counts files under volumes and bind mounts, but only those the agent itself reported in its last inventory.

func NewScanner

func NewScanner() *Scanner

NewScanner returns an unlimited scanner with no known targets.

func NewScannerWithLimits

func NewScannerWithLimits(lim ScanLimits) *Scanner

NewScannerWithLimits returns a scanner that refuses requests beyond lim.

func (*Scanner) Learn

func (s *Scanner) Learn(inv *migrationpb.Inventory)

Learn records the scannable targets of inv, replacing earlier ones.

func (*Scanner) Scan

func (s *Scanner) Scan(ctx context.Context, requestID string, targets []string) *migrationpb.ScanResult

Scan measures each target twice. A second pass with different totals marks the target changed_during_scan so live writes are never reported as a match.

type Stream

type Stream interface {
	Send(*migrationpb.AgentMessage) error
	Recv() (*migrationpb.ControlMessage, error)
}

Stream is the Session RPC surface the loop needs.

Jump to

Keyboard shortcuts

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