Documentation
¶
Overview ¶
Package cluster implements the in-cluster secret backend.
It is the counterpart to the external managers RFD-90 anticipates: the same reference model, but Miren holds the value. A team gets a secret store without standing up Vault first, and because Miren owns retention a pinned version is guaranteed to stay resolvable rather than being pruned out from under a deploy.
Secrets are modeled the way config already is — a stable identity plus immutable versions — so the secret value stops being the one floating input in an otherwise fully-pinned deploy record. Each version is independently envelope-encrypted, so nothing sits in etcd in plaintext and the value exists only transiently, in memory, during a resolve.
Index ¶
- func ValidatePath(path string) error
- type Backend
- func (b *Backend) CountOnKey(ctx context.Context, kekID string) (int, error)
- func (b *Backend) Keyring() *keyring.Keyring
- func (b *Backend) KeyringReport(ctx context.Context) (secret.KeyringReport, error)
- func (b *Backend) List(ctx context.Context) ([]secret.Summary, error)
- func (b *Backend) ListVersions(ctx context.Context, path string) (secret.Summary, error)
- func (b *Backend) Name() string
- func (b *Backend) Put(ctx context.Context, path string, value []byte) (string, bool, error)
- func (b *Backend) Resolve(ctx context.Context, ref string) (secret.SecretValue, error)
- func (b *Backend) RewrapBatch(ctx context.Context, kekID string, limit int) (int, error)
- func (b *Backend) SetState(ctx context.Context, ref string, state secret.VersionState) error
- func (b *Backend) UseKeyring(ring *keyring.Keyring)
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func ValidatePath ¶
ValidatePath reports whether a path is addressable in the cluster backend. External backends address secrets in shapes Miren does not control, so this constrains only paths the cluster itself stores.
Types ¶
type Backend ¶
type Backend struct {
// contains filtered or unexported fields
}
Backend stores secret values inside the cluster's entity store.
func NewBackend ¶
NewBackend builds the in-cluster backend over an entity store and the cluster's keyring.
func (*Backend) CountOnKey ¶
CountOnKey reports how many stored versions are still wrapped by a given key.
This is what decides when a retiring key can be dropped: while it is above zero, retiring the key would strand those versions with nothing able to unwrap them. kek_id is indexed, so this is a single lookup rather than a scan of every secret.
func (*Backend) KeyringReport ¶
KeyringReport describes the cluster's keys and any rotation in flight.
The per-key version count is what makes rotation legible: a non-current key with versions still on it is a backfill that has not finished, and is exactly why that key cannot be dropped yet.
func (*Backend) List ¶
List returns every secret the cluster holds, with its versions, and never a value. An operator uses it to see the blast radius of a rotation or a revocation before acting.
func (*Backend) ListVersions ¶
ListVersions returns one secret's versions, without their values.
func (*Backend) Put ¶
Put stores a new version of the secret at path, reporting whether it reused the current version instead of minting a new one.
The reuse check is a keyed-hash comparison, not a decrypt-and-compare, so a re-run of the same `secret set` does not churn a new version and invalidate every pin — and does not need the value to be readable to notice. Reporting it from here rather than leaving the caller to compare handles is what keeps the answer honest under a concurrent rotation.
func (*Backend) Resolve ¶
Resolve returns the value for a backend-relative reference along with the fully-qualified reference it resolved to.
A version-less reference tracks the secret's current version; a pinned one holds exactly what it names. Either way the returned Ref carries a concrete version, so a ConfigVersion that records it sees identical bytes on every later resolve.
func (*Backend) RewrapBatch ¶
RewrapBatch moves up to limit versions off kekID and onto the ring's current key, returning how many it moved.
The work is defined by a query rather than a cursor — "versions still on the old key" — so it needs no progress bookkeeping. An interrupted backfill resumes simply by asking again, and a version rewrapped twice is a no-op. That matters because the alternative, tracking position, is state that can disagree with reality after a crash.
Only wrapped_dek and kek_id change. The ciphertext is never rewritten, so the cost per version is a few dozen bytes regardless of how large the secret is, and a value cannot be corrupted by a partially applied rewrap.
func (*Backend) SetState ¶
SetState transitions a specific version between enabled, disabled and destroyed. Destroying additionally drops the payload, so the value is gone rather than merely unreachable.
The reference must name a version: a state change is always about one version, and letting it float would make "disable the current one" a different secret depending on when it ran.
func (*Backend) UseKeyring ¶
UseKeyring swaps in a new ring, after which writes seal with its current key.
The caller must have persisted the ring before calling this. Sealing with a key that is not yet on disk means a crash leaves rows naming a key the cluster no longer has, and there is nothing to recover them from.