@takodotid/azure-rest 0.1.0 → 0.1.1
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/dist/index.cjs +59 -6
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +28 -7
- package/dist/index.d.ts +28 -7
- package/dist/index.js +59 -6
- package/dist/index.js.map +1 -1
- package/package.json +10 -4
- package/.github/renovate.json +0 -4
- package/.github/workflows/publish.yaml +0 -47
- package/.github/workflows/test.yaml +0 -32
- package/.node-version +0 -1
- package/.vscode/settings.json +0 -12
- package/biome.json +0 -56
- package/lefthook.yaml +0 -11
- package/pnpm-workspace.yaml +0 -3
- package/src/AzureClient.ts +0 -147
- package/src/index.ts +0 -7
- package/src/lib/AzureCliCredential.ts +0 -135
- package/src/lib/AzureCredential.ts +0 -17
- package/src/lib/DefaultChainedCredential.ts +0 -34
- package/src/lib/ManagedIdentityCredential.ts +0 -75
- package/src/lib/ServicePrincipalCredential.ts +0 -132
- package/src/lib/WorkloadIdentityCredential.ts +0 -71
- package/tsconfig.json +0 -15
- package/tsup.config.ts +0 -10
package/dist/index.cjs
CHANGED
|
@@ -68,7 +68,10 @@ var AzureClient = class _AzureClient {
|
|
|
68
68
|
if (i > 0) await new Promise((res) => setTimeout(res, 100 * i));
|
|
69
69
|
}
|
|
70
70
|
if (!this.token) throw new Error("Token is unexpectedly null after refresh attempts");
|
|
71
|
-
|
|
71
|
+
const baseUrl = this.options.baseUrl.replace(/\/+$/, "");
|
|
72
|
+
const relPath = path.replace(/^\/+/, "");
|
|
73
|
+
const url = `${baseUrl}/${relPath}`;
|
|
74
|
+
return fetch(url, {
|
|
72
75
|
...init,
|
|
73
76
|
headers: {
|
|
74
77
|
...this.options.credential.builder ? this.options.credential.builder(this.token) : { Authorization: `Bearer ${this.token.accessToken}` },
|
|
@@ -238,6 +241,8 @@ var AzureCliCredential = class _AzureCliCredential {
|
|
|
238
241
|
}
|
|
239
242
|
/**
|
|
240
243
|
* Instantiates AzureCliCredential using the AZURE_TENANT_ID environment variable.
|
|
244
|
+
* This expects the following environment variable to be set:
|
|
245
|
+
* - AZURE_TENANT_ID: The Azure tenant ID to use for authentication.
|
|
241
246
|
* @returns AzureCliCredential instance
|
|
242
247
|
*/
|
|
243
248
|
static fromEnv() {
|
|
@@ -264,7 +269,7 @@ var ManagedIdentityCredential = class _ManagedIdentityCredential {
|
|
|
264
269
|
* @throws If the endpoint is unavailable or token request fails
|
|
265
270
|
*/
|
|
266
271
|
async getToken(scope) {
|
|
267
|
-
const endpoint =
|
|
272
|
+
const endpoint = this.options.identityEndpoint || "http://169.254.169.254/metadata/identity/oauth2/token";
|
|
268
273
|
const apiVersion = "2018-02-01";
|
|
269
274
|
const params = new URLSearchParams({
|
|
270
275
|
resource: scope.replace(".default", ""),
|
|
@@ -275,7 +280,20 @@ var ManagedIdentityCredential = class _ManagedIdentityCredential {
|
|
|
275
280
|
}
|
|
276
281
|
const url = `${endpoint}?${params.toString()}`;
|
|
277
282
|
const headers = { Metadata: "true" };
|
|
278
|
-
const
|
|
283
|
+
const timeoutMs = this.options.timeoutMs ?? 300;
|
|
284
|
+
const controller = new AbortController();
|
|
285
|
+
const timeout = setTimeout(() => controller.abort(), timeoutMs);
|
|
286
|
+
let response;
|
|
287
|
+
try {
|
|
288
|
+
response = await fetch(url, { headers, signal: controller.signal });
|
|
289
|
+
} catch (err) {
|
|
290
|
+
if (err.name === "AbortError") {
|
|
291
|
+
throw new Error(`ManagedIdentityCredential: Timed out after ${timeoutMs}ms waiting for metadata endpoint (${url})`);
|
|
292
|
+
}
|
|
293
|
+
throw err;
|
|
294
|
+
} finally {
|
|
295
|
+
clearTimeout(timeout);
|
|
296
|
+
}
|
|
279
297
|
if (!response.ok) {
|
|
280
298
|
throw new Error(`ManagedIdentityCredential: Failed to get token: ${await response.text()}`);
|
|
281
299
|
}
|
|
@@ -290,10 +308,18 @@ var ManagedIdentityCredential = class _ManagedIdentityCredential {
|
|
|
290
308
|
}
|
|
291
309
|
/**
|
|
292
310
|
* Instantiates ManagedIdentityCredential using environment variables.
|
|
311
|
+
* This expects the following environment variables to be set:
|
|
312
|
+
* - AZURE_CLIENT_ID: The user-assigned managed identity client ID. This is optional for system-assigned identities.
|
|
313
|
+
* - AZURE_MANAGED_IDENTITY_ENDPOINT or IDENTITY_ENDPOINT: The managed identity endpoint (optional, defaults to http://169.254.169.254/metadata/identity/oauth2/token)
|
|
314
|
+
* - AZURE_MANAGED_IDENTITY_TIMEOUT_MS: Custom timeout for metadata endpoint fetch in milliseconds (optional).
|
|
293
315
|
* @returns ManagedIdentityCredential instance
|
|
294
316
|
*/
|
|
295
317
|
static fromEnv() {
|
|
296
|
-
return new _ManagedIdentityCredential({
|
|
318
|
+
return new _ManagedIdentityCredential({
|
|
319
|
+
identityEndpoint: process.env.AZURE_MANAGED_IDENTITY_ENDPOINT || process.env.IDENTITY_ENDPOINT,
|
|
320
|
+
clientId: process.env.AZURE_CLIENT_ID,
|
|
321
|
+
timeoutMs: process.env.AZURE_MANAGED_IDENTITY_TIMEOUT_MS ? Number.parseInt(process.env.AZURE_MANAGED_IDENTITY_TIMEOUT_MS) : void 0
|
|
322
|
+
});
|
|
297
323
|
}
|
|
298
324
|
};
|
|
299
325
|
|
|
@@ -355,14 +381,20 @@ var ServicePrincipalCredential = class _ServicePrincipalCredential {
|
|
|
355
381
|
}
|
|
356
382
|
/**
|
|
357
383
|
* Instantiates ServicePrincipalCredential using environment variables.
|
|
384
|
+
* This expects the following environment variables to be set:
|
|
385
|
+
* - AZURE_CLIENT_ID: The Azure AD application (client) ID
|
|
386
|
+
* - AZURE_CLIENT_SECRET: The client secret
|
|
387
|
+
* - AZURE_TENANT_ID: The Azure AD tenant ID
|
|
388
|
+
* - AZURE_USE_FEDERATED_AUTH: Optional, if set to "true", uses federated authentication (JWT assertion).
|
|
358
389
|
* @returns ServicePrincipalCredential instance
|
|
359
390
|
*/
|
|
360
391
|
static fromEnv() {
|
|
361
392
|
return new _ServicePrincipalCredential({
|
|
393
|
+
authorityHost: process.env.AZURE_AUTHORITY_HOST,
|
|
362
394
|
clientId: process.env.AZURE_CLIENT_ID,
|
|
363
395
|
clientSecret: process.env.AZURE_CLIENT_SECRET,
|
|
364
396
|
tenantId: process.env.AZURE_TENANT_ID,
|
|
365
|
-
federated:
|
|
397
|
+
federated: process.env.AZURE_USE_FEDERATED_AUTH === "true"
|
|
366
398
|
});
|
|
367
399
|
}
|
|
368
400
|
};
|
|
@@ -392,6 +424,11 @@ var WorkloadIdentityCredential = class _WorkloadIdentityCredential {
|
|
|
392
424
|
}
|
|
393
425
|
/**
|
|
394
426
|
* Instantiates WorkloadIdentityCredential using environment variables.
|
|
427
|
+
* This expects the following environment variables to be set:
|
|
428
|
+
* - AZURE_AUTHORITY_HOST: The Azure AD authority host (optional)
|
|
429
|
+
* - AZURE_CLIENT_ID: The Azure AD application (client) ID
|
|
430
|
+
* - AZURE_FEDERATED_TOKEN_FILE: Path to the federated token file
|
|
431
|
+
* - AZURE_TENANT_ID: The Azure AD tenant ID
|
|
395
432
|
* @returns WorkloadIdentityCredential instance
|
|
396
433
|
*/
|
|
397
434
|
static fromEnv() {
|
|
@@ -415,10 +452,26 @@ var DefaultChainedCredential = class {
|
|
|
415
452
|
*/
|
|
416
453
|
async getToken(scope) {
|
|
417
454
|
const errors = [];
|
|
455
|
+
const debug = process.env.DEBUG?.includes("tako-azure-rest:credentials") || process.env.DEBUG?.includes("tako-azure-rest:*");
|
|
418
456
|
for (const Credential of credentialChain) {
|
|
457
|
+
const label = `[DefaultChainedCredential] ${Credential.name}`;
|
|
458
|
+
let start;
|
|
459
|
+
if (debug) {
|
|
460
|
+
start = Date.now();
|
|
461
|
+
console.log(`${label} - trying...`);
|
|
462
|
+
}
|
|
419
463
|
try {
|
|
420
|
-
|
|
464
|
+
const result = await Credential.fromEnv().getToken(scope);
|
|
465
|
+
if (debug && start !== void 0) {
|
|
466
|
+
const ms = Date.now() - start;
|
|
467
|
+
console.log(`${label} - success in ${ms}ms`);
|
|
468
|
+
}
|
|
469
|
+
return result;
|
|
421
470
|
} catch (error) {
|
|
471
|
+
if (debug && start !== void 0) {
|
|
472
|
+
const ms = Date.now() - start;
|
|
473
|
+
console.log(`${label} - failed in ${ms}ms: ${error.message}`);
|
|
474
|
+
}
|
|
422
475
|
errors.push({ error, name: Credential.name });
|
|
423
476
|
}
|
|
424
477
|
}
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/AzureClient.ts","../src/lib/AzureCliCredential.ts","../src/lib/AzureCredential.ts","../src/lib/ManagedIdentityCredential.ts","../src/lib/ServicePrincipalCredential.ts","../src/lib/WorkloadIdentityCredential.ts","../src/lib/DefaultChainedCredential.ts"],"sourcesContent":["export * from \"./AzureClient.js\";\nexport * from \"./lib/AzureCliCredential.js\";\nexport * from \"./lib/AzureCredential.js\";\nexport * from \"./lib/DefaultChainedCredential.js\";\nexport * from \"./lib/ManagedIdentityCredential.js\";\nexport * from \"./lib/ServicePrincipalCredential.js\";\nexport * from \"./lib/WorkloadIdentityCredential.js\";\n","import type { AzureCredential, Credential } from \"./lib/AzureCredential.js\";\n\n/**\n * Options for configuring the AzureClient instance.\n *\n * @property baseUrl - The base URL for Azure REST API endpoints (e.g. https://management.azure.com)\n * @property credential - Credential configuration for authenticating requests\n * @property helper - An AzureCredential implementation for acquiring tokens\n * @property scope - The Azure resource scope for the token (e.g. https://management.azure.com/.default)\n * @property builder - (Optional) Function to build request headers from a token. If not provided, an Authorization header is set by default.\n */\nexport type AzureClientOptions = {\n\tbaseUrl: string;\n\tcredential: {\n\t\thelper: AzureCredential;\n\t\tscope: string;\n\t\tbuilder?: (token: Credential) => Record<string, string>;\n\t};\n};\n\n/**\n * Azure REST API client with credential refresh and HTTP verb helpers.\n */\nexport class AzureClient {\n\tprivate static readonly MAX_TOKEN_RETRIES = 3;\n\tprivate token: Credential | null = null;\n\n\t/**\n\t * @param options Azure client configuration (baseUrl, credential, etc)\n\t */\n\tconstructor(public options: AzureClientOptions) {\n\t\tObject.defineProperty(this, \"token\", { enumerable: false });\n\t}\n\n\t/**\n\t * Sends a request to the Azure REST API, handling token refresh and retries.\n\t * @param path The API path (relative to baseUrl)\n\t * @param init Optional fetch options\n\t * @returns The fetch Response object\n\t * @throws If token refresh fails after max retries\n\t */\n\tpublic async sendRequest(path: string, init?: RequestInit): Promise<Response> {\n\t\tfor (let i = 0; i <= AzureClient.MAX_TOKEN_RETRIES; i++) {\n\t\t\tif (this.token && this.token.expiresAt > new Date()) break;\n\t\t\tif (i === AzureClient.MAX_TOKEN_RETRIES) {\n\t\t\t\tthrow new Error(\"Failed to refresh token after multiple attempts\");\n\t\t\t}\n\t\t\tawait this.refreshToken();\n\t\t\tif (i > 0) await new Promise(res => setTimeout(res, 100 * i));\n\t\t}\n\n\t\tif (!this.token) throw new Error(\"Token is unexpectedly null after refresh attempts\");\n\n\t\treturn fetch(`${this.options.baseUrl}${path}`, {\n\t\t\t...init,\n\t\t\theaders: {\n\t\t\t\t...(this.options.credential.builder ? this.options.credential.builder(this.token) : { Authorization: `Bearer ${this.token.accessToken}` }),\n\t\t\t\t...init?.headers\n\t\t\t}\n\t\t});\n\t}\n\n\t/**\n\t * Sends a GET request to the Azure REST API.\n\t * @param path The API path\n\t * @param init Optional fetch options\n\t * @returns The fetch Response object\n\t */\n\tpublic get(path: string, init?: RequestInit) {\n\t\treturn this.sendRequest(path, { ...init, method: \"GET\" });\n\t}\n\n\t/**\n\t * Sends a POST request with a JSON body to the Azure REST API.\n\t * @param path The API path\n\t * @param body The request body (will be JSON.stringified)\n\t * @param init Optional fetch options\n\t * @returns The fetch Response object\n\t */\n\tpublic post(path: string, body?: any, init?: RequestInit) {\n\t\treturn this.sendRequest(path, {\n\t\t\t...init,\n\t\t\tmethod: \"POST\",\n\t\t\theaders: {\n\t\t\t\t\"Content-Type\": \"application/json\",\n\t\t\t\t...init?.headers\n\t\t\t},\n\t\t\tbody: body !== undefined ? JSON.stringify(body) : undefined\n\t\t});\n\t}\n\n\t/**\n\t * Sends a PUT request with a JSON body to the Azure REST API.\n\t * @param path The API path\n\t * @param body The request body (will be JSON.stringified)\n\t * @param init Optional fetch options\n\t * @returns The fetch Response object\n\t */\n\tpublic put(path: string, body?: any, init?: RequestInit) {\n\t\treturn this.sendRequest(path, {\n\t\t\t...init,\n\t\t\tmethod: \"PUT\",\n\t\t\theaders: {\n\t\t\t\t\"Content-Type\": \"application/json\",\n\t\t\t\t...init?.headers\n\t\t\t},\n\t\t\tbody: body !== undefined ? JSON.stringify(body) : undefined\n\t\t});\n\t}\n\n\t/**\n\t * Sends a PATCH request with a JSON body to the Azure REST API.\n\t * @param path The API path\n\t * @param body The request body (will be JSON.stringified)\n\t * @param init Optional fetch options\n\t * @returns The fetch Response object\n\t */\n\tpublic patch(path: string, body?: any, init?: RequestInit) {\n\t\treturn this.sendRequest(path, {\n\t\t\t...init,\n\t\t\tmethod: \"PATCH\",\n\t\t\theaders: {\n\t\t\t\t\"Content-Type\": \"application/json\",\n\t\t\t\t...init?.headers\n\t\t\t},\n\t\t\tbody: body !== undefined ? JSON.stringify(body) : undefined\n\t\t});\n\t}\n\n\t/**\n\t * Sends a DELETE request to the Azure REST API.\n\t * @param path The API path\n\t * @param init Optional fetch options\n\t * @returns The fetch Response object\n\t */\n\tpublic delete(path: string, init?: RequestInit) {\n\t\treturn this.sendRequest(path, { ...init, method: \"DELETE\" });\n\t}\n\n\t/**\n\t * Refreshes the Azure access token using the provided credential helper.\n\t * @private\n\t */\n\tprivate async refreshToken(): Promise<void> {\n\t\tthis.token = await this.options.credential.helper.getToken(this.options.credential.scope);\n\t}\n}\n","import { execFile } from \"node:child_process\";\nimport process from \"node:process\";\nimport type { AzureCredential } from \"./AzureCredential.js\";\n\n/**\n * The raw response returned by Azure CLI when requesting an access token.\n *\n * @property accessToken - The access token string\n * @property expiresOn - Expiry date in RFC3339 format (legacy)\n * @property expires_on - Expiry as seconds since epoch (preferred)\n * @property subscription - (Optional) Subscription ID, may not be present\n * @property tenant - Tenant ID\n * @property tokenType - Token type (usually 'Bearer')\n */\nexport type CLITokenResponse = {\n\taccessToken: string;\n\texpiresOn: string;\n\texpires_on: string;\n\tsubscription?: string;\n\ttenant: string;\n\ttokenType: string;\n};\n\n/**\n * Options for AzureCliCredential.\n *\n * @property tenantId - The Azure tenant ID to use for authentication\n */\nexport type AzureCLICredentialOptions = {\n\ttenantId: string;\n};\n\nexport class AzureCliCredential implements AzureCredential {\n\tpublic constructor(public options: AzureCLICredentialOptions) {}\n\n\t/**\n\t * Gets an Azure access token using the Azure CLI.\n\t * @param scope The resource scope for the token\n\t * @returns An object with token and expiresAt\n\t * @throws If CLI is not installed or not logged in\n\t */\n\tpublic async getToken(scope: string) {\n\t\ttry {\n\t\t\tconst result = await this.getCliToken(scope);\n\n\t\t\tconst specificScope = result.stderr.match(\"(.*)az login --scope(.*)\");\n\t\t\tconst isLoginError = result.stderr.match(\"(.*)az login(.*)\") && !specificScope;\n\t\t\tconst isNotInstallError = result.stderr.match(\"az:(.*)not found\") ?? result.stderr.startsWith(\"'az' is not recognized\");\n\n\t\t\tif (isNotInstallError) {\n\t\t\t\tthrow new Error(\"Azure CLI not found. Please install\");\n\t\t\t}\n\t\t\tif (isLoginError) {\n\t\t\t\tthrow new Error(\"Please login to Azure CLI\");\n\t\t\t}\n\n\t\t\treturn this.parseRawOutput(result.stdout);\n\t\t} catch (error) {\n\t\t\tthrow new Error(`Failed to get token: ${(error as Error).stack}`);\n\t\t}\n\t}\n\n\t/**\n\t * Runs the Azure CLI to get an access token for the given scope.\n\t * @param scope The resource scope\n\t * @returns Promise resolving to CLI stdout and stderr\n\t * @private\n\t */\n\tprivate async getCliToken(scope: string) {\n\t\treturn new Promise<{ stderr: string; stdout: string }>((resolve, reject) => {\n\t\t\ttry {\n\t\t\t\texecFile(\n\t\t\t\t\t\"az\",\n\t\t\t\t\t[\"account\", \"get-access-token\", \"--output\", \"json\", \"--resource\", scope.replace(\".default\", \"\"), \"--tenant\", this.options.tenantId],\n\t\t\t\t\t{ cwd: process.cwd(), shell: true, timeout: 30_000 },\n\t\t\t\t\t(error, stdout, stderr) => {\n\t\t\t\t\t\tif (error) {\n\t\t\t\t\t\t\treject(new Error(`Failed to get token: ${error.stack}`));\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tresolve({ stdout, stderr });\n\t\t\t\t\t}\n\t\t\t\t);\n\t\t\t} catch (error) {\n\t\t\t\treject(error as Error);\n\t\t\t}\n\t\t});\n\t}\n\n\t/**\n\t * Parses the raw CLI output and returns a token + expiry object.\n\t * @param output The stdout from Azure CLI\n\t * @returns An object with token and expiresAt\n\t * @private\n\t */\n\tprivate parseRawOutput(output: string) {\n\t\tconst response = JSON.parse(output) as CLITokenResponse;\n\t\tconst token = response.accessToken;\n\n\t\t// if available, expires_on will be a number representing seconds since epoch.\n\t\t// ensure it's a number or NaN\n\t\tconst expiresOnTimestamp = Number.parseInt(response.expires_on, 10) * 1_000;\n\t\tif (!Number.isNaN(expiresOnTimestamp)) {\n\t\t\treturn {\n\t\t\t\taccessToken: token,\n\t\t\t\texpiresAt: new Date(expiresOnTimestamp),\n\t\t\t\ttokenType: response.tokenType\n\t\t\t};\n\t\t}\n\n\t\t// fallback to the older expiresOn - an RFC3339 date string\n\t\treturn {\n\t\t\taccessToken: token,\n\t\t\texpiresAt: new Date(response.expiresOn),\n\t\t\ttokenType: response.tokenType\n\t\t};\n\t}\n\n\t/**\n\t * Instantiates AzureCliCredential using the AZURE_TENANT_ID environment variable.\n\t * @returns AzureCliCredential instance\n\t */\n\tpublic static fromEnv() {\n\t\treturn new AzureCliCredential({ tenantId: process.env.AZURE_TENANT_ID });\n\t}\n}\n\ndeclare global {\n\tnamespace NodeJS {\n\t\tinterface ProcessEnv {\n\t\t\tAZURE_TENANT_ID: string;\n\t\t}\n\t}\n}\n","/**\n * Represents an Azure access token and its expiration.\n */\nexport type Credential = { accessToken: string; clientId?: string; expiresAt: Date; tokenType: string };\n\n/**\n * Abstract credential class for acquiring Azure tokens.\n * Implement this to provide custom authentication logic.\n */\nexport abstract class AzureCredential {\n\t/**\n\t * Gets an Azure access token for the given scope.\n\t * @param scope The resource or scope for which the token is requested\n\t * @returns A promise resolving to an AzureToken\n\t */\n\tpublic abstract getToken(scope: string): Promise<Credential>;\n}\n","import type { AzureCredential } from \"./AzureCredential.js\";\nimport type { OAuth2TokenResponse } from \"./ServicePrincipalCredential.js\";\n\n/**\n * Options for configuring ManagedIdentityCredential.\n *\n * @property clientId - (Optional) The user-assigned managed identity client ID\n */\nexport type ManagedIdentityCredentialOptions = {\n\tclientId?: string;\n};\n\n/**\n * AzureCredential implementation for Azure Managed Identity (MSI).\n *\n * Supports both system-assigned and user-assigned managed identities.\n * Works on Azure VM, App Service, Container Apps, etc.\n */\nexport class ManagedIdentityCredential implements AzureCredential {\n\t/**\n\t * @param options Managed identity credential options\n\t */\n\tpublic constructor(public options: ManagedIdentityCredentialOptions = {}) {}\n\n\t/**\n\t * Gets an Azure access token using the managed identity endpoint.\n\t * @param scope The resource scope for the token\n\t * @returns An object with token and expiresAt\n\t * @throws If the endpoint is unavailable or token request fails\n\t */\n\tpublic async getToken(scope: string) {\n\t\tconst endpoint = process.env.AZURE_MANAGED_IDENTITY_ENDPOINT || process.env.IDENTITY_ENDPOINT || \"http://169.254.169.254/metadata/identity/oauth2/token\";\n\t\tconst apiVersion = \"2018-02-01\";\n\t\tconst params = new URLSearchParams({\n\t\t\tresource: scope.replace(\".default\", \"\"),\n\t\t\tapiVersion\n\t\t});\n\t\tif (this.options.clientId) {\n\t\t\tparams.set(\"client_id\", this.options.clientId);\n\t\t}\n\n\t\tconst url = `${endpoint}?${params.toString()}`;\n\t\tconst headers = { Metadata: \"true\" };\n\n\t\tconst response = await fetch(url, { headers });\n\t\tif (!response.ok) {\n\t\t\tthrow new Error(`ManagedIdentityCredential: Failed to get token: ${await response.text()}`);\n\t\t}\n\n\t\tconst data = (await response.json()) as OAuth2TokenResponse;\n\t\treturn {\n\t\t\taccessToken: data.access_token,\n\t\t\tclientId: data.client_id,\n\t\t\texpiresAt: new Date(data.expires_on ? Number(data.expires_on) * 1000 : Date.now() + 60 * 60 * 1000), // fallback 1h\n\t\t\ttokenType: data.token_type\n\t\t};\n\t}\n\n\t/**\n\t * Instantiates ManagedIdentityCredential using environment variables.\n\t * @returns ManagedIdentityCredential instance\n\t */\n\tpublic static fromEnv() {\n\t\treturn new ManagedIdentityCredential({ clientId: process.env.AZURE_CLIENT_ID });\n\t}\n}\n\ndeclare global {\n\tnamespace NodeJS {\n\t\tinterface ProcessEnv {\n\t\t\tAZURE_MANAGED_IDENTITY_ENDPOINT?: string;\n\t\t\tIDENTITY_ENDPOINT?: string;\n\t\t}\n\t}\n}\n","import { URLSearchParams } from \"node:url\";\nimport type { AzureCredential } from \"./AzureCredential.js\";\n\n/**\n * The OAuth2 token response returned by Azure AD and Managed Identity endpoints.\n *\n * @property access_token - The access token string\n * @property client_id - The client/application ID (optional, present in MSI)\n * @property expires_in - Seconds until token expiry\n * @property expires_on - Expiry time (epoch seconds, as string)\n * @property ext_expires_in - Extended expiry in seconds\n * @property not_before - Not before time (epoch seconds, as string)\n * @property resource - The resource for which the token is issued\n * @property token_type - The type of token (usually 'Bearer')\n */\nexport type OAuth2TokenResponse = {\n\taccess_token: string;\n\tclient_id?: string;\n\texpires_in: number;\n\texpires_on: string;\n\text_expires_in: number;\n\tnot_before: string;\n\tresource: string;\n\ttoken_type: string;\n};\n\n/**\n * Options for configuring ServicePrincipalCredential.\n *\n * @property clientId - The Azure AD application (client) ID\n * @property clientSecret - The client secret or JWT assertion (for federated)\n * @property tenantId - The Azure AD tenant ID\n * @property authorityHost - (Optional) The Azure AD authority host\n * @property federated - Whether to use federated (JWT) auth\n */\nexport type ServicePrincipalCredentialOption = {\n\tclientId: string;\n\tclientSecret?: string;\n\ttenantId: string;\n\tauthorityHost?: string;\n\tfederated: boolean;\n};\n\n/**\n * AzureCredential implementation for authenticating with a Service Principal (client secret or federated/JWT).\n */\nexport class ServicePrincipalCredential implements AzureCredential {\n\t/**\n\t * @param options Service principal credential options\n\t */\n\tpublic constructor(public options: ServicePrincipalCredentialOption) {}\n\n\t/**\n\t * Gets an Azure access token using the service principal credentials.\n\t * @param scope The resource scope for the token\n\t * @returns An object with token and expiresAt\n\t * @throws If client secret is missing or token request fails\n\t */\n\tpublic async getToken(scope: string) {\n\t\tif (!this.options.clientSecret) throw new Error(\"ServicePrincipalCredential: The client secret is not provided.\");\n\n\t\t// Remove trailing slash from identityAuthorityHost\n\t\tconst url = [this.options.authorityHost?.replace(/\\/$/, \"\") ?? \"https://login.microsoftonline.com\", `${this.options.tenantId}/oauth2/v2.0/token`].join(\"/\");\n\n\t\ttry {\n\t\t\tconst searchParams = {\n\t\t\t\tclient_id: this.options.clientId,\n\t\t\t\tgrant_type: \"client_credentials\",\n\t\t\t\tscope\n\t\t\t};\n\n\t\t\t// If federated, use client_assertion and client_assertion_type\n\t\t\t// Otherwise, use client_secret\n\t\t\tif (this.options.federated) {\n\t\t\t\tObject.assign(searchParams, {\n\t\t\t\t\tclient_assertion: this.options.clientSecret,\n\t\t\t\t\tclient_assertion_type: \"urn:ietf:params:oauth:client-assertion-type:jwt-bearer\"\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tObject.assign(searchParams, {\n\t\t\t\t\tclient_secret: this.options.clientSecret\n\t\t\t\t});\n\t\t\t}\n\t\t\tconst response = await fetch(url, {\n\t\t\t\tmethod: \"POST\",\n\t\t\t\theaders: {\n\t\t\t\t\tAccept: \"application/json\",\n\t\t\t\t\t\"Content-Type\": \"application/x-www-form-urlencoded\"\n\t\t\t\t},\n\t\t\t\tbody: new URLSearchParams(searchParams)\n\t\t\t});\n\n\t\t\tif (!response.ok) {\n\t\t\t\tthrow new Error(`Failed to get token: ${await response.text()}`);\n\t\t\t}\n\n\t\t\tconst data = (await response.json()) as OAuth2TokenResponse;\n\n\t\t\treturn {\n\t\t\t\taccessToken: data.access_token,\n\t\t\t\tclientId: data.client_id ?? this.options.clientId,\n\t\t\t\texpiresAt: new Date(Date.now() + data.expires_in * 1_000),\n\t\t\t\ttokenType: data.token_type\n\t\t\t};\n\t\t} catch (error) {\n\t\t\tthrow new Error(`Failed to get token: ${(error as Error).stack}`);\n\t\t}\n\t}\n\n\t/**\n\t * Instantiates ServicePrincipalCredential using environment variables.\n\t * @returns ServicePrincipalCredential instance\n\t */\n\tpublic static fromEnv() {\n\t\treturn new ServicePrincipalCredential({\n\t\t\tclientId: process.env.AZURE_CLIENT_ID,\n\t\t\tclientSecret: process.env.AZURE_CLIENT_SECRET,\n\t\t\ttenantId: process.env.AZURE_TENANT_ID,\n\t\t\tfederated: false\n\t\t});\n\t}\n}\n\ndeclare global {\n\tnamespace NodeJS {\n\t\tinterface ProcessEnv {\n\t\t\tAZURE_CLIENT_ID: string;\n\t\t\tAZURE_CLIENT_SECRET: string;\n\t\t\tAZURE_TENANT_ID: string;\n\t\t}\n\t}\n}\n","import { existsSync, readFileSync } from \"node:fs\";\nimport type { AzureCredential } from \"./AzureCredential.js\";\nimport { ServicePrincipalCredential } from \"./ServicePrincipalCredential.js\";\n\n/**\n * Options for configuring WorkloadIdentityCredential.\n *\n * @property clientId - The Azure AD application (client) ID\n * @property federatedTokenFile - Path to the federated token file (OIDC/JWT)\n * @property tenantId - The Azure AD tenant ID\n * @property authorityHost - (Optional) The Azure AD authority host\n */\nexport type WorkloadIdentityCredentialOption = {\n\tclientId: string;\n\tfederatedTokenFile: string;\n\ttenantId: string;\n\tauthorityHost?: string;\n};\n\n/**\n * AzureCredential implementation for Azure Workload Identity (OIDC federated token).\n *\n * Reads a federated token from file and authenticates as a service principal using JWT assertion.\n */\nexport class WorkloadIdentityCredential implements AzureCredential {\n\t/**\n\t * @param options Workload identity credential options\n\t */\n\tpublic constructor(public options: WorkloadIdentityCredentialOption) {}\n\n\t/**\n\t * Gets an Azure access token using the federated token file.\n\t * @param scope The resource scope for the token\n\t * @returns An object with token and expiresAt\n\t * @throws If the federated token file does not exist\n\t */\n\tpublic async getToken(scope: string) {\n\t\tif (!existsSync(this.options.federatedTokenFile)) {\n\t\t\tthrow new Error(\"WorkloadIdentityCredential: The federated token file does not exist.\");\n\t\t}\n\n\t\tconst token = readFileSync(this.options.federatedTokenFile, \"utf-8\");\n\t\tconst servicePrincipal = new ServicePrincipalCredential({ ...this.options, clientSecret: token, federated: true });\n\n\t\treturn servicePrincipal.getToken(scope);\n\t}\n\n\t/**\n\t * Instantiates WorkloadIdentityCredential using environment variables.\n\t * @returns WorkloadIdentityCredential instance\n\t */\n\tpublic static fromEnv() {\n\t\treturn new WorkloadIdentityCredential({\n\t\t\tauthorityHost: process.env.AZURE_AUTHORITY_HOST,\n\t\t\tclientId: process.env.AZURE_CLIENT_ID,\n\t\t\tfederatedTokenFile: process.env.AZURE_FEDERATED_TOKEN_FILE,\n\t\t\ttenantId: process.env.AZURE_TENANT_ID\n\t\t});\n\t}\n}\n\ndeclare global {\n\tnamespace NodeJS {\n\t\tinterface ProcessEnv {\n\t\t\tAZURE_AUTHORITY_HOST: string;\n\t\t\tAZURE_CLIENT_ID: string;\n\t\t\tAZURE_FEDERATED_TOKEN_FILE: string;\n\t\t\tAZURE_TENANT_ID: string;\n\t\t}\n\t}\n}\n","import { AzureCliCredential } from \"./AzureCliCredential.js\";\nimport type { AzureCredential } from \"./AzureCredential.js\";\nimport { ManagedIdentityCredential } from \"./ManagedIdentityCredential.js\";\nimport { ServicePrincipalCredential } from \"./ServicePrincipalCredential.js\";\nimport { WorkloadIdentityCredential } from \"./WorkloadIdentityCredential.js\";\n\nconst credentialChain = [WorkloadIdentityCredential, ManagedIdentityCredential, ServicePrincipalCredential, AzureCliCredential];\n\n/**\n * DefaultChainedCredential tries multiple credential providers in order until one succeeds.\n *\n * The chain is: WorkloadIdentityCredential → ManagedIdentityCredential → ServicePrincipalCredential → AzureCliCredential.\n * Useful for local dev, CI, and cloud environments with minimal config.\n */\nexport class DefaultChainedCredential implements AzureCredential {\n\t/**\n\t * Attempts to get an Azure access token using the first available credential in the chain.\n\t * @param scope The resource scope for the token\n\t * @returns An object with token and expiresAt\n\t * @throws If all credential providers fail\n\t */\n\tpublic async getToken(scope: string) {\n\t\tconst errors: { name: string; error: Error }[] = [];\n\t\tfor (const Credential of credentialChain) {\n\t\t\ttry {\n\t\t\t\treturn await Credential.fromEnv().getToken(scope);\n\t\t\t} catch (error) {\n\t\t\t\terrors.push({ error: error as Error, name: Credential.name });\n\t\t\t}\n\t\t}\n\n\t\tthrow new Error(`Failed to get token, errors:\\n${errors.map(err => `[${err.name}] ${err.error.message}`).join(\"\\n\")}`);\n\t}\n}\n"],"mappings":"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","names":["process"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/AzureClient.ts","../src/lib/AzureCliCredential.ts","../src/lib/AzureCredential.ts","../src/lib/ManagedIdentityCredential.ts","../src/lib/ServicePrincipalCredential.ts","../src/lib/WorkloadIdentityCredential.ts","../src/lib/DefaultChainedCredential.ts"],"sourcesContent":["export * from \"./AzureClient.js\";\nexport * from \"./lib/AzureCliCredential.js\";\nexport * from \"./lib/AzureCredential.js\";\nexport * from \"./lib/DefaultChainedCredential.js\";\nexport * from \"./lib/ManagedIdentityCredential.js\";\nexport * from \"./lib/ServicePrincipalCredential.js\";\nexport * from \"./lib/WorkloadIdentityCredential.js\";\n","import type { AzureCredential, Credential } from \"./lib/AzureCredential.js\";\n\n/**\n * Options for configuring the AzureClient instance.\n *\n * @property baseUrl - The base URL for Azure REST API endpoints (e.g. https://management.azure.com)\n * @property credential - Credential configuration for authenticating requests\n * @property helper - An AzureCredential implementation for acquiring tokens\n * @property scope - The Azure resource scope for the token (e.g. https://management.azure.com/.default)\n * @property builder - (Optional) Function to build request headers from a token. If not provided, an Authorization header is set by default.\n */\nexport type AzureClientOptions = {\n\tbaseUrl: string;\n\tcredential: {\n\t\thelper: AzureCredential;\n\t\tscope: string;\n\t\tbuilder?: (token: Credential) => Record<string, string>;\n\t};\n};\n\n/**\n * Azure REST API client with credential refresh and HTTP verb helpers.\n */\nexport class AzureClient {\n\tprivate static readonly MAX_TOKEN_RETRIES = 3;\n\tprivate token: Credential | null = null;\n\n\t/**\n\t * @param options Azure client configuration (baseUrl, credential, etc)\n\t */\n\tconstructor(public options: AzureClientOptions) {\n\t\tObject.defineProperty(this, \"token\", { enumerable: false });\n\t}\n\n\t/**\n\t * Sends a request to the Azure REST API, handling token refresh and retries.\n\t * @param path The API path (relative to baseUrl)\n\t * @param init Optional fetch options\n\t * @returns The fetch Response object\n\t * @throws If token refresh fails after max retries\n\t */\n\tpublic async sendRequest(path: string, init?: RequestInit): Promise<Response> {\n\t\tfor (let i = 0; i <= AzureClient.MAX_TOKEN_RETRIES; i++) {\n\t\t\tif (this.token && this.token.expiresAt > new Date()) break;\n\t\t\tif (i === AzureClient.MAX_TOKEN_RETRIES) {\n\t\t\t\tthrow new Error(\"Failed to refresh token after multiple attempts\");\n\t\t\t}\n\t\t\tawait this.refreshToken();\n\t\t\tif (i > 0) await new Promise(res => setTimeout(res, 100 * i));\n\t\t}\n\n\t\tif (!this.token) throw new Error(\"Token is unexpectedly null after refresh attempts\");\n\n\t\t// Normalize baseUrl and path to avoid double or missing slashes\n\t\tconst baseUrl = this.options.baseUrl.replace(/\\/+$/, \"\");\n\t\tconst relPath = path.replace(/^\\/+/, \"\");\n\t\tconst url = `${baseUrl}/${relPath}`;\n\n\t\treturn fetch(url, {\n\t\t\t...init,\n\t\t\theaders: {\n\t\t\t\t...(this.options.credential.builder ? this.options.credential.builder(this.token) : { Authorization: `Bearer ${this.token.accessToken}` }),\n\t\t\t\t...init?.headers\n\t\t\t}\n\t\t});\n\t}\n\n\t/**\n\t * Sends a GET request to the Azure REST API.\n\t * @param path The API path\n\t * @param init Optional fetch options\n\t * @returns The fetch Response object\n\t */\n\tpublic get(path: string, init?: RequestInit) {\n\t\treturn this.sendRequest(path, { ...init, method: \"GET\" });\n\t}\n\n\t/**\n\t * Sends a POST request with a JSON body to the Azure REST API.\n\t * @param path The API path\n\t * @param body The request body (will be JSON.stringified)\n\t * @param init Optional fetch options\n\t * @returns The fetch Response object\n\t */\n\tpublic post(path: string, body?: any, init?: RequestInit) {\n\t\treturn this.sendRequest(path, {\n\t\t\t...init,\n\t\t\tmethod: \"POST\",\n\t\t\theaders: {\n\t\t\t\t\"Content-Type\": \"application/json\",\n\t\t\t\t...init?.headers\n\t\t\t},\n\t\t\tbody: body !== undefined ? JSON.stringify(body) : undefined\n\t\t});\n\t}\n\n\t/**\n\t * Sends a PUT request with a JSON body to the Azure REST API.\n\t * @param path The API path\n\t * @param body The request body (will be JSON.stringified)\n\t * @param init Optional fetch options\n\t * @returns The fetch Response object\n\t */\n\tpublic put(path: string, body?: any, init?: RequestInit) {\n\t\treturn this.sendRequest(path, {\n\t\t\t...init,\n\t\t\tmethod: \"PUT\",\n\t\t\theaders: {\n\t\t\t\t\"Content-Type\": \"application/json\",\n\t\t\t\t...init?.headers\n\t\t\t},\n\t\t\tbody: body !== undefined ? JSON.stringify(body) : undefined\n\t\t});\n\t}\n\n\t/**\n\t * Sends a PATCH request with a JSON body to the Azure REST API.\n\t * @param path The API path\n\t * @param body The request body (will be JSON.stringified)\n\t * @param init Optional fetch options\n\t * @returns The fetch Response object\n\t */\n\tpublic patch(path: string, body?: any, init?: RequestInit) {\n\t\treturn this.sendRequest(path, {\n\t\t\t...init,\n\t\t\tmethod: \"PATCH\",\n\t\t\theaders: {\n\t\t\t\t\"Content-Type\": \"application/json\",\n\t\t\t\t...init?.headers\n\t\t\t},\n\t\t\tbody: body !== undefined ? JSON.stringify(body) : undefined\n\t\t});\n\t}\n\n\t/**\n\t * Sends a DELETE request to the Azure REST API.\n\t * @param path The API path\n\t * @param init Optional fetch options\n\t * @returns The fetch Response object\n\t */\n\tpublic delete(path: string, init?: RequestInit) {\n\t\treturn this.sendRequest(path, { ...init, method: \"DELETE\" });\n\t}\n\n\t/**\n\t * Refreshes the Azure access token using the provided credential helper.\n\t * @private\n\t */\n\tprivate async refreshToken(): Promise<void> {\n\t\tthis.token = await this.options.credential.helper.getToken(this.options.credential.scope);\n\t}\n}\n","import { execFile } from \"node:child_process\";\nimport process from \"node:process\";\nimport type { AzureCredential } from \"./AzureCredential.js\";\n\n/**\n * The raw response returned by Azure CLI when requesting an access token.\n *\n * @property accessToken - The access token string\n * @property expiresOn - Expiry date in RFC3339 format (legacy)\n * @property expires_on - Expiry as seconds since epoch (preferred)\n * @property subscription - (Optional) Subscription ID, may not be present\n * @property tenant - Tenant ID\n * @property tokenType - Token type (usually 'Bearer')\n */\nexport type CLITokenResponse = {\n\taccessToken: string;\n\texpiresOn: string;\n\texpires_on: string;\n\tsubscription?: string;\n\ttenant: string;\n\ttokenType: string;\n};\n\n/**\n * Options for AzureCliCredential.\n *\n * @property tenantId - The Azure tenant ID to use for authentication.\n */\nexport type AzureCLICredentialOptions = {\n\ttenantId: string;\n};\n\nexport class AzureCliCredential implements AzureCredential {\n\tpublic constructor(public options: AzureCLICredentialOptions) {}\n\n\t/**\n\t * Gets an Azure access token using the Azure CLI.\n\t * @param scope The resource scope for the token\n\t * @returns An object with token and expiresAt\n\t * @throws If CLI is not installed or not logged in\n\t */\n\tpublic async getToken(scope: string) {\n\t\ttry {\n\t\t\tconst result = await this.getCliToken(scope);\n\n\t\t\tconst specificScope = result.stderr.match(\"(.*)az login --scope(.*)\");\n\t\t\tconst isLoginError = result.stderr.match(\"(.*)az login(.*)\") && !specificScope;\n\t\t\tconst isNotInstallError = result.stderr.match(\"az:(.*)not found\") ?? result.stderr.startsWith(\"'az' is not recognized\");\n\n\t\t\tif (isNotInstallError) {\n\t\t\t\tthrow new Error(\"Azure CLI not found. Please install\");\n\t\t\t}\n\t\t\tif (isLoginError) {\n\t\t\t\tthrow new Error(\"Please login to Azure CLI\");\n\t\t\t}\n\n\t\t\treturn this.parseRawOutput(result.stdout);\n\t\t} catch (error) {\n\t\t\tthrow new Error(`Failed to get token: ${(error as Error).stack}`);\n\t\t}\n\t}\n\n\t/**\n\t * Runs the Azure CLI to get an access token for the given scope.\n\t * @param scope The resource scope\n\t * @returns Promise resolving to CLI stdout and stderr\n\t * @private\n\t */\n\tprivate async getCliToken(scope: string) {\n\t\treturn new Promise<{ stderr: string; stdout: string }>((resolve, reject) => {\n\t\t\ttry {\n\t\t\t\texecFile(\n\t\t\t\t\t\"az\",\n\t\t\t\t\t[\"account\", \"get-access-token\", \"--output\", \"json\", \"--resource\", scope.replace(\".default\", \"\"), \"--tenant\", this.options.tenantId],\n\t\t\t\t\t{ cwd: process.cwd(), shell: true, timeout: 30_000 },\n\t\t\t\t\t(error, stdout, stderr) => {\n\t\t\t\t\t\tif (error) {\n\t\t\t\t\t\t\treject(new Error(`Failed to get token: ${error.stack}`));\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tresolve({ stdout, stderr });\n\t\t\t\t\t}\n\t\t\t\t);\n\t\t\t} catch (error) {\n\t\t\t\treject(error as Error);\n\t\t\t}\n\t\t});\n\t}\n\n\t/**\n\t * Parses the raw CLI output and returns a token + expiry object.\n\t * @param output The stdout from Azure CLI\n\t * @returns An object with token and expiresAt\n\t * @private\n\t */\n\tprivate parseRawOutput(output: string) {\n\t\tconst response = JSON.parse(output) as CLITokenResponse;\n\t\tconst token = response.accessToken;\n\n\t\t// if available, expires_on will be a number representing seconds since epoch.\n\t\t// ensure it's a number or NaN\n\t\tconst expiresOnTimestamp = Number.parseInt(response.expires_on, 10) * 1_000;\n\t\tif (!Number.isNaN(expiresOnTimestamp)) {\n\t\t\treturn {\n\t\t\t\taccessToken: token,\n\t\t\t\texpiresAt: new Date(expiresOnTimestamp),\n\t\t\t\ttokenType: response.tokenType\n\t\t\t};\n\t\t}\n\n\t\t// fallback to the older expiresOn - an RFC3339 date string\n\t\treturn {\n\t\t\taccessToken: token,\n\t\t\texpiresAt: new Date(response.expiresOn),\n\t\t\ttokenType: response.tokenType\n\t\t};\n\t}\n\n\t/**\n\t * Instantiates AzureCliCredential using the AZURE_TENANT_ID environment variable.\n\t * This expects the following environment variable to be set:\n\t * - AZURE_TENANT_ID: The Azure tenant ID to use for authentication.\n\t * @returns AzureCliCredential instance\n\t */\n\tpublic static fromEnv() {\n\t\treturn new AzureCliCredential({ tenantId: process.env.AZURE_TENANT_ID });\n\t}\n}\n\ndeclare global {\n\tnamespace NodeJS {\n\t\tinterface ProcessEnv {\n\t\t\tAZURE_TENANT_ID: string;\n\t\t}\n\t}\n}\n","/**\n * Represents an Azure access token and its expiration.\n */\nexport type Credential = { accessToken: string; clientId?: string; expiresAt: Date; tokenType: string };\n\n/**\n * Abstract credential class for acquiring Azure tokens.\n * Implement this to provide custom authentication logic.\n */\nexport abstract class AzureCredential {\n\t/**\n\t * Gets an Azure access token for the given scope.\n\t * @param scope The resource or scope for which the token is requested\n\t * @returns A promise resolving to an AzureToken\n\t */\n\tpublic abstract getToken(scope: string): Promise<Credential>;\n}\n","import type { AzureCredential } from \"./AzureCredential.js\";\nimport type { OAuth2TokenResponse } from \"./ServicePrincipalCredential.js\";\n\n/**\n * Options for configuring ManagedIdentityCredential.\n *\n * @property clientId - (Optional) The user-assigned managed identity client ID.\n * @property timeoutMs - (Optional) Timeout in milliseconds for metadata endpoint fetch. Default: 300ms.\n */\nexport type ManagedIdentityCredentialOptions = {\n\tidentityEndpoint?: string; // Optional: custom endpoint, defaults to Azure's default metadata endpoint\n\tclientId?: string;\n\ttimeoutMs?: number; // Optional: custom timeout for fetch\n};\n\n/**\n * AzureCredential implementation for Azure Managed Identity (MSI).\n *\n * Supports both system-assigned and user-assigned managed identities.\n * Works on Azure VM, App Service, Container Apps, etc.\n */\nexport class ManagedIdentityCredential implements AzureCredential {\n\t/**\n\t * @param options Managed identity credential options\n\t */\n\tpublic constructor(public options: ManagedIdentityCredentialOptions = {}) {}\n\n\t/**\n\t * Gets an Azure access token using the managed identity endpoint.\n\t * @param scope The resource scope for the token\n\t * @returns An object with token and expiresAt\n\t * @throws If the endpoint is unavailable or token request fails\n\t */\n\tpublic async getToken(scope: string) {\n\t\tconst endpoint = this.options.identityEndpoint || \"http://169.254.169.254/metadata/identity/oauth2/token\";\n\t\tconst apiVersion = \"2018-02-01\";\n\t\tconst params = new URLSearchParams({\n\t\t\tresource: scope.replace(\".default\", \"\"),\n\t\t\tapiVersion\n\t\t});\n\t\tif (this.options.clientId) {\n\t\t\tparams.set(\"client_id\", this.options.clientId);\n\t\t}\n\n\t\tconst url = `${endpoint}?${params.toString()}`;\n\t\tconst headers = { Metadata: \"true\" };\n\n\t\t// Add timeout to fetch (default 500ms, can override via options)\n\t\tconst timeoutMs = this.options.timeoutMs ?? 300;\n\t\tconst controller = new AbortController();\n\t\tconst timeout = setTimeout(() => controller.abort(), timeoutMs);\n\n\t\tlet response: Response;\n\t\ttry {\n\t\t\tresponse = await fetch(url, { headers, signal: controller.signal });\n\t\t} catch (err: any) {\n\t\t\tif (err.name === \"AbortError\") {\n\t\t\t\tthrow new Error(`ManagedIdentityCredential: Timed out after ${timeoutMs}ms waiting for metadata endpoint (${url})`);\n\t\t\t}\n\t\t\tthrow err;\n\t\t} finally {\n\t\t\tclearTimeout(timeout);\n\t\t}\n\n\t\tif (!response.ok) {\n\t\t\tthrow new Error(`ManagedIdentityCredential: Failed to get token: ${await response.text()}`);\n\t\t}\n\n\t\tconst data = (await response.json()) as OAuth2TokenResponse;\n\t\treturn {\n\t\t\taccessToken: data.access_token,\n\t\t\tclientId: data.client_id,\n\t\t\texpiresAt: new Date(data.expires_on ? Number(data.expires_on) * 1000 : Date.now() + 60 * 60 * 1000), // fallback 1h\n\t\t\ttokenType: data.token_type\n\t\t};\n\t}\n\n\t/**\n\t * Instantiates ManagedIdentityCredential using environment variables.\n\t * This expects the following environment variables to be set:\n\t * - AZURE_CLIENT_ID: The user-assigned managed identity client ID. This is optional for system-assigned identities.\n\t * - AZURE_MANAGED_IDENTITY_ENDPOINT or IDENTITY_ENDPOINT: The managed identity endpoint (optional, defaults to http://169.254.169.254/metadata/identity/oauth2/token)\n\t * - AZURE_MANAGED_IDENTITY_TIMEOUT_MS: Custom timeout for metadata endpoint fetch in milliseconds (optional).\n\t * @returns ManagedIdentityCredential instance\n\t */\n\tpublic static fromEnv() {\n\t\treturn new ManagedIdentityCredential({\n\t\t\tidentityEndpoint: process.env.AZURE_MANAGED_IDENTITY_ENDPOINT || process.env.IDENTITY_ENDPOINT,\n\t\t\tclientId: process.env.AZURE_CLIENT_ID,\n\t\t\ttimeoutMs: process.env.AZURE_MANAGED_IDENTITY_TIMEOUT_MS ? Number.parseInt(process.env.AZURE_MANAGED_IDENTITY_TIMEOUT_MS) : undefined\n\t\t});\n\t}\n}\n\ndeclare global {\n\tnamespace NodeJS {\n\t\tinterface ProcessEnv {\n\t\t\tAZURE_MANAGED_IDENTITY_ENDPOINT?: string;\n\t\t\tAZURE_MANAGED_IDENTITY_TIMEOUT_MS?: string; // Optional: custom timeout for fetch\n\t\t\tIDENTITY_ENDPOINT?: string;\n\t\t}\n\t}\n}\n","import { URLSearchParams } from \"node:url\";\nimport type { AzureCredential } from \"./AzureCredential.js\";\n\n/**\n * The OAuth2 token response returned by Azure AD and Managed Identity endpoints.\n *\n * @property access_token - The access token string\n * @property client_id - The client/application ID (optional, present in MSI)\n * @property expires_in - Seconds until token expiry\n * @property expires_on - Expiry time (epoch seconds, as string)\n * @property ext_expires_in - Extended expiry in seconds\n * @property not_before - Not before time (epoch seconds, as string)\n * @property resource - The resource for which the token is issued\n * @property token_type - The type of token (usually 'Bearer')\n */\nexport type OAuth2TokenResponse = {\n\taccess_token: string;\n\tclient_id?: string;\n\texpires_in: number;\n\texpires_on: string;\n\text_expires_in: number;\n\tnot_before: string;\n\tresource: string;\n\ttoken_type: string;\n};\n\n/**\n * Options for configuring ServicePrincipalCredential.\n *\n * @property clientId - The Azure AD application (client) ID.\n * @property clientSecret - The client secret or JWT assertion (for federated).\n * @property tenantId - The Azure AD tenant ID.\n * @property authorityHost - (Optional) The Azure AD authority host. Defaults to \"https://login.microsoftonline.com\".\n * @property federated - Whether to use federated (JWT) auth. If true, clientSecret is treated as a JWT assertion.\n */\nexport type ServicePrincipalCredentialOption = {\n\tclientId: string;\n\tclientSecret?: string;\n\ttenantId: string;\n\tauthorityHost?: string;\n\tfederated: boolean;\n};\n\n/**\n * AzureCredential implementation for authenticating with a Service Principal (client secret or federated/JWT).\n */\nexport class ServicePrincipalCredential implements AzureCredential {\n\t/**\n\t * @param options Service principal credential options\n\t */\n\tpublic constructor(public options: ServicePrincipalCredentialOption) {}\n\n\t/**\n\t * Gets an Azure access token using the service principal credentials.\n\t * @param scope The resource scope for the token\n\t * @returns An object with token and expiresAt\n\t * @throws If client secret is missing or token request fails\n\t */\n\tpublic async getToken(scope: string) {\n\t\tif (!this.options.clientSecret) throw new Error(\"ServicePrincipalCredential: The client secret is not provided.\");\n\n\t\t// Remove trailing slash from identityAuthorityHost\n\t\tconst url = [this.options.authorityHost?.replace(/\\/$/, \"\") ?? \"https://login.microsoftonline.com\", `${this.options.tenantId}/oauth2/v2.0/token`].join(\"/\");\n\n\t\ttry {\n\t\t\tconst searchParams = {\n\t\t\t\tclient_id: this.options.clientId,\n\t\t\t\tgrant_type: \"client_credentials\",\n\t\t\t\tscope\n\t\t\t};\n\n\t\t\t// If federated, use client_assertion and client_assertion_type\n\t\t\t// Otherwise, use client_secret\n\t\t\tif (this.options.federated) {\n\t\t\t\tObject.assign(searchParams, {\n\t\t\t\t\tclient_assertion: this.options.clientSecret,\n\t\t\t\t\tclient_assertion_type: \"urn:ietf:params:oauth:client-assertion-type:jwt-bearer\"\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tObject.assign(searchParams, {\n\t\t\t\t\tclient_secret: this.options.clientSecret\n\t\t\t\t});\n\t\t\t}\n\t\t\tconst response = await fetch(url, {\n\t\t\t\tmethod: \"POST\",\n\t\t\t\theaders: {\n\t\t\t\t\tAccept: \"application/json\",\n\t\t\t\t\t\"Content-Type\": \"application/x-www-form-urlencoded\"\n\t\t\t\t},\n\t\t\t\tbody: new URLSearchParams(searchParams)\n\t\t\t});\n\n\t\t\tif (!response.ok) {\n\t\t\t\tthrow new Error(`Failed to get token: ${await response.text()}`);\n\t\t\t}\n\n\t\t\tconst data = (await response.json()) as OAuth2TokenResponse;\n\n\t\t\treturn {\n\t\t\t\taccessToken: data.access_token,\n\t\t\t\tclientId: data.client_id ?? this.options.clientId,\n\t\t\t\texpiresAt: new Date(Date.now() + data.expires_in * 1_000),\n\t\t\t\ttokenType: data.token_type\n\t\t\t};\n\t\t} catch (error) {\n\t\t\tthrow new Error(`Failed to get token: ${(error as Error).stack}`);\n\t\t}\n\t}\n\n\t/**\n\t * Instantiates ServicePrincipalCredential using environment variables.\n\t * This expects the following environment variables to be set:\n\t * - AZURE_CLIENT_ID: The Azure AD application (client) ID\n\t * - AZURE_CLIENT_SECRET: The client secret\n\t * - AZURE_TENANT_ID: The Azure AD tenant ID\n\t * - AZURE_USE_FEDERATED_AUTH: Optional, if set to \"true\", uses federated authentication (JWT assertion).\n\t * @returns ServicePrincipalCredential instance\n\t */\n\tpublic static fromEnv() {\n\t\treturn new ServicePrincipalCredential({\n\t\t\tauthorityHost: process.env.AZURE_AUTHORITY_HOST,\n\t\t\tclientId: process.env.AZURE_CLIENT_ID,\n\t\t\tclientSecret: process.env.AZURE_CLIENT_SECRET,\n\t\t\ttenantId: process.env.AZURE_TENANT_ID,\n\t\t\tfederated: process.env.AZURE_USE_FEDERATED_AUTH === \"true\"\n\t\t});\n\t}\n}\n\ndeclare global {\n\tnamespace NodeJS {\n\t\tinterface ProcessEnv {\n\t\t\tAZURE_CLIENT_ID: string;\n\t\t\tAZURE_CLIENT_SECRET: string;\n\t\t\tAZURE_TENANT_ID: string;\n\t\t\tAZURE_USE_FEDERATED_AUTH: \"true\" | \"false\"; // Optional, defaults to \"false\"\n\t\t}\n\t}\n}\n","import { existsSync, readFileSync } from \"node:fs\";\nimport type { AzureCredential } from \"./AzureCredential.js\";\nimport { ServicePrincipalCredential } from \"./ServicePrincipalCredential.js\";\n\n/**\n * Options for configuring WorkloadIdentityCredential.\n *\n * @property clientId - The Azure AD application (client) ID\n * @property federatedTokenFile - Path to the federated token file (OIDC/JWT)\n * @property tenantId - The Azure AD tenant ID\n * @property authorityHost - (Optional) The Azure AD authority host\n */\nexport type WorkloadIdentityCredentialOption = {\n\tclientId: string;\n\tfederatedTokenFile: string;\n\ttenantId: string;\n\tauthorityHost?: string;\n};\n\n/**\n * AzureCredential implementation for Azure Workload Identity (OIDC federated token).\n *\n * Reads a federated token from file and authenticates as a service principal using JWT assertion.\n */\nexport class WorkloadIdentityCredential implements AzureCredential {\n\t/**\n\t * @param options Workload identity credential options\n\t */\n\tpublic constructor(public options: WorkloadIdentityCredentialOption) {}\n\n\t/**\n\t * Gets an Azure access token using the federated token file.\n\t * @param scope The resource scope for the token\n\t * @returns An object with token and expiresAt\n\t * @throws If the federated token file does not exist\n\t */\n\tpublic async getToken(scope: string) {\n\t\tif (!existsSync(this.options.federatedTokenFile)) {\n\t\t\tthrow new Error(\"WorkloadIdentityCredential: The federated token file does not exist.\");\n\t\t}\n\n\t\tconst token = readFileSync(this.options.federatedTokenFile, \"utf-8\");\n\t\tconst servicePrincipal = new ServicePrincipalCredential({ ...this.options, clientSecret: token, federated: true });\n\n\t\treturn servicePrincipal.getToken(scope);\n\t}\n\n\t/**\n\t * Instantiates WorkloadIdentityCredential using environment variables.\n\t * This expects the following environment variables to be set:\n\t * - AZURE_AUTHORITY_HOST: The Azure AD authority host (optional)\n\t * - AZURE_CLIENT_ID: The Azure AD application (client) ID\n\t * - AZURE_FEDERATED_TOKEN_FILE: Path to the federated token file\n\t * - AZURE_TENANT_ID: The Azure AD tenant ID\n\t * @returns WorkloadIdentityCredential instance\n\t */\n\tpublic static fromEnv() {\n\t\treturn new WorkloadIdentityCredential({\n\t\t\tauthorityHost: process.env.AZURE_AUTHORITY_HOST,\n\t\t\tclientId: process.env.AZURE_CLIENT_ID,\n\t\t\tfederatedTokenFile: process.env.AZURE_FEDERATED_TOKEN_FILE,\n\t\t\ttenantId: process.env.AZURE_TENANT_ID\n\t\t});\n\t}\n}\n\ndeclare global {\n\tnamespace NodeJS {\n\t\tinterface ProcessEnv {\n\t\t\tAZURE_AUTHORITY_HOST: string;\n\t\t\tAZURE_CLIENT_ID: string;\n\t\t\tAZURE_FEDERATED_TOKEN_FILE: string;\n\t\t\tAZURE_TENANT_ID: string;\n\t\t}\n\t}\n}\n","import { AzureCliCredential } from \"./AzureCliCredential.js\";\nimport type { AzureCredential } from \"./AzureCredential.js\";\nimport { ManagedIdentityCredential } from \"./ManagedIdentityCredential.js\";\nimport { ServicePrincipalCredential } from \"./ServicePrincipalCredential.js\";\nimport { WorkloadIdentityCredential } from \"./WorkloadIdentityCredential.js\";\n\nconst credentialChain = [WorkloadIdentityCredential, ManagedIdentityCredential, ServicePrincipalCredential, AzureCliCredential];\n\n/**\n * DefaultChainedCredential tries multiple credential providers in order until one succeeds.\n *\n * The chain is: WorkloadIdentityCredential → ManagedIdentityCredential → ServicePrincipalCredential → AzureCliCredential.\n * Useful for local dev, CI, and cloud environments with minimal config.\n */\nexport class DefaultChainedCredential implements AzureCredential {\n\t/**\n\t * Attempts to get an Azure access token using the first available credential in the chain.\n\t * @param scope The resource scope for the token\n\t * @returns An object with token and expiresAt\n\t * @throws If all credential providers fail\n\t */\n\tpublic async getToken(scope: string) {\n\t\tconst errors: { name: string; error: Error }[] = [];\n\t\tconst debug = process.env.DEBUG?.includes(\"tako-azure-rest:credentials\") || process.env.DEBUG?.includes(\"tako-azure-rest:*\");\n\t\tfor (const Credential of credentialChain) {\n\t\t\tconst label = `[DefaultChainedCredential] ${Credential.name}`;\n\t\t\tlet start: number | undefined;\n\t\t\tif (debug) {\n\t\t\t\tstart = Date.now();\n\t\t\t\tconsole.log(`${label} - trying...`);\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tconst result = await Credential.fromEnv().getToken(scope);\n\t\t\t\tif (debug && start !== undefined) {\n\t\t\t\t\tconst ms = Date.now() - start;\n\t\t\t\t\tconsole.log(`${label} - success in ${ms}ms`);\n\t\t\t\t}\n\t\t\t\treturn result;\n\t\t\t} catch (error) {\n\t\t\t\tif (debug && start !== undefined) {\n\t\t\t\t\tconst ms = Date.now() - start;\n\t\t\t\t\tconsole.log(`${label} - failed in ${ms}ms: ${(error as Error).message}`);\n\t\t\t\t}\n\t\t\t\terrors.push({ error: error as Error, name: Credential.name });\n\t\t\t}\n\t\t}\n\n\t\tthrow new Error(`Failed to get token, errors:\\n${errors.map(err => `[${err.name}] ${err.error.message}`).join(\"\\n\")}`);\n\t}\n}\n"],"mappings":"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","names":["process"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -122,7 +122,7 @@ type CLITokenResponse = {
|
|
|
122
122
|
/**
|
|
123
123
|
* Options for AzureCliCredential.
|
|
124
124
|
*
|
|
125
|
-
* @property tenantId - The Azure tenant ID to use for authentication
|
|
125
|
+
* @property tenantId - The Azure tenant ID to use for authentication.
|
|
126
126
|
*/
|
|
127
127
|
type AzureCLICredentialOptions = {
|
|
128
128
|
tenantId: string;
|
|
@@ -157,6 +157,8 @@ declare class AzureCliCredential implements AzureCredential {
|
|
|
157
157
|
private parseRawOutput;
|
|
158
158
|
/**
|
|
159
159
|
* Instantiates AzureCliCredential using the AZURE_TENANT_ID environment variable.
|
|
160
|
+
* This expects the following environment variable to be set:
|
|
161
|
+
* - AZURE_TENANT_ID: The Azure tenant ID to use for authentication.
|
|
160
162
|
* @returns AzureCliCredential instance
|
|
161
163
|
*/
|
|
162
164
|
static fromEnv(): AzureCliCredential;
|
|
@@ -192,10 +194,13 @@ declare class DefaultChainedCredential implements AzureCredential {
|
|
|
192
194
|
/**
|
|
193
195
|
* Options for configuring ManagedIdentityCredential.
|
|
194
196
|
*
|
|
195
|
-
* @property clientId - (Optional) The user-assigned managed identity client ID
|
|
197
|
+
* @property clientId - (Optional) The user-assigned managed identity client ID.
|
|
198
|
+
* @property timeoutMs - (Optional) Timeout in milliseconds for metadata endpoint fetch. Default: 300ms.
|
|
196
199
|
*/
|
|
197
200
|
type ManagedIdentityCredentialOptions = {
|
|
201
|
+
identityEndpoint?: string;
|
|
198
202
|
clientId?: string;
|
|
203
|
+
timeoutMs?: number;
|
|
199
204
|
};
|
|
200
205
|
/**
|
|
201
206
|
* AzureCredential implementation for Azure Managed Identity (MSI).
|
|
@@ -223,6 +228,10 @@ declare class ManagedIdentityCredential implements AzureCredential {
|
|
|
223
228
|
}>;
|
|
224
229
|
/**
|
|
225
230
|
* Instantiates ManagedIdentityCredential using environment variables.
|
|
231
|
+
* This expects the following environment variables to be set:
|
|
232
|
+
* - AZURE_CLIENT_ID: The user-assigned managed identity client ID. This is optional for system-assigned identities.
|
|
233
|
+
* - AZURE_MANAGED_IDENTITY_ENDPOINT or IDENTITY_ENDPOINT: The managed identity endpoint (optional, defaults to http://169.254.169.254/metadata/identity/oauth2/token)
|
|
234
|
+
* - AZURE_MANAGED_IDENTITY_TIMEOUT_MS: Custom timeout for metadata endpoint fetch in milliseconds (optional).
|
|
226
235
|
* @returns ManagedIdentityCredential instance
|
|
227
236
|
*/
|
|
228
237
|
static fromEnv(): ManagedIdentityCredential;
|
|
@@ -231,6 +240,7 @@ declare global {
|
|
|
231
240
|
namespace NodeJS {
|
|
232
241
|
interface ProcessEnv {
|
|
233
242
|
AZURE_MANAGED_IDENTITY_ENDPOINT?: string;
|
|
243
|
+
AZURE_MANAGED_IDENTITY_TIMEOUT_MS?: string;
|
|
234
244
|
IDENTITY_ENDPOINT?: string;
|
|
235
245
|
}
|
|
236
246
|
}
|
|
@@ -261,11 +271,11 @@ type OAuth2TokenResponse = {
|
|
|
261
271
|
/**
|
|
262
272
|
* Options for configuring ServicePrincipalCredential.
|
|
263
273
|
*
|
|
264
|
-
* @property clientId - The Azure AD application (client) ID
|
|
265
|
-
* @property clientSecret - The client secret or JWT assertion (for federated)
|
|
266
|
-
* @property tenantId - The Azure AD tenant ID
|
|
267
|
-
* @property authorityHost - (Optional) The Azure AD authority host
|
|
268
|
-
* @property federated - Whether to use federated (JWT) auth
|
|
274
|
+
* @property clientId - The Azure AD application (client) ID.
|
|
275
|
+
* @property clientSecret - The client secret or JWT assertion (for federated).
|
|
276
|
+
* @property tenantId - The Azure AD tenant ID.
|
|
277
|
+
* @property authorityHost - (Optional) The Azure AD authority host. Defaults to "https://login.microsoftonline.com".
|
|
278
|
+
* @property federated - Whether to use federated (JWT) auth. If true, clientSecret is treated as a JWT assertion.
|
|
269
279
|
*/
|
|
270
280
|
type ServicePrincipalCredentialOption = {
|
|
271
281
|
clientId: string;
|
|
@@ -297,6 +307,11 @@ declare class ServicePrincipalCredential implements AzureCredential {
|
|
|
297
307
|
}>;
|
|
298
308
|
/**
|
|
299
309
|
* Instantiates ServicePrincipalCredential using environment variables.
|
|
310
|
+
* This expects the following environment variables to be set:
|
|
311
|
+
* - AZURE_CLIENT_ID: The Azure AD application (client) ID
|
|
312
|
+
* - AZURE_CLIENT_SECRET: The client secret
|
|
313
|
+
* - AZURE_TENANT_ID: The Azure AD tenant ID
|
|
314
|
+
* - AZURE_USE_FEDERATED_AUTH: Optional, if set to "true", uses federated authentication (JWT assertion).
|
|
300
315
|
* @returns ServicePrincipalCredential instance
|
|
301
316
|
*/
|
|
302
317
|
static fromEnv(): ServicePrincipalCredential;
|
|
@@ -307,6 +322,7 @@ declare global {
|
|
|
307
322
|
AZURE_CLIENT_ID: string;
|
|
308
323
|
AZURE_CLIENT_SECRET: string;
|
|
309
324
|
AZURE_TENANT_ID: string;
|
|
325
|
+
AZURE_USE_FEDERATED_AUTH: "true" | "false";
|
|
310
326
|
}
|
|
311
327
|
}
|
|
312
328
|
}
|
|
@@ -350,6 +366,11 @@ declare class WorkloadIdentityCredential implements AzureCredential {
|
|
|
350
366
|
}>;
|
|
351
367
|
/**
|
|
352
368
|
* Instantiates WorkloadIdentityCredential using environment variables.
|
|
369
|
+
* This expects the following environment variables to be set:
|
|
370
|
+
* - AZURE_AUTHORITY_HOST: The Azure AD authority host (optional)
|
|
371
|
+
* - AZURE_CLIENT_ID: The Azure AD application (client) ID
|
|
372
|
+
* - AZURE_FEDERATED_TOKEN_FILE: Path to the federated token file
|
|
373
|
+
* - AZURE_TENANT_ID: The Azure AD tenant ID
|
|
353
374
|
* @returns WorkloadIdentityCredential instance
|
|
354
375
|
*/
|
|
355
376
|
static fromEnv(): WorkloadIdentityCredential;
|
package/dist/index.d.ts
CHANGED
|
@@ -122,7 +122,7 @@ type CLITokenResponse = {
|
|
|
122
122
|
/**
|
|
123
123
|
* Options for AzureCliCredential.
|
|
124
124
|
*
|
|
125
|
-
* @property tenantId - The Azure tenant ID to use for authentication
|
|
125
|
+
* @property tenantId - The Azure tenant ID to use for authentication.
|
|
126
126
|
*/
|
|
127
127
|
type AzureCLICredentialOptions = {
|
|
128
128
|
tenantId: string;
|
|
@@ -157,6 +157,8 @@ declare class AzureCliCredential implements AzureCredential {
|
|
|
157
157
|
private parseRawOutput;
|
|
158
158
|
/**
|
|
159
159
|
* Instantiates AzureCliCredential using the AZURE_TENANT_ID environment variable.
|
|
160
|
+
* This expects the following environment variable to be set:
|
|
161
|
+
* - AZURE_TENANT_ID: The Azure tenant ID to use for authentication.
|
|
160
162
|
* @returns AzureCliCredential instance
|
|
161
163
|
*/
|
|
162
164
|
static fromEnv(): AzureCliCredential;
|
|
@@ -192,10 +194,13 @@ declare class DefaultChainedCredential implements AzureCredential {
|
|
|
192
194
|
/**
|
|
193
195
|
* Options for configuring ManagedIdentityCredential.
|
|
194
196
|
*
|
|
195
|
-
* @property clientId - (Optional) The user-assigned managed identity client ID
|
|
197
|
+
* @property clientId - (Optional) The user-assigned managed identity client ID.
|
|
198
|
+
* @property timeoutMs - (Optional) Timeout in milliseconds for metadata endpoint fetch. Default: 300ms.
|
|
196
199
|
*/
|
|
197
200
|
type ManagedIdentityCredentialOptions = {
|
|
201
|
+
identityEndpoint?: string;
|
|
198
202
|
clientId?: string;
|
|
203
|
+
timeoutMs?: number;
|
|
199
204
|
};
|
|
200
205
|
/**
|
|
201
206
|
* AzureCredential implementation for Azure Managed Identity (MSI).
|
|
@@ -223,6 +228,10 @@ declare class ManagedIdentityCredential implements AzureCredential {
|
|
|
223
228
|
}>;
|
|
224
229
|
/**
|
|
225
230
|
* Instantiates ManagedIdentityCredential using environment variables.
|
|
231
|
+
* This expects the following environment variables to be set:
|
|
232
|
+
* - AZURE_CLIENT_ID: The user-assigned managed identity client ID. This is optional for system-assigned identities.
|
|
233
|
+
* - AZURE_MANAGED_IDENTITY_ENDPOINT or IDENTITY_ENDPOINT: The managed identity endpoint (optional, defaults to http://169.254.169.254/metadata/identity/oauth2/token)
|
|
234
|
+
* - AZURE_MANAGED_IDENTITY_TIMEOUT_MS: Custom timeout for metadata endpoint fetch in milliseconds (optional).
|
|
226
235
|
* @returns ManagedIdentityCredential instance
|
|
227
236
|
*/
|
|
228
237
|
static fromEnv(): ManagedIdentityCredential;
|
|
@@ -231,6 +240,7 @@ declare global {
|
|
|
231
240
|
namespace NodeJS {
|
|
232
241
|
interface ProcessEnv {
|
|
233
242
|
AZURE_MANAGED_IDENTITY_ENDPOINT?: string;
|
|
243
|
+
AZURE_MANAGED_IDENTITY_TIMEOUT_MS?: string;
|
|
234
244
|
IDENTITY_ENDPOINT?: string;
|
|
235
245
|
}
|
|
236
246
|
}
|
|
@@ -261,11 +271,11 @@ type OAuth2TokenResponse = {
|
|
|
261
271
|
/**
|
|
262
272
|
* Options for configuring ServicePrincipalCredential.
|
|
263
273
|
*
|
|
264
|
-
* @property clientId - The Azure AD application (client) ID
|
|
265
|
-
* @property clientSecret - The client secret or JWT assertion (for federated)
|
|
266
|
-
* @property tenantId - The Azure AD tenant ID
|
|
267
|
-
* @property authorityHost - (Optional) The Azure AD authority host
|
|
268
|
-
* @property federated - Whether to use federated (JWT) auth
|
|
274
|
+
* @property clientId - The Azure AD application (client) ID.
|
|
275
|
+
* @property clientSecret - The client secret or JWT assertion (for federated).
|
|
276
|
+
* @property tenantId - The Azure AD tenant ID.
|
|
277
|
+
* @property authorityHost - (Optional) The Azure AD authority host. Defaults to "https://login.microsoftonline.com".
|
|
278
|
+
* @property federated - Whether to use federated (JWT) auth. If true, clientSecret is treated as a JWT assertion.
|
|
269
279
|
*/
|
|
270
280
|
type ServicePrincipalCredentialOption = {
|
|
271
281
|
clientId: string;
|
|
@@ -297,6 +307,11 @@ declare class ServicePrincipalCredential implements AzureCredential {
|
|
|
297
307
|
}>;
|
|
298
308
|
/**
|
|
299
309
|
* Instantiates ServicePrincipalCredential using environment variables.
|
|
310
|
+
* This expects the following environment variables to be set:
|
|
311
|
+
* - AZURE_CLIENT_ID: The Azure AD application (client) ID
|
|
312
|
+
* - AZURE_CLIENT_SECRET: The client secret
|
|
313
|
+
* - AZURE_TENANT_ID: The Azure AD tenant ID
|
|
314
|
+
* - AZURE_USE_FEDERATED_AUTH: Optional, if set to "true", uses federated authentication (JWT assertion).
|
|
300
315
|
* @returns ServicePrincipalCredential instance
|
|
301
316
|
*/
|
|
302
317
|
static fromEnv(): ServicePrincipalCredential;
|
|
@@ -307,6 +322,7 @@ declare global {
|
|
|
307
322
|
AZURE_CLIENT_ID: string;
|
|
308
323
|
AZURE_CLIENT_SECRET: string;
|
|
309
324
|
AZURE_TENANT_ID: string;
|
|
325
|
+
AZURE_USE_FEDERATED_AUTH: "true" | "false";
|
|
310
326
|
}
|
|
311
327
|
}
|
|
312
328
|
}
|
|
@@ -350,6 +366,11 @@ declare class WorkloadIdentityCredential implements AzureCredential {
|
|
|
350
366
|
}>;
|
|
351
367
|
/**
|
|
352
368
|
* Instantiates WorkloadIdentityCredential using environment variables.
|
|
369
|
+
* This expects the following environment variables to be set:
|
|
370
|
+
* - AZURE_AUTHORITY_HOST: The Azure AD authority host (optional)
|
|
371
|
+
* - AZURE_CLIENT_ID: The Azure AD application (client) ID
|
|
372
|
+
* - AZURE_FEDERATED_TOKEN_FILE: Path to the federated token file
|
|
373
|
+
* - AZURE_TENANT_ID: The Azure AD tenant ID
|
|
353
374
|
* @returns WorkloadIdentityCredential instance
|
|
354
375
|
*/
|
|
355
376
|
static fromEnv(): WorkloadIdentityCredential;
|
package/dist/index.js
CHANGED
|
@@ -26,7 +26,10 @@ var AzureClient = class _AzureClient {
|
|
|
26
26
|
if (i > 0) await new Promise((res) => setTimeout(res, 100 * i));
|
|
27
27
|
}
|
|
28
28
|
if (!this.token) throw new Error("Token is unexpectedly null after refresh attempts");
|
|
29
|
-
|
|
29
|
+
const baseUrl = this.options.baseUrl.replace(/\/+$/, "");
|
|
30
|
+
const relPath = path.replace(/^\/+/, "");
|
|
31
|
+
const url = `${baseUrl}/${relPath}`;
|
|
32
|
+
return fetch(url, {
|
|
30
33
|
...init,
|
|
31
34
|
headers: {
|
|
32
35
|
...this.options.credential.builder ? this.options.credential.builder(this.token) : { Authorization: `Bearer ${this.token.accessToken}` },
|
|
@@ -196,6 +199,8 @@ var AzureCliCredential = class _AzureCliCredential {
|
|
|
196
199
|
}
|
|
197
200
|
/**
|
|
198
201
|
* Instantiates AzureCliCredential using the AZURE_TENANT_ID environment variable.
|
|
202
|
+
* This expects the following environment variable to be set:
|
|
203
|
+
* - AZURE_TENANT_ID: The Azure tenant ID to use for authentication.
|
|
199
204
|
* @returns AzureCliCredential instance
|
|
200
205
|
*/
|
|
201
206
|
static fromEnv() {
|
|
@@ -222,7 +227,7 @@ var ManagedIdentityCredential = class _ManagedIdentityCredential {
|
|
|
222
227
|
* @throws If the endpoint is unavailable or token request fails
|
|
223
228
|
*/
|
|
224
229
|
async getToken(scope) {
|
|
225
|
-
const endpoint =
|
|
230
|
+
const endpoint = this.options.identityEndpoint || "http://169.254.169.254/metadata/identity/oauth2/token";
|
|
226
231
|
const apiVersion = "2018-02-01";
|
|
227
232
|
const params = new URLSearchParams({
|
|
228
233
|
resource: scope.replace(".default", ""),
|
|
@@ -233,7 +238,20 @@ var ManagedIdentityCredential = class _ManagedIdentityCredential {
|
|
|
233
238
|
}
|
|
234
239
|
const url = `${endpoint}?${params.toString()}`;
|
|
235
240
|
const headers = { Metadata: "true" };
|
|
236
|
-
const
|
|
241
|
+
const timeoutMs = this.options.timeoutMs ?? 300;
|
|
242
|
+
const controller = new AbortController();
|
|
243
|
+
const timeout = setTimeout(() => controller.abort(), timeoutMs);
|
|
244
|
+
let response;
|
|
245
|
+
try {
|
|
246
|
+
response = await fetch(url, { headers, signal: controller.signal });
|
|
247
|
+
} catch (err) {
|
|
248
|
+
if (err.name === "AbortError") {
|
|
249
|
+
throw new Error(`ManagedIdentityCredential: Timed out after ${timeoutMs}ms waiting for metadata endpoint (${url})`);
|
|
250
|
+
}
|
|
251
|
+
throw err;
|
|
252
|
+
} finally {
|
|
253
|
+
clearTimeout(timeout);
|
|
254
|
+
}
|
|
237
255
|
if (!response.ok) {
|
|
238
256
|
throw new Error(`ManagedIdentityCredential: Failed to get token: ${await response.text()}`);
|
|
239
257
|
}
|
|
@@ -248,10 +266,18 @@ var ManagedIdentityCredential = class _ManagedIdentityCredential {
|
|
|
248
266
|
}
|
|
249
267
|
/**
|
|
250
268
|
* Instantiates ManagedIdentityCredential using environment variables.
|
|
269
|
+
* This expects the following environment variables to be set:
|
|
270
|
+
* - AZURE_CLIENT_ID: The user-assigned managed identity client ID. This is optional for system-assigned identities.
|
|
271
|
+
* - AZURE_MANAGED_IDENTITY_ENDPOINT or IDENTITY_ENDPOINT: The managed identity endpoint (optional, defaults to http://169.254.169.254/metadata/identity/oauth2/token)
|
|
272
|
+
* - AZURE_MANAGED_IDENTITY_TIMEOUT_MS: Custom timeout for metadata endpoint fetch in milliseconds (optional).
|
|
251
273
|
* @returns ManagedIdentityCredential instance
|
|
252
274
|
*/
|
|
253
275
|
static fromEnv() {
|
|
254
|
-
return new _ManagedIdentityCredential({
|
|
276
|
+
return new _ManagedIdentityCredential({
|
|
277
|
+
identityEndpoint: process.env.AZURE_MANAGED_IDENTITY_ENDPOINT || process.env.IDENTITY_ENDPOINT,
|
|
278
|
+
clientId: process.env.AZURE_CLIENT_ID,
|
|
279
|
+
timeoutMs: process.env.AZURE_MANAGED_IDENTITY_TIMEOUT_MS ? Number.parseInt(process.env.AZURE_MANAGED_IDENTITY_TIMEOUT_MS) : void 0
|
|
280
|
+
});
|
|
255
281
|
}
|
|
256
282
|
};
|
|
257
283
|
|
|
@@ -313,14 +339,20 @@ var ServicePrincipalCredential = class _ServicePrincipalCredential {
|
|
|
313
339
|
}
|
|
314
340
|
/**
|
|
315
341
|
* Instantiates ServicePrincipalCredential using environment variables.
|
|
342
|
+
* This expects the following environment variables to be set:
|
|
343
|
+
* - AZURE_CLIENT_ID: The Azure AD application (client) ID
|
|
344
|
+
* - AZURE_CLIENT_SECRET: The client secret
|
|
345
|
+
* - AZURE_TENANT_ID: The Azure AD tenant ID
|
|
346
|
+
* - AZURE_USE_FEDERATED_AUTH: Optional, if set to "true", uses federated authentication (JWT assertion).
|
|
316
347
|
* @returns ServicePrincipalCredential instance
|
|
317
348
|
*/
|
|
318
349
|
static fromEnv() {
|
|
319
350
|
return new _ServicePrincipalCredential({
|
|
351
|
+
authorityHost: process.env.AZURE_AUTHORITY_HOST,
|
|
320
352
|
clientId: process.env.AZURE_CLIENT_ID,
|
|
321
353
|
clientSecret: process.env.AZURE_CLIENT_SECRET,
|
|
322
354
|
tenantId: process.env.AZURE_TENANT_ID,
|
|
323
|
-
federated:
|
|
355
|
+
federated: process.env.AZURE_USE_FEDERATED_AUTH === "true"
|
|
324
356
|
});
|
|
325
357
|
}
|
|
326
358
|
};
|
|
@@ -350,6 +382,11 @@ var WorkloadIdentityCredential = class _WorkloadIdentityCredential {
|
|
|
350
382
|
}
|
|
351
383
|
/**
|
|
352
384
|
* Instantiates WorkloadIdentityCredential using environment variables.
|
|
385
|
+
* This expects the following environment variables to be set:
|
|
386
|
+
* - AZURE_AUTHORITY_HOST: The Azure AD authority host (optional)
|
|
387
|
+
* - AZURE_CLIENT_ID: The Azure AD application (client) ID
|
|
388
|
+
* - AZURE_FEDERATED_TOKEN_FILE: Path to the federated token file
|
|
389
|
+
* - AZURE_TENANT_ID: The Azure AD tenant ID
|
|
353
390
|
* @returns WorkloadIdentityCredential instance
|
|
354
391
|
*/
|
|
355
392
|
static fromEnv() {
|
|
@@ -373,10 +410,26 @@ var DefaultChainedCredential = class {
|
|
|
373
410
|
*/
|
|
374
411
|
async getToken(scope) {
|
|
375
412
|
const errors = [];
|
|
413
|
+
const debug = process.env.DEBUG?.includes("tako-azure-rest:credentials") || process.env.DEBUG?.includes("tako-azure-rest:*");
|
|
376
414
|
for (const Credential of credentialChain) {
|
|
415
|
+
const label = `[DefaultChainedCredential] ${Credential.name}`;
|
|
416
|
+
let start;
|
|
417
|
+
if (debug) {
|
|
418
|
+
start = Date.now();
|
|
419
|
+
console.log(`${label} - trying...`);
|
|
420
|
+
}
|
|
377
421
|
try {
|
|
378
|
-
|
|
422
|
+
const result = await Credential.fromEnv().getToken(scope);
|
|
423
|
+
if (debug && start !== void 0) {
|
|
424
|
+
const ms = Date.now() - start;
|
|
425
|
+
console.log(`${label} - success in ${ms}ms`);
|
|
426
|
+
}
|
|
427
|
+
return result;
|
|
379
428
|
} catch (error) {
|
|
429
|
+
if (debug && start !== void 0) {
|
|
430
|
+
const ms = Date.now() - start;
|
|
431
|
+
console.log(`${label} - failed in ${ms}ms: ${error.message}`);
|
|
432
|
+
}
|
|
380
433
|
errors.push({ error, name: Credential.name });
|
|
381
434
|
}
|
|
382
435
|
}
|