@azure/identity 1.2.0-beta.2 → 1.2.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.

Files changed (72) hide show
  1. package/CHANGELOG.md +24 -2
  2. package/README.md +75 -55
  3. package/dist/index.js +533 -396
  4. package/dist/index.js.map +1 -1
  5. package/dist-esm/src/client/msalClient.js +138 -0
  6. package/dist-esm/src/client/msalClient.js.map +1 -0
  7. package/dist-esm/src/credentials/authorizationCodeCredential.browser.js +2 -2
  8. package/dist-esm/src/credentials/authorizationCodeCredential.browser.js.map +1 -1
  9. package/dist-esm/src/credentials/authorizationCodeCredential.js +3 -1
  10. package/dist-esm/src/credentials/authorizationCodeCredential.js.map +1 -1
  11. package/dist-esm/src/credentials/azureCliCredential.browser.js +2 -2
  12. package/dist-esm/src/credentials/azureCliCredential.browser.js.map +1 -1
  13. package/dist-esm/src/credentials/azureCliCredential.js +5 -5
  14. package/dist-esm/src/credentials/azureCliCredential.js.map +1 -1
  15. package/dist-esm/src/credentials/chainedTokenCredential.js +2 -2
  16. package/dist-esm/src/credentials/chainedTokenCredential.js.map +1 -1
  17. package/dist-esm/src/credentials/clientCertificateCredential.browser.js +2 -2
  18. package/dist-esm/src/credentials/clientCertificateCredential.browser.js.map +1 -1
  19. package/dist-esm/src/credentials/clientCertificateCredential.js +5 -3
  20. package/dist-esm/src/credentials/clientCertificateCredential.js.map +1 -1
  21. package/dist-esm/src/credentials/clientCertificateCredentialOptions.js.map +1 -1
  22. package/dist-esm/src/credentials/clientSecretCredential.js +2 -2
  23. package/dist-esm/src/credentials/clientSecretCredential.js.map +1 -1
  24. package/dist-esm/src/credentials/deviceCodeCredential.browser.js +2 -2
  25. package/dist-esm/src/credentials/deviceCodeCredential.browser.js.map +1 -1
  26. package/dist-esm/src/credentials/deviceCodeCredential.js +53 -47
  27. package/dist-esm/src/credentials/deviceCodeCredential.js.map +1 -1
  28. package/dist-esm/src/credentials/environmentCredential.browser.js +2 -2
  29. package/dist-esm/src/credentials/environmentCredential.browser.js.map +1 -1
  30. package/dist-esm/src/credentials/environmentCredential.js +6 -2
  31. package/dist-esm/src/credentials/environmentCredential.js.map +1 -1
  32. package/dist-esm/src/credentials/interactiveBrowserCredential.browser.js +7 -5
  33. package/dist-esm/src/credentials/interactiveBrowserCredential.browser.js.map +1 -1
  34. package/dist-esm/src/credentials/interactiveBrowserCredential.js +30 -69
  35. package/dist-esm/src/credentials/interactiveBrowserCredential.js.map +1 -1
  36. package/dist-esm/src/credentials/interactiveBrowserCredentialOptions.js.map +1 -1
  37. package/dist-esm/src/credentials/managedIdentityCredential/appServiceMsi2017.js +44 -0
  38. package/dist-esm/src/credentials/managedIdentityCredential/appServiceMsi2017.js.map +1 -0
  39. package/dist-esm/src/credentials/managedIdentityCredential/arcMsi.js +74 -0
  40. package/dist-esm/src/credentials/managedIdentityCredential/arcMsi.js.map +1 -0
  41. package/dist-esm/src/credentials/managedIdentityCredential/cloudShellMsi.js +41 -0
  42. package/dist-esm/src/credentials/managedIdentityCredential/cloudShellMsi.js.map +1 -0
  43. package/dist-esm/src/credentials/managedIdentityCredential/constants.js +8 -0
  44. package/dist-esm/src/credentials/managedIdentityCredential/constants.js.map +1 -0
  45. package/dist-esm/src/credentials/managedIdentityCredential/fabricMsi.js +59 -0
  46. package/dist-esm/src/credentials/managedIdentityCredential/fabricMsi.js.map +1 -0
  47. package/dist-esm/src/credentials/managedIdentityCredential/imdsMsi.js +109 -0
  48. package/dist-esm/src/credentials/managedIdentityCredential/imdsMsi.js.map +1 -0
  49. package/dist-esm/src/credentials/{managedIdentityCredential.browser.js → managedIdentityCredential/index.browser.js} +4 -4
  50. package/dist-esm/src/credentials/managedIdentityCredential/index.browser.js.map +1 -0
  51. package/dist-esm/src/credentials/managedIdentityCredential/index.js +165 -0
  52. package/dist-esm/src/credentials/managedIdentityCredential/index.js.map +1 -0
  53. package/dist-esm/src/credentials/managedIdentityCredential/models.js +3 -0
  54. package/dist-esm/src/credentials/managedIdentityCredential/models.js.map +1 -0
  55. package/dist-esm/src/credentials/managedIdentityCredential/utils.js +28 -0
  56. package/dist-esm/src/credentials/managedIdentityCredential/utils.js.map +1 -0
  57. package/dist-esm/src/credentials/usernamePasswordCredential.js +3 -1
  58. package/dist-esm/src/credentials/usernamePasswordCredential.js.map +1 -1
  59. package/dist-esm/src/credentials/visualStudioCodeCredential.browser.js +2 -2
  60. package/dist-esm/src/credentials/visualStudioCodeCredential.browser.js.map +1 -1
  61. package/dist-esm/src/credentials/visualStudioCodeCredential.js +19 -8
  62. package/dist-esm/src/credentials/visualStudioCodeCredential.js.map +1 -1
  63. package/dist-esm/src/index.js.map +1 -1
  64. package/dist-esm/src/util/checkTenantId.js +11 -0
  65. package/dist-esm/src/util/checkTenantId.js.map +1 -0
  66. package/dist-esm/src/util/logging.js +7 -3
  67. package/dist-esm/src/util/logging.js.map +1 -1
  68. package/package.json +7 -5
  69. package/types/identity.d.ts +9 -33
  70. package/dist-esm/src/credentials/managedIdentityCredential.browser.js.map +0 -1
  71. package/dist-esm/src/credentials/managedIdentityCredential.js +0 -376
  72. package/dist-esm/src/credentials/managedIdentityCredential.js.map +0 -1
@@ -1,16 +1,13 @@
1
1
  // Copyright (c) Microsoft Corporation.
2
2
  // Licensed under the MIT license.
3
3
  import { __awaiter } from "tslib";
4
- import { credentialLogger } from "../util/logging";
5
- import { IdentityClient } from "../client/identityClient";
4
+ import { credentialLogger, formatError, formatSuccess } from "../util/logging";
6
5
  import { DefaultTenantId, DeveloperSignOnClientId } from "../constants";
6
+ import { AuthenticationRequired, MsalClient } from "../client/msalClient";
7
7
  import express from "express";
8
- import { PublicClientApplication } from "@azure/msal-node";
9
8
  import open from "open";
10
- import { CredentialUnavailable } from "../client/errors";
9
+ import { checkTenantId } from "../util/checkTenantId";
11
10
  const logger = credentialLogger("InteractiveBrowserCredential");
12
- class AuthenticationRequired extends CredentialUnavailable {
13
- }
14
11
  /**
15
12
  * Enables authentication to Azure Active Directory inside of the web browser
16
13
  * using the interactive login flow, either via browser redirects or a popup
@@ -18,12 +15,11 @@ class AuthenticationRequired extends CredentialUnavailable {
18
15
  */
19
16
  export class InteractiveBrowserCredential {
20
17
  constructor(options) {
21
- this.identityClient = new IdentityClient(options);
22
- this.tenantId = (options && options.tenantId) || DefaultTenantId;
23
- this.clientId = (options && options.clientId) || DeveloperSignOnClientId;
24
- // Future update: this is for persistent caching
25
- this.persistenceEnabled = this.persistenceEnabled = (options === null || options === void 0 ? void 0 : options.cacheOptions) !== undefined;
26
- this.authenticationRecord = options === null || options === void 0 ? void 0 : options.authenticationRecord;
18
+ const tenantId = (options && options.tenantId) || DefaultTenantId;
19
+ const clientId = (options && options.clientId) || DeveloperSignOnClientId;
20
+ checkTenantId(logger, tenantId);
21
+ // const persistenceEnabled = options?.persistenceEnabled ? options?.persistenceEnabled : false;
22
+ // const authenticationRecord = options?.authenticationRecord;
27
23
  if (options && options.redirectUri) {
28
24
  if (typeof options.redirectUri === "string") {
29
25
  this.redirectUri = options.redirectUri;
@@ -40,29 +36,19 @@ export class InteractiveBrowserCredential {
40
36
  if (isNaN(this.port)) {
41
37
  this.port = 80;
42
38
  }
39
+ let authorityHost;
43
40
  if (options && options.authorityHost) {
44
41
  if (options.authorityHost.endsWith("/")) {
45
- this.authorityHost = options.authorityHost + this.tenantId;
42
+ authorityHost = options.authorityHost + tenantId;
46
43
  }
47
44
  else {
48
- this.authorityHost = options.authorityHost + "/" + this.tenantId;
45
+ authorityHost = options.authorityHost + "/" + tenantId;
49
46
  }
50
47
  }
51
48
  else {
52
- this.authorityHost = "https://login.microsoftonline.com/" + this.tenantId;
49
+ authorityHost = "https://login.microsoftonline.com/" + tenantId;
53
50
  }
54
- const knownAuthorities = this.tenantId === "adfs" ? [this.authorityHost] : [];
55
- const publicClientConfig = {
56
- auth: {
57
- clientId: this.clientId,
58
- authority: this.authorityHost,
59
- knownAuthorities: knownAuthorities
60
- },
61
- cache: options === null || options === void 0 ? void 0 : options.cacheOptions,
62
- system: { networkClient: this.identityClient }
63
- };
64
- this.pca = new PublicClientApplication(publicClientConfig);
65
- this.msalCacheManager = this.pca.getTokenCache();
51
+ this.msalClient = new MsalClient({ clientId, authority: authorityHost }, false, undefined, options);
66
52
  }
67
53
  /**
68
54
  * Authenticates with Azure Active Directory and returns an access token if
@@ -76,37 +62,13 @@ export class InteractiveBrowserCredential {
76
62
  */
77
63
  getToken(scopes, _options) {
78
64
  const scopeArray = typeof scopes === "object" ? scopes : [scopes];
79
- if (this.authenticationRecord && this.persistenceEnabled) {
80
- return this.acquireTokenFromCache().catch((e) => {
81
- if (e instanceof AuthenticationRequired) {
82
- return this.acquireTokenFromBrowser(scopeArray);
83
- }
84
- else {
85
- throw e;
86
- }
87
- });
88
- }
89
- else {
90
- return this.acquireTokenFromBrowser(scopeArray);
91
- }
92
- }
93
- acquireTokenFromCache() {
94
- return __awaiter(this, void 0, void 0, function* () {
95
- yield this.msalCacheManager.readFromPersistence();
96
- const silentRequest = {
97
- account: this.authenticationRecord,
98
- scopes: ["https://vault.azure.net/user_impersonation", "https://vault.azure.net/.default"]
99
- };
100
- try {
101
- const response = yield this.pca.acquireTokenSilent(silentRequest);
102
- logger.info("Successful silent token acquisition");
103
- return {
104
- expiresOnTimestamp: response.expiresOn.getTime(),
105
- token: response.accessToken
106
- };
65
+ return this.msalClient.acquireTokenFromCache(scopeArray).catch((e) => {
66
+ if (e instanceof AuthenticationRequired) {
67
+ return this.acquireTokenFromBrowser(scopeArray);
107
68
  }
108
- catch (e) {
109
- throw new AuthenticationRequired("Could not authenticate silently using the cache");
69
+ else {
70
+ logger.getToken.info(formatError(scopes, e));
71
+ throw e;
110
72
  }
111
73
  });
112
74
  }
@@ -116,11 +78,8 @@ export class InteractiveBrowserCredential {
116
78
  scopes: scopeArray,
117
79
  redirectUri: this.redirectUri
118
80
  };
119
- const response = yield this.pca.getAuthCodeUrl(authCodeUrlParameters);
81
+ const response = yield this.msalClient.getAuthCodeUrl(authCodeUrlParameters);
120
82
  yield open(response);
121
- if (this.persistenceEnabled) {
122
- yield this.msalCacheManager.readFromPersistence();
123
- }
124
83
  });
125
84
  }
126
85
  acquireTokenFromBrowser(scopeArray) {
@@ -147,19 +106,21 @@ export class InteractiveBrowserCredential {
147
106
  scopes: scopeArray
148
107
  };
149
108
  try {
150
- const authResponse = yield this.pca.acquireTokenByCode(tokenRequest);
151
- res.sendStatus(200);
152
- if (this.persistenceEnabled) {
153
- this.msalCacheManager.writeToPersistence();
154
- }
109
+ const authResponse = yield this.msalClient.acquireTokenByCode(tokenRequest);
110
+ const successMessage = `Authentication Complete. You can close the browser and return to the application.`;
111
+ const expiresOnTimestamp = authResponse === null || authResponse === void 0 ? void 0 : authResponse.expiresOn.valueOf();
112
+ res.status(200).send(successMessage);
113
+ logger.getToken.info(formatSuccess(scopeArray));
155
114
  resolve({
156
- expiresOnTimestamp: authResponse.expiresOn.valueOf(),
115
+ expiresOnTimestamp,
157
116
  token: authResponse.accessToken
158
117
  });
159
118
  }
160
119
  catch (error) {
161
- res.status(500).send(error);
162
- reject(new Error(`Authentication Error "${req.query["error"]}":\n\n${req.query["error_description"]}`));
120
+ const errorMessage = formatError(scopeArray, `${req.query["error"]}. ${req.query["error_description"]}`);
121
+ res.status(500).send(errorMessage);
122
+ logger.getToken.info(errorMessage);
123
+ reject(new Error(errorMessage));
163
124
  }
164
125
  finally {
165
126
  cleanup();
@@ -1 +1 @@
1
- {"version":3,"file":"interactiveBrowserCredential.js","sourceRoot":"","sources":["../../../src/credentials/interactiveBrowserCredential.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\n/* eslint-disable @typescript-eslint/no-unused-vars */\n\nimport { TokenCredential, GetTokenOptions, AccessToken } from \"@azure/core-http\";\nimport {\n InteractiveBrowserCredentialOptions,\n AuthenticationRecord\n} from \"./interactiveBrowserCredentialOptions\";\nimport { credentialLogger } from \"../util/logging\";\nimport { IdentityClient } from \"../client/identityClient\";\nimport { DefaultTenantId, DeveloperSignOnClientId } from \"../constants\";\nimport { Socket } from \"net\";\n\nimport express from \"express\";\nimport {\n PublicClientApplication,\n TokenCache,\n AuthorizationCodeRequest,\n Configuration\n} from \"@azure/msal-node\";\nimport open from \"open\";\nimport http from \"http\";\nimport { CredentialUnavailable } from \"../client/errors\";\n\nconst logger = credentialLogger(\"InteractiveBrowserCredential\");\n\nclass AuthenticationRequired extends CredentialUnavailable {}\n\n/**\n * Enables authentication to Azure Active Directory inside of the web browser\n * using the interactive login flow, either via browser redirects or a popup\n * window. This credential is not currently supported in Node.js.\n */\nexport class InteractiveBrowserCredential implements TokenCredential {\n private identityClient: IdentityClient;\n private pca: PublicClientApplication;\n private msalCacheManager: TokenCache;\n private tenantId: string;\n private clientId: string;\n private persistenceEnabled: boolean;\n private redirectUri: string;\n private authorityHost: string;\n private authenticationRecord: AuthenticationRecord | undefined;\n private port: number;\n\n constructor(options?: InteractiveBrowserCredentialOptions) {\n this.identityClient = new IdentityClient(options);\n this.tenantId = (options && options.tenantId) || DefaultTenantId;\n this.clientId = (options && options.clientId) || DeveloperSignOnClientId;\n\n // Future update: this is for persistent caching\n this.persistenceEnabled = this.persistenceEnabled = options?.cacheOptions !== undefined;\n this.authenticationRecord = options?.authenticationRecord;\n\n if (options && options.redirectUri) {\n if (typeof options.redirectUri === \"string\") {\n this.redirectUri = options.redirectUri;\n } else {\n this.redirectUri = options.redirectUri();\n }\n } else {\n this.redirectUri = \"http://localhost\";\n }\n\n const url = new URL(this.redirectUri);\n this.port = parseInt(url.port);\n if (isNaN(this.port)) {\n this.port = 80;\n }\n\n if (options && options.authorityHost) {\n if (options.authorityHost.endsWith(\"/\")) {\n this.authorityHost = options.authorityHost + this.tenantId;\n } else {\n this.authorityHost = options.authorityHost + \"/\" + this.tenantId;\n }\n } else {\n this.authorityHost = \"https://login.microsoftonline.com/\" + this.tenantId;\n }\n\n const knownAuthorities = this.tenantId === \"adfs\" ? [this.authorityHost] : [];\n\n const publicClientConfig: Configuration = {\n auth: {\n clientId: this.clientId,\n authority: this.authorityHost,\n knownAuthorities: knownAuthorities\n },\n cache: options?.cacheOptions,\n system: { networkClient: this.identityClient }\n };\n this.pca = new PublicClientApplication(publicClientConfig);\n this.msalCacheManager = this.pca.getTokenCache();\n }\n\n /**\n * Authenticates with Azure Active Directory and returns an access token if\n * successful. If authentication cannot be performed at this time, this method may\n * return null. If an error occurs during authentication, an {@link AuthenticationError}\n * containing failure details will be thrown.\n *\n * @param scopes The list of scopes for which the token will have access.\n * @param options The options used to configure any requests this\n * TokenCredential implementation might make.\n */\n public getToken(\n scopes: string | string[],\n _options?: GetTokenOptions\n ): Promise<AccessToken | null> {\n const scopeArray = typeof scopes === \"object\" ? scopes : [scopes];\n\n if (this.authenticationRecord && this.persistenceEnabled) {\n return this.acquireTokenFromCache().catch((e) => {\n if (e instanceof AuthenticationRequired) {\n return this.acquireTokenFromBrowser(scopeArray);\n } else {\n throw e;\n }\n });\n } else {\n return this.acquireTokenFromBrowser(scopeArray);\n }\n }\n\n private async acquireTokenFromCache(): Promise<AccessToken | null> {\n await this.msalCacheManager.readFromPersistence();\n\n const silentRequest = {\n account: this.authenticationRecord!,\n scopes: [\"https://vault.azure.net/user_impersonation\", \"https://vault.azure.net/.default\"]\n };\n\n try {\n const response = await this.pca.acquireTokenSilent(silentRequest);\n logger.info(\"Successful silent token acquisition\");\n return {\n expiresOnTimestamp: response.expiresOn.getTime(),\n token: response.accessToken\n };\n } catch (e) {\n throw new AuthenticationRequired(\"Could not authenticate silently using the cache\");\n }\n }\n\n private async openAuthCodeUrl(scopeArray: string[]): Promise<void> {\n const authCodeUrlParameters = {\n scopes: scopeArray,\n redirectUri: this.redirectUri\n };\n\n const response = await this.pca.getAuthCodeUrl(authCodeUrlParameters);\n await open(response);\n\n if (this.persistenceEnabled) {\n await this.msalCacheManager.readFromPersistence();\n }\n }\n\n private async acquireTokenFromBrowser(scopeArray: string[]): Promise<AccessToken | null> {\n // eslint-disable-next-line\n return new Promise<AccessToken | null>(async (resolve, reject) => {\n // eslint-disable-next-line\n let listen: http.Server | undefined;\n let socketToDestroy: Socket | undefined;\n\n function cleanup() {\n if (listen) {\n listen.close();\n }\n if (socketToDestroy) {\n socketToDestroy.destroy();\n }\n }\n\n // Create Express App and Routes\n const app = express();\n\n app.get(\"/\", async (req, res) => {\n const tokenRequest: AuthorizationCodeRequest = {\n code: req.query.code as string,\n redirectUri: this.redirectUri,\n scopes: scopeArray\n };\n\n try {\n const authResponse = await this.pca.acquireTokenByCode(tokenRequest);\n res.sendStatus(200);\n\n if (this.persistenceEnabled) {\n this.msalCacheManager.writeToPersistence();\n }\n\n resolve({\n expiresOnTimestamp: authResponse.expiresOn.valueOf(),\n token: authResponse.accessToken\n });\n } catch (error) {\n res.status(500).send(error);\n\n reject(\n new Error(\n `Authentication Error \"${req.query[\"error\"]}\":\\n\\n${req.query[\"error_description\"]}`\n )\n );\n } finally {\n cleanup();\n }\n });\n\n listen = app.listen(this.port, () =>\n logger.info(`Msal Node Auth Code Sample app listening on port ${this.port}!`)\n );\n listen.on(\"connection\", (socket) => (socketToDestroy = socket));\n\n try {\n await this.openAuthCodeUrl(scopeArray);\n } catch (e) {\n cleanup();\n throw e;\n }\n });\n }\n}\n"]}
1
+ {"version":3,"file":"interactiveBrowserCredential.js","sourceRoot":"","sources":["../../../src/credentials/interactiveBrowserCredential.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,kCAAkC;;AAMlC,OAAO,EAAE,gBAAgB,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAC/E,OAAO,EAAE,eAAe,EAAE,uBAAuB,EAAE,MAAM,cAAc,CAAC;AAExE,OAAO,EAAE,sBAAsB,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAG1E,OAAO,OAAO,MAAM,SAAS,CAAC;AAC9B,OAAO,IAAI,MAAM,MAAM,CAAC;AAExB,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAEtD,MAAM,MAAM,GAAG,gBAAgB,CAAC,8BAA8B,CAAC,CAAC;AAEhE;;;;GAIG;AACH,MAAM,OAAO,4BAA4B;IAKvC,YAAY,OAA6C;QACvD,MAAM,QAAQ,GAAG,CAAC,OAAO,IAAI,OAAO,CAAC,QAAQ,CAAC,IAAI,eAAe,CAAC;QAClE,MAAM,QAAQ,GAAG,CAAC,OAAO,IAAI,OAAO,CAAC,QAAQ,CAAC,IAAI,uBAAuB,CAAC;QAE1E,aAAa,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;QAEhC,gGAAgG;QAChG,8DAA8D;QAE9D,IAAI,OAAO,IAAI,OAAO,CAAC,WAAW,EAAE;YAClC,IAAI,OAAO,OAAO,CAAC,WAAW,KAAK,QAAQ,EAAE;gBAC3C,IAAI,CAAC,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC;aACxC;iBAAM;gBACL,IAAI,CAAC,WAAW,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC;aAC1C;SACF;aAAM;YACL,IAAI,CAAC,WAAW,GAAG,kBAAkB,CAAC;SACvC;QAED,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QACtC,IAAI,CAAC,IAAI,GAAG,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAC/B,IAAI,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;YACpB,IAAI,CAAC,IAAI,GAAG,EAAE,CAAC;SAChB;QAED,IAAI,aAAa,CAAC;QAClB,IAAI,OAAO,IAAI,OAAO,CAAC,aAAa,EAAE;YACpC,IAAI,OAAO,CAAC,aAAa,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE;gBACvC,aAAa,GAAG,OAAO,CAAC,aAAa,GAAG,QAAQ,CAAC;aAClD;iBAAM;gBACL,aAAa,GAAG,OAAO,CAAC,aAAa,GAAG,GAAG,GAAG,QAAQ,CAAC;aACxD;SACF;aAAM;YACL,aAAa,GAAG,oCAAoC,GAAG,QAAQ,CAAC;SACjE;QAED,IAAI,CAAC,UAAU,GAAG,IAAI,UAAU,CAC9B,EAAE,QAAQ,EAAE,SAAS,EAAE,aAAa,EAAE,EACtC,KAAK,EACL,SAAS,EACT,OAAO,CACR,CAAC;IACJ,CAAC;IAED;;;;;;;;;OASG;IACI,QAAQ,CACb,MAAyB,EACzB,QAA0B;QAE1B,MAAM,UAAU,GAAG,OAAO,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;QAElE,OAAO,IAAI,CAAC,UAAU,CAAC,qBAAqB,CAAC,UAAU,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE;YACnE,IAAI,CAAC,YAAY,sBAAsB,EAAE;gBACvC,OAAO,IAAI,CAAC,uBAAuB,CAAC,UAAU,CAAC,CAAC;aACjD;iBAAM;gBACL,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC;gBAC7C,MAAM,CAAC,CAAC;aACT;QACH,CAAC,CAAC,CAAC;IACL,CAAC;IAEa,eAAe,CAAC,UAAoB;;YAChD,MAAM,qBAAqB,GAAG;gBAC5B,MAAM,EAAE,UAAU;gBAClB,WAAW,EAAE,IAAI,CAAC,WAAW;aAC9B,CAAC;YAEF,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,cAAc,CAAC,qBAAqB,CAAC,CAAC;YAC7E,MAAM,IAAI,CAAC,QAAQ,CAAC,CAAC;QACvB,CAAC;KAAA;IAEa,uBAAuB,CAAC,UAAoB;;YACxD,2BAA2B;YAC3B,OAAO,IAAI,OAAO,CAAqB,CAAO,OAAO,EAAE,MAAM,EAAE,EAAE;gBAC/D,2BAA2B;gBAC3B,IAAI,MAA+B,CAAC;gBACpC,IAAI,eAAmC,CAAC;gBAExC,SAAS,OAAO;oBACd,IAAI,MAAM,EAAE;wBACV,MAAM,CAAC,KAAK,EAAE,CAAC;qBAChB;oBACD,IAAI,eAAe,EAAE;wBACnB,eAAe,CAAC,OAAO,EAAE,CAAC;qBAC3B;gBACH,CAAC;gBAED,gCAAgC;gBAChC,MAAM,GAAG,GAAG,OAAO,EAAE,CAAC;gBAEtB,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,CAAO,GAAG,EAAE,GAAG,EAAE,EAAE;oBAC9B,MAAM,YAAY,GAA6B;wBAC7C,IAAI,EAAE,GAAG,CAAC,KAAK,CAAC,IAAc;wBAC9B,WAAW,EAAE,IAAI,CAAC,WAAW;wBAC7B,MAAM,EAAE,UAAU;qBACnB,CAAC;oBAEF,IAAI;wBACF,MAAM,YAAY,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,kBAAkB,CAAC,YAAY,CAAC,CAAC;wBAC5E,MAAM,cAAc,GAAG,mFAAmF,CAAC;wBAC3G,MAAM,kBAAkB,GAAG,YAAY,aAAZ,YAAY,uBAAZ,YAAY,CAAE,SAAS,CAAC,OAAO,EAAE,CAAC;wBAC7D,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;wBACrC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,aAAa,CAAC,UAAU,CAAC,CAAC,CAAC;wBAEhD,OAAO,CAAC;4BACN,kBAAkB;4BAClB,KAAK,EAAE,YAAY,CAAC,WAAW;yBAChC,CAAC,CAAC;qBACJ;oBAAC,OAAO,KAAK,EAAE;wBACd,MAAM,YAAY,GAAG,WAAW,CAC9B,UAAU,EACV,GAAG,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,GAAG,CAAC,KAAK,CAAC,mBAAmB,CAAC,EAAE,CAC3D,CAAC;wBACF,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;wBACnC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;wBACnC,MAAM,CAAC,IAAI,KAAK,CAAC,YAAY,CAAC,CAAC,CAAC;qBACjC;4BAAS;wBACR,OAAO,EAAE,CAAC;qBACX;gBACH,CAAC,CAAA,CAAC,CAAC;gBAEH,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,EAAE,CAClC,MAAM,CAAC,IAAI,CAAC,oDAAoD,IAAI,CAAC,IAAI,GAAG,CAAC,CAC9E,CAAC;gBACF,MAAM,CAAC,EAAE,CAAC,YAAY,EAAE,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,eAAe,GAAG,MAAM,CAAC,CAAC,CAAC;gBAEhE,IAAI;oBACF,MAAM,IAAI,CAAC,eAAe,CAAC,UAAU,CAAC,CAAC;iBACxC;gBAAC,OAAO,CAAC,EAAE;oBACV,OAAO,EAAE,CAAC;oBACV,MAAM,CAAC,CAAC;iBACT;YACH,CAAC,CAAA,CAAC,CAAC;QACL,CAAC;KAAA;CACF","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\n/* eslint-disable @typescript-eslint/no-unused-vars */\n\nimport { TokenCredential, GetTokenOptions, AccessToken } from \"@azure/core-http\";\nimport { InteractiveBrowserCredentialOptions } from \"./interactiveBrowserCredentialOptions\";\nimport { credentialLogger, formatError, formatSuccess } from \"../util/logging\";\nimport { DefaultTenantId, DeveloperSignOnClientId } from \"../constants\";\nimport { Socket } from \"net\";\nimport { AuthenticationRequired, MsalClient } from \"../client/msalClient\";\nimport { AuthorizationCodeRequest } from \"@azure/msal-node\";\n\nimport express from \"express\";\nimport open from \"open\";\nimport http from \"http\";\nimport { checkTenantId } from \"../util/checkTenantId\";\n\nconst logger = credentialLogger(\"InteractiveBrowserCredential\");\n\n/**\n * Enables authentication to Azure Active Directory inside of the web browser\n * using the interactive login flow, either via browser redirects or a popup\n * window. This credential is not currently supported in Node.js.\n */\nexport class InteractiveBrowserCredential implements TokenCredential {\n private redirectUri: string;\n private port: number;\n private msalClient: MsalClient;\n\n constructor(options?: InteractiveBrowserCredentialOptions) {\n const tenantId = (options && options.tenantId) || DefaultTenantId;\n const clientId = (options && options.clientId) || DeveloperSignOnClientId;\n\n checkTenantId(logger, tenantId);\n\n // const persistenceEnabled = options?.persistenceEnabled ? options?.persistenceEnabled : false;\n // const authenticationRecord = options?.authenticationRecord;\n\n if (options && options.redirectUri) {\n if (typeof options.redirectUri === \"string\") {\n this.redirectUri = options.redirectUri;\n } else {\n this.redirectUri = options.redirectUri();\n }\n } else {\n this.redirectUri = \"http://localhost\";\n }\n\n const url = new URL(this.redirectUri);\n this.port = parseInt(url.port);\n if (isNaN(this.port)) {\n this.port = 80;\n }\n\n let authorityHost;\n if (options && options.authorityHost) {\n if (options.authorityHost.endsWith(\"/\")) {\n authorityHost = options.authorityHost + tenantId;\n } else {\n authorityHost = options.authorityHost + \"/\" + tenantId;\n }\n } else {\n authorityHost = \"https://login.microsoftonline.com/\" + tenantId;\n }\n\n this.msalClient = new MsalClient(\n { clientId, authority: authorityHost },\n false,\n undefined,\n options\n );\n }\n\n /**\n * Authenticates with Azure Active Directory and returns an access token if\n * successful. If authentication cannot be performed at this time, this method may\n * return null. If an error occurs during authentication, an {@link AuthenticationError}\n * containing failure details will be thrown.\n *\n * @param scopes The list of scopes for which the token will have access.\n * @param options The options used to configure any requests this\n * TokenCredential implementation might make.\n */\n public getToken(\n scopes: string | string[],\n _options?: GetTokenOptions\n ): Promise<AccessToken | null> {\n const scopeArray = typeof scopes === \"object\" ? scopes : [scopes];\n\n return this.msalClient.acquireTokenFromCache(scopeArray).catch((e) => {\n if (e instanceof AuthenticationRequired) {\n return this.acquireTokenFromBrowser(scopeArray);\n } else {\n logger.getToken.info(formatError(scopes, e));\n throw e;\n }\n });\n }\n\n private async openAuthCodeUrl(scopeArray: string[]): Promise<void> {\n const authCodeUrlParameters = {\n scopes: scopeArray,\n redirectUri: this.redirectUri\n };\n\n const response = await this.msalClient.getAuthCodeUrl(authCodeUrlParameters);\n await open(response);\n }\n\n private async acquireTokenFromBrowser(scopeArray: string[]): Promise<AccessToken | null> {\n // eslint-disable-next-line\n return new Promise<AccessToken | null>(async (resolve, reject) => {\n // eslint-disable-next-line\n let listen: http.Server | undefined;\n let socketToDestroy: Socket | undefined;\n\n function cleanup(): void {\n if (listen) {\n listen.close();\n }\n if (socketToDestroy) {\n socketToDestroy.destroy();\n }\n }\n\n // Create Express App and Routes\n const app = express();\n\n app.get(\"/\", async (req, res) => {\n const tokenRequest: AuthorizationCodeRequest = {\n code: req.query.code as string,\n redirectUri: this.redirectUri,\n scopes: scopeArray\n };\n\n try {\n const authResponse = await this.msalClient.acquireTokenByCode(tokenRequest);\n const successMessage = `Authentication Complete. You can close the browser and return to the application.`;\n const expiresOnTimestamp = authResponse?.expiresOn.valueOf();\n res.status(200).send(successMessage);\n logger.getToken.info(formatSuccess(scopeArray));\n\n resolve({\n expiresOnTimestamp,\n token: authResponse.accessToken\n });\n } catch (error) {\n const errorMessage = formatError(\n scopeArray,\n `${req.query[\"error\"]}. ${req.query[\"error_description\"]}`\n );\n res.status(500).send(errorMessage);\n logger.getToken.info(errorMessage);\n reject(new Error(errorMessage));\n } finally {\n cleanup();\n }\n });\n\n listen = app.listen(this.port, () =>\n logger.info(`Msal Node Auth Code Sample app listening on port ${this.port}!`)\n );\n listen.on(\"connection\", (socket) => (socketToDestroy = socket));\n\n try {\n await this.openAuthCodeUrl(scopeArray);\n } catch (e) {\n cleanup();\n throw e;\n }\n });\n }\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"interactiveBrowserCredentialOptions.js","sourceRoot":"","sources":["../../../src/credentials/interactiveBrowserCredentialOptions.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,kCAAkC","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\nimport { TokenCredentialOptions } from \"../client/identityClient\";\n\n/**\n * The \"login style\" to use in the authentication flow:\n * - \"redirect\" redirects the user to the authentication page and then\n * redirects them back to the page once authentication is completed.\n * - \"popup\" opens a new browser window through with the redirect flow\n * is initiated. The user's existing browser window does not leave\n * the current page\n */\nexport type BrowserLoginStyle = \"redirect\" | \"popup\";\n\n/**\n * The record to use to find the cached tokens in the cache\n */\nexport interface AuthenticationRecord {\n /**\n * The associated authority, if used\n */\n authority?: string;\n\n /**\n * The home account Id\n */\n homeAccountId: string;\n\n /**\n * The login environment, eg \"login.windows.net\"\n */\n environment: string;\n\n /**\n * The associated tenant ID\n */\n tenantId: string;\n\n /**\n * The username of the logged in account\n */\n username: string;\n}\n\n/**\n * Defines options for the InteractiveBrowserCredential class.\n */\nexport interface InteractiveBrowserCredentialOptions extends TokenCredentialOptions {\n /**\n * Specifies whether a redirect or a popup window should be used to\n * initiate the user authentication flow. Possible values are \"redirect\"\n * or \"popup\" (default) for browser and \"popup\" (default) for node.\n *\n */\n loginStyle?: BrowserLoginStyle;\n\n /**\n * Gets the redirect URI of the application. This should be same as the value\n * in the application registration portal. Defaults to `window.location.href`.\n */\n redirectUri?: string | (() => string);\n\n /**\n * Gets the URI to which the user will be redirected when logging out.\n * Defaults to `window.location.href`.\n */\n postLogoutRedirectUri?: string | (() => string);\n\n /**\n * The Azure Active Directory tenant (directory) ID.\n */\n tenantId?: string;\n\n /**\n * The client (application) ID of an App Registration in the tenant.\n */\n clientId?: string;\n\n /**\n * The cache options to use when credentials are being checked.\n */\n cacheOptions?: {\n cachePlugin?: {\n readFromStorage: () => Promise<string>;\n writeToStorage: (getMergedState: (oldState: string) => string) => Promise<void>;\n };\n };\n\n /**\n * The authentication record to use to find existing tokens in the cache\n */\n authenticationRecord?: AuthenticationRecord;\n}\n"]}
1
+ {"version":3,"file":"interactiveBrowserCredentialOptions.js","sourceRoot":"","sources":["../../../src/credentials/interactiveBrowserCredentialOptions.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,kCAAkC","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\nimport { TokenCredentialOptions } from \"../client/identityClient\";\n\n/**\n * The \"login style\" to use in the authentication flow:\n * - \"redirect\" redirects the user to the authentication page and then\n * redirects them back to the page once authentication is completed.\n * - \"popup\" opens a new browser window through with the redirect flow\n * is initiated. The user's existing browser window does not leave\n * the current page\n */\nexport type BrowserLoginStyle = \"redirect\" | \"popup\";\n\n/**\n * Defines options for the InteractiveBrowserCredential class.\n */\nexport interface InteractiveBrowserCredentialOptions extends TokenCredentialOptions {\n /**\n * Specifies whether a redirect or a popup window should be used to\n * initiate the user authentication flow. Possible values are \"redirect\"\n * or \"popup\" (default) for browser and \"popup\" (default) for node.\n *\n */\n loginStyle?: BrowserLoginStyle;\n\n /**\n * Gets the redirect URI of the application. This should be same as the value\n * in the application registration portal. Defaults to `window.location.href`.\n */\n redirectUri?: string | (() => string);\n\n /**\n * Gets the URI to which the user will be redirected when logging out.\n * Defaults to `window.location.href`.\n */\n postLogoutRedirectUri?: string | (() => string);\n\n /**\n * The Azure Active Directory tenant (directory) ID.\n */\n tenantId?: string;\n\n /**\n * The client (application) ID of an App Registration in the tenant.\n */\n clientId?: string;\n}\n"]}
@@ -0,0 +1,44 @@
1
+ // Copyright (c) Microsoft Corporation.
2
+ // Licensed under the MIT license.
3
+ import { __awaiter } from "tslib";
4
+ import { credentialLogger } from "../../util/logging";
5
+ import { msiGenericGetToken } from "./utils";
6
+ const logger = credentialLogger("ManagedIdentityCredential - AppServiceMSI 2017");
7
+ function expiresInParser(requestBody) {
8
+ // Parse a date format like "06/20/2019 02:57:58 +00:00" and
9
+ // convert it into a JavaScript-formatted date
10
+ return Date.parse(requestBody.expires_on);
11
+ }
12
+ function prepareRequestOptions(resource, clientId) {
13
+ const queryParameters = {
14
+ resource,
15
+ "api-version": "2017-09-01"
16
+ };
17
+ if (clientId) {
18
+ queryParameters.clientid = clientId;
19
+ }
20
+ return {
21
+ url: process.env.MSI_ENDPOINT,
22
+ method: "GET",
23
+ queryParameters,
24
+ headers: {
25
+ Accept: "application/json",
26
+ secret: process.env.MSI_SECRET
27
+ }
28
+ };
29
+ }
30
+ export const appServiceMsi2017 = {
31
+ isAvailable() {
32
+ return __awaiter(this, void 0, void 0, function* () {
33
+ const env = process.env;
34
+ return Boolean(env.MSI_ENDPOINT && env.MSI_SECRET);
35
+ });
36
+ },
37
+ getToken(identityClient, resource, clientId, getTokenOptions = {}) {
38
+ return __awaiter(this, void 0, void 0, function* () {
39
+ logger.info(`Using the endpoint and the secret coming form the environment variables: MSI_ENDPOINT=${process.env.MSI_ENDPOINT} and MSI_SECRET=[REDACTED].`);
40
+ return msiGenericGetToken(identityClient, prepareRequestOptions(resource, clientId), expiresInParser, getTokenOptions);
41
+ });
42
+ }
43
+ };
44
+ //# sourceMappingURL=appServiceMsi2017.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"appServiceMsi2017.js","sourceRoot":"","sources":["../../../../src/credentials/managedIdentityCredential/appServiceMsi2017.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,kCAAkC;;AAIlC,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAEtD,OAAO,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC;AAE7C,MAAM,MAAM,GAAG,gBAAgB,CAAC,gDAAgD,CAAC,CAAC;AAElF,SAAS,eAAe,CAAC,WAAgB;IACvC,4DAA4D;IAC5D,8CAA8C;IAC9C,OAAO,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,UAAU,CAAC,CAAC;AAC5C,CAAC;AAED,SAAS,qBAAqB,CAAC,QAAgB,EAAE,QAAiB;IAChE,MAAM,eAAe,GAAQ;QAC3B,QAAQ;QACR,aAAa,EAAE,YAAY;KAC5B,CAAC;IAEF,IAAI,QAAQ,EAAE;QACZ,eAAe,CAAC,QAAQ,GAAG,QAAQ,CAAC;KACrC;IAED,OAAO;QACL,GAAG,EAAE,OAAO,CAAC,GAAG,CAAC,YAAY;QAC7B,MAAM,EAAE,KAAK;QACb,eAAe;QACf,OAAO,EAAE;YACP,MAAM,EAAE,kBAAkB;YAC1B,MAAM,EAAE,OAAO,CAAC,GAAG,CAAC,UAAU;SAC/B;KACF,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,MAAM,iBAAiB,GAAQ;IAC9B,WAAW;;YACf,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC;YACxB,OAAO,OAAO,CAAC,GAAG,CAAC,YAAY,IAAI,GAAG,CAAC,UAAU,CAAC,CAAC;QACrD,CAAC;KAAA;IACK,QAAQ,CACZ,cAA8B,EAC9B,QAAgB,EAChB,QAAiB,EACjB,kBAAmC,EAAE;;YAErC,MAAM,CAAC,IAAI,CACT,yFAAyF,OAAO,CAAC,GAAG,CAAC,YAAY,6BAA6B,CAC/I,CAAC;YAEF,OAAO,kBAAkB,CACvB,cAAc,EACd,qBAAqB,CAAC,QAAQ,EAAE,QAAQ,CAAC,EACzC,eAAe,EACf,eAAe,CAChB,CAAC;QACJ,CAAC;KAAA;CACF,CAAC","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\nimport { AccessToken, GetTokenOptions, RequestPrepareOptions } from \"@azure/core-http\";\nimport { IdentityClient } from \"../../client/identityClient\";\nimport { credentialLogger } from \"../../util/logging\";\nimport { MSI } from \"./models\";\nimport { msiGenericGetToken } from \"./utils\";\n\nconst logger = credentialLogger(\"ManagedIdentityCredential - AppServiceMSI 2017\");\n\nfunction expiresInParser(requestBody: any): number {\n // Parse a date format like \"06/20/2019 02:57:58 +00:00\" and\n // convert it into a JavaScript-formatted date\n return Date.parse(requestBody.expires_on);\n}\n\nfunction prepareRequestOptions(resource: string, clientId?: string): RequestPrepareOptions {\n const queryParameters: any = {\n resource,\n \"api-version\": \"2017-09-01\"\n };\n\n if (clientId) {\n queryParameters.clientid = clientId;\n }\n\n return {\n url: process.env.MSI_ENDPOINT,\n method: \"GET\",\n queryParameters,\n headers: {\n Accept: \"application/json\",\n secret: process.env.MSI_SECRET\n }\n };\n}\n\nexport const appServiceMsi2017: MSI = {\n async isAvailable(): Promise<boolean> {\n const env = process.env;\n return Boolean(env.MSI_ENDPOINT && env.MSI_SECRET);\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 endpoint and the secret coming form the environment variables: MSI_ENDPOINT=${process.env.MSI_ENDPOINT} and MSI_SECRET=[REDACTED].`\n );\n\n return msiGenericGetToken(\n identityClient,\n prepareRequestOptions(resource, clientId),\n expiresInParser,\n getTokenOptions\n );\n }\n};\n"]}
@@ -0,0 +1,74 @@
1
+ // Copyright (c) Microsoft Corporation.
2
+ // Licensed under the MIT license.
3
+ import { __awaiter } from "tslib";
4
+ import { credentialLogger } from "../../util/logging";
5
+ import { msiGenericGetToken } from "./utils";
6
+ import { azureArcAPIVersion } from "./constants";
7
+ import { AuthenticationError } from "../../client/errors";
8
+ import { readFile } from "fs";
9
+ const logger = credentialLogger("ManagedIdentityCredential - ArcMSI");
10
+ // Azure Arc MSI doesn't have a special expiresIn parser.
11
+ const expiresInParser = undefined;
12
+ function prepareRequestOptions(resource) {
13
+ const queryParameters = {
14
+ resource,
15
+ "api-version": azureArcAPIVersion
16
+ };
17
+ return {
18
+ // Should be similar to: http://localhost:40342/metadata/identity/oauth2/token
19
+ url: process.env.IDENTITY_ENDPOINT,
20
+ method: "GET",
21
+ queryParameters,
22
+ headers: {
23
+ Accept: "application/json",
24
+ Metadata: true
25
+ }
26
+ };
27
+ }
28
+ // Since "fs"'s readFileSync locks the thread, and to avoid extra dependencies.
29
+ function readFileAsync(path, options) {
30
+ return new Promise((resolve, reject) => readFile(path, options, (err, data) => {
31
+ if (err) {
32
+ reject(err);
33
+ }
34
+ resolve(data);
35
+ }));
36
+ }
37
+ function filePathRequest(identityClient, requestPrepareOptions) {
38
+ return __awaiter(this, void 0, void 0, function* () {
39
+ const response = yield identityClient.sendRequest(identityClient.createWebResource(requestPrepareOptions));
40
+ if (response.status !== 401) {
41
+ let message = "";
42
+ if (response.bodyAsText) {
43
+ message = ` Response: ${response.bodyAsText}`;
44
+ }
45
+ throw new AuthenticationError(response.status, `To authenticate with Azure Arc MSI, status code 401 is expected on the first request.${message}`);
46
+ }
47
+ const authHeader = response.headers.get("www-authenticate") || "";
48
+ return authHeader.split("=").slice(1)[0];
49
+ });
50
+ }
51
+ export const arcMsi = {
52
+ isAvailable() {
53
+ return __awaiter(this, void 0, void 0, function* () {
54
+ return Boolean(process.env.IMDS_ENDPOINT && process.env.IDENTITY_ENDPOINT);
55
+ });
56
+ },
57
+ getToken(identityClient, resource, clientId, getTokenOptions = {}) {
58
+ return __awaiter(this, void 0, void 0, function* () {
59
+ logger.info(`Using the Azure Arc MSI to authenticate.`);
60
+ if (clientId) {
61
+ throw new Error("User assigned identity is not supported by the Azure Arc Managed Identity Endpoint. To authenticate with the system assigned identity omit the client id when constructing the ManagedIdentityCredential, or if authenticating with the DefaultAzureCredential ensure the AZURE_CLIENT_ID environment variable is not set.");
62
+ }
63
+ const requestOptions = Object.assign({ disableJsonStringifyOnBody: true, deserializationMapper: undefined, abortSignal: getTokenOptions.abortSignal, spanOptions: getTokenOptions.tracingOptions && getTokenOptions.tracingOptions.spanOptions }, prepareRequestOptions(resource));
64
+ const filePath = yield filePathRequest(identityClient, requestOptions);
65
+ if (!filePath) {
66
+ throw new Error("Azure Arc MSI failed to find the token file.");
67
+ }
68
+ const key = yield readFileAsync(filePath, { encoding: "utf-8" });
69
+ requestOptions.headers["Authorization"] = `Basic ${key}`;
70
+ return msiGenericGetToken(identityClient, requestOptions, expiresInParser, getTokenOptions);
71
+ });
72
+ }
73
+ };
74
+ //# sourceMappingURL=arcMsi.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"arcMsi.js","sourceRoot":"","sources":["../../../../src/credentials/managedIdentityCredential/arcMsi.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\nimport { AccessToken, GetTokenOptions, RequestPrepareOptions } from \"@azure/core-http\";\nimport { MSI } from \"./models\";\nimport { credentialLogger } from \"../../util/logging\";\nimport { IdentityClient } from \"../../client/identityClient\";\nimport { msiGenericGetToken } from \"./utils\";\nimport { azureArcAPIVersion } from \"./constants\";\nimport { AuthenticationError } from \"../../client/errors\";\nimport { readFile } from \"fs\";\n\nconst logger = credentialLogger(\"ManagedIdentityCredential - ArcMSI\");\n\n// Azure Arc MSI doesn't have a special expiresIn parser.\nconst expiresInParser = undefined;\n\nfunction prepareRequestOptions(resource?: string): RequestPrepareOptions {\n const queryParameters: any = {\n resource,\n \"api-version\": azureArcAPIVersion\n };\n\n return {\n // Should be similar to: http://localhost:40342/metadata/identity/oauth2/token\n url: process.env.IDENTITY_ENDPOINT,\n method: \"GET\",\n queryParameters,\n headers: {\n Accept: \"application/json\",\n Metadata: true\n }\n };\n}\n\n// Since \"fs\"'s readFileSync locks the thread, and to avoid extra dependencies.\nfunction readFileAsync(path: string, options: { encoding: string }): Promise<string> {\n return new Promise((resolve, reject) =>\n readFile(path, options, (err, data) => {\n if (err) {\n reject(err);\n }\n resolve(data);\n })\n );\n}\n\nasync function filePathRequest(\n identityClient: IdentityClient,\n requestPrepareOptions: RequestPrepareOptions\n): Promise<string | undefined> {\n const response = await identityClient.sendRequest(\n identityClient.createWebResource(requestPrepareOptions)\n );\n\n if (response.status !== 401) {\n let message = \"\";\n if (response.bodyAsText) {\n message = ` Response: ${response.bodyAsText}`;\n }\n throw new AuthenticationError(\n response.status,\n `To authenticate with Azure Arc MSI, status code 401 is expected on the first request.${message}`\n );\n }\n\n const authHeader = response.headers.get(\"www-authenticate\") || \"\";\n return authHeader.split(\"=\").slice(1)[0];\n}\n\nexport const arcMsi: MSI = {\n async isAvailable(): Promise<boolean> {\n return Boolean(process.env.IMDS_ENDPOINT && process.env.IDENTITY_ENDPOINT);\n },\n async getToken(\n identityClient: IdentityClient,\n resource?: string,\n clientId?: string,\n getTokenOptions: GetTokenOptions = {}\n ): Promise<AccessToken | null> {\n logger.info(`Using the Azure Arc MSI to authenticate.`);\n\n if (clientId) {\n throw new Error(\n \"User assigned identity is not supported by the Azure Arc Managed Identity Endpoint. To authenticate with the system assigned identity omit the client id when constructing the ManagedIdentityCredential, or if authenticating with the DefaultAzureCredential ensure the AZURE_CLIENT_ID environment variable is not set.\"\n );\n }\n\n const requestOptions = {\n disableJsonStringifyOnBody: true,\n deserializationMapper: undefined,\n abortSignal: getTokenOptions.abortSignal,\n spanOptions: getTokenOptions.tracingOptions && getTokenOptions.tracingOptions.spanOptions,\n ...prepareRequestOptions(resource)\n };\n\n const filePath = await filePathRequest(identityClient, requestOptions);\n\n if (!filePath) {\n throw new Error(\"Azure Arc MSI failed to find the token file.\");\n }\n\n const key = await readFileAsync(filePath, { encoding: \"utf-8\" });\n requestOptions.headers![\"Authorization\"] = `Basic ${key}`;\n\n return msiGenericGetToken(identityClient, requestOptions, expiresInParser, getTokenOptions);\n }\n};\n"]}
@@ -0,0 +1,41 @@
1
+ // Copyright (c) Microsoft Corporation.
2
+ // Licensed under the MIT license.
3
+ import { __awaiter } from "tslib";
4
+ import qs from "qs";
5
+ import { credentialLogger } from "../../util/logging";
6
+ import { msiGenericGetToken } from "./utils";
7
+ const logger = credentialLogger("ManagedIdentityCredential - CloudShellMSI");
8
+ // Cloud Shell MSI doesn't have a special expiresIn parser.
9
+ const expiresInParser = undefined;
10
+ function prepareRequestOptions(resource, clientId) {
11
+ const body = {
12
+ resource
13
+ };
14
+ if (clientId) {
15
+ body.client_id = clientId;
16
+ }
17
+ return {
18
+ url: process.env.MSI_ENDPOINT,
19
+ method: "POST",
20
+ body: qs.stringify(body),
21
+ headers: {
22
+ Accept: "application/json",
23
+ Metadata: true,
24
+ "Content-Type": "application/x-www-form-urlencoded"
25
+ }
26
+ };
27
+ }
28
+ export const cloudShellMsi = {
29
+ isAvailable() {
30
+ return __awaiter(this, void 0, void 0, function* () {
31
+ return Boolean(process.env.MSI_ENDPOINT);
32
+ });
33
+ },
34
+ getToken(identityClient, resource, clientId, getTokenOptions = {}) {
35
+ return __awaiter(this, void 0, void 0, function* () {
36
+ logger.info(`Using the endpoint coming form the environment variable MSI_ENDPOINT=${process.env.MSI_ENDPOINT}, and using the Cloud Shell to proceed with the authentication.`);
37
+ return msiGenericGetToken(identityClient, prepareRequestOptions(resource, clientId), expiresInParser, getTokenOptions);
38
+ });
39
+ }
40
+ };
41
+ //# sourceMappingURL=cloudShellMsi.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cloudShellMsi.js","sourceRoot":"","sources":["../../../../src/credentials/managedIdentityCredential/cloudShellMsi.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,kCAAkC;;AAElC,OAAO,EAAE,MAAM,IAAI,CAAC;AAGpB,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAEtD,OAAO,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC;AAE7C,MAAM,MAAM,GAAG,gBAAgB,CAAC,2CAA2C,CAAC,CAAC;AAE7E,2DAA2D;AAC3D,MAAM,eAAe,GAAG,SAAS,CAAC;AAElC,SAAS,qBAAqB,CAAC,QAAgB,EAAE,QAAiB;IAChE,MAAM,IAAI,GAAQ;QAChB,QAAQ;KACT,CAAC;IAEF,IAAI,QAAQ,EAAE;QACZ,IAAI,CAAC,SAAS,GAAG,QAAQ,CAAC;KAC3B;IAED,OAAO;QACL,GAAG,EAAE,OAAO,CAAC,GAAG,CAAC,YAAY;QAC7B,MAAM,EAAE,MAAM;QACd,IAAI,EAAE,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC;QACxB,OAAO,EAAE;YACP,MAAM,EAAE,kBAAkB;YAC1B,QAAQ,EAAE,IAAI;YACd,cAAc,EAAE,mCAAmC;SACpD;KACF,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,MAAM,aAAa,GAAQ;IAC1B,WAAW;;YACf,OAAO,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;QAC3C,CAAC;KAAA;IACK,QAAQ,CACZ,cAA8B,EAC9B,QAAgB,EAChB,QAAiB,EACjB,kBAAmC,EAAE;;YAErC,MAAM,CAAC,IAAI,CACT,wEAAwE,OAAO,CAAC,GAAG,CAAC,YAAY,iEAAiE,CAClK,CAAC;YAEF,OAAO,kBAAkB,CACvB,cAAc,EACd,qBAAqB,CAAC,QAAQ,EAAE,QAAQ,CAAC,EACzC,eAAe,EACf,eAAe,CAChB,CAAC;QACJ,CAAC;KAAA;CACF,CAAC","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\nimport qs from \"qs\";\nimport { AccessToken, GetTokenOptions, RequestPrepareOptions } from \"@azure/core-http\";\nimport { MSI } from \"./models\";\nimport { credentialLogger } from \"../../util/logging\";\nimport { IdentityClient } from \"../../client/identityClient\";\nimport { msiGenericGetToken } from \"./utils\";\n\nconst logger = credentialLogger(\"ManagedIdentityCredential - CloudShellMSI\");\n\n// Cloud Shell MSI doesn't have a special expiresIn parser.\nconst expiresInParser = undefined;\n\nfunction prepareRequestOptions(resource: string, clientId?: string): RequestPrepareOptions {\n const body: any = {\n resource\n };\n\n if (clientId) {\n body.client_id = clientId;\n }\n\n return {\n url: process.env.MSI_ENDPOINT,\n method: \"POST\",\n body: qs.stringify(body),\n headers: {\n Accept: \"application/json\",\n Metadata: true,\n \"Content-Type\": \"application/x-www-form-urlencoded\"\n }\n };\n}\n\nexport const cloudShellMsi: MSI = {\n async isAvailable(): Promise<boolean> {\n return Boolean(process.env.MSI_ENDPOINT);\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 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 return msiGenericGetToken(\n identityClient,\n prepareRequestOptions(resource, clientId),\n expiresInParser,\n getTokenOptions\n );\n }\n};\n"]}
@@ -0,0 +1,8 @@
1
+ // Copyright (c) Microsoft Corporation.
2
+ // Licensed under the MIT license.
3
+ export const DefaultScopeSuffix = "/.default";
4
+ export const imdsEndpoint = "http://169.254.169.254/metadata/identity/oauth2/token";
5
+ export const imdsApiVersion = "2018-02-01";
6
+ export const azureArcAPIVersion = "2019-11-01";
7
+ export const azureFabricVersion = "2019-07-01-preview";
8
+ //# sourceMappingURL=constants.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.js","sourceRoot":"","sources":["../../../../src/credentials/managedIdentityCredential/constants.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,kCAAkC;AAElC,MAAM,CAAC,MAAM,kBAAkB,GAAG,WAAW,CAAC;AAE9C,MAAM,CAAC,MAAM,YAAY,GAAG,uDAAuD,CAAC;AACpF,MAAM,CAAC,MAAM,cAAc,GAAG,YAAY,CAAC;AAC3C,MAAM,CAAC,MAAM,kBAAkB,GAAG,YAAY,CAAC;AAC/C,MAAM,CAAC,MAAM,kBAAkB,GAAG,oBAAoB,CAAC","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\nexport const DefaultScopeSuffix = \"/.default\";\n\nexport const imdsEndpoint = \"http://169.254.169.254/metadata/identity/oauth2/token\";\nexport const imdsApiVersion = \"2018-02-01\";\nexport const azureArcAPIVersion = \"2019-11-01\";\nexport const azureFabricVersion = \"2019-07-01-preview\";\n"]}
@@ -0,0 +1,59 @@
1
+ // Copyright (c) Microsoft Corporation.
2
+ // Licensed under the MIT license.
3
+ import { __awaiter } from "tslib";
4
+ import { credentialLogger } from "../../util/logging";
5
+ import { msiGenericGetToken } from "./utils";
6
+ import { azureFabricVersion } from "./constants";
7
+ const logger = credentialLogger("ManagedIdentityCredential - Fabric MSI");
8
+ function expiresInParser(requestBody) {
9
+ // Parses a string representation of the seconds since epoch into a number value
10
+ return Number(requestBody.expires_on);
11
+ }
12
+ function prepareRequestOptions(resource, clientId) {
13
+ const queryParameters = {
14
+ resource,
15
+ "api-version": azureFabricVersion
16
+ };
17
+ if (clientId) {
18
+ queryParameters.client_id = clientId;
19
+ }
20
+ return {
21
+ url: process.env.IDENTITY_ENDPOINT,
22
+ method: "GET",
23
+ queryParameters,
24
+ headers: {
25
+ Accept: "application/json",
26
+ Secret: process.env.IDENTITY_HEADER
27
+ }
28
+ };
29
+ }
30
+ // This credential can be easily tested by deploying a container to Azure Service Fabric with the Dockerfile:
31
+ //
32
+ // FROM node:12
33
+ // RUN wget https://host.any/path/bash.sh
34
+ // CMD ["bash", "bash.sh"]
35
+ //
36
+ // Where the bash script contains:
37
+ //
38
+ // curl --insecure $IDENTITY_ENDPOINT'?api-version=2019-07-01-preview&resource=https://vault.azure.net/' -H "Secret: $IDENTITY_HEADER"
39
+ //
40
+ export const fabricMsi = {
41
+ isAvailable() {
42
+ return __awaiter(this, void 0, void 0, function* () {
43
+ const env = process.env;
44
+ return Boolean(env.IDENTITY_ENDPOINT && env.IDENTITY_HEADER && env.IDENTITY_SERVER_THUMBPRINT);
45
+ });
46
+ },
47
+ getToken(identityClient, resource, clientId, getTokenOptions = {}) {
48
+ return __awaiter(this, void 0, void 0, function* () {
49
+ logger.info([
50
+ "Using the endpoint and the secret coming from the environment variables:",
51
+ `IDENTITY_ENDPOINT=${process.env.IDENTITY_ENDPOINT},`,
52
+ "IDENTITY_HEADER=[REDACTED] and",
53
+ "IDENTITY_SERVER_THUMBPRINT=[REDACTED]."
54
+ ].join(" "));
55
+ return msiGenericGetToken(identityClient, prepareRequestOptions(resource, clientId), expiresInParser, getTokenOptions);
56
+ });
57
+ }
58
+ };
59
+ //# sourceMappingURL=fabricMsi.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fabricMsi.js","sourceRoot":"","sources":["../../../../src/credentials/managedIdentityCredential/fabricMsi.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,kCAAkC;;AAIlC,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAEtD,OAAO,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC;AAC7C,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAEjD,MAAM,MAAM,GAAG,gBAAgB,CAAC,wCAAwC,CAAC,CAAC;AAE1E,SAAS,eAAe,CAAC,WAAgB;IACvC,gFAAgF;IAChF,OAAO,MAAM,CAAC,WAAW,CAAC,UAAU,CAAC,CAAC;AACxC,CAAC;AAED,SAAS,qBAAqB,CAAC,QAAgB,EAAE,QAAiB;IAChE,MAAM,eAAe,GAAQ;QAC3B,QAAQ;QACR,aAAa,EAAE,kBAAkB;KAClC,CAAC;IAEF,IAAI,QAAQ,EAAE;QACZ,eAAe,CAAC,SAAS,GAAG,QAAQ,CAAC;KACtC;IAED,OAAO;QACL,GAAG,EAAE,OAAO,CAAC,GAAG,CAAC,iBAAiB;QAClC,MAAM,EAAE,KAAK;QACb,eAAe;QACf,OAAO,EAAE;YACP,MAAM,EAAE,kBAAkB;YAC1B,MAAM,EAAE,OAAO,CAAC,GAAG,CAAC,eAAe;SACpC;KACF,CAAC;AACJ,CAAC;AAED,6GAA6G;AAC7G,EAAE;AACF,iBAAiB;AACjB,2CAA2C;AAC3C,4BAA4B;AAC5B,EAAE;AACF,kCAAkC;AAClC,EAAE;AACF,wIAAwI;AACxI,EAAE;AAEF,MAAM,CAAC,MAAM,SAAS,GAAQ;IACtB,WAAW;;YACf,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC;YACxB,OAAO,OAAO,CAAC,GAAG,CAAC,iBAAiB,IAAI,GAAG,CAAC,eAAe,IAAI,GAAG,CAAC,0BAA0B,CAAC,CAAC;QACjG,CAAC;KAAA;IACK,QAAQ,CACZ,cAA8B,EAC9B,QAAgB,EAChB,QAAiB,EACjB,kBAAmC,EAAE;;YAErC,MAAM,CAAC,IAAI,CACT;gBACE,0EAA0E;gBAC1E,qBAAqB,OAAO,CAAC,GAAG,CAAC,iBAAiB,GAAG;gBACrD,gCAAgC;gBAChC,wCAAwC;aACzC,CAAC,IAAI,CAAC,GAAG,CAAC,CACZ,CAAC;YAEF,OAAO,kBAAkB,CACvB,cAAc,EACd,qBAAqB,CAAC,QAAQ,EAAE,QAAQ,CAAC,EACzC,eAAe,EACf,eAAe,CAChB,CAAC;QACJ,CAAC;KAAA;CACF,CAAC","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\nimport { AccessToken, GetTokenOptions, RequestPrepareOptions } from \"@azure/core-http\";\nimport { MSI } from \"./models\";\nimport { credentialLogger } from \"../../util/logging\";\nimport { IdentityClient } from \"../../client/identityClient\";\nimport { msiGenericGetToken } from \"./utils\";\nimport { azureFabricVersion } from \"./constants\";\n\nconst logger = credentialLogger(\"ManagedIdentityCredential - Fabric MSI\");\n\nfunction expiresInParser(requestBody: any): number {\n // Parses a string representation of the seconds since epoch into a number value\n return Number(requestBody.expires_on);\n}\n\nfunction prepareRequestOptions(resource: string, clientId?: string): RequestPrepareOptions {\n const queryParameters: any = {\n resource,\n \"api-version\": azureFabricVersion\n };\n\n if (clientId) {\n queryParameters.client_id = clientId;\n }\n\n return {\n url: process.env.IDENTITY_ENDPOINT,\n method: \"GET\",\n queryParameters,\n headers: {\n Accept: \"application/json\",\n Secret: process.env.IDENTITY_HEADER\n }\n };\n}\n\n// This credential can be easily tested by deploying a container to Azure Service Fabric with the Dockerfile:\n//\n// FROM node:12\n// RUN wget https://host.any/path/bash.sh\n// CMD [\"bash\", \"bash.sh\"]\n//\n// Where the bash script contains:\n//\n// curl --insecure $IDENTITY_ENDPOINT'?api-version=2019-07-01-preview&resource=https://vault.azure.net/' -H \"Secret: $IDENTITY_HEADER\"\n//\n\nexport const fabricMsi: MSI = {\n async isAvailable(): Promise<boolean> {\n const env = process.env;\n return Boolean(env.IDENTITY_ENDPOINT && env.IDENTITY_HEADER && env.IDENTITY_SERVER_THUMBPRINT);\n },\n async getToken(\n identityClient: IdentityClient,\n resource: string,\n clientId?: string,\n getTokenOptions: GetTokenOptions = {}\n ): Promise<AccessToken | null> {\n logger.info(\n [\n \"Using the endpoint and the secret coming from the environment variables:\",\n `IDENTITY_ENDPOINT=${process.env.IDENTITY_ENDPOINT},`,\n \"IDENTITY_HEADER=[REDACTED] and\",\n \"IDENTITY_SERVER_THUMBPRINT=[REDACTED].\"\n ].join(\" \")\n );\n\n return msiGenericGetToken(\n identityClient,\n prepareRequestOptions(resource, clientId),\n expiresInParser,\n getTokenOptions\n );\n }\n};\n"]}
@@ -0,0 +1,109 @@
1
+ // Copyright (c) Microsoft Corporation.
2
+ // Licensed under the MIT license.
3
+ import { __awaiter } from "tslib";
4
+ import { RestError } from "@azure/core-http";
5
+ import { CanonicalCode } from "@opentelemetry/api";
6
+ import { credentialLogger } from "../../util/logging";
7
+ import { createSpan } from "../../util/tracing";
8
+ import { imdsApiVersion, imdsEndpoint } from "./constants";
9
+ import { msiGenericGetToken } from "./utils";
10
+ const logger = credentialLogger("ManagedIdentityCredential - IMDS");
11
+ function expiresInParser(requestBody) {
12
+ if (requestBody.expires_on) {
13
+ // Use the expires_on timestamp if it's available
14
+ const expires = +requestBody.expires_on * 1000;
15
+ logger.info(`IMDS using expires_on: ${expires} (original value: ${requestBody.expires_on})`);
16
+ return expires;
17
+ }
18
+ else {
19
+ // If these aren't possible, use expires_in and calculate a timestamp
20
+ const expires = Date.now() + requestBody.expires_in * 1000;
21
+ logger.info(`IMDS using expires_in: ${expires} (original value: ${requestBody.expires_in})`);
22
+ return expires;
23
+ }
24
+ }
25
+ function prepareRequestOptions(resource, clientId) {
26
+ const queryParameters = {
27
+ resource,
28
+ "api-version": imdsApiVersion
29
+ };
30
+ if (clientId) {
31
+ queryParameters.client_id = clientId;
32
+ }
33
+ return {
34
+ url: imdsEndpoint,
35
+ method: "GET",
36
+ queryParameters,
37
+ headers: {
38
+ Accept: "application/json",
39
+ Metadata: true
40
+ }
41
+ };
42
+ }
43
+ export const imdsMsi = {
44
+ isAvailable(identityClient, resource, clientId, getTokenOptions) {
45
+ return __awaiter(this, void 0, void 0, function* () {
46
+ const { span, options } = createSpan("ManagedIdentityCredential-pingImdsEndpoint", getTokenOptions);
47
+ const request = prepareRequestOptions(resource, clientId);
48
+ // This will always be populated, but let's make TypeScript happy
49
+ if (request.headers) {
50
+ // Remove the Metadata header to invoke a request error from
51
+ // IMDS endpoint
52
+ delete request.headers.Metadata;
53
+ }
54
+ request.spanOptions = options.tracingOptions && options.tracingOptions.spanOptions;
55
+ try {
56
+ // Create a request with a timeout since we expect that
57
+ // not having a "Metadata" header should cause an error to be
58
+ // returned quickly from the endpoint, proving its availability.
59
+ const webResource = identityClient.createWebResource(request);
60
+ webResource.timeout = (options.requestOptions && options.requestOptions.timeout) || 500;
61
+ try {
62
+ logger.info(`Pinging IMDS endpoint`);
63
+ yield identityClient.sendRequest(webResource);
64
+ }
65
+ catch (err) {
66
+ if ((err instanceof RestError && err.code === RestError.REQUEST_SEND_ERROR) ||
67
+ err.name === "AbortError" ||
68
+ err.code === "ECONNREFUSED" || // connection refused
69
+ err.code === "EHOSTDOWN" // host is down
70
+ ) {
71
+ // If the request failed, or NodeJS was unable to establish a connection,
72
+ // or the host was down, we'll assume the IMDS endpoint isn't available.
73
+ logger.info(`IMDS endpoint unavailable`);
74
+ span.setStatus({
75
+ code: CanonicalCode.UNAVAILABLE,
76
+ message: err.message
77
+ });
78
+ // IMDS MSI unavailable.
79
+ return false;
80
+ }
81
+ }
82
+ // If we received any response, the endpoint is available
83
+ logger.info(`IMDS endpoint is available`);
84
+ // IMDS MSI available!
85
+ return true;
86
+ }
87
+ catch (err) {
88
+ // createWebResource failed.
89
+ // This error should bubble up to the user.
90
+ logger.info(`Error when creating the WebResource for the IMDS endpoint: ${err.message}`);
91
+ span.setStatus({
92
+ code: CanonicalCode.UNKNOWN,
93
+ message: err.message
94
+ });
95
+ throw err;
96
+ }
97
+ finally {
98
+ span.end();
99
+ }
100
+ });
101
+ },
102
+ getToken(identityClient, resource, clientId, getTokenOptions = {}) {
103
+ return __awaiter(this, void 0, void 0, function* () {
104
+ logger.info(`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.`);
105
+ return msiGenericGetToken(identityClient, prepareRequestOptions(resource, clientId), expiresInParser, getTokenOptions);
106
+ });
107
+ }
108
+ };
109
+ //# sourceMappingURL=imdsMsi.js.map