secrets

package
v0.14.1 Latest Latest
Warning

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

Go to latest
Published: Mar 30, 2026 License: Apache-2.0 Imports: 24 Imported by: 0

Documentation

Overview

Package secrets contains the secrets management logic for ToolHive.

Index

Constants

View Source
const (
	// PasswordEnvVar is the environment variable used to specify the password for encrypting and decrypting secrets.
	PasswordEnvVar = "TOOLHIVE_SECRETS_PASSWORD"

	// ProviderEnvVar is the environment variable used to specify the secrets provider type.
	ProviderEnvVar = "TOOLHIVE_SECRETS_PROVIDER"
)
View Source
const (
	// EnvVarPrefix is the prefix used for environment variable secrets
	EnvVarPrefix = "TOOLHIVE_SECRET_"
)

Variables

View Source
var Err1PasswordReadOnly = fmt.Errorf("1Password secrets manager is read-only, write operations are not supported")

Err1PasswordReadOnly indicates that the 1Password secrets manager is read-only. Is it returned by operations which attempt to change values in 1Password.

View Source
var ErrKeyringNotAvailable = httperr.WithCode(
	errors.New("OS keyring is not available. "+
		"The encrypted provider requires an OS keyring to securely store passwords. "+
		"Please use a different secrets provider (e.g., 1password) "+
		"or ensure your system has a keyring service available"),
	http.StatusBadRequest,
)

ErrKeyringNotAvailable is returned when the OS keyring is not available for the encrypted provider.

View Source
var ErrReservedKeyName = errors.New("secret name is reserved for system use and cannot be managed via user commands")

ErrReservedKeyName is returned when a user command attempts to manage a secret whose name is reserved for system use.

View Source
var ErrSecretsNotSetup = httperr.WithCode(
	errors.New("secrets provider not configured. "+
		"Please run 'thv secret setup' to configure a secrets provider first"),
	http.StatusNotFound,
)

ErrSecretsNotSetup is returned when secrets functionality is used before running setup.

View Source
var ErrUnknownManagerType = httperr.WithCode(
	errors.New("unknown secret manager type"),
	http.StatusBadRequest,
)

ErrUnknownManagerType is returned when an invalid value for ProviderType is specified.

Functions

func GenerateSecurePassword added in v0.0.48

func GenerateSecurePassword() (string, error)

GenerateSecurePassword generates a cryptographically secure random password

func GetSecretsPassword

func GetSecretsPassword(optionalPassword string) ([]byte, bool, error)

GetSecretsPassword returns the password to use for encrypting and decrypting secrets. It returns (password, isNew, error) where isNew indicates if the password was not found in the keyring and needs to be stored after successful validation. If optionalPassword is provided and keyring is not yet setup, it uses that password. Otherwise, it reads from keyring or prompts via stdin. IMPORTANT: When isNew is true, the caller MUST call StoreSecretsPassword after successfully validating the password (e.g., after successful decryption) to persist it in the keyring.

func IsKeyringAvailable added in v0.0.48

func IsKeyringAvailable() bool

IsKeyringAvailable tests if any keyring backend is available

func IsNotFoundError added in v0.2.14

func IsNotFoundError(err error) bool

IsNotFoundError checks if an error indicates a secret was not found

func ResetKeyringSecret

func ResetKeyringSecret() error

ResetKeyringSecret clears out the secret from the keystore (if present).

func SecretParametersToCLI added in v0.0.34

func SecretParametersToCLI(params []SecretParameter) []string

SecretParametersToCLI does the reverse of `ParseSecretParameter` TODO: It may be possible to get rid of this with refactoring.

func StoreSecretsPassword added in v0.8.0

func StoreSecretsPassword(password []byte) error

StoreSecretsPassword stores the password in the keyring. This should only be called after the password has been successfully validated (e.g., after successful decryption of the secrets file).

Types

type EncryptedManager

type EncryptedManager struct {
	// contains filtered or unexported fields
}

EncryptedManager stores secrets in an encrypted file. AES-256-GCM is used for encryption.

func (*EncryptedManager) Capabilities added in v0.0.43

func (*EncryptedManager) Capabilities() ProviderCapabilities

Capabilities returns the capabilities of the encrypted provider.

func (*EncryptedManager) Cleanup

func (e *EncryptedManager) Cleanup() error

Cleanup removes all secrets managed by this manager.

func (*EncryptedManager) DeleteSecret

func (e *EncryptedManager) DeleteSecret(_ context.Context, name string) error

DeleteSecret removes a secret from the secret store.

func (*EncryptedManager) DeleteSecrets added in v0.14.1

func (e *EncryptedManager) DeleteSecrets(_ context.Context, keys []string) error

DeleteSecrets removes all named keys from the store.

func (*EncryptedManager) GetSecret

func (e *EncryptedManager) GetSecret(_ context.Context, name string) (string, error)

GetSecret retrieves a secret from the in-memory cache. It does not re-read the file; secrets written by other processes after construction may not be visible. This is intentional: CLI invocations create a fresh manager per call, and long-running proxies only need their own tokens.

func (*EncryptedManager) ListSecrets

func (e *EncryptedManager) ListSecrets(_ context.Context) ([]SecretDescription, error)

ListSecrets returns a list of all secret names stored in the manager.

func (*EncryptedManager) SetSecret

func (e *EncryptedManager) SetSecret(_ context.Context, name, value string) error

SetSecret stores a secret in the secret store.

type EnvironmentProvider added in v0.2.14

type EnvironmentProvider struct {
	// contains filtered or unexported fields
}

EnvironmentProvider reads secrets from environment variables

func (*EnvironmentProvider) Capabilities added in v0.2.14

func (*EnvironmentProvider) Capabilities() ProviderCapabilities

Capabilities returns the capabilities of the environment provider

func (*EnvironmentProvider) Cleanup added in v0.2.14

func (*EnvironmentProvider) Cleanup() error

Cleanup is a no-op for environment provider

func (*EnvironmentProvider) DeleteSecret added in v0.2.14

func (*EnvironmentProvider) DeleteSecret(_ context.Context, name string) error

DeleteSecret is not supported for environment variables

func (*EnvironmentProvider) DeleteSecrets added in v0.14.1

func (*EnvironmentProvider) DeleteSecrets(_ context.Context, _ []string) error

DeleteSecrets is a no-op for the environment provider (read-only).

func (*EnvironmentProvider) GetSecret added in v0.2.14

func (e *EnvironmentProvider) GetSecret(_ context.Context, name string) (string, error)

GetSecret retrieves a secret from environment variables

func (*EnvironmentProvider) ListSecrets added in v0.2.14

ListSecrets is not supported for environment variables for security reasons

func (*EnvironmentProvider) SetSecret added in v0.2.14

func (*EnvironmentProvider) SetSecret(_ context.Context, name, _ string) error

SetSecret is not supported for environment variables

type FallbackProvider added in v0.2.14

type FallbackProvider struct {
	// contains filtered or unexported fields
}

FallbackProvider wraps a primary provider with environment variable fallback

func (*FallbackProvider) Capabilities added in v0.2.14

func (f *FallbackProvider) Capabilities() ProviderCapabilities

Capabilities returns the primary provider's capabilities

func (*FallbackProvider) Cleanup added in v0.2.14

func (f *FallbackProvider) Cleanup() error

Cleanup delegates to the primary provider

func (*FallbackProvider) DeleteSecret added in v0.2.14

func (f *FallbackProvider) DeleteSecret(ctx context.Context, name string) error

DeleteSecret always uses the primary provider (no env var deletes)

func (*FallbackProvider) DeleteSecrets added in v0.14.1

func (f *FallbackProvider) DeleteSecrets(ctx context.Context, keys []string) error

DeleteSecrets delegates to the primary provider.

func (*FallbackProvider) GetSecret added in v0.2.14

func (f *FallbackProvider) GetSecret(ctx context.Context, name string) (string, error)

GetSecret attempts to get a secret from the primary provider, falling back to environment variables if not found

func (*FallbackProvider) ListSecrets added in v0.2.14

func (f *FallbackProvider) ListSecrets(ctx context.Context) ([]SecretDescription, error)

ListSecrets only lists from the primary provider (env vars not listed in fallback mode for security)

func (*FallbackProvider) SetSecret added in v0.2.14

func (f *FallbackProvider) SetSecret(ctx context.Context, name, value string) error

SetSecret always uses the primary provider (no env var writes)

type OnePasswordManager added in v0.0.32

type OnePasswordManager struct {
	// contains filtered or unexported fields
}

OnePasswordManager manages secrets in 1Password.

func NewOnePasswordManagerWithClient added in v0.0.43

func NewOnePasswordManagerWithClient(client clients.OnePasswordClient) *OnePasswordManager

NewOnePasswordManagerWithClient creates an instance of OnePasswordManager with a provided 1password client. This function is primarily intended for testing purposes.

func (*OnePasswordManager) Capabilities added in v0.0.43

func (*OnePasswordManager) Capabilities() ProviderCapabilities

Capabilities returns the capabilities of the 1Password provider. Read-only provider with listing support.

func (*OnePasswordManager) Cleanup added in v0.0.32

func (*OnePasswordManager) Cleanup() error

Cleanup is not needed for 1Password.

func (*OnePasswordManager) DeleteSecret added in v0.0.32

func (*OnePasswordManager) DeleteSecret(_ context.Context, _ string) error

DeleteSecret is not supported for 1Password unless there is demand for it.

func (*OnePasswordManager) DeleteSecrets added in v0.14.1

func (*OnePasswordManager) DeleteSecrets(_ context.Context, _ []string) error

DeleteSecrets is a no-op for the 1Password provider (read-only).

func (*OnePasswordManager) GetSecret added in v0.0.32

func (o *OnePasswordManager) GetSecret(ctx context.Context, path string) (string, error)

GetSecret retrieves a secret from 1Password.

func (*OnePasswordManager) ListSecrets added in v0.0.32

func (o *OnePasswordManager) ListSecrets(ctx context.Context) ([]SecretDescription, error)

ListSecrets lists the paths to the secrets in 1Password. 1Password has a hierarchy of vaults, items, and fields. Each secret is represented as a path in the format: op://<vault>/<item>/<field>

func (*OnePasswordManager) SetSecret added in v0.0.32

func (*OnePasswordManager) SetSecret(_ context.Context, _, _ string) error

SetSecret is not supported for 1Password unless there is demand for it.

type Provider added in v0.0.32

type Provider interface {
	GetSecret(ctx context.Context, name string) (string, error)
	SetSecret(ctx context.Context, name, value string) error
	DeleteSecret(ctx context.Context, name string) error
	ListSecrets(ctx context.Context) ([]SecretDescription, error)
	// DeleteSecrets removes all named keys. Read-only providers treat this as a no-op.
	DeleteSecrets(ctx context.Context, keys []string) error
	Cleanup() error
	// Capabilities returns what operations this provider supports
	Capabilities() ProviderCapabilities
}

Provider describes a type which can manage secrets.

func CreateSecretProvider added in v0.0.33

func CreateSecretProvider(managerType ProviderType) (Provider, error)

CreateSecretProvider creates the specified type of secrets provider. TODO CREATE function does not actually create anything, refactor or rename

func CreateSecretProviderWithPassword added in v0.0.48

func CreateSecretProviderWithPassword(managerType ProviderType, password string) (Provider, error)

CreateSecretProviderWithPassword creates the specified type of secrets provider with an optional password. If password is empty, it uses the current functionality (read from keyring or stdin). If password is provided, it uses that password and stores it in the keyring if not already setup.

func NewEncryptedManager

func NewEncryptedManager(filePath string, key []byte) (Provider, error)

NewEncryptedManager creates an instance of EncryptedManager.

func NewEnvironmentProvider added in v0.2.14

func NewEnvironmentProvider() Provider

NewEnvironmentProvider creates a new environment variable secrets provider

func NewFallbackProvider added in v0.2.14

func NewFallbackProvider(primary Provider) Provider

NewFallbackProvider creates a new provider with environment variable fallback

func NewOnePasswordManager added in v0.0.32

func NewOnePasswordManager() (Provider, error)

NewOnePasswordManager creates an instance of OnePasswordManager.

func NewScopedProvider added in v0.14.1

func NewScopedProvider(inner Provider, scope SecretScope) Provider

NewScopedProvider creates a Provider that transparently prefixes every key with "__thv_<scope>_", keeping system secrets isolated from user secrets.

func NewUserProvider added in v0.14.1

func NewUserProvider(inner Provider) Provider

NewUserProvider creates a Provider that filters out system-reserved keys so that user-facing callers cannot accidentally read or overwrite internal secrets managed by ScopedProvider.

type ProviderCapabilities added in v0.0.43

type ProviderCapabilities struct {
	CanRead    bool
	CanWrite   bool
	CanDelete  bool
	CanList    bool
	CanCleanup bool
}

ProviderCapabilities represents what operations a secrets provider supports.

func (ProviderCapabilities) IsReadOnly added in v0.0.43

func (pc ProviderCapabilities) IsReadOnly() bool

IsReadOnly returns true if the provider only supports read operations.

func (ProviderCapabilities) IsReadWrite added in v0.0.43

func (pc ProviderCapabilities) IsReadWrite() bool

IsReadWrite returns true if the provider supports both read and write operations.

func (ProviderCapabilities) String added in v0.0.43

func (pc ProviderCapabilities) String() string

String returns a human-readable description of the capabilities.

type ProviderType

type ProviderType string

ProviderType represents an enum of the types of available secrets providers.

const (
	// EncryptedType represents the encrypted secret provider.
	EncryptedType ProviderType = "encrypted"

	// OnePasswordType represents the 1Password secret provider.
	OnePasswordType ProviderType = "1password"

	// EnvironmentType represents the environment variable secret provider
	EnvironmentType ProviderType = "environment"
)

type ScopedProvider added in v0.14.1

type ScopedProvider struct {
	// contains filtered or unexported fields
}

ScopedProvider wraps a Provider and namespaces all operations under a system-managed scope prefix ("__thv_<scope>_"). It is intended for internal callers such as registry auth and workload auth that need isolated key spaces inside the shared secrets store.

func (*ScopedProvider) Capabilities added in v0.14.1

func (s *ScopedProvider) Capabilities() ProviderCapabilities

Capabilities delegates to the underlying provider.

func (*ScopedProvider) Cleanup added in v0.14.1

func (s *ScopedProvider) Cleanup() error

Cleanup removes only the secrets that belong to this scope, leaving all other secrets untouched.

func (*ScopedProvider) DeleteSecret added in v0.14.1

func (s *ScopedProvider) DeleteSecret(ctx context.Context, name string) error

DeleteSecret removes the scoped key for name from the underlying store.

func (*ScopedProvider) DeleteSecrets added in v0.14.1

func (s *ScopedProvider) DeleteSecrets(ctx context.Context, names []string) error

DeleteSecrets removes all named keys under this scope by delegating to the inner provider.

func (*ScopedProvider) GetSecret added in v0.14.1

func (s *ScopedProvider) GetSecret(ctx context.Context, name string) (string, error)

GetSecret retrieves the secret identified by name under this provider's scope.

func (*ScopedProvider) ListSecrets added in v0.14.1

func (s *ScopedProvider) ListSecrets(ctx context.Context) ([]SecretDescription, error)

ListSecrets returns only the entries that belong to this provider's scope, with the "__thv_<scope>_" prefix stripped from each Key so callers receive bare names.

func (*ScopedProvider) SetSecret added in v0.14.1

func (s *ScopedProvider) SetSecret(ctx context.Context, name, value string) error

SetSecret stores value under the scoped key for name.

type SecretDescription added in v0.0.43

type SecretDescription struct {
	// Key is the unique identifier for the secret, used when retrieving it.
	Key string `json:"key"`
	// Description provides a human-readable description of the secret
	// Particularly useful for 1password.
	// May be empty if no description is available.
	Description string `json:"description"`
}

SecretDescription is returned by `ListSecrets`.

type SecretParameter

type SecretParameter struct {
	Name   string `json:"name"`
	Target string `json:"target"`
}

SecretParameter represents a parsed `--secret` parameter.

func ParseSecretParameter

func ParseSecretParameter(parameter string) (SecretParameter, error)

ParseSecretParameter creates an instance of SecretParameter from a string. Expected format: `<Name>,target=<Target>`.

func (SecretParameter) ToCLIString added in v0.3.9

func (sp SecretParameter) ToCLIString() string

ToCLIString converts a SecretParameter to CLI format string

type SecretScope added in v0.14.1

type SecretScope string

SecretScope is the type for system-managed secret scope identifiers.

Invariants that every SecretScope value MUST satisfy:

  • Non-empty: an empty scope would produce the prefix "__thv__", which is ambiguous and cannot be reliably stripped.
  • No underscores: the key format is "__thv_<scope>_<name>"; an underscore inside the scope would make it impossible to determine where the scope ends and the name begins.

All constants declared in this package (ScopeRegistry, ScopeWorkloads, ScopeAuth) satisfy these invariants. Custom scopes introduced in the future must be validated against them.

const (
	// SystemKeyPrefix is the prefix used for all system-managed secret keys.
	// Any key starting with this prefix is reserved for internal use.
	// The double-underscore and trailing underscore make it visually distinct
	// and avoid conflicts with backends (e.g. 1Password) that treat "/" as a
	// path separator.
	SystemKeyPrefix = "__thv_"

	// ScopeRegistry is the scope for registry OAuth refresh tokens.
	ScopeRegistry SecretScope = "registry"

	// ScopeWorkloads is the scope for remote workload authentication tokens
	// (OAuth client secrets, bearer tokens, OAuth refresh tokens).
	ScopeWorkloads SecretScope = "workloads"

	// ScopeAuth is reserved for enterprise CLI/Desktop login tokens.
	ScopeAuth SecretScope = "auth"
)

type SetupResult added in v0.0.48

type SetupResult struct {
	ProviderType ProviderType
	Success      bool
	Message      string
	Error        error
}

SetupResult contains the result of a provider setup operation

func ValidateEnvironmentProvider added in v0.2.14

func ValidateEnvironmentProvider(ctx context.Context, provider Provider, result *SetupResult) *SetupResult

ValidateEnvironmentProvider tests environment provider functionality

func ValidateProvider added in v0.0.48

func ValidateProvider(ctx context.Context, providerType ProviderType) *SetupResult

ValidateProvider validates that a provider can be created and performs basic functionality tests

func ValidateProviderWithPassword added in v0.0.48

func ValidateProviderWithPassword(ctx context.Context, providerType ProviderType, password string) *SetupResult

ValidateProviderWithPassword validates that a provider can be created and performs basic functionality tests. If password is provided for encrypted provider, it uses that password instead of reading from stdin.

type UserProvider added in v0.14.1

type UserProvider struct {
	// contains filtered or unexported fields
}

UserProvider wraps a Provider and hides all system-reserved keys from user-facing callers (CLI, API, MCP tool server). Any attempt to read or modify a key that starts with the system prefix is rejected with ErrReservedKeyName.

func (*UserProvider) Capabilities added in v0.14.1

func (u *UserProvider) Capabilities() ProviderCapabilities

Capabilities delegates to the underlying provider.

func (*UserProvider) Cleanup added in v0.14.1

func (u *UserProvider) Cleanup() error

Cleanup removes only user-owned secrets (those that do not start with the system prefix). System secrets are managed independently through their own ScopedProvider.Cleanup calls and must not be touched here.

func (*UserProvider) DeleteSecret added in v0.14.1

func (u *UserProvider) DeleteSecret(ctx context.Context, name string) error

DeleteSecret removes name from the underlying store, or returns ErrReservedKeyName if the name is system-reserved.

func (*UserProvider) DeleteSecrets added in v0.14.1

func (u *UserProvider) DeleteSecrets(ctx context.Context, names []string) error

DeleteSecrets removes all named keys with all-or-nothing semantics: it validates every name in the list before issuing any delete to the underlying store. If any name is system-reserved the entire operation is aborted and ErrReservedKeyName is returned without deleting anything.

func (*UserProvider) GetSecret added in v0.14.1

func (u *UserProvider) GetSecret(ctx context.Context, name string) (string, error)

GetSecret returns the secret for name, or ErrReservedKeyName if the name is a system-reserved key.

func (*UserProvider) ListSecrets added in v0.14.1

func (u *UserProvider) ListSecrets(ctx context.Context) ([]SecretDescription, error)

ListSecrets returns all non-system secrets from the underlying store. Entries whose Key starts with the system prefix are silently omitted.

func (*UserProvider) SetSecret added in v0.14.1

func (u *UserProvider) SetSecret(ctx context.Context, name, value string) error

SetSecret stores value under name, or returns ErrReservedKeyName if the name is system-reserved.

Directories

Path Synopsis
Package aes contains functions for encrypting and decrypting data using AES-GCM
Package aes contains functions for encrypting and decrypting data using AES-GCM
Package clients contains code for connecting to secret provider APIs.
Package clients contains code for connecting to secret provider APIs.
mocks
Package mocks is a generated GoMock package.
Package mocks is a generated GoMock package.
Package keyring provides a composite keyring provider that supports multiple backends.
Package keyring provides a composite keyring provider that supports multiple backends.
Package mocks is a generated GoMock package.
Package mocks is a generated GoMock package.

Jump to

Keyboard shortcuts

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