Skip to content

Commit 13cf1ff

Browse files
authored
[identity] [keyvault] Fix long timeout in KeyVault with MSI (Azure#23035)
* Fix long timeout in KeyVault with MSI
1 parent d645024 commit 13cf1ff

File tree

3 files changed

+41
-43
lines changed

3 files changed

+41
-43
lines changed

sdk/identity/identity/src/credentials/managedIdentityCredential/imdsMsi.ts

Lines changed: 34 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
11
// Copyright (c) Microsoft Corporation.
22
// Licensed under the MIT license.
33

4-
import { delay } from "@azure/core-util";
4+
import { delay, isError } from "@azure/core-util";
55
import { AccessToken, GetTokenOptions } from "@azure/core-auth";
66
import {
77
PipelineRequestOptions,
8-
RestError,
98
createHttpHeaders,
109
createPipelineRequest,
1110
} from "@azure/core-rest-pipeline";
@@ -141,46 +140,35 @@ export const imdsMsi: MSI = {
141140
getTokenOptions,
142141
async (options) => {
143142
requestOptions.tracingOptions = options.tracingOptions;
143+
144+
// Create a request with a timeout since we expect that
145+
// not having a "Metadata" header should cause an error to be
146+
// returned quickly from the endpoint, proving its availability.
147+
const request = createPipelineRequest(requestOptions);
148+
149+
// Default to 300 if the default of 0 is used.
150+
// Negative values can still be used to disable the timeout.
151+
request.timeout = options.requestOptions?.timeout || 300;
152+
153+
// This MSI uses the imdsEndpoint to get the token, which only uses http://
154+
request.allowInsecureConnection = true;
155+
144156
try {
145-
// Create a request with a timeout since we expect that
146-
// not having a "Metadata" header should cause an error to be
147-
// returned quickly from the endpoint, proving its availability.
148-
const request = createPipelineRequest(requestOptions);
149-
150-
request.timeout = options.requestOptions?.timeout ?? 300;
151-
152-
// This MSI uses the imdsEndpoint to get the token, which only uses http://
153-
request.allowInsecureConnection = true;
154-
155-
try {
156-
logger.info(`${msiName}: Pinging the Azure IMDS endpoint`);
157-
await identityClient.sendRequest(request);
158-
} catch (err: any) {
159-
if (
160-
(err.name === "RestError" && err.code === RestError.REQUEST_SEND_ERROR) ||
161-
err.name === "AbortError" ||
162-
err.code === "ENETUNREACH" || // Network unreachable
163-
err.code === "ECONNREFUSED" || // connection refused
164-
err.code === "EHOSTDOWN" // host is down
165-
) {
166-
// If the request failed, or Node.js was unable to establish a connection,
167-
// or the host was down, we'll assume the IMDS endpoint isn't available.
168-
logger.info(`${msiName}: The Azure IMDS endpoint is unavailable`);
169-
return false;
170-
}
157+
logger.info(`${msiName}: Pinging the Azure IMDS endpoint`);
158+
await identityClient.sendRequest(request);
159+
} catch (err: unknown) {
160+
// If the request failed, or Node.js was unable to establish a connection,
161+
// or the host was down, we'll assume the IMDS endpoint isn't available.
162+
if (isError(err)) {
163+
logger.verbose(`${msiName}: Caught error ${err.name}: ${err.message}`);
171164
}
172-
173-
// If we received any response, the endpoint is available
174-
logger.info(`${msiName}: The Azure IMDS endpoint is available`);
175-
return true;
176-
} catch (err: any) {
177-
// createWebResource failed.
178-
// This error should bubble up to the user.
179-
logger.info(
180-
`${msiName}: Error when creating the WebResource for the Azure IMDS endpoint: ${err.message}`
181-
);
182-
throw err;
165+
logger.info(`${msiName}: The Azure IMDS endpoint is unavailable`);
166+
return false;
183167
}
168+
169+
// If we received any response, the endpoint is available
170+
logger.info(`${msiName}: The Azure IMDS endpoint is available`);
171+
return true;
184172
}
185173
);
186174
},
@@ -190,9 +178,13 @@ export const imdsMsi: MSI = {
190178
): Promise<AccessToken | null> {
191179
const { identityClient, scopes, clientId, resourceId } = configuration;
192180

193-
logger.info(
194-
`${msiName}: Using the Azure IMDS endpoint coming from the environment variable MSI_ENDPOINT=${process.env.MSI_ENDPOINT}, and using the cloud shell to proceed with the authentication.`
195-
);
181+
if (process.env.AZURE_POD_IDENTITY_AUTHORITY_HOST) {
182+
logger.info(
183+
`${msiName}: Using the Azure IMDS endpoint coming from the environment variable AZURE_POD_IDENTITY_AUTHORITY_HOST=${process.env.AZURE_POD_IDENTITY_AUTHORITY_HOST}.`
184+
);
185+
} else {
186+
logger.info(`${msiName}: Using the default Azure IMDS endpoint ${imdsHost}.`);
187+
}
196188

197189
let nextDelayInMs = imdsMsiRetryConfig.startDelayInMs;
198190
for (let retries = 0; retries < imdsMsiRetryConfig.maxRetries; retries++) {

sdk/identity/identity/src/util/logging.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ export interface CredentialLoggerInstance {
7070
fullTitle: string;
7171
info(message: string): void;
7272
warning(message: string): void;
73+
verbose(message: string): void;
7374
/**
7475
* The logging functions for warning and error are intentionally left out, since we want the identity logging to be at the info level.
7576
* Otherwise, they would look like:
@@ -101,11 +102,16 @@ export function credentialLoggerInstance(
101102
function warning(message: string): void {
102103
log.warning(`${fullTitle} =>`, message);
103104
}
105+
106+
function verbose(message: string): void {
107+
log.verbose(`${fullTitle} =>`, message);
108+
}
104109
return {
105110
title,
106111
fullTitle,
107112
info,
108113
warning,
114+
verbose,
109115
};
110116
}
111117

sdk/keyvault/keyvault-common/src/challengeBasedAuthenticationPolicy.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ export function createChallengeCallbacks(): ChallengeCallbacks {
5858
return {
5959
abortSignal: request.abortSignal,
6060
requestOptions: {
61-
timeout: request.timeout,
61+
timeout: request.timeout > 0 ? request.timeout : undefined,
6262
},
6363
tracingOptions: request.tracingOptions,
6464
};

0 commit comments

Comments
 (0)