vault

package module
v0.0.0-...-f6f491c Latest Latest
Warning

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

Go to latest
Published: Feb 9, 2026 License: MIT Imports: 5 Imported by: 0

README

vault

Go Reference Go Report Card

A pluggable configuration and secret store for Go.

Vault decouples where configuration comes from (sources) and where it lives locally (stores). Sources are read-only providers that fetch entries from external systems. Stores are read-write backends that persist entries locally for fast access.

Install

go get github.com/bjaus/vault

Quick Start

package main

import (
    "context"
    "fmt"
    "log"

    "github.com/bjaus/vault"
    "github.com/bjaus/vault/keychain"
)

func main() {
    v := vault.New(
        vault.WithStore(keychain.New()),
        vault.WithNamespace("prod"),
    )

    ctx := context.Background()

    // Store a secret manually.
    if err := v.Set(ctx, vault.Entry{Key: "api-token", Value: "sk-abc123"}); err != nil {
        log.Fatal(err)
    }

    // Retrieve it.
    entry, err := v.Get(ctx, "api-token")
    if err != nil {
        log.Fatal(err)
    }
    fmt.Println(entry.Value)
}

Core Interfaces

Two pluggable interfaces define the contract:

// Store persists entries locally (read-write).
type Store interface {
    Get(ctx context.Context, key string) (Entry, error)
    Set(ctx context.Context, entry Entry) error
    Delete(ctx context.Context, key string) error
    List(ctx context.Context) ([]Entry, error)
}

// Source fetches entries from an external system (read-only).
type Source interface {
    Fetch(ctx context.Context) ([]Entry, error)
}

SourceFunc adapts a plain function into a Source.

Sources and Auto-Refresh

When configured with sources, the vault auto-refreshes on the first cache miss. With a TTL configured, it re-refreshes after entries expire.

src := vault.SourceFunc(func(ctx context.Context) ([]vault.Entry, error) {
    // Fetch from SSM, Secrets Manager, a file, an API, etc.
    return []vault.Entry{
        {Key: "db-password", Value: "secret", Source: "ssm"},
    }, nil
})

v := vault.New(
    vault.WithStore(keychain.New()),
    vault.WithSource(src),
    vault.WithTTL(7 * 24 * time.Hour),
)

// First call: store miss -> fetches from source -> caches -> returns.
entry, err := v.Get(ctx, "db-password")

Explicit v.Refresh(ctx) is always available regardless of TTL.

Namespace Support

Store implementations that support scoping implement Namespaced:

type Namespaced interface {
    WithNamespace(namespace string) Store
}

Both the built-in Memory store and keychain.Store implement this. When a vault is configured with a namespace, operations are scoped automatically:

prod := vault.New(vault.WithStore(keychain.New()), vault.WithNamespace("prod"))
qa   := vault.New(vault.WithStore(keychain.New()), vault.WithNamespace("qa"))

// These don't collide — they're stored under different keyring services.
prod.Set(ctx, vault.Entry{Key: "db-host", Value: "prod.db.internal"})
qa.Set(ctx, vault.Entry{Key: "db-host", Value: "qa.db.internal"})

Store Implementations

Store Package Description
Memory vault In-memory, safe for concurrent use. Default when no store is provided.
Keychain vault/keychain OS keychain via go-keyring. macOS Keychain, Linux Secret Service, Windows Credential Manager.

License

MIT

Documentation

Overview

Package vault is a pluggable configuration and secret store.

Vault decouples where configuration comes from (Source) and where it lives locally (Store). Sources are read-only providers that fetch entries from external systems. Stores are read-write backends that persist entries locally for fast access.

Core Interfaces

Two pluggable interfaces define the contract:

  • Store — persists entries locally (read-write)
  • Source — fetches entries from an external system (read-only)

SourceFunc adapts a plain function into a Source.

Namespace Support

Store implementations that support scoping implement Namespaced. When a Vault is configured with a namespace and its store implements Namespaced, the vault automatically scopes all operations.

Resolution Flow

When [Vault.Get] is called:

  1. Check the store for the key
  2. If found and not expired (when TTL is configured), return it
  3. If missing or expired, auto-refresh from all sources (at most once per TTL period)
  4. Check the store again

Explicit [Vault.Refresh] is always available regardless of TTL.

Usage

v := vault.New(
    vault.WithStore(keychain.New()),
    vault.WithSource(mySSMSource),
    vault.WithNamespace("prod"),
    vault.WithTTL(7 * 24 * time.Hour),
)

entry, err := v.Get(ctx, "db-password")

Index

Constants

This section is empty.

Variables

View Source
var ErrNotFound = errors.New("vault: not found")

ErrNotFound is returned when an entry does not exist in the store.

Functions

This section is empty.

Types

type Entry

type Entry struct {
	Key       string    `json:"key"`
	Value     string    `json:"value"`
	CreatedAt time.Time `json:"created_at"`
	Source    string    `json:"source"`
}

Entry is a configuration or secret value.

type Memory

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

Memory is an in-memory Store. It is safe for concurrent use and implements Namespaced. Useful for testing and as the default store.

func NewMemory

func NewMemory() *Memory

NewMemory creates an empty in-memory store.

func (*Memory) Delete

func (m *Memory) Delete(_ context.Context, key string) error

Delete removes an entry by key.

func (*Memory) Get

func (m *Memory) Get(_ context.Context, key string) (Entry, error)

Get retrieves an entry by key.

func (*Memory) List

func (m *Memory) List(_ context.Context) ([]Entry, error)

List returns all entries in the store (within the current namespace).

func (*Memory) Set

func (m *Memory) Set(_ context.Context, entry Entry) error

Set stores an entry.

func (*Memory) WithNamespace

func (m *Memory) WithNamespace(ns string) Store

WithNamespace returns a Store scoped to the given namespace. The returned store shares the same backing data as the original.

type Namespaced

type Namespaced interface {
	WithNamespace(namespace string) Store
}

Namespaced is an optional interface for stores that support scoping. Store implementations that support namespacing implement this interface. When implemented, [Namespaced.WithNamespace] returns a Store whose operations are scoped to the given namespace. The returned store shares the same backing data as the original.

type Option

type Option func(*config)

Option configures a Vault created by New.

func WithNamespace

func WithNamespace(ns string) Option

WithNamespace scopes the vault to a namespace. If the configured store implements Namespaced, all operations are scoped automatically. If the store does not implement Namespaced, this option has no effect.

func WithSource

func WithSource(s Source) Option

WithSource adds a source to the vault. Sources are consulted in the order they are added during [Vault.Refresh].

func WithStore

func WithStore(s Store) Option

WithStore sets the backing store for the vault. If not provided, an in-memory store is used.

func WithTTL

func WithTTL(d time.Duration) Option

WithTTL sets the time-to-live for cached entries. When set, entries older than the TTL are considered expired and trigger an automatic refresh from sources on the next [Vault.Get]. A zero TTL means entries never expire automatically.

type Source

type Source interface {
	Fetch(ctx context.Context) ([]Entry, error)
}

Source fetches entries from an external system. Implementations are read-only providers — they produce entries but do not store them.

type SourceFunc

type SourceFunc func(ctx context.Context) ([]Entry, error)

SourceFunc adapts a plain function into a Source.

func (SourceFunc) Fetch

func (f SourceFunc) Fetch(ctx context.Context) ([]Entry, error)

Fetch calls the underlying function.

type Store

type Store interface {
	Get(ctx context.Context, key string) (Entry, error)
	Set(ctx context.Context, entry Entry) error
	Delete(ctx context.Context, key string) error
	List(ctx context.Context) ([]Entry, error)
}

Store persists entries locally. Implementations must be safe for concurrent use.

type Vault

type Vault interface {
	Store
	Refresh(ctx context.Context) error
}

Vault is a Store that resolves entries from external Source providers and caches them in a local Store. Use New to create one.

func New

func New(opts ...Option) Vault

New creates a Vault with the given options. If no store is provided, an in-memory store is used.

Directories

Path Synopsis
Package keychain implements a vault.Store backed by the operating system keychain via go-keyring.
Package keychain implements a vault.Store backed by the operating system keychain via go-keyring.

Jump to

Keyboard shortcuts

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