README

Vault

A vault is an encrypted database used to securely store secrets. The format for the vault is designed to preserve history and allow for backup and syncing.

For details see, keys.pub/docs/specs/vault.

Examples.

Documentation

Index

Examples

Constants

This section is empty.

Variables

View Source
var ErrAlreadyOpen = errors.Errorf("vault already open")

ErrAlreadyOpen if you try to open when it is already open.

View Source
var ErrAlreadySetup = errors.New("vault is already setup")

ErrAlreadySetup if already setup.

View Source
var ErrInvalidAuth = errors.New("invalid auth")

ErrInvalidAuth if auth is invalid.

View Source
var ErrItemValueTooLarge = errors.New("item value is too large")

ErrItemValueTooLarge is item value is too large.

View Source
var ErrLocked = errors.New("vault is locked")

ErrLocked if you try to access vault while it is locked.

View Source
var ErrNotOpen = errors.Errorf("vault not open")

ErrNotOpen if you try to use the vault when it isn't open.

Functions

func Collections

func Collections(st Store, parent string) ([]string, error)

Collections lists collection paths from parent.

func ConvertKeyring

func ConvertKeyring(kr keyring.Keyring, to *Vault) (bool, error)

ConvertKeyring converts keyring store.

func Copy

func Copy(from Store, to Store, opt ...CopyOption) ([]string, error)

Copy data from a vault.Store to another vault.Store. It copies raw data, it doesn't need to be unlocked.

func SetLogger

func SetLogger(l Logger)

SetLogger sets logger for the package.

Types

type AuthType

type AuthType string

AuthType describes an auth method.

const (
	// UnknownAuth ...
	UnknownAuth AuthType = ""
	// PaperKeyAuth ...
	PaperKeyAuth AuthType = "paper-key"
	// PasswordAuth ...
	PasswordAuth AuthType = "password"
	// FIDO2HMACSecretAuth ...
	FIDO2HMACSecretAuth AuthType = "fido2-hmac-secret" // #nosec
)

type Client

type Client struct {
	*client.Client
}

Client for API.

func NewClient

func NewClient(client *client.Client) *Client

NewClient creates a client.

func (*Client) Vault

func (c *Client) Vault(ctx context.Context, key *keys.EdX25519Key, index int64) (*Events, error)

Vault events. Vault data is decrypted using the vault key before being returned. If truncated, there are more results if you call again with the new index.

func (*Client) VaultDelete

func (c *Client) VaultDelete(ctx context.Context, key *keys.EdX25519Key) error

VaultDelete removes a vault.

func (*Client) VaultExists

func (c *Client) VaultExists(ctx context.Context, key *keys.EdX25519Key) (bool, error)

VaultExists checks if vault exists.

func (*Client) VaultSend

func (c *Client) VaultSend(ctx context.Context, key *keys.EdX25519Key, events []*Event) error

VaultSend saves events to the vault API with a key. Events are encrypted with the key before saving.

type CopyOption

type CopyOption func(*CopyOptions)

CopyOption ...

func DryRun

func DryRun() CopyOption

DryRun to pretend to copy.

func SkipExisting

func SkipExisting() CopyOption

SkipExisting to skip existing entries, otherwise error.

type CopyOptions

type CopyOptions struct {
	SkipExisting bool
	DryRun       bool
}

CopyOptions ...

type DB

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

DB Store.

func NewDB

func NewDB(path string) *DB

NewDB creates DB Store.

func (*DB) Close

func (d *DB) Close() error

Close db.

func (*DB) Delete

func (d *DB) Delete(path string) (bool, error)

Delete from DB.

func (*DB) Exists

func (d *DB) Exists(path string) (bool, error)

Exists if path exists.

func (*DB) Get

func (d *DB) Get(path string) ([]byte, error)

Get from DB.

func (*DB) List

func (d *DB) List(opts *ListOptions) ([]*Entry, error)

List ...

func (*DB) Name

func (d *DB) Name() string

Name for Store.

func (*DB) Open

func (d *DB) Open() error

Open db.

func (*DB) Reset

func (d *DB) Reset() error

Reset db.

func (*DB) Set

func (d *DB) Set(path string, b []byte) error

Set in DB.

type Entry

type Entry struct {
	Path string
	Data []byte
}

Entry in Store.

type Event

type Event struct {
	// Path for event.
	Path string `json:"path" msgpack:"p"`
	// Data ...
	Data []byte `json:"data" msgpack:"dat"`

	// RemoteIndex is set from the remote events API (untrusted).
	RemoteIndex int64 `json:"-" msgpack:"-"`
	// RemoteTimestamp is set from the remote events API (untrusted).
	RemoteTimestamp time.Time `json:"-" msgpack:"-"`
}

Event describes a vault event.

func NewEvent

func NewEvent(path string, b []byte) *Event

NewEvent creates a new event.

type Events

type Events struct {
	Events    []*Event
	Index     int64
	Truncated bool
}

Events events from the API, decrypted with vault API key.

type Item

type Item struct {
	ID   string `msgpack:"id"`
	Data []byte `msgpack:"dat"`

	// Type for item data.
	Type string `msgpack:"typ,omitempty"`

	// Timestamp for item.
	Timestamp time.Time `msgpack:"cts,omitempty"`
}

Item in the vault, uses msgpack.

func NewItem

func NewItem(id string, b []byte, typ string, ts time.Time) *Item

NewItem creates an item. Item IDs are NOT encrypted locally and are provided for fast lookups.

func (*Item) Encrypt

func (i *Item) Encrypt(mk *[32]byte) ([]byte, error)

Encrypt item.

type ListOptions

type ListOptions struct {
	Prefix string
	NoData bool
	Limit  int
}

ListOptions for listing Store.

type LogLevel

type LogLevel int

LogLevel ...

const (
	// DebugLevel ...
	DebugLevel LogLevel = 3
	// InfoLevel ...
	InfoLevel LogLevel = 2
	// WarnLevel ...
	WarnLevel LogLevel = 1
	// ErrLevel ...
	ErrLevel LogLevel = 0
)

func (LogLevel) String

func (l LogLevel) String() string

type Logger

type Logger interface {
	Debugf(format string, args ...interface{})
	Infof(format string, args ...interface{})
	Warningf(format string, args ...interface{})
	Errorf(format string, args ...interface{})
	Fatalf(format string, args ...interface{})
}

Logger interface used in this package.

func NewLogger

func NewLogger(lev LogLevel) Logger

NewLogger ...

type Option

type Option func(*Options)

Option for Vault.

func WithClock

func WithClock(clock tsutil.Clock) Option

WithClock ...

type Options

type Options struct {
	Clock tsutil.Clock
}

Options for Vault.

type Provision

type Provision struct {
	ID        string    `msgpack:"id" json:"id"`
	Type      AuthType  `msgpack:"type" json:"type"`
	CreatedAt time.Time `msgpack:"cts" json:"cts"`

	// AAGUID (for FIDO2HMACSecret)
	AAGUID string `msgpack:"aaguid,omitempty" json:"aaguid"`
	// Salt (for FIDO2HMACSecret)
	Salt []byte `msgpack:"salt,omitempty" json:"salt"`
	// NoPin (for FIDO2HMACSecret)
	NoPin bool `msgpack:"nopin,omitempty" json:"nopin"`
}

Provision is unencrypted provision and parameters used by client auth.

func NewProvision

func NewProvision(typ AuthType) *Provision

NewProvision creates a new provision.

type Remote

type Remote struct {
	URL  *url.URL          `json:"url,omitempty"`
	Key  *keys.EdX25519Key `json:"key"`
	Salt []byte            `json:"salt"`
}

Remote for vault.

func NewRemote

func NewRemote(url *url.URL, key *keys.EdX25519Key, salt []byte) *Remote

NewRemote creates a Remote.

type Status

type Status string

Status for vault.

const (
	// Unknown status.
	Unknown Status = ""
	// SetupNeeded if setup needed.
	SetupNeeded Status = "setup-needed"
	// Unlocked if unlocked.
	Unlocked Status = "unlocked"
	// Locked if locked.
	Locked Status = "locked"
)

type Store

type Store interface {
	// Name of the Store implementation.
	Name() string

	// Get bytes.
	Get(path string) ([]byte, error)
	// Set bytes.
	Set(path string, data []byte) error
	// Delete bytes.
	Delete(path string) (bool, error)

	// List store entries.
	List(opts *ListOptions) ([]*Entry, error)

	// Open store.
	Open() error
	// Close store.
	Close() error
	// Reset store.
	Reset() error
}

Store is the interface used to store data.

func NewMem

func NewMem() Store

NewMem returns an in memory Store useful for testing or ephemeral keys.

type SyncStatus

type SyncStatus struct {
	KID      keys.ID
	Salt     []byte
	SyncedAt time.Time
}

SyncStatus is status of sync.

type Vault

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

Vault stores keys and secrets.

func New

func New(st Store, opt ...Option) *Vault

New vault.

Example
package main

import (
	"fmt"
	"log"
	"time"

	"github.com/keys-pub/keys-ext/vault"
)

func main() {
	// New vault.
	// Use vault.NewDB for a persistent store.
	vlt := vault.New(vault.NewMem())
	if err := vlt.Open(); err != nil {
		log.Fatal(err)
	}
	defer vlt.Close()

	// Setup auth.
	if err := vlt.UnlockWithPassword("mypassword", true); err != nil {
		log.Fatal(err)
	}

	// Save item.
	// Item IDs are NOT encrypted locally.
	item := vault.NewItem("id1", []byte("mysecret"), "", time.Now())
	if err := vlt.Set(item); err != nil {
		log.Fatal(err)
	}

	// Get item.
	out, err := vlt.Get("id1")
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("secret: %s\n", string(out.Data))

	// List items.
	items, err := vlt.Items()
	if err != nil {
		log.Fatal(err)
	}
	for _, item := range items {
		fmt.Printf("%s: %v\n", item.ID, string(item.Data))
	}

}
Output:

secret: mysecret
id1: mysecret

func (*Vault) CheckSync

func (v *Vault) CheckSync(ctx context.Context, expire time.Duration) (bool, error)

CheckSync performs sync unless disabled or already synced recently (within expire duration).

func (*Vault) Clone

func (v *Vault) Clone(ctx context.Context, remote *Remote) error

Clone initializes a Vault from a remote.

func (*Vault) Close

func (v *Vault) Close() error

Close vault.

func (*Vault) Delete

func (v *Vault) Delete(id string) (bool, error)

Delete vault item.

func (*Vault) Deprovision

func (v *Vault) Deprovision(id string, force bool) (bool, error)

Deprovision auth. Doesn't require Unlock().

func (*Vault) Get

func (v *Vault) Get(id string) (*Item, error)

Get vault item.

func (*Vault) IsEmpty

func (v *Vault) IsEmpty() (bool, error)

IsEmpty returns true if vault is empty.

func (*Vault) ItemHistory

func (v *Vault) ItemHistory(id string) ([]*Item, error)

ItemHistory returns history of an item. Items with empty data are deleted items. This is slow.

func (*Vault) Items

func (v *Vault) Items() ([]*Item, error)

Items to list.

func (*Vault) Lock

func (v *Vault) Lock()

Lock the vault.

func (*Vault) MasterKey

func (v *Vault) MasterKey() *[32]byte

MasterKey returns master key, if unlocked. The master key is used to encrypt items in the vault. It's not recommended to use this key for anything other than possibly deriving new keys. TODO: Point to spec.

func (*Vault) Now

func (v *Vault) Now() time.Time

Now is current time.

func (*Vault) Open

func (v *Vault) Open() error

Open vault.

func (*Vault) Provision

func (v *Vault) Provision(key *[32]byte, provision *Provision) error

Provision new auth. Requires Unlock().

func (*Vault) ProvisionSave

func (v *Vault) ProvisionSave(provision *Provision) error

ProvisionSave for auth methods that need to store registration data before key is available (for example, FIDO2 hmac-secret).

func (*Vault) Provisions

func (v *Vault) Provisions() ([]*Provision, error)

Provisions are currently provisioned auth. Doesn't require Unlock().

func (*Vault) Pull

func (v *Vault) Pull(ctx context.Context) error

Pull events from remote. Does NOT require Unlock.

func (*Vault) Remote

func (v *Vault) Remote() *Remote

Remote returns remote server and auth, if unlocked. The vault auth key is used to encrypt and verify vault items from the server. This encryption happens on top of the encryption by the master key. TODO: Point to spec.

func (*Vault) Reset

func (v *Vault) Reset() error

Reset vault.

func (*Vault) Salt

func (v *Vault) Salt() ([]byte, error)

Salt is default salt value, generated on first access. This salt value is not encrypted. Doesn't require Unlock().

func (*Vault) Set

func (v *Vault) Set(item *Item) error

Set vault item.

func (*Vault) SetClient

func (v *Vault) SetClient(client *Client)

SetClient sets the client.

func (*Vault) Setup

func (v *Vault) Setup(key *[32]byte, provision *Provision) error

Setup auth, if no auth exists. Returns ErrAlreadySetup if already setup. Doesn't require Unlock().

func (*Vault) Spew

func (v *Vault) Spew(prefix string, out io.Writer) error

Spew to out.

func (*Vault) Status

func (v *Vault) Status() (Status, error)

Status returns vault status. If there are no auths or provisions, returns vault.Setup. Doesn't require Unlock(). TODO: We may want to re-think hardware provisioning requiring seperate Unlock step on setup.

func (*Vault) Store

func (v *Vault) Store() Store

Store used by vault.

func (*Vault) Sync

func (v *Vault) Sync(ctx context.Context) error

Sync vault.

func (*Vault) SyncEnabled

func (v *Vault) SyncEnabled() (bool, error)

SyncEnabled returns true if sync is enabled. Sync is enabled by performing a sync and not having sync disabled.

func (*Vault) SyncStatus

func (v *Vault) SyncStatus() (*SyncStatus, error)

SyncStatus returns status for sync, or nil, if no sync has been performed.

func (*Vault) Unlock

func (v *Vault) Unlock(key *[32]byte) (*Provision, error)

Unlock with auth. Returns provision used to unlock.

func (*Vault) UnlockWithPassword

func (v *Vault) UnlockWithPassword(password string, setup bool) error

UnlockWithPassword unlocks with a password. If setup is true, we are setting up the auth for the first time. This is a convenience method, calling Setup or Unlock with KeyForPassword using the Salt.

func (*Vault) Unsync

func (v *Vault) Unsync(ctx context.Context) error

Unsync removes vault from the remote and resets the vault log.

The steps for "unsyncing" are: - Delete the vault from the server - Reset log (move pull into push) - Clear status (last synced, push, pull, nonces, rsalt) - Clear remote

Directories

Path Synopsis