@azure/identity 4.1.0-alpha.20240328.2 → 4.1.0-alpha.20240409.1

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.

Potentially problematic release.


This version of @azure/identity might be problematic. Click here for more details.

package/dist/index.js CHANGED
@@ -12,8 +12,8 @@ var fs = require('fs');
12
12
  var os = require('os');
13
13
  var path = require('path');
14
14
  var msalCommon = require('@azure/msal-node');
15
- var promises = require('fs/promises');
16
15
  var https = require('https');
16
+ var promises = require('fs/promises');
17
17
  var child_process = require('child_process');
18
18
  var crypto = require('crypto');
19
19
  var util = require('util');
@@ -1022,7 +1022,7 @@ const appServiceMsi2017 = {
1022
1022
 
1023
1023
  // Copyright (c) Microsoft Corporation.
1024
1024
  // Licensed under the MIT license.
1025
- const msiName$5 = "ManagedIdentityCredential - CloudShellMSI";
1025
+ const msiName$5 = "ManagedIdentityCredential - AppServiceMSI 2019";
1026
1026
  const logger$m = credentialLogger(msiName$5);
1027
1027
  /**
1028
1028
  * Generates the options used on the request for an access token.
@@ -1032,58 +1032,54 @@ function prepareRequestOptions$4(scopes, clientId, resourceId) {
1032
1032
  if (!resource) {
1033
1033
  throw new Error(`${msiName$5}: Multiple scopes are not supported.`);
1034
1034
  }
1035
- const body = {
1035
+ const queryParameters = {
1036
1036
  resource,
1037
+ "api-version": "2019-08-01",
1037
1038
  };
1038
1039
  if (clientId) {
1039
- body.client_id = clientId;
1040
+ queryParameters.client_id = clientId;
1040
1041
  }
1041
1042
  if (resourceId) {
1042
- body.msi_res_id = resourceId;
1043
+ queryParameters.mi_res_id = resourceId;
1043
1044
  }
1045
+ const query = new URLSearchParams(queryParameters);
1044
1046
  // This error should not bubble up, since we verify that this environment variable is defined in the isAvailable() method defined below.
1045
- if (!process.env.MSI_ENDPOINT) {
1046
- throw new Error(`${msiName$5}: Missing environment variable: MSI_ENDPOINT`);
1047
+ if (!process.env.IDENTITY_ENDPOINT) {
1048
+ throw new Error(`${msiName$5}: Missing environment variable: IDENTITY_ENDPOINT`);
1049
+ }
1050
+ if (!process.env.IDENTITY_HEADER) {
1051
+ throw new Error(`${msiName$5}: Missing environment variable: IDENTITY_HEADER`);
1047
1052
  }
1048
- const params = new URLSearchParams(body);
1049
1053
  return {
1050
- url: process.env.MSI_ENDPOINT,
1051
- method: "POST",
1052
- body: params.toString(),
1054
+ url: `${process.env.IDENTITY_ENDPOINT}?${query.toString()}`,
1055
+ method: "GET",
1053
1056
  headers: coreRestPipeline.createHttpHeaders({
1054
1057
  Accept: "application/json",
1055
- Metadata: "true",
1056
- "Content-Type": "application/x-www-form-urlencoded",
1058
+ "X-IDENTITY-HEADER": process.env.IDENTITY_HEADER,
1057
1059
  }),
1058
1060
  };
1059
1061
  }
1060
1062
  /**
1061
- * Defines how to determine whether the Azure Cloud Shell MSI is available, and also how to retrieve a token from the Azure Cloud Shell MSI.
1062
- * Since Azure Managed Identities aren't available in the Azure Cloud Shell, we log a warning for users that try to access cloud shell using user assigned identity.
1063
+ * Defines how to determine whether the Azure App Service MSI is available, and also how to retrieve a token from the Azure App Service MSI.
1063
1064
  */
1064
- const cloudShellMsi = {
1065
- name: "cloudShellMsi",
1065
+ const appServiceMsi2019 = {
1066
+ name: "appServiceMsi2019",
1066
1067
  async isAvailable({ scopes }) {
1067
1068
  const resource = mapScopesToResource(scopes);
1068
1069
  if (!resource) {
1069
1070
  logger$m.info(`${msiName$5}: Unavailable. Multiple scopes are not supported.`);
1070
1071
  return false;
1071
1072
  }
1072
- const result = Boolean(process.env.MSI_ENDPOINT);
1073
+ const env = process.env;
1074
+ const result = Boolean(env.IDENTITY_ENDPOINT && env.IDENTITY_HEADER);
1073
1075
  if (!result) {
1074
- logger$m.info(`${msiName$5}: Unavailable. The environment variable MSI_ENDPOINT is needed.`);
1076
+ logger$m.info(`${msiName$5}: Unavailable. The environment variables needed are: IDENTITY_ENDPOINT and IDENTITY_HEADER.`);
1075
1077
  }
1076
1078
  return result;
1077
1079
  },
1078
1080
  async getToken(configuration, getTokenOptions = {}) {
1079
1081
  const { identityClient, scopes, clientId, resourceId } = configuration;
1080
- if (clientId) {
1081
- logger$m.warning(`${msiName$5}: user-assigned identities not supported. The argument clientId might be ignored by the service.`);
1082
- }
1083
- if (resourceId) {
1084
- logger$m.warning(`${msiName$5}: user defined managed Identity by resource Id not supported. The argument resourceId might be ignored by the service.`);
1085
- }
1086
- logger$m.info(`${msiName$5}: Using the endpoint coming form the environment variable MSI_ENDPOINT = ${process.env.MSI_ENDPOINT}.`);
1082
+ logger$m.info(`${msiName$5}: Using the endpoint and the secret coming form the environment variables: IDENTITY_ENDPOINT=${process.env.IDENTITY_ENDPOINT} and IDENTITY_HEADER=[REDACTED].`);
1087
1083
  const request = coreRestPipeline.createPipelineRequest(Object.assign(Object.assign({ abortSignal: getTokenOptions.abortSignal }, prepareRequestOptions$4(scopes, clientId, resourceId)), {
1088
1084
  // Generally, MSI endpoints use the HTTP protocol, without transport layer security (TLS).
1089
1085
  allowInsecureConnection: true }));
@@ -1094,159 +1090,16 @@ const cloudShellMsi = {
1094
1090
 
1095
1091
  // Copyright (c) Microsoft Corporation.
1096
1092
  // Licensed under the MIT license.
1097
- const msiName$4 = "ManagedIdentityCredential - IMDS";
1093
+ const msiName$4 = "ManagedIdentityCredential - Azure Arc MSI";
1098
1094
  const logger$l = credentialLogger(msiName$4);
1099
1095
  /**
1100
1096
  * Generates the options used on the request for an access token.
1101
1097
  */
1102
- function prepareRequestOptions$3(scopes, clientId, resourceId, options) {
1103
- var _a;
1098
+ function prepareRequestOptions$3(scopes, clientId, resourceId) {
1104
1099
  const resource = mapScopesToResource(scopes);
1105
1100
  if (!resource) {
1106
1101
  throw new Error(`${msiName$4}: Multiple scopes are not supported.`);
1107
1102
  }
1108
- const { skipQuery, skipMetadataHeader } = options || {};
1109
- let query = "";
1110
- // Pod Identity will try to process this request even if the Metadata header is missing.
1111
- // We can exclude the request query to ensure no IMDS endpoint tries to process the ping request.
1112
- if (!skipQuery) {
1113
- const queryParameters = {
1114
- resource,
1115
- "api-version": imdsApiVersion,
1116
- };
1117
- if (clientId) {
1118
- queryParameters.client_id = clientId;
1119
- }
1120
- if (resourceId) {
1121
- queryParameters.msi_res_id = resourceId;
1122
- }
1123
- const params = new URLSearchParams(queryParameters);
1124
- query = `?${params.toString()}`;
1125
- }
1126
- const url = new URL(imdsEndpointPath, (_a = process.env.AZURE_POD_IDENTITY_AUTHORITY_HOST) !== null && _a !== void 0 ? _a : imdsHost);
1127
- const rawHeaders = {
1128
- Accept: "application/json",
1129
- Metadata: "true",
1130
- };
1131
- // Remove the Metadata header to invoke a request error from some IMDS endpoints.
1132
- if (skipMetadataHeader) {
1133
- delete rawHeaders.Metadata;
1134
- }
1135
- return {
1136
- // In this case, the `?` should be added in the "query" variable `skipQuery` is not set.
1137
- url: `${url}${query}`,
1138
- method: "GET",
1139
- headers: coreRestPipeline.createHttpHeaders(rawHeaders),
1140
- };
1141
- }
1142
- // 800ms -> 1600ms -> 3200ms
1143
- const imdsMsiRetryConfig = {
1144
- maxRetries: 3,
1145
- startDelayInMs: 800,
1146
- intervalIncrement: 2,
1147
- };
1148
- /**
1149
- * Defines how to determine whether the Azure IMDS MSI is available, and also how to retrieve a token from the Azure IMDS MSI.
1150
- */
1151
- const imdsMsi = {
1152
- name: "imdsMsi",
1153
- async isAvailable({ scopes, identityClient, clientId, resourceId, getTokenOptions = {}, }) {
1154
- const resource = mapScopesToResource(scopes);
1155
- if (!resource) {
1156
- logger$l.info(`${msiName$4}: Unavailable. Multiple scopes are not supported.`);
1157
- return false;
1158
- }
1159
- // if the PodIdentityEndpoint environment variable was set no need to probe the endpoint, it can be assumed to exist
1160
- if (process.env.AZURE_POD_IDENTITY_AUTHORITY_HOST) {
1161
- return true;
1162
- }
1163
- if (!identityClient) {
1164
- throw new Error("Missing IdentityClient");
1165
- }
1166
- const requestOptions = prepareRequestOptions$3(resource, clientId, resourceId, {
1167
- skipMetadataHeader: true,
1168
- skipQuery: true,
1169
- });
1170
- return tracingClient.withSpan("ManagedIdentityCredential-pingImdsEndpoint", getTokenOptions, async (options) => {
1171
- var _a, _b;
1172
- requestOptions.tracingOptions = options.tracingOptions;
1173
- // Create a request with a timeout since we expect that
1174
- // not having a "Metadata" header should cause an error to be
1175
- // returned quickly from the endpoint, proving its availability.
1176
- const request = coreRestPipeline.createPipelineRequest(requestOptions);
1177
- // Default to 1000 if the default of 0 is used.
1178
- // Negative values can still be used to disable the timeout.
1179
- request.timeout = ((_a = options.requestOptions) === null || _a === void 0 ? void 0 : _a.timeout) || 1000;
1180
- // This MSI uses the imdsEndpoint to get the token, which only uses http://
1181
- request.allowInsecureConnection = true;
1182
- let response;
1183
- try {
1184
- logger$l.info(`${msiName$4}: Pinging the Azure IMDS endpoint`);
1185
- response = await identityClient.sendRequest(request);
1186
- }
1187
- catch (err) {
1188
- // If the request failed, or Node.js was unable to establish a connection,
1189
- // or the host was down, we'll assume the IMDS endpoint isn't available.
1190
- if (coreUtil.isError(err)) {
1191
- logger$l.verbose(`${msiName$4}: Caught error ${err.name}: ${err.message}`);
1192
- }
1193
- // This is a special case for Docker Desktop which responds with a 403 with a message that contains "A socket operation was attempted to an unreachable network"
1194
- // rather than just timing out, as expected.
1195
- logger$l.info(`${msiName$4}: The Azure IMDS endpoint is unavailable`);
1196
- return false;
1197
- }
1198
- if (response.status === 403) {
1199
- if ((_b = response.bodyAsText) === null || _b === void 0 ? void 0 : _b.includes("A socket operation was attempted to an unreachable network")) {
1200
- logger$l.info(`${msiName$4}: The Azure IMDS endpoint is unavailable`);
1201
- logger$l.info(`${msiName$4}: ${response.bodyAsText}`);
1202
- return false;
1203
- }
1204
- }
1205
- // If we received any response, the endpoint is available
1206
- logger$l.info(`${msiName$4}: The Azure IMDS endpoint is available`);
1207
- return true;
1208
- });
1209
- },
1210
- async getToken(configuration, getTokenOptions = {}) {
1211
- const { identityClient, scopes, clientId, resourceId } = configuration;
1212
- if (process.env.AZURE_POD_IDENTITY_AUTHORITY_HOST) {
1213
- logger$l.info(`${msiName$4}: Using the Azure IMDS endpoint coming from the environment variable AZURE_POD_IDENTITY_AUTHORITY_HOST=${process.env.AZURE_POD_IDENTITY_AUTHORITY_HOST}.`);
1214
- }
1215
- else {
1216
- logger$l.info(`${msiName$4}: Using the default Azure IMDS endpoint ${imdsHost}.`);
1217
- }
1218
- let nextDelayInMs = imdsMsiRetryConfig.startDelayInMs;
1219
- for (let retries = 0; retries < imdsMsiRetryConfig.maxRetries; retries++) {
1220
- try {
1221
- const request = coreRestPipeline.createPipelineRequest(Object.assign(Object.assign({ abortSignal: getTokenOptions.abortSignal }, prepareRequestOptions$3(scopes, clientId, resourceId)), { allowInsecureConnection: true }));
1222
- const tokenResponse = await identityClient.sendTokenRequest(request);
1223
- return (tokenResponse && tokenResponse.accessToken) || null;
1224
- }
1225
- catch (error) {
1226
- if (error.statusCode === 404) {
1227
- await coreUtil.delay(nextDelayInMs);
1228
- nextDelayInMs *= imdsMsiRetryConfig.intervalIncrement;
1229
- continue;
1230
- }
1231
- throw error;
1232
- }
1233
- }
1234
- throw new AuthenticationError(404, `${msiName$4}: Failed to retrieve IMDS token after ${imdsMsiRetryConfig.maxRetries} retries.`);
1235
- },
1236
- };
1237
-
1238
- // Copyright (c) Microsoft Corporation.
1239
- // Licensed under the MIT license.
1240
- const msiName$3 = "ManagedIdentityCredential - Azure Arc MSI";
1241
- const logger$k = credentialLogger(msiName$3);
1242
- /**
1243
- * Generates the options used on the request for an access token.
1244
- */
1245
- function prepareRequestOptions$2(scopes, clientId, resourceId) {
1246
- const resource = mapScopesToResource(scopes);
1247
- if (!resource) {
1248
- throw new Error(`${msiName$3}: Multiple scopes are not supported.`);
1249
- }
1250
1103
  const queryParameters = {
1251
1104
  resource,
1252
1105
  "api-version": azureArcAPIVersion,
@@ -1259,7 +1112,7 @@ function prepareRequestOptions$2(scopes, clientId, resourceId) {
1259
1112
  }
1260
1113
  // This error should not bubble up, since we verify that this environment variable is defined in the isAvailable() method defined below.
1261
1114
  if (!process.env.IDENTITY_ENDPOINT) {
1262
- throw new Error(`${msiName$3}: Missing environment variable: IDENTITY_ENDPOINT`);
1115
+ throw new Error(`${msiName$4}: Missing environment variable: IDENTITY_ENDPOINT`);
1263
1116
  }
1264
1117
  const query = new URLSearchParams(queryParameters);
1265
1118
  return coreRestPipeline.createPipelineRequest({
@@ -1294,7 +1147,7 @@ async function filePathRequest(identityClient, requestPrepareOptions) {
1294
1147
  if (response.bodyAsText) {
1295
1148
  message = ` Response: ${response.bodyAsText}`;
1296
1149
  }
1297
- throw new AuthenticationError(response.status, `${msiName$3}: To authenticate with Azure Arc MSI, status code 401 is expected on the first request. ${message}`);
1150
+ throw new AuthenticationError(response.status, `${msiName$4}: To authenticate with Azure Arc MSI, status code 401 is expected on the first request. ${message}`);
1298
1151
  }
1299
1152
  const authHeader = response.headers.get("www-authenticate") || "";
1300
1153
  try {
@@ -1312,12 +1165,12 @@ const arcMsi = {
1312
1165
  async isAvailable({ scopes }) {
1313
1166
  const resource = mapScopesToResource(scopes);
1314
1167
  if (!resource) {
1315
- logger$k.info(`${msiName$3}: Unavailable. Multiple scopes are not supported.`);
1168
+ logger$l.info(`${msiName$4}: Unavailable. Multiple scopes are not supported.`);
1316
1169
  return false;
1317
1170
  }
1318
1171
  const result = Boolean(process.env.IMDS_ENDPOINT && process.env.IDENTITY_ENDPOINT);
1319
1172
  if (!result) {
1320
- logger$k.info(`${msiName$3}: The environment variables needed are: IMDS_ENDPOINT and IDENTITY_ENDPOINT`);
1173
+ logger$l.info(`${msiName$4}: The environment variables needed are: IMDS_ENDPOINT and IDENTITY_ENDPOINT`);
1321
1174
  }
1322
1175
  return result;
1323
1176
  },
@@ -1325,16 +1178,16 @@ const arcMsi = {
1325
1178
  var _a;
1326
1179
  const { identityClient, scopes, clientId, resourceId } = configuration;
1327
1180
  if (clientId) {
1328
- logger$k.warning(`${msiName$3}: user-assigned identities not supported. The argument clientId might be ignored by the service.`);
1181
+ logger$l.warning(`${msiName$4}: user-assigned identities not supported. The argument clientId might be ignored by the service.`);
1329
1182
  }
1330
1183
  if (resourceId) {
1331
- logger$k.warning(`${msiName$3}: user defined managed Identity by resource Id is not supported. Argument resourceId will be ignored.`);
1184
+ logger$l.warning(`${msiName$4}: user defined managed Identity by resource Id is not supported. Argument resourceId will be ignored.`);
1332
1185
  }
1333
- logger$k.info(`${msiName$3}: Authenticating.`);
1334
- const requestOptions = Object.assign(Object.assign({ disableJsonStringifyOnBody: true, deserializationMapper: undefined, abortSignal: getTokenOptions.abortSignal }, prepareRequestOptions$2(scopes, clientId, resourceId)), { allowInsecureConnection: true });
1186
+ logger$l.info(`${msiName$4}: Authenticating.`);
1187
+ const requestOptions = Object.assign(Object.assign({ disableJsonStringifyOnBody: true, deserializationMapper: undefined, abortSignal: getTokenOptions.abortSignal }, prepareRequestOptions$3(scopes, clientId, resourceId)), { allowInsecureConnection: true });
1335
1188
  const filePath = await filePathRequest(identityClient, requestOptions);
1336
1189
  if (!filePath) {
1337
- throw new Error(`${msiName$3}: Failed to find the token file.`);
1190
+ throw new Error(`${msiName$4}: Failed to find the token file.`);
1338
1191
  }
1339
1192
  const key = await readFileAsync$1(filePath, { encoding: "utf-8" });
1340
1193
  (_a = requestOptions.headers) === null || _a === void 0 ? void 0 : _a.set("Authorization", `Basic ${key}`);
@@ -1346,12 +1199,174 @@ const arcMsi = {
1346
1199
  },
1347
1200
  };
1348
1201
 
1202
+ // Copyright (c) Microsoft Corporation.
1203
+ // Licensed under the MIT license.
1204
+ const msiName$3 = "ManagedIdentityCredential - CloudShellMSI";
1205
+ const logger$k = credentialLogger(msiName$3);
1206
+ /**
1207
+ * Generates the options used on the request for an access token.
1208
+ */
1209
+ function prepareRequestOptions$2(scopes, clientId, resourceId) {
1210
+ const resource = mapScopesToResource(scopes);
1211
+ if (!resource) {
1212
+ throw new Error(`${msiName$3}: Multiple scopes are not supported.`);
1213
+ }
1214
+ const body = {
1215
+ resource,
1216
+ };
1217
+ if (clientId) {
1218
+ body.client_id = clientId;
1219
+ }
1220
+ if (resourceId) {
1221
+ body.msi_res_id = resourceId;
1222
+ }
1223
+ // This error should not bubble up, since we verify that this environment variable is defined in the isAvailable() method defined below.
1224
+ if (!process.env.MSI_ENDPOINT) {
1225
+ throw new Error(`${msiName$3}: Missing environment variable: MSI_ENDPOINT`);
1226
+ }
1227
+ const params = new URLSearchParams(body);
1228
+ return {
1229
+ url: process.env.MSI_ENDPOINT,
1230
+ method: "POST",
1231
+ body: params.toString(),
1232
+ headers: coreRestPipeline.createHttpHeaders({
1233
+ Accept: "application/json",
1234
+ Metadata: "true",
1235
+ "Content-Type": "application/x-www-form-urlencoded",
1236
+ }),
1237
+ };
1238
+ }
1239
+ /**
1240
+ * Defines how to determine whether the Azure Cloud Shell MSI is available, and also how to retrieve a token from the Azure Cloud Shell MSI.
1241
+ * Since Azure Managed Identities aren't available in the Azure Cloud Shell, we log a warning for users that try to access cloud shell using user assigned identity.
1242
+ */
1243
+ const cloudShellMsi = {
1244
+ name: "cloudShellMsi",
1245
+ async isAvailable({ scopes }) {
1246
+ const resource = mapScopesToResource(scopes);
1247
+ if (!resource) {
1248
+ logger$k.info(`${msiName$3}: Unavailable. Multiple scopes are not supported.`);
1249
+ return false;
1250
+ }
1251
+ const result = Boolean(process.env.MSI_ENDPOINT);
1252
+ if (!result) {
1253
+ logger$k.info(`${msiName$3}: Unavailable. The environment variable MSI_ENDPOINT is needed.`);
1254
+ }
1255
+ return result;
1256
+ },
1257
+ async getToken(configuration, getTokenOptions = {}) {
1258
+ const { identityClient, scopes, clientId, resourceId } = configuration;
1259
+ if (clientId) {
1260
+ logger$k.warning(`${msiName$3}: user-assigned identities not supported. The argument clientId might be ignored by the service.`);
1261
+ }
1262
+ if (resourceId) {
1263
+ logger$k.warning(`${msiName$3}: user defined managed Identity by resource Id not supported. The argument resourceId might be ignored by the service.`);
1264
+ }
1265
+ logger$k.info(`${msiName$3}: Using the endpoint coming form the environment variable MSI_ENDPOINT = ${process.env.MSI_ENDPOINT}.`);
1266
+ const request = coreRestPipeline.createPipelineRequest(Object.assign(Object.assign({ abortSignal: getTokenOptions.abortSignal }, prepareRequestOptions$2(scopes, clientId, resourceId)), {
1267
+ // Generally, MSI endpoints use the HTTP protocol, without transport layer security (TLS).
1268
+ allowInsecureConnection: true }));
1269
+ const tokenResponse = await identityClient.sendTokenRequest(request);
1270
+ return (tokenResponse && tokenResponse.accessToken) || null;
1271
+ },
1272
+ };
1273
+
1274
+ // Copyright (c) Microsoft Corporation.
1275
+ // Licensed under the MIT license.
1276
+ // This MSI can be easily tested by deploying a container to Azure Service Fabric with the Dockerfile:
1277
+ //
1278
+ // FROM node:12
1279
+ // RUN wget https://host.any/path/bash.sh
1280
+ // CMD ["bash", "bash.sh"]
1281
+ //
1282
+ // Where the bash script contains:
1283
+ //
1284
+ // curl --insecure $IDENTITY_ENDPOINT'?api-version=2019-07-01-preview&resource=https://vault.azure.net/' -H "Secret: $IDENTITY_HEADER"
1285
+ //
1286
+ const msiName$2 = "ManagedIdentityCredential - Fabric MSI";
1287
+ const logger$j = credentialLogger(msiName$2);
1288
+ /**
1289
+ * Generates the options used on the request for an access token.
1290
+ */
1291
+ function prepareRequestOptions$1(scopes, clientId, resourceId) {
1292
+ const resource = mapScopesToResource(scopes);
1293
+ if (!resource) {
1294
+ throw new Error(`${msiName$2}: Multiple scopes are not supported.`);
1295
+ }
1296
+ const queryParameters = {
1297
+ resource,
1298
+ "api-version": azureFabricVersion,
1299
+ };
1300
+ if (clientId) {
1301
+ queryParameters.client_id = clientId;
1302
+ }
1303
+ if (resourceId) {
1304
+ queryParameters.msi_res_id = resourceId;
1305
+ }
1306
+ const query = new URLSearchParams(queryParameters);
1307
+ // This error should not bubble up, since we verify that this environment variable is defined in the isAvailable() method defined below.
1308
+ if (!process.env.IDENTITY_ENDPOINT) {
1309
+ throw new Error("Missing environment variable: IDENTITY_ENDPOINT");
1310
+ }
1311
+ if (!process.env.IDENTITY_HEADER) {
1312
+ throw new Error("Missing environment variable: IDENTITY_HEADER");
1313
+ }
1314
+ return {
1315
+ url: `${process.env.IDENTITY_ENDPOINT}?${query.toString()}`,
1316
+ method: "GET",
1317
+ headers: coreRestPipeline.createHttpHeaders({
1318
+ Accept: "application/json",
1319
+ secret: process.env.IDENTITY_HEADER,
1320
+ }),
1321
+ };
1322
+ }
1323
+ /**
1324
+ * Defines how to determine whether the Azure Service Fabric MSI is available, and also how to retrieve a token from the Azure Service Fabric MSI.
1325
+ */
1326
+ const fabricMsi = {
1327
+ name: "fabricMsi",
1328
+ async isAvailable({ scopes }) {
1329
+ const resource = mapScopesToResource(scopes);
1330
+ if (!resource) {
1331
+ logger$j.info(`${msiName$2}: Unavailable. Multiple scopes are not supported.`);
1332
+ return false;
1333
+ }
1334
+ const env = process.env;
1335
+ const result = Boolean(env.IDENTITY_ENDPOINT && env.IDENTITY_HEADER && env.IDENTITY_SERVER_THUMBPRINT);
1336
+ if (!result) {
1337
+ logger$j.info(`${msiName$2}: Unavailable. The environment variables needed are: IDENTITY_ENDPOINT, IDENTITY_HEADER and IDENTITY_SERVER_THUMBPRINT`);
1338
+ }
1339
+ return result;
1340
+ },
1341
+ async getToken(configuration, getTokenOptions = {}) {
1342
+ const { scopes, identityClient, clientId, resourceId } = configuration;
1343
+ if (resourceId) {
1344
+ logger$j.warning(`${msiName$2}: user defined managed Identity by resource Id is not supported. Argument resourceId might be ignored by the service.`);
1345
+ }
1346
+ logger$j.info([
1347
+ `${msiName$2}:`,
1348
+ "Using the endpoint and the secret coming from the environment variables:",
1349
+ `IDENTITY_ENDPOINT=${process.env.IDENTITY_ENDPOINT},`,
1350
+ "IDENTITY_HEADER=[REDACTED] and",
1351
+ "IDENTITY_SERVER_THUMBPRINT=[REDACTED].",
1352
+ ].join(" "));
1353
+ const request = coreRestPipeline.createPipelineRequest(Object.assign({ abortSignal: getTokenOptions.abortSignal }, prepareRequestOptions$1(scopes, clientId, resourceId)));
1354
+ request.agent = new https.Agent({
1355
+ // This is necessary because Service Fabric provides a self-signed certificate.
1356
+ // The alternative path is to verify the certificate using the IDENTITY_SERVER_THUMBPRINT env variable.
1357
+ rejectUnauthorized: false,
1358
+ });
1359
+ const tokenResponse = await identityClient.sendTokenRequest(request);
1360
+ return (tokenResponse && tokenResponse.accessToken) || null;
1361
+ },
1362
+ };
1363
+
1349
1364
  // Copyright (c) Microsoft Corporation.
1350
1365
  // Licensed under the MIT license.
1351
1366
  /**
1352
1367
  * @internal
1353
1368
  */
1354
- const logger$j = credentialLogger("IdentityUtils");
1369
+ const logger$i = credentialLogger("IdentityUtils");
1355
1370
  /**
1356
1371
  * Latest AuthenticationRecord version
1357
1372
  * @internal
@@ -1363,7 +1378,7 @@ const LatestAuthenticationRecordVersion = "1.0";
1363
1378
  */
1364
1379
  function ensureValidMsalToken(scopes, msalToken, getTokenOptions) {
1365
1380
  const error = (message) => {
1366
- logger$j.getToken.info(message);
1381
+ logger$i.getToken.info(message);
1367
1382
  return new AuthenticationRequiredError({
1368
1383
  scopes: Array.isArray(scopes) ? scopes : [scopes],
1369
1384
  getTokenOptions,
@@ -1473,17 +1488,17 @@ function handleMsalError(scopes, error, getTokenOptions) {
1473
1488
  const msalError = error;
1474
1489
  switch (msalError.errorCode) {
1475
1490
  case "endpoints_resolution_error":
1476
- logger$j.info(formatError(scopes, error.message));
1491
+ logger$i.info(formatError(scopes, error.message));
1477
1492
  return new CredentialUnavailableError(error.message);
1478
1493
  case "device_code_polling_cancelled":
1479
1494
  return new abortController.AbortError("The authentication has been aborted by the caller.");
1480
1495
  case "consent_required":
1481
1496
  case "interaction_required":
1482
1497
  case "login_required":
1483
- logger$j.info(formatError(scopes, `Authentication returned errorCode ${msalError.errorCode}`));
1498
+ logger$i.info(formatError(scopes, `Authentication returned errorCode ${msalError.errorCode}`));
1484
1499
  break;
1485
1500
  default:
1486
- logger$j.info(formatError(scopes, `Failed to acquire token: ${error.message}`));
1501
+ logger$i.info(formatError(scopes, `Failed to acquire token: ${error.message}`));
1487
1502
  break;
1488
1503
  }
1489
1504
  }
@@ -1493,7 +1508,7 @@ function handleMsalError(scopes, error, getTokenOptions) {
1493
1508
  return error;
1494
1509
  }
1495
1510
  if (error.name === "NativeAuthError") {
1496
- logger$j.info(formatError(scopes, `Error from the native broker: ${error.message} with status code: ${error.statusCode}`));
1511
+ logger$i.info(formatError(scopes, `Error from the native broker: ${error.message} with status code: ${error.statusCode}`));
1497
1512
  return error;
1498
1513
  }
1499
1514
  return new AuthenticationRequiredError({ scopes, getTokenOptions, message: error.message });
@@ -1532,31 +1547,168 @@ function serializeAuthenticationRecord(record) {
1532
1547
  return JSON.stringify(record);
1533
1548
  }
1534
1549
  /**
1535
- * Deserializes a previously serialized authentication record from a string into an object.
1536
- *
1537
- * The input string must contain the following properties:
1538
- *
1539
- * - "authority"
1540
- * - "homeAccountId"
1541
- * - "clientId"
1542
- * - "tenantId"
1543
- * - "username"
1544
- * - "version"
1545
- *
1546
- * If the version we receive is unsupported, an error will be thrown.
1547
- *
1548
- * At the moment, the only available version is: "1.0", which is always set when the authentication record is serialized.
1549
- *
1550
- * @param serializedRecord - Authentication record previously serialized into string.
1551
- * @returns AuthenticationRecord.
1550
+ * Deserializes a previously serialized authentication record from a string into an object.
1551
+ *
1552
+ * The input string must contain the following properties:
1553
+ *
1554
+ * - "authority"
1555
+ * - "homeAccountId"
1556
+ * - "clientId"
1557
+ * - "tenantId"
1558
+ * - "username"
1559
+ * - "version"
1560
+ *
1561
+ * If the version we receive is unsupported, an error will be thrown.
1562
+ *
1563
+ * At the moment, the only available version is: "1.0", which is always set when the authentication record is serialized.
1564
+ *
1565
+ * @param serializedRecord - Authentication record previously serialized into string.
1566
+ * @returns AuthenticationRecord.
1567
+ */
1568
+ function deserializeAuthenticationRecord(serializedRecord) {
1569
+ const parsed = JSON.parse(serializedRecord);
1570
+ if (parsed.version && parsed.version !== LatestAuthenticationRecordVersion) {
1571
+ throw Error("Unsupported AuthenticationRecord version");
1572
+ }
1573
+ return parsed;
1574
+ }
1575
+
1576
+ // Copyright (c) Microsoft Corporation.
1577
+ // Licensed under the MIT license.
1578
+ const msiName$1 = "ManagedIdentityCredential - IMDS";
1579
+ const logger$h = credentialLogger(msiName$1);
1580
+ /**
1581
+ * Generates the options used on the request for an access token.
1582
+ */
1583
+ function prepareRequestOptions(scopes, clientId, resourceId, options) {
1584
+ var _a;
1585
+ const resource = mapScopesToResource(scopes);
1586
+ if (!resource) {
1587
+ throw new Error(`${msiName$1}: Multiple scopes are not supported.`);
1588
+ }
1589
+ const { skipQuery, skipMetadataHeader } = options || {};
1590
+ let query = "";
1591
+ // Pod Identity will try to process this request even if the Metadata header is missing.
1592
+ // We can exclude the request query to ensure no IMDS endpoint tries to process the ping request.
1593
+ if (!skipQuery) {
1594
+ const queryParameters = {
1595
+ resource,
1596
+ "api-version": imdsApiVersion,
1597
+ };
1598
+ if (clientId) {
1599
+ queryParameters.client_id = clientId;
1600
+ }
1601
+ if (resourceId) {
1602
+ queryParameters.msi_res_id = resourceId;
1603
+ }
1604
+ const params = new URLSearchParams(queryParameters);
1605
+ query = `?${params.toString()}`;
1606
+ }
1607
+ const url = new URL(imdsEndpointPath, (_a = process.env.AZURE_POD_IDENTITY_AUTHORITY_HOST) !== null && _a !== void 0 ? _a : imdsHost);
1608
+ const rawHeaders = {
1609
+ Accept: "application/json",
1610
+ Metadata: "true",
1611
+ };
1612
+ // Remove the Metadata header to invoke a request error from some IMDS endpoints.
1613
+ if (skipMetadataHeader) {
1614
+ delete rawHeaders.Metadata;
1615
+ }
1616
+ return {
1617
+ // In this case, the `?` should be added in the "query" variable `skipQuery` is not set.
1618
+ url: `${url}${query}`,
1619
+ method: "GET",
1620
+ headers: coreRestPipeline.createHttpHeaders(rawHeaders),
1621
+ };
1622
+ }
1623
+ /**
1624
+ * Defines how to determine whether the Azure IMDS MSI is available, and also how to retrieve a token from the Azure IMDS MSI.
1552
1625
  */
1553
- function deserializeAuthenticationRecord(serializedRecord) {
1554
- const parsed = JSON.parse(serializedRecord);
1555
- if (parsed.version && parsed.version !== LatestAuthenticationRecordVersion) {
1556
- throw Error("Unsupported AuthenticationRecord version");
1557
- }
1558
- return parsed;
1559
- }
1626
+ const imdsMsi = {
1627
+ name: "imdsMsi",
1628
+ async isAvailable({ scopes, identityClient, clientId, resourceId, getTokenOptions = {}, }) {
1629
+ const resource = mapScopesToResource(scopes);
1630
+ if (!resource) {
1631
+ logger$h.info(`${msiName$1}: Unavailable. Multiple scopes are not supported.`);
1632
+ return false;
1633
+ }
1634
+ // if the PodIdentityEndpoint environment variable was set no need to probe the endpoint, it can be assumed to exist
1635
+ if (process.env.AZURE_POD_IDENTITY_AUTHORITY_HOST) {
1636
+ return true;
1637
+ }
1638
+ if (!identityClient) {
1639
+ throw new Error("Missing IdentityClient");
1640
+ }
1641
+ const requestOptions = prepareRequestOptions(resource, clientId, resourceId, {
1642
+ skipMetadataHeader: true,
1643
+ skipQuery: true,
1644
+ });
1645
+ return tracingClient.withSpan("ManagedIdentityCredential-pingImdsEndpoint", getTokenOptions, async (options) => {
1646
+ var _a, _b;
1647
+ requestOptions.tracingOptions = options.tracingOptions;
1648
+ // Create a request with a timeout since we expect that
1649
+ // not having a "Metadata" header should cause an error to be
1650
+ // returned quickly from the endpoint, proving its availability.
1651
+ const request = coreRestPipeline.createPipelineRequest(requestOptions);
1652
+ // Default to 1000 if the default of 0 is used.
1653
+ // Negative values can still be used to disable the timeout.
1654
+ request.timeout = ((_a = options.requestOptions) === null || _a === void 0 ? void 0 : _a.timeout) || 1000;
1655
+ // This MSI uses the imdsEndpoint to get the token, which only uses http://
1656
+ request.allowInsecureConnection = true;
1657
+ let response;
1658
+ try {
1659
+ logger$h.info(`${msiName$1}: Pinging the Azure IMDS endpoint`);
1660
+ response = await identityClient.sendRequest(request);
1661
+ }
1662
+ catch (err) {
1663
+ // If the request failed, or Node.js was unable to establish a connection,
1664
+ // or the host was down, we'll assume the IMDS endpoint isn't available.
1665
+ if (coreUtil.isError(err)) {
1666
+ logger$h.verbose(`${msiName$1}: Caught error ${err.name}: ${err.message}`);
1667
+ }
1668
+ // This is a special case for Docker Desktop which responds with a 403 with a message that contains "A socket operation was attempted to an unreachable network" or "A socket operation was attempted to an unreachable host"
1669
+ // rather than just timing out, as expected.
1670
+ logger$h.info(`${msiName$1}: The Azure IMDS endpoint is unavailable`);
1671
+ return false;
1672
+ }
1673
+ if (response.status === 403) {
1674
+ if ((_b = response.bodyAsText) === null || _b === void 0 ? void 0 : _b.includes("unreachable")) {
1675
+ logger$h.info(`${msiName$1}: The Azure IMDS endpoint is unavailable`);
1676
+ logger$h.info(`${msiName$1}: ${response.bodyAsText}`);
1677
+ return false;
1678
+ }
1679
+ }
1680
+ // If we received any response, the endpoint is available
1681
+ logger$h.info(`${msiName$1}: The Azure IMDS endpoint is available`);
1682
+ return true;
1683
+ });
1684
+ },
1685
+ async getToken(configuration, getTokenOptions = {}) {
1686
+ const { identityClient, scopes, clientId, resourceId } = configuration;
1687
+ if (process.env.AZURE_POD_IDENTITY_AUTHORITY_HOST) {
1688
+ logger$h.info(`${msiName$1}: Using the Azure IMDS endpoint coming from the environment variable AZURE_POD_IDENTITY_AUTHORITY_HOST=${process.env.AZURE_POD_IDENTITY_AUTHORITY_HOST}.`);
1689
+ }
1690
+ else {
1691
+ logger$h.info(`${msiName$1}: Using the default Azure IMDS endpoint ${imdsHost}.`);
1692
+ }
1693
+ let nextDelayInMs = configuration.retryConfig.startDelayInMs;
1694
+ for (let retries = 0; retries < configuration.retryConfig.maxRetries; retries++) {
1695
+ try {
1696
+ const request = coreRestPipeline.createPipelineRequest(Object.assign(Object.assign({ abortSignal: getTokenOptions.abortSignal }, prepareRequestOptions(scopes, clientId, resourceId)), { allowInsecureConnection: true }));
1697
+ const tokenResponse = await identityClient.sendTokenRequest(request);
1698
+ return (tokenResponse && tokenResponse.accessToken) || null;
1699
+ }
1700
+ catch (error) {
1701
+ if (error.statusCode === 404) {
1702
+ await coreUtil.delay(nextDelayInMs);
1703
+ nextDelayInMs *= configuration.retryConfig.intervalIncrement;
1704
+ continue;
1705
+ }
1706
+ throw error;
1707
+ }
1708
+ }
1709
+ throw new AuthenticationError(404, `${msiName$1}: Failed to retrieve IMDS token after ${configuration.retryConfig.maxRetries} retries.`);
1710
+ },
1711
+ };
1560
1712
 
1561
1713
  // Copyright (c) Microsoft Corporation.
1562
1714
  // Licensed under the MIT license.
@@ -2047,7 +2199,7 @@ class MsalClientAssertion extends MsalNode {
2047
2199
 
2048
2200
  // Copyright (c) Microsoft Corporation.
2049
2201
  // Licensed under the MIT license.
2050
- const logger$i = credentialLogger("ClientAssertionCredential");
2202
+ const logger$g = credentialLogger("ClientAssertionCredential");
2051
2203
  /**
2052
2204
  * Authenticates a service principal with a JWT assertion.
2053
2205
  */
@@ -2070,7 +2222,7 @@ class ClientAssertionCredential {
2070
2222
  this.additionallyAllowedTenantIds = resolveAdditionallyAllowedTenantIds(options === null || options === void 0 ? void 0 : options.additionallyAllowedTenants);
2071
2223
  this.clientId = clientId;
2072
2224
  this.options = options;
2073
- this.msalFlow = new MsalClientAssertion(Object.assign(Object.assign({}, options), { logger: logger$i, clientId: this.clientId, tenantId: this.tenantId, tokenCredentialOptions: this.options, getAssertion }));
2225
+ this.msalFlow = new MsalClientAssertion(Object.assign(Object.assign({}, options), { logger: logger$g, clientId: this.clientId, tenantId: this.tenantId, tokenCredentialOptions: this.options, getAssertion }));
2074
2226
  }
2075
2227
  /**
2076
2228
  * Authenticates with Microsoft Entra ID and returns an access token if successful.
@@ -2082,7 +2234,7 @@ class ClientAssertionCredential {
2082
2234
  */
2083
2235
  async getToken(scopes, options = {}) {
2084
2236
  return tracingClient.withSpan(`${this.constructor.name}.getToken`, options, async (newOptions) => {
2085
- newOptions.tenantId = processMultiTenantRequest(this.tenantId, newOptions, this.additionallyAllowedTenantIds, logger$i);
2237
+ newOptions.tenantId = processMultiTenantRequest(this.tenantId, newOptions, this.additionallyAllowedTenantIds, logger$g);
2086
2238
  const arrayScopes = Array.isArray(scopes) ? scopes : [scopes];
2087
2239
  return this.msalFlow.getToken(arrayScopes, newOptions);
2088
2240
  });
@@ -2104,7 +2256,7 @@ const SupportedWorkloadEnvironmentVariables = [
2104
2256
  "AZURE_CLIENT_ID",
2105
2257
  "AZURE_FEDERATED_TOKEN_FILE",
2106
2258
  ];
2107
- const logger$h = credentialLogger(credentialName$3);
2259
+ const logger$f = credentialLogger(credentialName$3);
2108
2260
  /**
2109
2261
  * Workload Identity authentication is a feature in Azure that allows applications running on virtual machines (VMs)
2110
2262
  * to access other Azure resources without the need for a service principal or managed identity. With Workload Identity
@@ -2130,17 +2282,17 @@ class WorkloadIdentityCredential {
2130
2282
  this.cacheDate = undefined;
2131
2283
  // Logging environment variables for error details
2132
2284
  const assignedEnv = processEnvVars(SupportedWorkloadEnvironmentVariables).assigned.join(", ");
2133
- logger$h.info(`Found the following environment variables: ${assignedEnv}`);
2285
+ logger$f.info(`Found the following environment variables: ${assignedEnv}`);
2134
2286
  const workloadIdentityCredentialOptions = options !== null && options !== void 0 ? options : {};
2135
2287
  const tenantId = workloadIdentityCredentialOptions.tenantId || process.env.AZURE_TENANT_ID;
2136
2288
  const clientId = workloadIdentityCredentialOptions.clientId || process.env.AZURE_CLIENT_ID;
2137
2289
  this.federatedTokenFilePath =
2138
2290
  workloadIdentityCredentialOptions.tokenFilePath || process.env.AZURE_FEDERATED_TOKEN_FILE;
2139
2291
  if (tenantId) {
2140
- checkTenantId(logger$h, tenantId);
2292
+ checkTenantId(logger$f, tenantId);
2141
2293
  }
2142
2294
  if (clientId && tenantId && this.federatedTokenFilePath) {
2143
- logger$h.info(`Invoking ClientAssertionCredential with tenant ID: ${tenantId}, clientId: ${workloadIdentityCredentialOptions.clientId} and federated token path: [REDACTED]`);
2295
+ logger$f.info(`Invoking ClientAssertionCredential with tenant ID: ${tenantId}, clientId: ${workloadIdentityCredentialOptions.clientId} and federated token path: [REDACTED]`);
2144
2296
  this.client = new ClientAssertionCredential(tenantId, clientId, this.readFileContents.bind(this), options);
2145
2297
  }
2146
2298
  }
@@ -2159,10 +2311,10 @@ class WorkloadIdentityCredential {
2159
2311
  "AZURE_TENANT_ID",
2160
2312
  "AZURE_CLIENT_ID",
2161
2313
  "AZURE_FEDERATED_TOKEN_FILE". See the troubleshooting guide for more information: https://aka.ms/azsdk/js/identity/workloadidentitycredential/troubleshoot `;
2162
- logger$h.info(errorMessage);
2314
+ logger$f.info(errorMessage);
2163
2315
  throw new CredentialUnavailableError(errorMessage);
2164
2316
  }
2165
- logger$h.info("Invoking getToken() of Client Assertion Credential");
2317
+ logger$f.info("Invoking getToken() of Client Assertion Credential");
2166
2318
  return this.client.getToken(scopes, options);
2167
2319
  }
2168
2320
  async readFileContents() {
@@ -2190,8 +2342,8 @@ class WorkloadIdentityCredential {
2190
2342
 
2191
2343
  // Copyright (c) Microsoft Corporation.
2192
2344
  // Licensed under the MIT license.
2193
- const msiName$2 = "ManagedIdentityCredential - Token Exchange";
2194
- const logger$g = credentialLogger(msiName$2);
2345
+ const msiName = "ManagedIdentityCredential - Token Exchange";
2346
+ const logger$e = credentialLogger(msiName);
2195
2347
  /**
2196
2348
  * Defines how to determine whether the token exchange MSI is available, and also how to retrieve a token from the token exchange MSI.
2197
2349
  */
@@ -2204,7 +2356,7 @@ function tokenExchangeMsi() {
2204
2356
  env.AZURE_TENANT_ID &&
2205
2357
  process.env.AZURE_FEDERATED_TOKEN_FILE);
2206
2358
  if (!result) {
2207
- logger$g.info(`${msiName$2}: Unavailable. The environment variables needed are: AZURE_CLIENT_ID (or the client ID sent through the parameters), AZURE_TENANT_ID and AZURE_FEDERATED_TOKEN_FILE`);
2359
+ logger$e.info(`${msiName}: Unavailable. The environment variables needed are: AZURE_CLIENT_ID (or the client ID sent through the parameters), AZURE_TENANT_ID and AZURE_FEDERATED_TOKEN_FILE`);
2208
2360
  }
2209
2361
  return result;
2210
2362
  },
@@ -2218,164 +2370,6 @@ function tokenExchangeMsi() {
2218
2370
  };
2219
2371
  }
2220
2372
 
2221
- // Copyright (c) Microsoft Corporation.
2222
- // Licensed under the MIT license.
2223
- // This MSI can be easily tested by deploying a container to Azure Service Fabric with the Dockerfile:
2224
- //
2225
- // FROM node:12
2226
- // RUN wget https://host.any/path/bash.sh
2227
- // CMD ["bash", "bash.sh"]
2228
- //
2229
- // Where the bash script contains:
2230
- //
2231
- // curl --insecure $IDENTITY_ENDPOINT'?api-version=2019-07-01-preview&resource=https://vault.azure.net/' -H "Secret: $IDENTITY_HEADER"
2232
- //
2233
- const msiName$1 = "ManagedIdentityCredential - Fabric MSI";
2234
- const logger$f = credentialLogger(msiName$1);
2235
- /**
2236
- * Generates the options used on the request for an access token.
2237
- */
2238
- function prepareRequestOptions$1(scopes, clientId, resourceId) {
2239
- const resource = mapScopesToResource(scopes);
2240
- if (!resource) {
2241
- throw new Error(`${msiName$1}: Multiple scopes are not supported.`);
2242
- }
2243
- const queryParameters = {
2244
- resource,
2245
- "api-version": azureFabricVersion,
2246
- };
2247
- if (clientId) {
2248
- queryParameters.client_id = clientId;
2249
- }
2250
- if (resourceId) {
2251
- queryParameters.msi_res_id = resourceId;
2252
- }
2253
- const query = new URLSearchParams(queryParameters);
2254
- // This error should not bubble up, since we verify that this environment variable is defined in the isAvailable() method defined below.
2255
- if (!process.env.IDENTITY_ENDPOINT) {
2256
- throw new Error("Missing environment variable: IDENTITY_ENDPOINT");
2257
- }
2258
- if (!process.env.IDENTITY_HEADER) {
2259
- throw new Error("Missing environment variable: IDENTITY_HEADER");
2260
- }
2261
- return {
2262
- url: `${process.env.IDENTITY_ENDPOINT}?${query.toString()}`,
2263
- method: "GET",
2264
- headers: coreRestPipeline.createHttpHeaders({
2265
- Accept: "application/json",
2266
- secret: process.env.IDENTITY_HEADER,
2267
- }),
2268
- };
2269
- }
2270
- /**
2271
- * Defines how to determine whether the Azure Service Fabric MSI is available, and also how to retrieve a token from the Azure Service Fabric MSI.
2272
- */
2273
- const fabricMsi = {
2274
- name: "fabricMsi",
2275
- async isAvailable({ scopes }) {
2276
- const resource = mapScopesToResource(scopes);
2277
- if (!resource) {
2278
- logger$f.info(`${msiName$1}: Unavailable. Multiple scopes are not supported.`);
2279
- return false;
2280
- }
2281
- const env = process.env;
2282
- const result = Boolean(env.IDENTITY_ENDPOINT && env.IDENTITY_HEADER && env.IDENTITY_SERVER_THUMBPRINT);
2283
- if (!result) {
2284
- logger$f.info(`${msiName$1}: Unavailable. The environment variables needed are: IDENTITY_ENDPOINT, IDENTITY_HEADER and IDENTITY_SERVER_THUMBPRINT`);
2285
- }
2286
- return result;
2287
- },
2288
- async getToken(configuration, getTokenOptions = {}) {
2289
- const { scopes, identityClient, clientId, resourceId } = configuration;
2290
- if (resourceId) {
2291
- logger$f.warning(`${msiName$1}: user defined managed Identity by resource Id is not supported. Argument resourceId might be ignored by the service.`);
2292
- }
2293
- logger$f.info([
2294
- `${msiName$1}:`,
2295
- "Using the endpoint and the secret coming from the environment variables:",
2296
- `IDENTITY_ENDPOINT=${process.env.IDENTITY_ENDPOINT},`,
2297
- "IDENTITY_HEADER=[REDACTED] and",
2298
- "IDENTITY_SERVER_THUMBPRINT=[REDACTED].",
2299
- ].join(" "));
2300
- const request = coreRestPipeline.createPipelineRequest(Object.assign({ abortSignal: getTokenOptions.abortSignal }, prepareRequestOptions$1(scopes, clientId, resourceId)));
2301
- request.agent = new https.Agent({
2302
- // This is necessary because Service Fabric provides a self-signed certificate.
2303
- // The alternative path is to verify the certificate using the IDENTITY_SERVER_THUMBPRINT env variable.
2304
- rejectUnauthorized: false,
2305
- });
2306
- const tokenResponse = await identityClient.sendTokenRequest(request);
2307
- return (tokenResponse && tokenResponse.accessToken) || null;
2308
- },
2309
- };
2310
-
2311
- // Copyright (c) Microsoft Corporation.
2312
- // Licensed under the MIT license.
2313
- const msiName = "ManagedIdentityCredential - AppServiceMSI 2019";
2314
- const logger$e = credentialLogger(msiName);
2315
- /**
2316
- * Generates the options used on the request for an access token.
2317
- */
2318
- function prepareRequestOptions(scopes, clientId, resourceId) {
2319
- const resource = mapScopesToResource(scopes);
2320
- if (!resource) {
2321
- throw new Error(`${msiName}: Multiple scopes are not supported.`);
2322
- }
2323
- const queryParameters = {
2324
- resource,
2325
- "api-version": "2019-08-01",
2326
- };
2327
- if (clientId) {
2328
- queryParameters.client_id = clientId;
2329
- }
2330
- if (resourceId) {
2331
- queryParameters.mi_res_id = resourceId;
2332
- }
2333
- const query = new URLSearchParams(queryParameters);
2334
- // This error should not bubble up, since we verify that this environment variable is defined in the isAvailable() method defined below.
2335
- if (!process.env.IDENTITY_ENDPOINT) {
2336
- throw new Error(`${msiName}: Missing environment variable: IDENTITY_ENDPOINT`);
2337
- }
2338
- if (!process.env.IDENTITY_HEADER) {
2339
- throw new Error(`${msiName}: Missing environment variable: IDENTITY_HEADER`);
2340
- }
2341
- return {
2342
- url: `${process.env.IDENTITY_ENDPOINT}?${query.toString()}`,
2343
- method: "GET",
2344
- headers: coreRestPipeline.createHttpHeaders({
2345
- Accept: "application/json",
2346
- "X-IDENTITY-HEADER": process.env.IDENTITY_HEADER,
2347
- }),
2348
- };
2349
- }
2350
- /**
2351
- * Defines how to determine whether the Azure App Service MSI is available, and also how to retrieve a token from the Azure App Service MSI.
2352
- */
2353
- const appServiceMsi2019 = {
2354
- name: "appServiceMsi2019",
2355
- async isAvailable({ scopes }) {
2356
- const resource = mapScopesToResource(scopes);
2357
- if (!resource) {
2358
- logger$e.info(`${msiName}: Unavailable. Multiple scopes are not supported.`);
2359
- return false;
2360
- }
2361
- const env = process.env;
2362
- const result = Boolean(env.IDENTITY_ENDPOINT && env.IDENTITY_HEADER);
2363
- if (!result) {
2364
- logger$e.info(`${msiName}: Unavailable. The environment variables needed are: IDENTITY_ENDPOINT and IDENTITY_HEADER.`);
2365
- }
2366
- return result;
2367
- },
2368
- async getToken(configuration, getTokenOptions = {}) {
2369
- const { identityClient, scopes, clientId, resourceId } = configuration;
2370
- logger$e.info(`${msiName}: Using the endpoint and the secret coming form the environment variables: IDENTITY_ENDPOINT=${process.env.IDENTITY_ENDPOINT} and IDENTITY_HEADER=[REDACTED].`);
2371
- const request = coreRestPipeline.createPipelineRequest(Object.assign(Object.assign({ abortSignal: getTokenOptions.abortSignal }, prepareRequestOptions(scopes, clientId, resourceId)), {
2372
- // Generally, MSI endpoints use the HTTP protocol, without transport layer security (TLS).
2373
- allowInsecureConnection: true }));
2374
- const tokenResponse = await identityClient.sendTokenRequest(request);
2375
- return (tokenResponse && tokenResponse.accessToken) || null;
2376
- },
2377
- };
2378
-
2379
2373
  // Copyright (c) Microsoft Corporation.
2380
2374
  // Licensed under the MIT license.
2381
2375
  const logger$d = credentialLogger("ManagedIdentityCredential");
@@ -2393,9 +2387,14 @@ class ManagedIdentityCredential {
2393
2387
  * @hidden
2394
2388
  */
2395
2389
  constructor(clientIdOrOptions, options) {
2396
- var _a;
2390
+ var _a, _b;
2397
2391
  this.isEndpointUnavailable = null;
2398
2392
  this.isAppTokenProviderInitialized = false;
2393
+ this.msiRetryConfig = {
2394
+ maxRetries: 3,
2395
+ startDelayInMs: 800,
2396
+ intervalIncrement: 2,
2397
+ };
2399
2398
  let _options;
2400
2399
  if (typeof clientIdOrOptions === "string") {
2401
2400
  this.clientId = clientIdOrOptions;
@@ -2410,6 +2409,9 @@ class ManagedIdentityCredential {
2410
2409
  if (this.clientId && this.resourceId) {
2411
2410
  throw new Error(`${ManagedIdentityCredential.name} - Client Id and Resource Id can't be provided at the same time.`);
2412
2411
  }
2412
+ if (((_a = _options === null || _options === void 0 ? void 0 : _options.retryOptions) === null || _a === void 0 ? void 0 : _a.maxRetries) !== undefined) {
2413
+ this.msiRetryConfig.maxRetries = _options.retryOptions.maxRetries;
2414
+ }
2413
2415
  this.identityClient = new IdentityClient(_options);
2414
2416
  this.isAvailableIdentityClient = new IdentityClient(Object.assign(Object.assign({}, _options), { retryOptions: {
2415
2417
  maxRetries: 0,
@@ -2420,7 +2422,7 @@ class ManagedIdentityCredential {
2420
2422
  this.confidentialApp = new msalCommon.ConfidentialClientApplication({
2421
2423
  auth: {
2422
2424
  authority: "https://login.microsoftonline.com/managed_identity",
2423
- clientId: (_a = this.clientId) !== null && _a !== void 0 ? _a : DeveloperSignOnClientId,
2425
+ clientId: (_b = this.clientId) !== null && _b !== void 0 ? _b : DeveloperSignOnClientId,
2424
2426
  clientSecret: "dummy-secret",
2425
2427
  cloudDiscoveryMetadata: '{"tenant_discovery_endpoint":"https://login.microsoftonline.com/common/v2.0/.well-known/openid-configuration","api-version":"1.1","metadata":[{"preferred_network":"login.microsoftonline.com","preferred_cache":"login.windows.net","aliases":["login.microsoftonline.com","login.windows.net","login.microsoft.com","sts.windows.net"]},{"preferred_network":"login.partner.microsoftonline.cn","preferred_cache":"login.partner.microsoftonline.cn","aliases":["login.partner.microsoftonline.cn","login.chinacloudapi.cn"]},{"preferred_network":"login.microsoftonline.de","preferred_cache":"login.microsoftonline.de","aliases":["login.microsoftonline.de"]},{"preferred_network":"login.microsoftonline.us","preferred_cache":"login.microsoftonline.us","aliases":["login.microsoftonline.us","login.usgovcloudapi.net"]},{"preferred_network":"login-us.microsoftonline.com","preferred_cache":"login-us.microsoftonline.com","aliases":["login-us.microsoftonline.com"]}]}',
2426
2428
  authorityMetadata: '{"token_endpoint":"https://login.microsoftonline.com/common/oauth2/v2.0/token","token_endpoint_auth_methods_supported":["client_secret_post","private_key_jwt","client_secret_basic"],"jwks_uri":"https://login.microsoftonline.com/common/discovery/v2.0/keys","response_modes_supported":["query","fragment","form_post"],"subject_types_supported":["pairwise"],"id_token_signing_alg_values_supported":["RS256"],"response_types_supported":["code","id_token","code id_token","id_token token"],"scopes_supported":["openid","profile","email","offline_access"],"issuer":"https://login.microsoftonline.com/{tenantid}/v2.0","request_uri_parameter_supported":false,"userinfo_endpoint":"https://graph.microsoft.com/oidc/userinfo","authorization_endpoint":"https://login.microsoftonline.com/common/oauth2/v2.0/authorize","device_authorization_endpoint":"https://login.microsoftonline.com/common/oauth2/v2.0/devicecode","http_logout_supported":true,"frontchannel_logout_supported":true,"end_session_endpoint":"https://login.microsoftonline.com/common/oauth2/v2.0/logout","claims_supported":["sub","iss","cloud_instance_name","cloud_instance_host_name","cloud_graph_host_name","msgraph_host","aud","exp","iat","auth_time","acr","nonce","preferred_username","name","tid","ver","at_hash","c_hash","email"],"kerberos_endpoint":"https://login.microsoftonline.com/common/kerberos","tenant_region_scope":null,"cloud_instance_name":"microsoftonline.com","cloud_graph_host_name":"graph.windows.net","msgraph_host":"graph.microsoft.com","rbac_url":"https://pas.windows.net"}',
@@ -2470,6 +2472,7 @@ class ManagedIdentityCredential {
2470
2472
  scopes,
2471
2473
  clientId: this.clientId,
2472
2474
  resourceId: this.resourceId,
2475
+ retryConfig: this.msiRetryConfig,
2473
2476
  }, updatedOptions);
2474
2477
  }
2475
2478
  catch (err) {
@@ -2576,10 +2579,10 @@ class ManagedIdentityCredential {
2576
2579
  if (err.statusCode === 400) {
2577
2580
  throw new CredentialUnavailableError(`${ManagedIdentityCredential.name}: The managed identity endpoint is indicating there's no available identity. Message: ${err.message}`);
2578
2581
  }
2579
- // This is a special case for Docker Desktop which responds with a 403 with a message that contains "A socket operation was attempted to an unreachable network"
2582
+ // This is a special case for Docker Desktop which responds with a 403 with a message that contains "A socket operation was attempted to an unreachable network" or "A socket operation was attempted to an unreachable host"
2580
2583
  // rather than just timing out, as expected.
2581
2584
  if (err.statusCode === 403 || err.code === 403) {
2582
- if (err.message.includes("A socket operation was attempted to an unreachable network")) {
2585
+ if (err.message.includes("unreachable")) {
2583
2586
  const error = new CredentialUnavailableError(`${ManagedIdentityCredential.name}: Unavailable. Network unreachable. Message: ${err.message}`);
2584
2587
  logger$d.getToken.info(formatError(scopes, error));
2585
2588
  throw error;
@@ -3762,13 +3765,17 @@ const logger$4 = credentialLogger("DefaultAzureCredential");
3762
3765
  *
3763
3766
  * @internal
3764
3767
  */
3765
- function createDefaultManagedIdentityCredential(options) {
3766
- var _a, _b, _c;
3767
- const managedIdentityClientId = (_a = options === null || options === void 0 ? void 0 : options.managedIdentityClientId) !== null && _a !== void 0 ? _a : process.env.AZURE_CLIENT_ID;
3768
- const workloadIdentityClientId = (_b = options === null || options === void 0 ? void 0 : options.workloadIdentityClientId) !== null && _b !== void 0 ? _b : managedIdentityClientId;
3768
+ function createDefaultManagedIdentityCredential(options = {}) {
3769
+ var _a, _b, _c, _d;
3770
+ (_a = options.retryOptions) !== null && _a !== void 0 ? _a : (options.retryOptions = {
3771
+ maxRetries: 5,
3772
+ retryDelayInMs: 800,
3773
+ });
3774
+ const managedIdentityClientId = (_b = options === null || options === void 0 ? void 0 : options.managedIdentityClientId) !== null && _b !== void 0 ? _b : process.env.AZURE_CLIENT_ID;
3775
+ const workloadIdentityClientId = (_c = options === null || options === void 0 ? void 0 : options.workloadIdentityClientId) !== null && _c !== void 0 ? _c : managedIdentityClientId;
3769
3776
  const managedResourceId = options === null || options === void 0 ? void 0 : options.managedIdentityResourceId;
3770
3777
  const workloadFile = process.env.AZURE_FEDERATED_TOKEN_FILE;
3771
- const tenantId = (_c = options === null || options === void 0 ? void 0 : options.tenantId) !== null && _c !== void 0 ? _c : process.env.AZURE_TENANT_ID;
3778
+ const tenantId = (_d = options === null || options === void 0 ? void 0 : options.tenantId) !== null && _d !== void 0 ? _d : process.env.AZURE_TENANT_ID;
3772
3779
  if (managedResourceId) {
3773
3780
  const managedIdentityResourceIdOptions = Object.assign(Object.assign({}, options), { resourceId: managedResourceId });
3774
3781
  return new ManagedIdentityCredential(managedIdentityResourceIdOptions);