Documentation
¶
Overview ¶
Package keystore provides secure storage for API keys.
Index ¶
- Constants
- Variables
- func DefaultKeystorePath() string
- type EnvMasterKeySource
- type ErrKeyNotFound
- type FallbackMasterKeySource
- type FileKeystore
- func (f *FileKeystore) Delete(name string) error
- func (f *FileKeystore) Get(name string) (string, error)
- func (f *FileKeystore) IsV2Format() (bool, error)
- func (f *FileKeystore) List() ([]string, error)
- func (f *FileKeystore) MigrateToV2() (MigrateResult, error)
- func (f *FileKeystore) NeedsMigration() (bool, error)
- func (f *FileKeystore) Path() string
- func (f *FileKeystore) Set(name, value string) error
- func (f *FileKeystore) UsesLegacyKey() bool
- func (f *FileKeystore) WithLegacyKeyFallback() *FileKeystore
- type Keystore
- type MasterKeySource
- type MigrateResult
- type PromptMasterKeySource
Constants ¶
const DefaultMasterKeyEnvVar = "IRIS_KEYSTORE_KEY"
DefaultMasterKeyEnvVar is the environment variable name for the master key.
Variables ¶
var ErrMasterKeyRequired = errors.New("master key required for keystore operation")
ErrMasterKeyRequired is returned when a master key is needed but not provided.
Functions ¶
func DefaultKeystorePath ¶
func DefaultKeystorePath() string
DefaultKeystorePath returns the default keystore file path. - macOS/Linux: ~/.iris/keys.enc - Windows: %USERPROFILE%\.iris\keys.enc
Types ¶
type EnvMasterKeySource ¶ added in v0.10.0
type EnvMasterKeySource struct {
EnvVar string
}
EnvMasterKeySource provides the master key from an environment variable.
func (*EnvMasterKeySource) GetMasterKey ¶ added in v0.10.0
func (s *EnvMasterKeySource) GetMasterKey() ([]byte, error)
GetMasterKey returns the master key from the configured environment variable.
type ErrKeyNotFound ¶
type ErrKeyNotFound struct {
Name string
}
ErrKeyNotFound is returned when a requested key does not exist.
func (*ErrKeyNotFound) Error ¶
func (e *ErrKeyNotFound) Error() string
type FallbackMasterKeySource ¶ added in v0.10.0
type FallbackMasterKeySource struct {
Sources []MasterKeySource
}
FallbackMasterKeySource tries multiple sources in order.
func (*FallbackMasterKeySource) GetMasterKey ¶ added in v0.10.0
func (s *FallbackMasterKeySource) GetMasterKey() ([]byte, error)
GetMasterKey tries each source in order until one succeeds.
type FileKeystore ¶
type FileKeystore struct {
// contains filtered or unexported fields
}
FileKeystore implements Keystore using encrypted file storage. Keys are stored in a JSON map encrypted with AES-256-GCM. v2 format uses Argon2id for key derivation from a master key.
func NewFileKeystore ¶
func NewFileKeystore(path string) (*FileKeystore, error)
NewFileKeystore creates a new file-based keystore at the given path. The encryption key is derived from machine-specific data (v1 legacy mode). For production use, prefer NewFileKeystoreWithSource.
func NewFileKeystoreWithSource ¶ added in v0.10.0
func NewFileKeystoreWithSource(path string, source MasterKeySource) (*FileKeystore, error)
NewFileKeystoreWithSource creates a new file-based keystore with a master key source. This is the recommended way to create a keystore for production use.
func (*FileKeystore) Delete ¶
func (f *FileKeystore) Delete(name string) error
Delete removes a key by name.
func (*FileKeystore) Get ¶
func (f *FileKeystore) Get(name string) (string, error)
Get retrieves a value by name.
func (*FileKeystore) IsV2Format ¶ added in v0.10.0
func (f *FileKeystore) IsV2Format() (bool, error)
IsV2Format checks if the keystore file is in v2 format.
func (*FileKeystore) List ¶
func (f *FileKeystore) List() ([]string, error)
List returns all stored key names.
func (*FileKeystore) MigrateToV2 ¶ added in v0.10.0
func (f *FileKeystore) MigrateToV2() (MigrateResult, error)
MigrateToV2 migrates a legacy keystore to v2 format encrypted under this keystore's master key. It handles both v1-format files and v2-format files encrypted with the legacy machine-derived key (requires WithLegacyKeyFallback, which NewKeystore enables automatically). The original file is preserved at <path>.bak before the new one is written. The call is idempotent: an already-current store returns MigrateAlreadyCurrent.
func (*FileKeystore) NeedsMigration ¶ added in v1.0.0
func (f *FileKeystore) NeedsMigration() (bool, error)
NeedsMigration reports whether the store file cannot be decrypted with the current master key alone, meaning it is v1-format or was encrypted under the legacy machine-derived key. Running MigrateToV2 re-encrypts it.
func (*FileKeystore) Path ¶ added in v1.0.0
func (f *FileKeystore) Path() string
Path returns the keystore file path.
func (*FileKeystore) Set ¶
func (f *FileKeystore) Set(name, value string) error
Set stores a key-value pair.
func (*FileKeystore) UsesLegacyKey ¶ added in v1.0.0
func (f *FileKeystore) UsesLegacyKey() bool
UsesLegacyKey reports whether the keystore was opened with the insecure machine-derived v1 key (i.e., no master key source was provided).
func (*FileKeystore) WithLegacyKeyFallback ¶ added in v1.0.0
func (f *FileKeystore) WithLegacyKeyFallback() *FileKeystore
WithLegacyKeyFallback enables reading stores encrypted by older versions: v1-format files and v2-format files keyed with the machine-derived legacy key. Decryption is attempted with the master key first; the legacy key is only tried when that fails. Writes always use the master key, so any Set or Delete transparently re-encrypts the store.
type Keystore ¶
type Keystore interface {
// Set stores a key-value pair.
Set(name, value string) error
// Get retrieves a value by name. Returns error if not found.
Get(name string) (string, error)
// Delete removes a key by name.
Delete(name string) error
// List returns all stored key names.
List() ([]string, error)
}
Keystore defines the interface for secure key storage.
func NewKeystore ¶
NewKeystore creates a new keystore using file-based encrypted storage.
It is master-key aware: when DefaultMasterKeyEnvVar (IRIS_KEYSTORE_KEY) is set, the store is encrypted with that master key (v2 format, Argon2id + AES-256-GCM) and legacy stores written by older versions remain readable via a decryption fallback, so they can be migrated with MigrateToV2 (or transparently on the next write). When the environment variable is not set, it falls back to the legacy machine-derived key (v1 mode), which is convenient for development but predictable; callers can detect this via FileKeystore.UsesLegacyKey.
func NewKeystoreAtPath ¶ added in v1.0.0
NewKeystoreAtPath is like NewKeystore but opens the store at path.
type MasterKeySource ¶ added in v0.10.0
type MasterKeySource interface {
// GetMasterKey returns the master key for encryption/decryption.
// Returns an error if the key cannot be obtained.
GetMasterKey() ([]byte, error)
}
MasterKeySource provides the encryption master key. Implementations can source the key from various places (env var, prompt, etc.).
type MigrateResult ¶ added in v1.0.0
type MigrateResult int
MigrateResult reports the outcome of a MigrateToV2 call.
const ( // MigrateNone means no keystore file existed (or it was empty). MigrateNone MigrateResult = iota // MigrateAlreadyCurrent means the store is already v2-format and // encrypted under the current master key. MigrateAlreadyCurrent // MigrateRekeyed means the store was decrypted (via the master key or the // legacy fallback) and re-encrypted under the current master key. MigrateRekeyed )
type PromptMasterKeySource ¶ added in v0.10.0
PromptMasterKeySource provides the master key via interactive prompt.
func (*PromptMasterKeySource) GetMasterKey ¶ added in v0.10.0
func (s *PromptMasterKeySource) GetMasterKey() ([]byte, error)
GetMasterKey prompts the user for the master key.