@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.
- package/CHANGELOG.md +24 -2
- package/README.md +75 -55
- package/dist/index.js +533 -396
- package/dist/index.js.map +1 -1
- package/dist-esm/src/client/msalClient.js +138 -0
- package/dist-esm/src/client/msalClient.js.map +1 -0
- package/dist-esm/src/credentials/authorizationCodeCredential.browser.js +2 -2
- package/dist-esm/src/credentials/authorizationCodeCredential.browser.js.map +1 -1
- package/dist-esm/src/credentials/authorizationCodeCredential.js +3 -1
- package/dist-esm/src/credentials/authorizationCodeCredential.js.map +1 -1
- package/dist-esm/src/credentials/azureCliCredential.browser.js +2 -2
- package/dist-esm/src/credentials/azureCliCredential.browser.js.map +1 -1
- package/dist-esm/src/credentials/azureCliCredential.js +5 -5
- package/dist-esm/src/credentials/azureCliCredential.js.map +1 -1
- package/dist-esm/src/credentials/chainedTokenCredential.js +2 -2
- package/dist-esm/src/credentials/chainedTokenCredential.js.map +1 -1
- package/dist-esm/src/credentials/clientCertificateCredential.browser.js +2 -2
- package/dist-esm/src/credentials/clientCertificateCredential.browser.js.map +1 -1
- package/dist-esm/src/credentials/clientCertificateCredential.js +5 -3
- 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.js +2 -2
- package/dist-esm/src/credentials/clientSecretCredential.js.map +1 -1
- package/dist-esm/src/credentials/deviceCodeCredential.browser.js +2 -2
- package/dist-esm/src/credentials/deviceCodeCredential.browser.js.map +1 -1
- package/dist-esm/src/credentials/deviceCodeCredential.js +53 -47
- package/dist-esm/src/credentials/deviceCodeCredential.js.map +1 -1
- package/dist-esm/src/credentials/environmentCredential.browser.js +2 -2
- package/dist-esm/src/credentials/environmentCredential.browser.js.map +1 -1
- package/dist-esm/src/credentials/environmentCredential.js +6 -2
- package/dist-esm/src/credentials/environmentCredential.js.map +1 -1
- package/dist-esm/src/credentials/interactiveBrowserCredential.browser.js +7 -5
- package/dist-esm/src/credentials/interactiveBrowserCredential.browser.js.map +1 -1
- package/dist-esm/src/credentials/interactiveBrowserCredential.js +30 -69
- 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 +44 -0
- package/dist-esm/src/credentials/managedIdentityCredential/appServiceMsi2017.js.map +1 -0
- package/dist-esm/src/credentials/managedIdentityCredential/arcMsi.js +74 -0
- package/dist-esm/src/credentials/managedIdentityCredential/arcMsi.js.map +1 -0
- package/dist-esm/src/credentials/managedIdentityCredential/cloudShellMsi.js +41 -0
- package/dist-esm/src/credentials/managedIdentityCredential/cloudShellMsi.js.map +1 -0
- package/dist-esm/src/credentials/managedIdentityCredential/constants.js +8 -0
- package/dist-esm/src/credentials/managedIdentityCredential/constants.js.map +1 -0
- package/dist-esm/src/credentials/managedIdentityCredential/fabricMsi.js +59 -0
- package/dist-esm/src/credentials/managedIdentityCredential/fabricMsi.js.map +1 -0
- package/dist-esm/src/credentials/managedIdentityCredential/imdsMsi.js +109 -0
- package/dist-esm/src/credentials/managedIdentityCredential/imdsMsi.js.map +1 -0
- package/dist-esm/src/credentials/{managedIdentityCredential.browser.js → managedIdentityCredential/index.browser.js} +4 -4
- package/dist-esm/src/credentials/managedIdentityCredential/index.browser.js.map +1 -0
- package/dist-esm/src/credentials/managedIdentityCredential/index.js +165 -0
- package/dist-esm/src/credentials/managedIdentityCredential/index.js.map +1 -0
- package/dist-esm/src/credentials/managedIdentityCredential/models.js +3 -0
- package/dist-esm/src/credentials/managedIdentityCredential/models.js.map +1 -0
- package/dist-esm/src/credentials/managedIdentityCredential/utils.js +28 -0
- package/dist-esm/src/credentials/managedIdentityCredential/utils.js.map +1 -0
- package/dist-esm/src/credentials/usernamePasswordCredential.js +3 -1
- package/dist-esm/src/credentials/usernamePasswordCredential.js.map +1 -1
- package/dist-esm/src/credentials/visualStudioCodeCredential.browser.js +2 -2
- package/dist-esm/src/credentials/visualStudioCodeCredential.browser.js.map +1 -1
- package/dist-esm/src/credentials/visualStudioCodeCredential.js +19 -8
- package/dist-esm/src/credentials/visualStudioCodeCredential.js.map +1 -1
- package/dist-esm/src/index.js.map +1 -1
- package/dist-esm/src/util/checkTenantId.js +11 -0
- package/dist-esm/src/util/checkTenantId.js.map +1 -0
- package/dist-esm/src/util/logging.js +7 -3
- package/dist-esm/src/util/logging.js.map +1 -1
- package/package.json +7 -5
- package/types/identity.d.ts +9 -33
- package/dist-esm/src/credentials/managedIdentityCredential.browser.js.map +0 -1
- package/dist-esm/src/credentials/managedIdentityCredential.js +0 -376
- package/dist-esm/src/credentials/managedIdentityCredential.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"logging.js","sourceRoot":"","sources":["../../../src/util/logging.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,kCAAkC;AAElC,OAAO,EAAE,kBAAkB,EAAe,MAAM,eAAe,CAAC;AAEhE;;GAEG;AACH,MAAM,CAAC,MAAM,MAAM,GAAG,kBAAkB,CAAC,UAAU,CAAC,CAAC;AAOrD;;;GAGG;AACH,MAAM,UAAU,cAAc,CAAC,gBAA0B;IACvD,OAAO,gBAAgB,CAAC,MAAM,CAC5B,CAAC,GAA2B,EAAE,WAAmB,EAAE,EAAE;QACnD,IAAI,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,EAAE;YAC5B,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;SAChC;aAAM;YACL,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;SAC/B;QACD,OAAO,GAAG,CAAC;IACb,CAAC,EACD,EAAE,OAAO,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,CAC9B,CAAC;AACJ,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,UAAU,CAAC,cAAsB,EAAE,gBAA0B;IAC3E,MAAM,EAAE,QAAQ,EAAE,GAAG,cAAc,CAAC,gBAAgB,CAAC,CAAC;IACtD,MAAM,CAAC,IAAI,CACT,GAAG,cAAc,kDAAkD,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CACzF,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,aAAa,CAAC,KAAwB;IACpD,OAAO,
|
|
1
|
+
{"version":3,"file":"logging.js","sourceRoot":"","sources":["../../../src/util/logging.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,kCAAkC;AAElC,OAAO,EAAE,kBAAkB,EAAe,MAAM,eAAe,CAAC;AAEhE;;GAEG;AACH,MAAM,CAAC,MAAM,MAAM,GAAG,kBAAkB,CAAC,UAAU,CAAC,CAAC;AAOrD;;;GAGG;AACH,MAAM,UAAU,cAAc,CAAC,gBAA0B;IACvD,OAAO,gBAAgB,CAAC,MAAM,CAC5B,CAAC,GAA2B,EAAE,WAAmB,EAAE,EAAE;QACnD,IAAI,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,EAAE;YAC5B,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;SAChC;aAAM;YACL,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;SAC/B;QACD,OAAO,GAAG,CAAC;IACb,CAAC,EACD,EAAE,OAAO,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,CAC9B,CAAC;AACJ,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,UAAU,CAAC,cAAsB,EAAE,gBAA0B;IAC3E,MAAM,EAAE,QAAQ,EAAE,GAAG,cAAc,CAAC,gBAAgB,CAAC,CAAC;IACtD,MAAM,CAAC,IAAI,CACT,GAAG,cAAc,kDAAkD,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CACzF,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,aAAa,CAAC,KAAwB;IACpD,OAAO,oBAAoB,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC;AAChF,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,WAAW,CAAC,KAAoC,EAAE,KAAqB;IACrF,IAAI,OAAO,GAAG,QAAQ,CAAC;IACvB,IAAI,KAAK,aAAL,KAAK,uBAAL,KAAK,CAAE,MAAM,EAAE;QACjB,OAAO,IAAI,YAAY,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC;KAC3E;IACD,OAAO,GAAG,OAAO,mBAAmB,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,GAAG,CAAC;AAC3F,CAAC;AAkBD;;;;;;;GAOG;AACH,MAAM,UAAU,wBAAwB,CACtC,KAAa,EACb,MAAiC,EACjC,MAAmB,MAAM;IAEzB,MAAM,SAAS,GAAG,MAAM,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,SAAS,IAAI,KAAK,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC;IAElE,SAAS,IAAI,CAAC,OAAe;QAC3B,GAAG,CAAC,IAAI,CAAC,GAAG,SAAS,KAAK,EAAE,OAAO,CAAC,CAAC;IACvC,CAAC;IAED,OAAO;QACL,KAAK;QACL,SAAS;QACT,IAAI;KACL,CAAC;AACJ,CAAC;AAUD;;;;;;;;;GASG;AACH,MAAM,UAAU,gBAAgB,CAAC,KAAa,EAAE,MAAmB,MAAM;IACvE,MAAM,MAAM,GAAG,wBAAwB,CAAC,KAAK,EAAE,SAAS,EAAE,GAAG,CAAC,CAAC;IAC/D,uCACK,MAAM,KACT,QAAQ,EAAE,wBAAwB,CAAC,eAAe,EAAE,MAAM,EAAE,GAAG,CAAC,IAChE;AACJ,CAAC","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\nimport { createClientLogger, AzureLogger } from \"@azure/logger\";\n\n/**\n * The AzureLogger used for all clients within the identity package\n */\nexport const logger = createClientLogger(\"identity\");\n\ninterface EnvironmentAccumulator {\n missing: string[];\n assigned: string[];\n}\n\n/**\n * Separates a list of environment variable names into a plain object with two arrays: an array of missing environment variables and another array with assigned environment variables.\n * @param supportedEnvVars List of environment variable names\n */\nexport function processEnvVars(supportedEnvVars: string[]): EnvironmentAccumulator {\n return supportedEnvVars.reduce(\n (acc: EnvironmentAccumulator, envVariable: string) => {\n if (process.env[envVariable]) {\n acc.assigned.push(envVariable);\n } else {\n acc.missing.push(envVariable);\n }\n return acc;\n },\n { missing: [], assigned: [] }\n );\n}\n\n/**\n * Based on a given list of environment variable names,\n * logs the environment variables currently assigned during the usage of a credential that goes by the given name.\n * @param credentialName Name of the credential in use\n * @param supportedEnvVars List of environment variables supported by that credential\n */\nexport function logEnvVars(credentialName: string, supportedEnvVars: string[]): void {\n const { assigned } = processEnvVars(supportedEnvVars);\n logger.info(\n `${credentialName} => Found the following environment variables: ${assigned.join(\", \")}`\n );\n}\n\n/**\n * Formatting the success event on the credentials\n */\nexport function formatSuccess(scope: string | string[]): string {\n return `SUCCESS. Scopes: ${Array.isArray(scope) ? scope.join(\", \") : scope}.`;\n}\n\n/**\n * Formatting the success event on the credentials\n */\nexport function formatError(scope: string | string[] | undefined, error: Error | string): string {\n let message = \"ERROR.\";\n if (scope?.length) {\n message += ` Scopes: ${Array.isArray(scope) ? scope.join(\", \") : scope}.`;\n }\n return `${message} Error message: ${typeof error === \"string\" ? error : error.message}.`;\n}\n\n/**\n * A CredentialLoggerInstance is a logger properly formatted to work in a credential's constructor, and its methods.\n */\nexport interface CredentialLoggerInstance {\n title: string;\n fullTitle: string;\n info(message: string): void;\n /**\n * The logging functions for warning and error are intentionally left out, since we want the identity logging to be at the info level.\n * Otherwise, they would look like:\n *\n * warning(message: string): void;\n * error(err: Error): void;\n */\n}\n\n/**\n * Generates a CredentialLoggerInstance.\n *\n * It logs with the format:\n *\n * [title] => [message]\n *\n */\nexport function credentialLoggerInstance(\n title: string,\n parent?: CredentialLoggerInstance,\n log: AzureLogger = logger\n): CredentialLoggerInstance {\n const fullTitle = parent ? `${parent.fullTitle} ${title}` : title;\n\n function info(message: string): void {\n log.info(`${fullTitle} =>`, message);\n }\n\n return {\n title,\n fullTitle,\n info\n };\n}\n\n/**\n * A CredentialLogger is a logger declared at the credential's constructor, and used at any point in the credential.\n * It has all the properties of a CredentialLoggerInstance, plus other logger instances, one per method.\n */\nexport interface CredentialLogger extends CredentialLoggerInstance {\n getToken: CredentialLoggerInstance;\n}\n\n/**\n * Generates a CredentialLogger, which is a logger declared at the credential's constructor, and used at any point in the credential.\n * It has all the properties of a CredentialLoggerInstance, plus other logger instances, one per method.\n *\n * It logs with the format:\n *\n * [title] => [message]\n * [title] => getToken() => [message]\n *\n */\nexport function credentialLogger(title: string, log: AzureLogger = logger): CredentialLogger {\n const logger = credentialLoggerInstance(title, undefined, log);\n return {\n ...logger,\n getToken: credentialLoggerInstance(\"=> getToken()\", logger, log)\n };\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@azure/identity",
|
|
3
3
|
"sdk-type": "client",
|
|
4
|
-
"version": "1.2.0
|
|
4
|
+
"version": "1.2.0",
|
|
5
5
|
"description": "Provides credential implementations for Azure SDK libraries that can authenticate with Azure Active Directory",
|
|
6
6
|
"main": "dist/index.js",
|
|
7
7
|
"module": "dist-esm/src/index.js",
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
"browser": {
|
|
10
10
|
"./dist-esm/src/credentials/azureCliCredential.js": "./dist-esm/src/credentials/azureCliCredential.browser.js",
|
|
11
11
|
"./dist-esm/src/credentials/environmentCredential.js": "./dist-esm/src/credentials/environmentCredential.browser.js",
|
|
12
|
-
"./dist-esm/src/credentials/managedIdentityCredential.js": "./dist-esm/src/credentials/managedIdentityCredential.browser.js",
|
|
12
|
+
"./dist-esm/src/credentials/managedIdentityCredential/index.js": "./dist-esm/src/credentials/managedIdentityCredential/index.browser.js",
|
|
13
13
|
"./dist-esm/src/credentials/clientCertificateCredential.js": "./dist-esm/src/credentials/clientCertificateCredential.browser.js",
|
|
14
14
|
"./dist-esm/src/credentials/deviceCodeCredential.js": "./dist-esm/src/credentials/deviceCodeCredential.browser.js",
|
|
15
15
|
"./dist-esm/src/credentials/defaultAzureCredential.js": "./dist-esm/src/credentials/defaultAzureCredential.browser.js",
|
|
@@ -79,11 +79,12 @@
|
|
|
79
79
|
"homepage": "https://github.com/Azure/azure-sdk-for-js/tree/master/sdk/identity/identity/README.md",
|
|
80
80
|
"sideEffects": false,
|
|
81
81
|
"dependencies": {
|
|
82
|
-
"@azure/core-http": "^1.
|
|
82
|
+
"@azure/core-http": "^1.2.0",
|
|
83
83
|
"@azure/core-tracing": "1.0.0-preview.9",
|
|
84
84
|
"@azure/logger": "^1.0.0",
|
|
85
|
-
"@azure/msal-node": "^1.0.0-alpha.
|
|
85
|
+
"@azure/msal-node": "^1.0.0-alpha.13",
|
|
86
86
|
"@opentelemetry/api": "^0.10.2",
|
|
87
|
+
"axios": "^0.20.0",
|
|
87
88
|
"events": "^3.0.0",
|
|
88
89
|
"jws": "^4.0.0",
|
|
89
90
|
"msal": "^1.0.2",
|
|
@@ -135,6 +136,7 @@
|
|
|
135
136
|
"typescript": "~3.9.3",
|
|
136
137
|
"util": "^0.12.1",
|
|
137
138
|
"sinon": "^9.0.2",
|
|
138
|
-
"@types/sinon": "^9.0.4"
|
|
139
|
+
"@types/sinon": "^9.0.4",
|
|
140
|
+
"mock-fs": "^4.10.4"
|
|
139
141
|
}
|
|
140
142
|
}
|
package/types/identity.d.ts
CHANGED
|
@@ -293,7 +293,7 @@ export declare interface ClientCertificateCredentialOptions extends TokenCredent
|
|
|
293
293
|
* Option to include x5c header for SubjectName and Issuer name authorization.
|
|
294
294
|
* Set this option to send base64 encoded public certificate in the client assertion header as an x5c claim
|
|
295
295
|
*/
|
|
296
|
-
|
|
296
|
+
sendCertificateChain?: boolean;
|
|
297
297
|
}
|
|
298
298
|
|
|
299
299
|
/**
|
|
@@ -380,23 +380,22 @@ export declare interface DefaultAzureCredentialOptions extends TokenCredentialOp
|
|
|
380
380
|
* that the user can enter into https://microsoft.com/devicelogin.
|
|
381
381
|
*/
|
|
382
382
|
export declare class DeviceCodeCredential implements TokenCredential {
|
|
383
|
-
private pca;
|
|
384
|
-
private tenantId;
|
|
385
|
-
private clientId;
|
|
386
383
|
private userPromptCallback;
|
|
387
|
-
private
|
|
384
|
+
private msalClient;
|
|
388
385
|
/**
|
|
389
386
|
* Creates an instance of DeviceCodeCredential with the details needed
|
|
390
387
|
* to initiate the device code authorization flow with Azure Active Directory.
|
|
391
388
|
*
|
|
392
389
|
* @param tenantId The Azure Active Directory tenant (directory) ID or name.
|
|
390
|
+
* The default value is 'organizations'.
|
|
393
391
|
* 'organizations' may be used when dealing with multi-tenant scenarios.
|
|
394
392
|
* @param clientId The client (application) ID of an App Registration in the tenant.
|
|
393
|
+
* By default we will try to use the Azure CLI's client ID to authenticate.
|
|
395
394
|
* @param userPromptCallback A callback function that will be invoked to show
|
|
396
395
|
{@link DeviceCodeInfo} to the user. If left unassigned, we will automatically log the device code information and the authentication instructions in the console.
|
|
397
396
|
* @param options Options for configuring the client which makes the authentication request.
|
|
398
397
|
*/
|
|
399
|
-
constructor(tenantId
|
|
398
|
+
constructor(tenantId?: string, clientId?: string, userPromptCallback?: DeviceCodePromptCallback, options?: TokenCredentialOptions);
|
|
400
399
|
/**
|
|
401
400
|
* Authenticates with Azure Active Directory and returns an access token if
|
|
402
401
|
* successful. If authentication cannot be performed at this time, this method may
|
|
@@ -523,16 +522,9 @@ export { GetTokenOptions }
|
|
|
523
522
|
* window. This credential is not currently supported in Node.js.
|
|
524
523
|
*/
|
|
525
524
|
export declare class InteractiveBrowserCredential implements TokenCredential {
|
|
526
|
-
private identityClient;
|
|
527
|
-
private pca;
|
|
528
|
-
private msalCacheManager;
|
|
529
|
-
private tenantId;
|
|
530
|
-
private clientId;
|
|
531
|
-
private persistenceEnabled;
|
|
532
525
|
private redirectUri;
|
|
533
|
-
private authorityHost;
|
|
534
|
-
private authenticationRecord;
|
|
535
526
|
private port;
|
|
527
|
+
private msalClient;
|
|
536
528
|
constructor(options?: InteractiveBrowserCredentialOptions);
|
|
537
529
|
/**
|
|
538
530
|
* Authenticates with Azure Active Directory and returns an access token if
|
|
@@ -545,7 +537,6 @@ export declare class InteractiveBrowserCredential implements TokenCredential {
|
|
|
545
537
|
* TokenCredential implementation might make.
|
|
546
538
|
*/
|
|
547
539
|
getToken(scopes: string | string[], _options?: GetTokenOptions): Promise<AccessToken | null>;
|
|
548
|
-
private acquireTokenFromCache;
|
|
549
540
|
private openAuthCodeUrl;
|
|
550
541
|
private acquireTokenFromBrowser;
|
|
551
542
|
}
|
|
@@ -579,19 +570,6 @@ export declare interface InteractiveBrowserCredentialOptions extends TokenCreden
|
|
|
579
570
|
* The client (application) ID of an App Registration in the tenant.
|
|
580
571
|
*/
|
|
581
572
|
clientId?: string;
|
|
582
|
-
/**
|
|
583
|
-
* The cache options to use when credentials are being checked.
|
|
584
|
-
*/
|
|
585
|
-
cacheOptions?: {
|
|
586
|
-
cachePlugin?: {
|
|
587
|
-
readFromStorage: () => Promise<string>;
|
|
588
|
-
writeToStorage: (getMergedState: (oldState: string) => string) => Promise<void>;
|
|
589
|
-
};
|
|
590
|
-
};
|
|
591
|
-
/**
|
|
592
|
-
* The authentication record to use to find existing tokens in the cache
|
|
593
|
-
*/
|
|
594
|
-
authenticationRecord?: AuthenticationRecord;
|
|
595
573
|
}
|
|
596
574
|
|
|
597
575
|
/**
|
|
@@ -626,11 +604,8 @@ export declare class ManagedIdentityCredential implements TokenCredential {
|
|
|
626
604
|
* @param options Options for configuring the client which makes the access token request.
|
|
627
605
|
*/
|
|
628
606
|
constructor(options?: TokenCredentialOptions);
|
|
629
|
-
private
|
|
630
|
-
private
|
|
631
|
-
private createAppServiceMsiAuthRequest;
|
|
632
|
-
private createCloudShellMsiAuthRequest;
|
|
633
|
-
private pingImdsEndpoint;
|
|
607
|
+
private cachedMSI;
|
|
608
|
+
private cachedAvailableMSI;
|
|
634
609
|
private authenticateManagedIdentity;
|
|
635
610
|
/**
|
|
636
611
|
* Authenticates with Azure Active Directory and returns an access token if
|
|
@@ -703,6 +678,7 @@ export declare class UsernamePasswordCredential implements TokenCredential {
|
|
|
703
678
|
export declare class VisualStudioCodeCredential implements TokenCredential {
|
|
704
679
|
private identityClient;
|
|
705
680
|
private tenantId;
|
|
681
|
+
private cloudName;
|
|
706
682
|
/**
|
|
707
683
|
* Creates an instance of VisualStudioCodeCredential to use for automatically authenticating via VSCode.
|
|
708
684
|
*
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"managedIdentityCredential.browser.js","sourceRoot":"","sources":["../../../src/credentials/managedIdentityCredential.browser.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,kCAAkC;;AAIlC,OAAO,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAEhE,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,wBAAwB,CAAC,CAAC,CAAC;QACnD,MAAM,wBAAwB,CAAC;IACjC,CAAC;IAEY,QAAQ;;YACnB,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,wBAAwB,CAAC,CAAC,CAAC;YAC5D,MAAM,wBAAwB,CAAC;QACjC,CAAC;KAAA;CACF","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\nimport { AccessToken, TokenCredential } from \"@azure/core-http\";\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,376 +0,0 @@
|
|
|
1
|
-
// Copyright (c) Microsoft Corporation.
|
|
2
|
-
// Licensed under the MIT license.
|
|
3
|
-
import { __awaiter } from "tslib";
|
|
4
|
-
import qs from "qs";
|
|
5
|
-
import { RestError } from "@azure/core-http";
|
|
6
|
-
import { IdentityClient } from "../client/identityClient";
|
|
7
|
-
import { createSpan } from "../util/tracing";
|
|
8
|
-
import { AuthenticationErrorName, AuthenticationError, CredentialUnavailable } from "../client/errors";
|
|
9
|
-
import { CanonicalCode } from "@opentelemetry/api";
|
|
10
|
-
import { credentialLogger, formatSuccess, formatError } from "../util/logging";
|
|
11
|
-
const DefaultScopeSuffix = "/.default";
|
|
12
|
-
export const ImdsEndpoint = "http://169.254.169.254/metadata/identity/oauth2/token";
|
|
13
|
-
export const ImdsApiVersion = "2018-02-01";
|
|
14
|
-
export const AppServiceMsiApiVersion = "2017-09-01";
|
|
15
|
-
const logger = credentialLogger("ManagedIdentityCredential");
|
|
16
|
-
/**
|
|
17
|
-
* Attempts authentication using a managed identity that has been assigned
|
|
18
|
-
* to the deployment environment. This authentication type works in Azure VMs,
|
|
19
|
-
* App Service and Azure Functions applications, and inside of Azure Cloud Shell.
|
|
20
|
-
*
|
|
21
|
-
* More information about configuring managed identities can be found here:
|
|
22
|
-
*
|
|
23
|
-
* https://docs.microsoft.com/en-us/azure/active-directory/managed-identities-azure-resources/overview
|
|
24
|
-
*/
|
|
25
|
-
export class ManagedIdentityCredential {
|
|
26
|
-
/**
|
|
27
|
-
* @internal
|
|
28
|
-
* @ignore
|
|
29
|
-
*/
|
|
30
|
-
constructor(clientIdOrOptions, options) {
|
|
31
|
-
this.isEndpointUnavailable = null;
|
|
32
|
-
if (typeof clientIdOrOptions === "string") {
|
|
33
|
-
// clientId, options constructor
|
|
34
|
-
this.clientId = clientIdOrOptions;
|
|
35
|
-
this.identityClient = new IdentityClient(options);
|
|
36
|
-
}
|
|
37
|
-
else {
|
|
38
|
-
// options only constructor
|
|
39
|
-
this.identityClient = new IdentityClient(clientIdOrOptions);
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
mapScopesToResource(scopes) {
|
|
43
|
-
let scope = "";
|
|
44
|
-
if (Array.isArray(scopes)) {
|
|
45
|
-
if (scopes.length !== 1) {
|
|
46
|
-
throw new Error("To convert to a resource string the specified array must be exactly length 1");
|
|
47
|
-
}
|
|
48
|
-
scope = scopes[0];
|
|
49
|
-
}
|
|
50
|
-
else if (typeof scopes === "string") {
|
|
51
|
-
scope = scopes;
|
|
52
|
-
}
|
|
53
|
-
if (!scope.endsWith(DefaultScopeSuffix)) {
|
|
54
|
-
return scope;
|
|
55
|
-
}
|
|
56
|
-
return scope.substr(0, scope.lastIndexOf(DefaultScopeSuffix));
|
|
57
|
-
}
|
|
58
|
-
createImdsAuthRequest(resource, clientId) {
|
|
59
|
-
const queryParameters = {
|
|
60
|
-
resource,
|
|
61
|
-
"api-version": ImdsApiVersion
|
|
62
|
-
};
|
|
63
|
-
if (clientId) {
|
|
64
|
-
queryParameters.client_id = clientId;
|
|
65
|
-
}
|
|
66
|
-
return {
|
|
67
|
-
url: ImdsEndpoint,
|
|
68
|
-
method: "GET",
|
|
69
|
-
queryParameters,
|
|
70
|
-
headers: {
|
|
71
|
-
Accept: "application/json",
|
|
72
|
-
Metadata: true
|
|
73
|
-
}
|
|
74
|
-
};
|
|
75
|
-
}
|
|
76
|
-
createAppServiceMsiAuthRequest(resource, clientId, version) {
|
|
77
|
-
const queryParameters = {
|
|
78
|
-
resource,
|
|
79
|
-
"api-version": AppServiceMsiApiVersion
|
|
80
|
-
};
|
|
81
|
-
if (version === "2019-08-01") {
|
|
82
|
-
if (clientId) {
|
|
83
|
-
queryParameters.client_id = clientId;
|
|
84
|
-
}
|
|
85
|
-
return {
|
|
86
|
-
url: process.env.IDENTITY_ENDPOINT,
|
|
87
|
-
method: "GET",
|
|
88
|
-
queryParameters,
|
|
89
|
-
headers: {
|
|
90
|
-
Accept: "application/json",
|
|
91
|
-
"X-IDENTITY-HEADER": process.env.IDENTITY_HEADER
|
|
92
|
-
}
|
|
93
|
-
};
|
|
94
|
-
}
|
|
95
|
-
else if (version === "2017-09-01") {
|
|
96
|
-
if (clientId) {
|
|
97
|
-
queryParameters.clientid = clientId;
|
|
98
|
-
}
|
|
99
|
-
return {
|
|
100
|
-
url: process.env.MSI_ENDPOINT,
|
|
101
|
-
method: "GET",
|
|
102
|
-
queryParameters,
|
|
103
|
-
headers: {
|
|
104
|
-
Accept: "application/json",
|
|
105
|
-
secret: process.env.MSI_SECRET
|
|
106
|
-
}
|
|
107
|
-
};
|
|
108
|
-
}
|
|
109
|
-
else {
|
|
110
|
-
throw new Error(`Unsupported version ${version}. The supported versions are "2019-08-01" and "2017-09-01"`);
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
createCloudShellMsiAuthRequest(resource, clientId) {
|
|
114
|
-
const body = {
|
|
115
|
-
resource
|
|
116
|
-
};
|
|
117
|
-
if (clientId) {
|
|
118
|
-
body.client_id = clientId;
|
|
119
|
-
}
|
|
120
|
-
return {
|
|
121
|
-
url: process.env.MSI_ENDPOINT,
|
|
122
|
-
method: "POST",
|
|
123
|
-
body: qs.stringify(body),
|
|
124
|
-
headers: {
|
|
125
|
-
Accept: "application/json",
|
|
126
|
-
Metadata: true,
|
|
127
|
-
"Content-Type": "application/x-www-form-urlencoded"
|
|
128
|
-
}
|
|
129
|
-
};
|
|
130
|
-
}
|
|
131
|
-
pingImdsEndpoint(resource, clientId, getTokenOptions) {
|
|
132
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
133
|
-
const { span, options } = createSpan("ManagedIdentityCredential-pingImdsEndpoint", getTokenOptions);
|
|
134
|
-
const request = this.createImdsAuthRequest(resource, clientId);
|
|
135
|
-
// This will always be populated, but let's make TypeScript happy
|
|
136
|
-
if (request.headers) {
|
|
137
|
-
// Remove the Metadata header to invoke a request error from
|
|
138
|
-
// IMDS endpoint
|
|
139
|
-
delete request.headers.Metadata;
|
|
140
|
-
}
|
|
141
|
-
request.spanOptions = options.tracingOptions && options.tracingOptions.spanOptions;
|
|
142
|
-
try {
|
|
143
|
-
// Create a request with a timeout since we expect that
|
|
144
|
-
// not having a "Metadata" header should cause an error to be
|
|
145
|
-
// returned quickly from the endpoint, proving its availability.
|
|
146
|
-
const webResource = this.identityClient.createWebResource(request);
|
|
147
|
-
webResource.timeout = (options.requestOptions && options.requestOptions.timeout) || 500;
|
|
148
|
-
try {
|
|
149
|
-
logger.info(`Pinging IMDS endpoint`);
|
|
150
|
-
yield this.identityClient.sendRequest(webResource);
|
|
151
|
-
}
|
|
152
|
-
catch (err) {
|
|
153
|
-
if ((err instanceof RestError && err.code === RestError.REQUEST_SEND_ERROR) ||
|
|
154
|
-
err.name === "AbortError" ||
|
|
155
|
-
err.code === "ECONNREFUSED" || // connection refused
|
|
156
|
-
err.code === "EHOSTDOWN" // host is down
|
|
157
|
-
) {
|
|
158
|
-
// If the request failed, or NodeJS was unable to establish a connection,
|
|
159
|
-
// or the host was down, we'll assume the IMDS endpoint isn't available.
|
|
160
|
-
logger.info(`IMDS endpoint unavailable`);
|
|
161
|
-
span.setStatus({
|
|
162
|
-
code: CanonicalCode.UNAVAILABLE,
|
|
163
|
-
message: err.message
|
|
164
|
-
});
|
|
165
|
-
return false;
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
// If we received any response, the endpoint is available
|
|
169
|
-
logger.info(`IMDS endpoint is available`);
|
|
170
|
-
return true;
|
|
171
|
-
}
|
|
172
|
-
catch (err) {
|
|
173
|
-
// createWebResource failed.
|
|
174
|
-
// This error should bubble up to the user.
|
|
175
|
-
logger.info(formatError(`Error when creating the WebResource for the IMDS endpoint: ${err.message}`));
|
|
176
|
-
span.setStatus({
|
|
177
|
-
code: CanonicalCode.UNKNOWN,
|
|
178
|
-
message: err.message
|
|
179
|
-
});
|
|
180
|
-
throw err;
|
|
181
|
-
}
|
|
182
|
-
finally {
|
|
183
|
-
span.end();
|
|
184
|
-
}
|
|
185
|
-
});
|
|
186
|
-
}
|
|
187
|
-
authenticateManagedIdentity(scopes, checkIfImdsEndpointAvailable, clientId, getTokenOptions) {
|
|
188
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
189
|
-
let authRequestOptions;
|
|
190
|
-
const resource = this.mapScopesToResource(scopes);
|
|
191
|
-
let expiresInParser;
|
|
192
|
-
const { span, options } = createSpan("ManagedIdentityCredential-authenticateManagedIdentity", getTokenOptions);
|
|
193
|
-
try {
|
|
194
|
-
// Detect which type of environment we are running in
|
|
195
|
-
if (process.env.IDENTITY_ENDPOINT && process.env.IDENTITY_HEADER) {
|
|
196
|
-
// Running in App Service 2019-08-01
|
|
197
|
-
authRequestOptions = this.createAppServiceMsiAuthRequest(resource, clientId, "2019-08-01");
|
|
198
|
-
expiresInParser = (requestBody) => {
|
|
199
|
-
// Parses a string representation of the seconds since epoch into a number value
|
|
200
|
-
return Number(requestBody.expires_on);
|
|
201
|
-
};
|
|
202
|
-
logger.info(`Using the endpoint and the secret coming form the environment variables: IDENTITY_ENDPOINT=${process.env.IDENTITY_ENDPOINT} and IDENTITY_HEADER=[REDACTED].`);
|
|
203
|
-
}
|
|
204
|
-
else if (process.env.MSI_ENDPOINT) {
|
|
205
|
-
if (process.env.MSI_SECRET) {
|
|
206
|
-
// Running in App Service
|
|
207
|
-
authRequestOptions = this.createAppServiceMsiAuthRequest(resource, clientId, "2017-09-01");
|
|
208
|
-
expiresInParser = (requestBody) => {
|
|
209
|
-
// Parse a date format like "06/20/2019 02:57:58 +00:00" and
|
|
210
|
-
// convert it into a JavaScript-formatted date
|
|
211
|
-
return Date.parse(requestBody.expires_on);
|
|
212
|
-
};
|
|
213
|
-
logger.info(`Using the endpoint and the secret coming form the environment variables: MSI_ENDPOINT=${process.env.MSI_ENDPOINT} and MSI_SECRET=[REDACTED].`);
|
|
214
|
-
}
|
|
215
|
-
else {
|
|
216
|
-
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.`);
|
|
217
|
-
// Running in Cloud Shell
|
|
218
|
-
authRequestOptions = this.createCloudShellMsiAuthRequest(resource, clientId);
|
|
219
|
-
}
|
|
220
|
-
}
|
|
221
|
-
else {
|
|
222
|
-
expiresInParser = (requestBody) => {
|
|
223
|
-
if (requestBody.expires_on) {
|
|
224
|
-
// Use the expires_on timestamp if it's available
|
|
225
|
-
const expires = +requestBody.expires_on * 1000;
|
|
226
|
-
logger.info(`IMDS using expires_on: ${expires} (original value: ${requestBody.expires_on})`);
|
|
227
|
-
return expires;
|
|
228
|
-
}
|
|
229
|
-
else {
|
|
230
|
-
// If these aren't possible, use expires_in and calculate a timestamp
|
|
231
|
-
const expires = Date.now() + requestBody.expires_in * 1000;
|
|
232
|
-
logger.info(`IMDS using expires_in: ${expires} (original value: ${requestBody.expires_in})`);
|
|
233
|
-
return expires;
|
|
234
|
-
}
|
|
235
|
-
};
|
|
236
|
-
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.`);
|
|
237
|
-
// Ping the IMDS endpoint to see if it's available
|
|
238
|
-
if (!checkIfImdsEndpointAvailable ||
|
|
239
|
-
(yield this.pingImdsEndpoint(resource, clientId, options))) {
|
|
240
|
-
// Running in an Azure VM
|
|
241
|
-
authRequestOptions = this.createImdsAuthRequest(resource, clientId);
|
|
242
|
-
}
|
|
243
|
-
else {
|
|
244
|
-
// Returning null tells the ManagedIdentityCredential that
|
|
245
|
-
// no MSI authentication endpoints are available
|
|
246
|
-
return null;
|
|
247
|
-
}
|
|
248
|
-
}
|
|
249
|
-
const webResource = this.identityClient.createWebResource(Object.assign({ disableJsonStringifyOnBody: true, deserializationMapper: undefined, abortSignal: options.abortSignal, spanOptions: options.tracingOptions && options.tracingOptions.spanOptions }, authRequestOptions));
|
|
250
|
-
const tokenResponse = yield this.identityClient.sendTokenRequest(webResource, expiresInParser);
|
|
251
|
-
return (tokenResponse && tokenResponse.accessToken) || null;
|
|
252
|
-
}
|
|
253
|
-
catch (err) {
|
|
254
|
-
// Expected errors to reach this point:
|
|
255
|
-
// - When we try call createWebResource and it fails (at any point).
|
|
256
|
-
// - When identityClient.sendTokenRequest throws.
|
|
257
|
-
// If the status code was 400, it means that the endpoint is working,
|
|
258
|
-
// but no identity is available.
|
|
259
|
-
//
|
|
260
|
-
// Errors that might reach this point, but shouldn't:
|
|
261
|
-
// - When createAppServiceMsiAuthRequest is called with an unsupported version.
|
|
262
|
-
// We shouldn't see this happening, because we specify the version in the parameters.
|
|
263
|
-
//
|
|
264
|
-
// Errors that shouldn't reach this point at all:
|
|
265
|
-
// - If we tried to reach to the IMDS endpoint and it ends up being unavailable, we simply don't call to createImdsAuthRequest, so we return null.
|
|
266
|
-
const code = err.name === AuthenticationErrorName
|
|
267
|
-
? CanonicalCode.UNAUTHENTICATED
|
|
268
|
-
: CanonicalCode.UNKNOWN;
|
|
269
|
-
span.setStatus({
|
|
270
|
-
code,
|
|
271
|
-
message: err.message
|
|
272
|
-
});
|
|
273
|
-
throw err;
|
|
274
|
-
}
|
|
275
|
-
finally {
|
|
276
|
-
span.end();
|
|
277
|
-
}
|
|
278
|
-
});
|
|
279
|
-
}
|
|
280
|
-
/**
|
|
281
|
-
* Authenticates with Azure Active Directory and returns an access token if
|
|
282
|
-
* successful. If authentication cannot be performed at this time, this method may
|
|
283
|
-
* return null. If an error occurs during authentication, an {@link AuthenticationError}
|
|
284
|
-
* containing failure details will be thrown.
|
|
285
|
-
*
|
|
286
|
-
* @param scopes The list of scopes for which the token will have access.
|
|
287
|
-
* @param options The options used to configure any requests this
|
|
288
|
-
* TokenCredential implementation might make.
|
|
289
|
-
*/
|
|
290
|
-
getToken(scopes, options) {
|
|
291
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
292
|
-
let result = null;
|
|
293
|
-
const { span, options: newOptions } = createSpan("ManagedIdentityCredential-getToken", options);
|
|
294
|
-
try {
|
|
295
|
-
// isEndpointAvailable can be true, false, or null,
|
|
296
|
-
// If it's null, it means we don't yet know whether
|
|
297
|
-
// the endpoint is available and need to check for it.
|
|
298
|
-
if (this.isEndpointUnavailable !== true) {
|
|
299
|
-
result = yield this.authenticateManagedIdentity(scopes, this.isEndpointUnavailable === null, this.clientId, newOptions);
|
|
300
|
-
if (result === null) {
|
|
301
|
-
// If authenticateManagedIdentity returns null,
|
|
302
|
-
// it means no MSI endpoints are available.
|
|
303
|
-
// If so, we avoid trying to reach to them in future requests.
|
|
304
|
-
this.isEndpointUnavailable = true;
|
|
305
|
-
// It also means that the endpoint answered with either 200 or 201 (see the sendTokenRequest method),
|
|
306
|
-
// yet we had no access token. For this reason, we'll throw once with a specific message:
|
|
307
|
-
const error = new CredentialUnavailable("The managed identity endpoint was reached, yet no tokens were received.");
|
|
308
|
-
logger.getToken.info(formatError(error));
|
|
309
|
-
throw error;
|
|
310
|
-
}
|
|
311
|
-
// Since `authenticateManagedIdentity` didn't throw, and the result was not null,
|
|
312
|
-
// We will assume that this endpoint is reachable from this point forward,
|
|
313
|
-
// and avoid pinging again to it.
|
|
314
|
-
// Details:
|
|
315
|
-
// - If `isEndpointUnavailable` is not true, `authenticateManagedIdentity` is called.
|
|
316
|
-
// - If `isEndpointUnavailable` is only set to false if `authenticateManagedIdentity` returns null.
|
|
317
|
-
// - If `isEndpointUnavailable` is null, `authenticateManagedIdentity` wil be called with "true" as the second parameter.
|
|
318
|
-
// - When `authenticateManagedIdentity` is called with `checkIfImdsEndpointAvailable` set to "true", `pingImdsEndpoint` is called.
|
|
319
|
-
// - If `pingImdsEndpoint` returns false, `authenticateManagedIdentity` returns null, which sets `isEndpointUnavailable` to false.
|
|
320
|
-
// - If `pingImdsEndpoint` returns true, `authenticateManagedIdentity` tries to authenticate with the IMDS endpoint.
|
|
321
|
-
// - If `authenticateManagedIdentity` tries to authenticate, and throws, we move to the catch section of this function.
|
|
322
|
-
// - If `authenticateManagedIdentity` manages to authenticate, `result` won't be null.
|
|
323
|
-
// - If `result` isn't null at this point, the endpoint was in fact available at first.
|
|
324
|
-
// - To avoid calling again to `pingImdsEndpoint`, we need to set `isEndpointUnavailable` to false,
|
|
325
|
-
// so that `authenticateManagedIdentity` gets to be called with `checkIfImdsEndpointAvailable` set to "false",
|
|
326
|
-
// thus skipping any further call to `pingImdsEndpoint`.
|
|
327
|
-
this.isEndpointUnavailable = false;
|
|
328
|
-
}
|
|
329
|
-
else {
|
|
330
|
-
// We've previously determined that the endpoint was unavailable,
|
|
331
|
-
// either because it was unreachable or permanently unable to authenticate.
|
|
332
|
-
const error = new CredentialUnavailable("The managed identity endpoint is not currently available");
|
|
333
|
-
logger.getToken.info(formatError(error));
|
|
334
|
-
throw error;
|
|
335
|
-
}
|
|
336
|
-
logger.getToken.info(formatSuccess(scopes));
|
|
337
|
-
return result;
|
|
338
|
-
}
|
|
339
|
-
catch (err) {
|
|
340
|
-
// CredentialUnavailable errors are expected to reach here.
|
|
341
|
-
// We intend them to bubble up, so that DefaultAzureCredential can catch them.
|
|
342
|
-
if (err instanceof CredentialUnavailable) {
|
|
343
|
-
throw err;
|
|
344
|
-
}
|
|
345
|
-
// Expected errors to reach this point:
|
|
346
|
-
// - Errors coming from a method unexpectedly breaking.
|
|
347
|
-
// - When identityClient.sendTokenRequest throws, in which case
|
|
348
|
-
// if the status code was 400, it means that the endpoint is working,
|
|
349
|
-
// but no identity is available.
|
|
350
|
-
span.setStatus({
|
|
351
|
-
code: CanonicalCode.UNKNOWN,
|
|
352
|
-
message: err.message
|
|
353
|
-
});
|
|
354
|
-
if (err.code === "ENETUNREACH") {
|
|
355
|
-
const error = new CredentialUnavailable("ManagedIdentityCredential is unavailable. No managed identity endpoint found.");
|
|
356
|
-
logger.getToken.info(formatError(error));
|
|
357
|
-
throw error;
|
|
358
|
-
}
|
|
359
|
-
// If err.statusCode has a value of 400, it comes from sendTokenRequest,
|
|
360
|
-
// and it means that the endpoint is working, but that no identity is available.
|
|
361
|
-
if (err.statusCode === 400) {
|
|
362
|
-
throw new CredentialUnavailable("The managed identity endpoint is indicating there's no available identity");
|
|
363
|
-
}
|
|
364
|
-
throw new AuthenticationError(err.statusCode, {
|
|
365
|
-
error: "ManagedIdentityCredential authentication failed.",
|
|
366
|
-
error_description: err.message
|
|
367
|
-
});
|
|
368
|
-
}
|
|
369
|
-
finally {
|
|
370
|
-
// Finally is always called, both if we return and if we throw in the above try/catch.
|
|
371
|
-
span.end();
|
|
372
|
-
}
|
|
373
|
-
});
|
|
374
|
-
}
|
|
375
|
-
}
|
|
376
|
-
//# sourceMappingURL=managedIdentityCredential.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"managedIdentityCredential.js","sourceRoot":"","sources":["../../../src/credentials/managedIdentityCredential.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\nimport qs from \"qs\";\nimport {\n AccessToken,\n GetTokenOptions,\n RequestPrepareOptions,\n RestError,\n TokenCredential\n} from \"@azure/core-http\";\nimport { IdentityClient, TokenCredentialOptions } from \"../client/identityClient\";\nimport { createSpan } from \"../util/tracing\";\nimport {\n AuthenticationErrorName,\n AuthenticationError,\n CredentialUnavailable\n} from \"../client/errors\";\nimport { CanonicalCode } from \"@opentelemetry/api\";\nimport { credentialLogger, formatSuccess, formatError } from \"../util/logging\";\n\nconst DefaultScopeSuffix = \"/.default\";\nexport const ImdsEndpoint = \"http://169.254.169.254/metadata/identity/oauth2/token\";\nexport const ImdsApiVersion = \"2018-02-01\";\nexport const AppServiceMsiApiVersion = \"2017-09-01\";\nconst logger = credentialLogger(\"ManagedIdentityCredential\");\n\n/**\n * Attempts authentication using a managed identity that has been assigned\n * to the deployment environment. This authentication type works in Azure VMs,\n * App Service and Azure Functions applications, and inside of Azure Cloud Shell.\n *\n * More information about configuring managed identities can be found here:\n *\n * https://docs.microsoft.com/en-us/azure/active-directory/managed-identities-azure-resources/overview\n */\nexport class ManagedIdentityCredential implements TokenCredential {\n private identityClient: IdentityClient;\n private clientId: string | undefined;\n private isEndpointUnavailable: boolean | null = null;\n\n /**\n * Creates an instance of ManagedIdentityCredential with the client ID of a\n * user-assigned identity.\n *\n * @param clientId The client ID of the user-assigned identity.\n * @param options Options for configuring the client which makes the access token request.\n */\n constructor(clientId: string, options?: TokenCredentialOptions);\n /**\n * Creates an instance of ManagedIdentityCredential\n *\n * @param options Options for configuring the client which makes the access token request.\n */\n constructor(options?: TokenCredentialOptions);\n /**\n * @internal\n * @ignore\n */\n constructor(\n clientIdOrOptions: string | TokenCredentialOptions | undefined,\n options?: TokenCredentialOptions\n ) {\n if (typeof clientIdOrOptions === \"string\") {\n // clientId, options constructor\n this.clientId = clientIdOrOptions;\n this.identityClient = new IdentityClient(options);\n } else {\n // options only constructor\n this.identityClient = new IdentityClient(clientIdOrOptions);\n }\n }\n\n private mapScopesToResource(scopes: string | string[]): string {\n let scope = \"\";\n if (Array.isArray(scopes)) {\n if (scopes.length !== 1) {\n throw new Error(\n \"To convert to a resource string the specified array must be exactly length 1\"\n );\n }\n\n scope = scopes[0];\n } else if (typeof scopes === \"string\") {\n scope = scopes;\n }\n\n if (!scope.endsWith(DefaultScopeSuffix)) {\n return scope;\n }\n\n return scope.substr(0, scope.lastIndexOf(DefaultScopeSuffix));\n }\n\n private createImdsAuthRequest(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 private createAppServiceMsiAuthRequest(\n resource: string,\n clientId?: string,\n version?: \"2019-08-01\" | \"2017-09-01\"\n ): RequestPrepareOptions {\n const queryParameters: any = {\n resource,\n \"api-version\": AppServiceMsiApiVersion\n };\n\n if (version === \"2019-08-01\") {\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 \"X-IDENTITY-HEADER\": process.env.IDENTITY_HEADER\n }\n };\n } else if (version === \"2017-09-01\") {\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 } else {\n throw new Error(\n `Unsupported version ${version}. The supported versions are \"2019-08-01\" and \"2017-09-01\"`\n );\n }\n }\n\n private createCloudShellMsiAuthRequest(\n resource: string,\n clientId?: string\n ): 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\n private async pingImdsEndpoint(\n resource: string,\n clientId?: string,\n getTokenOptions?: GetTokenOptions\n ): Promise<boolean> {\n const { span, options } = createSpan(\n \"ManagedIdentityCredential-pingImdsEndpoint\",\n getTokenOptions\n );\n const request = this.createImdsAuthRequest(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 = options.tracingOptions && options.tracingOptions.spanOptions;\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 = this.identityClient.createWebResource(request);\n webResource.timeout = (options.requestOptions && options.requestOptions.timeout) || 500;\n\n try {\n logger.info(`Pinging IMDS endpoint`);\n await this.identityClient.sendRequest(webResource);\n } catch (err) {\n if (\n (err instanceof 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(`IMDS endpoint unavailable`);\n span.setStatus({\n code: CanonicalCode.UNAVAILABLE,\n message: err.message\n });\n return false;\n }\n }\n\n // If we received any response, the endpoint is available\n logger.info(`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 formatError(`Error when creating the WebResource for the IMDS endpoint: ${err.message}`)\n );\n span.setStatus({\n code: CanonicalCode.UNKNOWN,\n message: err.message\n });\n throw err;\n } finally {\n span.end();\n }\n }\n\n private async authenticateManagedIdentity(\n scopes: string | string[],\n checkIfImdsEndpointAvailable: boolean,\n clientId?: string,\n getTokenOptions?: GetTokenOptions\n ): Promise<AccessToken | null> {\n let authRequestOptions: RequestPrepareOptions;\n const resource = this.mapScopesToResource(scopes);\n let expiresInParser: ((requestBody: any) => number) | undefined;\n\n const { span, options } = createSpan(\n \"ManagedIdentityCredential-authenticateManagedIdentity\",\n getTokenOptions\n );\n\n try {\n // Detect which type of environment we are running in\n if (process.env.IDENTITY_ENDPOINT && process.env.IDENTITY_HEADER) {\n // Running in App Service 2019-08-01\n authRequestOptions = this.createAppServiceMsiAuthRequest(resource, clientId, \"2019-08-01\");\n expiresInParser = (requestBody: any) => {\n // Parses a string representation of the seconds since epoch into a number value\n return Number(requestBody.expires_on);\n };\n logger.info(\n `Using the endpoint and the secret coming form the environment variables: IDENTITY_ENDPOINT=${process.env.IDENTITY_ENDPOINT} and IDENTITY_HEADER=[REDACTED].`\n );\n } else if (process.env.MSI_ENDPOINT) {\n if (process.env.MSI_SECRET) {\n // Running in App Service\n authRequestOptions = this.createAppServiceMsiAuthRequest(\n resource,\n clientId,\n \"2017-09-01\"\n );\n expiresInParser = (requestBody: any) => {\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 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 } else {\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 // Running in Cloud Shell\n authRequestOptions = this.createCloudShellMsiAuthRequest(resource, clientId);\n }\n } else {\n expiresInParser = (requestBody: any) => {\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 `IMDS 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 `IMDS using expires_in: ${expires} (original value: ${requestBody.expires_in})`\n );\n return expires;\n }\n };\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 // Ping the IMDS endpoint to see if it's available\n if (\n !checkIfImdsEndpointAvailable ||\n (await this.pingImdsEndpoint(resource, clientId, options))\n ) {\n // Running in an Azure VM\n authRequestOptions = this.createImdsAuthRequest(resource, clientId);\n } else {\n // Returning null tells the ManagedIdentityCredential that\n // no MSI authentication endpoints are available\n return null;\n }\n }\n\n const webResource = this.identityClient.createWebResource({\n disableJsonStringifyOnBody: true,\n deserializationMapper: undefined,\n abortSignal: options.abortSignal,\n spanOptions: options.tracingOptions && options.tracingOptions.spanOptions,\n ...authRequestOptions\n });\n\n const tokenResponse = await this.identityClient.sendTokenRequest(\n webResource,\n expiresInParser\n );\n return (tokenResponse && tokenResponse.accessToken) || null;\n } catch (err) {\n // Expected errors to reach this point:\n // - When we try call createWebResource and it fails (at any point).\n // - When identityClient.sendTokenRequest throws.\n // If the status code was 400, it means that the endpoint is working,\n // but no identity is available.\n //\n // Errors that might reach this point, but shouldn't:\n // - When createAppServiceMsiAuthRequest is called with an unsupported version.\n // We shouldn't see this happening, because we specify the version in the parameters.\n //\n // Errors that shouldn't reach this point at all:\n // - If we tried to reach to the IMDS endpoint and it ends up being unavailable, we simply don't call to createImdsAuthRequest, so we return null.\n\n const code =\n err.name === AuthenticationErrorName\n ? CanonicalCode.UNAUTHENTICATED\n : CanonicalCode.UNKNOWN;\n span.setStatus({\n code,\n message: err.message\n });\n throw err;\n } finally {\n span.end();\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 async getToken(\n scopes: string | string[],\n options?: GetTokenOptions\n ): Promise<AccessToken | null> {\n let result: AccessToken | null = null;\n\n const { span, options: newOptions } = createSpan(\"ManagedIdentityCredential-getToken\", options);\n\n try {\n // isEndpointAvailable can be true, false, or null,\n // If it's null, it means we don't yet know whether\n // the endpoint is available and need to check for it.\n if (this.isEndpointUnavailable !== true) {\n result = await this.authenticateManagedIdentity(\n scopes,\n this.isEndpointUnavailable === null,\n this.clientId,\n newOptions\n );\n\n if (result === null) {\n // If authenticateManagedIdentity returns null,\n // it means no MSI endpoints are available.\n // If so, we avoid trying to reach to them in future requests.\n this.isEndpointUnavailable = true;\n\n // It also means that the endpoint answered with either 200 or 201 (see the sendTokenRequest method),\n // yet we had no access token. For this reason, we'll throw once with a specific message:\n const error = new CredentialUnavailable(\n \"The managed identity endpoint was reached, yet no tokens were received.\"\n );\n logger.getToken.info(formatError(error));\n throw error;\n }\n \n // Since `authenticateManagedIdentity` didn't throw, and the result was not null,\n // We will assume that this endpoint is reachable from this point forward,\n // and avoid pinging again to it.\n // Details:\n // - If `isEndpointUnavailable` is not true, `authenticateManagedIdentity` is called.\n // - If `isEndpointUnavailable` is only set to false if `authenticateManagedIdentity` returns null.\n // - If `isEndpointUnavailable` is null, `authenticateManagedIdentity` wil be called with \"true\" as the second parameter.\n // - When `authenticateManagedIdentity` is called with `checkIfImdsEndpointAvailable` set to \"true\", `pingImdsEndpoint` is called.\n // - If `pingImdsEndpoint` returns false, `authenticateManagedIdentity` returns null, which sets `isEndpointUnavailable` to false.\n // - If `pingImdsEndpoint` returns true, `authenticateManagedIdentity` tries to authenticate with the IMDS endpoint.\n // - If `authenticateManagedIdentity` tries to authenticate, and throws, we move to the catch section of this function.\n // - If `authenticateManagedIdentity` manages to authenticate, `result` won't be null.\n // - If `result` isn't null at this point, the endpoint was in fact available at first.\n // - To avoid calling again to `pingImdsEndpoint`, we need to set `isEndpointUnavailable` to false,\n // so that `authenticateManagedIdentity` gets to be called with `checkIfImdsEndpointAvailable` set to \"false\",\n // thus skipping any further call to `pingImdsEndpoint`.\n this.isEndpointUnavailable = false;\n } else {\n // We've previously determined that the endpoint was unavailable,\n // either because it was unreachable or permanently unable to authenticate.\n const error = new CredentialUnavailable(\n \"The managed identity endpoint is not currently available\"\n );\n logger.getToken.info(formatError(error));\n throw error;\n }\n\n logger.getToken.info(formatSuccess(scopes));\n return result;\n } catch (err) {\n // CredentialUnavailable errors are expected to reach here.\n // We intend them to bubble up, so that DefaultAzureCredential can catch them.\n if (err instanceof CredentialUnavailable) {\n throw err;\n }\n\n // Expected errors to reach this point:\n // - Errors coming from a method unexpectedly breaking.\n // - When identityClient.sendTokenRequest throws, in which case\n // if the status code was 400, it means that the endpoint is working,\n // but no identity is available.\n\n span.setStatus({\n code: CanonicalCode.UNKNOWN,\n message: err.message\n });\n\n if (err.code === \"ENETUNREACH\") {\n const error = new CredentialUnavailable(\n \"ManagedIdentityCredential is unavailable. No managed identity endpoint found.\"\n );\n\n logger.getToken.info(formatError(error));\n throw error;\n }\n\n // If err.statusCode has a value of 400, it comes from sendTokenRequest,\n // and it means that the endpoint is working, but that no identity is available.\n if (err.statusCode === 400) {\n throw new CredentialUnavailable(\n \"The managed identity endpoint is indicating there's no available identity\"\n );\n }\n\n throw new AuthenticationError(err.statusCode, {\n error: \"ManagedIdentityCredential authentication failed.\",\n error_description: err.message\n });\n } finally {\n // Finally is always called, both if we return and if we throw in the above try/catch.\n span.end();\n }\n }\n}\n"]}
|