UNPKG

@takodotid/azure-rest

Version:

Minimal Azure REST client with Entra ID (formerly AAD) authentication. Zero external dependencies.

408 lines (400 loc) 15.3 kB
/** * Represents an Azure access token and its expiration. */ type Credential = { accessToken: string; clientId?: string; expiresAt: Date; tokenType: string; }; /** * Abstract credential class for acquiring Azure tokens. * Implement this to provide custom authentication logic. */ declare abstract class AzureCredential { /** * Gets an Azure access token for the given scope. * @param scope The resource or scope for which the token is requested * @returns A promise resolving to an AzureToken */ abstract getToken(scope: string): Promise<Credential>; } /** * Options for configuring the AzureClient instance. * * @property baseUrl - The base URL for Azure REST API endpoints (e.g. https://management.azure.com) * @property credential - Credential configuration for authenticating requests * @property helper - An AzureCredential implementation for acquiring tokens * @property scope - The Azure resource scope for the token (e.g. https://management.azure.com/.default) * @property builder - (Optional) Function to build request headers from a token. If not provided, an Authorization header is set by default. */ type AzureClientOptions = { baseUrl: string; credential: { helper: AzureCredential; scope: string; builder?: (token: Credential) => Record<string, string>; }; }; /** * Azure REST API client with credential refresh and HTTP verb helpers. */ declare class AzureClient { options: AzureClientOptions; private static readonly MAX_TOKEN_RETRIES; private token; /** * @param options Azure client configuration (baseUrl, credential, etc) */ constructor(options: AzureClientOptions); /** * Sends a GET request to the Azure REST API. * @param path The API path * @param options Fetch options, including headers * @returns The fetch Response object */ get(path: string, options?: Exclude<RequestInit, "method">): Promise<Response>; /** * Sends a POST request with a JSON body to the Azure REST API. * @param path The API path * @param options Fetch options, including body and headers * @returns The fetch Response object */ post(path: string, options?: Exclude<RequestInit, "method">): Promise<Response>; /** * Sends a PUT request with a JSON body to the Azure REST API. * @param path The API path * @param options Fetch options, including body and headers * @returns The fetch Response object */ put(path: string, options?: Exclude<RequestInit, "method">): Promise<Response>; /** * Sends a PATCH request with a JSON body to the Azure REST API. * @param path The API path * @param options Fetch options, including body and headers * @returns The fetch Response object */ patch(path: string, options?: Exclude<RequestInit, "method">): Promise<Response>; /** * Sends a DELETE request to the Azure REST API. * @param path The API path * @param options Fetch options, including body and headers * @returns The fetch Response object */ delete(path: string, options?: Exclude<RequestInit, "method">): Promise<Response>; /** * Sends a request to the Azure REST API, handling token refresh and retries. * @param path The API path (relative to baseUrl) * @param options Optional fetch options * @returns The fetch Response object * @throws If token refresh fails after max retries */ request(path: string, options?: RequestInit): Promise<Response>; /** * Refreshes the Azure access token using the provided credential helper. * @private */ private refreshToken; } /** * The raw response returned by Azure CLI when requesting an access token. * * @property accessToken - The access token string * @property expiresOn - Expiry date in RFC3339 format (legacy) * @property expires_on - Expiry as seconds since epoch (preferred) * @property subscription - (Optional) Subscription ID, may not be present * @property tenant - Tenant ID * @property tokenType - Token type (usually 'Bearer') */ type CLITokenResponse = { accessToken: string; expiresOn: string; expires_on: string; subscription?: string; tenant: string; tokenType: string; }; /** * Options for AzureCliCredential. * * @property tenantId - (Optional) The Azure tenant ID to use for authentication. If not provided, will use the current Azure CLI context. */ type AzureCLICredentialOptions = { tenantId?: string; }; /** * AzureCliCredential authenticates using the Azure CLI (`az`). * * - If `tenantId` is provided, uses it for token requests. * - If not, will try `AZURE_TENANT_ID` env var, then fall back to the current Azure CLI context. * * Throws clear errors if the CLI is not installed or not logged in. */ declare class AzureCliCredential implements AzureCredential { options: AzureCLICredentialOptions; constructor(options: AzureCLICredentialOptions); /** * Instantiates AzureCliCredential using the AZURE_TENANT_ID environment variable (if set), * or falls back to the current Azure CLI context. * @returns AzureCliCredential instance */ static fromEnv(): AzureCliCredential; /** * Gets an Azure access token using the Azure CLI. * @param scope The resource scope for the token (e.g. 'https://management.azure.com/.default') * @returns An object with accessToken, expiresAt, and tokenType * @throws If CLI is not installed or not logged in */ getToken(scope: string): Promise<{ accessToken: string; expiresAt: Date; tokenType: string; }>; /** * Runs the Azure CLI to get an access token for the given scope and tenant. * @param scope The resource scope * @param tenantId The Azure tenant ID * @returns Promise resolving to CLI stdout and stderr * @private */ private getCliToken; /** * Gets the current tenant ID from Azure CLI context. * @returns Promise resolving to the current tenant ID string * @throws If CLI is not installed or not logged in */ private static getCurrentTenantId; /** * Parses the raw CLI output and returns a token + expiry object. * @param output The stdout from Azure CLI * @returns An object with accessToken, expiresAt, and tokenType * @private */ private parseRawOutput; /** * Checks stderr for common Azure CLI login errors. * @param stderr The stderr string from CLI * @returns Object with isLoginError and isNotInstallError booleans * @private */ private static parseCliLoginError; } declare global { namespace NodeJS { interface ProcessEnv { AZURE_TENANT_ID: string; } } } /** * ChainedCredential tries multiple credential providers in order until one succeeds. * * The chain is: WorkloadIdentityCredential → ManagedIdentityCredential → ServicePrincipalCredential → AzureCliCredential. * Useful for local dev, CI, and cloud environments with minimal config. */ declare class ChainedCredential implements AzureCredential { /** * Attempts to get an Azure access token using the first available credential in the chain. * @param scope The resource scope for the token * @returns An object with token and expiresAt * @throws If all credential providers fail */ getToken(scope: string): Promise<{ accessToken: string; expiresAt: Date; tokenType: string; }>; } /** * Options for configuring ManagedIdentityCredential. * * @property clientId - (Optional) The user-assigned managed identity client ID. * @property timeoutMs - (Optional) Timeout in milliseconds for metadata endpoint fetch. Default: 300ms. */ type ManagedIdentityCredentialOptions = { identityEndpoint?: string; clientId?: string; timeoutMs?: number; }; /** * AzureCredential implementation for Azure Managed Identity (MSI). * * Supports both system-assigned and user-assigned managed identities. * Works on Azure VM, App Service, Container Apps, etc. */ declare class ManagedIdentityCredential implements AzureCredential { options: ManagedIdentityCredentialOptions; /** * @param options Managed identity credential options */ constructor(options?: ManagedIdentityCredentialOptions); /** * Gets an Azure access token using the managed identity endpoint. * @param scope The resource scope for the token * @returns An object with token and expiresAt * @throws If the endpoint is unavailable or token request fails */ getToken(scope: string): Promise<{ accessToken: string; clientId: string | undefined; expiresAt: Date; tokenType: string; }>; /** * Instantiates ManagedIdentityCredential using environment variables. * This expects the following environment variables to be set: * - AZURE_CLIENT_ID: The user-assigned managed identity client ID. This is optional for system-assigned identities. * - AZURE_MANAGED_IDENTITY_ENDPOINT or IDENTITY_ENDPOINT: The managed identity endpoint (optional, defaults to http://169.254.169.254/metadata/identity/oauth2/token) * - AZURE_MANAGED_IDENTITY_TIMEOUT_MS: Custom timeout for metadata endpoint fetch in milliseconds (optional). * @returns ManagedIdentityCredential instance */ static fromEnv(): ManagedIdentityCredential; } declare global { namespace NodeJS { interface ProcessEnv { AZURE_MANAGED_IDENTITY_ENDPOINT?: string; AZURE_MANAGED_IDENTITY_TIMEOUT_MS?: string; IDENTITY_ENDPOINT?: string; } } } /** * The OAuth2 token response returned by Azure AD and Managed Identity endpoints. * * @property access_token - The access token string * @property client_id - The client/application ID (optional, present in MSI) * @property expires_in - Seconds until token expiry * @property expires_on - Expiry time (epoch seconds, as string) * @property ext_expires_in - Extended expiry in seconds * @property not_before - Not before time (epoch seconds, as string) * @property resource - The resource for which the token is issued * @property token_type - The type of token (usually 'Bearer') */ type OAuth2TokenResponse = { access_token: string; client_id?: string; expires_in: number; expires_on: string; ext_expires_in: number; not_before: string; resource: string; token_type: string; }; /** * Options for configuring ServicePrincipalCredential. * * @property clientId - The Azure AD application (client) ID. * @property clientSecret - The client secret or JWT assertion (for federated). * @property tenantId - The Azure AD tenant ID. * @property authorityHost - (Optional) The Azure AD authority host. Defaults to "https://login.microsoftonline.com". * @property federated - Whether to use federated (JWT) auth. If true, clientSecret is treated as a JWT assertion. */ type ServicePrincipalCredentialOption = { clientId: string; clientSecret?: string; tenantId: string; authorityHost?: string; federated: boolean; }; /** * AzureCredential implementation for authenticating with a Service Principal (client secret or federated/JWT). */ declare class ServicePrincipalCredential implements AzureCredential { options: ServicePrincipalCredentialOption; /** * @param options Service principal credential options */ constructor(options: ServicePrincipalCredentialOption); /** * Gets an Azure access token using the service principal credentials. * @param scope The resource scope for the token * @returns An object with token and expiresAt * @throws If client secret is missing or token request fails */ getToken(scope: string): Promise<{ accessToken: string; clientId: string; expiresAt: Date; tokenType: string; }>; /** * Instantiates ServicePrincipalCredential using environment variables. * This expects the following environment variables to be set: * - AZURE_CLIENT_ID: The Azure AD application (client) ID * - AZURE_CLIENT_SECRET: The client secret * - AZURE_TENANT_ID: The Azure AD tenant ID * - AZURE_USE_FEDERATED_AUTH: Optional, if set to "true", uses federated authentication (JWT assertion). * @returns ServicePrincipalCredential instance */ static fromEnv(): ServicePrincipalCredential; } declare global { namespace NodeJS { interface ProcessEnv { AZURE_CLIENT_ID: string; AZURE_CLIENT_SECRET: string; AZURE_TENANT_ID: string; AZURE_USE_FEDERATED_AUTH: "true" | "false"; } } } /** * Options for configuring WorkloadIdentityCredential. * * @property clientId - The Azure AD application (client) ID * @property federatedTokenFile - Path to the federated token file (OIDC/JWT) * @property tenantId - The Azure AD tenant ID * @property authorityHost - (Optional) The Azure AD authority host */ type WorkloadIdentityCredentialOption = { clientId: string; federatedTokenFile: string; tenantId: string; authorityHost?: string; }; /** * AzureCredential implementation for Azure Workload Identity (OIDC federated token). * * Reads a federated token from file and authenticates as a service principal using JWT assertion. */ declare class WorkloadIdentityCredential implements AzureCredential { options: WorkloadIdentityCredentialOption; /** * @param options Workload identity credential options */ constructor(options: WorkloadIdentityCredentialOption); /** * Gets an Azure access token using the federated token file. * @param scope The resource scope for the token * @returns An object with token and expiresAt * @throws If the federated token file does not exist */ getToken(scope: string): Promise<{ accessToken: string; clientId: string; expiresAt: Date; tokenType: string; }>; /** * Instantiates WorkloadIdentityCredential using environment variables. * This expects the following environment variables to be set: * - AZURE_AUTHORITY_HOST: The Azure AD authority host (optional) * - AZURE_CLIENT_ID: The Azure AD application (client) ID * - AZURE_FEDERATED_TOKEN_FILE: Path to the federated token file * - AZURE_TENANT_ID: The Azure AD tenant ID * @returns WorkloadIdentityCredential instance */ static fromEnv(): WorkloadIdentityCredential; } declare global { namespace NodeJS { interface ProcessEnv { AZURE_AUTHORITY_HOST: string; AZURE_CLIENT_ID: string; AZURE_FEDERATED_TOKEN_FILE: string; AZURE_TENANT_ID: string; } } } export { type AzureCLICredentialOptions, AzureCliCredential, AzureClient, type AzureClientOptions, AzureCredential, type CLITokenResponse, ChainedCredential, type Credential, ManagedIdentityCredential, type ManagedIdentityCredentialOptions, type OAuth2TokenResponse, ServicePrincipalCredential, type ServicePrincipalCredentialOption, WorkloadIdentityCredential, type WorkloadIdentityCredentialOption };