Help us shape the future of Go! Take the 2026 Go Developer Survey

remotesync

package
v0.3.0 Latest Latest
Warning

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

Go to latest
Published: Oct 4, 2026 License: MIT Imports: 21 Imported by: 0

Documentation

Overview

Package remotesync keeps the local encrypted inventory in step with a shared remote store (HashiCorp Vault KV v2), so several devices running SSLKnife see the same certificates, keys and SSH keys.

The local database stays the working copy: search, TLS history and CT monitoring keep running on SQLite. A sync is a three-way merge between the local inventory, the remote manifest and the state both sides last agreed on (database table remote_sync). See docs/DESIGN.md §13.

Index

Constants

View Source
const (
	KindKey  = "key"
	KindCert = "cert"
	KindSSH  = "ssh"
)

Object kinds. They double as the tags/notes object type in the database.

Variables

View Source
var ErrConflict = errors.New("remote changed during sync")

ErrConflict means another device changed the remote during this sync; the sync is retried from a fresh manifest.

Functions

func Fatal

func Fatal(err error) error

Fatal wraps err so Sync aborts on it. Stores use it for authentication and transport failures.

func SSHIdent

func SSHIdent(fp string) (string, error)

SSHIdent converts an OpenSSH "SHA256:<base64>" fingerprint into the hex form used in remote paths (base64 may contain "/").

Types

type Action

type Action string

Action is what a sync does with one object.

const (
	ActPush         Action = "push"          // new or changed here
	ActPull         Action = "pull"          // new or changed on the remote
	ActMerge        Action = "merge"         // changed on both sides
	ActDeleteLocal  Action = "delete-local"  // deleted on another device
	ActDeleteRemote Action = "delete-remote" // deleted here
)

type Change

type Change struct {
	Action Action `json:"action"`
	Kind   string `json:"kind"`
	Ident  string `json:"ident"`
	Label  string `json:"label"`
	Error  string `json:"error,omitempty"`
}

Change is one planned or applied change.

type Entry

type Entry struct {
	Digest  string `json:"digest"`
	Version int    `json:"version"`
}

Entry is one manifest line: the digest and KV version of an object.

type Key

type Key = database.SyncKey

Key identifies an object across devices by content, never by local ID.

type Manifest

type Manifest map[Key]Entry

Manifest lists every object in the remote store. Devices read it once per sync instead of fetching every object.

type Meta

type Meta struct {
	Name       string   `json:"name"`
	Comment    string   `json:"comment"`
	Tags       []string `json:"tags"`
	Notes      []Note   `json:"notes"`
	HasPrivate bool     `json:"has_private"`
}

Meta is the part of an object that can change after import. Its digest decides whether a side changed since the last sync.

type Note

type Note struct {
	ID        string    `json:"id"`
	Body      string    `json:"body"`
	CreatedAt time.Time `json:"created_at"`
}

Note is a synced note.

type Object

type Object struct {
	Kind  string
	Ident string
	// Public is the certificate DER, the key's SubjectPublicKeyInfo DER, or
	// the SSH authorized_keys line.
	Public []byte
	// Private is the PKCS#8 DER or the SSH private key file; nil when not
	// loaded or not present (see Meta.HasPrivate).
	Private             []byte
	PassphraseProtected bool
	Source              string
	ImportedAt          time.Time
	Meta
}

Object is one inventory object in its device-independent form.

func (*Object) Digest

func (o *Object) Digest() string

Digest is a stable hash of the identity and metadata. Private material is represented only by HasPrivate: the same public key always has the same private key, and Transit ciphertexts differ on every write.

func (*Object) Key

func (o *Object) Key() Key

Key returns the object's identity.

func (*Object) Label

func (o *Object) Label() string

Label is a short human description for reports.

type Options

type Options struct {
	DryRun bool
}

Options tune a sync.

type Report

type Report struct {
	Remote   string   `json:"remote"`
	DryRun   bool     `json:"dry_run,omitempty"`
	Objects  int      `json:"objects"` // objects on the remote afterwards
	Changes  []Change `json:"changes"`
	Failed   int      `json:"failed"`
	Attempts int      `json:"attempts"`
}

Report summarises a sync.

func Sync

func Sync(ctx context.Context, inv *inventory.Service, st Store, opts Options) (*Report, error)

Sync merges the local inventory with the remote store.

func (*Report) Count

func (r *Report) Count(a Action) int

Count returns how many changes had action a (and succeeded).

type Store

type Store interface {
	// Identity names the remote; sync state is kept per identity.
	Identity() string
	// Manifest returns the manifest and its version (0 when there is none).
	Manifest(ctx context.Context) (Manifest, int, error)
	// PutManifest replaces the manifest if its version is still cas, or
	// returns ErrConflict.
	PutManifest(ctx context.Context, m Manifest, cas int) error
	// Get fetches an object with its private material.
	Get(ctx context.Context, k Key) (*Object, int, error)
	// Put writes an object if its version is still cas (0: must not exist)
	// and returns the new version, or returns ErrConflict.
	Put(ctx context.Context, o *Object, cas int) (int, error)
	// Delete removes an object and its history.
	Delete(ctx context.Context, k Key) error
}

Store is a remote object store shared by several devices.

type VaultStore

type VaultStore struct {
	Client *vaultkv.Client
	Mount  string
	Path   string
	// Transit, when set, encrypts private keys with a Vault Transit key
	// before they are written, so KV readers without transit decrypt
	// permission only see ciphertext.
	Transit *vaultkv.Transit
	// Namespace is part of the identity only.
	Namespace string
}

VaultStore keeps the shared inventory in a HashiCorp Vault KV v2 mount.

func (*VaultStore) Delete

func (s *VaultStore) Delete(ctx context.Context, k Key) error

Delete implements Store.

func (*VaultStore) Get

func (s *VaultStore) Get(ctx context.Context, k Key) (*Object, int, error)

Get implements Store.

func (*VaultStore) Identity

func (s *VaultStore) Identity() string

Identity implements Store.

func (*VaultStore) Manifest

func (s *VaultStore) Manifest(ctx context.Context) (Manifest, int, error)

Manifest implements Store.

func (*VaultStore) Put

func (s *VaultStore) Put(ctx context.Context, o *Object, cas int) (int, error)

Put implements Store.

func (*VaultStore) PutManifest

func (s *VaultStore) PutManifest(ctx context.Context, m Manifest, cas int) error

PutManifest implements Store.

Jump to

Keyboard shortcuts

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