- go.mod with Wails v2.9.2, x/crypto, go-sqlite3, go-keyring, uuid - cmd/app/main.go: Wails entry point (Nexus Terminal, 1400x900, #1a1a2e) - internal/app/app.go: lifecycle (Startup/Shutdown/DomReady) - internal/models/models.go: full model definitions (Profile, SSHConfig, TelnetConfig, RAWConfig, SessionInfo, KnownHost, AppPreferences, etc.) - internal/models/defaults.go: default values and NewProfile factory - internal/validation/validation.go: thorough field-level validation - frontend/embed.go: embedded frontend assets - Updated existing storage, secrets, config to match new model structure
67 lines
2.2 KiB
Go
67 lines
2.2 KiB
Go
package secrets
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
"github.com/zalando/go-keyring"
|
|
)
|
|
|
|
// KeychainStore attempts to use the OS keychain for secret storage.
|
|
// On macOS this uses the Keychain, on Linux it uses the Secret Service API,
|
|
// and on Windows it uses the Credential Manager.
|
|
//
|
|
// This is the preferred storage method when available. Falls back to
|
|
// the encrypted file-based SecretStore when the keychain is not accessible.
|
|
type KeychainStore struct {
|
|
serviceName string
|
|
}
|
|
|
|
// NewKeychainStore creates a KeychainStore that stores credentials under the
|
|
// given service name in the operating system's native keychain.
|
|
func NewKeychainStore(serviceName string) *KeychainStore {
|
|
return &KeychainStore{serviceName: serviceName}
|
|
}
|
|
|
|
// Available checks whether the OS keychain is accessible by performing a
|
|
// harmless write-then-delete probe. Returns true if the keychain responded
|
|
// without error.
|
|
func (k *KeychainStore) Available() bool {
|
|
// Attempt a round-trip to verify the keychain is usable.
|
|
probeKey := "__nexus_keychain_probe__"
|
|
probeVal := "probe"
|
|
|
|
if err := keyring.Set(k.serviceName, probeKey, probeVal); err != nil {
|
|
return false
|
|
}
|
|
_ = keyring.Delete(k.serviceName, probeKey)
|
|
return true
|
|
}
|
|
|
|
// SetSecret stores a secret in the OS keychain under the configured service
|
|
// name with the given key.
|
|
func (k *KeychainStore) SetSecret(key, value string) error {
|
|
if err := keyring.Set(k.serviceName, key, value); err != nil {
|
|
return fmt.Errorf("keychain: failed to store secret %q: %w", key, err)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// GetSecret retrieves a secret from the OS keychain. Returns an error if the
|
|
// key does not exist or the keychain is inaccessible.
|
|
func (k *KeychainStore) GetSecret(key string) (string, error) {
|
|
val, err := keyring.Get(k.serviceName, key)
|
|
if err != nil {
|
|
return "", fmt.Errorf("keychain: failed to retrieve secret %q: %w", key, err)
|
|
}
|
|
return val, nil
|
|
}
|
|
|
|
// DeleteSecret removes a secret from the OS keychain. Returns an error if the
|
|
// key does not exist or the keychain is inaccessible.
|
|
func (k *KeychainStore) DeleteSecret(key string) error {
|
|
if err := keyring.Delete(k.serviceName, key); err != nil {
|
|
return fmt.Errorf("keychain: failed to delete secret %q: %w", key, err)
|
|
}
|
|
return nil
|
|
}
|