Documentation
¶
Index ¶
- Constants
- func DottedReference(text string) (kind, name string, ok bool)
- func ExpandReferences(ctx context.Context, mgr ScopedManager, vhost, value string) (string, error)
- func ExpandSettings(ctx context.Context, mgr ScopedManager, vhost string, settings map[string]any, ...) (map[string]any, bool, error)
- func ExpandTokenReferences(ctx context.Context, mgr ScopedManager, vhost, value string) (string, error)
- func ExpandTree(ctx context.Context, mgr ScopedManager, vhost string, v any, ...) (out any, changed bool, err error)
- func LookupEnvVar(key string) string
- func ReadEnv(ctx context.Context, mgr ScopedManager, vhost, key string) (string, error)
- func ResolveSecret(ctx context.Context, mgr Manager, value string) string
- func ResolveSecretScoped(ctx context.Context, mgr ScopedManager, vhost, value string) string
- type AWSConfig
- type AWSSecretsManager
- type AzureConfig
- type AzureKeyVaultManager
- type CachedManager
- type CombinedManager
- type Config
- type EnvConfig
- type EnvManager
- type Manager
- type OpenBaoManager
- type ScopedManager
- type VHostManager
- type VHostStore
- type VaultConfig
- type VaultManager
Constants ¶
const AllowUnprefixedEnv = "HERMOD_SECRETS_ALLOW_UNPREFIXED"
AllowUnprefixedEnv, set to true in the operator's own environment, lets a secret with no prefixed variable fall back to its bare name, as every lookup did before. It exists so a deployment can rename its variables without an outage, and it will be removed.
const DefaultEnvPrefix = "HERMOD_SECRET_"
DefaultEnvPrefix is where an env secret is read from when no prefix is set.
const EnvVarPrefix = "HERMOD_ENV_"
EnvVarPrefix is the namespace env references read from the process environment. Only variables the operator deliberately put under it are readable, so a workflow editor reaches HERMOD_ENV_REGION but never HERMOD_JWT_SECRET, a database password or anything else the process holds.
Variables ¶
This section is empty.
Functions ¶
func DottedReference ¶ added in v1.18.4
DottedReference reads the inside of a {{ }} token as the standard spelling, secret.NAME or env.NAME, and returns its kind ("secret" or "env") and name. The kind is case-insensitive. A leading dot makes it a message field, as in {{.after.id}}, and a deeper path (secret.A.b) is not a reference either.
func ExpandReferences ¶ added in v1.18.3
ExpandReferences replaces every secret and env reference in a config value, for the vhost the config belongs to, and leaves every other {{ }} token as it was for whatever resolves the value per message.
It reads, anywhere in the value, the standard spelling
{{secret.NAME}} {{env.NAME}}
and the older ones, which keep working:
{{secret:NAME}} {{secret("NAME")}} {{secret("NAME", "fallback")}}
{{env:NAME}} {{env("NAME")}} {{env("NAME", "fallback")}}
and, as the whole value, secret:NAME. A secret is read from the vhost's secrets and then the global manager; an env reference from the same lookup and then the HERMOD_ENV_ variable (see ReadEnv).
It is one forward pass: a resolved value is never scanned again, so a secret holding "{{secret:OTHER}}" cannot read OTHER. A value that is a JSON object or array has references replaced inside its strings, escaped, so a secret holding a quote leaves it JSON.
A reference that resolves to nothing, with no fallback, is an error naming it -- never its value. A whole value of the legacy secret:NAME form is the exception: it has always passed through unchanged, and still does.
func ExpandSettings ¶ added in v1.18.3
func ExpandSettings(ctx context.Context, mgr ScopedManager, vhost string, settings map[string]any, skip func(key string) bool) (map[string]any, bool, error)
ExpandSettings is ExpandTree for a node's settings map.
func ExpandTokenReferences ¶ added in v1.18.3
func ExpandTokenReferences(ctx context.Context, mgr ScopedManager, vhost, value string) (string, error)
ExpandTokenReferences is ExpandReferences for {{ }} tokens only: a bare secret:NAME is left as text. It is for a workflow node's settings, where that spelling never meant a secret and a Set value may well hold it.
func ExpandTree ¶ added in v1.18.3
func ExpandTree(ctx context.Context, mgr ScopedManager, vhost string, v any, skip func(key string) bool) (out any, changed bool, err error)
ExpandTree is ExpandTokenReferences over a node's settings: every string in v, inside maps and lists to any depth. A value under a key skip reports true is left as it is, with everything beneath it. The tree passed in is never modified; what changed is copied, and changed reports whether anything was.
func LookupEnvVar ¶ added in v1.18.3
LookupEnvVar reads EnvVarPrefix+key from the process environment -- or key itself when it already carries the prefix -- and nothing else.
func ReadEnv ¶ added in v1.18.3
ReadEnv answers an env reference for vhost: the secret manager first, which is what env() has always read, then the HERMOD_ENV_ variable.
func ResolveSecret ¶
ResolveSecret takes a value and if it is marked as a secret (e.g. "secret:KEY" or "{{secret:KEY}}"), it attempts to resolve it using the provided manager.
func ResolveSecretScoped ¶ added in v1.17.0
func ResolveSecretScoped(ctx context.Context, mgr ScopedManager, vhost, value string) string
ResolveSecretScoped is ResolveSecret for a connector that belongs to a vhost: `secret:KEY` and `{{secret:KEY}}` are read from that vhost's secrets first.
Types ¶
type AWSSecretsManager ¶
type AWSSecretsManager struct {
// contains filtered or unexported fields
}
AWSSecretsManager implements secrets.Manager for AWS Secrets Manager.
func NewAWSSecretsManager ¶
func NewAWSSecretsManager(ctx context.Context, region string) (*AWSSecretsManager, error)
NewAWSSecretsManager creates a new AWSSecretsManager.
type AzureConfig ¶
type AzureConfig struct {
VaultURL string `yaml:"vault_url" json:"vault_url"`
}
type AzureKeyVaultManager ¶
type AzureKeyVaultManager struct {
// contains filtered or unexported fields
}
AzureKeyVaultManager implements secrets.Manager for Azure Key Vault.
func NewAzureKeyVaultManager ¶
func NewAzureKeyVaultManager(vaultURL string) (*AzureKeyVaultManager, error)
NewAzureKeyVaultManager creates a new AzureKeyVaultManager.
type CachedManager ¶ added in v1.17.0
type CachedManager struct {
// contains filtered or unexported fields
}
CachedManager remembers what another Manager answered. It is what the expression functions secret() and env() read through.
An expression reads its secrets once per message. Against Vault, OpenBao, AWS or Azure that is a network call per message, and a manager that stops answering would hold every message behind it. So a lookup has a timeout; an answer -- a missing secret included -- is kept for ttl; lookups for one key that miss at the same moment share a single call; and a failure is not kept, so the next message asks again. The keys come from expressions a workflow editor writes, so at most maxKeys are held, and the oldest goes first.
func NewCachedManager ¶ added in v1.17.0
func NewCachedManager(inner Manager, ttl time.Duration, maxKeys int, timeout time.Duration) *CachedManager
NewCachedManager wraps inner. maxKeys below 1 is taken as 1.
func (*CachedManager) Get ¶ added in v1.17.0
Get answers without a vhost: whatever inner holds globally.
func (*CachedManager) GetScoped ¶ added in v1.17.0
GetScoped answers key for vhost. The cache is keyed by both: keyed by name alone, the first vhost to read API_KEY would decide what every other vhost was given until the entry expired.
func (*CachedManager) Invalidate ¶ added in v1.17.0
func (c *CachedManager) Invalidate(vhost, key string)
Invalidate forgets what was cached for one vhost's secret, so a rotation or a deletion is seen by the next message rather than when the entry expires.
type CombinedManager ¶
type CombinedManager struct {
Managers []Manager
}
CombinedManager tries multiple secret managers in order.
type Config ¶
type Config struct {
Type string `yaml:"type" json:"type"` // env, vault, aws, azure, openbao
Vault VaultConfig `yaml:"vault" json:"vault"`
OpenBao VaultConfig `yaml:"openbao" json:"openbao"` // OpenBao uses same config as Vault
AWS AWSConfig `yaml:"aws" json:"aws"`
Azure AzureConfig `yaml:"azure" json:"azure"`
Env EnvConfig `yaml:"env" json:"env"`
}
Config defines the configuration for secret managers.
type EnvManager ¶
type EnvManager struct {
Prefix string
}
EnvManager resolves secrets from environment variables.
func (*EnvManager) Get ¶
Get reads the secret named key from the variable Prefix+key -- or from key itself when it already carries the prefix -- and from nothing else. An empty Prefix means DefaultEnvPrefix.
It used to fall back to os.Getenv(key). Keys reach here from connector configs and expressions, so that fallback let anyone who could edit a workflow read any variable of the process: `secret:HERMOD_JWT_SECRET` in a connector config, env('HERMOD_JWT_SECRET') in a transformation.
type OpenBaoManager ¶
type OpenBaoManager struct {
// contains filtered or unexported fields
}
OpenBaoManager implements secrets.Manager for OpenBao. Since OpenBao is wire-compatible with HashiCorp Vault, we use the same client.
func NewOpenBaoManager ¶
func NewOpenBaoManager(address, token, mount string) (*OpenBaoManager, error)
NewOpenBaoManager creates a new OpenBaoManager.
type ScopedManager ¶ added in v1.17.0
ScopedManager answers a secret for the vhost asking for it.
type VHostManager ¶ added in v1.17.0
type VHostManager struct {
Store VHostStore
Global Manager
}
VHostManager answers a secret from the asking vhost's own store, and from the global manager when that vhost holds none by the name. A vhost can therefore keep its own API_KEY, override a shared one, and still read the HERMOD_SECRET_ variables or Vault entries it read before. It is never answered from another vhost's store.
type VHostStore ¶ added in v1.17.0
type VHostStore interface {
VHostSecret(ctx context.Context, vhost, name string) (value string, found bool, err error)
}
VHostStore reads one secret a vhost holds; found is false when it has none by that name.
type VaultConfig ¶
type VaultManager ¶
type VaultManager struct {
// contains filtered or unexported fields
}
VaultManager implements secrets.Manager for HashiCorp Vault.
func NewVaultManager ¶
func NewVaultManager(address, token, mount string) (*VaultManager, error)
NewVaultManager creates a new VaultManager.