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

secret

package
v0.2.0 Latest Latest
Warning

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

Go to latest
Published: Sep 27, 2026 License: MIT Imports: 9 Imported by: 0

Documentation

Overview

Package secret keeps values that must survive a database dump.

The engine stores what it needs to re-apply a workload, and some of that is a password somebody pasted in. Stored plainly it is in Postgres, in every backup, and in whatever the backup was copied to — none of which anybody thinks about at the moment they paste it.

So values are sealed here and only opened to apply. A dump is then useless without the key, which lives in configuration rather than in the database it protects.

A sealed value carries the format it was written in and the identity of the key that wrote it. Without those, replacing a key means every stored value fails at once with an error that can only guess at why, and there is no way to hold the old key alongside the new one while values are rewritten.

Index

Constants

This section is empty.

Variables

View Source
var ErrAltered = errors.New("secret: the stored value did not authenticate")

ErrAltered means the bytes did not authenticate under any key held.

View Source
var ErrFutureVersion = errors.New("secret: the stored value uses a newer envelope format")

ErrFutureVersion means the envelope names a format this build cannot read.

Its own error rather than ErrAltered, because the likely answer is to stop running the older binary. Reported as altered it would read as "this value is gone, set it again" — the one response that would actually lose it, since the newer binary could have opened it all along. Altered bytes remain a real possibility here and the message says so rather than picking.

View Source
var ErrUnknownKey = errors.New("secret: sealed with a key this install does not hold")

ErrUnknownKey means the value names a key this install does not hold.

Kept apart from ErrAltered because the two have different fixes and only one of them is alarming. A key retired a step too early is put back in YACHT_SECRET_KEY_PREVIOUS and everything opens again; a value that will not authenticate under a key that should open it has been changed underneath us. One error covering both is what the operator used to get, and it left them guessing at which had happened.

Functions

This section is empty.

Types

type Keeper

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

Keeper seals values with one key and opens them with any key it holds.

func NewKeeper

func NewKeeper(encodedKey string, encodedPrevious ...string) (*Keeper, error)

NewKeeper builds a Keeper from a base64-encoded 32-byte key, plus any keys retained only to open values sealed before it.

Generate one with:

openssl rand -base64 32

func (*Keeper) ActiveKeyID

func (k *Keeper) ActiveKeyID() string

ActiveKeyID is the ID of the key values are sealed with now.

func (*Keeper) Configured

func (k *Keeper) Configured() bool

Configured reports whether values can be sealed.

A nil Keeper is the shape of "no key set", so callers can hold one without a separate flag and this stays safe to call.

func (*Keeper) KeyIDFor

func (k *Keeper) KeyIDFor(sealed []byte) (string, error)

KeyIDFor reports which held key opens a stored value.

This is what turns "can this key be retired" into a query: a value that answers with some other key's ID does not need the one being dropped.

It answers by opening the value rather than by reading its header, because the header is only what the bytes claim. A value written before the envelope existed carries no ID at all, and the only truthful answer for one of those is the key that actually authenticates it.

func (*Keeper) KeyIDs

func (k *Keeper) KeyIDs() []string

KeyIDs lists every key held, the active one first.

The other half of a retirement check: KeyIDFor says which key a value needs, this says which are still being kept for it.

func (*Keeper) Open

func (k *Keeper) Open(sealed []byte) (string, error)

Open decrypts a stored value.

GCM authenticates as well as encrypts, so a value altered in the database fails here rather than decrypting to something else.

func (*Keeper) Seal

func (k *Keeper) Seal(plain string) ([]byte, error)

Seal encrypts a value for storage.

The nonce is random per call and stored ahead of the ciphertext, so sealing one value twice gives different bytes. Deterministic output would let anyone reading a dump tell which apps share a secret and which ones changed — without opening any of them.

Jump to

Keyboard shortcuts

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