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 ¶
- Variables
- func Allowed(method string, u *url.URL) error
- func Connect(ctx context.Context, addr string, id *Identity, h *Handler, version string, ...) error
- func Discover(ctx context.Context, d *Docker, requestID string, now time.Time) (*migrationpb.Inventory, error)
- func EngineOf(image string) (engine, version string)
- func NewGuard(next http.RoundTripper, onDeny DenyFunc) http.RoundTripper
- func SaveIdentity(path string, id *Identity) error
- func Serve(ctx context.Context, st Stream, h *Handler, version, goos, arch string, ...) error
- type DenyFunc
- type Docker
- type Handler
- type Identity
- type ScanLimits
- type Scanner
- type Stream
Constants ¶
This section is empty.
Variables ¶
var ErrDenied = errors.New("migrationmode: docker call is not on the allowlist")
ErrDenied wraps every refusal of the Docker allowlist.
var ErrGoAway = errors.New("migrationmode: control plane closed the session")
ErrGoAway ends a session the control plane closed on purpose.
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.
var ErrUnknownControl = errors.New("migrationmode: control message outside the migration set")
ErrUnknownControl ends a session that received a message outside the migration set.
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 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 ¶
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 ¶
SaveIdentity writes id to path with owner-only permissions, atomically.
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 ¶
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 ¶
func (h *Handler) Handle(ctx context.Context, msg *migrationpb.ControlMessage) (*migrationpb.AgentMessage, error)
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 ¶
Enroll exchanges a single-use token for an Identity. The control plane CA must match caFingerprint before the token is sent.
func LoadIdentity ¶
LoadIdentity reads an identity file, or returns os.ErrNotExist.
type ScanLimits ¶
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.