Skip to content

Commit a01ac02

Browse files
committed
Address codex review on PinSecureMode
Two findings: 1. The persist failure was logged at debug, which silently weakens the stated pin-on-success guarantee: login succeeds, the keyring write succeeds, but auth_storage = secure is never persisted. A later default-secure read with a transient keyring probe failure would then fall back to plaintext, undoing the protection the pin was supposed to provide. Promote to log.Warnf so the user sees the failure during login and can investigate (file permissions, etc.). Login is still not blocked: pinning is best-effort. 2. PinSecureMode re-resolved the storage mode with StorageModeUnknown, so a caller-supplied override was invisible to the source check. The function's doc said "No-op when the user already chose a mode explicitly", but only env and config were detected; an override secure mode would still pin auth_storage = secure to config, silently turning an ephemeral per-invocation choice into a persistent one. No caller passes a non-empty override today, so the bug was dormant, but fix it before someone wires up a flag and notices the behavior. PinSecureMode now takes an override StorageMode parameter, and the three call sites (main login, discoveryLogin, runInlineLogin) pass storage.StorageModeUnknown explicitly. New table-driven case covers the override path. Co-authored-by: Isaac
1 parent a15feae commit a01ac02

4 files changed

Lines changed: 31 additions & 14 deletions

File tree

cmd/auth/login.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -298,7 +298,7 @@ a new profile is created.
298298
// Lock secure mode in after a successful keyring write so a later
299299
// transient keyring probe failure cannot silently demote this user
300300
// to plaintext.
301-
storage.PinSecureMode(ctx, mode)
301+
storage.PinSecureMode(ctx, mode, storage.StorageModeUnknown)
302302

303303
// At this point, an OAuth token has been successfully minted and stored
304304
// in the CLI cache. The rest of the command focuses on:
@@ -639,7 +639,7 @@ func discoveryLogin(ctx context.Context, in discoveryLoginInputs) error {
639639
if err := persistentAuth.Challenge(); err != nil {
640640
return discoveryErr("login via login.databricks.com failed", err)
641641
}
642-
storage.PinSecureMode(ctx, in.mode)
642+
storage.PinSecureMode(ctx, in.mode, storage.StorageModeUnknown)
643643

644644
discoveredHost := arg.GetDiscoveredHost()
645645
if discoveredHost == "" {

cmd/auth/token.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -433,7 +433,7 @@ func runInlineLogin(ctx context.Context, profiler profile.Profiler, tokenCache c
433433
if err = persistentAuth.Challenge(); err != nil {
434434
return "", nil, err
435435
}
436-
storage.PinSecureMode(ctx, mode)
436+
storage.PinSecureMode(ctx, mode, storage.StorageModeUnknown)
437437

438438
clearKeys := oauthLoginClearKeys()
439439
clearKeys = append(clearKeys, databrickscfg.ExperimentalIsUnifiedHostKey)

libs/auth/storage/cache.go

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -248,14 +248,20 @@ func persistPlaintextFallback(ctx context.Context) {
248248
// the user to plaintext.
249249
//
250250
// No-op when mode is not secure or when the user already chose a mode
251-
// explicitly. Best-effort: persistence failures are logged at debug and
252-
// never block login. Concurrent logins racing this write is benign because
253-
// both write the same value.
254-
func PinSecureMode(ctx context.Context, mode StorageMode) {
251+
// explicitly via override, env var, or config. override must be the same
252+
// value the caller passed to ResolveCacheForLogin so the source check sees
253+
// the caller's intent rather than re-resolving without it.
254+
//
255+
// Persistence failures are logged at warn: they do not block login, but
256+
// the user should know the pin did not happen, since a later transient
257+
// keyring failure could then silently route a default-secure user to
258+
// plaintext. Concurrent logins racing this write is benign because both
259+
// write the same value.
260+
func PinSecureMode(ctx context.Context, mode, override StorageMode) {
255261
if mode != StorageModeSecure {
256262
return
257263
}
258-
_, source, err := ResolveStorageModeWithSource(ctx, StorageModeUnknown)
264+
_, source, err := ResolveStorageModeWithSource(ctx, override)
259265
if err != nil {
260266
log.Debugf(ctx, "pin secure mode: resolve: %v", err)
261267
return
@@ -265,6 +271,6 @@ func PinSecureMode(ctx context.Context, mode StorageMode) {
265271
}
266272
configPath := env.Get(ctx, "DATABRICKS_CONFIG_FILE")
267273
if err := databrickscfg.SetConfiguredAuthStorage(ctx, string(StorageModeSecure), configPath); err != nil {
268-
log.Debugf(ctx, "persist auth_storage=secure pin failed: %v", err)
274+
log.Warnf(ctx, "could not persist auth_storage=secure to %s: %v. Future commands may need DATABRICKS_AUTH_STORAGE=secure to keep using the OS keyring.", configPath, err)
269275
}
270276
}

libs/auth/storage/cache_test.go

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -386,6 +386,7 @@ func TestPinSecureMode(t *testing.T) {
386386
cases := []struct {
387387
name string
388388
mode StorageMode
389+
override StorageMode
389390
envValue string
390391
configBody string
391392
wantWritten string
@@ -412,6 +413,16 @@ func TestPinSecureMode(t *testing.T) {
412413
configBody: "[__settings__]\nauth_storage = secure\n",
413414
wantWritten: "secure",
414415
},
416+
{
417+
// The override signal is per-invocation, so persisting it to
418+
// config would silently turn an ephemeral choice into a
419+
// persistent one. Honor the caller's explicit override by
420+
// no-op'ing the pin.
421+
name: "secure from override is a no-op",
422+
mode: StorageModeSecure,
423+
override: StorageModeSecure,
424+
wantWritten: "",
425+
},
415426
}
416427

417428
for _, tc := range cases {
@@ -426,7 +437,7 @@ func TestPinSecureMode(t *testing.T) {
426437
ctx = env.Set(ctx, EnvVar, tc.envValue)
427438
}
428439

429-
PinSecureMode(ctx, tc.mode)
440+
PinSecureMode(ctx, tc.mode, tc.override)
430441

431442
got, err := databrickscfg.GetConfiguredAuthStorage(ctx, configPath)
432443
require.NoError(t, err)
@@ -440,13 +451,13 @@ func TestPinSecureMode_IsIdempotent(t *testing.T) {
440451
ctx := t.Context()
441452
configPath := env.Get(ctx, "DATABRICKS_CONFIG_FILE")
442453

443-
PinSecureMode(ctx, StorageModeSecure)
454+
PinSecureMode(ctx, StorageModeSecure, StorageModeUnknown)
444455
first, err := databrickscfg.GetConfiguredAuthStorage(ctx, configPath)
445456
require.NoError(t, err)
446457
require.Equal(t, "secure", first)
447458

448459
// Second call should see source=Config and skip the write.
449-
PinSecureMode(ctx, StorageModeSecure)
460+
PinSecureMode(ctx, StorageModeSecure, StorageModeUnknown)
450461
second, err := databrickscfg.GetConfiguredAuthStorage(ctx, configPath)
451462
require.NoError(t, err)
452463
assert.Equal(t, "secure", second)
@@ -461,8 +472,8 @@ func TestPinSecureMode_PersistFailureIsSwallowed(t *testing.T) {
461472
configPath := filepath.Join(t.TempDir(), "no-such-dir", ".databrickscfg")
462473
t.Setenv("DATABRICKS_CONFIG_FILE", configPath)
463474

464-
// Must not panic or block; failures are logged at debug.
465-
PinSecureMode(ctx, StorageModeSecure)
475+
// Must not panic or block; failure surfaces in the warn log.
476+
PinSecureMode(ctx, StorageModeSecure, StorageModeUnknown)
466477

467478
// The persist failure must not have produced any file.
468479
_, err := os.Stat(configPath)

0 commit comments

Comments
 (0)