backup

package
v0.4.5 Latest Latest
Warning

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

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

Documentation

Overview

Package backup is the app data backup/restore core (plan §7.10, §16). The docker orchestration (throwaway RO backup containers, DB-dump sidecars) is write-plane; THIS file is the security-critical, I/O-streaming crypto + the hostile-input hardening (restore.go) + the prune denylist (denylist.go), all pure/streaming and exhaustively testable.

stream.go is the chunked AES-256-GCM pipeline: tar → gzip → THIS → sink. It never buffers the whole stream in RSS (works on a tiny box), and the chunk chaining makes tampering, REORDERING, and TRUNCATION all detectable — a silently-truncated or shuffled backup must never restore as "success".

Index

Constants

This section is empty.

Variables

View Source
var ErrCorrupt = errors.New("backup: stream is corrupt or tampered")

ErrCorrupt means the stream failed authentication (tamper / wrong key / reorder / truncation) — fail-closed, never a partial restore.

Functions

func Decrypt

func Decrypt(dst io.Writer, src io.Reader, key []byte) error

Decrypt reads the chunked stream from src, authenticates every chunk IN ORDER, and writes the plaintext to dst. It returns ErrCorrupt on any auth failure, a missing/early final chunk (truncation), or extra data after the final chunk.

func Encrypt

func Encrypt(dst io.Writer, src io.Reader, key []byte, maxBytes int64) error

Encrypt reads plaintext from src and writes the chunked, authenticated stream to dst. maxBytes caps the plaintext (0 = no cap); exceeding it errors rather than writing an unbounded archive. The AAD of each chunk binds its INDEX and a final flag, so a decryptor detects a dropped, duplicated, or reordered chunk.

func PruneImageSafe

func PruneImageSafe(digest string, s LiveState) (bool, string)

PruneImageSafe reports whether an image (by resolved digest) may be pruned. It denies anything provably unsafe; everything else is the safe complement.

func PruneVolumeSafe

func PruneVolumeSafe(name string, s LiveState) (bool, string)

PruneVolumeSafe reports whether a volume may be removed. A sole-data volume may be removed ONLY if it is verified present in backup_inventory ("back it up first").

func RestoreTuple

func RestoreTuple(plaintextSHA, ciphertextSHA string, targetVolumes, bindings []string, sizes []int64) string

RestoreTuple binds the FULL restore operation (plan §7.10): plaintext + ciphertext digests, the resolved target volumes, the service-binding set, and the member sizes. The confirm token is hash(tuple); it is re-derived under the held write-plane lock at execute and VOIDED on any drift (not just archive bytes), so a swapped archive / re-pointed target / changed size invalidates the confirmation.

func SafeExtract

func SafeExtract(tr *tar.Reader, w FileWriter, lim ExtractLimits) error

SafeExtract walks a tar stream, enforcing confinement + special-file rejection + the zip-bomb caps, and emits each confined member through w. It returns the first violation (fail-closed: a single bad member aborts the whole restore).

Types

type ExtractLimits

type ExtractLimits struct {
	MaxTotalBytes  int64 // total decompressed bytes across all members
	MaxMemberBytes int64 // a single member's size
	MaxMembers     int   // number of members
}

ExtractLimits bounds a restore extraction (fail-closed defaults via Sane()).

func SaneLimits

func SaneLimits() ExtractLimits

SaneLimits returns conservative defaults for an app-volume restore.

type FileWriter

type FileWriter interface {
	WriteFile(relPath string, mode int64, r io.Reader) error
	Mkdir(relPath string) error
}

FileWriter is how SafeExtract emits a confined file (injected so the caller owns the actual filesystem write / staging dir; tests use an in-memory sink).

type LiveState

type LiveState struct {
	ProtectedImages  map[string]bool // child-proxy / edge / socket-proxy images
	ReferencedImages map[string]bool // referenced by any app's DEPLOYED or ROLLBACK compose
	InUseImages      map[string]bool // images of running containers
	ProtectedVolumes map[string]bool // edge/ACME/control-plane volumes
	SoleDataVolumes  map[string]bool // a volume that is an app's ONLY data store
	BackedUpVolumes  map[string]bool // verified present in backup_inventory
}

LiveState is the fresh-from-live view the prune denylist resolves against. All image identities are RESOLVED DIGESTS (never tags), so a rollback image can't be pruned just because it's currently dangling/untagged.

Jump to

Keyboard shortcuts

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