@azure/identity 2.0.0-beta.3 → 2.0.0
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/CHANGELOG.md +232 -6
- package/README.md +124 -39
- package/dist/index.js +2317 -1596
- package/dist/index.js.map +1 -1
- package/dist-esm/src/client/identityClient.js +147 -133
- package/dist-esm/src/client/identityClient.js.map +1 -1
- package/dist-esm/src/constants.js +1 -1
- package/dist-esm/src/constants.js.map +1 -1
- package/dist-esm/src/credentials/authorizationCodeCredential.browser.js +1 -1
- package/dist-esm/src/credentials/authorizationCodeCredential.browser.js.map +1 -1
- package/dist-esm/src/credentials/authorizationCodeCredential.js +13 -76
- package/dist-esm/src/credentials/authorizationCodeCredential.js.map +1 -1
- package/dist-esm/src/credentials/azureApplicationCredential.browser.js +34 -0
- package/dist-esm/src/credentials/azureApplicationCredential.browser.js.map +1 -0
- package/dist-esm/src/credentials/azureApplicationCredential.js +36 -0
- package/dist-esm/src/credentials/azureApplicationCredential.js.map +1 -0
- package/dist-esm/src/credentials/azureCliCredential.browser.js +7 -0
- package/dist-esm/src/credentials/azureCliCredential.browser.js.map +1 -1
- package/dist-esm/src/credentials/azureCliCredential.js +110 -83
- package/dist-esm/src/credentials/azureCliCredential.js.map +1 -1
- package/dist-esm/src/credentials/azureCliCredentialOptions.js +4 -0
- package/dist-esm/src/credentials/azureCliCredentialOptions.js.map +1 -0
- package/dist-esm/src/credentials/azurePowerShellCredential.browser.js +3 -1
- package/dist-esm/src/credentials/azurePowerShellCredential.browser.js.map +1 -1
- package/dist-esm/src/credentials/azurePowerShellCredential.js +93 -83
- package/dist-esm/src/credentials/azurePowerShellCredential.js.map +1 -1
- package/dist-esm/src/credentials/azurePowerShellCredentialOptions.js +4 -0
- package/dist-esm/src/credentials/azurePowerShellCredentialOptions.js.map +1 -0
- package/dist-esm/src/credentials/chainedTokenCredential.js +34 -37
- package/dist-esm/src/credentials/chainedTokenCredential.js.map +1 -1
- package/dist-esm/src/credentials/clientCertificateCredential.browser.js +7 -0
- package/dist-esm/src/credentials/clientCertificateCredential.browser.js.map +1 -1
- package/dist-esm/src/credentials/clientCertificateCredential.js +24 -23
- package/dist-esm/src/credentials/clientCertificateCredential.js.map +1 -1
- package/dist-esm/src/credentials/clientCertificateCredentialOptions.js.map +1 -1
- package/dist-esm/src/credentials/clientSecretCredential.browser.js +39 -44
- package/dist-esm/src/credentials/clientSecretCredential.browser.js.map +1 -1
- package/dist-esm/src/credentials/clientSecretCredential.js +9 -11
- package/dist-esm/src/credentials/clientSecretCredential.js.map +1 -1
- package/dist-esm/src/credentials/clientSecretCredentialOptions.js.map +1 -1
- package/dist-esm/src/credentials/credentialPersistenceOptions.js +4 -0
- package/dist-esm/src/credentials/credentialPersistenceOptions.js.map +1 -0
- package/dist-esm/src/credentials/defaultAzureCredential.browser.js +1 -1
- package/dist-esm/src/credentials/defaultAzureCredential.browser.js.map +1 -1
- package/dist-esm/src/credentials/defaultAzureCredential.js +50 -27
- package/dist-esm/src/credentials/defaultAzureCredential.js.map +1 -1
- package/dist-esm/src/credentials/deviceCodeCredential.browser.js +7 -0
- package/dist-esm/src/credentials/deviceCodeCredential.browser.js.map +1 -1
- package/dist-esm/src/credentials/deviceCodeCredential.js +27 -22
- package/dist-esm/src/credentials/deviceCodeCredential.js.map +1 -1
- package/dist-esm/src/credentials/deviceCodeCredentialOptions.js.map +1 -1
- package/dist-esm/src/credentials/environmentCredential.browser.js +7 -0
- package/dist-esm/src/credentials/environmentCredential.browser.js.map +1 -1
- package/dist-esm/src/credentials/environmentCredential.js +39 -38
- package/dist-esm/src/credentials/environmentCredential.js.map +1 -1
- package/dist-esm/src/credentials/interactiveBrowserCredential.browser.js +20 -29
- package/dist-esm/src/credentials/interactiveBrowserCredential.browser.js.map +1 -1
- package/dist-esm/src/credentials/interactiveBrowserCredential.js +23 -29
- package/dist-esm/src/credentials/interactiveBrowserCredential.js.map +1 -1
- package/dist-esm/src/credentials/interactiveBrowserCredentialOptions.js.map +1 -1
- package/dist-esm/src/credentials/managedIdentityCredential/appServiceMsi2017.js +36 -22
- package/dist-esm/src/credentials/managedIdentityCredential/appServiceMsi2017.js.map +1 -1
- package/dist-esm/src/credentials/managedIdentityCredential/arcMsi.js +62 -47
- package/dist-esm/src/credentials/managedIdentityCredential/arcMsi.js.map +1 -1
- package/dist-esm/src/credentials/managedIdentityCredential/cloudShellMsi.js +33 -22
- package/dist-esm/src/credentials/managedIdentityCredential/cloudShellMsi.js.map +1 -1
- package/dist-esm/src/credentials/managedIdentityCredential/constants.js +2 -1
- package/dist-esm/src/credentials/managedIdentityCredential/constants.js.map +1 -1
- package/dist-esm/src/credentials/managedIdentityCredential/fabricMsi.js +42 -27
- package/dist-esm/src/credentials/managedIdentityCredential/fabricMsi.js.map +1 -1
- package/dist-esm/src/credentials/managedIdentityCredential/imdsMsi.js +115 -91
- package/dist-esm/src/credentials/managedIdentityCredential/imdsMsi.js.map +1 -1
- package/dist-esm/src/credentials/managedIdentityCredential/index.browser.js +3 -6
- package/dist-esm/src/credentials/managedIdentityCredential/index.browser.js.map +1 -1
- package/dist-esm/src/credentials/managedIdentityCredential/index.js +120 -125
- package/dist-esm/src/credentials/managedIdentityCredential/index.js.map +1 -1
- package/dist-esm/src/credentials/managedIdentityCredential/models.js.map +1 -1
- package/dist-esm/src/credentials/managedIdentityCredential/tokenExchangeMsi.js +82 -0
- package/dist-esm/src/credentials/managedIdentityCredential/tokenExchangeMsi.js.map +1 -0
- package/dist-esm/src/credentials/managedIdentityCredential/utils.js +14 -8
- package/dist-esm/src/credentials/managedIdentityCredential/utils.js.map +1 -1
- package/dist-esm/src/credentials/onBehalfOfCredential.browser.js +23 -0
- package/dist-esm/src/credentials/onBehalfOfCredential.browser.js.map +1 -0
- package/dist-esm/src/credentials/onBehalfOfCredential.js +57 -0
- package/dist-esm/src/credentials/onBehalfOfCredential.js.map +1 -0
- package/dist-esm/src/credentials/onBehalfOfCredentialOptions.js +4 -0
- package/dist-esm/src/credentials/onBehalfOfCredentialOptions.js.map +1 -0
- package/dist-esm/src/credentials/usernamePasswordCredential.browser.js +41 -46
- package/dist-esm/src/credentials/usernamePasswordCredential.browser.js.map +1 -1
- package/dist-esm/src/credentials/usernamePasswordCredential.js +9 -13
- package/dist-esm/src/credentials/usernamePasswordCredential.js.map +1 -1
- package/dist-esm/src/credentials/usernamePasswordCredentialOptions.js.map +1 -1
- package/dist-esm/src/credentials/visualStudioCodeCredential.browser.js +27 -0
- package/dist-esm/src/credentials/visualStudioCodeCredential.browser.js.map +1 -0
- package/dist-esm/src/credentials/visualStudioCodeCredential.js +183 -0
- package/dist-esm/src/credentials/visualStudioCodeCredential.js.map +1 -0
- package/dist-esm/src/credentials/visualStudioCodeCredentialPlugin.js +4 -0
- package/dist-esm/src/credentials/visualStudioCodeCredentialPlugin.js.map +1 -0
- package/dist-esm/src/{client/errors.js → errors.js} +16 -1
- package/dist-esm/src/errors.js.map +1 -0
- package/dist-esm/src/index.js +4 -2
- package/dist-esm/src/index.js.map +1 -1
- package/dist-esm/src/msal/browserFlows/browserCommon.js +33 -31
- package/dist-esm/src/msal/browserFlows/browserCommon.js.map +1 -1
- package/dist-esm/src/msal/browserFlows/msalAuthCode.js +113 -115
- package/dist-esm/src/msal/browserFlows/msalAuthCode.js.map +1 -1
- package/dist-esm/src/msal/credentials.js.map +1 -1
- package/dist-esm/src/msal/flows.js.map +1 -1
- package/dist-esm/src/msal/nodeFlows/msalAuthorizationCode.js +41 -0
- package/dist-esm/src/msal/nodeFlows/msalAuthorizationCode.js.map +1 -0
- package/dist-esm/src/msal/nodeFlows/msalClientCertificate.js +65 -46
- package/dist-esm/src/msal/nodeFlows/msalClientCertificate.js.map +1 -1
- package/dist-esm/src/msal/nodeFlows/msalClientSecret.js +15 -16
- package/dist-esm/src/msal/nodeFlows/msalClientSecret.js.map +1 -1
- package/dist-esm/src/msal/nodeFlows/msalDeviceCode.js +20 -22
- package/dist-esm/src/msal/nodeFlows/msalDeviceCode.js.map +1 -1
- package/dist-esm/src/msal/nodeFlows/msalOnBehalfOf.js +56 -0
- package/dist-esm/src/msal/nodeFlows/msalOnBehalfOf.js.map +1 -0
- package/dist-esm/src/msal/nodeFlows/msalOpenBrowser.js +44 -33
- package/dist-esm/src/msal/nodeFlows/msalOpenBrowser.js.map +1 -1
- package/dist-esm/src/msal/nodeFlows/msalUsernamePassword.js +15 -17
- package/dist-esm/src/msal/nodeFlows/msalUsernamePassword.js.map +1 -1
- package/dist-esm/src/msal/nodeFlows/nodeCommon.js +141 -98
- package/dist-esm/src/msal/nodeFlows/nodeCommon.js.map +1 -1
- package/dist-esm/src/msal/nodeFlows/tokenCachePersistenceOptions.js +4 -0
- package/dist-esm/src/msal/nodeFlows/tokenCachePersistenceOptions.js.map +1 -0
- package/dist-esm/src/msal/utils.js +23 -15
- package/dist-esm/src/msal/utils.js.map +1 -1
- package/dist-esm/src/plugins/consumer.browser.js +7 -0
- package/dist-esm/src/plugins/consumer.browser.js.map +1 -0
- package/dist-esm/src/plugins/consumer.js +44 -0
- package/dist-esm/src/plugins/consumer.js.map +1 -0
- package/dist-esm/src/plugins/provider.js +4 -0
- package/dist-esm/src/plugins/provider.js.map +1 -0
- package/dist-esm/src/regionalAuthority.js +115 -0
- package/dist-esm/src/regionalAuthority.js.map +1 -0
- package/dist-esm/src/util/tracing.js +24 -27
- package/dist-esm/src/util/tracing.js.map +1 -1
- package/dist-esm/src/util/validateMultiTenant.browser.js +22 -0
- package/dist-esm/src/util/validateMultiTenant.browser.js.map +1 -0
- package/dist-esm/src/util/validateMultiTenant.js +29 -0
- package/dist-esm/src/util/validateMultiTenant.js.map +1 -0
- package/package.json +44 -28
- package/types/identity.d.ts +482 -126
- package/dist-esm/src/client/errors.js.map +0 -1
- package/dist-esm/src/msal/errors.js +0 -22
- package/dist-esm/src/msal/errors.js.map +0 -1
- package/dist-esm/src/util/authHostEnv.js +0 -13
- package/dist-esm/src/util/authHostEnv.js.map +0 -1
|
@@ -1,44 +1,64 @@
|
|
|
1
1
|
// Copyright (c) Microsoft Corporation.
|
|
2
2
|
// Licensed under the MIT license.
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
3
|
+
import { delay } from "@azure/core-util";
|
|
4
|
+
import { createHttpHeaders, createPipelineRequest, RestError } from "@azure/core-rest-pipeline";
|
|
5
5
|
import { SpanStatusCode } from "@azure/core-tracing";
|
|
6
|
-
import { AuthenticationError } from "../../client/errors";
|
|
7
6
|
import { credentialLogger } from "../../util/logging";
|
|
8
7
|
import { createSpan } from "../../util/tracing";
|
|
9
|
-
import { imdsApiVersion,
|
|
10
|
-
import { msiGenericGetToken } from "./utils";
|
|
11
|
-
|
|
8
|
+
import { imdsApiVersion, imdsEndpointPath, imdsHost } from "./constants";
|
|
9
|
+
import { mapScopesToResource, msiGenericGetToken } from "./utils";
|
|
10
|
+
import { AuthenticationError } from "../../errors";
|
|
11
|
+
const msiName = "ManagedIdentityCredential - IMDS";
|
|
12
|
+
const logger = credentialLogger(msiName);
|
|
12
13
|
function expiresInParser(requestBody) {
|
|
13
14
|
if (requestBody.expires_on) {
|
|
14
15
|
// Use the expires_on timestamp if it's available
|
|
15
16
|
const expires = +requestBody.expires_on * 1000;
|
|
16
|
-
logger.info(
|
|
17
|
+
logger.info(`${msiName}: Using expires_on: ${expires} (original value: ${requestBody.expires_on})`);
|
|
17
18
|
return expires;
|
|
18
19
|
}
|
|
19
20
|
else {
|
|
20
21
|
// If these aren't possible, use expires_in and calculate a timestamp
|
|
21
22
|
const expires = Date.now() + requestBody.expires_in * 1000;
|
|
22
|
-
logger.info(
|
|
23
|
+
logger.info(`${msiName}: IMDS using expires_in: ${expires} (original value: ${requestBody.expires_in})`);
|
|
23
24
|
return expires;
|
|
24
25
|
}
|
|
25
26
|
}
|
|
26
|
-
function prepareRequestOptions(
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
27
|
+
function prepareRequestOptions(scopes, clientId, options) {
|
|
28
|
+
var _a;
|
|
29
|
+
const resource = mapScopesToResource(scopes);
|
|
30
|
+
if (!resource) {
|
|
31
|
+
throw new Error(`${msiName}: Multiple scopes are not supported.`);
|
|
32
|
+
}
|
|
33
|
+
const { skipQuery, skipMetadataHeader } = options || {};
|
|
34
|
+
let query = "";
|
|
35
|
+
// Pod Identity will try to process this request even if the Metadata header is missing.
|
|
36
|
+
// We can exclude the request query to ensure no IMDS endpoint tries to process the ping request.
|
|
37
|
+
if (!skipQuery) {
|
|
38
|
+
const queryParameters = {
|
|
39
|
+
resource,
|
|
40
|
+
"api-version": imdsApiVersion
|
|
41
|
+
};
|
|
42
|
+
if (clientId) {
|
|
43
|
+
queryParameters.client_id = clientId;
|
|
44
|
+
}
|
|
45
|
+
const params = new URLSearchParams(queryParameters);
|
|
46
|
+
query = `?${params.toString()}`;
|
|
47
|
+
}
|
|
48
|
+
const url = new URL(imdsEndpointPath, (_a = process.env.AZURE_POD_IDENTITY_AUTHORITY_HOST) !== null && _a !== void 0 ? _a : imdsHost);
|
|
49
|
+
const rawHeaders = {
|
|
50
|
+
Accept: "application/json",
|
|
51
|
+
Metadata: "true"
|
|
30
52
|
};
|
|
31
|
-
|
|
32
|
-
|
|
53
|
+
// Remove the Metadata header to invoke a request error from some IMDS endpoints.
|
|
54
|
+
if (skipMetadataHeader) {
|
|
55
|
+
delete rawHeaders.Metadata;
|
|
33
56
|
}
|
|
34
57
|
return {
|
|
35
|
-
|
|
58
|
+
// In this case, the `?` should be added in the "query" variable `skipQuery` is not set.
|
|
59
|
+
url: `${url}${query}`,
|
|
36
60
|
method: "GET",
|
|
37
|
-
|
|
38
|
-
headers: {
|
|
39
|
-
Accept: "application/json",
|
|
40
|
-
Metadata: true
|
|
41
|
-
}
|
|
61
|
+
headers: createHttpHeaders(rawHeaders)
|
|
42
62
|
};
|
|
43
63
|
}
|
|
44
64
|
// 800ms -> 1600ms -> 3200ms
|
|
@@ -48,84 +68,88 @@ export const imdsMsiRetryConfig = {
|
|
|
48
68
|
intervalIncrement: 2
|
|
49
69
|
};
|
|
50
70
|
export const imdsMsi = {
|
|
51
|
-
isAvailable(
|
|
52
|
-
var _a, _b
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
71
|
+
async isAvailable(scopes, identityClient, clientId, getTokenOptions) {
|
|
72
|
+
var _a, _b;
|
|
73
|
+
const resource = mapScopesToResource(scopes);
|
|
74
|
+
if (!resource) {
|
|
75
|
+
logger.info(`${msiName}: Unavailable. Multiple scopes are not supported.`);
|
|
76
|
+
return false;
|
|
77
|
+
}
|
|
78
|
+
const { span, updatedOptions: options } = createSpan("ManagedIdentityCredential-pingImdsEndpoint", getTokenOptions);
|
|
79
|
+
// if the PodIdenityEndpoint environment variable was set no need to probe the endpoint, it can be assumed to exist
|
|
80
|
+
if (process.env.AZURE_POD_IDENTITY_AUTHORITY_HOST) {
|
|
81
|
+
return true;
|
|
82
|
+
}
|
|
83
|
+
const requestOptions = prepareRequestOptions(resource, clientId, {
|
|
84
|
+
skipMetadataHeader: true,
|
|
85
|
+
skipQuery: true
|
|
86
|
+
});
|
|
87
|
+
requestOptions.tracingOptions = options.tracingOptions;
|
|
88
|
+
try {
|
|
89
|
+
// Create a request with a timeout since we expect that
|
|
90
|
+
// not having a "Metadata" header should cause an error to be
|
|
91
|
+
// returned quickly from the endpoint, proving its availability.
|
|
92
|
+
const request = createPipelineRequest(requestOptions);
|
|
93
|
+
request.timeout = (_b = (_a = options.requestOptions) === null || _a === void 0 ? void 0 : _a.timeout) !== null && _b !== void 0 ? _b : 300;
|
|
94
|
+
// This MSI uses the imdsEndpoint to get the token, which only uses http://
|
|
95
|
+
request.allowInsecureConnection = true;
|
|
64
96
|
try {
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
// returned quickly from the endpoint, proving its availability.
|
|
68
|
-
const webResource = identityClient.createWebResource(request);
|
|
69
|
-
webResource.timeout = ((_c = updatedOptions === null || updatedOptions === void 0 ? void 0 : updatedOptions.requestOptions) === null || _c === void 0 ? void 0 : _c.timeout) || 500;
|
|
70
|
-
try {
|
|
71
|
-
logger.info(`Pinging IMDS endpoint`);
|
|
72
|
-
yield identityClient.sendRequest(webResource);
|
|
73
|
-
}
|
|
74
|
-
catch (err) {
|
|
75
|
-
if ((err.name === "RestError" && err.code === RestError.REQUEST_SEND_ERROR) ||
|
|
76
|
-
err.name === "AbortError" ||
|
|
77
|
-
err.code === "ECONNREFUSED" || // connection refused
|
|
78
|
-
err.code === "EHOSTDOWN" // host is down
|
|
79
|
-
) {
|
|
80
|
-
// If the request failed, or NodeJS was unable to establish a connection,
|
|
81
|
-
// or the host was down, we'll assume the IMDS endpoint isn't available.
|
|
82
|
-
logger.info(`The Azure IMDS endpoint is unavailable`);
|
|
83
|
-
span.setStatus({
|
|
84
|
-
code: SpanStatusCode.ERROR,
|
|
85
|
-
message: err.message
|
|
86
|
-
});
|
|
87
|
-
return false;
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
// If we received any response, the endpoint is available
|
|
91
|
-
logger.info(`The Azure IMDS endpoint is available`);
|
|
92
|
-
// IMDS MSI available!
|
|
93
|
-
return true;
|
|
97
|
+
logger.info(`${msiName}: Pinging the Azure IMDS endpoint`);
|
|
98
|
+
await identityClient.sendRequest(request);
|
|
94
99
|
}
|
|
95
100
|
catch (err) {
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
code
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
101
|
+
if ((err.name === "RestError" && err.code === RestError.REQUEST_SEND_ERROR) ||
|
|
102
|
+
err.name === "AbortError" ||
|
|
103
|
+
err.code === "ENETUNREACH" || // Network unreachable
|
|
104
|
+
err.code === "ECONNREFUSED" || // connection refused
|
|
105
|
+
err.code === "EHOSTDOWN" // host is down
|
|
106
|
+
) {
|
|
107
|
+
// If the request failed, or Node.js was unable to establish a connection,
|
|
108
|
+
// or the host was down, we'll assume the IMDS endpoint isn't available.
|
|
109
|
+
logger.info(`${msiName}: The Azure IMDS endpoint is unavailable`);
|
|
110
|
+
span.setStatus({
|
|
111
|
+
code: SpanStatusCode.ERROR,
|
|
112
|
+
message: err.message
|
|
113
|
+
});
|
|
114
|
+
return false;
|
|
115
|
+
}
|
|
107
116
|
}
|
|
108
|
-
|
|
117
|
+
// If we received any response, the endpoint is available
|
|
118
|
+
logger.info(`${msiName}: The Azure IMDS endpoint is available`);
|
|
119
|
+
return true;
|
|
120
|
+
}
|
|
121
|
+
catch (err) {
|
|
122
|
+
// createWebResource failed.
|
|
123
|
+
// This error should bubble up to the user.
|
|
124
|
+
logger.info(`${msiName}: Error when creating the WebResource for the Azure IMDS endpoint: ${err.message}`);
|
|
125
|
+
span.setStatus({
|
|
126
|
+
code: SpanStatusCode.ERROR,
|
|
127
|
+
message: err.message
|
|
128
|
+
});
|
|
129
|
+
throw err;
|
|
130
|
+
}
|
|
131
|
+
finally {
|
|
132
|
+
span.end();
|
|
133
|
+
}
|
|
109
134
|
},
|
|
110
|
-
getToken(
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
}
|
|
124
|
-
throw error;
|
|
135
|
+
async getToken(configuration, getTokenOptions = {}) {
|
|
136
|
+
const { identityClient, scopes, clientId } = configuration;
|
|
137
|
+
logger.info(`${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.`);
|
|
138
|
+
let nextDelayInMs = imdsMsiRetryConfig.startDelayInMs;
|
|
139
|
+
for (let retries = 0; retries < imdsMsiRetryConfig.maxRetries; retries++) {
|
|
140
|
+
try {
|
|
141
|
+
return await msiGenericGetToken(identityClient, prepareRequestOptions(scopes, clientId), expiresInParser, getTokenOptions);
|
|
142
|
+
}
|
|
143
|
+
catch (error) {
|
|
144
|
+
if (error.statusCode === 404) {
|
|
145
|
+
await delay(nextDelayInMs);
|
|
146
|
+
nextDelayInMs *= imdsMsiRetryConfig.intervalIncrement;
|
|
147
|
+
continue;
|
|
125
148
|
}
|
|
149
|
+
throw error;
|
|
126
150
|
}
|
|
127
|
-
|
|
128
|
-
});
|
|
151
|
+
}
|
|
152
|
+
throw new AuthenticationError(404, `${msiName}: Failed to retrieve IMDS token after ${imdsMsiRetryConfig.maxRetries} retries.`);
|
|
129
153
|
}
|
|
130
154
|
};
|
|
131
155
|
//# sourceMappingURL=imdsMsi.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"imdsMsi.js","sourceRoot":"","sources":["../../../../src/credentials/managedIdentityCredential/imdsMsi.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\nimport {\n AccessToken,\n delay,\n GetTokenOptions,\n RequestPrepareOptions,\n RestError\n} from \"@azure/core-http\";\nimport { SpanStatusCode } from \"@azure/core-tracing\";\nimport { AuthenticationError } from \"../../client/errors\";\nimport { IdentityClient } from \"../../client/identityClient\";\nimport { credentialLogger } from \"../../util/logging\";\nimport { createSpan } from \"../../util/tracing\";\nimport { imdsApiVersion, imdsEndpoint } from \"./constants\";\nimport { MSI } from \"./models\";\nimport { msiGenericGetToken } from \"./utils\";\n\nconst logger = credentialLogger(\"ManagedIdentityCredential - IMDS\");\n\nfunction expiresInParser(requestBody: any): number {\n if (requestBody.expires_on) {\n // Use the expires_on timestamp if it's available\n const expires = +requestBody.expires_on * 1000;\n logger.info(`IMDS using expires_on: ${expires} (original value: ${requestBody.expires_on})`);\n return expires;\n } else {\n // If these aren't possible, use expires_in and calculate a timestamp\n const expires = Date.now() + requestBody.expires_in * 1000;\n logger.info(`IMDS using expires_in: ${expires} (original value: ${requestBody.expires_in})`);\n return expires;\n }\n}\n\nfunction prepareRequestOptions(resource?: string, clientId?: string): RequestPrepareOptions {\n const queryParameters: any = {\n resource,\n \"api-version\": imdsApiVersion\n };\n\n if (clientId) {\n queryParameters.client_id = clientId;\n }\n\n return {\n url: imdsEndpoint,\n method: \"GET\",\n queryParameters,\n headers: {\n Accept: \"application/json\",\n Metadata: true\n }\n };\n}\n\n// 800ms -> 1600ms -> 3200ms\nexport const imdsMsiRetryConfig = {\n maxRetries: 3,\n startDelayInMs: 800,\n intervalIncrement: 2\n};\n\nexport const imdsMsi: MSI = {\n async isAvailable(\n identityClient: IdentityClient,\n resource: string,\n clientId?: string,\n getTokenOptions?: GetTokenOptions\n ): Promise<boolean> {\n const { span, updatedOptions } = createSpan(\n \"ManagedIdentityCredential-pingImdsEndpoint\",\n getTokenOptions\n );\n\n const request = prepareRequestOptions(resource, clientId);\n\n // This will always be populated, but let's make TypeScript happy\n if (request.headers) {\n // Remove the Metadata header to invoke a request error from\n // IMDS endpoint\n delete request.headers.Metadata;\n }\n\n request.spanOptions = updatedOptions?.tracingOptions?.spanOptions;\n request.tracingContext = updatedOptions?.tracingOptions?.tracingContext;\n\n try {\n // Create a request with a timeout since we expect that\n // not having a \"Metadata\" header should cause an error to be\n // returned quickly from the endpoint, proving its availability.\n const webResource = identityClient.createWebResource(request);\n webResource.timeout = updatedOptions?.requestOptions?.timeout || 500;\n\n try {\n logger.info(`Pinging IMDS endpoint`);\n await identityClient.sendRequest(webResource);\n } catch (err) {\n if (\n (err.name === \"RestError\" && err.code === RestError.REQUEST_SEND_ERROR) ||\n err.name === \"AbortError\" ||\n err.code === \"ECONNREFUSED\" || // connection refused\n err.code === \"EHOSTDOWN\" // host is down\n ) {\n // If the request failed, or NodeJS was unable to establish a connection,\n // or the host was down, we'll assume the IMDS endpoint isn't available.\n logger.info(`The Azure IMDS endpoint is unavailable`);\n span.setStatus({\n code: SpanStatusCode.ERROR,\n message: err.message\n });\n return false;\n }\n }\n\n // If we received any response, the endpoint is available\n logger.info(`The Azure IMDS endpoint is available`);\n\n // IMDS MSI available!\n return true;\n } catch (err) {\n // createWebResource failed.\n // This error should bubble up to the user.\n logger.info(`Error when creating the WebResource for the IMDS endpoint: ${err.message}`);\n span.setStatus({\n code: SpanStatusCode.ERROR,\n message: err.message\n });\n throw err;\n } finally {\n span.end();\n }\n },\n async getToken(\n identityClient: IdentityClient,\n resource: string,\n clientId?: string,\n getTokenOptions: GetTokenOptions = {}\n ): Promise<AccessToken | null> {\n logger.info(\n `Using the IMDS endpoint coming form the environment variable MSI_ENDPOINT=${process.env.MSI_ENDPOINT}, and using the cloud shell to proceed with the authentication.`\n );\n\n let nextDelayInMs = imdsMsiRetryConfig.startDelayInMs;\n for (let retries = 0; retries < imdsMsiRetryConfig.maxRetries; retries++) {\n try {\n return await msiGenericGetToken(\n identityClient,\n prepareRequestOptions(resource, clientId),\n expiresInParser,\n getTokenOptions\n );\n } catch (error) {\n if (error.statusCode === 404) {\n await delay(nextDelayInMs);\n nextDelayInMs *= imdsMsiRetryConfig.intervalIncrement;\n continue;\n }\n throw error;\n }\n }\n\n throw new AuthenticationError(\n 404,\n `Failed to retrieve IMDS token after ${imdsMsiRetryConfig.maxRetries} retries.`\n );\n }\n};\n"]}
|
|
1
|
+
{"version":3,"file":"imdsMsi.js","sourceRoot":"","sources":["../../../../src/credentials/managedIdentityCredential/imdsMsi.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\nimport { delay } from \"@azure/core-util\";\nimport { AccessToken, GetTokenOptions } from \"@azure/core-auth\";\nimport {\n createHttpHeaders,\n PipelineRequestOptions,\n createPipelineRequest,\n RestError\n} from \"@azure/core-rest-pipeline\";\nimport { SpanStatusCode } from \"@azure/core-tracing\";\nimport { IdentityClient } from \"../../client/identityClient\";\nimport { credentialLogger } from \"../../util/logging\";\nimport { createSpan } from \"../../util/tracing\";\nimport { imdsApiVersion, imdsEndpointPath, imdsHost } from \"./constants\";\nimport { MSI, MSIConfiguration } from \"./models\";\nimport { mapScopesToResource, msiGenericGetToken } from \"./utils\";\nimport { AuthenticationError } from \"../../errors\";\n\nconst msiName = \"ManagedIdentityCredential - IMDS\";\nconst logger = credentialLogger(msiName);\n\nfunction expiresInParser(requestBody: any): number {\n if (requestBody.expires_on) {\n // Use the expires_on timestamp if it's available\n const expires = +requestBody.expires_on * 1000;\n logger.info(\n `${msiName}: Using expires_on: ${expires} (original value: ${requestBody.expires_on})`\n );\n return expires;\n } else {\n // If these aren't possible, use expires_in and calculate a timestamp\n const expires = Date.now() + requestBody.expires_in * 1000;\n logger.info(\n `${msiName}: IMDS using expires_in: ${expires} (original value: ${requestBody.expires_in})`\n );\n return expires;\n }\n}\n\nfunction prepareRequestOptions(\n scopes: string | string[],\n clientId?: string,\n options?: {\n skipQuery?: boolean;\n skipMetadataHeader?: boolean;\n }\n): PipelineRequestOptions {\n const resource = mapScopesToResource(scopes);\n if (!resource) {\n throw new Error(`${msiName}: Multiple scopes are not supported.`);\n }\n\n const { skipQuery, skipMetadataHeader } = options || {};\n let query = \"\";\n\n // Pod Identity will try to process this request even if the Metadata header is missing.\n // We can exclude the request query to ensure no IMDS endpoint tries to process the ping request.\n if (!skipQuery) {\n const queryParameters: any = {\n resource,\n \"api-version\": imdsApiVersion\n };\n if (clientId) {\n queryParameters.client_id = clientId;\n }\n const params = new URLSearchParams(queryParameters);\n query = `?${params.toString()}`;\n }\n\n const url = new URL(imdsEndpointPath, process.env.AZURE_POD_IDENTITY_AUTHORITY_HOST ?? imdsHost);\n\n const rawHeaders: Record<string, string> = {\n Accept: \"application/json\",\n Metadata: \"true\"\n };\n\n // Remove the Metadata header to invoke a request error from some IMDS endpoints.\n if (skipMetadataHeader) {\n delete rawHeaders.Metadata;\n }\n\n return {\n // In this case, the `?` should be added in the \"query\" variable `skipQuery` is not set.\n url: `${url}${query}`,\n method: \"GET\",\n headers: createHttpHeaders(rawHeaders)\n };\n}\n\n// 800ms -> 1600ms -> 3200ms\nexport const imdsMsiRetryConfig = {\n maxRetries: 3,\n startDelayInMs: 800,\n intervalIncrement: 2\n};\n\nexport const imdsMsi: MSI = {\n async isAvailable(\n scopes: string | string[],\n identityClient: IdentityClient,\n clientId?: string,\n getTokenOptions?: GetTokenOptions\n ): Promise<boolean> {\n const resource = mapScopesToResource(scopes);\n if (!resource) {\n logger.info(`${msiName}: Unavailable. Multiple scopes are not supported.`);\n return false;\n }\n const { span, updatedOptions: options } = createSpan(\n \"ManagedIdentityCredential-pingImdsEndpoint\",\n getTokenOptions\n );\n\n // if the PodIdenityEndpoint environment variable was set no need to probe the endpoint, it can be assumed to exist\n if (process.env.AZURE_POD_IDENTITY_AUTHORITY_HOST) {\n return true;\n }\n\n const requestOptions = prepareRequestOptions(resource, clientId, {\n skipMetadataHeader: true,\n skipQuery: true\n });\n requestOptions.tracingOptions = options.tracingOptions;\n\n try {\n // Create a request with a timeout since we expect that\n // not having a \"Metadata\" header should cause an error to be\n // returned quickly from the endpoint, proving its availability.\n const request = createPipelineRequest(requestOptions);\n\n request.timeout = options.requestOptions?.timeout ?? 300;\n\n // This MSI uses the imdsEndpoint to get the token, which only uses http://\n request.allowInsecureConnection = true;\n\n try {\n logger.info(`${msiName}: Pinging the Azure IMDS endpoint`);\n await identityClient.sendRequest(request);\n } catch (err) {\n if (\n (err.name === \"RestError\" && err.code === RestError.REQUEST_SEND_ERROR) ||\n err.name === \"AbortError\" ||\n err.code === \"ENETUNREACH\" || // Network unreachable\n err.code === \"ECONNREFUSED\" || // connection refused\n err.code === \"EHOSTDOWN\" // host is down\n ) {\n // If the request failed, or Node.js was unable to establish a connection,\n // or the host was down, we'll assume the IMDS endpoint isn't available.\n logger.info(`${msiName}: The Azure IMDS endpoint is unavailable`);\n span.setStatus({\n code: SpanStatusCode.ERROR,\n message: err.message\n });\n return false;\n }\n }\n\n // If we received any response, the endpoint is available\n logger.info(`${msiName}: The Azure IMDS endpoint is available`);\n return true;\n } catch (err) {\n // createWebResource failed.\n // This error should bubble up to the user.\n logger.info(\n `${msiName}: Error when creating the WebResource for the Azure IMDS endpoint: ${err.message}`\n );\n span.setStatus({\n code: SpanStatusCode.ERROR,\n message: err.message\n });\n throw err;\n } finally {\n span.end();\n }\n },\n async getToken(\n configuration: MSIConfiguration,\n getTokenOptions: GetTokenOptions = {}\n ): Promise<AccessToken | null> {\n const { identityClient, scopes, clientId } = configuration;\n\n logger.info(\n `${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.`\n );\n\n let nextDelayInMs = imdsMsiRetryConfig.startDelayInMs;\n for (let retries = 0; retries < imdsMsiRetryConfig.maxRetries; retries++) {\n try {\n return await msiGenericGetToken(\n identityClient,\n prepareRequestOptions(scopes, clientId),\n expiresInParser,\n getTokenOptions\n );\n } catch (error) {\n if (error.statusCode === 404) {\n await delay(nextDelayInMs);\n nextDelayInMs *= imdsMsiRetryConfig.intervalIncrement;\n continue;\n }\n throw error;\n }\n }\n\n throw new AuthenticationError(\n 404,\n `${msiName}: Failed to retrieve IMDS token after ${imdsMsiRetryConfig.maxRetries} retries.`\n );\n }\n};\n"]}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
// Copyright (c) Microsoft Corporation.
|
|
2
2
|
// Licensed under the MIT license.
|
|
3
|
-
import { __awaiter } from "tslib";
|
|
4
3
|
import { credentialLogger, formatError } from "../../util/logging";
|
|
5
4
|
const BrowserNotSupportedError = new Error("ManagedIdentityCredential is not supported in the browser.");
|
|
6
5
|
const logger = credentialLogger("ManagedIdentityCredential");
|
|
@@ -9,11 +8,9 @@ export class ManagedIdentityCredential {
|
|
|
9
8
|
logger.info(formatError("", BrowserNotSupportedError));
|
|
10
9
|
throw BrowserNotSupportedError;
|
|
11
10
|
}
|
|
12
|
-
getToken() {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
throw BrowserNotSupportedError;
|
|
16
|
-
});
|
|
11
|
+
async getToken() {
|
|
12
|
+
logger.getToken.info(formatError("", BrowserNotSupportedError));
|
|
13
|
+
throw BrowserNotSupportedError;
|
|
17
14
|
}
|
|
18
15
|
}
|
|
19
16
|
//# sourceMappingURL=index.browser.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.browser.js","sourceRoot":"","sources":["../../../../src/credentials/managedIdentityCredential/index.browser.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,kCAAkC
|
|
1
|
+
{"version":3,"file":"index.browser.js","sourceRoot":"","sources":["../../../../src/credentials/managedIdentityCredential/index.browser.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,kCAAkC;AAKlC,OAAO,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAEnE,MAAM,wBAAwB,GAAG,IAAI,KAAK,CACxC,4DAA4D,CAC7D,CAAC;AACF,MAAM,MAAM,GAAG,gBAAgB,CAAC,2BAA2B,CAAC,CAAC;AAE7D,MAAM,OAAO,yBAAyB;IAGpC;QACE,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE,EAAE,wBAAwB,CAAC,CAAC,CAAC;QACvD,MAAM,wBAAwB,CAAC;IACjC,CAAC;IAEM,KAAK,CAAC,QAAQ;QACnB,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE,EAAE,wBAAwB,CAAC,CAAC,CAAC;QAChE,MAAM,wBAAwB,CAAC;IACjC,CAAC;CACF","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\nimport { AccessToken, TokenCredential } from \"@azure/core-auth\";\n\nimport { TokenCredentialOptions } from \"../../client/identityClient\";\nimport { credentialLogger, formatError } from \"../../util/logging\";\n\nconst BrowserNotSupportedError = new Error(\n \"ManagedIdentityCredential is not supported in the browser.\"\n);\nconst logger = credentialLogger(\"ManagedIdentityCredential\");\n\nexport class ManagedIdentityCredential implements TokenCredential {\n constructor(clientId: string, options?: TokenCredentialOptions);\n constructor(options?: TokenCredentialOptions);\n constructor() {\n logger.info(formatError(\"\", BrowserNotSupportedError));\n throw BrowserNotSupportedError;\n }\n\n public async getToken(): Promise<AccessToken | null> {\n logger.getToken.info(formatError(\"\", BrowserNotSupportedError));\n throw BrowserNotSupportedError;\n }\n}\n"]}
|
|
@@ -1,16 +1,15 @@
|
|
|
1
1
|
// Copyright (c) Microsoft Corporation.
|
|
2
2
|
// Licensed under the MIT license.
|
|
3
|
-
import { __awaiter } from "tslib";
|
|
4
|
-
import { IdentityClient } from "../../client/identityClient";
|
|
5
|
-
import { createSpan } from "../../util/tracing";
|
|
6
|
-
import { AuthenticationError, CredentialUnavailableError } from "../../client/errors";
|
|
7
3
|
import { SpanStatusCode } from "@azure/core-tracing";
|
|
4
|
+
import { IdentityClient } from "../../client/identityClient";
|
|
5
|
+
import { AuthenticationError, CredentialUnavailableError } from "../../errors";
|
|
8
6
|
import { credentialLogger, formatSuccess, formatError } from "../../util/logging";
|
|
9
|
-
import {
|
|
7
|
+
import { appServiceMsi2017 } from "./appServiceMsi2017";
|
|
8
|
+
import { createSpan } from "../../util/tracing";
|
|
10
9
|
import { cloudShellMsi } from "./cloudShellMsi";
|
|
11
10
|
import { imdsMsi } from "./imdsMsi";
|
|
12
|
-
import { appServiceMsi2017 } from "./appServiceMsi2017";
|
|
13
11
|
import { arcMsi } from "./arcMsi";
|
|
12
|
+
import { tokenExchangeMsi } from "./tokenExchangeMsi";
|
|
14
13
|
const logger = credentialLogger("ManagedIdentityCredential");
|
|
15
14
|
/**
|
|
16
15
|
* Attempts authentication using a managed identity that has been assigned
|
|
@@ -38,140 +37,136 @@ export class ManagedIdentityCredential {
|
|
|
38
37
|
this.identityClient = new IdentityClient(clientIdOrOptions);
|
|
39
38
|
}
|
|
40
39
|
}
|
|
41
|
-
cachedAvailableMSI(
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
return msi;
|
|
53
|
-
}
|
|
40
|
+
async cachedAvailableMSI(scopes, clientId, getTokenOptions) {
|
|
41
|
+
if (this.cachedMSI) {
|
|
42
|
+
return this.cachedMSI;
|
|
43
|
+
}
|
|
44
|
+
// "fabricMsi" can't be added yet because our HTTPs pipeline doesn't allow skipping the SSL verification step,
|
|
45
|
+
// which is necessary since Service Fabric only provides self-signed certificates on their Identity Endpoint.
|
|
46
|
+
const MSIs = [appServiceMsi2017, cloudShellMsi, arcMsi, tokenExchangeMsi(), imdsMsi];
|
|
47
|
+
for (const msi of MSIs) {
|
|
48
|
+
if (await msi.isAvailable(scopes, this.identityClient, clientId, getTokenOptions)) {
|
|
49
|
+
this.cachedMSI = msi;
|
|
50
|
+
return msi;
|
|
54
51
|
}
|
|
55
|
-
|
|
56
|
-
|
|
52
|
+
}
|
|
53
|
+
throw new CredentialUnavailableError("ManagedIdentityCredential - No MSI credential available");
|
|
57
54
|
}
|
|
58
|
-
authenticateManagedIdentity(scopes, clientId, getTokenOptions) {
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
55
|
+
async authenticateManagedIdentity(scopes, clientId, getTokenOptions) {
|
|
56
|
+
const { span, updatedOptions } = createSpan("ManagedIdentityCredential-authenticateManagedIdentity", getTokenOptions);
|
|
57
|
+
try {
|
|
58
|
+
// Determining the available MSI, and avoiding checking for other MSIs while the program is running.
|
|
59
|
+
const availableMSI = await this.cachedAvailableMSI(scopes, clientId, updatedOptions);
|
|
60
|
+
return availableMSI.getToken({
|
|
61
|
+
identityClient: this.identityClient,
|
|
62
|
+
scopes,
|
|
63
|
+
clientId
|
|
64
|
+
}, updatedOptions);
|
|
65
|
+
}
|
|
66
|
+
catch (err) {
|
|
67
|
+
span.setStatus({
|
|
68
|
+
code: SpanStatusCode.ERROR,
|
|
69
|
+
message: err.message
|
|
70
|
+
});
|
|
71
|
+
throw err;
|
|
72
|
+
}
|
|
73
|
+
finally {
|
|
74
|
+
span.end();
|
|
75
|
+
}
|
|
78
76
|
}
|
|
79
77
|
/**
|
|
80
|
-
* Authenticates with Azure Active Directory and returns an access token if
|
|
81
|
-
*
|
|
82
|
-
*
|
|
83
|
-
* containing failure details will be thrown.
|
|
78
|
+
* Authenticates with Azure Active Directory and returns an access token if successful.
|
|
79
|
+
* If authentication fails, a {@link CredentialUnavailableError} will be thrown with the details of the failure.
|
|
80
|
+
* If an unexpected error occurs, an {@link AuthenticationError} will be thrown with the details of the failure.
|
|
84
81
|
*
|
|
85
82
|
* @param scopes - The list of scopes for which the token will have access.
|
|
86
83
|
* @param options - The options used to configure any requests this
|
|
87
84
|
* TokenCredential implementation might make.
|
|
88
85
|
*/
|
|
89
|
-
getToken(scopes, options) {
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
const error = new CredentialUnavailableError("The managed identity endpoint was reached, yet no tokens were received.");
|
|
107
|
-
logger.getToken.info(formatError(scopes, error));
|
|
108
|
-
throw error;
|
|
109
|
-
}
|
|
110
|
-
// Since `authenticateManagedIdentity` didn't throw, and the result was not null,
|
|
111
|
-
// We will assume that this endpoint is reachable from this point forward,
|
|
112
|
-
// and avoid pinging again to it.
|
|
113
|
-
this.isEndpointUnavailable = false;
|
|
114
|
-
}
|
|
115
|
-
else {
|
|
116
|
-
// We've previously determined that the endpoint was unavailable,
|
|
117
|
-
// either because it was unreachable or permanently unable to authenticate.
|
|
118
|
-
const error = new CredentialUnavailableError("The managed identity endpoint is not currently available");
|
|
86
|
+
async getToken(scopes, options) {
|
|
87
|
+
let result = null;
|
|
88
|
+
const { span, updatedOptions } = createSpan("ManagedIdentityCredential.getToken", options);
|
|
89
|
+
try {
|
|
90
|
+
// isEndpointAvailable can be true, false, or null,
|
|
91
|
+
// If it's null, it means we don't yet know whether
|
|
92
|
+
// the endpoint is available and need to check for it.
|
|
93
|
+
if (this.isEndpointUnavailable !== true) {
|
|
94
|
+
result = await this.authenticateManagedIdentity(scopes, this.clientId, updatedOptions);
|
|
95
|
+
if (result === null) {
|
|
96
|
+
// If authenticateManagedIdentity returns null,
|
|
97
|
+
// it means no MSI endpoints are available.
|
|
98
|
+
// If so, we avoid trying to reach to them in future requests.
|
|
99
|
+
this.isEndpointUnavailable = true;
|
|
100
|
+
// It also means that the endpoint answered with either 200 or 201 (see the sendTokenRequest method),
|
|
101
|
+
// yet we had no access token. For this reason, we'll throw once with a specific message:
|
|
102
|
+
const error = new CredentialUnavailableError("The managed identity endpoint was reached, yet no tokens were received.");
|
|
119
103
|
logger.getToken.info(formatError(scopes, error));
|
|
120
104
|
throw error;
|
|
121
105
|
}
|
|
122
|
-
|
|
123
|
-
|
|
106
|
+
// Since `authenticateManagedIdentity` didn't throw, and the result was not null,
|
|
107
|
+
// We will assume that this endpoint is reachable from this point forward,
|
|
108
|
+
// and avoid pinging again to it.
|
|
109
|
+
this.isEndpointUnavailable = false;
|
|
124
110
|
}
|
|
125
|
-
|
|
126
|
-
//
|
|
127
|
-
//
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
// Expected errors to reach this point:
|
|
132
|
-
// - Errors coming from a method unexpectedly breaking.
|
|
133
|
-
// - When identityClient.sendTokenRequest throws, in which case
|
|
134
|
-
// if the status code was 400, it means that the endpoint is working,
|
|
135
|
-
// but no identity is available.
|
|
136
|
-
span.setStatus({
|
|
137
|
-
code: SpanStatusCode.ERROR,
|
|
138
|
-
message: err.message
|
|
139
|
-
});
|
|
140
|
-
// If either the network is unreachable,
|
|
141
|
-
// we can safely assume the credential is unavailable.
|
|
142
|
-
if (err.code === "ENETUNREACH") {
|
|
143
|
-
const error = new CredentialUnavailableError("ManagedIdentityCredential is unavailable. Network unreachable.");
|
|
144
|
-
logger.getToken.info(formatError(scopes, error));
|
|
145
|
-
throw error;
|
|
146
|
-
}
|
|
147
|
-
// If either the host was unreachable,
|
|
148
|
-
// we can safely assume the credential is unavailable.
|
|
149
|
-
if (err.code === "EHOSTUNREACH") {
|
|
150
|
-
const error = new CredentialUnavailableError("ManagedIdentityCredential is unavailable. No managed identity endpoint found.");
|
|
151
|
-
logger.getToken.info(formatError(scopes, error));
|
|
152
|
-
throw error;
|
|
153
|
-
}
|
|
154
|
-
// If err.statusCode has a value of 400, it comes from sendTokenRequest,
|
|
155
|
-
// and it means that the endpoint is working, but that no identity is available.
|
|
156
|
-
if (err.statusCode === 400) {
|
|
157
|
-
throw new CredentialUnavailableError("The managed identity endpoint is indicating there's no available identity");
|
|
158
|
-
}
|
|
159
|
-
// If the error has no status code, we can assume there was no available identity.
|
|
160
|
-
// This will throw silently during any ChainedTokenCredential.
|
|
161
|
-
if (err.statusCode === undefined) {
|
|
162
|
-
throw new CredentialUnavailableError(`ManagedIdentityCredential authentication failed. Message ${err.message}`);
|
|
163
|
-
}
|
|
164
|
-
// Any other error should break the chain.
|
|
165
|
-
throw new AuthenticationError(err.statusCode, {
|
|
166
|
-
error: "ManagedIdentityCredential authentication failed.",
|
|
167
|
-
error_description: err.message
|
|
168
|
-
});
|
|
111
|
+
else {
|
|
112
|
+
// We've previously determined that the endpoint was unavailable,
|
|
113
|
+
// either because it was unreachable or permanently unable to authenticate.
|
|
114
|
+
const error = new CredentialUnavailableError("The managed identity endpoint is not currently available");
|
|
115
|
+
logger.getToken.info(formatError(scopes, error));
|
|
116
|
+
throw error;
|
|
169
117
|
}
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
118
|
+
logger.getToken.info(formatSuccess(scopes));
|
|
119
|
+
return result;
|
|
120
|
+
}
|
|
121
|
+
catch (err) {
|
|
122
|
+
// CredentialUnavailable errors are expected to reach here.
|
|
123
|
+
// We intend them to bubble up, so that DefaultAzureCredential can catch them.
|
|
124
|
+
if (err.name === "AuthenticationRequiredError") {
|
|
125
|
+
throw err;
|
|
126
|
+
}
|
|
127
|
+
// Expected errors to reach this point:
|
|
128
|
+
// - Errors coming from a method unexpectedly breaking.
|
|
129
|
+
// - When identityClient.sendTokenRequest throws, in which case
|
|
130
|
+
// if the status code was 400, it means that the endpoint is working,
|
|
131
|
+
// but no identity is available.
|
|
132
|
+
span.setStatus({
|
|
133
|
+
code: SpanStatusCode.ERROR,
|
|
134
|
+
message: err.message
|
|
135
|
+
});
|
|
136
|
+
// If either the network is unreachable,
|
|
137
|
+
// we can safely assume the credential is unavailable.
|
|
138
|
+
if (err.code === "ENETUNREACH") {
|
|
139
|
+
const error = new CredentialUnavailableError(`ManagedIdentityCredential is unavailable. Network unreachable. Message: ${err.message}`);
|
|
140
|
+
logger.getToken.info(formatError(scopes, error));
|
|
141
|
+
throw error;
|
|
142
|
+
}
|
|
143
|
+
// If either the host was unreachable,
|
|
144
|
+
// we can safely assume the credential is unavailable.
|
|
145
|
+
if (err.code === "EHOSTUNREACH") {
|
|
146
|
+
const error = new CredentialUnavailableError(`ManagedIdentityCredential is unavailable. No managed identity endpoint found. Message: ${err.message}`);
|
|
147
|
+
logger.getToken.info(formatError(scopes, error));
|
|
148
|
+
throw error;
|
|
173
149
|
}
|
|
174
|
-
|
|
150
|
+
// If err.statusCode has a value of 400, it comes from sendTokenRequest,
|
|
151
|
+
// and it means that the endpoint is working, but that no identity is available.
|
|
152
|
+
if (err.statusCode === 400) {
|
|
153
|
+
throw new CredentialUnavailableError(`ManagedIdentityCredential: The managed identity endpoint is indicating there's no available identity. Message: ${err.message}`);
|
|
154
|
+
}
|
|
155
|
+
// If the error has no status code, we can assume there was no available identity.
|
|
156
|
+
// This will throw silently during any ChainedTokenCredential.
|
|
157
|
+
if (err.statusCode === undefined) {
|
|
158
|
+
throw new CredentialUnavailableError(`ManagedIdentityCredential authentication failed. Message ${err.message}`);
|
|
159
|
+
}
|
|
160
|
+
// Any other error should break the chain.
|
|
161
|
+
throw new AuthenticationError(err.statusCode, {
|
|
162
|
+
error: "ManagedIdentityCredential authentication failed.",
|
|
163
|
+
error_description: err.message
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
finally {
|
|
167
|
+
// Finally is always called, both if we return and if we throw in the above try/catch.
|
|
168
|
+
span.end();
|
|
169
|
+
}
|
|
175
170
|
}
|
|
176
171
|
}
|
|
177
172
|
//# sourceMappingURL=index.js.map
|