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: 2

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