Documentation
¶
Overview ¶
Package secrets reads and writes AWS Secrets Manager secrets, with the cache and the transforms of package parameters.
Create a Provider once and share it:
var vault = secrets.FromConfig(cfg) // or secrets.New(client)
key, err := vault.Get(ctx, "api-key")
creds, err := parameters.Get[Credentials](ctx, vault, "db-credentials",
parameters.WithTransform(parameters.TransformJSON))
previous, err := vault.Get(ctx, "db-password", secrets.WithVersionStage("AWSPREVIOUS"))
values, failed, err := vault.GetByName(ctx, []string{"api-key", "db-password"})
or use the shortcuts, which build a provider from the default AWS configuration on first use: GetSecret, GetSecretsByName, SetSecret.
Get calls GetSecretValue and returns SecretString, or the bytes of SecretBinary. GetByName calls BatchGetSecretValue. Set adds a version to a secret with PutSecretValue and creates the secret with CreateSecret when it does not exist yet; a []byte value is a SecretBinary, a string a SecretString, any other value its JSON encoding.
Differences from Python ¶
- Fixed in GetByName: Python finds the secrets through a name filter, which matches by prefix ("db" also returns "db-password") and takes ten names at most. Here the secrets are asked for by their exact name or ARN (SecretIdList), twenty per call and as many calls as needed; with WithFilters the name filter is used, ten names per call, and only exact matches are kept.
- Fixed in GetByName: the secrets Secrets Manager could not read (missing, access denied, decryption failure) are returned with their error instead of being dropped silently. The read still succeeds with the others, as in Python, and fails only when none could be read.
- Version selectors (WithVersionID, WithVersionStage) are part of the cache key, so a previous version never answers for the current one.
- Set accepts any JSON value, not only a dict, and returns the ARN, the name and the version id of either answer.
Index ¶
- Variables
- func GetByName[T any](ctx context.Context, p *Provider, names []string, opts ...parameters.Option) (values map[string]T, failed map[string]error, err error)
- func GetSecret[T any](ctx context.Context, name string, opts ...parameters.Option) (T, error)
- func GetSecretsByName[T any](ctx context.Context, names []string, opts ...parameters.Option) (values map[string]T, failed map[string]error, err error)
- func WithFilters(filters ...types.Filter) parameters.Option
- func WithVersionID(id string) parameters.Option
- func WithVersionStage(stage string) parameters.Option
- type Client
- type Provider
- type SetOption
- type SetResult
Examples ¶
Constants ¶
This section is empty.
Variables ¶
var ( // ErrNoNames reports a GetByName without names. ErrNoNames = errors.New("you must provide at least one secret name") // ErrNoSecretsFound reports a GetByName that could read none of the // secrets it was asked for. ErrNoSecretsFound = errors.New("no secrets found matching the provided names") )
The sentinel errors of GetByName, inside a *parameters.GetSecretError.
Functions ¶
func GetByName ¶
func GetByName[T any](ctx context.Context, p *Provider, names []string, opts ...parameters.Option) (values map[string]T, failed map[string]error, err error)
GetByName reads several secrets with BatchGetSecretValue and returns them as Ts (see parameters.Get), keyed by the names asked for: Python's get_secrets_by_name. Names may be ARNs.
The secrets are asked for by their exact name or ARN (SecretIdList, up to twenty per call, as many calls as needed). With WithFilters they are found through a name filter instead, as Python does, and only exact matches are kept.
As in Python, the secrets that cannot be read do not fail the others: they are returned in failed, by name, each with its error (Secrets Manager reports ResourceNotFoundException, AccessDeniedException, DecryptionFailure as smithy.APIError). The read fails when none of the secrets can be read, or when a call fails as a whole. A secret whose transform fails is in failed too, unless WithRaiseOnTransformError makes it fail the read.
The result is cached under the set of names asked for, as in Python.
func GetSecret ¶
GetSecret returns the secret name as a T (see parameters.Get), through a provider built on first use from the default AWS configuration: Python's get_secret.
func GetSecretsByName ¶
func GetSecretsByName[T any](ctx context.Context, names []string, opts ...parameters.Option) (values map[string]T, failed map[string]error, err error)
GetSecretsByName reads several secrets through the default provider: Python's get_secrets_by_name. See GetByName.
func WithFilters ¶
func WithFilters(filters ...types.Filter) parameters.Option
WithFilters narrows GetByName with Secrets Manager filters (by tag, by description), Python's Filters: the names asked for are then matched through a name filter, and only the secrets whose name is exactly one of them are returned.
func WithVersionID ¶
func WithVersionID(id string) parameters.Option
WithVersionID reads the version of the secret with this id instead of the current one (VersionId). Versions are cached apart.
func WithVersionStage ¶
func WithVersionStage(stage string) parameters.Option
WithVersionStage reads the version of the secret with this staging label, AWSPREVIOUS for one, instead of AWSCURRENT (VersionStage). Stages are cached apart.
Types ¶
type Client ¶
type Client interface {
GetSecretValue(ctx context.Context, params *secretsmanager.GetSecretValueInput, optFns ...func(*secretsmanager.Options)) (*secretsmanager.GetSecretValueOutput, error)
BatchGetSecretValue(ctx context.Context, params *secretsmanager.BatchGetSecretValueInput, optFns ...func(*secretsmanager.Options)) (*secretsmanager.BatchGetSecretValueOutput, error)
PutSecretValue(ctx context.Context, params *secretsmanager.PutSecretValueInput, optFns ...func(*secretsmanager.Options)) (*secretsmanager.PutSecretValueOutput, error)
CreateSecret(ctx context.Context, params *secretsmanager.CreateSecretInput, optFns ...func(*secretsmanager.Options)) (*secretsmanager.CreateSecretOutput, error)
}
Client is the part of the Secrets Manager client the provider calls; *secretsmanager.Client satisfies it.
type Provider ¶
type Provider struct {
*parameters.Provider
// contains filtered or unexported fields
}
Provider reads and writes Secrets Manager secrets. It is safe for concurrent use: create it once and share it across invocations.
func FromConfig ¶
FromConfig returns a provider with a Secrets Manager client built from cfg.
func (*Provider) GetByName ¶
func (p *Provider) GetByName(ctx context.Context, names []string, opts ...parameters.Option) (values map[string]string, failed map[string]error, err error)
GetByName returns the string value of several secrets: GetByName[string].
Example ¶
// In a function: secrets.FromConfig(cfg), created once in main.
provider := secrets.New(newFake())
values, failed, err := provider.GetByName(context.Background(), []string{"api-key", "db-password", "missing"})
if err != nil {
panic(err)
}
fmt.Println(values["api-key"], values["db-password"])
fmt.Println("failed:", slices.Sorted(maps.Keys(failed)))
Output: k3y s3cret failed: [missing]
func (*Provider) Set ¶
func (p *Provider) Set(ctx context.Context, name string, value any, opts ...SetOption) (SetResult, error)
Set writes the secret name: Python's set_secret. A string is written as SecretString, a []byte as SecretBinary, anything else as its JSON encoding in SecretString (Python accepts a dict).
As in Python, Set first adds a version to the secret (PutSecretValue) and creates the secret (CreateSecret) only when it does not exist, the cheaper path for a secret that is written often. Failures are a *parameters.SetSecretError.
type SetOption ¶
type SetOption func(*setOptions)
SetOption configures Provider.Set and SetSecret.
func WithClientRequestToken ¶
WithClientRequestToken makes the write idempotent: Secrets Manager creates one version per token, and the token becomes the version id.
func WithCreateSecretInput ¶
func WithCreateSecretInput(edit func(*secretsmanager.CreateSecretInput)) SetOption
WithCreateSecretInput edits the CreateSecret request sent when the secret does not exist yet (description, KMS key, tags): Python's **sdk_options for the creation.
func WithPutSecretValueInput ¶
func WithPutSecretValueInput(edit func(*secretsmanager.PutSecretValueInput)) SetOption
WithPutSecretValueInput edits the PutSecretValue request before it is sent (version stages, for one): Python's **sdk_options for the update.