Skip to content

auth: silently fall back to plaintext when keyring is unreachable on login#5181

Open
simonfaltum wants to merge 3 commits intomainfrom
simonfaltum/secure-storage-silent-fallback
Open

auth: silently fall back to plaintext when keyring is unreachable on login#5181
simonfaltum wants to merge 3 commits intomainfrom
simonfaltum/secure-storage-silent-fallback

Conversation

@simonfaltum
Copy link
Copy Markdown
Member

@simonfaltum simonfaltum commented May 5, 2026

Why

Today, when secure storage is selected but the OS keyring is unreachable (no D-Bus on Linux, headless SSH, WSL1, locked keychain that hangs for 3s), databricks auth login errors out and tells the user to set DATABRICKS_AUTH_STORAGE=plaintext. That is a hard wall for users who do not know in advance whether their environment has a working keyring, and the failure typically lands after the user has already completed the browser flow.

The team agreed to aim for security by default, but do not block users when the keyring is not available.

Scope of this PR: silent fallback on the default path, sticky persistence in .databrickscfg, an early-decision UX, and strict honoring of explicit secure choice. Telemetry and the databricks auth storage plaintext command are intentionally out of scope and tracked separately.

Changes

Before: databricks auth login with secure storage on a machine without a keyring fails with an error after OAuth, regardless of how secure was selected.

Now: databricks auth login probes the keyring before opening the browser. The behavior on probe failure depends on whether the user explicitly asked for secure:

  • Default mode (no DATABRICKS_AUTH_STORAGE, no auth_storage in .databrickscfg, no flag): silently fall back to plaintext and persist auth_storage = plaintext to [__settings__] so subsequent commands skip the probe and route directly to the file cache.
  • Explicit secure (env var, config, or override flag): return a clear error. "I want secure" is honored strictly, never silently downgraded.

This avoids the divergence GPT 5.5 review caught: writing the token to file while leaving auth_storage = secure in config would make auth token and bundle commands fail on the next call because they would still resolve to secure and hit the unreachable keyring.

Implementation:

  • storage.ProbeKeyring() performs a write+delete cycle with the existing 3s timeout to detect a usable keyring without leaving stray entries.
  • storage.ResolveStorageModeWithSource() returns the resolved mode plus whether it came from an explicit user choice (override / env / config) versus the default.
  • storage.ResolveCacheForLogin() wraps the resolver. For default-secure + probe failure it falls back and writes config; for explicit-secure + probe failure it returns an error; for any non-secure mode it skips the probe entirely.
  • databrickscfg.SetConfiguredAuthStorage() writes the key under [__settings__], mirroring SetDefaultProfile.
  • cmd/auth/login.go swaps ResolveCache for ResolveCacheForLogin. Read paths (auth token, bundle commands) keep the original keyring error so they do not silently mint plaintext copies of tokens that live in the keyring on another machine.

Test plan

  • Unit: ProbeKeyring success cleans up after itself; Set/Delete error and Set timeout each propagate.
  • Unit: ResolveStorageModeWithSource returns explicit=false for default and explicit=true for override / env / config.
  • Unit: applyLoginFallback falls back and persists auth_storage = plaintext for default-secure + probe fail.
  • Unit: applyLoginFallback returns a "secure storage was requested" error for explicit-secure + probe fail, and does not write config.
  • Unit: resolveCacheForLoginWith errors out for explicit secure (env, config, override) when the probe fails.
  • Unit: SetConfiguredAuthStorage creates the file/section as needed and preserves default_profile.
  • ./task checks clean
  • ./task lint-q 0 issues
  • All cmd/auth, libs/auth/storage, libs/databrickscfg unit tests pass
  • All acceptance/cmd/auth/storage-modes and acceptance/cmd/auth/login acceptance tests still pass

This pull request and its description were written by Isaac.

…login

When secure storage is selected but the OS keyring is unreachable (no D-Bus
on Linux, headless SSH session, locked keychain that hangs), databricks
auth login now silently falls back to plaintext storage and writes
auth_storage = plaintext to .databrickscfg so the choice is sticky for
later commands. Mirrors the behavior of GitHub CLI.

The probe runs before the browser step so users do not complete OAuth
just to fail at the final Store call. Login is the only command that
falls back: read paths (auth token, bundle commands) keep the original
keyring error so they do not silently mint plaintext copies of tokens
that live in the keyring on another machine.

Co-authored-by: Isaac
@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 5, 2026

Approval status: pending

/cmd/auth/ - needs approval

Files: cmd/auth/login.go
Suggested: @tanmay-db
Also eligible: @tejaskochar-db, @mihaimitrea-db, @hectorcast-db, @renaudhartert-db, @parthban-db, @Divyansh-db, @chrisst, @rauchy

/libs/auth/ - needs approval

6 files changed
Suggested: @tanmay-db
Also eligible: @tejaskochar-db, @mihaimitrea-db, @hectorcast-db, @renaudhartert-db, @parthban-db, @Divyansh-db, @chrisst, @rauchy

/libs/databrickscfg/ - needs approval

Files: libs/databrickscfg/ops.go, libs/databrickscfg/ops_test.go
Suggested: @tanmay-db
Also eligible: @tejaskochar-db, @mihaimitrea-db, @hectorcast-db, @renaudhartert-db, @parthban-db, @Divyansh-db, @chrisst, @rauchy

Any maintainer (@andrewnester, @anton-107, @denik, @pietern, @shreyas-goenka, @renaudhartert-db) can approve all areas.
See OWNERS for ownership rules.

@simonfaltum simonfaltum temporarily deployed to test-trigger-is May 5, 2026 09:12 — with GitHub Actions Inactive
@simonfaltum simonfaltum temporarily deployed to test-trigger-is May 5, 2026 09:12 — with GitHub Actions Inactive
Differentiate "I asked for secure" from "the default happens to be secure":
when the user sets DATABRICKS_AUTH_STORAGE=secure or auth_storage = secure
in .databrickscfg, honor it strictly. If the keyring fails the probe, return
a clear error rather than silently downgrading to plaintext.

The silent fallback now applies only when secure was the implicit default
(no override flag, no env var, no config). In that case login still falls
back and persists auth_storage = plaintext so subsequent commands route to
the file cache without re-probing.

Adds ResolveStorageModeWithSource so callers can detect explicit user
choice. Splits the login-time policy into applyLoginFallback so it can be
unit-tested across the (mode, explicit) input space directly.

Co-authored-by: Isaac
@simonfaltum simonfaltum temporarily deployed to test-trigger-is May 5, 2026 11:28 — with GitHub Actions Inactive
@simonfaltum simonfaltum temporarily deployed to test-trigger-is May 5, 2026 11:28 — with GitHub Actions Inactive
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant