Skip to content

Fix U2M/M2M OAuth for SPOG (unified) AWS hosts#374

Merged
msrathore-db merged 3 commits into
mainfrom
fix/spog-u2m-account-oidc-endpoint
Jun 4, 2026
Merged

Fix U2M/M2M OAuth for SPOG (unified) AWS hosts#374
msrathore-db merged 3 commits into
mainfrom
fix/spog-u2m-account-oidc-endpoint

Conversation

@msrathore-db
Copy link
Copy Markdown
Contributor

@msrathore-db msrathore-db commented Jun 3, 2026

Problem

SPOG / unified hosts — a single *.databricks.com custom URL that fronts workspaces across multiple accounts, addressed with ?o=<workspaceId> — failed OAuth (U2M and M2M) in two ways:

  1. Cloud inference. InferCloudFromHost returned Unknown for bare *.databricks.com hosts, so u2m.NewAuthenticator errored with unhandled cloud type before any OAuth happened.

  2. Endpoint discovery. For AWS/GCP, GetEndpoint discovered the OIDC endpoint by hitting https://<host>/oidc directly. On a SPOG host the discovery doc points at the account-agnostic account-console authorize endpoint (accounts.../oidc/v1/authorize), which mints a token for the caller's default account. The target workspace (owned by a different account) then rejects it with 400 Invalid Token (ext_authz_denied).

The non-SPOG path was unaffected: a dedicated workspace host advertises its own workspace-rooted endpoint, so there was never any account ambiguity.

Fix

  • InferCloudFromHost: classify bare *.databricks.com hosts as AWS. Checked after the Azure (.azuredatabricks.net) and GCP (.gcp.databricks.com) matches so those stay correctly classified.

  • GetEndpoint (AWS/GCP): resolve the OIDC issuer via /.well-known/databricks-config, substituting the {account_id} placeholder, so unified/SPOG hosts use their account-rooted endpoint (https://<host>/oidc/accounts/<accountId>). Normal workspace hosts advertise https://<host>/oidc, so the resolved issuer is identical to before. The resolved issuer is validated (https + recognized Databricks domain + placeholder fully resolved); any failure or unusable value falls back to the previous bare-host issuer, preserving existing behavior.

Azure is unchanged — its account resolution is handled server-side by the host's /oidc/oauth2/v2.0/authorize redirector.

Server contract

/.well-known/databricks-config was verified live on staging: both dogfood.staging.databricks.com (unified) and e2-dogfood.staging.cloud.databricks.com (workspace) return {oidc_endpoint, account_id} with those exact field names; the unified host returns oidc_endpoint: https://<host>/oidc/accounts/{account_id}. (The same host-metadata concept exists in databricks-sdk-go's config package; this driver implements its own minimal resolver against the shipped endpoint.)

Tests

auth/oauth/oauth_test.go: InferCloudFromHost (incl. SPOG hosts and GCP/Azure disambiguation), resolveOIDCIssuer end-to-end via httptest (substitute / workspace-unchanged / empty-account_id / empty-endpoint / non-https / non-databricks-host / 404 / garbage / unreachable), isValidDatabricksIssuer, and fetchHostMetadata failure paths.

End-to-end against staging via the real driver auth paths (no overrides):

Host Auth Result
e2-dogfood…cloud.databricks.com (non-SPOG AWS) U2M
e2-dogfood…cloud.databricks.com (non-SPOG AWS) M2M
dogfood.staging.databricks.com (SPOG AWS) U2M
dogfood.staging.databricks.com (SPOG AWS) M2M
dogfood-spog.staging.azuredatabricks.net (SPOG Azure) U2M

Full unit suite passes with no regressions.

Known limitation

The databricks-config GET (and the existing OIDC discovery) use the default HTTP transport; a connector-supplied WithTransport / WithSkipTLSHostVerify is not threaded into the OAuth endpoint-resolution path. This is pre-existing (the prior oidc.NewProvider discovery had the same behavior) and is left for a follow-up since it requires changing the public authenticator constructors.

SPOG / unified hosts (a single *.databricks.com custom URL that fronts
workspaces across accounts, addressed with ?o=<workspaceId>) failed OAuth
in two ways:

1. InferCloudFromHost returned Unknown for bare *.databricks.com hosts, so
   the U2M authenticator errored ("unhandled cloud type") before any OAuth.

2. For AWS/GCP, GetEndpoint discovered the OIDC endpoint by hitting
   https://<host>/oidc directly. On a SPOG host that resolves to the
   account-agnostic account-console authorize endpoint, which mints a token
   for the caller's default account. The target workspace (owned by a
   different account) then rejects it with 400 "Invalid Token".

Fixes:

- InferCloudFromHost: classify bare *.databricks.com hosts as AWS (checked
  after Azure/GCP so those remain correctly classified).

- GetEndpoint (AWS/GCP): resolve the OIDC issuer via
  /.well-known/databricks-config, substituting the {account_id} placeholder,
  so unified/SPOG hosts use their account-rooted endpoint. Normal workspace
  hosts advertise https://<host>/oidc, so the issuer is identical to before.
  Any failure (absent endpoint, non-200, unparseable, timeout) falls back to
  the previous bare-host issuer, so existing behavior is preserved. This
  mirrors databricks-sdk-go's config host-metadata resolution.

Adds oauth_test.go covering cloud inference (incl. SPOG and the
GCP/Azure disambiguation), {account_id} substitution, and the
databricks-config failure/fallback paths.

Tested end-to-end against staging via the real driver auth paths:
- AWS non-SPOG (e2-dogfood...cloud.databricks.com): U2M and M2M pass.
- AWS SPOG (dogfood.staging.databricks.com): U2M and M2M pass.
- Azure SPOG (dogfood-spog.staging.azuredatabricks.net): U2M passes
  (Azure path unchanged; account resolution handled by the host redirector).
- Full unit suite passes with no regressions.

Co-authored-by: Isaac
Comment thread auth/oauth/oauth.go
client := &http.Client{Timeout: hostConfigTimeout}

meta, ok := fetchHostMetadata(ctx, client, url)
if !ok || meta.OIDCEndpoint == "" {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[HIGH] resolveOIDCIssuer guards only !ok || meta.OIDCEndpoint == ""; it never checks meta.AccountID. If metadata returns oidc_endpoint: ".../accounts/{account_id}" with account_id: "", substituteAccountID (line 98) yields .../accounts/ — an account-less, malformed issuer. Execution has already committed past the fallback here, so oidc.NewProvider fails and GetEndpoint returns a hard error rather than degrading to the bare host.

This directly contradicts this function's own doc comment: "Any failure (… missing field …) falls back to the bare-host issuer."

Fix: when the post-substitution string still contains {account_id} (or OIDCEndpoint has the placeholder while AccountID == ""), return fallback. Flagged independently by the devil's-advocate, test, language, and architecture reviewers.


Posted by code-review-squad · /full-review · feedback: #code-review-squad-feedback

Comment thread auth/oauth/oauth.go Outdated
fallback := fmt.Sprintf("https://%s/oidc", hostName)

url := fmt.Sprintf("https://%s/.well-known/databricks-config", hostName)
client := &http.Client{Timeout: hostConfigTimeout}
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[MEDIUM] &http.Client{Timeout: hostConfigTimeout} has a nil Transport, so it uses http.DefaultTransport — bypassing WithTransport, WithSkipTLSHostVerify (connector.go:378-399), and the driver's PooledTransport. A user behind a corporate proxy (programmatic transport), with a custom CA / mTLS, or with InsecureSkipVerify set in dev will have this fetch fail TLS/connect and silently fall back to bare-host discovery — the exact broken path this PR fixes — with no diagnostic. (Env-var proxies still work; http.DefaultTransport honors HTTPS_PROXY.)

Not a regression: the pre-existing oidc.NewProvider(ctx, …) already uses the default client (no oidc.ClientContext installed). But it does mean the fix is a no-op in exactly the enterprise/dev environments where SPOG is most likely exercised. fetchHostMetadata already takes an injected *http.Client; thread the driver's configured client/transport (or at least cfg.TLSConfig) down through GetEndpoint → resolveOIDCIssuer. This also closes the testability gap on resolveOIDCIssuer.


Posted by code-review-squad · /full-review · feedback: #code-review-squad-feedback

Comment thread auth/oauth/oauth.go

meta, ok := fetchHostMetadata(ctx, client, url)
if !ok || meta.OIDCEndpoint == "" {
return fallback
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[MEDIUM] Every non-200, redirect-to-HTML, malformed JSON, or wrong-account_id response collapses to the same silent bare-host fallback. A genuinely misconfigured SPOG host then re-produces the opaque 400 Invalid Token this PR exists to eliminate, with zero breadcrumb as to why.

The repo already uses zerolog/log in these packages — a log.Debug()/log.Warn() on the fallback path would pay for itself in support time. (security + devil's-advocate)


Posted by code-review-squad · /full-review · feedback: #code-review-squad-feedback

Comment thread auth/oauth/oauth_test.go Outdated
}
}

func TestResolveOIDCIssuer_substitutesAccountID(t *testing.T) {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[MEDIUM] TestResolveOIDCIssuer_substitutesAccountID (and _workspaceHostUnchanged at line 90) are misnamed: they call fetchHostMetadata + substituteAccountID directly and never call resolveOIDCIssuer. So the actual fallback wiring (!ok || OIDCEndpoint == "" → bare host), the URL-format construction, the oidc_endpoint == "" guard, and the empty-account_id case (see the High finding) are all uncovered. TestFetchHostMetadata_failuresFallBack proves failure detection (ok=false), not the fallback string mapping. And GetEndpoint end-to-end — the M2M TokenURL actually coming out account-rooted, the whole point of the PR — is untested.

Suggested fix

add a table-driven resolveOIDCIssuer test against an httptest server covering substitute / unchanged / empty-endpoint-fallback / failure-fallback / empty-account_id. (test + devil's-advocate)

--- Posted by code-review-squad · /full-review · feedback: #code-review-squad-feedback

Comment thread auth/oauth/oauth.go
// For normal workspace hosts this resolves to https://<host>/oidc, identical to
// the previous behavior.
issuerURL := resolveOIDCIssuer(ctx, hostName)
ctx = oidc.InsecureIssuerURLContext(ctx, issuerURL)
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[MEDIUM] oidc.InsecureIssuerURLContext disables the check that the discovered config's issuer field matches the requested issuer. Pre-PR this was benign because issuerURL was always pinned to https://<host>/oidc. Post-PR the issuer is taken from a host-supplied JSON document (line 50) and may point at a different host. Not exploitable without controlling the target host's HTTPS response, but it widens the trust surface and deserves an explicit decision:

  • validate the resolved issuer host against an allowlist of Databricks suffixes before passing to NewProvider, or
  • drop the InsecureIssuerURLContext override on the AWS/GCP path now that the issuer is resolved dynamically, so go-oidc re-enforces issuer matching.

Posted by code-review-squad · /full-review · feedback: #code-review-squad-feedback

Comment thread auth/oauth/oauth.go Outdated
// substituteAccountID resolves the {account_id} placeholder in the advertised
// oidc_endpoint. Workspace hosts have no placeholder and are returned unchanged.
func substituteAccountID(meta hostMetadata) string {
return strings.ReplaceAll(meta.OIDCEndpoint, "{account_id}", meta.AccountID)
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[LOW] substituteAccountID returns meta.OIDCEndpoint verbatim with no scheme check. If the metadata doc returns oidc_endpoint: "http://.../oidc", oidc.NewProvider issues a plaintext discovery GET and the derived authorize/token URLs are HTTP — OAuth traffic in cleartext. The hard-coded fallback is always HTTPS, so this only appears on the new metadata-driven path.

Suggested fix

a one-line strings.HasPrefix(resolved, "https://") guard (fall back otherwise) closes it and matches the stated "fall back on anything unexpected" intent. Gated on controlling the (HTTPS-served) metadata response.

--- Posted by code-review-squad · /full-review · feedback: #code-review-squad-feedback

Comment thread auth/oauth/oauth.go Outdated
fallback := fmt.Sprintf("https://%s/oidc", hostName)

url := fmt.Sprintf("https://%s/.well-known/databricks-config", hostName)
client := &http.Client{Timeout: hostConfigTimeout}
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[LOW] Every AWS/GCP GetEndpoint now makes a synchronous /.well-known/databricks-config call before the existing OIDC discovery, on the connection-setup path. It is bounded only by the fixed 30s hostConfigTimeout — both production callers pass context.Background(), so the caller's deadline doesn't tighten it (though fetchHostMetadata does honor ctx cancellation via NewRequestWithContext). The result is immutable per host but is re-fetched on every authenticator construction with no caching.

Consider: deriving the timeout from the incoming ctx, a tighter default, and memoizing per host. databricks-sdk-go resolves host metadata once per Config and reuses it. (architecture + security + devil's-advocate)


Posted by code-review-squad · /full-review · feedback: #code-review-squad-feedback

@vikrantpuppala
Copy link
Copy Markdown
Collaborator

Code Review Squad — Review

Score: 76/100 — MODERATE RISK

The fix is well-targeted and the fallback design is conservative (any metadata-fetch failure degrades to the historical bare-host issuer), and the InferCloudFromHost change is verified necessary. Reviewers (5/5 delivered) converged on one real correctness gap — empty account_id violates the function's own documented fallback contract — plus a cluster of medium concerns around the new HTTP call ignoring driver transport/TLS config, which can make the fix silently ineffective behind a proxy / custom CA / InsecureSkipVerify. Tests pass but skip resolveOIDCIssuer (the function the PR is named after) and GetEndpoint end-to-end.


Low Findings

Low findings — click to expand

"Mirrors databricks-sdk-go" claim is inaccurate; /.well-known/databricks-config server contract unverified

The devil's-advocate reviewer checked databricks-sdk-go v0.111.0: it does not fetch /.well-known/databricks-config anywhere. Its unified-host path is driven by an explicit Experimental_IsUnifiedHost flag + a configured AccountID, constructing <host>/oidc/accounts/<accountId>/.well-known/oauth-authorization-server; it never auto-discovers the account id. This PR invents a different auto-discovery mechanism.

Two asks: (1) correct the PR description's "Mirrors databricks-sdk-go" wording, and (2) confirm that /.well-known/databricks-config returning {oidc_endpoint, account_id} is a real, shipped server contract with field names matching exactly. If it's a new/unshipped endpoint, the fix is a no-op until the server side lands. This gates whether the PR does anything at all.

Also worth a one-line confirmation (raised by devil's-advocate + security): the AWS-only assumption for bare *.databricks.com — could a GCP or Azure custom/unified domain present as bare *.databricks.com (no .gcp./.azure marker)? If so it would misclassify as AWS. (The strings.Contains vs HasSuffix looseness is pre-existing and was not counted as a finding.)

- Fall back to the bare-host issuer when oidc_endpoint has an {account_id}
  placeholder but account_id is empty (previously produced a malformed
  ".../accounts/" issuer and a hard error, violating the fallback contract).
- Validate the metadata-supplied issuer before use (isValidDatabricksIssuer):
  must be https, on a recognized Databricks domain, with no unresolved
  placeholder. Covers the http:// cleartext case and bounds the trust placed
  in the host-supplied document given InsecureIssuerURLContext disables the
  issuer-match check.
- Log (debug/warn) on every fallback path so a misconfigured SPOG host leaves
  a breadcrumb instead of silently reproducing the opaque 400.
- Inject the *http.Client into resolveOIDCIssuer and bound OIDC discovery with
  the same client (oidc.ClientContext); tighten the timeout 30s -> 10s.
- Tests: drive resolveOIDCIssuer end-to-end via httptest (substitute /
  workspace-unchanged / empty-account_id / empty-endpoint / non-https /
  non-databricks-host / 404 / garbage / unreachable) and add
  isValidDatabricksIssuer coverage.

Co-authored-by: Isaac
@msrathore-db
Copy link
Copy Markdown
Contributor Author

Thanks for the review — addressed in 548e4bf.

[HIGH] empty account_id → malformed issuer / hard error. Fixed. resolveOIDCIssuer now falls back to the bare-host issuer when oidc_endpoint contains the {account_id} placeholder but account_id is empty, and isValidDatabricksIssuer also rejects any string that still contains an unresolved placeholder. Honors the documented fallback contract.

[MED] InsecureIssuerURLContext trust surface (+ [LOW] http scheme). Added isValidDatabricksIssuer: the metadata-supplied issuer must be https, on a recognized Databricks domain (InferCloudFromHost != Unknown), with no unresolved placeholder — else fall back. I kept InsecureIssuerURLContext because for the SPOG case the discovered issuer is legitimately cross-host (accounts.<region>.cloud.databricks.com vs the connection host), so re-enabling go-oidc's issuer-match would break the working path; the allowlist bounds the trust instead. This also closes the cleartext-http:// LOW finding.

[MED] silent fallback / no diagnostics. Added log.Debug/log.Warn (via rs/zerolog/log, as in m2m) on every fallback branch, naming the host and reason.

[MED] tests skip resolveOIDCIssuer / GetEndpoint. Replaced the direct fetchHostMetadata+substituteAccountID tests with a table-driven test that drives resolveOIDCIssuer end-to-end against an httptest.NewTLSServer (substitute / workspace-unchanged / empty-account_id / empty-endpoint / non-https / non-databricks-host / 404 / garbage / unreachable), plus isValidDatabricksIssuer coverage. Full GetEndpoint e2e against a live OIDC server isn't unit-testable (it gates on InferCloudFromHost, which rejects a 127.0.0.1 test host) — that path is covered by the live staging validation in the PR description.

[LOW] latency / timeout / caching. Tightened the timeout 30s→10s and bound OIDC discovery with the same client (oidc.ClientContext). No per-host cache added: GetEndpoint runs once per authenticator construction (the config is cached in the token source), not per request, so it's a one-time setup cost.

[MED] transport/TLS not honored. Acknowledged and, as the review notes, not a regression — the pre-existing oidc.NewProvider discovery already used the default client. The databricks-config GET now goes through the same single client as discovery, so there's one injection point — but actually threading the connector's WithTransport/WithSkipTLSHostVerify requires changing the public authenticator constructors (u2m.NewAuthenticator(host, timeout) is built by the caller, outside the connector), so I've left it as a documented limitation for a follow-up rather than expand this PR's surface. Flagging for your call if you'd prefer it here.

[LOW] "mirrors databricks-sdk-go" wording + contract. Corrected the PR description. I verified the /.well-known/databricks-config contract live (curl) on staging: both dogfood.staging.databricks.com (unified) and e2-dogfood.staging.cloud.databricks.com (workspace) return {oidc_endpoint, account_id} with these exact field names; the unified host returns oidc_endpoint: https://<host>/oidc/accounts/{account_id}. So the server contract is shipped, not hypothetical.

bare *.databricks.com AWS assumption. Azure custom/unified hosts are *.azuredatabricks.net and GCP are *.gcp.databricks.com — both matched earlier in InferCloudFromHost, so they can't fall through to the bare-databricks.com→AWS branch. A bare *.databricks.com unified host is AWS by SPOG design.

@vikrantpuppala
Copy link
Copy Markdown
Collaborator

Code Review Squad — Follow-up on 548e4bf

Re-reviewed against the new commit "Address review: harden databricks-config issuer resolution" and ran the new tests (all pass). Thorough response — the High finding and most Mediums are resolved.

Resolved

  • F1 (empty account_id → malformed issuer) ✅ — new strings.Contains(OIDCEndpoint, accountIDPlaceholder) && AccountID == "" guard returns the fallback, with a dedicated test case.
  • F3 (silent fallback, no log) ✅ — zerolog Debug/Warn lines on every fallback path.
  • F4 (resolveOIDCIssuer/GetEndpoint untested) ✅ — misnamed leaf-tests replaced by TestResolveOIDCIssuer driving the function end-to-end (8 cases) + new TestIsValidDatabricksIssuer.
  • F5 (host-controlled issuer + InsecureIssuerURLContext) ✅ — isValidDatabricksIssuer now allowlists the resolved issuer to a recognized Databricks domain before discovery; the insecure override is retained but bounded, with an explaining comment.
  • F6 (no https:// scheme check) ✅ — isValidDatabricksIssuer requires https, plus a test.
  • F2 / F7 — acknowledged: client transport/TLS deferred as a documented pre-existing limitation (and oidc.ClientContext now reuses the same client); timeout tightened 30s → 10s.

Two items still worth a look

1. (gating) Confirm the /.well-known/databricks-config server contract is real and shipped. databricks-sdk-go (v0.111.0) does not fetch this endpoint — its unified-host path uses an explicit Experimental_IsUnifiedHost flag + configured AccountID. This PR introduces a different auto-discovery mechanism. Please confirm that /.well-known/databricks-config returning {oidc_endpoint, account_id} is a live server contract with exactly those field names; if it's unshipped, the feature is a no-op until the server side lands. (Also worth correcting the "Mirrors databricks-sdk-go" wording in the description.)

2. (new, low) The Contains looseness is now load-bearing for a trust check. isValidDatabricksIssuer calls InferCloudFromHost(u.Hostname()), which uses strings.Contains(host, "databricks.com"). So an issuer host like databricks.com.evil.example would pass the allowlist. This Contains-based matching is pre-existing, but the hardening commit promotes it from cloud-routing to the gate that decides whether to trust a cross-host issuer. Tightening to a suffix match (in InferCloudFromHost, or a HasSuffix check inside isValidDatabricksIssuer) would close it. Low severity — still requires controlling the HTTPS metadata response — but noting it since it's now a trust boundary.

With the hardening commit, the only real gate left is the non-code server-contract confirmation (#1). Nice turnaround.

Re-review by Code Review Squad against 548e4bf.


This comment was generated with GitHub MCP.

The hardening commit made InferCloudFromHost (substring matching) load-bearing
for the cross-host issuer trust decision in isValidDatabricksIssuer, so a host
like "databricks.com.evil.example" would have passed.

Replace the InferCloudFromHost call in the trust gate with isDatabricksHost,
which uses HasSuffix against an explicit list of Databricks DNS suffixes
(case-insensitive). Cloud routing (InferCloudFromHost) is left unchanged.

Tests: add TestIsDatabricksHost and extend TestIsValidDatabricksIssuer /
TestResolveOIDCIssuer with suffix-spoof ("databricks.com.evil.example"),
"-databricks.com", and bare-apex cases, plus the real SPOG/non-SPOG issuer
hosts as positives.

Verified end-to-end against staging over the network (opt-in test, not
committed): GetEndpoint resolves the SPOG host to its account-rooted endpoint
(accounts.staging.cloud.databricks.com/oidc/accounts/<id>/v1/{authorize,token})
and the non-SPOG host to its workspace endpoint, unchanged by the gate.

Co-authored-by: Isaac
@msrathore-db
Copy link
Copy Markdown
Contributor Author

Thanks for the re-review. Both remaining items addressed.

#2 (Contains looseness now a trust boundary). Fixed in ae8bf4d. The trust gate no longer goes through InferCloudFromHost's substring matching — isValidDatabricksIssuer now calls a new isDatabricksHost that does case-insensitive HasSuffix against an explicit Databricks DNS-suffix list. So databricks.com.evil.example, notdatabricks.com, and bare databricks.com are all rejected; the real SPOG/non-SPOG issuer hosts still pass. Cloud routing (InferCloudFromHost) is intentionally left unchanged. New TestIsDatabricksHost + extended TestIsValidDatabricksIssuer/TestResolveOIDCIssuer cover the spoof cases.

#1 (server contract — gating). Verified live, not assumed. curl https://<host>/.well-known/databricks-config on staging returns exactly {oidc_endpoint, account_id, ...}:

  • dogfood.staging.databricks.com (unified) → oidc_endpoint: "https://dogfood.staging.databricks.com/oidc/accounts/{account_id}", account_id: "7a99b43c-...", host_type: "unified".
  • e2-dogfood.staging.cloud.databricks.com (workspace) → oidc_endpoint: "https://e2-dogfood.staging.cloud.databricks.com/oidc", host_type: "workspace".

Field names match the struct exactly. And end-to-end through the real driver the full CUJ works on these hosts (U2M + M2M, table in the PR description). I also ran an opt-in live test of GetEndpoint itself against both hosts under this commit:

SPOG     dogfood.staging.databricks.com            -> https://accounts.staging.cloud.databricks.com/oidc/accounts/7a99b43c-.../v1/authorize
non-SPOG e2-dogfood.staging.cloud.databricks.com   -> https://e2-dogfood.staging.cloud.databricks.com/oidc/v1/authorize

So it is a shipped contract (dev/staging today; prod ramp is tracked separately by the platform team). I corrected the "Mirrors databricks-sdk-go" wording in the PR description — the SDK has the same host-metadata concept in its config package, but this driver implements its own minimal resolver against the live endpoint rather than copying the SDK's flag-based path.

All hermetic unit tests pass; full suite (incl. root package) green with no regressions.

@msrathore-db msrathore-db merged commit 9d711e7 into main Jun 4, 2026
2 of 3 checks passed
@msrathore-db msrathore-db deleted the fix/spog-u2m-account-oidc-endpoint branch June 4, 2026 06:55
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.

2 participants