Skip to content

Commit 60adcaf

Browse files
docs(kernel): azure-sp-m2m management token is gated on azure_workspace_resource_id
Correct the wording (bridge docstring/comments, CHANGELOG, CONNECTION_PARAMETERS) to match the kernel: the Azure SP management token + X-Databricks-Azure-Workspace-Resource-Id header are sent only when azure_workspace_resource_id is set (JDBC parity), not always. A workspace-member SP authenticates with the data token alone; the management token is only needed for an RBAC-only SP (Azure role, not a workspace member), which is what the resource id signals. Co-authored-by: Isaac Signed-off-by: eric-wang-1990 <e.wang@databricks.com>
1 parent b121efd commit 60adcaf

3 files changed

Lines changed: 18 additions & 17 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
# Unreleased
44
- Kernel backend (`use_kernel=True`): OAuth U2M with `auth_type="databricks-oauth"` now forwards the connector's `databricks-sql-python` OAuth-app bundle (`client_id` + `sql offline_access` scopes + redirect port) into the kernel, so a bare U2M connection authenticates as `databricks-sql-python` — parity with the Thrift path — instead of inheriting the kernel's own `databricks-sql-connector` default. A caller-supplied `oauth_client_id` (with its coupled `oauth_redirect_port`) is honored, as is a caller-supplied `oauth_scopes`; absent one, the connector default (`sql offline_access`) is forwarded. Note: the kernel binds a single U2M redirect port, so unlike the Thrift path (which tries the full `8020..8024` range) the kernel path uses only one port and does not fall back to the next port if it is already bound — pass `oauth_redirect_port` (with `oauth_client_id`) to pick a free one on a port collision (PECOBLR-4040)
5-
- Kernel backend (`use_kernel=True`): **Azure Entra (Azure AD) service-principal M2M is now supported.** `auth_type="azure-sp-m2m"` forwards `azure_client_id` / `azure_client_secret`; the kernel is the Azure-aware auth core — it builds the Entra v2.0 token endpoint and the `{app_id}/.default` scope, and **auto-discovers the tenant** from the workspace's `/aad/auth` redirect when `azure_tenant_id` is omitted (matching Thrift). The `Authorization` bearer is the Databricks-audience data token; the kernel **always** also sends the Azure SP management token (`X-Databricks-Azure-SP-Management-Token`), matching Thrift, so a service principal with an Azure RBAC role but no workspace membership can authenticate — set `azure_workspace_resource_id` to add the `X-Databricks-Azure-Workspace-Resource-Id` header too. Azure AD **U2M** (`auth_type="azure-oauth"`) is **not** supported on the kernel path — use `auth_type="databricks-oauth"`, whose in-house OAuth browser flow works against Azure workspaces (the workspace federates login to Entra); `azure-oauth` on `use_kernel=True` is rejected with that pointer (PECOBLR-4141; PECOBLR-4120)
5+
- Kernel backend (`use_kernel=True`): **Azure Entra (Azure AD) service-principal M2M is now supported.** `auth_type="azure-sp-m2m"` forwards `azure_client_id` / `azure_client_secret`; the kernel is the Azure-aware auth core — it builds the Entra v2.0 token endpoint and the `{app_id}/.default` scope, and **auto-discovers the tenant** from the workspace's `/aad/auth` redirect when `azure_tenant_id` is omitted (matching Thrift). The `Authorization` bearer is the Databricks-audience data token, which alone authenticates a workspace-member SP. Set `azure_workspace_resource_id` and the kernel also sends the Azure SP management token (`X-Databricks-Azure-SP-Management-Token`) + `X-Databricks-Azure-Workspace-Resource-Id` header (matching the JDBC driver), so a service principal with an Azure RBAC role but no workspace membership can authenticate; omit it and no ARM management-scope token is fetched. Azure AD **U2M** (`auth_type="azure-oauth"`) is **not** supported on the kernel path — use `auth_type="databricks-oauth"`, whose in-house OAuth browser flow works against Azure workspaces (the workspace federates login to Entra); `azure-oauth` on `use_kernel=True` is rejected with that pointer (PECOBLR-4141; PECOBLR-4120)
66

77
# 4.4.0 (2026-07-22)
88
- Raised the minimum supported Python version to 3.10, dropping the end-of-life 3.8/3.9, to update the lockfile and clear CVE-flagged dependencies in the repo (databricks/databricks-sql-python#798)

CONNECTION_PARAMETERS.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ to change without notice.
7878
| `identity_federation_client_id` | `str` ||| `None` | Workload identity / token-federation client id (kernel support added in #910). |
7979
| `experimental_oauth_persistence` | `OAuthPersistence` ||| `None` | **Thrift-only.** The kernel owns its own token lifecycle and does not accept a persistence store. |
8080
| `azure_client_id` / `azure_client_secret` / `azure_tenant_id` | `str` ||| `None` | Azure service-principal (Entra ID M2M), selected by `auth_type="azure-sp-m2m"`. On the kernel path the connector forwards these to the kernel, which owns Azure resolution (Entra v2.0 token endpoint + the Databricks-resource `.default` scope) (#919). **`azure_tenant_id` is optional on the kernel path too** — like Thrift, the kernel auto-discovers it from the workspace's `/aad/auth` redirect when omitted. |
81-
| `azure_workspace_resource_id` | `str` ||| `None` | For `azure-sp-m2m`. The SP **management token** (`X-Databricks-Azure-SP-Management-Token`) is always sent; setting this adds the `X-Databricks-Azure-Workspace-Resource-Id` header too, to authorize an SP that has an Azure RBAC role but is not a workspace member. Works on both the kernel and Thrift paths. |
81+
| `azure_workspace_resource_id` | `str` ||| `None` | For `azure-sp-m2m`. When set, the SP **management token** (`X-Databricks-Azure-SP-Management-Token`) + `X-Databricks-Azure-Workspace-Resource-Id` header are sent, to authorize an SP that has an Azure RBAC role but is not a workspace member. Omit it for a workspace-member SP (the data token authenticates alone; no management token is fetched). Works on both the kernel and Thrift paths. |
8282
| `_use_cert_as_auth` (+ `_tls_client_cert_file`) | `bool` ||| `False` | Authenticate with a TLS client certificate instead of a token. Thrift-only. |
8383
| `username` / `password` | `str` ||| `None` | **Removed.** Basic auth is no longer supported; passing either raises `ValueError`. |
8484

src/databricks/sql/backend/kernel/auth_bridge.py

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,13 @@
3333
Azure service-principal ``azure_client_id`` / ``azure_client_secret`` (plus
3434
optional ``azure_tenant_id`` / ``azure_workspace_resource_id``). The kernel
3535
builds the Entra v2.0 token endpoint and the ``{effective_app_id}/.default``
36-
scope, auto-discovers the tenant from the workspace's ``/aad/auth`` redirect
37-
when ``azure_tenant_id`` is omitted, and always sends the Azure SP
38-
management token (adding the ``X-Databricks-Azure-Workspace-Resource-Id``
39-
header when ``azure_workspace_resource_id`` is set) — matching the Thrift
40-
connector, so an RBAC-only SP can authenticate (PECOBLR-4141).
36+
scope, and auto-discovers the tenant from the workspace's ``/aad/auth``
37+
redirect when ``azure_tenant_id`` is omitted. When
38+
``azure_workspace_resource_id`` is set, the kernel also sends the Azure SP
39+
management token + ``X-Databricks-Azure-Workspace-Resource-Id`` header
40+
(matching the JDBC driver), so an RBAC-only SP — one with an Azure role but
41+
no workspace membership — can authenticate; omit it for a workspace-member
42+
SP (PECOBLR-4141).
4143
4244
``identity_federation_client_id`` is forwarded with whichever auth shape
4345
wins resolution. It selects mandatory SP-wide workload-identity token
@@ -234,11 +236,11 @@ def kernel_auth_kwargs(
234236
# (so connect() is byte-identical between Thrift and use_kernel=True).
235237
# PECOBLR-4141.
236238
#
237-
# The Authorization bearer is the Databricks-audience data token; the kernel
238-
# also always sends the Azure SP management token, and adds the
239-
# X-Databricks-Azure-Workspace-Resource-Id header when
240-
# azure_workspace_resource_id is set — matching the Thrift connector, so an
241-
# RBAC-only SP (Azure role, not a workspace member) can authenticate.
239+
# The Authorization bearer is the Databricks-audience data token, which alone
240+
# authenticates a workspace-member SP. When azure_workspace_resource_id is
241+
# set, the kernel also sends the Azure SP management token +
242+
# X-Databricks-Azure-Workspace-Resource-Id header (matching the JDBC driver),
243+
# so an RBAC-only SP (Azure role, not a workspace member) can authenticate.
242244
if auth_type == "azure-sp-m2m":
243245
azure_client_id = opts.get("azure_client_id")
244246
azure_client_secret = opts.get("azure_client_secret")
@@ -253,11 +255,10 @@ def kernel_auth_kwargs(
253255
"azure_client_secret": azure_client_secret,
254256
}
255257
# Optional passthroughs: the kernel auto-discovers the tenant when
256-
# absent, and always sends the Azure SP management token. When
257-
# azure_workspace_resource_id is set, the kernel adds the
258-
# X-Databricks-Azure-Workspace-Resource-Id header alongside it (for an
259-
# SP with an Azure RBAC role but no workspace membership) — matching the
260-
# Thrift connector.
258+
# absent. When azure_workspace_resource_id is set, the kernel sends the
259+
# Azure SP management token + X-Databricks-Azure-Workspace-Resource-Id
260+
# header (for an SP with an Azure RBAC role but no workspace membership)
261+
# — matching the JDBC driver; omit it for a workspace-member SP.
261262
azure_tenant_id = opts.get("azure_tenant_id")
262263
if azure_tenant_id:
263264
kwargs["azure_tenant_id"] = azure_tenant_id

0 commit comments

Comments
 (0)