secrets

package module
v0.1.13 Latest Latest
Warning

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

Go to latest
Published: May 12, 2026 License: Apache-2.0 Imports: 4 Imported by: 0

Documentation

Overview

Package secrets provides the core types and URI parser for secret provider integration in audit.

Secret references use the syntax ref+SCHEME://PATH#KEY, following the vals convention. When a YAML config value contains a ref URI, the outputconfig package resolves it by looking up the registered provider for the scheme and calling [Provider.Resolve].

This package is stdlib-only and defines only the interface, ref parser, and sentinel errors. Concrete provider implementations (OpenBao, Vault) live in separate sub-modules.

Index

Constants

This section is empty.

Variables

View Source
var (
	// ErrMalformedRef indicates a string starts with "ref+" but is
	// structurally invalid (missing scheme, path, key, or contains
	// path traversal).
	ErrMalformedRef = errors.New("audit/secrets: malformed secret reference")

	// ErrProviderNotRegistered indicates no provider is registered
	// for the scheme in a ref URI.
	ErrProviderNotRegistered = errors.New("audit/secrets: no provider registered for scheme")

	// ErrSecretNotFound indicates the secret path exists but the
	// requested key was not found.
	ErrSecretNotFound = errors.New("audit/secrets: secret not found at path")

	// ErrSecretResolveFailed indicates a transient or permanent
	// failure during secret resolution (network error, auth failure).
	ErrSecretResolveFailed = errors.New("audit/secrets: secret resolution failed")

	// ErrUnresolvedRef indicates that after all resolution passes, a
	// string in the config still contains a ref+ URI.
	ErrUnresolvedRef = errors.New("audit/secrets: unresolved secret reference in config")
)

Sentinel errors for secret provider operations. Consumers use errors.Is to distinguish error categories.

Functions

func ContainsRef

func ContainsRef(s string) bool

ContainsRef reports whether s contains a ref+ URI pattern anywhere in the string. Used by the safety-net scanner to detect unresolved references, including those embedded in larger strings.

This function intentionally over-matches (false positives are acceptable). It checks for "ref+" followed by at least one lowercase letter and "://" — but does not validate the full ref structure. Callers should follow up with ParseRef for full validation when needed.

func ValidatePath

func ValidatePath(path string) error

ValidatePath checks that a secret path has no traversal, empty segments, or percent-encoded characters. Intended for BatchProvider implementations to validate paths received from external callers.

Types

type BatchProvider

type BatchProvider interface {
	Provider

	// ResolvePath fetches all key-value pairs at the given path.
	// Returns the full map; the caller extracts individual keys.
	// The caller guarantees that path has passed [Ref.Valid]
	// validation (no traversal, no empty segments).
	//
	// Returns [ErrSecretNotFound] when the path does not exist.
	// Returns [ErrSecretResolveFailed] for transient/auth failures.
	ResolvePath(ctx context.Context, path string) (map[string]string, error)
}

BatchProvider is an optional extension of Provider for backends that can fetch all keys at a path in a single API call (e.g. Vault KV v2, OpenBao KV v2). The outputconfig resolver uses this to enable path-level caching — same path with different #key fragments results in one API call.

Providers that do not implement BatchProvider fall back to per-key [Provider.Resolve] calls with ref-level caching.

type Provider

type Provider interface {
	// Scheme returns the URI scheme this provider handles (e.g.
	// "openbao", "vault"). Must be lowercase and match the scheme
	// used in ref+ URIs.
	Scheme() string

	// Resolve fetches the secret value for the given reference.
	// The ctx controls timeout and cancellation for network I/O.
	// Returns the plaintext secret value as a string.
	//
	// Implementations should call [Ref.Valid] before using the ref
	// path to guard against manually-constructed invalid refs.
	//
	// Errors should wrap the appropriate sentinel:
	//   - [ErrSecretNotFound] when the path or key does not exist
	//   - [ErrSecretResolveFailed] for transient or auth failures
	//
	// Memory retention: the returned string is a Go string and
	// cannot be zeroed. Providers SHOULD store their authentication
	// material as `[]byte` and zero it in [Close] to reduce the
	// retention window for bootstrap credentials, but the resolved
	// VALUE returned from Resolve persists in memory until GC
	// reclaims it. Callers (notably [outputconfig.Load]) embed
	// resolved values in long-lived config structs; see SECURITY.md
	// §Secrets and Memory Retention for the full model.
	Resolve(ctx context.Context, ref Ref) (string, error)

	// Close releases resources held by the provider (HTTP clients,
	// connection pools). Errors are informational — the caller
	// cannot recover from a close failure but should log it.
	// Close is idempotent.
	//
	// Memory retention: implementations SHOULD zero any `[]byte`
	// storage of authentication material (e.g. the provider token)
	// to minimise the retention window. This is best-effort —
	// Go strings derived from the bytes (e.g. HTTP header copies)
	// cannot be zeroed and persist until GC. See SECURITY.md
	// §Secrets and Memory Retention.
	Close() error
}

Provider resolves secret references to their plaintext values. Implementations must be safe for sequential use within a single goroutine (the outputconfig load pipeline is single-threaded).

Providers carry credentials and must redact them in fmt.Stringer output. Construction (New) must not perform network I/O — connection is deferred to the first [Resolve] call.

type Ref

type Ref struct {
	// Scheme is the provider identifier (e.g. "openbao", "vault").
	Scheme string

	// Path is the secret path within the provider. Never contains
	// ".." segments, "." segments, empty segments, or percent-encoded
	// characters. MUST NOT be included in logs or error messages.
	Path string

	// Key is the field name within the secret (from the URI fragment).
	Key string
}

Ref is a parsed secret reference. The zero value indicates that ParseRef determined the input was not a secret reference.

Fields are exported for use by [Provider.Resolve] implementations. The Path field contains the vault path and MUST NOT appear in logs or error messages — use Ref.String for safe formatting.

func ParseRef

func ParseRef(s string) (Ref, error)

ParseRef parses "ref+SCHEME://PATH#KEY" into a Ref.

Returns (zero, nil) if s does not start with "ref+" — the input is not a secret reference and callers should treat it as a literal value.

Returns (zero, ErrMalformedRef) if s starts with "ref+" but is structurally invalid. Invalid cases include: empty scheme, empty path, leading slash in path, path containing ".." or "." segments, path containing empty segments (consecutive slashes), trailing slash, percent-encoded characters, empty or missing key fragment, key containing "#".

Returns (ref, nil) on success.

Error-message redaction

No error returned by ParseRef echoes any substring of the input (scheme, path, or key). A malformed ref may carry sensitive material; a user-controlled substring in an error message is a leakage vector when the error is logged or propagated through a config-loader surface. Error messages are category-level ("invalid scheme", "empty path", "key fragment must not contain "#"") plus the class descriptor returned by [redactRef] for the whole-input case (#486).

func (Ref) Format

func (r Ref) Format(f fmt.State, _ rune)

Format implements fmt.Formatter to ensure path redaction across all format verbs (%v, %+v, %#v, %s). Without this, %+v would print the struct fields directly, leaking the vault path.

func (Ref) GoString

func (r Ref) GoString() string

GoString implements fmt.GoStringer to prevent path leakage via %#v.

func (Ref) IsZero

func (r Ref) IsZero() bool

IsZero reports whether r is the zero value, indicating that ParseRef determined the input was not a secret reference.

func (Ref) String

func (r Ref) String() string

String returns a safe representation that redacts the secret path to prevent infrastructure topology leakage in logs and error messages. Use the struct fields directly for internal operations.

func (Ref) Valid

func (r Ref) Valid() error

Valid reports whether r is structurally valid. Returns nil if all fields are non-empty and the path passes validation. Provider implementations should call this before using r.Path to guard against manually-constructed invalid refs.

Directories

Path Synopsis
env module
file module
openbao module
vault module

Jump to

Keyboard shortcuts

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