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
- Variables
- func Fatal(err error) error
- func SSHIdent(fp string) (string, error)
- type Action
- type Change
- type Entry
- type Key
- type Manifest
- type Meta
- type Note
- type Object
- type Options
- type Report
- type Store
- type VaultStore
- func (s *VaultStore) Delete(ctx context.Context, k Key) error
- func (s *VaultStore) Get(ctx context.Context, k Key) (*Object, int, error)
- func (s *VaultStore) Identity() string
- func (s *VaultStore) Manifest(ctx context.Context) (Manifest, int, error)
- func (s *VaultStore) Put(ctx context.Context, o *Object, cas int) (int, error)
- func (s *VaultStore) PutManifest(ctx context.Context, m Manifest, cas int) error
Constants ¶
const ( KindKey = "key" KindCert = "cert" KindSSH = "ssh" )
Object kinds. They double as the tags/notes object type in the database.
Variables ¶
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 ¶
Types ¶
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 Manifest ¶
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.
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.
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) PutManifest ¶
PutManifest implements Store.