@takodotid/azure-rest 0.1.0 → 0.1.2
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 +62 -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 +62 -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
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Represents an Azure access token and its expiration.
|
|
3
|
-
*/
|
|
4
|
-
export type Credential = { accessToken: string; clientId?: string; expiresAt: Date; tokenType: string };
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* Abstract credential class for acquiring Azure tokens.
|
|
8
|
-
* Implement this to provide custom authentication logic.
|
|
9
|
-
*/
|
|
10
|
-
export abstract class AzureCredential {
|
|
11
|
-
/**
|
|
12
|
-
* Gets an Azure access token for the given scope.
|
|
13
|
-
* @param scope The resource or scope for which the token is requested
|
|
14
|
-
* @returns A promise resolving to an AzureToken
|
|
15
|
-
*/
|
|
16
|
-
public abstract getToken(scope: string): Promise<Credential>;
|
|
17
|
-
}
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
import { AzureCliCredential } from "./AzureCliCredential.js";
|
|
2
|
-
import type { AzureCredential } from "./AzureCredential.js";
|
|
3
|
-
import { ManagedIdentityCredential } from "./ManagedIdentityCredential.js";
|
|
4
|
-
import { ServicePrincipalCredential } from "./ServicePrincipalCredential.js";
|
|
5
|
-
import { WorkloadIdentityCredential } from "./WorkloadIdentityCredential.js";
|
|
6
|
-
|
|
7
|
-
const credentialChain = [WorkloadIdentityCredential, ManagedIdentityCredential, ServicePrincipalCredential, AzureCliCredential];
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* DefaultChainedCredential tries multiple credential providers in order until one succeeds.
|
|
11
|
-
*
|
|
12
|
-
* The chain is: WorkloadIdentityCredential → ManagedIdentityCredential → ServicePrincipalCredential → AzureCliCredential.
|
|
13
|
-
* Useful for local dev, CI, and cloud environments with minimal config.
|
|
14
|
-
*/
|
|
15
|
-
export class DefaultChainedCredential implements AzureCredential {
|
|
16
|
-
/**
|
|
17
|
-
* Attempts to get an Azure access token using the first available credential in the chain.
|
|
18
|
-
* @param scope The resource scope for the token
|
|
19
|
-
* @returns An object with token and expiresAt
|
|
20
|
-
* @throws If all credential providers fail
|
|
21
|
-
*/
|
|
22
|
-
public async getToken(scope: string) {
|
|
23
|
-
const errors: { name: string; error: Error }[] = [];
|
|
24
|
-
for (const Credential of credentialChain) {
|
|
25
|
-
try {
|
|
26
|
-
return await Credential.fromEnv().getToken(scope);
|
|
27
|
-
} catch (error) {
|
|
28
|
-
errors.push({ error: error as Error, name: Credential.name });
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
throw new Error(`Failed to get token, errors:\n${errors.map(err => `[${err.name}] ${err.error.message}`).join("\n")}`);
|
|
33
|
-
}
|
|
34
|
-
}
|
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
import type { AzureCredential } from "./AzureCredential.js";
|
|
2
|
-
import type { OAuth2TokenResponse } from "./ServicePrincipalCredential.js";
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Options for configuring ManagedIdentityCredential.
|
|
6
|
-
*
|
|
7
|
-
* @property clientId - (Optional) The user-assigned managed identity client ID
|
|
8
|
-
*/
|
|
9
|
-
export type ManagedIdentityCredentialOptions = {
|
|
10
|
-
clientId?: string;
|
|
11
|
-
};
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* AzureCredential implementation for Azure Managed Identity (MSI).
|
|
15
|
-
*
|
|
16
|
-
* Supports both system-assigned and user-assigned managed identities.
|
|
17
|
-
* Works on Azure VM, App Service, Container Apps, etc.
|
|
18
|
-
*/
|
|
19
|
-
export class ManagedIdentityCredential implements AzureCredential {
|
|
20
|
-
/**
|
|
21
|
-
* @param options Managed identity credential options
|
|
22
|
-
*/
|
|
23
|
-
public constructor(public options: ManagedIdentityCredentialOptions = {}) {}
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* Gets an Azure access token using the managed identity endpoint.
|
|
27
|
-
* @param scope The resource scope for the token
|
|
28
|
-
* @returns An object with token and expiresAt
|
|
29
|
-
* @throws If the endpoint is unavailable or token request fails
|
|
30
|
-
*/
|
|
31
|
-
public async getToken(scope: string) {
|
|
32
|
-
const endpoint = process.env.AZURE_MANAGED_IDENTITY_ENDPOINT || process.env.IDENTITY_ENDPOINT || "http://169.254.169.254/metadata/identity/oauth2/token";
|
|
33
|
-
const apiVersion = "2018-02-01";
|
|
34
|
-
const params = new URLSearchParams({
|
|
35
|
-
resource: scope.replace(".default", ""),
|
|
36
|
-
apiVersion
|
|
37
|
-
});
|
|
38
|
-
if (this.options.clientId) {
|
|
39
|
-
params.set("client_id", this.options.clientId);
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
const url = `${endpoint}?${params.toString()}`;
|
|
43
|
-
const headers = { Metadata: "true" };
|
|
44
|
-
|
|
45
|
-
const response = await fetch(url, { headers });
|
|
46
|
-
if (!response.ok) {
|
|
47
|
-
throw new Error(`ManagedIdentityCredential: Failed to get token: ${await response.text()}`);
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
const data = (await response.json()) as OAuth2TokenResponse;
|
|
51
|
-
return {
|
|
52
|
-
accessToken: data.access_token,
|
|
53
|
-
clientId: data.client_id,
|
|
54
|
-
expiresAt: new Date(data.expires_on ? Number(data.expires_on) * 1000 : Date.now() + 60 * 60 * 1000), // fallback 1h
|
|
55
|
-
tokenType: data.token_type
|
|
56
|
-
};
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
/**
|
|
60
|
-
* Instantiates ManagedIdentityCredential using environment variables.
|
|
61
|
-
* @returns ManagedIdentityCredential instance
|
|
62
|
-
*/
|
|
63
|
-
public static fromEnv() {
|
|
64
|
-
return new ManagedIdentityCredential({ clientId: process.env.AZURE_CLIENT_ID });
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
declare global {
|
|
69
|
-
namespace NodeJS {
|
|
70
|
-
interface ProcessEnv {
|
|
71
|
-
AZURE_MANAGED_IDENTITY_ENDPOINT?: string;
|
|
72
|
-
IDENTITY_ENDPOINT?: string;
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
}
|
|
@@ -1,132 +0,0 @@
|
|
|
1
|
-
import { URLSearchParams } from "node:url";
|
|
2
|
-
import type { AzureCredential } from "./AzureCredential.js";
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* The OAuth2 token response returned by Azure AD and Managed Identity endpoints.
|
|
6
|
-
*
|
|
7
|
-
* @property access_token - The access token string
|
|
8
|
-
* @property client_id - The client/application ID (optional, present in MSI)
|
|
9
|
-
* @property expires_in - Seconds until token expiry
|
|
10
|
-
* @property expires_on - Expiry time (epoch seconds, as string)
|
|
11
|
-
* @property ext_expires_in - Extended expiry in seconds
|
|
12
|
-
* @property not_before - Not before time (epoch seconds, as string)
|
|
13
|
-
* @property resource - The resource for which the token is issued
|
|
14
|
-
* @property token_type - The type of token (usually 'Bearer')
|
|
15
|
-
*/
|
|
16
|
-
export type OAuth2TokenResponse = {
|
|
17
|
-
access_token: string;
|
|
18
|
-
client_id?: string;
|
|
19
|
-
expires_in: number;
|
|
20
|
-
expires_on: string;
|
|
21
|
-
ext_expires_in: number;
|
|
22
|
-
not_before: string;
|
|
23
|
-
resource: string;
|
|
24
|
-
token_type: string;
|
|
25
|
-
};
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* Options for configuring ServicePrincipalCredential.
|
|
29
|
-
*
|
|
30
|
-
* @property clientId - The Azure AD application (client) ID
|
|
31
|
-
* @property clientSecret - The client secret or JWT assertion (for federated)
|
|
32
|
-
* @property tenantId - The Azure AD tenant ID
|
|
33
|
-
* @property authorityHost - (Optional) The Azure AD authority host
|
|
34
|
-
* @property federated - Whether to use federated (JWT) auth
|
|
35
|
-
*/
|
|
36
|
-
export type ServicePrincipalCredentialOption = {
|
|
37
|
-
clientId: string;
|
|
38
|
-
clientSecret?: string;
|
|
39
|
-
tenantId: string;
|
|
40
|
-
authorityHost?: string;
|
|
41
|
-
federated: boolean;
|
|
42
|
-
};
|
|
43
|
-
|
|
44
|
-
/**
|
|
45
|
-
* AzureCredential implementation for authenticating with a Service Principal (client secret or federated/JWT).
|
|
46
|
-
*/
|
|
47
|
-
export class ServicePrincipalCredential implements AzureCredential {
|
|
48
|
-
/**
|
|
49
|
-
* @param options Service principal credential options
|
|
50
|
-
*/
|
|
51
|
-
public constructor(public options: ServicePrincipalCredentialOption) {}
|
|
52
|
-
|
|
53
|
-
/**
|
|
54
|
-
* Gets an Azure access token using the service principal credentials.
|
|
55
|
-
* @param scope The resource scope for the token
|
|
56
|
-
* @returns An object with token and expiresAt
|
|
57
|
-
* @throws If client secret is missing or token request fails
|
|
58
|
-
*/
|
|
59
|
-
public async getToken(scope: string) {
|
|
60
|
-
if (!this.options.clientSecret) throw new Error("ServicePrincipalCredential: The client secret is not provided.");
|
|
61
|
-
|
|
62
|
-
// Remove trailing slash from identityAuthorityHost
|
|
63
|
-
const url = [this.options.authorityHost?.replace(/\/$/, "") ?? "https://login.microsoftonline.com", `${this.options.tenantId}/oauth2/v2.0/token`].join("/");
|
|
64
|
-
|
|
65
|
-
try {
|
|
66
|
-
const searchParams = {
|
|
67
|
-
client_id: this.options.clientId,
|
|
68
|
-
grant_type: "client_credentials",
|
|
69
|
-
scope
|
|
70
|
-
};
|
|
71
|
-
|
|
72
|
-
// If federated, use client_assertion and client_assertion_type
|
|
73
|
-
// Otherwise, use client_secret
|
|
74
|
-
if (this.options.federated) {
|
|
75
|
-
Object.assign(searchParams, {
|
|
76
|
-
client_assertion: this.options.clientSecret,
|
|
77
|
-
client_assertion_type: "urn:ietf:params:oauth:client-assertion-type:jwt-bearer"
|
|
78
|
-
});
|
|
79
|
-
} else {
|
|
80
|
-
Object.assign(searchParams, {
|
|
81
|
-
client_secret: this.options.clientSecret
|
|
82
|
-
});
|
|
83
|
-
}
|
|
84
|
-
const response = await fetch(url, {
|
|
85
|
-
method: "POST",
|
|
86
|
-
headers: {
|
|
87
|
-
Accept: "application/json",
|
|
88
|
-
"Content-Type": "application/x-www-form-urlencoded"
|
|
89
|
-
},
|
|
90
|
-
body: new URLSearchParams(searchParams)
|
|
91
|
-
});
|
|
92
|
-
|
|
93
|
-
if (!response.ok) {
|
|
94
|
-
throw new Error(`Failed to get token: ${await response.text()}`);
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
const data = (await response.json()) as OAuth2TokenResponse;
|
|
98
|
-
|
|
99
|
-
return {
|
|
100
|
-
accessToken: data.access_token,
|
|
101
|
-
clientId: data.client_id ?? this.options.clientId,
|
|
102
|
-
expiresAt: new Date(Date.now() + data.expires_in * 1_000),
|
|
103
|
-
tokenType: data.token_type
|
|
104
|
-
};
|
|
105
|
-
} catch (error) {
|
|
106
|
-
throw new Error(`Failed to get token: ${(error as Error).stack}`);
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
/**
|
|
111
|
-
* Instantiates ServicePrincipalCredential using environment variables.
|
|
112
|
-
* @returns ServicePrincipalCredential instance
|
|
113
|
-
*/
|
|
114
|
-
public static fromEnv() {
|
|
115
|
-
return new ServicePrincipalCredential({
|
|
116
|
-
clientId: process.env.AZURE_CLIENT_ID,
|
|
117
|
-
clientSecret: process.env.AZURE_CLIENT_SECRET,
|
|
118
|
-
tenantId: process.env.AZURE_TENANT_ID,
|
|
119
|
-
federated: false
|
|
120
|
-
});
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
declare global {
|
|
125
|
-
namespace NodeJS {
|
|
126
|
-
interface ProcessEnv {
|
|
127
|
-
AZURE_CLIENT_ID: string;
|
|
128
|
-
AZURE_CLIENT_SECRET: string;
|
|
129
|
-
AZURE_TENANT_ID: string;
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
}
|
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
import { existsSync, readFileSync } from "node:fs";
|
|
2
|
-
import type { AzureCredential } from "./AzureCredential.js";
|
|
3
|
-
import { ServicePrincipalCredential } from "./ServicePrincipalCredential.js";
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Options for configuring WorkloadIdentityCredential.
|
|
7
|
-
*
|
|
8
|
-
* @property clientId - The Azure AD application (client) ID
|
|
9
|
-
* @property federatedTokenFile - Path to the federated token file (OIDC/JWT)
|
|
10
|
-
* @property tenantId - The Azure AD tenant ID
|
|
11
|
-
* @property authorityHost - (Optional) The Azure AD authority host
|
|
12
|
-
*/
|
|
13
|
-
export type WorkloadIdentityCredentialOption = {
|
|
14
|
-
clientId: string;
|
|
15
|
-
federatedTokenFile: string;
|
|
16
|
-
tenantId: string;
|
|
17
|
-
authorityHost?: string;
|
|
18
|
-
};
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* AzureCredential implementation for Azure Workload Identity (OIDC federated token).
|
|
22
|
-
*
|
|
23
|
-
* Reads a federated token from file and authenticates as a service principal using JWT assertion.
|
|
24
|
-
*/
|
|
25
|
-
export class WorkloadIdentityCredential implements AzureCredential {
|
|
26
|
-
/**
|
|
27
|
-
* @param options Workload identity credential options
|
|
28
|
-
*/
|
|
29
|
-
public constructor(public options: WorkloadIdentityCredentialOption) {}
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
* Gets an Azure access token using the federated token file.
|
|
33
|
-
* @param scope The resource scope for the token
|
|
34
|
-
* @returns An object with token and expiresAt
|
|
35
|
-
* @throws If the federated token file does not exist
|
|
36
|
-
*/
|
|
37
|
-
public async getToken(scope: string) {
|
|
38
|
-
if (!existsSync(this.options.federatedTokenFile)) {
|
|
39
|
-
throw new Error("WorkloadIdentityCredential: The federated token file does not exist.");
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
const token = readFileSync(this.options.federatedTokenFile, "utf-8");
|
|
43
|
-
const servicePrincipal = new ServicePrincipalCredential({ ...this.options, clientSecret: token, federated: true });
|
|
44
|
-
|
|
45
|
-
return servicePrincipal.getToken(scope);
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
/**
|
|
49
|
-
* Instantiates WorkloadIdentityCredential using environment variables.
|
|
50
|
-
* @returns WorkloadIdentityCredential instance
|
|
51
|
-
*/
|
|
52
|
-
public static fromEnv() {
|
|
53
|
-
return new WorkloadIdentityCredential({
|
|
54
|
-
authorityHost: process.env.AZURE_AUTHORITY_HOST,
|
|
55
|
-
clientId: process.env.AZURE_CLIENT_ID,
|
|
56
|
-
federatedTokenFile: process.env.AZURE_FEDERATED_TOKEN_FILE,
|
|
57
|
-
tenantId: process.env.AZURE_TENANT_ID
|
|
58
|
-
});
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
declare global {
|
|
63
|
-
namespace NodeJS {
|
|
64
|
-
interface ProcessEnv {
|
|
65
|
-
AZURE_AUTHORITY_HOST: string;
|
|
66
|
-
AZURE_CLIENT_ID: string;
|
|
67
|
-
AZURE_FEDERATED_TOKEN_FILE: string;
|
|
68
|
-
AZURE_TENANT_ID: string;
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
}
|
package/tsconfig.json
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"compilerOptions": {
|
|
3
|
-
"baseUrl": ".",
|
|
4
|
-
"lib": ["ES2022"],
|
|
5
|
-
"module": "node18",
|
|
6
|
-
"moduleResolution": "nodenext",
|
|
7
|
-
"target": "es2022",
|
|
8
|
-
"strict": true,
|
|
9
|
-
"esModuleInterop": true,
|
|
10
|
-
"skipLibCheck": true,
|
|
11
|
-
"declaration": true,
|
|
12
|
-
"noEmit": true
|
|
13
|
-
},
|
|
14
|
-
"include": ["src"]
|
|
15
|
-
}
|