Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion plugins/azure/types.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
export interface AzureCredentials {
resourceName: string;
azureAuthMode: 'apiKey' | 'entra' | 'managed';
azureAuthMode: 'apiKey' | 'entra' | 'managed' | 'azure_cli';
apiKey?: string;
clientId?: string;
clientSecret?: string;
Expand Down
40 changes: 40 additions & 0 deletions plugins/azure/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,42 @@ export async function getAzureManagedIdentityToken(
return result;
}

export function getAzureCliToken(
scope = 'https://cognitiveservices.azure.com/.default',
check: string
): { token: string; error: string | null } {
const result: { token: string; error: string | null } = {
token: '',
error: null,
};

try {
// Note: Azure CLI auth only works in Node.js runtime
// This will not work in Cloudflare Workers or other edge runtimes
if (typeof process === 'undefined' || !process.versions?.node) {
result.error = 'Azure CLI authentication requires Node.js runtime';
return result;
}

const { execSync } = require('child_process');

// Execute Azure CLI command to get access token
const command = `az account get-access-token --resource ${scope.replace('/.default', '')}`;
const output = execSync(command, { encoding: 'utf-8' });

const tokenData = JSON.parse(output);
result.token = tokenData.accessToken;
} catch (error: any) {
result.error = error?.message || String(error);
console.error('getAzureCliToken error: ', result.error);
console.error(
'Make sure Azure CLI is installed and you are logged in using "az login"'
);
}

return result;
}

export const getAccessToken = async (
credentials: AzureCredentials,
check: string,
Expand Down Expand Up @@ -142,5 +178,9 @@ export const getAccessToken = async (
);
}

if (azureAuthMode === 'azure_cli') {
tokenResult = getAzureCliToken(scope, check);
}

return tokenResult;
};
11 changes: 11 additions & 0 deletions src/providers/azure-ai-inference/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
getAccessTokenFromEntraId,
getAzureManagedIdentityToken,
getAzureWorkloadIdentityToken,
getAzureCliToken,
} from '../azure-openai/utils';
import { ProviderAPIConfig } from '../types';

Expand Down Expand Up @@ -131,6 +132,16 @@ const AzureAIInferenceAPI: ProviderAPIConfig = {
}
}

// Azure CLI authentication mode - only available in Node.js runtime
if (azureAuthMode === 'azure_cli' && runtime === 'node') {
const scope = 'https://cognitiveservices.azure.com/.default';
const accessToken = getAzureCliToken(scope);
if (accessToken) {
headers['Authorization'] = `Bearer ${accessToken}`;
return headers;
}
}

if (apiKey) {
headers['Authorization'] = `Bearer ${apiKey}`;
return headers;
Expand Down
11 changes: 11 additions & 0 deletions src/providers/azure-openai/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
getAccessTokenFromEntraId,
getAzureManagedIdentityToken,
getAzureWorkloadIdentityToken,
getAzureCliToken,
} from './utils';
import { getRuntimeKey } from 'hono/adapter';

Expand Down Expand Up @@ -77,6 +78,16 @@ const AzureOpenAIAPIConfig: ProviderAPIConfig = {
}
}
}
// Azure CLI authentication mode - only available in Node.js runtime
if (azureAuthMode === 'azure_cli' && runtime === 'node') {
const scope = 'https://cognitiveservices.azure.com/.default';
const accessToken = getAzureCliToken(scope);
if (accessToken) {
return {
Authorization: `Bearer ${accessToken}`,
};
}
}
const headersObj: Record<string, string> = {
'api-key': `${apiKey}`,
};
Expand Down
20 changes: 20 additions & 0 deletions src/providers/azure-openai/utils.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { AZURE_OPEN_AI } from '../../globals';
import { OpenAIErrorResponseTransform } from '../openai/utils';
import { ErrorResponse } from '../types';
import { execSync } from 'child_process';

export async function getAccessTokenFromEntraId(
tenantId: string,
Expand Down Expand Up @@ -105,6 +106,25 @@ export async function getAzureWorkloadIdentityToken(
}
}

export function getAzureCliToken(
scope = 'https://cognitiveservices.azure.com/.default'
): string | undefined {
try {
// Execute Azure CLI command to get access token
const command = `az account get-access-token --resource ${scope.replace('/.default', '')}`;
const output = execSync(command, { encoding: 'utf-8' });

const tokenData = JSON.parse(output);
return tokenData.accessToken;
} catch (error: any) {
console.error('getAzureCliToken error: ', error?.message || error);
console.error(
'Make sure Azure CLI is installed and you are logged in using "az login"'
);
return undefined;
}
}

export const AzureOpenAIFinetuneResponseTransform = (
response: Response | ErrorResponse,
responseStatus: number
Expand Down
3 changes: 3 additions & 0 deletions src/types/requestBody.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ export interface Options {
deploymentId?: string;
apiVersion?: string;
adAuth?: string;
/** Azure authentication mode: 'apiKey' | 'entra' | 'managed' | 'workload' | 'azure_cli' */
azureAuthMode?: string;
azureManagedClientId?: string;
azureWorkloadClientId?: string;
Expand Down Expand Up @@ -193,6 +194,7 @@ export interface Targets {
deploymentId?: string;
apiVersion?: string;
adAuth?: string;
/** Azure authentication mode: 'apiKey' | 'entra' | 'managed' | 'workload' | 'azure_cli' */
azureAuthMode?: string;
azureManagedClientId?: string;
azureEntraClientId?: string;
Expand Down Expand Up @@ -475,6 +477,7 @@ export interface ShortConfig {
deploymentId?: string;
workersAiAccountId?: string;
apiVersion?: string;
/** Azure authentication mode: 'apiKey' | 'entra' | 'managed' | 'workload' | 'azure_cli' */
azureAuthMode?: string;
azureManagedClientId?: string;
azureEntraClientId?: string;
Expand Down