secrets

package
v1.18.2 Latest Latest
Warning

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

Go to latest
Published: Oct 13, 2026 License: MIT Imports: 15 Imported by: 0

Documentation

Index

Constants

View Source
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.

View Source
const DefaultEnvPrefix = "HERMOD_SECRET_"

DefaultEnvPrefix is where an env secret is read from when no prefix is set.

Variables

This section is empty.

Functions

func ResolveSecret

func ResolveSecret(ctx context.Context, mgr Manager, value string) string

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 AWSConfig

type AWSConfig struct {
	Region string `yaml:"region" json:"region"`
}

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.

func (*AWSSecretsManager) Get

func (m *AWSSecretsManager) Get(ctx context.Context, key string) (string, error)

Get retrieves a secret from AWS Secrets Manager.

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.

func (*AzureKeyVaultManager) Get

func (m *AzureKeyVaultManager) Get(ctx context.Context, key string) (string, error)

Get retrieves a secret from Azure Key Vault.

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

func (c *CachedManager) Get(ctx context.Context, key string) (string, error)

Get answers without a vhost: whatever inner holds globally.

func (*CachedManager) GetScoped added in v1.17.0

func (c *CachedManager) GetScoped(ctx context.Context, vhost, key string) (string, error)

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.

func (*CombinedManager) Get

func (m *CombinedManager) Get(ctx context.Context, key string) (string, error)

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 EnvConfig

type EnvConfig struct {
	Prefix string `yaml:"prefix" json:"prefix"`
}

type EnvManager

type EnvManager struct {
	Prefix string
}

EnvManager resolves secrets from environment variables.

func (*EnvManager) Get

func (m *EnvManager) Get(ctx context.Context, key string) (string, error)

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 Manager

type Manager interface {
	Get(ctx context.Context, key string) (string, error)
}

Manager defines the interface for external secret managers.

func NewManager

func NewManager(ctx context.Context, cfg Config) (Manager, error)

NewManager creates a secret manager based on the provided configuration.

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.

func (*OpenBaoManager) Get

func (m *OpenBaoManager) Get(ctx context.Context, key string) (string, error)

Get retrieves a secret from OpenBao. key format: "path/to/secret" or "path/to/secret:field" If field is not provided, it defaults to "value".

type ScopedManager added in v1.17.0

type ScopedManager interface {
	GetScoped(ctx context.Context, vhost, key string) (string, error)
}

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.

func (*VHostManager) Get added in v1.17.0

func (m *VHostManager) Get(ctx context.Context, key string) (string, error)

Get answers without a vhost: the global manager only.

func (*VHostManager) GetScoped added in v1.17.0

func (m *VHostManager) GetScoped(ctx context.Context, vhost, key string) (string, error)

GetScoped answers key for vhost. A store that fails is an error rather than a fall-through: the global manager may hold a different value under the same name, and handing that one over would be worse than handing over nothing.

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 VaultConfig struct {
	Address string `yaml:"address" json:"address"`
	Token   string `yaml:"token" json:"token"`
	Mount   string `yaml:"mount" json:"mount"`
}

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.

func (*VaultManager) Get

func (m *VaultManager) Get(ctx context.Context, key string) (string, error)

Get retrieves a secret from Vault. key format: "path/to/secret" or "path/to/secret:field" If field is not provided, it defaults to "value".

Jump to

Keyboard shortcuts

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