@dbx-tools/auth 0.9.31 → 0.9.36
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +49 -97
- package/index.ts +8 -26
- package/lib/index.d.ts +8 -26
- package/lib/index.js +6 -22
- package/lib/src/{databricks-cli.d.ts → _databricks-cli.d.ts} +3 -7
- package/lib/src/_databricks-cli.js +172 -0
- package/lib/src/_errors.d.ts +5 -0
- package/lib/src/_errors.js +10 -0
- package/lib/src/{lifecycle.d.ts → _lifecycle.d.ts} +5 -5
- package/lib/src/_lifecycle.js +214 -0
- package/lib/src/_logging.d.ts +1 -1
- package/lib/src/_logging.js +2 -2
- package/lib/src/{personal-access-token.d.ts → _personal-access-token.d.ts} +1 -1
- package/lib/src/_personal-access-token.js +30 -0
- package/lib/src/_profile-config.d.ts +43 -0
- package/lib/src/_profile-config.js +443 -0
- package/lib/src/{service-principal.d.ts → _service-principal.d.ts} +1 -1
- package/lib/src/_service-principal.js +69 -0
- package/lib/src/{storage.d.ts → _storage.d.ts} +4 -6
- package/lib/src/_storage.js +94 -0
- package/lib/src/_types.d.ts +40 -0
- package/lib/src/_types.js +2 -0
- package/lib/src/client.d.ts +30 -0
- package/lib/src/client.js +223 -0
- package/lib/src/config.d.ts +36 -0
- package/lib/src/config.js +15 -0
- package/lib/src/profile.d.ts +11 -0
- package/lib/src/profile.js +21 -0
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/package.json +34 -10
- package/src/{databricks-cli.ts → _databricks-cli.ts} +20 -109
- package/src/_errors.ts +11 -0
- package/src/{lifecycle.ts → _lifecycle.ts} +24 -48
- package/src/_logging.ts +2 -2
- package/src/{personal-access-token.ts → _personal-access-token.ts} +1 -1
- package/src/_profile-config.ts +545 -0
- package/src/{service-principal.ts → _service-principal.ts} +2 -2
- package/src/_storage.ts +109 -0
- package/src/_types.ts +45 -0
- package/src/client.ts +291 -0
- package/src/config.ts +44 -0
- package/src/profile.ts +33 -0
- package/lib/exports.d.ts +0 -2
- package/lib/exports.js +0 -3
- package/lib/src/_profile-core.d.ts +0 -28
- package/lib/src/_profile-core.js +0 -216
- package/lib/src/_profile.d.ts +0 -15
- package/lib/src/_profile.js +0 -236
- package/lib/src/databricks-auth.d.ts +0 -11
- package/lib/src/databricks-auth.js +0 -314
- package/lib/src/databricks-cli.js +0 -239
- package/lib/src/errors.d.ts +0 -7
- package/lib/src/errors.js +0 -14
- package/lib/src/generated/databricks-cli-assets.json +0 -33
- package/lib/src/http-client.d.ts +0 -23
- package/lib/src/http-client.js +0 -116
- package/lib/src/lifecycle.js +0 -229
- package/lib/src/node-storage.d.ts +0 -20
- package/lib/src/node-storage.js +0 -207
- package/lib/src/personal-access-token.js +0 -30
- package/lib/src/service-principal.js +0 -69
- package/lib/src/storage.js +0 -98
- package/lib/src/types.d.ts +0 -157
- package/lib/src/types.js +0 -67
- package/src/_profile-core.ts +0 -258
- package/src/_profile.ts +0 -319
- package/src/databricks-auth.ts +0 -416
- package/src/errors.ts +0 -16
- package/src/generated/databricks-cli-assets.json +0 -33
- package/src/http-client.ts +0 -147
- package/src/node-storage.ts +0 -230
- package/src/storage.ts +0 -104
- package/src/types.ts +0 -188
package/src/node-storage.ts
DELETED
|
@@ -1,230 +0,0 @@
|
|
|
1
|
-
import { createHash, randomUUID } from "node:crypto";
|
|
2
|
-
import { chmod, mkdir, readFile, rename, unlink, writeFile } from "node:fs/promises";
|
|
3
|
-
import { homedir } from "node:os";
|
|
4
|
-
import { basename, dirname, join } from "node:path";
|
|
5
|
-
|
|
6
|
-
import { acquireFileLock, type FileLockLease } from "@dbx-tools/core/file-lock";
|
|
7
|
-
|
|
8
|
-
import { authLogger, credentialId, tokenMetadata } from "./_logging.ts";
|
|
9
|
-
import { AuthError } from "./errors.ts";
|
|
10
|
-
import type { CredentialStore, LockAdapter, Token } from "./types.ts";
|
|
11
|
-
import { FileLayout } from "./types.ts";
|
|
12
|
-
|
|
13
|
-
const logger = authLogger("file-storage");
|
|
14
|
-
|
|
15
|
-
interface TokenCache {
|
|
16
|
-
version: number;
|
|
17
|
-
tokens: Record<string, unknown>;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
class NodeFileLocks implements LockAdapter {
|
|
21
|
-
private readonly leases = new Map<string, FileLockLease>();
|
|
22
|
-
|
|
23
|
-
constructor(private readonly lockDirectory: string) {}
|
|
24
|
-
|
|
25
|
-
async acquire(key: string, timeoutMs: number): Promise<string> {
|
|
26
|
-
logger.debug("waiting for file lock", {
|
|
27
|
-
credential: credentialId(key),
|
|
28
|
-
timeoutMs,
|
|
29
|
-
});
|
|
30
|
-
const lease = await acquireFileLock(key, { dir: this.lockDirectory, timeoutMs });
|
|
31
|
-
const id = randomUUID();
|
|
32
|
-
this.leases.set(id, lease);
|
|
33
|
-
logger.debug("file lock acquired", {
|
|
34
|
-
credential: credentialId(key),
|
|
35
|
-
backend: lease.backend,
|
|
36
|
-
});
|
|
37
|
-
return id;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
async release(id: string): Promise<void> {
|
|
41
|
-
const lease = this.leases.get(id);
|
|
42
|
-
if (!lease) return;
|
|
43
|
-
this.leases.delete(id);
|
|
44
|
-
await lease.release();
|
|
45
|
-
logger.debug("file lock released", { backend: lease.backend });
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
/** File-backed credential store preserving unrelated Databricks CLI entries. */
|
|
50
|
-
export class FileCredentialStore implements CredentialStore {
|
|
51
|
-
private readonly locks: LockAdapter;
|
|
52
|
-
|
|
53
|
-
constructor(
|
|
54
|
-
private readonly root = join(homedir(), ".databricks"),
|
|
55
|
-
private readonly layout = FileLayout.Single,
|
|
56
|
-
locks?: LockAdapter,
|
|
57
|
-
) {
|
|
58
|
-
this.locks = locks ?? new NodeFileLocks(join(root, "locks"));
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
async load(key: string): Promise<Token | undefined> {
|
|
62
|
-
const store = this.forKey(key);
|
|
63
|
-
return store.withCacheLock(async () => {
|
|
64
|
-
const token = deserializeToken((await store.readCache()).tokens[key]);
|
|
65
|
-
logger.debug("loaded file credential", {
|
|
66
|
-
credential: credentialId(key),
|
|
67
|
-
layout: this.layout,
|
|
68
|
-
token: tokenMetadata(token),
|
|
69
|
-
});
|
|
70
|
-
return token;
|
|
71
|
-
});
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
async prepareWrite(): Promise<void> {
|
|
75
|
-
await ensureDirectory(this.root, 0o700);
|
|
76
|
-
logger.debug("prepared credential directory", { layout: this.layout });
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
async save(key: string, token: Token): Promise<void> {
|
|
80
|
-
const store = this.forKey(key);
|
|
81
|
-
await store.withCacheLock(async () => {
|
|
82
|
-
const cache = await store.readCache();
|
|
83
|
-
cache.tokens[key] = serializeToken(token);
|
|
84
|
-
await store.writeCache(cache);
|
|
85
|
-
logger.debug("saved file credential", {
|
|
86
|
-
credential: credentialId(key),
|
|
87
|
-
layout: this.layout,
|
|
88
|
-
token: tokenMetadata(token),
|
|
89
|
-
});
|
|
90
|
-
});
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
async remove(key: string): Promise<void> {
|
|
94
|
-
const store = this.forKey(key);
|
|
95
|
-
await store.withCacheLock(async () => {
|
|
96
|
-
const cache = await store.readCache();
|
|
97
|
-
delete cache.tokens[key];
|
|
98
|
-
await store.writeCache(cache);
|
|
99
|
-
logger.debug("removed file credential", {
|
|
100
|
-
credential: credentialId(key),
|
|
101
|
-
layout: this.layout,
|
|
102
|
-
});
|
|
103
|
-
});
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
acquireLock(key: string, timeoutMs: number): Promise<string> {
|
|
107
|
-
return this.locks.acquire(
|
|
108
|
-
this.layout === FileLayout.Single ? `${this.root}:refresh` : `${this.root}:${key}:refresh`,
|
|
109
|
-
timeoutMs,
|
|
110
|
-
);
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
releaseLock(lease: string): Promise<void> {
|
|
114
|
-
return this.locks.release(lease);
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
name(): string {
|
|
118
|
-
return "file";
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
private forKey(key: string): FileCredentialStore {
|
|
122
|
-
if (this.layout === FileLayout.Single) return this;
|
|
123
|
-
const digest = createHash("sha256").update(key).digest("hex");
|
|
124
|
-
return new FileCredentialStore(join(this.root, digest), FileLayout.Single, this.locks);
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
private async withCacheLock<T>(action: () => Promise<T>): Promise<T> {
|
|
128
|
-
await ensureDirectory(this.root, 0o700);
|
|
129
|
-
const lease = await this.locks.acquire(`${this.root}:cache`, 30_000);
|
|
130
|
-
try {
|
|
131
|
-
return await action();
|
|
132
|
-
} finally {
|
|
133
|
-
await this.locks.release(lease);
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
private async readCache(): Promise<TokenCache> {
|
|
138
|
-
try {
|
|
139
|
-
const source = await readTextFile(join(this.root, "token-cache.json"));
|
|
140
|
-
const cache = source ? (JSON.parse(source) as TokenCache) : { version: 1, tokens: {} };
|
|
141
|
-
if (cache.version !== 1 || typeof cache.tokens !== "object" || !cache.tokens) {
|
|
142
|
-
throw new AuthError("storage", "Token cache must use version 1");
|
|
143
|
-
}
|
|
144
|
-
logger.debug("read token cache", {
|
|
145
|
-
exists: Boolean(source),
|
|
146
|
-
credentialCount: Object.keys(cache.tokens).length,
|
|
147
|
-
});
|
|
148
|
-
return cache;
|
|
149
|
-
} catch (cause) {
|
|
150
|
-
if (cause instanceof AuthError) throw cause;
|
|
151
|
-
throw new AuthError("storage", "Could not read Databricks token cache", { cause });
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
private async writeCache(cache: TokenCache): Promise<void> {
|
|
156
|
-
try {
|
|
157
|
-
await atomicWriteTextFile(
|
|
158
|
-
join(this.root, "token-cache.json"),
|
|
159
|
-
`${JSON.stringify(cache, null, 2)}\n`,
|
|
160
|
-
0o600,
|
|
161
|
-
);
|
|
162
|
-
logger.debug("wrote token cache", { credentialCount: Object.keys(cache.tokens).length });
|
|
163
|
-
} catch (cause) {
|
|
164
|
-
throw new AuthError("storage", "Could not write Databricks token cache", { cause });
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
async function ensureDirectory(path: string, mode: number): Promise<void> {
|
|
170
|
-
await mkdir(path, { recursive: true, mode });
|
|
171
|
-
await chmod(path, mode);
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
async function readTextFile(path: string): Promise<string | undefined> {
|
|
175
|
-
try {
|
|
176
|
-
return await readFile(path, "utf8");
|
|
177
|
-
} catch (cause) {
|
|
178
|
-
if ((cause as NodeJS.ErrnoException).code === "ENOENT") return undefined;
|
|
179
|
-
throw cause;
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
async function atomicWriteTextFile(path: string, content: string, mode: number): Promise<void> {
|
|
184
|
-
const parent = dirname(path);
|
|
185
|
-
await ensureDirectory(parent, 0o700);
|
|
186
|
-
const temporary = join(parent, `.${basename(path)}-${randomUUID()}.tmp`);
|
|
187
|
-
try {
|
|
188
|
-
await writeFile(temporary, content, { mode, flag: "wx" });
|
|
189
|
-
await chmod(temporary, mode);
|
|
190
|
-
await rename(temporary, path);
|
|
191
|
-
} finally {
|
|
192
|
-
await unlink(temporary).catch((cause: NodeJS.ErrnoException) => {
|
|
193
|
-
if (cause.code !== "ENOENT") throw cause;
|
|
194
|
-
});
|
|
195
|
-
}
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
function serializeToken(token: Token): Record<string, unknown> {
|
|
199
|
-
return {
|
|
200
|
-
access_token: token.accessToken,
|
|
201
|
-
token_type: token.tokenType,
|
|
202
|
-
...(token.refreshToken ? { refresh_token: token.refreshToken } : {}),
|
|
203
|
-
...(token.expiry ? { expiry: token.expiry } : {}),
|
|
204
|
-
...(token.scopes.length ? { scopes: token.scopes } : {}),
|
|
205
|
-
};
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
function deserializeToken(value: unknown): Token | undefined {
|
|
209
|
-
if (!value || typeof value !== "object") return undefined;
|
|
210
|
-
const record = value as Record<string, unknown>;
|
|
211
|
-
const accessToken = stringValue(record.access_token ?? record.accessToken);
|
|
212
|
-
if (!accessToken) return undefined;
|
|
213
|
-
return {
|
|
214
|
-
accessToken,
|
|
215
|
-
tokenType: stringValue(record.token_type ?? record.tokenType) ?? "Bearer",
|
|
216
|
-
...(stringValue(record.refresh_token ?? record.refreshToken)
|
|
217
|
-
? { refreshToken: stringValue(record.refresh_token ?? record.refreshToken) }
|
|
218
|
-
: {}),
|
|
219
|
-
...(stringValue(record.expiry ?? record.expires_at)
|
|
220
|
-
? { expiry: stringValue(record.expiry ?? record.expires_at) }
|
|
221
|
-
: {}),
|
|
222
|
-
scopes: Array.isArray(record.scopes)
|
|
223
|
-
? record.scopes.filter((scope): scope is string => typeof scope === "string")
|
|
224
|
-
: [],
|
|
225
|
-
};
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
function stringValue(value: unknown): string | undefined {
|
|
229
|
-
return typeof value === "string" && value.trim() ? value : undefined;
|
|
230
|
-
}
|
package/src/storage.ts
DELETED
|
@@ -1,104 +0,0 @@
|
|
|
1
|
-
import { authLogger, credentialId, tokenMetadata } from "./_logging.ts";
|
|
2
|
-
import type { CredentialStore, LockAdapter, Token } from "./types.ts";
|
|
3
|
-
|
|
4
|
-
const logger = authLogger("memory-storage");
|
|
5
|
-
|
|
6
|
-
/** Process-local generic lease registry used by the in-memory store. */
|
|
7
|
-
export class MemoryLockAdapter implements LockAdapter {
|
|
8
|
-
readonly #tails = new Map<string, Promise<void>>();
|
|
9
|
-
readonly #leases = new Map<string, () => void>();
|
|
10
|
-
#sequence = 0;
|
|
11
|
-
|
|
12
|
-
async acquire(key: string, timeoutMs: number): Promise<string> {
|
|
13
|
-
const credential = credentialId(key);
|
|
14
|
-
const previous = this.#tails.get(key) ?? Promise.resolve();
|
|
15
|
-
let release!: () => void;
|
|
16
|
-
const current = new Promise<void>((resolve) => {
|
|
17
|
-
release = resolve;
|
|
18
|
-
});
|
|
19
|
-
const tail = previous.then(() => current);
|
|
20
|
-
this.#tails.set(key, tail);
|
|
21
|
-
try {
|
|
22
|
-
logger.debug("waiting for memory lock", { credential, timeoutMs });
|
|
23
|
-
await withTimeout(previous, timeoutMs, `Timed out waiting for lock ${key}`);
|
|
24
|
-
} catch (error) {
|
|
25
|
-
release();
|
|
26
|
-
if (this.#tails.get(key) === tail) this.#tails.delete(key);
|
|
27
|
-
throw error;
|
|
28
|
-
}
|
|
29
|
-
const lease = `${++this.#sequence}:${key}`;
|
|
30
|
-
this.#leases.set(lease, () => {
|
|
31
|
-
release();
|
|
32
|
-
this.#leases.delete(lease);
|
|
33
|
-
if (this.#tails.get(key) === tail) this.#tails.delete(key);
|
|
34
|
-
});
|
|
35
|
-
logger.debug("memory lock acquired", { credential });
|
|
36
|
-
return lease;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
async release(lease: string): Promise<void> {
|
|
40
|
-
logger.debug("releasing memory lock", {
|
|
41
|
-
credential: credentialId(lease.split(":").slice(1).join(":")),
|
|
42
|
-
});
|
|
43
|
-
this.#leases.get(lease)?.();
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
/** Process-local credential store with per-key refresh locks. */
|
|
48
|
-
export class MemoryCredentialStore implements CredentialStore {
|
|
49
|
-
readonly #tokens = new Map<string, Token>();
|
|
50
|
-
|
|
51
|
-
constructor(private readonly locks: LockAdapter = new MemoryLockAdapter()) {}
|
|
52
|
-
|
|
53
|
-
async load(key: string): Promise<Token | undefined> {
|
|
54
|
-
const token = this.#tokens.get(key);
|
|
55
|
-
logger.debug("loaded memory credential", {
|
|
56
|
-
credential: credentialId(key),
|
|
57
|
-
token: tokenMetadata(token),
|
|
58
|
-
});
|
|
59
|
-
return token ? structuredClone(token) : undefined;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
async prepareWrite(): Promise<void> {}
|
|
63
|
-
|
|
64
|
-
async save(key: string, token: Token): Promise<void> {
|
|
65
|
-
this.#tokens.set(key, structuredClone(token));
|
|
66
|
-
logger.debug("saved memory credential", {
|
|
67
|
-
credential: credentialId(key),
|
|
68
|
-
token: tokenMetadata(token),
|
|
69
|
-
});
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
async remove(key: string): Promise<void> {
|
|
73
|
-
this.#tokens.delete(key);
|
|
74
|
-
logger.debug("removed memory credential", { credential: credentialId(key) });
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
acquireLock(key: string, timeoutMs: number): Promise<string> {
|
|
78
|
-
return this.locks.acquire(key, timeoutMs);
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
releaseLock(lease: string): Promise<void> {
|
|
82
|
-
return this.locks.release(lease);
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
name(): string {
|
|
86
|
-
return "memory";
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
async function withTimeout<T>(promise: Promise<T>, timeoutMs: number, message: string): Promise<T> {
|
|
91
|
-
if (!Number.isFinite(timeoutMs) || timeoutMs < 0)
|
|
92
|
-
throw new TypeError("timeoutMs must be non-negative");
|
|
93
|
-
let timeout: ReturnType<typeof setTimeout> | undefined;
|
|
94
|
-
try {
|
|
95
|
-
return await Promise.race([
|
|
96
|
-
promise,
|
|
97
|
-
new Promise<never>((_, reject) => {
|
|
98
|
-
timeout = setTimeout(() => reject(new Error(message)), timeoutMs);
|
|
99
|
-
}),
|
|
100
|
-
]);
|
|
101
|
-
} finally {
|
|
102
|
-
if (timeout) clearTimeout(timeout);
|
|
103
|
-
}
|
|
104
|
-
}
|
package/src/types.ts
DELETED
|
@@ -1,188 +0,0 @@
|
|
|
1
|
-
/** Authentication strategy selected from Databricks configuration. */
|
|
2
|
-
export enum AuthKind {
|
|
3
|
-
UserToMachine = "user-to-machine",
|
|
4
|
-
MachineToMachine = "machine-to-machine",
|
|
5
|
-
PersonalAccessToken = "personal-access-token",
|
|
6
|
-
AppServicePrincipal = "app-service-principal",
|
|
7
|
-
AppOnBehalfOf = "app-on-behalf-of",
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
/** Scope of the Databricks authentication target. */
|
|
11
|
-
export enum TargetKind {
|
|
12
|
-
Workspace = "workspace",
|
|
13
|
-
Account = "account",
|
|
14
|
-
Unified = "unified",
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
/** Built-in credential storage backend. */
|
|
18
|
-
export enum Storage {
|
|
19
|
-
Auto = "auto",
|
|
20
|
-
Memory = "memory",
|
|
21
|
-
File = "file",
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
/** File organization used by a persistent credential store. */
|
|
25
|
-
export enum FileLayout {
|
|
26
|
-
Single = "single",
|
|
27
|
-
PerCredential = "per-credential",
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
/** Stored OAuth credential, including renewal metadata. */
|
|
31
|
-
export interface Token {
|
|
32
|
-
accessToken: string;
|
|
33
|
-
tokenType: string;
|
|
34
|
-
refreshToken?: string;
|
|
35
|
-
expiry?: string;
|
|
36
|
-
scopes: string[];
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
/** Public credential result; deliberately excludes the refresh token. */
|
|
40
|
-
export interface AccessToken {
|
|
41
|
-
accessToken: string;
|
|
42
|
-
tokenType: string;
|
|
43
|
-
expiry?: string;
|
|
44
|
-
scopes: string[];
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
/** Shared lifecycle configuration embedded by every provider. */
|
|
48
|
-
export interface AuthOptions {
|
|
49
|
-
refreshBufferSeconds: number;
|
|
50
|
-
lockTimeoutSeconds: number;
|
|
51
|
-
loginTimeoutSeconds: number;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
const AUTH_DEFAULTS: AuthOptions = {
|
|
55
|
-
refreshBufferSeconds: 300,
|
|
56
|
-
lockTimeoutSeconds: 30,
|
|
57
|
-
loginTimeoutSeconds: 900,
|
|
58
|
-
};
|
|
59
|
-
|
|
60
|
-
/** Record-style factory retained for straightforward Node/Python bridging. */
|
|
61
|
-
export const AuthOptions = {
|
|
62
|
-
create(options: Partial<AuthOptions> = {}): AuthOptions {
|
|
63
|
-
return { ...AUTH_DEFAULTS, ...options };
|
|
64
|
-
},
|
|
65
|
-
defaults(): Readonly<AuthOptions> {
|
|
66
|
-
return Object.freeze({ ...AUTH_DEFAULTS });
|
|
67
|
-
},
|
|
68
|
-
};
|
|
69
|
-
|
|
70
|
-
/** Secret-free metadata discovered from one Databricks CLI profile. */
|
|
71
|
-
export interface DatabricksProfileSummary {
|
|
72
|
-
name: string;
|
|
73
|
-
host?: string;
|
|
74
|
-
accountId?: string;
|
|
75
|
-
workspaceId?: string;
|
|
76
|
-
target: TargetKind;
|
|
77
|
-
authKind: AuthKind;
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
/** Resolved Databricks identity and active storage backend. */
|
|
81
|
-
export interface DatabricksAuthStatus {
|
|
82
|
-
profile: string;
|
|
83
|
-
host: string;
|
|
84
|
-
storage: Storage;
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
/** Public Databricks authentication options. */
|
|
88
|
-
export interface DatabricksAuthOptions {
|
|
89
|
-
profile?: string;
|
|
90
|
-
host?: string;
|
|
91
|
-
accountId?: string;
|
|
92
|
-
workspaceId?: string;
|
|
93
|
-
configFile?: string;
|
|
94
|
-
clientId?: string;
|
|
95
|
-
clientSecret?: string;
|
|
96
|
-
accessToken?: string;
|
|
97
|
-
groupId?: string;
|
|
98
|
-
authType?: string;
|
|
99
|
-
scopes?: string[];
|
|
100
|
-
target?: string;
|
|
101
|
-
cacheDir?: string;
|
|
102
|
-
auth?: AuthOptions;
|
|
103
|
-
requestHeaders?: Record<string, string>;
|
|
104
|
-
accessTokenHeader?: string;
|
|
105
|
-
installCliInApp?: boolean;
|
|
106
|
-
preferUserToMachine: boolean;
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
/** Record-style factory retained for callers migrating from generated bindings. */
|
|
110
|
-
export const DatabricksAuthOptions = {
|
|
111
|
-
create(options: Partial<DatabricksAuthOptions> = {}): DatabricksAuthOptions {
|
|
112
|
-
return { preferUserToMachine: true, ...options };
|
|
113
|
-
},
|
|
114
|
-
defaults(): Readonly<DatabricksAuthOptions> {
|
|
115
|
-
return Object.freeze({ preferUserToMachine: true });
|
|
116
|
-
},
|
|
117
|
-
};
|
|
118
|
-
|
|
119
|
-
/** Resolved profile with secrets retained only for provider construction. */
|
|
120
|
-
export interface DatabricksProfile extends DatabricksProfileSummary {
|
|
121
|
-
host: string;
|
|
122
|
-
authType?: string;
|
|
123
|
-
clientId: string;
|
|
124
|
-
groupId?: string;
|
|
125
|
-
scopes: string[];
|
|
126
|
-
clientSecret?: string;
|
|
127
|
-
accessToken?: string;
|
|
128
|
-
cacheKey: string;
|
|
129
|
-
principal: string;
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
/** Cross-language lease adapter; implementations may use files, databases, or FFI. */
|
|
133
|
-
export interface LockAdapter {
|
|
134
|
-
acquire(key: string, timeoutMs: number): Promise<string>;
|
|
135
|
-
release(lease: string): Promise<void>;
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
/** Cross-language credential persistence contract. */
|
|
139
|
-
export interface CredentialStore {
|
|
140
|
-
load(key: string): Promise<Token | undefined>;
|
|
141
|
-
prepareWrite(): Promise<void>;
|
|
142
|
-
save(key: string, token: Token): Promise<void>;
|
|
143
|
-
remove(key: string): Promise<void>;
|
|
144
|
-
acquireLock(key: string, timeoutMs: number): Promise<string>;
|
|
145
|
-
releaseLock(lease: string): Promise<void>;
|
|
146
|
-
name(): string;
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
/** Provider-specific token acquisition. */
|
|
150
|
-
export interface TokenProvider {
|
|
151
|
-
authenticate(timeoutMs: number): Promise<Token>;
|
|
152
|
-
login(timeoutMs: number): Promise<Token>;
|
|
153
|
-
refresh(token: Token): Promise<Token>;
|
|
154
|
-
canAuthenticateSilently(): boolean;
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
/** Stable facade shared by Node, the CLI, and generated language bindings. */
|
|
158
|
-
export interface AuthClient {
|
|
159
|
-
challenge(): Promise<void>;
|
|
160
|
-
token(login?: boolean): Promise<AccessToken>;
|
|
161
|
-
authenticate(login?: boolean): Promise<Record<string, string>>;
|
|
162
|
-
authorizationHeaderForUrl(requestUrl: string, login?: boolean): Promise<string | undefined>;
|
|
163
|
-
requestHeadersForUrl(requestUrl: string, login?: boolean): Promise<Record<string, string>>;
|
|
164
|
-
forceRefreshToken(login?: boolean): Promise<AccessToken>;
|
|
165
|
-
refreshRejectedToken(staleAccessToken: string, login?: boolean): Promise<AccessToken>;
|
|
166
|
-
logout(): Promise<void>;
|
|
167
|
-
status(): DatabricksAuthStatus;
|
|
168
|
-
principal(): string;
|
|
169
|
-
workspaceId(): string | undefined;
|
|
170
|
-
authKind(): AuthKind;
|
|
171
|
-
profile(name?: string): DatabricksProfileSummary;
|
|
172
|
-
listProfiles(refresh?: boolean): DatabricksProfileSummary[];
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
/** Public OAuth client used by Databricks CLI-compatible user authentication. */
|
|
176
|
-
export const DEFAULT_CLIENT_ID = "databricks-cli";
|
|
177
|
-
/** Default Databricks profile configuration path. */
|
|
178
|
-
export const DEFAULT_CONFIG_FILE = "~/.databrickscfg";
|
|
179
|
-
/** Default Databricks account console origin. */
|
|
180
|
-
export const DEFAULT_ACCOUNTS_HOST = "https://accounts.cloud.databricks.com";
|
|
181
|
-
/** Canonical request header carrying a bearer access token. */
|
|
182
|
-
export const DEFAULT_ACCESS_TOKEN_HEADER = "authorization";
|
|
183
|
-
/** Canonical request header carrying the resolved Databricks workspace ID. */
|
|
184
|
-
export const WORKSPACE_ID_HEADER = "x-databricks-workspace-id";
|
|
185
|
-
/** Authentication type for Databricks App on-behalf-of request credentials. */
|
|
186
|
-
export const AUTH_TYPE_APP_OBO = "app_obo";
|
|
187
|
-
/** Authentication type for Databricks App service-principal credentials. */
|
|
188
|
-
export const AUTH_TYPE_APP_SP = "app_sp";
|