Fix auth profiles misclassifying SPOG hosts as workspace configs#4929
Fix auth profiles misclassifying SPOG hosts as workspace configs#4929mihaimitrea-db wants to merge 6 commits intomainfrom
auth profiles misclassifying SPOG hosts as workspace configs#4929Conversation
SPOG hosts (e.g. db-deco-test.gcp.databricks.com) don't match the accounts.* URL prefix, so ConfigType() classifies them as WorkspaceConfig. This causes `auth profiles` to validate with CurrentUser.Me instead of Workspaces.List, which fails for account-scoped SPOG profiles. Use the resolved DiscoveryURL from .well-known/databricks-config to detect SPOG hosts with account-scoped OIDC, matching the routing logic in auth.AuthArguments.ToOAuthArgument(). Also add a fallback for legacy profiles with Experimental_IsUnifiedHost where .well-known is unreachable.
Approval status: pending
|
simonfaltum
left a comment
There was a problem hiding this comment.
Review (multi-agent swarm: Isaac + Cursor, cross-reviewed)
Overall the fix is correct and well-targeted. The routing logic properly mirrors ToOAuthArgument(), and the tests are thorough. A few suggestions below, nothing blocking.
Summary of findings
| # | Severity | Finding | File |
|---|---|---|---|
| 1 | suggestion | Legacy fallback ignores workspace_id |
profiles.go:77-82 |
| 2 | suggestion | Logic duplication with arguments.go |
profiles.go:61-75 |
| 3 | suggestion | Misleading test name | profiles_test.go:224 |
| 4 | nitpick | Tests don't prove which validation branch ran | profiles_test.go:85 |
| 5 | nitpick | Unused wantConfigCloud test field |
profiles_test.go:123 |
| 6 | suggestion | Missing negative test case | profiles_test.go |
| 7 | pass | Go code structure checklist | all files |
See inline comments for details.
cmd/auth/profiles.go
Outdated
| // Legacy backward compat: profiles with Experimental_IsUnifiedHost where | ||
| // .well-known is unreachable (so DiscoveryURL is empty). Matches the | ||
| // fallback in auth.AuthArguments.ToOAuthArgument(). | ||
| if configType == config.InvalidConfig && cfg.Experimental_IsUnifiedHost && cfg.AccountID != "" { | ||
| configType = config.AccountConfig | ||
| } |
There was a problem hiding this comment.
suggestion: This legacy fallback always forces AccountConfig regardless of workspace_id. In arguments.go:80-81, ignoring workspace_id is intentional because unified OAuth routing is always account-scoped. But here you're choosing a validation strategy, not an OAuth flow. MatchWorkspaceProfiles in profiler.go treats any non-none workspace_id as workspace-scoped.
If a legacy experimental_is_unified_host profile has a real workspace_id and .well-known is unreachable, this would validate it with Workspaces.List instead of CurrentUser.Me. That said, the combination of Experimental_IsUnifiedHost + real workspace_id is unlikely in practice since workspace-scoped SPOG came after the legacy flag era.
Consider either:
- Adding the same workspace_id branching here as in the discovery block above, or
- Adding a comment explaining why it's intentionally omitted
| configType := cfg.ConfigType() | ||
| isAccountScopedOIDC := cfg.DiscoveryURL != "" && strings.Contains(cfg.DiscoveryURL, "/oidc/accounts/") | ||
| if configType != config.AccountConfig && cfg.AccountID != "" && isAccountScopedOIDC { | ||
| if cfg.WorkspaceID != "" && cfg.WorkspaceID != auth.WorkspaceIDNone { | ||
| configType = config.WorkspaceConfig | ||
| } else { | ||
| configType = config.AccountConfig | ||
| } | ||
| } |
There was a problem hiding this comment.
suggestion (follow-up): The SPOG detection heuristic (DiscoveryURL contains /oidc/accounts/ + IsUnifiedHost fallback) is now duplicated between here and libs/auth/arguments.go:69-82. The cross-referencing comments help, but if the routing logic changes in one place the other can drift.
Consider extracting a shared helper in libs/auth/ in a follow-up, e.g.:
func ResolveConfigType(cfg *config.Config) config.ConfigType { ... }Not blocking for this PR since the logic is simple and well-documented.
There was a problem hiding this comment.
This would be good to have. Bonus points that it moves some of the logic form the SDK to the CLI.
cmd/auth/profiles_test.go
Outdated
| } | ||
|
|
||
| func TestProfileLoadClassicAccountHost(t *testing.T) { | ||
| // Verify that a host with account-scoped OIDC from discovery is validated |
There was a problem hiding this comment.
suggestion: This test name says "classic account host" but the httptest.Server URL (e.g. http://127.0.0.1:PORT) doesn't match the accounts.* prefix, so ConfigType() won't return AccountConfig for the classic-host reason. This actually exercises the SPOG discovery override path (same as TestProfileLoadSPOGConfigType).
Consider renaming to something like TestProfileLoadSPOGAccountWithDiscovery, or updating the comment to acknowledge that classic accounts.* behavior can't easily be tested with httptest and this serves as a supplementary SPOG case.
cmd/auth/profiles_test.go
Outdated
| // newProfileTestServer creates a mock server for profile validation tests. | ||
| // It serves /.well-known/databricks-config with the given OIDC shape and | ||
| // responds to the workspace/account validation API endpoints. | ||
| func newProfileTestServer(t *testing.T, accountScoped bool, accountID string) *httptest.Server { |
There was a problem hiding this comment.
nitpick: Both the workspace and account validation endpoints (/api/2.0/preview/scim/v2/Me and /api/2.0/accounts/{id}/workspaces) return success, so Valid == true doesn't prove which branch was taken. Consider making the "wrong" endpoint return an error for each test case to prove routing correctness.
suggestion: Also consider adding a negative test case where .well-known returns 404, account_id is set, Experimental_IsUnifiedHost is false, to verify the profile stays as WorkspaceConfig (proving the override doesn't trigger accidentally).
- Add workspace_id branching to legacy IsUnifiedHost fallback - Rename TestProfileLoadClassicAccountHost to TestProfileLoadSPOGAccountWithDiscovery - Extract hasWorkspace variable to deduplicate condition - Add negative test: no discovery + account_id stays WorkspaceConfig - Fix misleading mock server comments
Summary
ConfigType()classifies hosts by URL prefix (accounts.*→ account, everything else → workspace). SPOG hosts don't match theaccounts.*prefix, so they were misclassified asWorkspaceConfigand validated withCurrentUser.Me, which fails on account-scoped SPOG hosts.DiscoveryURLfrom/.well-known/databricks-configto detect SPOG hosts with account-scoped OIDC (contains/oidc/accounts/), matching the routing logic inauth.AuthArguments.ToOAuthArgument()and the approach from Fix auth logout failing to clear token for workspace profiles with account ID #4853.experimental_is_unified_hostwhere.well-knownis unreachable.Why not just check
account_id?Since #4809,
runHostDiscoverypopulatesaccount_idon every workspace profile from the.well-knownendpoint. A regular workspace profile now routinely carriesaccount_id. The only reliable discriminator is theoidc_endpointshape from.well-known, resolved at runtime (as established in #4853).Test plan
TestProfileLoadSPOGConfigType— table-driven with mock HTTP servers covering SPOG account, SPOG workspace, SPOG withworkspace_id=none, and classic workspace with discovery-populatedaccount_id.TestProfileLoadUnifiedHostFallback—experimental_is_unified_hostprofile with unreachable.well-knownfalls back to account validation.TestProfileLoadClassicAccountHost— classic account-scoped OIDC host.cmd/auth/profiles/spog-account— end-to-end: SPOG profile withworkspace_id=noneshowsvalid:true.go test ./cmd/authandgo test ./acceptance -run TestAccept/cmd/auth/profilespass.