Skip to content

Commit 9ae995c

Browse files
committed
feat(kernel): forward identity federation client ID
1 parent 6c5008a commit 9ae995c

7 files changed

Lines changed: 80 additions & 5 deletions

File tree

‎KERNEL_REV‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
0d46716c466897148dfc1d2976ff03bdf097998c
1+
eff8950428f4e6cc9975c663ec919f334962f7d0

‎lib/contracts/IDBSQLClient.ts‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ type AuthOptions =
1414
| {
1515
authType?: 'access-token';
1616
token: string;
17+
/** Kernel backend: selects mandatory SP-wide Workload Identity Federation. */
18+
identityFederationClientId?: string;
1719
}
1820
| {
1921
authType: 'databricks-oauth';
@@ -26,6 +28,8 @@ type AuthOptions =
2628
// U2M flow to `['sql', 'offline_access']` (parity with the Thrift driver's
2729
// `defaultOAuthScopes`), overriding the kernel's bare `all-apis offline_access`.
2830
oauthScopes?: Array<string>;
31+
/** Kernel backend: selects mandatory SP-wide Workload Identity Federation. */
32+
identityFederationClientId?: string;
2933
}
3034
| {
3135
authType: 'custom';

‎lib/kernel/KernelAuth.ts‎

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,9 @@ const DEFAULT_OAUTH_CLIENT_ID = 'databricks-sql-connector';
6161
* everything else (client_id, scopes, callback timeout,
6262
* token_url_override) uses kernel defaults.
6363
*
64+
* A non-empty `identityFederationClientId` selects mandatory SP-wide
65+
* workload-identity token exchange for every auth mode.
66+
*
6467
* The `authMode` string literals MUST match the napi-emitted `AuthMode`
6568
* variant names verbatim (`'Pat'`, `'OAuthM2m'`, `'OAuthU2m'` — napi-rs's
6669
* `#[napi(string_enum)]` without an explicit case option emits the
@@ -212,10 +215,19 @@ export interface KernelProxyOptions {
212215
};
213216
}
214217

218+
export interface KernelFederationOptions {
219+
/**
220+
* SP-wide Workload Identity Federation client id. Omitted selects BYOT /
221+
* account-wide WIF.
222+
*/
223+
identityFederationClientId?: string;
224+
}
225+
215226
export type KernelNativeConnectionOptions = KernelSessionDefaults &
216227
KernelTlsOptions &
217228
KernelHttpOptions &
218229
KernelProxyOptions &
230+
KernelFederationOptions &
219231
(
220232
| {
221233
hostName: string;
@@ -559,7 +571,8 @@ export function buildKernelConnectionOptions(options: ConnectionOptions): Kernel
559571
maxConnections?: number;
560572
} & KernelTlsOptions &
561573
KernelHttpOptions &
562-
KernelProxyOptions = {
574+
KernelProxyOptions &
575+
KernelFederationOptions = {
563576
hostName: options.host,
564577
httpPath: prependSlash(options.path),
565578
// Match the NodeJS Thrift driver, which surfaces INTERVAL columns as
@@ -579,6 +592,11 @@ export function buildKernelConnectionOptions(options: ConnectionOptions): Kernel
579592
...buildKernelProxyOptions(options),
580593
};
581594

595+
const { identityFederationClientId } = options as { identityFederationClientId?: string };
596+
if (identityFederationClientId) {
597+
base.identityFederationClientId = identityFederationClientId;
598+
}
599+
582600
// kernel-only pool sizing; read via cast to match how this function reads the
583601
// other kernel-specific options (TLS) — they live on the internal options
584602
// surface, not the published public `ConnectionOptions` `.d.ts`.

‎native/kernel/index.d.ts‎

Lines changed: 8 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎tests/unit/kernel/auth-m2m.test.ts‎

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,19 @@ describe('KernelAuth + KernelBackend — OAuth M2M auth flow', () => {
4343
});
4444
});
4545

46+
it('forwards a federation client id on M2M auth', () => {
47+
const native = buildKernelConnectionOptions({
48+
host: 'example.cloud.databricks.com',
49+
path: '/sql/1.0/warehouses/abc',
50+
authType: 'databricks-oauth',
51+
oauthClientId: 'client-uuid',
52+
oauthClientSecret: 'dose-fake-secret',
53+
identityFederationClientId: 'federation-client',
54+
});
55+
56+
expect(native.identityFederationClientId).to.equal('federation-client');
57+
});
58+
4659
it('defaults M2M oauthScopes to all-apis (Thrift + kernel parity)', () => {
4760
const native = buildKernelConnectionOptions({
4861
host: 'example.cloud.databricks.com',
@@ -190,6 +203,7 @@ describe('KernelAuth + KernelBackend — OAuth M2M auth flow', () => {
190203
authType: 'databricks-oauth',
191204
oauthClientId: 'client-uuid',
192205
oauthClientSecret: 'dose-fake-secret',
206+
identityFederationClientId: 'federation-client',
193207
});
194208

195209
const session = await backend.openSession({});
@@ -207,6 +221,7 @@ describe('KernelAuth + KernelBackend — OAuth M2M auth flow', () => {
207221
oauthClientId: 'client-uuid',
208222
oauthClientSecret: 'dose-fake-secret',
209223
oauthScopes: ['all-apis'],
224+
identityFederationClientId: 'federation-client',
210225
});
211226

212227
await session.close();

‎tests/unit/kernel/auth-pat.test.ts‎

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,28 @@ describe('KernelAuth — PAT auth options builder', () => {
5353
}
5454
});
5555

56+
it('forwards a federation client id on PAT auth', () => {
57+
const native = buildKernelConnectionOptions({
58+
host: 'example.cloud.databricks.com',
59+
path: '/sql/1.0/warehouses/abc',
60+
token: 'dapi-fake-pat',
61+
identityFederationClientId: 'federation-client',
62+
});
63+
64+
expect(native.identityFederationClientId).to.equal('federation-client');
65+
});
66+
67+
it('omits an empty federation client id', () => {
68+
const native = buildKernelConnectionOptions({
69+
host: 'example.cloud.databricks.com',
70+
path: '/sql/1.0/warehouses/abc',
71+
token: 'dapi-fake-pat',
72+
identityFederationClientId: '',
73+
});
74+
75+
expect(native).not.to.have.property('identityFederationClientId');
76+
});
77+
5678
it('prepends `/` to a path missing the leading slash', () => {
5779
const opts: ConnectionOptions = {
5880
host: 'example.cloud.databricks.com',

‎tests/unit/kernel/auth-u2m.test.ts‎

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,17 @@ describe('KernelAuth + KernelBackend — OAuth U2M auth flow', () => {
4040
});
4141
});
4242

43+
it('forwards a federation client id on U2M auth', () => {
44+
const native = buildKernelConnectionOptions({
45+
host: 'example.cloud.databricks.com',
46+
path: '/sql/1.0/warehouses/abc',
47+
authType: 'databricks-oauth',
48+
identityFederationClientId: 'federation-client',
49+
});
50+
51+
expect(native.identityFederationClientId).to.equal('federation-client');
52+
});
53+
4354
it('defaults U2M oauthScopes to Thrift parity (sql offline_access)', () => {
4455
const native = buildKernelConnectionOptions({
4556
host: 'example.cloud.databricks.com',

0 commit comments

Comments
 (0)