Documentation
¶
Overview ¶
Package kmsclient is the Go client SDK for the KMS parameter store and secret management service.
It hides gRPC boilerplate behind a small ergonomic surface:
- Simple reads: Client.GetParameter and Client.GetSecret.
- Declarative, store-backed config fields: SecretValue and ParameterValue, resolved with a single Client.Resolve call.
- Hot reload of non-secret parameters over the Subscribe stream, with live ParameterValue.Get handles and ParameterValue.OnChange callbacks.
- Atomic multi-resource releases through ReleaseLoader, with an optional pre-fetch ReleaseLoaderConfig.ValidateManifest contract check.
- TLS / mTLS configuration, per-RPC timeouts, an optional in-memory read cache, and typed sentinel errors.
Secret plaintext never appears in logs, errors, or the default string/JSON representation of any type in this package. Access to plaintext always requires an explicit call (Secret.Value, SecretValue.Value).
Namespaces and keys ¶
A client operates in a namespace — a fixed (env, app) pair such as "prod/gradethis". Keys are relative to that namespace ("postgres/password"); interior slashes are part of the key name, not namespace structure. Set the namespace with Config.Namespace, or leave it empty to discover it from the identity at first use (via WhoAmI); a relative key on an unbound identity then fails with ErrNoNamespace. A leading-slash key is an absolute "/env/app/key" display path, split in the SDK to reach another namespace.
Hot reload ¶
Non-secret ParameterValue fields hot-reload by default: they track the store over a shared Subscribe stream and ParameterValue.Get always returns the latest value. Set ParameterValue.Static to resolve once at Init instead.
Quick start ¶
client, err := kmsclient.NewClient(kmsclient.Config{
Endpoint: "parameter-store.prod.internal:8443",
Namespace: "prod/payments", // or "" to discover via WhoAmI
TLS: kmsclient.MTLSFromFiles("client.crt", "client.key", "server-ca.crt"),
CacheTTL: time.Minute,
})
if err != nil {
return err
}
defer client.Close()
dbPassword, err := client.GetSecret(ctx, "postgres/password")
if err != nil {
return err
}
_ = dbPassword.Value() // []byte plaintext, never logged
Index ¶
- Constants
- Variables
- func MTLSConfig(certFile, keyFile, caFile string) (*tls.Config, error)
- func MTLSFromFiles(certFile, keyFile, caFile string) *tls.Config
- func RunTypedRelease[T any](ctx context.Context, loader *ReleaseLoader, ...) error
- func TLSConfig(caFile string) (*tls.Config, error)
- func TLSFromFiles(caFile string) *tls.Config
- type Client
- func (c *Client) Close() error
- func (c *Client) GetParameter(ctx context.Context, key string, opts ...GetOption) (string, error)
- func (c *Client) GetSecret(ctx context.Context, key string, opts ...GetOption) (Secret, error)
- func (c *Client) PutParameter(ctx context.Context, key, value string, opts ...PutOption) (PutParameterResult, error)
- func (c *Client) PutSecret(ctx context.Context, key string, value []byte, opts ...PutSecretOption) (PutSecretResult, error)
- func (c *Client) Resolve(ctx context.Context, cfg any) error
- func (c *Client) Watch(ctx context.Context, fn func(Event)) (stop func(), err error)
- func (c *Client) WatchNamespace(ctx context.Context, namespace string, fn func(Event)) (stop func(), err error)
- type Config
- type Event
- type EventType
- type GetOption
- type Logger
- type ParameterValue
- func (p *ParameterValue) Get() string
- func (p *ParameterValue) Init(client *Client) error
- func (p *ParameterValue) InitContext(ctx context.Context, client *Client) error
- func (p *ParameterValue) Initialized() bool
- func (p *ParameterValue) OnChange(fn func(old, new string))
- func (p ParameterValue) String() string
- type PrepareReleaseFunc
- type PreparedRelease
- type PutOption
- type PutParameterResult
- type PutSecretOption
- type PutSecretResult
- type ReleaseEntryMetadata
- type ReleaseLoader
- type ReleaseLoaderConfig
- type ReleaseLoaderStats
- type ReleaseLoaderStatus
- type ReleaseManifest
- func (m ReleaseManifest) ActivationRevision() uint64
- func (m ReleaseManifest) Digest() string
- func (m ReleaseManifest) Entries() map[string]ReleaseEntryMetadata
- func (m ReleaseManifest) Entry(alias string) (ReleaseEntryMetadata, bool)
- func (m ReleaseManifest) Format(f fmt.State, _ rune)
- func (m ReleaseManifest) GoString() string
- func (m ReleaseManifest) MarshalJSON() ([]byte, error)
- func (m ReleaseManifest) MetadataJSON() string
- func (m ReleaseManifest) Name() string
- func (m ReleaseManifest) Namespace() string
- func (m ReleaseManifest) SchemaID() string
- func (m ReleaseManifest) SchemaVersion() uint64
- func (m ReleaseManifest) String() string
- func (m ReleaseManifest) Version() uint64
- type ReleaseParameter
- type ReleaseSnapshot
- func (s ReleaseSnapshot) ActivationRevision() uint64
- func (s ReleaseSnapshot) Digest() string
- func (s ReleaseSnapshot) Entries() map[string]ReleaseEntryMetadata
- func (s ReleaseSnapshot) Entry(alias string) (ReleaseEntryMetadata, bool)
- func (s ReleaseSnapshot) Format(f fmt.State, _ rune)
- func (s ReleaseSnapshot) GoString() string
- func (s ReleaseSnapshot) MarshalJSON() ([]byte, error)
- func (s ReleaseSnapshot) MetadataJSON() string
- func (s ReleaseSnapshot) Name() string
- func (s ReleaseSnapshot) Namespace() string
- func (s ReleaseSnapshot) Parameter(alias string) (ReleaseParameter, bool)
- func (s ReleaseSnapshot) Parameters() map[string]ReleaseParameter
- func (s ReleaseSnapshot) SchemaID() string
- func (s ReleaseSnapshot) SchemaVersion() uint64
- func (s ReleaseSnapshot) Secret(alias string) (Secret, bool)
- func (s ReleaseSnapshot) Secrets() map[string]Secret
- func (s ReleaseSnapshot) String() string
- func (s ReleaseSnapshot) Version() uint64
- type Secret
- func (s Secret) Clone() Secret
- func (s Secret) ContentType() string
- func (s Secret) Format(f fmt.State, verb rune)
- func (s Secret) GoString() string
- func (s Secret) IsZero() bool
- func (s Secret) MarshalJSON() ([]byte, error)
- func (s Secret) Path() string
- func (s Secret) String() string
- func (s Secret) StringValue() string
- func (s Secret) Value() []byte
- func (s Secret) Version() uint64
- type SecretTokenProvider
- type SecretValue
- func (v SecretValue) Format(f fmt.State, verb rune)
- func (v SecretValue) GoString() string
- func (v *SecretValue) Init(client *Client) error
- func (v *SecretValue) InitContext(ctx context.Context, client *Client) error
- func (v *SecretValue) Initialized() bool
- func (v SecretValue) MarshalJSON() ([]byte, error)
- func (v *SecretValue) Secret() Secret
- func (v SecretValue) String() string
- func (v *SecretValue) StringValue() string
- func (v *SecretValue) Value() string
- type ValidateReleaseManifestFunc
Examples ¶
Constants ¶
const ( ReleaseStateReceived = "received" ReleaseStatePrepared = "prepared" ReleaseStateApplied = "applied" ReleaseStateRejected = "rejected" ReleaseRejectResolutionFailed = "resolution_failed" ReleaseRejectVersionMismatch = "version_mismatch" ReleaseRejectDigestMismatch = "digest_mismatch" ReleaseRejectPrepareFailed = "prepare_failed" ReleaseRejectConfigContractMismatch = "config_contract_mismatch" ReleaseRejectConfigDecodeFailed = "config_decode_failed" ReleaseRejectConfigValidationFailed = "config_validation_failed" ReleaseRejectDefaultMismatch = "default_mismatch" ReleaseRejectRestartRequired = "restart_required" ReleaseRejectSuperseded = "superseded" ReleaseRejectActiveCheck = "active_check_failed" ReleaseRejectInternal = "internal" )
Variables ¶
var ( // ErrNotFound is returned when a parameter or secret (or the requested // version/label) does not exist. ErrNotFound = errors.New("kmsclient: not found") // ErrPermissionDenied is returned when the caller is authenticated but not // authorized for the requested path or operation. ErrPermissionDenied = errors.New("kmsclient: permission denied") // ErrUnauthenticated is returned when the client identity token is missing, // invalid, or expired. ErrUnauthenticated = errors.New("kmsclient: unauthenticated") // ErrFailedPrecondition is returned when the request is well-formed but the // server state does not allow it (e.g. mode mismatch on a client-bound // secret). ErrFailedPrecondition = errors.New("kmsclient: failed precondition") // ErrNotInitialized is reserved for compatibility. Declarative values do not // currently return it: SecretValue.Value panics with a descriptive message, // while ParameterValue.Get returns the empty string before Init/Resolve. ErrNotInitialized = errors.New("kmsclient: value not initialized") // ErrNoNamespace is returned when a relative key must be resolved but no // namespace is available: Config.Namespace is empty and the identity is // unbound (WhoAmI reports no namespace). Set Config.Namespace, bind the // identity to a namespace, or use an absolute "/env/app/key" display path. ErrNoNamespace = errors.New("kmsclient: no namespace") )
Sentinel errors returned by the SDK. Callers should test with errors.Is. None of these values, nor any error wrapping them, ever contains secret plaintext.
Functions ¶
func MTLSConfig ¶
MTLSConfig is the error-returning form of MTLSFromFiles.
func MTLSFromFiles ¶
MTLSFromFiles builds a *tls.Config for mutual TLS: it presents the given client certificate/key and verifies the server against caFile.
It panics on error so it can be used inline in a Config literal; use MTLSConfig for an error-returning variant.
func RunTypedRelease ¶
func RunTypedRelease[T any]( ctx context.Context, loader *ReleaseLoader, decode func(ReleaseSnapshot) (T, error), prepare func(context.Context, T) (PreparedRelease, error), ) error
RunTypedRelease explicitly decodes a release snapshot into T and then calls the application preparation function. It uses no reflection.
func TLSFromFiles ¶
TLSFromFiles builds a *tls.Config that verifies the server against the CA bundle in caFile. Use it for one-way TLS where the server does not require a client certificate.
It panics if the files cannot be read or parsed, so it is convenient to use inline in a Config literal at startup; use TLSConfig for an error-returning variant.
Types ¶
type Client ¶
type Client struct {
// contains filtered or unexported fields
}
Client is a connection to the parameter store. It is safe for concurrent use and should be shared for the lifetime of the process. Call Close to release resources.
func NewClient ¶
NewClient dials the parameter store and returns a ready Client. Transport security must be selected explicitly with Config.TLS, Config.Insecure, or custom transport credentials in Config.DialOptions.
Example ¶
package main
import (
"context"
"log"
"time"
"github.com/Suhaibinator/kms/sdk/go/kmsclient"
)
func main() {
client, err := kmsclient.NewClient(kmsclient.Config{
Endpoint: "parameter-store.prod.internal:8443",
// Cert-only identity: the namespace is discovered from the cert via
// WhoAmI. Set Namespace explicitly to skip discovery.
TLS: kmsclient.MTLSFromFiles("client.crt", "client.key", "server-ca.crt"),
CacheTTL: time.Minute,
})
if err != nil {
log.Fatal(err)
}
defer func() { _ = client.Close() }()
ctx := context.Background()
dbPassword, err := client.GetSecret(ctx, "postgres/password")
if err != nil {
log.Fatal(err)
}
// dbPassword prints as [REDACTED]; call Value() for plaintext.
_ = dbPassword.Value()
}
Output:
func (*Client) Close ¶
Close releases the connection and stops all background goroutines. It is safe to call multiple times.
func (*Client) GetParameter ¶
GetParameter returns the value of a non-secret parameter. key is relative to the client namespace, or an absolute "/env/app/key" display path. By default it reads the "current" label; use WithVersion or WithLabel to read another.
func (*Client) GetSecret ¶
GetSecret returns a secret. The returned Secret redacts itself in logs and string/JSON formatting; call Value or StringValue for plaintext. Use WithSecretToken for token-protected or client-bound secrets.
Token-gated reads (WithSecretToken) bypass the client cache entirely: caching them under the token-less key would let later calls without the token read the plaintext from cache, skipping the server's per-secret token check, and would keep serving after a token rotation until the TTL expired.
Example (ErrorHandling) ¶
package main
import (
"context"
"errors"
"fmt"
"github.com/Suhaibinator/kms/sdk/go/kmsclient"
)
func main() {
client, _ := kmsclient.NewClient(kmsclient.Config{
Endpoint: "localhost:8443",
Namespace: "prod/payments",
Insecure: true, // local development only
})
defer func() { _ = client.Close() }()
_, err := client.GetSecret(context.Background(), "missing")
switch {
case errors.Is(err, kmsclient.ErrNotFound):
fmt.Println("not found")
case errors.Is(err, kmsclient.ErrPermissionDenied):
fmt.Println("denied")
}
}
Output:
func (*Client) PutParameter ¶
func (c *Client) PutParameter(ctx context.Context, key, value string, opts ...PutOption) (PutParameterResult, error)
PutParameter creates a new immutable version of a parameter. key is relative to the client namespace, or an absolute "/env/app/key" display path. It is intended for tooling; most applications only read.
func (*Client) PutSecret ¶
func (c *Client) PutSecret(ctx context.Context, key string, value []byte, opts ...PutSecretOption) (PutSecretResult, error)
PutSecret creates a new immutable version of a secret. key is relative to the client namespace, or an absolute "/env/app/key" display path. It is intended for tooling.
func (*Client) Resolve ¶
Resolve walks cfg (which must be a non-nil pointer to a struct) and initializes every SecretValue and ParameterValue field it finds. Fetches are issued concurrently to minimize startup latency.
Walked: exported struct fields, non-nil pointers (including pointer chains), and the elements of slices and arrays — recursively, so a []SubConfig or []*SubConfig whose elements hold SecretValue/ParameterValue fields is fully initialized.
Not walked: map values (dynamically keyed), interface values, unexported fields, and channels/funcs. A SecretValue/ParameterValue reached only through one of these is left uninitialized and will panic at .Value()/return "" from .Get(); place such fields where Resolve can reach them.
If any field fails to resolve, Resolve returns the first error (after all in-flight fetches settle); already-initialized fields are left initialized.
Example ¶
package main
import (
"context"
"fmt"
"log"
"github.com/Suhaibinator/kms/sdk/go/kmsclient"
)
func main() {
type Config struct {
DBPassword kmsclient.SecretValue
StripeKey kmsclient.SecretValue
RateLimit kmsclient.ParameterValue
}
client, err := kmsclient.NewClient(kmsclient.Config{
Endpoint: "localhost:8443",
Namespace: "prod/payments",
Insecure: true, // local development only
})
if err != nil {
log.Fatal(err)
}
defer func() { _ = client.Close() }()
cfg := Config{
DBPassword: kmsclient.SecretValue{Key: "postgres/password"},
StripeKey: kmsclient.SecretValue{Key: "stripe/api-key", EnvVar: "STRIPE_KEY"},
RateLimit: kmsclient.ParameterValue{Key: "rate-limit"}, // hot-reloads by default
}
if err := client.Resolve(context.Background(), &cfg); err != nil {
log.Fatal(err)
}
cfg.RateLimit.OnChange(func(old, new string) {
fmt.Printf("rate limit changed: %s -> %s\n", old, new)
})
_ = cfg.DBPassword.Value()
_ = cfg.RateLimit.Get()
}
Output:
func (*Client) Watch ¶
Watch subscribes to the client's whole namespace and invokes fn for every change in it — there is no key pattern. An app that only cares about a subset filters inside fn by its own convention (e.g. strings.HasPrefix(ev.Key, "db/")). The returned stop function unregisters the watcher; it is also called automatically if ctx is cancelled. Watch requires the client to have a namespace (Config.Namespace or a namespace-bound identity); otherwise it returns ErrNoNamespace.
Example ¶
package main
import (
"context"
"fmt"
"log"
"github.com/Suhaibinator/kms/sdk/go/kmsclient"
)
func main() {
client, _ := kmsclient.NewClient(kmsclient.Config{
Endpoint: "localhost:8443",
Namespace: "prod/payments",
Insecure: true, // local development only
})
defer func() { _ = client.Close() }()
// Watch fires for every change in the client's namespace; filter inside the
// callback if you only care about a subset.
stop, err := client.Watch(context.Background(), func(ev kmsclient.Event) {
fmt.Printf("%s %s => %s\n", ev.Type, ev.Key, ev.Value)
})
if err != nil {
log.Fatal(err)
}
defer stop()
}
Output:
func (*Client) WatchNamespace ¶
func (c *Client) WatchNamespace(ctx context.Context, namespace string, fn func(Event)) (stop func(), err error)
WatchNamespace watches a specific namespace ("env/app") the client is authorized for, invoking fn for every change in it. Like Watch it takes no key pattern. Use it to observe a namespace other than the client's own.
type Config ¶
type Config struct {
// Endpoint is the server address as host:port. For custom transports it
// may be any gRPC target; see DialOptions.
Endpoint string
// Namespace is the client's home namespace in "env/app" form (e.g.
// "prod/gradethis"). Relative keys are resolved against it. Leave it empty
// to discover the namespace from the identity at first use via WhoAmI; a
// relative key on an unbound identity then fails with ErrNoNamespace.
// Absolute "/env/app/key" display paths never require a namespace.
Namespace string
// Token is the per-client identity token, sent as
// "authorization: Bearer <token>" on every RPC. It is optional when TLS
// carries a client certificate (the identity then derives from the cert
// server-side); required only for token-method identities. Empty is also
// allowed for unauthenticated/dev servers.
Token string
// TLS configures transport security. Use TLSFromFiles or MTLSFromFiles to
// build one. When TLS is nil, NewClient fails unless Insecure is explicitly
// set or DialOptions supplies custom transport credentials.
TLS *tls.Config
// Insecure explicitly permits a cleartext connection. Use it only for local
// development on a trusted network. It is mutually exclusive with TLS.
Insecure bool
// CacheTTL enables an in-memory read cache for GetParameter/GetSecret when
// greater than zero. Cached parameter and secret entries are invalidated by
// watch events when a subscription is active.
CacheTTL time.Duration
// FallbackToDefaultsOnError controls whether declarative SecretValue /
// ParameterValue fields fall back to their Default on ANY store-fetch error.
//
// By default (false) a Default is used only when the store affirmatively
// reports the value absent (ErrNotFound). Every other error — unavailable,
// timeout, unauthenticated, permission denied — fails Init/Resolve, so a
// process cannot silently boot on a dev Default (e.g. "sk_test_...") merely
// because the store was briefly unreachable at startup.
//
// Set true to restore the permissive any-error → Default behavior (plan
// 9.2.9, "fallback behavior where explicitly configured"). Use it only where
// booting on a stale or dev default is genuinely acceptable.
FallbackToDefaultsOnError bool
// Timeout is the default per-RPC deadline applied when the caller's context
// has no earlier deadline. Defaults to 5s. Does not apply to the long-lived
// Subscribe stream.
Timeout time.Duration
// ClientName identifies this client to the subscription registry (plan
// 8.4). Defaults to the base name of os.Args[0].
ClientName string
// Logger receives operational log lines. It never receives secret
// plaintext. Defaults to the standard library logger.
Logger Logger
// DialOptions are appended to the dial options the SDK builds, allowing
// advanced transport tuning or injection of a custom dialer. Options here
// override earlier ones (e.g. transport credentials). When neither TLS nor
// Insecure is set, DialOptions must supply transport credentials; this is how
// tests explicitly dial an in-process cleartext server.
DialOptions []grpc.DialOption
}
Config configures a Client.
type Event ¶
type Event struct {
Type EventType
// Namespace is the "env/app" namespace of the changed resource.
Namespace string
// Key is the resource key, relative to Namespace.
Key string
Value string // populated for EventPut
Version uint64
Revision uint64
ChangeType string // raw server change_type, useful for secret changes
}
Event is delivered to Watch callbacks for every change in a watched namespace.
type EventType ¶
type EventType int
EventType classifies a watch Event.
const ( // EventPut is a parameter create/update or label move; Value holds the new // value. EventPut EventType = iota // EventDelete is a parameter deletion. EventDelete // EventSecretChange is a secret metadata change (no plaintext); the app // re-fetches via GetSecret if it cares. EventSecretChange )
type GetOption ¶
type GetOption func(*getOptions)
GetOption customizes a single GetParameter / GetSecret call.
func WithLabel ¶
WithLabel reads the version currently pointed at by the given label (e.g. "current", "previous"). Ignored if WithVersion is also supplied.
func WithSecretToken ¶
WithSecretToken sets the x-kms-secret-token metadata for the call. It is required for token-protected and client-bound secrets; for client-bound secrets the token also carries the client key share (see plan 10.7).
func WithVersion ¶
WithVersion pins the read to a specific immutable version. It takes precedence over WithLabel.
type Logger ¶
Logger is the minimal logging surface the SDK uses. It mirrors the signature of the standard library's log.Printf.
The SDK only ever logs operational information (paths, env-var names, connection state, revisions). It never logs secret plaintext.
type ParameterValue ¶
type ParameterValue struct {
// Key is the parameter key, relative to the client namespace (e.g.
// "rate-limit"), or an absolute "/env/app/key" display path.
Key string
// EnvVar optionally overrides the store value; an env-set value is pinned
// and does not hot-reload.
EnvVar string
// Default is an optional fallback, intended for development.
Default string
// Static disables hot reload: the value resolves once at Init and never
// changes afterward. The zero value keeps hot reload ON — every non-static
// ParameterValue tracks its namespace over the shared Subscribe stream.
Static bool
// contains filtered or unexported fields
}
ParameterValue is a declarative, store-backed non-secret field. By default it hot-reloads over the client's shared Subscribe stream, so Get always returns the latest value without an RPC. Set Static to opt out and resolve once at Init.
Like SecretValue, mutable state lives behind a pointer so the value type stays copy-safe.
func (*ParameterValue) Get ¶
func (p *ParameterValue) Get() string
Get returns the latest value. Safe for concurrent use; returns "" before Init.
func (*ParameterValue) Init ¶
func (p *ParameterValue) Init(client *Client) error
Init resolves the value (env override, store fetch, Default only when the store reports the value absent unless Config.FallbackToDefaultsOnError is set, else error) and, unless Static is set or the value came from an env override, registers the value's namespace on the client's shared subscription for hot reload. It is idempotent.
func (*ParameterValue) InitContext ¶
func (p *ParameterValue) InitContext(ctx context.Context, client *Client) error
InitContext is Init with a caller-supplied context.
func (*ParameterValue) Initialized ¶
func (p *ParameterValue) Initialized() bool
Initialized reports whether the value has been resolved.
func (*ParameterValue) OnChange ¶
func (p *ParameterValue) OnChange(fn func(old, new string))
OnChange registers a callback invoked (on a dedicated goroutine) whenever the value changes. old and new are the previous and current values. Registering a callback on a Static or env-pinned value is allowed but it will never fire.
func (ParameterValue) String ¶
func (p ParameterValue) String() string
String returns the current value (non-secret), or "" before Init.
type PrepareReleaseFunc ¶
type PrepareReleaseFunc func(context.Context, ReleaseSnapshot) (PreparedRelease, error)
PrepareReleaseFunc validates a candidate and constructs resources before it becomes visible. The context is canceled when a newer release supersedes the candidate.
type PreparedRelease ¶
type PreparedRelease interface {
Commit()
Abort()
}
PreparedRelease is application-owned state built from a complete candidate. Commit must be infallible and should normally perform only an atomic swap.
type PutOption ¶
type PutOption func(*putOptions)
PutOption customizes a PutParameter call.
func WithContentType ¶
WithContentType sets the parameter content type (string, integer, float, boolean, json, binary). Defaults to "string" on the server.
func WithMetadataJSON ¶
WithMetadataJSON attaches an opaque JSON metadata blob to the parameter.
type PutParameterResult ¶
PutParameterResult reports the outcome of a parameter write.
type PutSecretOption ¶
type PutSecretOption func(*putSecretOptions)
PutSecretOption customizes a PutSecret call.
func WithClientBound ¶
func WithClientBound() PutSecretOption
WithClientBound opts a secret into client-bound double wrapping. New secrets also require WithGenerateAccessToken; updates must keep this option set and supply the current token with WithPutSecretToken.
func WithExpiresAt ¶
func WithExpiresAt(unixMS int64) PutSecretOption
WithExpiresAt sets an expiry (unix milliseconds) for the new secret version; 0 means never.
func WithGenerateAccessToken ¶
func WithGenerateAccessToken() PutSecretOption
WithGenerateAccessToken asks the server to mint a per-secret access token, returned exactly once in PutSecretResult.AccessToken.
func WithPutSecretToken ¶
func WithPutSecretToken(token string) PutSecretOption
WithPutSecretToken sets the x-kms-secret-token for the write, needed when updating an existing token-protected or client-bound secret.
func WithSecretContentType ¶
func WithSecretContentType(ct string) PutSecretOption
WithSecretContentType sets the secret content type.
func WithSecretMetadataJSON ¶
func WithSecretMetadataJSON(j string) PutSecretOption
WithSecretMetadataJSON attaches an opaque JSON metadata blob to the secret.
type PutSecretResult ¶
PutSecretResult reports the outcome of a secret write. AccessToken is set only when WithGenerateAccessToken was supplied, and is never retrievable again.
type ReleaseEntryMetadata ¶
type ReleaseEntryMetadata struct {
Alias string `json:"alias"`
Kind string `json:"kind"`
Path string `json:"path"`
Version uint64 `json:"version"`
ContentType string `json:"content_type,omitempty"`
MetadataJSON string `json:"metadata_json,omitempty"`
ParameterDigest string `json:"parameter_digest,omitempty"`
ClientBound bool `json:"client_bound,omitempty"`
HasAccessToken bool `json:"has_access_token,omitempty"`
}
ReleaseEntryMetadata describes one immutable resource pin in a configuration release. It contains no parameter value, secret plaintext, or access token.
type ReleaseLoader ¶
type ReleaseLoader struct {
// contains filtered or unexported fields
}
ReleaseLoader owns release stream reliability, exact resource resolution, lifecycle acknowledgements, and last-known-good behavior.
func NewReleaseLoader ¶
func NewReleaseLoader(client *Client, cfg ReleaseLoaderConfig) (*ReleaseLoader, error)
NewReleaseLoader creates a loader. It does not contact KMS until Run.
func (*ReleaseLoader) InstanceID ¶
func (l *ReleaseLoader) InstanceID() string
InstanceID returns the subscriber instance ID reused across reconnects.
func (*ReleaseLoader) Run ¶
func (l *ReleaseLoader) Run(ctx context.Context, prepare PrepareReleaseFunc) error
Run watches, resolves, prepares, and atomically applies release candidates. Before the first successful Commit, a non-supersession candidate failure is returned. After that point errors reject the candidate and the last-known-good release remains applied until a later candidate succeeds.
func (*ReleaseLoader) Stats ¶
func (l *ReleaseLoader) Stats() ReleaseLoaderStats
Stats returns bounded counters without resource aliases or paths.
func (*ReleaseLoader) Status ¶
func (l *ReleaseLoader) Status() ReleaseLoaderStatus
Status returns a redacted, concurrency-safe loader status snapshot.
type ReleaseLoaderConfig ¶
type ReleaseLoaderConfig struct {
// Name is the release name within the client's home namespace.
Name string
// ReconcileInterval controls fresh GetActiveRelease safety checks. It
// defaults to one minute.
ReconcileInterval time.Duration
// SecretTokenProvider supplies locally held credentials for protected
// secret entries. Tokens are sent only to the corresponding GetSecret RPC.
SecretTokenProvider SecretTokenProvider
// ValidateManifest optionally validates the immutable unresolved manifest.
// It runs after release identity, digest, and basic entry validation, but
// before any resource fetch or secret-token lookup.
ValidateManifest ValidateReleaseManifestFunc
// MaxConcurrentFetches bounds parallel pinned resource reads. Values <= 0
// use 16; values above 256 are rejected.
MaxConcurrentFetches int
// InstanceID overrides the generated process-lifetime subscriber ID. It is
// mainly useful when an application already has a stable replica identifier.
InstanceID string
}
ReleaseLoaderConfig configures a high-level configuration release loader.
type ReleaseLoaderStats ¶
type ReleaseLoaderStats struct {
Candidates uint64
Applied uint64
Rejected map[string]uint64
Reconnects uint64
}
ReleaseLoaderStats contains bounded counters suitable for metrics export. It intentionally contains no aliases, paths, diagnostics, or secret metadata.
type ReleaseLoaderStatus ¶
type ReleaseLoaderStatus struct {
State string
ObservedVersion uint64
ObservedRevision uint64
AppliedVersion uint64
AppliedRevision uint64
LastFailureCategory string
LastFailureAt time.Time
LastResolutionDuration time.Duration
Reconnects uint64
}
ReleaseLoaderStatus is a redacted point-in-time view of loader progress.
type ReleaseManifest ¶
type ReleaseManifest struct {
// contains filtered or unexported fields
}
ReleaseManifest is an immutable, unresolved configuration release. It contains only release identity and non-sensitive entry metadata, never parameter values, secret plaintext, or access tokens. Its entry map is private and accessors return copies so validation callbacks cannot alter the candidate that the loader will resolve.
func (ReleaseManifest) ActivationRevision ¶
func (m ReleaseManifest) ActivationRevision() uint64
func (ReleaseManifest) Digest ¶
func (m ReleaseManifest) Digest() string
func (ReleaseManifest) Entries ¶
func (m ReleaseManifest) Entries() map[string]ReleaseEntryMetadata
Entries returns an alias-keyed copy of every unresolved release entry.
func (ReleaseManifest) Entry ¶
func (m ReleaseManifest) Entry(alias string) (ReleaseEntryMetadata, bool)
Entry returns metadata for one stable alias.
func (ReleaseManifest) Format ¶
func (m ReleaseManifest) Format(f fmt.State, _ rune)
Format prevents formatting from reflecting private implementation fields.
func (ReleaseManifest) GoString ¶
func (m ReleaseManifest) GoString() string
GoString uses the same safe representation as String.
func (ReleaseManifest) MarshalJSON ¶
func (m ReleaseManifest) MarshalJSON() ([]byte, error)
MarshalJSON emits only release identity and non-sensitive entry metadata.
func (ReleaseManifest) MetadataJSON ¶
func (m ReleaseManifest) MetadataJSON() string
func (ReleaseManifest) Name ¶
func (m ReleaseManifest) Name() string
func (ReleaseManifest) Namespace ¶
func (m ReleaseManifest) Namespace() string
func (ReleaseManifest) SchemaID ¶
func (m ReleaseManifest) SchemaID() string
func (ReleaseManifest) SchemaVersion ¶
func (m ReleaseManifest) SchemaVersion() uint64
func (ReleaseManifest) String ¶
func (m ReleaseManifest) String() string
String intentionally contains only release identity, never resolved values.
func (ReleaseManifest) Version ¶
func (m ReleaseManifest) Version() uint64
type ReleaseParameter ¶
type ReleaseParameter struct {
// contains filtered or unexported fields
}
ReleaseParameter is a resolved, version-pinned non-secret value. Its metadata is copied from the immutable release manifest.
func (ReleaseParameter) Entry ¶
func (p ReleaseParameter) Entry() ReleaseEntryMetadata
Entry returns the resource pin and non-sensitive metadata.
func (ReleaseParameter) StringValue ¶
func (p ReleaseParameter) StringValue() string
StringValue is an alias for Value.
func (ReleaseParameter) Value ¶
func (p ReleaseParameter) Value() string
Value returns the parameter document exactly as stored.
type ReleaseSnapshot ¶
type ReleaseSnapshot struct {
// contains filtered or unexported fields
}
ReleaseSnapshot is a completely resolved configuration release candidate. Its maps are private and accessors return copies, so application code cannot alter the candidate seen by another preparation step.
func (ReleaseSnapshot) ActivationRevision ¶
func (s ReleaseSnapshot) ActivationRevision() uint64
func (ReleaseSnapshot) Digest ¶
func (s ReleaseSnapshot) Digest() string
func (ReleaseSnapshot) Entries ¶
func (s ReleaseSnapshot) Entries() map[string]ReleaseEntryMetadata
Entries returns an alias-keyed copy of every release entry.
func (ReleaseSnapshot) Entry ¶
func (s ReleaseSnapshot) Entry(alias string) (ReleaseEntryMetadata, bool)
Entry returns metadata for one stable alias.
func (ReleaseSnapshot) Format ¶
func (s ReleaseSnapshot) Format(f fmt.State, _ rune)
Format prevents %+v and %#v from reflecting private secret-bearing fields.
func (ReleaseSnapshot) GoString ¶
func (s ReleaseSnapshot) GoString() string
GoString uses the same redacted representation as String.
func (ReleaseSnapshot) MarshalJSON ¶
func (s ReleaseSnapshot) MarshalJSON() ([]byte, error)
MarshalJSON emits release identity and entry metadata only. Resolved values are deliberately excluded so snapshots are safe to attach to diagnostics.
func (ReleaseSnapshot) MetadataJSON ¶
func (s ReleaseSnapshot) MetadataJSON() string
func (ReleaseSnapshot) Name ¶
func (s ReleaseSnapshot) Name() string
func (ReleaseSnapshot) Namespace ¶
func (s ReleaseSnapshot) Namespace() string
func (ReleaseSnapshot) Parameter ¶
func (s ReleaseSnapshot) Parameter(alias string) (ReleaseParameter, bool)
Parameter returns one resolved parameter document.
func (ReleaseSnapshot) Parameters ¶
func (s ReleaseSnapshot) Parameters() map[string]ReleaseParameter
Parameters returns an alias-keyed copy of all resolved parameter documents.
func (ReleaseSnapshot) SchemaID ¶
func (s ReleaseSnapshot) SchemaID() string
func (ReleaseSnapshot) SchemaVersion ¶
func (s ReleaseSnapshot) SchemaVersion() uint64
func (ReleaseSnapshot) Secret ¶
func (s ReleaseSnapshot) Secret(alias string) (Secret, bool)
Secret returns one resolved secret without exposing it through formatting.
func (ReleaseSnapshot) Secrets ¶
func (s ReleaseSnapshot) Secrets() map[string]Secret
Secrets returns an alias-keyed copy of the resolved secret values. Every Secret preserves the SDK's redacting formatting behavior; plaintext remains available only through Secret.Value/StringValue.
func (ReleaseSnapshot) String ¶
func (s ReleaseSnapshot) String() string
String intentionally contains only release identity, never resolved values.
func (ReleaseSnapshot) Version ¶
func (s ReleaseSnapshot) Version() uint64
type Secret ¶
type Secret struct {
// contains filtered or unexported fields
}
Secret holds secret plaintext together with non-sensitive metadata. It is deliberately hard to leak: its String, GoString, Format and MarshalJSON implementations all emit "[REDACTED]", so it is safe to pass to fmt.Printf, structured loggers, or json.Marshal. Plaintext is only accessible through the explicit Value / StringValue accessors.
Secret is a value type; copies redact identically.
func NewSecret ¶
NewSecret wraps plaintext in a Secret. It is mainly useful in tests and tooling; normal code obtains Secrets from Client.GetSecret.
func (Secret) Clone ¶
Clone returns an independent copy of the Secret. The plaintext buffer is deep-copied while the immutable path, version, and content-type metadata are preserved.
func (Secret) ContentType ¶
ContentType returns the declared content type of the secret, if known.
func (Secret) Format ¶
Format implements fmt.Formatter so that every verb (%v, %s, %+v, %#v, %q, ...) redacts the plaintext. %q wraps the redaction in quotes for valid output.
func (Secret) GoString ¶
GoString implements fmt.GoStringer (used by the %#v verb) and always redacts.
func (Secret) MarshalJSON ¶
MarshalJSON always emits the redaction string, so a Secret embedded in a JSON-marshaled struct never leaks plaintext.
func (Secret) StringValue ¶
StringValue returns the secret plaintext as a string.
type SecretTokenProvider ¶
SecretTokenProvider supplies a locally held per-secret access token or client-bound key share. It is called only for release entries marked as token-protected or client-bound.
type SecretValue ¶
type SecretValue struct {
// Key is the secret key, relative to the client namespace (e.g.
// "stripe/api-key"), or an absolute "/env/app/key" display path.
Key string
// Token is the per-secret access token. For client-bound secrets it is also
// the client key share (plan 10.7).
Token string
// EnvVar is an optional environment variable that, when set and non-empty,
// overrides the store value.
EnvVar string
// Default is an optional fallback value, intended for development only.
Default string
// contains filtered or unexported fields
}
SecretValue is a declarative, store-backed secret field. Declare it in a config struct, then resolve it with Init (or via Client.Resolve). Once initialized it redacts itself in all string/JSON formatting; plaintext is only reachable through Value/StringValue.
The mutable state lives behind an unexported pointer so that SecretValue's redacting formatter methods can use value receivers (a struct that embedded a mutex directly could not, and would leak plaintext through fmt's reflection of unexported fields).
func (SecretValue) Format ¶
func (v SecretValue) Format(f fmt.State, verb rune)
Format redacts for every verb.
func (SecretValue) GoString ¶
func (v SecretValue) GoString() string
GoString redacts (used by %#v).
func (*SecretValue) Init ¶
func (v *SecretValue) Init(client *Client) error
Init resolves the value using the standard order: env override, then store fetch, then Default (only when the store reports the value absent, unless Config.FallbackToDefaultsOnError is set), else an error naming the path. It is idempotent: a second call after success is a no-op. Init is not safe to call concurrently on the same SecretValue (Client.Resolve initializes distinct fields in parallel, which is safe).
func (*SecretValue) InitContext ¶
func (v *SecretValue) InitContext(ctx context.Context, client *Client) error
InitContext is Init with a caller-supplied context.
func (*SecretValue) Initialized ¶
func (v *SecretValue) Initialized() bool
Initialized reports whether the value has been resolved.
func (SecretValue) MarshalJSON ¶
func (v SecretValue) MarshalJSON() ([]byte, error)
MarshalJSON redacts.
func (*SecretValue) Secret ¶
func (v *SecretValue) Secret() Secret
Secret returns the resolved plaintext wrapped in a redacting Secret.
func (SecretValue) String ¶
func (v SecretValue) String() string
String redacts. Value receiver so both SecretValue and *SecretValue redact, and so fmt does not fall through to the unexported state.
func (*SecretValue) StringValue ¶
func (v *SecretValue) StringValue() string
StringValue is an alias for Value.
func (*SecretValue) Value ¶
func (v *SecretValue) Value() string
Value returns the resolved plaintext. It panics if the value has not been initialized, which surfaces wiring mistakes at first use rather than serving an empty secret.
type ValidateReleaseManifestFunc ¶
type ValidateReleaseManifestFunc func(context.Context, ReleaseManifest) error
ValidateReleaseManifestFunc validates unresolved release identity and entry metadata. It runs before any pinned parameter or secret is fetched and before SecretTokenProvider is called.
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
Package kmsclienttest provides an in-process, scriptable fake of the KMS gRPC services, backed by bufconn.
|
Package kmsclienttest provides an in-process, scriptable fake of the KMS gRPC services, backed by bufconn. |