@azure/identity 2.0.0-beta.4 → 2.0.1-alpha.20211025.3

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 (132) hide show
  1. package/CHANGELOG.md +215 -4
  2. package/README.md +78 -25
  3. package/dist/index.js +888 -477
  4. package/dist/index.js.map +1 -1
  5. package/dist-esm/src/client/identityClient.js +75 -62
  6. package/dist-esm/src/client/identityClient.js.map +1 -1
  7. package/dist-esm/src/credentials/authorizationCodeCredential.browser.js +1 -1
  8. package/dist-esm/src/credentials/authorizationCodeCredential.browser.js.map +1 -1
  9. package/dist-esm/src/credentials/authorizationCodeCredential.js +12 -74
  10. package/dist-esm/src/credentials/authorizationCodeCredential.js.map +1 -1
  11. package/dist-esm/src/credentials/azureApplicationCredential.browser.js +34 -0
  12. package/dist-esm/src/credentials/azureApplicationCredential.browser.js.map +1 -0
  13. package/dist-esm/src/credentials/azureApplicationCredential.js +36 -0
  14. package/dist-esm/src/credentials/azureApplicationCredential.js.map +1 -0
  15. package/dist-esm/src/credentials/azureCliCredential.browser.js +7 -0
  16. package/dist-esm/src/credentials/azureCliCredential.browser.js.map +1 -1
  17. package/dist-esm/src/credentials/azureCliCredential.js +10 -10
  18. package/dist-esm/src/credentials/azureCliCredential.js.map +1 -1
  19. package/dist-esm/src/credentials/azurePowerShellCredential.browser.js +3 -1
  20. package/dist-esm/src/credentials/azurePowerShellCredential.browser.js.map +1 -1
  21. package/dist-esm/src/credentials/azurePowerShellCredential.js +13 -13
  22. package/dist-esm/src/credentials/azurePowerShellCredential.js.map +1 -1
  23. package/dist-esm/src/credentials/chainedTokenCredential.js +3 -3
  24. package/dist-esm/src/credentials/chainedTokenCredential.js.map +1 -1
  25. package/dist-esm/src/credentials/clientCertificateCredential.browser.js +7 -0
  26. package/dist-esm/src/credentials/clientCertificateCredential.browser.js.map +1 -1
  27. package/dist-esm/src/credentials/clientCertificateCredential.js +19 -13
  28. package/dist-esm/src/credentials/clientCertificateCredential.js.map +1 -1
  29. package/dist-esm/src/credentials/clientCertificateCredentialOptions.js.map +1 -1
  30. package/dist-esm/src/credentials/clientSecretCredential.browser.js +17 -19
  31. package/dist-esm/src/credentials/clientSecretCredential.browser.js.map +1 -1
  32. package/dist-esm/src/credentials/clientSecretCredential.js +3 -0
  33. package/dist-esm/src/credentials/clientSecretCredential.js.map +1 -1
  34. package/dist-esm/src/credentials/clientSecretCredentialOptions.js.map +1 -1
  35. package/dist-esm/src/credentials/credentialPersistenceOptions.js.map +1 -1
  36. package/dist-esm/src/credentials/defaultAzureCredential.browser.js +1 -1
  37. package/dist-esm/src/credentials/defaultAzureCredential.browser.js.map +1 -1
  38. package/dist-esm/src/credentials/defaultAzureCredential.js +22 -21
  39. package/dist-esm/src/credentials/defaultAzureCredential.js.map +1 -1
  40. package/dist-esm/src/credentials/deviceCodeCredential.browser.js +7 -0
  41. package/dist-esm/src/credentials/deviceCodeCredential.browser.js.map +1 -1
  42. package/dist-esm/src/credentials/deviceCodeCredential.js +14 -0
  43. package/dist-esm/src/credentials/deviceCodeCredential.js.map +1 -1
  44. package/dist-esm/src/credentials/deviceCodeCredentialOptions.js.map +1 -1
  45. package/dist-esm/src/credentials/environmentCredential.browser.js +7 -0
  46. package/dist-esm/src/credentials/environmentCredential.browser.js.map +1 -1
  47. package/dist-esm/src/credentials/environmentCredential.js +5 -21
  48. package/dist-esm/src/credentials/environmentCredential.js.map +1 -1
  49. package/dist-esm/src/credentials/interactiveBrowserCredential.browser.js +7 -7
  50. package/dist-esm/src/credentials/interactiveBrowserCredential.browser.js.map +1 -1
  51. package/dist-esm/src/credentials/interactiveBrowserCredential.js +7 -7
  52. package/dist-esm/src/credentials/interactiveBrowserCredential.js.map +1 -1
  53. package/dist-esm/src/credentials/interactiveBrowserCredentialOptions.js.map +1 -1
  54. package/dist-esm/src/credentials/managedIdentityCredential/appServiceMsi2017.js +31 -12
  55. package/dist-esm/src/credentials/managedIdentityCredential/appServiceMsi2017.js.map +1 -1
  56. package/dist-esm/src/credentials/managedIdentityCredential/arcMsi.js +45 -23
  57. package/dist-esm/src/credentials/managedIdentityCredential/arcMsi.js.map +1 -1
  58. package/dist-esm/src/credentials/managedIdentityCredential/cloudShellMsi.js +29 -13
  59. package/dist-esm/src/credentials/managedIdentityCredential/cloudShellMsi.js.map +1 -1
  60. package/dist-esm/src/credentials/managedIdentityCredential/constants.js +2 -1
  61. package/dist-esm/src/credentials/managedIdentityCredential/constants.js.map +1 -1
  62. package/dist-esm/src/credentials/managedIdentityCredential/fabricMsi.js +36 -11
  63. package/dist-esm/src/credentials/managedIdentityCredential/fabricMsi.js.map +1 -1
  64. package/dist-esm/src/credentials/managedIdentityCredential/imdsMsi.js +69 -47
  65. package/dist-esm/src/credentials/managedIdentityCredential/imdsMsi.js.map +1 -1
  66. package/dist-esm/src/credentials/managedIdentityCredential/index.js +19 -17
  67. package/dist-esm/src/credentials/managedIdentityCredential/index.js.map +1 -1
  68. package/dist-esm/src/credentials/managedIdentityCredential/models.js.map +1 -1
  69. package/dist-esm/src/credentials/managedIdentityCredential/tokenExchangeMsi.js +82 -0
  70. package/dist-esm/src/credentials/managedIdentityCredential/tokenExchangeMsi.js.map +1 -0
  71. package/dist-esm/src/credentials/managedIdentityCredential/utils.js +16 -4
  72. package/dist-esm/src/credentials/managedIdentityCredential/utils.js.map +1 -1
  73. package/dist-esm/src/credentials/onBehalfOfCredential.browser.js +23 -0
  74. package/dist-esm/src/credentials/onBehalfOfCredential.browser.js.map +1 -0
  75. package/dist-esm/src/credentials/onBehalfOfCredential.js +57 -0
  76. package/dist-esm/src/credentials/onBehalfOfCredential.js.map +1 -0
  77. package/dist-esm/src/credentials/{visualStudioCodeCredentialExtension.js → onBehalfOfCredentialOptions.js} +1 -1
  78. package/dist-esm/src/credentials/onBehalfOfCredentialOptions.js.map +1 -0
  79. package/dist-esm/src/credentials/usernamePasswordCredential.browser.js +17 -19
  80. package/dist-esm/src/credentials/usernamePasswordCredential.browser.js.map +1 -1
  81. package/dist-esm/src/credentials/usernamePasswordCredential.js +3 -2
  82. package/dist-esm/src/credentials/usernamePasswordCredential.js.map +1 -1
  83. package/dist-esm/src/credentials/visualStudioCodeCredential.browser.js +7 -1
  84. package/dist-esm/src/credentials/visualStudioCodeCredential.browser.js.map +1 -1
  85. package/dist-esm/src/credentials/visualStudioCodeCredential.js +16 -8
  86. package/dist-esm/src/credentials/visualStudioCodeCredential.js.map +1 -1
  87. package/dist-esm/src/credentials/visualStudioCodeCredentialPlugin.js +4 -0
  88. package/dist-esm/src/credentials/visualStudioCodeCredentialPlugin.js.map +1 -0
  89. package/dist-esm/src/{client/errors.js → errors.js} +16 -1
  90. package/dist-esm/src/errors.js.map +1 -0
  91. package/dist-esm/src/index.js +3 -4
  92. package/dist-esm/src/index.js.map +1 -1
  93. package/dist-esm/src/msal/browserFlows/browserCommon.js +8 -7
  94. package/dist-esm/src/msal/browserFlows/browserCommon.js.map +1 -1
  95. package/dist-esm/src/msal/browserFlows/msalAuthCode.js +12 -4
  96. package/dist-esm/src/msal/browserFlows/msalAuthCode.js.map +1 -1
  97. package/dist-esm/src/msal/nodeFlows/msalAuthorizationCode.js +41 -0
  98. package/dist-esm/src/msal/nodeFlows/msalAuthorizationCode.js.map +1 -0
  99. package/dist-esm/src/msal/nodeFlows/msalClientCertificate.js +49 -29
  100. package/dist-esm/src/msal/nodeFlows/msalClientCertificate.js.map +1 -1
  101. package/dist-esm/src/msal/nodeFlows/msalClientSecret.js.map +1 -1
  102. package/dist-esm/src/msal/nodeFlows/msalOnBehalfOf.js +56 -0
  103. package/dist-esm/src/msal/nodeFlows/msalOnBehalfOf.js.map +1 -0
  104. package/dist-esm/src/msal/nodeFlows/msalOpenBrowser.js +2 -2
  105. package/dist-esm/src/msal/nodeFlows/msalOpenBrowser.js.map +1 -1
  106. package/dist-esm/src/msal/nodeFlows/nodeCommon.js +32 -13
  107. package/dist-esm/src/msal/nodeFlows/nodeCommon.js.map +1 -1
  108. package/dist-esm/src/msal/nodeFlows/tokenCachePersistenceOptions.js.map +1 -1
  109. package/dist-esm/src/msal/utils.js +15 -8
  110. package/dist-esm/src/msal/utils.js.map +1 -1
  111. package/dist-esm/src/plugins/consumer.browser.js +7 -0
  112. package/dist-esm/src/plugins/consumer.browser.js.map +1 -0
  113. package/dist-esm/src/{extensions → plugins}/consumer.js +12 -12
  114. package/dist-esm/src/plugins/consumer.js.map +1 -0
  115. package/dist-esm/src/{extensions → plugins}/provider.js +0 -0
  116. package/dist-esm/src/plugins/provider.js.map +1 -0
  117. package/dist-esm/src/util/tracing.js +2 -2
  118. package/dist-esm/src/util/tracing.js.map +1 -1
  119. package/dist-esm/src/util/validateMultiTenant.browser.js +22 -0
  120. package/dist-esm/src/util/validateMultiTenant.browser.js.map +1 -0
  121. package/dist-esm/src/util/validateMultiTenant.js +17 -12
  122. package/dist-esm/src/util/validateMultiTenant.js.map +1 -1
  123. package/package.json +38 -21
  124. package/types/identity.d.ts +250 -225
  125. package/dist-esm/src/client/errors.js.map +0 -1
  126. package/dist-esm/src/credentials/visualStudioCodeCredentialExtension.js.map +0 -1
  127. package/dist-esm/src/extensions/consumer.browser.js +0 -7
  128. package/dist-esm/src/extensions/consumer.browser.js.map +0 -1
  129. package/dist-esm/src/extensions/consumer.js.map +0 -1
  130. package/dist-esm/src/extensions/provider.js.map +0 -1
  131. package/dist-esm/src/msal/errors.js +0 -22
  132. package/dist-esm/src/msal/errors.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"appServiceMsi2017.js","sourceRoot":"","sources":["../../../../src/credentials/managedIdentityCredential/appServiceMsi2017.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,kCAAkC;AAOlC,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;IACpC,KAAK,CAAC,WAAW;QACf,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC;QACxB,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,YAAY,IAAI,GAAG,CAAC,UAAU,CAAC,CAAC;QAC3D,IAAI,CAAC,MAAM,EAAE;YACX,MAAM,CAAC,IAAI,CAAC,gDAAgD,CAAC,CAAC;SAC/D;QACD,OAAO,MAAM,CAAC;IAChB,CAAC;IACD,KAAK,CAAC,QAAQ,CACZ,cAA8B,EAC9B,QAAgB,EAChB,QAAiB,EACjB,kBAAmC,EAAE;QAErC,MAAM,CAAC,IAAI,CACT,yFAAyF,OAAO,CAAC,GAAG,CAAC,YAAY,6BAA6B,CAC/I,CAAC;QAEF,OAAO,kBAAkB,CACvB,cAAc,EACd,qBAAqB,CAAC,QAAQ,EAAE,QAAQ,CAAC,EACzC,eAAe,EACf,eAAe,CAChB,CAAC;IACJ,CAAC;CACF,CAAC","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\nimport { AccessToken, GetTokenOptions } from \"@azure/core-auth\";\n\nimport { RequestPrepareOptions } from \"@azure/core-http\";\n\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 const result = Boolean(env.MSI_ENDPOINT && env.MSI_SECRET);\n if (!result) {\n logger.info(\"The Azure App Service MSI 2017 is unavailable.\");\n }\n return result;\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"]}
1
+ {"version":3,"file":"appServiceMsi2017.js","sourceRoot":"","sources":["../../../../src/credentials/managedIdentityCredential/appServiceMsi2017.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,kCAAkC;AAElC,OAAO,EAAE,iBAAiB,EAA0B,MAAM,2BAA2B,CAAC;AAEtF,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAEtD,OAAO,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC;AAElE,MAAM,OAAO,GAAG,gDAAgD,CAAC;AACjE,MAAM,MAAM,GAAG,gBAAgB,CAAC,OAAO,CAAC,CAAC;AAEzC,SAAS,eAAe,CAAC,WAAgB;IACvC,4DAA4D;IAC5D,8CAA8C;IAC9C,OAAO,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,UAAU,CAAC,CAAC;AAC5C,CAAC;AAED,SAAS,qBAAqB,CAC5B,MAAyB,EACzB,QAAiB;IAEjB,MAAM,QAAQ,GAAG,mBAAmB,CAAC,MAAM,CAAC,CAAC;IAC7C,IAAI,CAAC,QAAQ,EAAE;QACb,MAAM,IAAI,KAAK,CAAC,GAAG,OAAO,sCAAsC,CAAC,CAAC;KACnE;IAED,MAAM,eAAe,GAAQ;QAC3B,QAAQ;QACR,aAAa,EAAE,YAAY;KAC5B,CAAC;IAEF,IAAI,QAAQ,EAAE;QACZ,eAAe,CAAC,QAAQ,GAAG,QAAQ,CAAC;KACrC;IAED,MAAM,KAAK,GAAG,IAAI,eAAe,CAAC,eAAe,CAAC,CAAC;IAEnD,wIAAwI;IACxI,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,YAAY,EAAE;QAC7B,MAAM,IAAI,KAAK,CAAC,GAAG,OAAO,8CAA8C,CAAC,CAAC;KAC3E;IACD,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,UAAU,EAAE;QAC3B,MAAM,IAAI,KAAK,CAAC,GAAG,OAAO,4CAA4C,CAAC,CAAC;KACzE;IAED,OAAO;QACL,GAAG,EAAE,GAAG,OAAO,CAAC,GAAG,CAAC,YAAY,IAAI,KAAK,CAAC,QAAQ,EAAE,EAAE;QACtD,MAAM,EAAE,KAAK;QACb,OAAO,EAAE,iBAAiB,CAAC;YACzB,MAAM,EAAE,kBAAkB;YAC1B,MAAM,EAAE,OAAO,CAAC,GAAG,CAAC,UAAU;SAC/B,CAAC;KACH,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,MAAM,iBAAiB,GAAQ;IACpC,KAAK,CAAC,WAAW,CAAC,MAAM;QACtB,MAAM,QAAQ,GAAG,mBAAmB,CAAC,MAAM,CAAC,CAAC;QAC7C,IAAI,CAAC,QAAQ,EAAE;YACb,MAAM,CAAC,IAAI,CAAC,GAAG,OAAO,mDAAmD,CAAC,CAAC;YAC3E,OAAO,KAAK,CAAC;SACd;QACD,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC;QACxB,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,YAAY,IAAI,GAAG,CAAC,UAAU,CAAC,CAAC;QAC3D,IAAI,CAAC,MAAM,EAAE;YACX,MAAM,CAAC,IAAI,CACT,GAAG,OAAO,mFAAmF,CAC9F,CAAC;SACH;QACD,OAAO,MAAM,CAAC;IAChB,CAAC;IACD,KAAK,CAAC,QAAQ,CACZ,aAA+B,EAC/B,kBAAmC,EAAE;QAErC,MAAM,EAAE,cAAc,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,aAAa,CAAC;QAE3D,MAAM,CAAC,IAAI,CACT,GAAG,OAAO,2FAA2F,OAAO,CAAC,GAAG,CAAC,YAAY,6BAA6B,CAC3J,CAAC;QAEF,OAAO,kBAAkB,CACvB,cAAc,EACd,qBAAqB,CAAC,MAAM,EAAE,QAAQ,CAAC,EACvC,eAAe,EACf,eAAe,CAChB,CAAC;IACJ,CAAC;CACF,CAAC","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\nimport { createHttpHeaders, PipelineRequestOptions } from \"@azure/core-rest-pipeline\";\nimport { AccessToken, GetTokenOptions } from \"@azure/core-auth\";\nimport { credentialLogger } from \"../../util/logging\";\nimport { MSI, MSIConfiguration } from \"./models\";\nimport { mapScopesToResource, msiGenericGetToken } from \"./utils\";\n\nconst msiName = \"ManagedIdentityCredential - AppServiceMSI 2017\";\nconst logger = credentialLogger(msiName);\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(\n scopes: string | string[],\n clientId?: string\n): PipelineRequestOptions {\n const resource = mapScopesToResource(scopes);\n if (!resource) {\n throw new Error(`${msiName}: Multiple scopes are not supported.`);\n }\n\n const queryParameters: any = {\n resource,\n \"api-version\": \"2017-09-01\"\n };\n\n if (clientId) {\n queryParameters.clientid = clientId;\n }\n\n const query = new URLSearchParams(queryParameters);\n\n // This error should not bubble up, since we verify that this environment variable is defined in the isAvailable() method defined below.\n if (!process.env.MSI_ENDPOINT) {\n throw new Error(`${msiName}: Missing environment variable: MSI_ENDPOINT`);\n }\n if (!process.env.MSI_SECRET) {\n throw new Error(`${msiName}: Missing environment variable: MSI_SECRET`);\n }\n\n return {\n url: `${process.env.MSI_ENDPOINT}?${query.toString()}`,\n method: \"GET\",\n headers: createHttpHeaders({\n Accept: \"application/json\",\n secret: process.env.MSI_SECRET\n })\n };\n}\n\nexport const appServiceMsi2017: MSI = {\n async isAvailable(scopes): Promise<boolean> {\n const resource = mapScopesToResource(scopes);\n if (!resource) {\n logger.info(`${msiName}: Unavailable. Multiple scopes are not supported.`);\n return false;\n }\n const env = process.env;\n const result = Boolean(env.MSI_ENDPOINT && env.MSI_SECRET);\n if (!result) {\n logger.info(\n `${msiName}: Unavailable. The environment variables needed are: MSI_ENDPOINT and MSI_SECRET.`\n );\n }\n return result;\n },\n async getToken(\n configuration: MSIConfiguration,\n getTokenOptions: GetTokenOptions = {}\n ): Promise<AccessToken | null> {\n const { identityClient, scopes, clientId } = configuration;\n\n logger.info(\n `${msiName}: Using the 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(scopes, clientId),\n expiresInParser,\n getTokenOptions\n );\n }\n};\n"]}
@@ -1,28 +1,38 @@
1
1
  // Copyright (c) Microsoft Corporation.
2
2
  // Licensed under the MIT license.
3
+ import { createHttpHeaders, createPipelineRequest } from "@azure/core-rest-pipeline";
4
+ import { readFile } from "fs";
3
5
  import { credentialLogger } from "../../util/logging";
4
- import { msiGenericGetToken } from "./utils";
6
+ import { mapScopesToResource, msiGenericGetToken } from "./utils";
5
7
  import { azureArcAPIVersion } from "./constants";
6
- import { AuthenticationError } from "../../client/errors";
7
- import { readFile } from "fs";
8
- const logger = credentialLogger("ManagedIdentityCredential - ArcMSI");
8
+ import { AuthenticationError } from "../../errors";
9
+ const msiName = "ManagedIdentityCredential - Azure Arc MSI";
10
+ const logger = credentialLogger(msiName);
9
11
  // Azure Arc MSI doesn't have a special expiresIn parser.
10
12
  const expiresInParser = undefined;
11
- function prepareRequestOptions(resource) {
13
+ function prepareRequestOptions(scopes) {
14
+ const resource = mapScopesToResource(scopes);
15
+ if (!resource) {
16
+ throw new Error(`${msiName}: Multiple scopes are not supported.`);
17
+ }
12
18
  const queryParameters = {
13
19
  resource,
14
20
  "api-version": azureArcAPIVersion
15
21
  };
16
- return {
22
+ const query = new URLSearchParams(queryParameters);
23
+ // This error should not bubble up, since we verify that this environment variable is defined in the isAvailable() method defined below.
24
+ if (!process.env.IDENTITY_ENDPOINT) {
25
+ throw new Error(`${msiName}: Missing environment variable: IDENTITY_ENDPOINT`);
26
+ }
27
+ return createPipelineRequest({
17
28
  // Should be similar to: http://localhost:40342/metadata/identity/oauth2/token
18
- url: process.env.IDENTITY_ENDPOINT,
29
+ url: `${process.env.IDENTITY_ENDPOINT}?${query.toString()}`,
19
30
  method: "GET",
20
- queryParameters,
21
- headers: {
31
+ headers: createHttpHeaders({
22
32
  Accept: "application/json",
23
- Metadata: true
24
- }
25
- };
33
+ Metadata: "true"
34
+ })
35
+ });
26
36
  }
27
37
  // Since "fs"'s readFileSync locks the thread, and to avoid extra dependencies.
28
38
  function readFileAsync(path, options) {
@@ -34,37 +44,49 @@ function readFileAsync(path, options) {
34
44
  }));
35
45
  }
36
46
  async function filePathRequest(identityClient, requestPrepareOptions) {
37
- const response = await identityClient.sendRequest(identityClient.createWebResource(requestPrepareOptions));
47
+ const response = await identityClient.sendRequest(createPipelineRequest(requestPrepareOptions));
38
48
  if (response.status !== 401) {
39
49
  let message = "";
40
50
  if (response.bodyAsText) {
41
51
  message = ` Response: ${response.bodyAsText}`;
42
52
  }
43
- throw new AuthenticationError(response.status, `To authenticate with Azure Arc MSI, status code 401 is expected on the first request.${message}`);
53
+ throw new AuthenticationError(response.status, `${msiName}: To authenticate with Azure Arc MSI, status code 401 is expected on the first request. ${message}`);
44
54
  }
45
55
  const authHeader = response.headers.get("www-authenticate") || "";
46
- return authHeader.split("=").slice(1)[0];
56
+ try {
57
+ return authHeader.split("=").slice(1)[0];
58
+ }
59
+ catch (e) {
60
+ throw Error(`Invalid www-authenticate header format: ${authHeader}`);
61
+ }
47
62
  }
48
63
  export const arcMsi = {
49
- async isAvailable() {
64
+ async isAvailable(scopes) {
65
+ const resource = mapScopesToResource(scopes);
66
+ if (!resource) {
67
+ logger.info(`${msiName}: Unavailable. Multiple scopes are not supported.`);
68
+ return false;
69
+ }
50
70
  const result = Boolean(process.env.IMDS_ENDPOINT && process.env.IDENTITY_ENDPOINT);
51
71
  if (!result) {
52
- logger.info("The Azure Arc MSI is unavailable.");
72
+ logger.info(`${msiName}: The environment variables needed are: IMDS_ENDPOINT and IDENTITY_ENDPOINT`);
53
73
  }
54
74
  return result;
55
75
  },
56
- async getToken(identityClient, resource, clientId, getTokenOptions = {}) {
57
- logger.info(`Using the Azure Arc MSI to authenticate.`);
76
+ async getToken(configuration, getTokenOptions = {}) {
77
+ var _a;
78
+ const { identityClient, scopes, clientId } = configuration;
79
+ logger.info(`${msiName}: Authenticating.`);
58
80
  if (clientId) {
59
- 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.");
81
+ throw new Error(`${msiName}: 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.`);
60
82
  }
61
- const requestOptions = Object.assign({ disableJsonStringifyOnBody: true, deserializationMapper: undefined, abortSignal: getTokenOptions.abortSignal, spanOptions: getTokenOptions.tracingOptions && getTokenOptions.tracingOptions.spanOptions }, prepareRequestOptions(resource));
83
+ const requestOptions = Object.assign(Object.assign({ disableJsonStringifyOnBody: true, deserializationMapper: undefined, abortSignal: getTokenOptions.abortSignal }, prepareRequestOptions(scopes)), { allowInsecureConnection: true });
62
84
  const filePath = await filePathRequest(identityClient, requestOptions);
63
85
  if (!filePath) {
64
- throw new Error("Azure Arc MSI failed to find the token file.");
86
+ throw new Error(`${msiName}: Failed to find the token file.`);
65
87
  }
66
88
  const key = await readFileAsync(filePath, { encoding: "utf-8" });
67
- requestOptions.headers["Authorization"] = `Basic ${key}`;
89
+ (_a = requestOptions.headers) === null || _a === void 0 ? void 0 : _a.set("Authorization", `Basic ${key}`);
68
90
  return msiGenericGetToken(identityClient, requestOptions, expiresInParser, getTokenOptions);
69
91
  }
70
92
  };
@@ -1 +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 } from \"@azure/core-auth\";\nimport { RequestPrepareOptions } from \"@azure/core-http\";\n\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 const result = Boolean(process.env.IMDS_ENDPOINT && process.env.IDENTITY_ENDPOINT);\n if (!result) {\n logger.info(\"The Azure Arc MSI is unavailable.\");\n }\n return result;\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"]}
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 {\n createHttpHeaders,\n createPipelineRequest,\n PipelineRequestOptions\n} from \"@azure/core-rest-pipeline\";\nimport { AccessToken, GetTokenOptions } from \"@azure/core-auth\";\nimport { readFile } from \"fs\";\nimport { MSI, MSIConfiguration } from \"./models\";\nimport { credentialLogger } from \"../../util/logging\";\nimport { IdentityClient } from \"../../client/identityClient\";\nimport { mapScopesToResource, msiGenericGetToken } from \"./utils\";\nimport { azureArcAPIVersion } from \"./constants\";\nimport { AuthenticationError } from \"../../errors\";\n\nconst msiName = \"ManagedIdentityCredential - Azure Arc MSI\";\nconst logger = credentialLogger(msiName);\n\n// Azure Arc MSI doesn't have a special expiresIn parser.\nconst expiresInParser = undefined;\n\nfunction prepareRequestOptions(scopes: string | string[]): PipelineRequestOptions {\n const resource = mapScopesToResource(scopes);\n if (!resource) {\n throw new Error(`${msiName}: Multiple scopes are not supported.`);\n }\n const queryParameters: any = {\n resource,\n \"api-version\": azureArcAPIVersion\n };\n\n const query = new URLSearchParams(queryParameters);\n\n // This error should not bubble up, since we verify that this environment variable is defined in the isAvailable() method defined below.\n if (!process.env.IDENTITY_ENDPOINT) {\n throw new Error(`${msiName}: Missing environment variable: IDENTITY_ENDPOINT`);\n }\n\n return createPipelineRequest({\n // Should be similar to: http://localhost:40342/metadata/identity/oauth2/token\n url: `${process.env.IDENTITY_ENDPOINT}?${query.toString()}`,\n method: \"GET\",\n headers: createHttpHeaders({\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: PipelineRequestOptions\n): Promise<string | undefined> {\n const response = await identityClient.sendRequest(createPipelineRequest(requestPrepareOptions));\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 `${msiName}: 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 try {\n return authHeader.split(\"=\").slice(1)[0];\n } catch (e) {\n throw Error(`Invalid www-authenticate header format: ${authHeader}`);\n }\n}\n\nexport const arcMsi: MSI = {\n async isAvailable(scopes): Promise<boolean> {\n const resource = mapScopesToResource(scopes);\n if (!resource) {\n logger.info(`${msiName}: Unavailable. Multiple scopes are not supported.`);\n return false;\n }\n const result = Boolean(process.env.IMDS_ENDPOINT && process.env.IDENTITY_ENDPOINT);\n if (!result) {\n logger.info(\n `${msiName}: The environment variables needed are: IMDS_ENDPOINT and IDENTITY_ENDPOINT`\n );\n }\n return result;\n },\n async getToken(\n configuration: MSIConfiguration,\n getTokenOptions: GetTokenOptions = {}\n ): Promise<AccessToken | null> {\n const { identityClient, scopes, clientId } = configuration;\n\n logger.info(`${msiName}: Authenticating.`);\n\n if (clientId) {\n throw new Error(\n `${msiName}: 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 ...prepareRequestOptions(scopes),\n allowInsecureConnection: true\n };\n\n const filePath = await filePathRequest(identityClient, requestOptions);\n\n if (!filePath) {\n throw new Error(`${msiName}: Failed to find the token file.`);\n }\n\n const key = await readFileAsync(filePath, { encoding: \"utf-8\" });\n requestOptions.headers?.set(\"Authorization\", `Basic ${key}`);\n\n return msiGenericGetToken(identityClient, requestOptions, expiresInParser, getTokenOptions);\n }\n};\n"]}
@@ -1,40 +1,56 @@
1
1
  // Copyright (c) Microsoft Corporation.
2
2
  // Licensed under the MIT license.
3
- import qs from "qs";
3
+ import { createHttpHeaders } from "@azure/core-rest-pipeline";
4
4
  import { credentialLogger } from "../../util/logging";
5
- import { msiGenericGetToken } from "./utils";
6
- const logger = credentialLogger("ManagedIdentityCredential - CloudShellMSI");
5
+ import { mapScopesToResource, msiGenericGetToken } from "./utils";
6
+ const msiName = "ManagedIdentityCredential - CloudShellMSI";
7
+ const logger = credentialLogger(msiName);
7
8
  // Cloud Shell MSI doesn't have a special expiresIn parser.
8
9
  const expiresInParser = undefined;
9
- function prepareRequestOptions(resource, clientId) {
10
+ function prepareRequestOptions(scopes, clientId) {
11
+ const resource = mapScopesToResource(scopes);
12
+ if (!resource) {
13
+ throw new Error(`${msiName}: Multiple scopes are not supported.`);
14
+ }
10
15
  const body = {
11
16
  resource
12
17
  };
13
18
  if (clientId) {
14
19
  body.client_id = clientId;
15
20
  }
21
+ // This error should not bubble up, since we verify that this environment variable is defined in the isAvailable() method defined below.
22
+ if (!process.env.MSI_ENDPOINT) {
23
+ throw new Error(`${msiName}: Missing environment variable: MSI_ENDPOINT`);
24
+ }
25
+ const params = new URLSearchParams(body);
16
26
  return {
17
27
  url: process.env.MSI_ENDPOINT,
18
28
  method: "POST",
19
- body: qs.stringify(body),
20
- headers: {
29
+ body: params.toString(),
30
+ headers: createHttpHeaders({
21
31
  Accept: "application/json",
22
- Metadata: true,
32
+ Metadata: "true",
23
33
  "Content-Type": "application/x-www-form-urlencoded"
24
- }
34
+ })
25
35
  };
26
36
  }
27
37
  export const cloudShellMsi = {
28
- async isAvailable() {
38
+ async isAvailable(scopes) {
39
+ const resource = mapScopesToResource(scopes);
40
+ if (!resource) {
41
+ logger.info(`${msiName}: Unavailable. Multiple scopes are not supported.`);
42
+ return false;
43
+ }
29
44
  const result = Boolean(process.env.MSI_ENDPOINT);
30
45
  if (!result) {
31
- logger.info("The Azure Cloud Shell MSI is unavailable.");
46
+ logger.info(`${msiName}: Unavailable. The environment variable MSI_ENDPOINT is needed.`);
32
47
  }
33
48
  return result;
34
49
  },
35
- async getToken(identityClient, resource, clientId, getTokenOptions = {}) {
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);
50
+ async getToken(configuration, getTokenOptions = {}) {
51
+ const { identityClient, scopes, clientId } = configuration;
52
+ logger.info(`${msiName}: Using the endpoint coming form the environment variable MSI_ENDPOINT = ${process.env.MSI_ENDPOINT}.`);
53
+ return msiGenericGetToken(identityClient, prepareRequestOptions(scopes, clientId), expiresInParser, getTokenOptions);
38
54
  }
39
55
  };
40
56
  //# sourceMappingURL=cloudShellMsi.js.map
@@ -1 +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;AAMpB,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;IAChC,KAAK,CAAC,WAAW;QACf,MAAM,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;QACjD,IAAI,CAAC,MAAM,EAAE;YACX,MAAM,CAAC,IAAI,CAAC,2CAA2C,CAAC,CAAC;SAC1D;QACD,OAAO,MAAM,CAAC;IAChB,CAAC;IACD,KAAK,CAAC,QAAQ,CACZ,cAA8B,EAC9B,QAAgB,EAChB,QAAiB,EACjB,kBAAmC,EAAE;QAErC,MAAM,CAAC,IAAI,CACT,wEAAwE,OAAO,CAAC,GAAG,CAAC,YAAY,iEAAiE,CAClK,CAAC;QAEF,OAAO,kBAAkB,CACvB,cAAc,EACd,qBAAqB,CAAC,QAAQ,EAAE,QAAQ,CAAC,EACzC,eAAe,EACf,eAAe,CAChB,CAAC;IACJ,CAAC;CACF,CAAC","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\nimport qs from \"qs\";\n\nimport { AccessToken, GetTokenOptions } from \"@azure/core-auth\";\nimport { RequestPrepareOptions } from \"@azure/core-http\";\n\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 const result = Boolean(process.env.MSI_ENDPOINT);\n if (!result) {\n logger.info(\"The Azure Cloud Shell MSI is unavailable.\");\n }\n return result;\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"]}
1
+ {"version":3,"file":"cloudShellMsi.js","sourceRoot":"","sources":["../../../../src/credentials/managedIdentityCredential/cloudShellMsi.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,kCAAkC;AAElC,OAAO,EAAE,iBAAiB,EAA0B,MAAM,2BAA2B,CAAC;AAGtF,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC;AAElE,MAAM,OAAO,GAAG,2CAA2C,CAAC;AAC5D,MAAM,MAAM,GAAG,gBAAgB,CAAC,OAAO,CAAC,CAAC;AAEzC,2DAA2D;AAC3D,MAAM,eAAe,GAAG,SAAS,CAAC;AAElC,SAAS,qBAAqB,CAC5B,MAAyB,EACzB,QAAiB;IAEjB,MAAM,QAAQ,GAAG,mBAAmB,CAAC,MAAM,CAAC,CAAC;IAC7C,IAAI,CAAC,QAAQ,EAAE;QACb,MAAM,IAAI,KAAK,CAAC,GAAG,OAAO,sCAAsC,CAAC,CAAC;KACnE;IAED,MAAM,IAAI,GAAQ;QAChB,QAAQ;KACT,CAAC;IAEF,IAAI,QAAQ,EAAE;QACZ,IAAI,CAAC,SAAS,GAAG,QAAQ,CAAC;KAC3B;IAED,wIAAwI;IACxI,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,YAAY,EAAE;QAC7B,MAAM,IAAI,KAAK,CAAC,GAAG,OAAO,8CAA8C,CAAC,CAAC;KAC3E;IACD,MAAM,MAAM,GAAG,IAAI,eAAe,CAAC,IAAI,CAAC,CAAC;IACzC,OAAO;QACL,GAAG,EAAE,OAAO,CAAC,GAAG,CAAC,YAAY;QAC7B,MAAM,EAAE,MAAM;QACd,IAAI,EAAE,MAAM,CAAC,QAAQ,EAAE;QACvB,OAAO,EAAE,iBAAiB,CAAC;YACzB,MAAM,EAAE,kBAAkB;YAC1B,QAAQ,EAAE,MAAM;YAChB,cAAc,EAAE,mCAAmC;SACpD,CAAC;KACH,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,MAAM,aAAa,GAAQ;IAChC,KAAK,CAAC,WAAW,CAAC,MAAM;QACtB,MAAM,QAAQ,GAAG,mBAAmB,CAAC,MAAM,CAAC,CAAC;QAC7C,IAAI,CAAC,QAAQ,EAAE;YACb,MAAM,CAAC,IAAI,CAAC,GAAG,OAAO,mDAAmD,CAAC,CAAC;YAC3E,OAAO,KAAK,CAAC;SACd;QACD,MAAM,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;QACjD,IAAI,CAAC,MAAM,EAAE;YACX,MAAM,CAAC,IAAI,CAAC,GAAG,OAAO,iEAAiE,CAAC,CAAC;SAC1F;QACD,OAAO,MAAM,CAAC;IAChB,CAAC;IACD,KAAK,CAAC,QAAQ,CACZ,aAA+B,EAC/B,kBAAmC,EAAE;QAErC,MAAM,EAAE,cAAc,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,aAAa,CAAC;QAE3D,MAAM,CAAC,IAAI,CACT,GAAG,OAAO,4EAA4E,OAAO,CAAC,GAAG,CAAC,YAAY,GAAG,CAClH,CAAC;QAEF,OAAO,kBAAkB,CACvB,cAAc,EACd,qBAAqB,CAAC,MAAM,EAAE,QAAQ,CAAC,EACvC,eAAe,EACf,eAAe,CAChB,CAAC;IACJ,CAAC;CACF,CAAC","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\nimport { createHttpHeaders, PipelineRequestOptions } from \"@azure/core-rest-pipeline\";\nimport { AccessToken, GetTokenOptions } from \"@azure/core-auth\";\nimport { MSI, MSIConfiguration } from \"./models\";\nimport { credentialLogger } from \"../../util/logging\";\nimport { mapScopesToResource, msiGenericGetToken } from \"./utils\";\n\nconst msiName = \"ManagedIdentityCredential - CloudShellMSI\";\nconst logger = credentialLogger(msiName);\n\n// Cloud Shell MSI doesn't have a special expiresIn parser.\nconst expiresInParser = undefined;\n\nfunction prepareRequestOptions(\n scopes: string | string[],\n clientId?: string\n): PipelineRequestOptions {\n const resource = mapScopesToResource(scopes);\n if (!resource) {\n throw new Error(`${msiName}: Multiple scopes are not supported.`);\n }\n\n const body: any = {\n resource\n };\n\n if (clientId) {\n body.client_id = clientId;\n }\n\n // This error should not bubble up, since we verify that this environment variable is defined in the isAvailable() method defined below.\n if (!process.env.MSI_ENDPOINT) {\n throw new Error(`${msiName}: Missing environment variable: MSI_ENDPOINT`);\n }\n const params = new URLSearchParams(body);\n return {\n url: process.env.MSI_ENDPOINT,\n method: \"POST\",\n body: params.toString(),\n headers: createHttpHeaders({\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(scopes): Promise<boolean> {\n const resource = mapScopesToResource(scopes);\n if (!resource) {\n logger.info(`${msiName}: Unavailable. Multiple scopes are not supported.`);\n return false;\n }\n const result = Boolean(process.env.MSI_ENDPOINT);\n if (!result) {\n logger.info(`${msiName}: Unavailable. The environment variable MSI_ENDPOINT is needed.`);\n }\n return result;\n },\n async getToken(\n configuration: MSIConfiguration,\n getTokenOptions: GetTokenOptions = {}\n ): Promise<AccessToken | null> {\n const { identityClient, scopes, clientId } = configuration;\n\n logger.info(\n `${msiName}: Using the endpoint coming form the environment variable MSI_ENDPOINT = ${process.env.MSI_ENDPOINT}.`\n );\n\n return msiGenericGetToken(\n identityClient,\n prepareRequestOptions(scopes, clientId),\n expiresInParser,\n getTokenOptions\n );\n }\n};\n"]}
@@ -1,7 +1,8 @@
1
1
  // Copyright (c) Microsoft Corporation.
2
2
  // Licensed under the MIT license.
3
3
  export const DefaultScopeSuffix = "/.default";
4
- export const imdsEndpoint = "http://169.254.169.254/metadata/identity/oauth2/token";
4
+ export const imdsHost = "http://169.254.169.254";
5
+ export const imdsEndpointPath = "/metadata/identity/oauth2/token";
5
6
  export const imdsApiVersion = "2018-02-01";
6
7
  export const azureArcAPIVersion = "2019-11-01";
7
8
  export const azureFabricVersion = "2019-07-01-preview";
@@ -1 +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"]}
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,QAAQ,GAAG,wBAAwB,CAAC;AACjD,MAAM,CAAC,MAAM,gBAAgB,GAAG,iCAAiC,CAAC;AAClE,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 imdsHost = \"http://169.254.169.254\";\nexport const imdsEndpointPath = \"/metadata/identity/oauth2/token\";\nexport const imdsApiVersion = \"2018-02-01\";\nexport const azureArcAPIVersion = \"2019-11-01\";\nexport const azureFabricVersion = \"2019-07-01-preview\";\n"]}
@@ -1,14 +1,21 @@
1
1
  // Copyright (c) Microsoft Corporation.
2
2
  // Licensed under the MIT license.
3
+ import https from "https";
4
+ import { createHttpHeaders } from "@azure/core-rest-pipeline";
3
5
  import { credentialLogger } from "../../util/logging";
4
- import { msiGenericGetToken } from "./utils";
6
+ import { mapScopesToResource, msiGenericGetToken } from "./utils";
5
7
  import { azureFabricVersion } from "./constants";
6
- const logger = credentialLogger("ManagedIdentityCredential - Fabric MSI");
8
+ const msiName = "ManagedIdentityCredential - Fabric MSI";
9
+ const logger = credentialLogger(msiName);
7
10
  function expiresInParser(requestBody) {
8
11
  // Parses a string representation of the seconds since epoch into a number value
9
12
  return Number(requestBody.expires_on);
10
13
  }
11
- function prepareRequestOptions(resource, clientId) {
14
+ function prepareRequestOptions(scopes, clientId) {
15
+ const resource = mapScopesToResource(scopes);
16
+ if (!resource) {
17
+ throw new Error(`${msiName}: Multiple scopes are not supported.`);
18
+ }
12
19
  const queryParameters = {
13
20
  resource,
14
21
  "api-version": azureFabricVersion
@@ -16,14 +23,21 @@ function prepareRequestOptions(resource, clientId) {
16
23
  if (clientId) {
17
24
  queryParameters.client_id = clientId;
18
25
  }
26
+ const query = new URLSearchParams(queryParameters);
27
+ // This error should not bubble up, since we verify that this environment variable is defined in the isAvailable() method defined below.
28
+ if (!process.env.IDENTITY_ENDPOINT) {
29
+ throw new Error("Missing environment variable: IDENTITY_ENDPOINT");
30
+ }
31
+ if (!process.env.IDENTITY_HEADER) {
32
+ throw new Error("Missing environment variable: IDENTITY_HEADER");
33
+ }
19
34
  return {
20
- url: process.env.IDENTITY_ENDPOINT,
35
+ url: `${process.env.IDENTITY_ENDPOINT}?${query.toString()}`,
21
36
  method: "GET",
22
- queryParameters,
23
- headers: {
37
+ headers: createHttpHeaders({
24
38
  Accept: "application/json",
25
39
  Secret: process.env.IDENTITY_HEADER
26
- }
40
+ })
27
41
  };
28
42
  }
29
43
  // This credential can be easily tested by deploying a container to Azure Service Fabric with the Dockerfile:
@@ -37,22 +51,33 @@ function prepareRequestOptions(resource, clientId) {
37
51
  // curl --insecure $IDENTITY_ENDPOINT'?api-version=2019-07-01-preview&resource=https://vault.azure.net/' -H "Secret: $IDENTITY_HEADER"
38
52
  //
39
53
  export const fabricMsi = {
40
- async isAvailable() {
54
+ async isAvailable(scopes) {
55
+ const resource = mapScopesToResource(scopes);
56
+ if (!resource) {
57
+ logger.info(`${msiName}: Unavailable. Multiple scopes are not supported.`);
58
+ return false;
59
+ }
41
60
  const env = process.env;
42
61
  const result = Boolean(env.IDENTITY_ENDPOINT && env.IDENTITY_HEADER && env.IDENTITY_SERVER_THUMBPRINT);
43
62
  if (!result) {
44
- logger.info("The Azure App Service Fabric MSI is unavailable.");
63
+ logger.info(`${msiName}: Unavailable. The environment variables needed are: IDENTITY_ENDPOINT, IDENTITY_HEADER and IDENTITY_SERVER_THUMBPRINT`);
45
64
  }
46
65
  return result;
47
66
  },
48
- async getToken(identityClient, resource, clientId, getTokenOptions = {}) {
67
+ async getToken(configuration, getTokenOptions = {}) {
68
+ const { scopes, identityClient, clientId } = configuration;
49
69
  logger.info([
70
+ `${msiName}:`,
50
71
  "Using the endpoint and the secret coming from the environment variables:",
51
72
  `IDENTITY_ENDPOINT=${process.env.IDENTITY_ENDPOINT},`,
52
73
  "IDENTITY_HEADER=[REDACTED] and",
53
74
  "IDENTITY_SERVER_THUMBPRINT=[REDACTED]."
54
75
  ].join(" "));
55
- return msiGenericGetToken(identityClient, prepareRequestOptions(resource, clientId), expiresInParser, getTokenOptions);
76
+ return msiGenericGetToken(identityClient, prepareRequestOptions(scopes, clientId), expiresInParser, getTokenOptions, new https.Agent({
77
+ // This is necessary because Service Fabric provides a self-signed certificate.
78
+ // The alternative path is to verify the certificate using the IDENTITY_SERVER_THUMBPRINT env variable.
79
+ rejectUnauthorized: false
80
+ }));
56
81
  }
57
82
  };
58
83
  //# sourceMappingURL=fabricMsi.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"fabricMsi.js","sourceRoot":"","sources":["../../../../src/credentials/managedIdentityCredential/fabricMsi.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,kCAAkC;AAMlC,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;IAC5B,KAAK,CAAC,WAAW;QACf,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC;QACxB,MAAM,MAAM,GAAG,OAAO,CACpB,GAAG,CAAC,iBAAiB,IAAI,GAAG,CAAC,eAAe,IAAI,GAAG,CAAC,0BAA0B,CAC/E,CAAC;QACF,IAAI,CAAC,MAAM,EAAE;YACX,MAAM,CAAC,IAAI,CAAC,kDAAkD,CAAC,CAAC;SACjE;QACD,OAAO,MAAM,CAAC;IAChB,CAAC;IACD,KAAK,CAAC,QAAQ,CACZ,cAA8B,EAC9B,QAAgB,EAChB,QAAiB,EACjB,kBAAmC,EAAE;QAErC,MAAM,CAAC,IAAI,CACT;YACE,0EAA0E;YAC1E,qBAAqB,OAAO,CAAC,GAAG,CAAC,iBAAiB,GAAG;YACrD,gCAAgC;YAChC,wCAAwC;SACzC,CAAC,IAAI,CAAC,GAAG,CAAC,CACZ,CAAC;QAEF,OAAO,kBAAkB,CACvB,cAAc,EACd,qBAAqB,CAAC,QAAQ,EAAE,QAAQ,CAAC,EACzC,eAAe,EACf,eAAe,CAChB,CAAC;IACJ,CAAC;CACF,CAAC","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\nimport { AccessToken, GetTokenOptions } from \"@azure/core-auth\";\nimport { RequestPrepareOptions } from \"@azure/core-http\";\n\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 const result = Boolean(\n env.IDENTITY_ENDPOINT && env.IDENTITY_HEADER && env.IDENTITY_SERVER_THUMBPRINT\n );\n if (!result) {\n logger.info(\"The Azure App Service Fabric MSI is unavailable.\");\n }\n return result;\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"]}
1
+ {"version":3,"file":"fabricMsi.js","sourceRoot":"","sources":["../../../../src/credentials/managedIdentityCredential/fabricMsi.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\nimport https from \"https\";\nimport { createHttpHeaders, PipelineRequestOptions } from \"@azure/core-rest-pipeline\";\nimport { AccessToken, GetTokenOptions } from \"@azure/core-auth\";\nimport { MSI, MSIConfiguration } from \"./models\";\nimport { credentialLogger } from \"../../util/logging\";\nimport { mapScopesToResource, msiGenericGetToken } from \"./utils\";\nimport { azureFabricVersion } from \"./constants\";\n\nconst msiName = \"ManagedIdentityCredential - Fabric MSI\";\nconst logger = credentialLogger(msiName);\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(\n scopes: string | string[],\n clientId?: string\n): PipelineRequestOptions {\n const resource = mapScopesToResource(scopes);\n if (!resource) {\n throw new Error(`${msiName}: Multiple scopes are not supported.`);\n }\n\n const queryParameters: any = {\n resource,\n \"api-version\": azureFabricVersion\n };\n\n if (clientId) {\n queryParameters.client_id = clientId;\n }\n\n const query = new URLSearchParams(queryParameters);\n\n // This error should not bubble up, since we verify that this environment variable is defined in the isAvailable() method defined below.\n if (!process.env.IDENTITY_ENDPOINT) {\n throw new Error(\"Missing environment variable: IDENTITY_ENDPOINT\");\n }\n if (!process.env.IDENTITY_HEADER) {\n throw new Error(\"Missing environment variable: IDENTITY_HEADER\");\n }\n\n return {\n url: `${process.env.IDENTITY_ENDPOINT}?${query.toString()}`,\n method: \"GET\",\n headers: createHttpHeaders({\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(scopes): Promise<boolean> {\n const resource = mapScopesToResource(scopes);\n if (!resource) {\n logger.info(`${msiName}: Unavailable. Multiple scopes are not supported.`);\n return false;\n }\n const env = process.env;\n const result = Boolean(\n env.IDENTITY_ENDPOINT && env.IDENTITY_HEADER && env.IDENTITY_SERVER_THUMBPRINT\n );\n if (!result) {\n logger.info(\n `${msiName}: Unavailable. The environment variables needed are: IDENTITY_ENDPOINT, IDENTITY_HEADER and IDENTITY_SERVER_THUMBPRINT`\n );\n }\n return result;\n },\n async getToken(\n configuration: MSIConfiguration,\n getTokenOptions: GetTokenOptions = {}\n ): Promise<AccessToken | null> {\n const { scopes, identityClient, clientId } = configuration;\n\n logger.info(\n [\n `${msiName}:`,\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(scopes, clientId),\n expiresInParser,\n getTokenOptions,\n new https.Agent({\n // This is necessary because Service Fabric provides a self-signed certificate.\n // The alternative path is to verify the certificate using the IDENTITY_SERVER_THUMBPRINT env variable.\n rejectUnauthorized: false\n })\n );\n }\n};\n"]}
@@ -1,44 +1,64 @@
1
1
  // Copyright (c) Microsoft Corporation.
2
2
  // Licensed under the MIT license.
3
- import { delay, RestError } from "@azure/core-http";
3
+ import { delay } from "@azure/core-util";
4
+ import { createHttpHeaders, createPipelineRequest, RestError } from "@azure/core-rest-pipeline";
4
5
  import { SpanStatusCode } from "@azure/core-tracing";
5
- import { AuthenticationError } from "../../client/errors";
6
6
  import { credentialLogger } from "../../util/logging";
7
7
  import { createSpan } from "../../util/tracing";
8
- import { imdsApiVersion, imdsEndpoint } from "./constants";
9
- import { msiGenericGetToken } from "./utils";
10
- const logger = credentialLogger("ManagedIdentityCredential - IMDS");
8
+ import { imdsApiVersion, imdsEndpointPath, imdsHost } from "./constants";
9
+ import { mapScopesToResource, msiGenericGetToken } from "./utils";
10
+ import { AuthenticationError } from "../../errors";
11
+ const msiName = "ManagedIdentityCredential - IMDS";
12
+ const logger = credentialLogger(msiName);
11
13
  function expiresInParser(requestBody) {
12
14
  if (requestBody.expires_on) {
13
15
  // Use the expires_on timestamp if it's available
14
16
  const expires = +requestBody.expires_on * 1000;
15
- logger.info(`IMDS using expires_on: ${expires} (original value: ${requestBody.expires_on})`);
17
+ logger.info(`${msiName}: Using expires_on: ${expires} (original value: ${requestBody.expires_on})`);
16
18
  return expires;
17
19
  }
18
20
  else {
19
21
  // If these aren't possible, use expires_in and calculate a timestamp
20
22
  const expires = Date.now() + requestBody.expires_in * 1000;
21
- logger.info(`IMDS using expires_in: ${expires} (original value: ${requestBody.expires_in})`);
23
+ logger.info(`${msiName}: IMDS using expires_in: ${expires} (original value: ${requestBody.expires_in})`);
22
24
  return expires;
23
25
  }
24
26
  }
25
- function prepareRequestOptions(resource, clientId) {
27
+ function prepareRequestOptions(scopes, clientId, options) {
26
28
  var _a;
27
- const queryParameters = {
28
- resource,
29
- "api-version": imdsApiVersion
29
+ const resource = mapScopesToResource(scopes);
30
+ if (!resource) {
31
+ throw new Error(`${msiName}: Multiple scopes are not supported.`);
32
+ }
33
+ const { skipQuery, skipMetadataHeader } = options || {};
34
+ let query = "";
35
+ // Pod Identity will try to process this request even if the Metadata header is missing.
36
+ // We can exclude the request query to ensure no IMDS endpoint tries to process the ping request.
37
+ if (!skipQuery) {
38
+ const queryParameters = {
39
+ resource,
40
+ "api-version": imdsApiVersion
41
+ };
42
+ if (clientId) {
43
+ queryParameters.client_id = clientId;
44
+ }
45
+ const params = new URLSearchParams(queryParameters);
46
+ query = `?${params.toString()}`;
47
+ }
48
+ const url = new URL(imdsEndpointPath, (_a = process.env.AZURE_POD_IDENTITY_AUTHORITY_HOST) !== null && _a !== void 0 ? _a : imdsHost);
49
+ const rawHeaders = {
50
+ Accept: "application/json",
51
+ Metadata: "true"
30
52
  };
31
- if (clientId) {
32
- queryParameters.client_id = clientId;
53
+ // Remove the Metadata header to invoke a request error from some IMDS endpoints.
54
+ if (skipMetadataHeader) {
55
+ delete rawHeaders.Metadata;
33
56
  }
34
57
  return {
35
- url: (_a = process.env.AZURE_POD_IDENTITY_TOKEN_URL) !== null && _a !== void 0 ? _a : imdsEndpoint,
58
+ // In this case, the `?` should be added in the "query" variable `skipQuery` is not set.
59
+ url: `${url}${query}`,
36
60
  method: "GET",
37
- queryParameters,
38
- headers: {
39
- Accept: "application/json",
40
- Metadata: true
41
- }
61
+ headers: createHttpHeaders(rawHeaders)
42
62
  };
43
63
  }
44
64
  // 800ms -> 1600ms -> 3200ms
@@ -48,43 +68,45 @@ export const imdsMsiRetryConfig = {
48
68
  intervalIncrement: 2
49
69
  };
50
70
  export const imdsMsi = {
51
- async isAvailable(identityClient, resource, clientId, getTokenOptions) {
52
- var _a, _b, _c;
53
- const { span, updatedOptions } = createSpan("ManagedIdentityCredential-pingImdsEndpoint", getTokenOptions);
71
+ async isAvailable(scopes, identityClient, clientId, getTokenOptions) {
72
+ var _a, _b;
73
+ const resource = mapScopesToResource(scopes);
74
+ if (!resource) {
75
+ logger.info(`${msiName}: Unavailable. Multiple scopes are not supported.`);
76
+ return false;
77
+ }
78
+ const { span, updatedOptions: options } = createSpan("ManagedIdentityCredential-pingImdsEndpoint", getTokenOptions);
54
79
  // if the PodIdenityEndpoint environment variable was set no need to probe the endpoint, it can be assumed to exist
55
- if (process.env.AZURE_POD_IDENTITY_TOKEN_URL) {
80
+ if (process.env.AZURE_POD_IDENTITY_AUTHORITY_HOST) {
56
81
  return true;
57
82
  }
58
- const request = prepareRequestOptions(resource, clientId);
59
- // This will always be populated, but let's make TypeScript happy
60
- if (request.headers) {
61
- // Remove the Metadata header to invoke a request error from
62
- // IMDS endpoint
63
- delete request.headers.Metadata;
64
- }
65
- request.spanOptions = (_a = updatedOptions === null || updatedOptions === void 0 ? void 0 : updatedOptions.tracingOptions) === null || _a === void 0 ? void 0 : _a.spanOptions;
66
- request.tracingContext = (_b = updatedOptions === null || updatedOptions === void 0 ? void 0 : updatedOptions.tracingOptions) === null || _b === void 0 ? void 0 : _b.tracingContext;
83
+ const requestOptions = prepareRequestOptions(resource, clientId, {
84
+ skipMetadataHeader: true,
85
+ skipQuery: true
86
+ });
87
+ requestOptions.tracingOptions = options.tracingOptions;
67
88
  try {
68
89
  // Create a request with a timeout since we expect that
69
90
  // not having a "Metadata" header should cause an error to be
70
91
  // returned quickly from the endpoint, proving its availability.
71
- const webResource = identityClient.createWebResource(request);
72
- // In Kubernetes pods, node-fetch (used by core-http) takes longer than 2 seconds to begin sending the network request,
73
- // So smaller timeouts will cause this credential to be immediately aborted.
74
- // This won't be a problem once we move Identity to core-rest-pipeline.
75
- webResource.timeout = ((_c = updatedOptions === null || updatedOptions === void 0 ? void 0 : updatedOptions.requestOptions) === null || _c === void 0 ? void 0 : _c.timeout) || 3000;
92
+ const request = createPipelineRequest(requestOptions);
93
+ request.timeout = (_b = (_a = options.requestOptions) === null || _a === void 0 ? void 0 : _a.timeout) !== null && _b !== void 0 ? _b : 300;
94
+ // This MSI uses the imdsEndpoint to get the token, which only uses http://
95
+ request.allowInsecureConnection = true;
76
96
  try {
77
- await identityClient.sendRequest(webResource);
97
+ logger.info(`${msiName}: Pinging the Azure IMDS endpoint`);
98
+ await identityClient.sendRequest(request);
78
99
  }
79
100
  catch (err) {
80
101
  if ((err.name === "RestError" && err.code === RestError.REQUEST_SEND_ERROR) ||
81
102
  err.name === "AbortError" ||
103
+ err.code === "ENETUNREACH" || // Network unreachable
82
104
  err.code === "ECONNREFUSED" || // connection refused
83
105
  err.code === "EHOSTDOWN" // host is down
84
106
  ) {
85
- // If the request failed, or NodeJS was unable to establish a connection,
107
+ // If the request failed, or Node.js was unable to establish a connection,
86
108
  // or the host was down, we'll assume the IMDS endpoint isn't available.
87
- logger.info(`The Azure IMDS endpoint is unavailable`);
109
+ logger.info(`${msiName}: The Azure IMDS endpoint is unavailable`);
88
110
  span.setStatus({
89
111
  code: SpanStatusCode.ERROR,
90
112
  message: err.message
@@ -93,14 +115,13 @@ export const imdsMsi = {
93
115
  }
94
116
  }
95
117
  // If we received any response, the endpoint is available
96
- logger.info(`The Azure IMDS endpoint is available`);
97
- // IMDS MSI available!
118
+ logger.info(`${msiName}: The Azure IMDS endpoint is available`);
98
119
  return true;
99
120
  }
100
121
  catch (err) {
101
122
  // createWebResource failed.
102
123
  // This error should bubble up to the user.
103
- logger.info(`Error when creating the WebResource for the IMDS endpoint: ${err.message}`);
124
+ logger.info(`${msiName}: Error when creating the WebResource for the Azure IMDS endpoint: ${err.message}`);
104
125
  span.setStatus({
105
126
  code: SpanStatusCode.ERROR,
106
127
  message: err.message
@@ -111,12 +132,13 @@ export const imdsMsi = {
111
132
  span.end();
112
133
  }
113
134
  },
114
- async getToken(identityClient, resource, clientId, getTokenOptions = {}) {
115
- 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.`);
135
+ async getToken(configuration, getTokenOptions = {}) {
136
+ const { identityClient, scopes, clientId } = configuration;
137
+ logger.info(`${msiName}: Using the Azure IMDS endpoint coming from the environment variable MSI_ENDPOINT=${process.env.MSI_ENDPOINT}, and using the cloud shell to proceed with the authentication.`);
116
138
  let nextDelayInMs = imdsMsiRetryConfig.startDelayInMs;
117
139
  for (let retries = 0; retries < imdsMsiRetryConfig.maxRetries; retries++) {
118
140
  try {
119
- return await msiGenericGetToken(identityClient, prepareRequestOptions(resource, clientId), expiresInParser, getTokenOptions);
141
+ return await msiGenericGetToken(identityClient, prepareRequestOptions(scopes, clientId), expiresInParser, getTokenOptions);
120
142
  }
121
143
  catch (error) {
122
144
  if (error.statusCode === 404) {
@@ -127,7 +149,7 @@ export const imdsMsi = {
127
149
  throw error;
128
150
  }
129
151
  }
130
- throw new AuthenticationError(404, `Failed to retrieve IMDS token after ${imdsMsiRetryConfig.maxRetries} retries.`);
152
+ throw new AuthenticationError(404, `${msiName}: Failed to retrieve IMDS token after ${imdsMsiRetryConfig.maxRetries} retries.`);
131
153
  }
132
154
  };
133
155
  //# sourceMappingURL=imdsMsi.js.map