Skip to content

Commit 4013886

Browse files
committed
feat: add Azure CLI authentication mode and related token retrieval functions
1 parent da1a1d0 commit 4013886

File tree

6 files changed

+87
-1
lines changed

6 files changed

+87
-1
lines changed

plugins/azure/types.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
export interface AzureCredentials {
22
resourceName: string;
3-
azureAuthMode: 'apiKey' | 'entra' | 'managed';
3+
azureAuthMode: 'apiKey' | 'entra' | 'managed' | 'azure_cli';
44
apiKey?: string;
55
clientId?: string;
66
clientSecret?: string;

plugins/azure/utils.ts

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,42 @@ export async function getAzureManagedIdentityToken(
102102
return result;
103103
}
104104

105+
export function getAzureCliToken(
106+
scope = 'https://cognitiveservices.azure.com/.default',
107+
check: string
108+
): { token: string; error: string | null } {
109+
const result: { token: string; error: string | null } = {
110+
token: '',
111+
error: null,
112+
};
113+
114+
try {
115+
// Note: Azure CLI auth only works in Node.js runtime
116+
// This will not work in Cloudflare Workers or other edge runtimes
117+
if (typeof process === 'undefined' || !process.versions?.node) {
118+
result.error = 'Azure CLI authentication requires Node.js runtime';
119+
return result;
120+
}
121+
122+
const { execSync } = require('child_process');
123+
124+
// Execute Azure CLI command to get access token
125+
const command = `az account get-access-token --resource ${scope.replace('/.default', '')}`;
126+
const output = execSync(command, { encoding: 'utf-8' });
127+
128+
const tokenData = JSON.parse(output);
129+
result.token = tokenData.accessToken;
130+
} catch (error: any) {
131+
result.error = error?.message || String(error);
132+
console.error('getAzureCliToken error: ', result.error);
133+
console.error(
134+
'Make sure Azure CLI is installed and you are logged in using "az login"'
135+
);
136+
}
137+
138+
return result;
139+
}
140+
105141
export const getAccessToken = async (
106142
credentials: AzureCredentials,
107143
check: string,
@@ -142,5 +178,9 @@ export const getAccessToken = async (
142178
);
143179
}
144180

181+
if (azureAuthMode === 'azure_cli') {
182+
tokenResult = getAzureCliToken(scope, check);
183+
}
184+
145185
return tokenResult;
146186
};

src/providers/azure-ai-inference/api.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import {
55
getAccessTokenFromEntraId,
66
getAzureManagedIdentityToken,
77
getAzureWorkloadIdentityToken,
8+
getAzureCliToken,
89
} from '../azure-openai/utils';
910
import { ProviderAPIConfig } from '../types';
1011

@@ -131,6 +132,16 @@ const AzureAIInferenceAPI: ProviderAPIConfig = {
131132
}
132133
}
133134

135+
// Azure CLI authentication mode - only available in Node.js runtime
136+
if (azureAuthMode === 'azure_cli' && runtime === 'node') {
137+
const scope = 'https://cognitiveservices.azure.com/.default';
138+
const accessToken = getAzureCliToken(scope);
139+
if (accessToken) {
140+
headers['Authorization'] = `Bearer ${accessToken}`;
141+
return headers;
142+
}
143+
}
144+
134145
if (apiKey) {
135146
headers['Authorization'] = `Bearer ${apiKey}`;
136147
return headers;

src/providers/azure-openai/api.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import {
44
getAccessTokenFromEntraId,
55
getAzureManagedIdentityToken,
66
getAzureWorkloadIdentityToken,
7+
getAzureCliToken,
78
} from './utils';
89
import { getRuntimeKey } from 'hono/adapter';
910

@@ -77,6 +78,16 @@ const AzureOpenAIAPIConfig: ProviderAPIConfig = {
7778
}
7879
}
7980
}
81+
// Azure CLI authentication mode - only available in Node.js runtime
82+
if (azureAuthMode === 'azure_cli' && runtime === 'node') {
83+
const scope = 'https://cognitiveservices.azure.com/.default';
84+
const accessToken = getAzureCliToken(scope);
85+
if (accessToken) {
86+
return {
87+
Authorization: `Bearer ${accessToken}`,
88+
};
89+
}
90+
}
8091
const headersObj: Record<string, string> = {
8192
'api-key': `${apiKey}`,
8293
};

src/providers/azure-openai/utils.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,27 @@ export async function getAzureWorkloadIdentityToken(
105105
}
106106
}
107107

108+
export function getAzureCliToken(
109+
scope = 'https://cognitiveservices.azure.com/.default'
110+
): string | undefined {
111+
try {
112+
const { execSync } = require('child_process');
113+
114+
// Execute Azure CLI command to get access token
115+
const command = `az account get-access-token --resource ${scope.replace('/.default', '')}`;
116+
const output = execSync(command, { encoding: 'utf-8' });
117+
118+
const tokenData = JSON.parse(output);
119+
return tokenData.accessToken;
120+
} catch (error: any) {
121+
console.error('getAzureCliToken error: ', error?.message || error);
122+
console.error(
123+
'Make sure Azure CLI is installed and you are logged in using "az login"'
124+
);
125+
return undefined;
126+
}
127+
}
128+
108129
export const AzureOpenAIFinetuneResponseTransform = (
109130
response: Response | ErrorResponse,
110131
responseStatus: number

src/types/requestBody.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ export interface Options {
6262
deploymentId?: string;
6363
apiVersion?: string;
6464
adAuth?: string;
65+
/** Azure authentication mode: 'apiKey' | 'entra' | 'managed' | 'workload' | 'azure_cli' */
6566
azureAuthMode?: string;
6667
azureManagedClientId?: string;
6768
azureWorkloadClientId?: string;
@@ -193,6 +194,7 @@ export interface Targets {
193194
deploymentId?: string;
194195
apiVersion?: string;
195196
adAuth?: string;
197+
/** Azure authentication mode: 'apiKey' | 'entra' | 'managed' | 'workload' | 'azure_cli' */
196198
azureAuthMode?: string;
197199
azureManagedClientId?: string;
198200
azureEntraClientId?: string;
@@ -475,6 +477,7 @@ export interface ShortConfig {
475477
deploymentId?: string;
476478
workersAiAccountId?: string;
477479
apiVersion?: string;
480+
/** Azure authentication mode: 'apiKey' | 'entra' | 'managed' | 'workload' | 'azure_cli' */
478481
azureAuthMode?: string;
479482
azureManagedClientId?: string;
480483
azureEntraClientId?: string;

0 commit comments

Comments
 (0)