Documentation
¶
Overview ¶
Package keychain provides cross-platform secure storage for secrets. - macOS: System Keychain stores DEK (Data Encryption Key), data encrypted with AES-256-GCM - Linux: File-based DEK storage with AES-256-GCM encryption - Windows: DPAPI + Registry storage
Index ¶
- Constants
- Variables
- func CleanupLegacyBackup(configDir string) error
- func Exists(service, account string) bool
- func Get(service, account string) (string, error)
- func HasLegacyData(configDir string) bool
- func IsDEKMissing(err error) bool
- func IsUnavailable(err error) bool
- func NewUnavailableError(op string, err error) error
- func Remove(service, account string) error
- func Set(service, account, data string) error
- func StorageDir(service string) string
- type Diagnostic
- type KeychainAccess
- type MigrationResult
- type UnavailableError
Constants ¶
const ( // Service is the unified keychain service name for all secrets. Service = "dws-cli" // AccountToken is the account key for storing auth token data. AccountToken = "auth-token" // StorageDirEnv overrides the on-disk keychain storage root on // platforms that use file-backed storage (macOS, Linux). It is // intended for tests that need to isolate keychain state from the // real user environment and from sibling test packages running in // parallel. When empty, the platform default applies. StorageDirEnv = "DWS_KEYCHAIN_DIR" // DisableKeychainEnv opts the macOS implementation out of system // Keychain access for the DEK, falling back to a file-based DEK // (same scheme as Linux). Intended for sandboxed runtimes where // Keychain APIs are blocked (e.g. Codex App). This weakens the // at-rest protection — DEK and ciphertext live in the same // directory — and is therefore opt-in. DisableKeychainEnv = "DWS_DISABLE_KEYCHAIN" )
Variables ¶
var ErrDEKMissing = errors.New("dek missing")
ErrDEKMissing means encrypted local data may exist, but the Data Encryption Key needed to decrypt it is missing. Read paths must not create a new DEK, because a fresh key cannot decrypt existing ciphertext.
Functions ¶
func CleanupLegacyBackup ¶
CleanupLegacyBackup removes the backup file created during migration. Call this after confirming the new keychain storage works correctly.
func Get ¶
Get retrieves a value from the keychain. Returns empty string and nil error if the entry does not exist.
func HasLegacyData ¶
HasLegacyData checks if legacy .data file exists.
func IsDEKMissing ¶ added in v1.0.51
func IsUnavailable ¶ added in v1.0.51
func NewUnavailableError ¶ added in v1.0.51
func StorageDir ¶
StorageDir returns the storage directory for a given service name. Follows XDG Base Directory Specification: ~/.local/share/<service>. When the DWS_KEYCHAIN_DIR environment variable is set (used by tests for isolation), the storage root is taken from that env var instead.
Types ¶
type Diagnostic ¶ added in v1.0.51
type Diagnostic struct {
OK bool `json:"ok"`
Reason string `json:"reason,omitempty"`
Message string `json:"message"`
Hint string `json:"hint,omitempty"`
Detail map[string]string `json:"detail,omitempty"`
}
Diagnostic is a read-only health report for the platform keychain backend. It never mutates credentials, DEKs, or OS keychain settings.
func Diagnose ¶ added in v1.0.51
func Diagnose() Diagnostic
type KeychainAccess ¶
type KeychainAccess interface {
Get(service, account string) (string, error)
Set(service, account, value string) error
Remove(service, account string) error
}
KeychainAccess abstracts keychain Get/Set/Remove for dependency injection.
type MigrationResult ¶
type MigrationResult struct {
Migrated bool // true if migration was performed
FromPath string // source file path
BackupPath string // backup file path (if migrated)
Error error // error if migration failed
NeedRelogin bool // true if user needs to re-login
}
MigrationResult contains the result of a migration attempt.
func MigrateFromLegacy ¶
func MigrateFromLegacy(configDir string) *MigrationResult
MigrateFromLegacy attempts to migrate from the legacy MAC-based encryption to the new keychain-based storage. It: 1. Checks if legacy .data file exists 2. Tries to decrypt with MAC address 3. Re-encrypts and stores in keychain 4. Backs up the old file
If the keychain already has data, migration is skipped. If the legacy file doesn't exist, migration is skipped. If decryption fails (wrong MAC/corrupted), returns NeedRelogin=true.
type UnavailableError ¶ added in v1.0.51
type UnavailableError struct {
}
UnavailableError marks failures where the platform keychain itself could not be reached, unlocked, or created. Callers can surface a diagnostic instead of treating the result as a normal missing credential.
func (*UnavailableError) Error ¶ added in v1.0.51
func (e *UnavailableError) Error() string
func (*UnavailableError) Unwrap ¶ added in v1.0.51
func (e *UnavailableError) Unwrap() error