feat(cloud): support plaintext file credential store on systems without an OS keychain

› Tenant ID:  fails on headless Linux (containers, VMs, CI) because
no D-Bus Secret Service is available and the keychain resolver refuses
to construct. Add an explicit --insecure-file-store flag that enables
dry's plaintext file fallback (~/.config/safedep/creds.json, mode 0600)
for writing.

Reading is fallback-enabled unconditionally in the credential resolver
chain, logout and setup info, so stored file credentials resolve with
no extra flags and logout can always clear them. On systems with a
working keychain the file provider is never constructed.
This commit is contained in:
Sahilb315
2026-07-15 21:53:55 +05:30
parent 46803f8e70
commit 1cc1520d71
6 changed files with 103 additions and 9 deletions
+9 -2
View File
@@ -16,13 +16,20 @@ import (
// credentials and a close function that releases keychain resources. The
// close function is always non-nil and safe to call regardless of the error.
//
// The insecure file fallback is always enabled for reading so credentials
// stored via `pmg cloud login --insecure-file-store` on systems without an
// OS keychain (headless Linux, containers) resolve without extra flags. On
// systems with a working keychain the file provider is never constructed.
//
// An error is returned when no credentials are available, which callers can
// use to decide whether authenticated cloud features should be enabled.
func ResolveCredentials() (*cloud.Credentials, func() error, error) {
func ResolveCredentials(opts ...cloud.KeychainOption) (*cloud.Credentials, func() error, error) {
var resolvers []cloud.CredentialResolver
var keychainResolver cloud.CloseableCredentialResolver
keychainResolver, err := cloud.NewKeychainCredentialResolver(cloud.CredentialTypeAPIKey)
keychainOpts := append([]cloud.KeychainOption{cloud.WithInsecureFileFallback()}, opts...)
keychainResolver, err := cloud.NewKeychainCredentialResolver(cloud.CredentialTypeAPIKey, keychainOpts...)
if err != nil {
log.Debugf("Keychain credential resolver not available, skipping: %v", err)
} else {