login.js 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680
  1. "use strict";
  2. // Copyright (c) Microsoft Corporation. All rights reserved.
  3. // Licensed under the MIT License. See License.txt in the project root for license information.
  4. var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
  5. return new (P || (P = Promise))(function (resolve, reject) {
  6. function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
  7. function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
  8. function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
  9. step((generator = generator.apply(thisArg, _arguments || [])).next());
  10. });
  11. };
  12. Object.defineProperty(exports, "__esModule", { value: true });
  13. const adal = require("adal-node");
  14. const msRest = require("@azure/ms-rest-js");
  15. const child_process_1 = require("child_process");
  16. const fs_1 = require("fs");
  17. const ms_rest_azure_env_1 = require("@azure/ms-rest-azure-env");
  18. const applicationTokenCredentials_1 = require("./credentials/applicationTokenCredentials");
  19. const applicationTokenCertificateCredentials_1 = require("./credentials/applicationTokenCertificateCredentials");
  20. const deviceTokenCredentials_1 = require("./credentials/deviceTokenCredentials");
  21. const userTokenCredentials_1 = require("./credentials/userTokenCredentials");
  22. const authConstants_1 = require("./util/authConstants");
  23. const subscriptionUtils_1 = require("./subscriptionManagement/subscriptionUtils");
  24. const msiVmTokenCredentials_1 = require("./credentials/msiVmTokenCredentials");
  25. const msiAppServiceTokenCredentials_1 = require("./credentials/msiAppServiceTokenCredentials");
  26. /**
  27. * @constant {Array<string>} managementPlaneTokenAudiences - Urls for management plane token
  28. * audience across different azure environments.
  29. */
  30. const managementPlaneTokenAudiences = [
  31. "https://management.core.windows.net/",
  32. "https://management.core.chinacloudapi.cn/",
  33. "https://management.core.usgovcloudapi.net/",
  34. "https://management.core.cloudapi.de/",
  35. "https://management.azure.com/",
  36. "https://management.core.windows.net",
  37. "https://management.core.chinacloudapi.cn",
  38. "https://management.core.usgovcloudapi.net",
  39. "https://management.core.cloudapi.de",
  40. "https://management.azure.com"
  41. ];
  42. function turnOnLogging() {
  43. const log = adal.Logging;
  44. log.setLoggingOptions({
  45. level: 3,
  46. log: function (level, message, error) {
  47. level;
  48. console.info(message);
  49. if (error) {
  50. console.error(error);
  51. }
  52. }
  53. });
  54. }
  55. if (process.env["AZURE_ADAL_LOGGING_ENABLED"]) {
  56. turnOnLogging();
  57. }
  58. /**
  59. * Provides a UserTokenCredentials object and the list of subscriptions associated with that userId across all the applicable tenants.
  60. * This method is applicable only for organizational ids that are not 2FA enabled otherwise please use interactive login.
  61. *
  62. * @param {string} username The user name for the Organization Id account.
  63. * @param {string} password The password for the Organization Id account.
  64. * @param {object} [options] Object representing optional parameters.
  65. * @param {string} [options.clientId] The active directory application client id.
  66. * See {@link https://azure.microsoft.com/en-us/documentation/articles/active-directory-devquickstarts-dotnet/ Active Directory Quickstart for .Net}
  67. * for an example.
  68. * @param {string} [options.tokenAudience] The audience for which the token is requested. Valid values are 'graph', 'batch', or any other resource like 'https://vault.azure.net/'.
  69. * If tokenAudience is 'graph' then domain should also be provided and its value should not be the default 'common' tenant. It must be a string (preferrably in a guid format).
  70. * @param {string} [options.domain] The domain or tenant id containing this application. Default value "common".
  71. * @param {Environment} [options.environment] The azure environment to authenticate with.
  72. * @param {object} [options.tokenCache] The token cache. Default value is the MemoryCache object from adal.
  73. *
  74. * @returns {Promise<AuthResponse>} A Promise that resolves to AuthResponse that contains "credentials" and optional "subscriptions" array and rejects with an Error.
  75. */
  76. function withUsernamePasswordWithAuthResponse(username, password, options) {
  77. return __awaiter(this, void 0, void 0, function* () {
  78. if (!options) {
  79. options = {};
  80. }
  81. if (!options.clientId) {
  82. options.clientId = authConstants_1.AuthConstants.DEFAULT_ADAL_CLIENT_ID;
  83. }
  84. if (!options.domain) {
  85. options.domain = authConstants_1.AuthConstants.AAD_COMMON_TENANT;
  86. }
  87. if (!options.environment) {
  88. options.environment = ms_rest_azure_env_1.Environment.AzureCloud;
  89. }
  90. let creds;
  91. let tenantList = [];
  92. let subscriptionList = [];
  93. try {
  94. creds = new userTokenCredentials_1.UserTokenCredentials(options.clientId, options.domain, username, password, options.tokenAudience, options.environment);
  95. yield creds.getToken();
  96. // The token cache gets propulated for all the tenants as a part of building the tenantList.
  97. tenantList = yield subscriptionUtils_1.buildTenantList(creds);
  98. subscriptionList = yield _getSubscriptions(creds, tenantList, options.tokenAudience);
  99. }
  100. catch (err) {
  101. return Promise.reject(err);
  102. }
  103. return Promise.resolve({ credentials: creds, subscriptions: subscriptionList });
  104. });
  105. }
  106. exports.withUsernamePasswordWithAuthResponse = withUsernamePasswordWithAuthResponse;
  107. /**
  108. * Provides an ApplicationTokenCredentials object and the list of subscriptions associated with that servicePrinicpalId/clientId across all the applicable tenants.
  109. *
  110. * @param {string} clientId The active directory application client id also known as the SPN (ServicePrincipal Name).
  111. * See {@link https://azure.microsoft.com/en-us/documentation/articles/active-directory-devquickstarts-dotnet/ Active Directory Quickstart for .Net}
  112. * for an example.
  113. * @param {string} secret The application secret for the service principal.
  114. * @param {string} domain The domain or tenant id containing this application.
  115. * @param {object} [options] Object representing optional parameters.
  116. * @param {string} [options.tokenAudience] The audience for which the token is requested. Valid values are 'graph', 'batch', or any other resource like 'https://vault.azure.net/'.
  117. * If tokenAudience is 'graph' then domain should also be provided and its value should not be the default 'common' tenant. It must be a string (preferrably in a guid format).
  118. * @param {Environment} [options.environment] The azure environment to authenticate with.
  119. * @param {object} [options.tokenCache] The token cache. Default value is the MemoryCache object from adal.
  120. *
  121. * @returns {Promise<AuthResponse>} A Promise that resolves to AuthResponse that contains "credentials" and optional "subscriptions" array and rejects with an Error.
  122. */
  123. function withServicePrincipalSecretWithAuthResponse(clientId, secret, domain, options) {
  124. return __awaiter(this, void 0, void 0, function* () {
  125. if (!options) {
  126. options = {};
  127. }
  128. if (!options.environment) {
  129. options.environment = ms_rest_azure_env_1.Environment.AzureCloud;
  130. }
  131. let creds;
  132. let subscriptionList = [];
  133. try {
  134. creds = new applicationTokenCredentials_1.ApplicationTokenCredentials(clientId, domain, secret, options.tokenAudience, options.environment);
  135. yield creds.getToken();
  136. subscriptionList = yield _getSubscriptions(creds, [domain], options.tokenAudience);
  137. }
  138. catch (err) {
  139. return Promise.reject(err);
  140. }
  141. return Promise.resolve({ credentials: creds, subscriptions: subscriptionList });
  142. });
  143. }
  144. exports.withServicePrincipalSecretWithAuthResponse = withServicePrincipalSecretWithAuthResponse;
  145. /**
  146. * Provides an ApplicationTokenCertificateCredentials object and the list of subscriptions associated with that servicePrinicpalId/clientId across all the applicable tenants.
  147. *
  148. * @param {string} clientId The active directory application client id also known as the SPN (ServicePrincipal Name).
  149. * See {@link https://azure.microsoft.com/en-us/documentation/articles/active-directory-devquickstarts-dotnet/ Active Directory Quickstart for .Net}
  150. * for an example.
  151. * @param {string} certificateStringOrFilePath A PEM encoded certificate and private key OR an absolute filepath to the .pem file containing that information. For example:
  152. * - CertificateString: "-----BEGIN PRIVATE KEY-----\n<xxxxx>\n-----END PRIVATE KEY-----\n-----BEGIN CERTIFICATE-----\n<yyyyy>\n-----END CERTIFICATE-----\n"
  153. * - CertificateFilePath: **Absolute** file path of the .pem file.
  154. * @param {string} domain The domain or tenant id containing this application.
  155. * @param {object} [options] Object representing optional parameters.
  156. * @param {string} [options.tokenAudience] The audience for which the token is requested. Valid values are 'graph', 'batch', or any other resource like 'https://vault.azure.net/'.
  157. * If tokenAudience is 'graph' then domain should also be provided and its value should not be the default 'common' tenant. It must be a string (preferrably in a guid format).
  158. * @param {Environment} [options.environment] The azure environment to authenticate with.
  159. * @param {object} [options.tokenCache] The token cache. Default value is the MemoryCache object from adal.
  160. *
  161. * @returns {Promise<AuthResponse>} A Promise that resolves to AuthResponse that contains "credentials" and optional "subscriptions" array and rejects with an Error.
  162. */
  163. function withServicePrincipalCertificateWithAuthResponse(clientId, certificateStringOrFilePath, domain, options) {
  164. return __awaiter(this, void 0, void 0, function* () {
  165. if (!options) {
  166. options = {};
  167. }
  168. if (!options.environment) {
  169. options.environment = ms_rest_azure_env_1.Environment.AzureCloud;
  170. }
  171. let creds;
  172. let subscriptionList = [];
  173. try {
  174. creds = applicationTokenCertificateCredentials_1.ApplicationTokenCertificateCredentials.create(clientId, certificateStringOrFilePath, domain, options);
  175. yield creds.getToken();
  176. subscriptionList = yield _getSubscriptions(creds, [domain], options.tokenAudience);
  177. }
  178. catch (err) {
  179. return Promise.reject(err);
  180. }
  181. return Promise.resolve({ credentials: creds, subscriptions: subscriptionList });
  182. });
  183. }
  184. exports.withServicePrincipalCertificateWithAuthResponse = withServicePrincipalCertificateWithAuthResponse;
  185. function validateAuthFileContent(credsObj, filePath) {
  186. if (!credsObj) {
  187. throw new Error("Please provide a credsObj to validate.");
  188. }
  189. if (!filePath) {
  190. throw new Error("Please provide a filePath.");
  191. }
  192. if (!credsObj.clientId) {
  193. throw new Error(`"clientId" is missing from the auth file: ${filePath}.`);
  194. }
  195. if (!credsObj.clientSecret && !credsObj.clientCertificate) {
  196. throw new Error(`Either "clientSecret" or "clientCertificate" must be present in the auth file: ${filePath}.`);
  197. }
  198. if (!credsObj.subscriptionId) {
  199. throw new Error(`"subscriptionId" is missing from the auth file: ${filePath}.`);
  200. }
  201. if (!credsObj.tenantId) {
  202. throw new Error(`"tenantId" is missing from the auth file: ${filePath}.`);
  203. }
  204. if (!credsObj.activeDirectoryEndpointUrl) {
  205. throw new Error(`"activeDirectoryEndpointUrl" is missing from the auth file: ${filePath}.`);
  206. }
  207. if (!credsObj.resourceManagerEndpointUrl) {
  208. throw new Error(`"resourceManagerEndpointUrl" is missing from the auth file: ${filePath}.`);
  209. }
  210. if (!credsObj.activeDirectoryGraphResourceId) {
  211. throw new Error(`"activeDirectoryGraphResourceId" is missing from the auth file: ${filePath}.`);
  212. }
  213. if (!credsObj.sqlManagementEndpointUrl) {
  214. throw new Error(`"sqlManagementEndpointUrl" is missing from the auth file: ${filePath}.`);
  215. }
  216. }
  217. function foundManagementEndpointUrl(authFileUrl, envUrl) {
  218. if (!authFileUrl || (authFileUrl && typeof authFileUrl.valueOf() !== "string")) {
  219. throw new Error("authFileUrl cannot be null or undefined and must be of type string.");
  220. }
  221. if (!envUrl || (envUrl && typeof envUrl.valueOf() !== "string")) {
  222. throw new Error("envUrl cannot be null or undefined and must be of type string.");
  223. }
  224. authFileUrl = authFileUrl.endsWith("/") ? authFileUrl.slice(0, -1) : authFileUrl;
  225. envUrl = envUrl.endsWith("/") ? envUrl.slice(0, -1) : envUrl;
  226. return (authFileUrl.toLowerCase() === envUrl.toLowerCase());
  227. }
  228. /**
  229. * Before using this method please install az cli from https://github.com/Azure/azure-cli/releases. Then execute `az ad sp create-for-rbac --sdk-auth > ${yourFilename.json}`.
  230. * If you want to create the sp for a different cloud/environment then please execute:
  231. * 1. az cloud list
  232. * 2. az cloud set –n <name of the environment>
  233. * 3. az ad sp create-for-rbac --sdk-auth > auth.json // create sp with secret
  234. * **OR**
  235. * 3. az ad sp create-for-rbac --create-cert --sdk-auth > auth.json // create sp with certificate
  236. * If the service principal is already created then login with service principal info:
  237. * 4. az login --service-principal -u <clientId> -p <clientSecret> -t <tenantId>
  238. * 5. az account show --sdk-auth > auth.json
  239. *
  240. * Authenticates using the service principal information provided in the auth file. This method will set
  241. * the subscriptionId from the auth file to the user provided environment variable in the options
  242. * parameter or the default "AZURE_SUBSCRIPTION_ID".
  243. *
  244. * @param {object} [options] - Optional parameters
  245. * @param {string} [options.filePath] - Absolute file path to the auth file. If not provided
  246. * then please set the environment variable AZURE_AUTH_LOCATION.
  247. * @param {string} [options.subscriptionEnvVariableName] - The subscriptionId environment variable
  248. * name. Default is "AZURE_SUBSCRIPTION_ID".
  249. * @param {function} [optionalCallback] The optional callback.
  250. *
  251. * @returns {Promise<AuthResponse>} A Promise that resolves to AuthResponse that contains "credentials" and optional "subscriptions" array and rejects with an Error.
  252. */
  253. function withAuthFileWithAuthResponse(options) {
  254. return __awaiter(this, void 0, void 0, function* () {
  255. if (!options)
  256. options = { filePath: "" };
  257. const filePath = options.filePath || process.env[authConstants_1.AuthConstants.AZURE_AUTH_LOCATION];
  258. const subscriptionEnvVariableName = options.subscriptionEnvVariableName || "AZURE_SUBSCRIPTION_ID";
  259. if (!filePath) {
  260. const msg = `Either provide an absolute file path to the auth file or set/export the environment variable - ${authConstants_1.AuthConstants.AZURE_AUTH_LOCATION}.`;
  261. return Promise.reject(new Error(msg));
  262. }
  263. let content, credsObj = {};
  264. const optionsForSp = {};
  265. try {
  266. content = fs_1.readFileSync(filePath, { encoding: "utf8" });
  267. credsObj = JSON.parse(content);
  268. validateAuthFileContent(credsObj, filePath);
  269. }
  270. catch (err) {
  271. return Promise.reject(err);
  272. }
  273. if (!credsObj.managementEndpointUrl) {
  274. credsObj.managementEndpointUrl = credsObj.resourceManagerEndpointUrl;
  275. }
  276. // setting the subscriptionId from auth file to the environment variable
  277. process.env[subscriptionEnvVariableName] = credsObj.subscriptionId;
  278. // get the AzureEnvironment or create a new AzureEnvironment based on the info provided in the auth file
  279. const envFound = {
  280. name: ""
  281. };
  282. const envNames = Object.keys(ms_rest_azure_env_1.Environment);
  283. for (let i = 0; i < envNames.length; i++) {
  284. const env = envNames[i];
  285. const environmentObj = ms_rest_azure_env_1.Environment[env];
  286. if (environmentObj &&
  287. environmentObj.managementEndpointUrl &&
  288. foundManagementEndpointUrl(credsObj.managementEndpointUrl, environmentObj.managementEndpointUrl)) {
  289. envFound.name = environmentObj.name;
  290. break;
  291. }
  292. }
  293. if (envFound.name) {
  294. optionsForSp.environment = ms_rest_azure_env_1.Environment[envFound.name];
  295. }
  296. else {
  297. // create a new environment with provided info.
  298. const envParams = {
  299. // try to find a logical name or set the filepath as the env name.
  300. name: credsObj.managementEndpointUrl.match(/.*management\.core\.(.*)\..*/i)[1] || filePath
  301. };
  302. const keys = Object.keys(credsObj);
  303. for (let i = 0; i < keys.length; i++) {
  304. const key = keys[i];
  305. if (key.match(/^(clientId|clientSecret|clientCertificate|subscriptionId|tenantId)$/ig) === null) {
  306. if (key === "activeDirectoryEndpointUrl" && !key.endsWith("/")) {
  307. envParams[key] = credsObj[key] + "/";
  308. }
  309. else {
  310. envParams[key] = credsObj[key];
  311. }
  312. }
  313. }
  314. if (!envParams.activeDirectoryResourceId) {
  315. envParams.activeDirectoryResourceId = credsObj.managementEndpointUrl;
  316. }
  317. if (!envParams.portalUrl) {
  318. envParams.portalUrl = "https://portal.azure.com";
  319. }
  320. optionsForSp.environment = ms_rest_azure_env_1.Environment.add(envParams);
  321. }
  322. if (credsObj.clientSecret) {
  323. return withServicePrincipalSecretWithAuthResponse(credsObj.clientId, credsObj.clientSecret, credsObj.tenantId, optionsForSp);
  324. }
  325. return withServicePrincipalCertificateWithAuthResponse(credsObj.clientId, credsObj.clientCertificate, credsObj.tenantId, optionsForSp);
  326. });
  327. }
  328. exports.withAuthFileWithAuthResponse = withAuthFileWithAuthResponse;
  329. /**
  330. * Provides a url and code that needs to be copy and pasted in a browser and authenticated over there. If successful, the user will get a
  331. * DeviceTokenCredentials object and the list of subscriptions associated with that userId across all the applicable tenants.
  332. *
  333. * @param {object} [options] Object representing optional parameters.
  334. *
  335. * @param {string} [options.clientId] The active directory application client id.
  336. * See {@link https://azure.microsoft.com/en-us/documentation/articles/active-directory-devquickstarts-dotnet/ Active Directory Quickstart for .Net}
  337. * for an example.
  338. *
  339. * @param {string} [options.tokenAudience] The audience for which the token is requested. Valid value is "graph".If tokenAudience is provided
  340. * then domain should also be provided its value should not be the default "common" tenant. It must be a string (preferrably in a guid format).
  341. *
  342. * @param {string} [options.domain] The domain or tenant id containing this application. Default value is "common".
  343. *
  344. * @param {Environment} [options.environment] The azure environment to authenticate with. Default environment is "Public Azure".
  345. *
  346. * @param {object} [options.tokenCache] The token cache. Default value is the MemoryCache object from adal.
  347. *
  348. * @param {object} [options.language] The language code specifying how the message should be localized to. Default value "en-us".
  349. *
  350. * @param {object|function} [options.userCodeResponseLogger] A logger that logs the user code response message required for interactive login. When
  351. * this option is specified the usercode response message will not be logged to console.
  352. *
  353. * @param {function} [optionalCallback] The optional callback.
  354. *
  355. * @returns {Promise<AuthResponse>} A Promise that resolves to AuthResponse that contains "credentials" and optional "subscriptions" array and rejects with an Error.
  356. */
  357. function withInteractiveWithAuthResponse(options) {
  358. return __awaiter(this, void 0, void 0, function* () {
  359. if (!options) {
  360. options = {};
  361. }
  362. if (!options) {
  363. options = {};
  364. }
  365. if (!options.environment) {
  366. options.environment = ms_rest_azure_env_1.Environment.AzureCloud;
  367. }
  368. if (!options.domain) {
  369. options.domain = authConstants_1.AuthConstants.AAD_COMMON_TENANT;
  370. }
  371. if (!options.clientId) {
  372. options.clientId = authConstants_1.AuthConstants.DEFAULT_ADAL_CLIENT_ID;
  373. }
  374. if (!options.tokenCache) {
  375. options.tokenCache = new adal.MemoryCache();
  376. }
  377. if (!options.language) {
  378. options.language = authConstants_1.AuthConstants.DEFAULT_LANGUAGE;
  379. }
  380. if (!options.tokenAudience) {
  381. options.tokenAudience = options.environment.activeDirectoryResourceId;
  382. }
  383. const interactiveOptions = {};
  384. interactiveOptions.tokenAudience = options.tokenAudience;
  385. interactiveOptions.environment = options.environment;
  386. interactiveOptions.domain = options.domain;
  387. interactiveOptions.clientId = options.clientId;
  388. interactiveOptions.tokenCache = options.tokenCache;
  389. interactiveOptions.language = options.language;
  390. interactiveOptions.userCodeResponseLogger = options.userCodeResponseLogger;
  391. const authorityUrl = interactiveOptions.environment.activeDirectoryEndpointUrl + interactiveOptions.domain;
  392. const authContext = new adal.AuthenticationContext(authorityUrl, interactiveOptions.environment.validateAuthority, interactiveOptions.tokenCache);
  393. interactiveOptions.context = authContext;
  394. let userCodeResponse;
  395. let creds;
  396. function tryAcquireToken(interactiveOptions, resolve, reject) {
  397. authContext.acquireUserCode(interactiveOptions.tokenAudience, interactiveOptions.clientId, interactiveOptions.language, (err, userCodeRes) => {
  398. if (err) {
  399. if (err.error === "authorization_pending") {
  400. setTimeout(() => {
  401. tryAcquireToken(interactiveOptions, resolve, reject);
  402. }, 1000);
  403. }
  404. else {
  405. return reject(err);
  406. }
  407. }
  408. userCodeResponse = userCodeRes;
  409. if (interactiveOptions.userCodeResponseLogger) {
  410. interactiveOptions.userCodeResponseLogger(userCodeResponse.message);
  411. }
  412. else {
  413. console.log(userCodeResponse.message);
  414. }
  415. return resolve(userCodeResponse);
  416. });
  417. }
  418. const getUserCode = new Promise((resolve, reject) => {
  419. return tryAcquireToken(interactiveOptions, resolve, reject);
  420. });
  421. return getUserCode.then(() => {
  422. return new Promise((resolve, reject) => {
  423. return authContext.acquireTokenWithDeviceCode(interactiveOptions.tokenAudience, interactiveOptions.clientId, userCodeResponse, (error, tokenResponse) => {
  424. if (error) {
  425. return reject(error);
  426. }
  427. interactiveOptions.userName = tokenResponse.userId;
  428. interactiveOptions.authorizationScheme = tokenResponse.tokenType;
  429. try {
  430. creds = new deviceTokenCredentials_1.DeviceTokenCredentials(interactiveOptions.clientId, interactiveOptions.domain, interactiveOptions.userName, interactiveOptions.tokenAudience, interactiveOptions.environment, interactiveOptions.tokenCache);
  431. }
  432. catch (err) {
  433. return reject(err);
  434. }
  435. return resolve(creds);
  436. });
  437. });
  438. }).then((creds) => {
  439. return subscriptionUtils_1.buildTenantList(creds);
  440. }).then((tenants) => {
  441. return _getSubscriptions(creds, tenants, interactiveOptions.tokenAudience);
  442. }).then((subscriptions) => {
  443. return Promise.resolve({ credentials: creds, subscriptions: subscriptions });
  444. });
  445. });
  446. }
  447. exports.withInteractiveWithAuthResponse = withInteractiveWithAuthResponse;
  448. function withAuthFile(options, callback) {
  449. if (!callback && typeof options === "function") {
  450. callback = options;
  451. options = undefined;
  452. }
  453. const cb = callback;
  454. if (!callback) {
  455. return withAuthFileWithAuthResponse(options).then((authRes) => {
  456. return Promise.resolve(authRes.credentials);
  457. }).catch((err) => {
  458. return Promise.reject(err);
  459. });
  460. }
  461. else {
  462. msRest.promiseToCallback(withAuthFileWithAuthResponse(options))((err, authRes) => {
  463. if (err) {
  464. return cb(err);
  465. }
  466. return cb(undefined, authRes.credentials, authRes.subscriptions);
  467. });
  468. }
  469. }
  470. exports.withAuthFile = withAuthFile;
  471. function interactive(options, callback) {
  472. if (!callback && typeof options === "function") {
  473. callback = options;
  474. options = undefined;
  475. }
  476. const cb = callback;
  477. if (!callback) {
  478. return withInteractiveWithAuthResponse(options).then((authRes) => {
  479. return Promise.resolve(authRes.credentials);
  480. }).catch((err) => {
  481. return Promise.reject(err);
  482. });
  483. }
  484. else {
  485. msRest.promiseToCallback(withInteractiveWithAuthResponse(options))((err, authRes) => {
  486. if (err) {
  487. return cb(err);
  488. }
  489. return cb(undefined, authRes.credentials, authRes.subscriptions);
  490. });
  491. }
  492. }
  493. exports.interactive = interactive;
  494. function withServicePrincipalSecret(clientId, secret, domain, options, callback) {
  495. if (!callback && typeof options === "function") {
  496. callback = options;
  497. options = undefined;
  498. }
  499. const cb = callback;
  500. if (!callback) {
  501. return withServicePrincipalSecretWithAuthResponse(clientId, secret, domain, options).then((authRes) => {
  502. return Promise.resolve(authRes.credentials);
  503. }).catch((err) => {
  504. return Promise.reject(err);
  505. });
  506. }
  507. else {
  508. msRest.promiseToCallback(withServicePrincipalSecretWithAuthResponse(clientId, secret, domain, options))((err, authRes) => {
  509. if (err) {
  510. return cb(err);
  511. }
  512. return cb(undefined, authRes.credentials, authRes.subscriptions);
  513. });
  514. }
  515. }
  516. exports.withServicePrincipalSecret = withServicePrincipalSecret;
  517. function withServicePrincipalCertificate(clientId, certificateStringOrFilePath, domain, options, callback) {
  518. if (!callback && typeof options === "function") {
  519. callback = options;
  520. options = undefined;
  521. }
  522. const cb = callback;
  523. if (!callback) {
  524. return withServicePrincipalCertificateWithAuthResponse(clientId, certificateStringOrFilePath, domain, options).then((authRes) => {
  525. return Promise.resolve(authRes.credentials);
  526. }).catch((err) => {
  527. return Promise.reject(err);
  528. });
  529. }
  530. else {
  531. msRest.promiseToCallback(withServicePrincipalCertificateWithAuthResponse(clientId, certificateStringOrFilePath, domain, options))((err, authRes) => {
  532. if (err) {
  533. return cb(err);
  534. }
  535. return cb(undefined, authRes.credentials, authRes.subscriptions);
  536. });
  537. }
  538. }
  539. exports.withServicePrincipalCertificate = withServicePrincipalCertificate;
  540. function withUsernamePassword(username, password, options, callback) {
  541. if (!callback && typeof options === "function") {
  542. callback = options;
  543. options = undefined;
  544. }
  545. const cb = callback;
  546. if (!callback) {
  547. return withUsernamePasswordWithAuthResponse(username, password, options).then((authRes) => {
  548. return Promise.resolve(authRes.credentials);
  549. }).catch((err) => {
  550. return Promise.reject(err);
  551. });
  552. }
  553. else {
  554. msRest.promiseToCallback(withUsernamePasswordWithAuthResponse(username, password, options))((err, authRes) => {
  555. if (err) {
  556. return cb(err);
  557. }
  558. return cb(undefined, authRes.credentials, authRes.subscriptions);
  559. });
  560. }
  561. }
  562. exports.withUsernamePassword = withUsernamePassword;
  563. /**
  564. * We only need to get the subscription list if the tokenAudience is for a management client.
  565. */
  566. function _getSubscriptions(creds, tenants, tokenAudience) {
  567. if (tokenAudience &&
  568. !managementPlaneTokenAudiences.some((item) => { return item === tokenAudience.toLowerCase(); })) {
  569. return Promise.resolve(([]));
  570. }
  571. return subscriptionUtils_1.getSubscriptionsFromTenants(creds, tenants);
  572. }
  573. /**
  574. * Initializes MSITokenCredentials class and calls getToken and returns a token response.
  575. *
  576. * @param {string} domain - required. The tenant id.
  577. * @param {object} options - Optional parameters
  578. * @param {string} [options.port] - port on which the MSI service is running on the host VM. Default port is 50342
  579. * @param {string} [options.resource] - The resource uri or token audience for which the token is needed. Default - "https://management.azure.com/"
  580. * @param {string} [options.aadEndpoint] - The add endpoint for authentication. default - "https://login.microsoftonline.com"
  581. * @param {any} callback - the callback function.
  582. */
  583. function _withMSI(options) {
  584. if (!options) {
  585. options = {};
  586. }
  587. return new Promise((resolve, reject) => {
  588. const creds = new msiVmTokenCredentials_1.MSIVmTokenCredentials(options);
  589. creds.getToken().then((_tokenResponse) => {
  590. // We ignore the token response, it's put in the cache.
  591. return resolve(creds);
  592. }).catch(error => {
  593. reject(error);
  594. });
  595. });
  596. }
  597. function loginWithVmMSI(options, callback) {
  598. if (!callback && typeof options === "function") {
  599. callback = options;
  600. options = {};
  601. }
  602. const cb = callback;
  603. if (!callback) {
  604. return _withMSI(options);
  605. }
  606. else {
  607. msRest.promiseToCallback(_withMSI(options))((err, tokenRes) => {
  608. if (err) {
  609. return cb(err);
  610. }
  611. return cb(undefined, tokenRes);
  612. });
  613. }
  614. }
  615. exports.loginWithVmMSI = loginWithVmMSI;
  616. /**
  617. * Private method
  618. */
  619. function _withAppServiceMSI(options) {
  620. if (!options) {
  621. options = {};
  622. }
  623. return new Promise((resolve, reject) => {
  624. const creds = new msiAppServiceTokenCredentials_1.MSIAppServiceTokenCredentials(options);
  625. creds.getToken().then((_tokenResponse) => {
  626. // We ignore the token response, it's put in the cache.
  627. return resolve(creds);
  628. }).catch(error => {
  629. reject(error);
  630. });
  631. });
  632. }
  633. function loginWithAppServiceMSI(options, callback) {
  634. if (!callback && typeof options === "function") {
  635. callback = options;
  636. options = {};
  637. }
  638. const cb = callback;
  639. if (!callback) {
  640. return _withAppServiceMSI(options);
  641. }
  642. else {
  643. msRest.promiseToCallback(_withAppServiceMSI(options))((err, tokenRes) => {
  644. if (err) {
  645. return cb(err);
  646. }
  647. return cb(undefined, tokenRes);
  648. });
  649. }
  650. }
  651. exports.loginWithAppServiceMSI = loginWithAppServiceMSI;
  652. /**
  653. * Executes the azure cli command and returns the result. It will be `undefined` if the command did
  654. * not return anything or a `JSON object` if the command did return something.
  655. * @param cmd The az cli command to execute.
  656. */
  657. function execAz(cmd) {
  658. return __awaiter(this, void 0, void 0, function* () {
  659. return new Promise((resolve, reject) => {
  660. child_process_1.exec(`az ${cmd} --out json`, { encoding: "utf8" }, (error, stdout) => {
  661. if (error) {
  662. return reject(error);
  663. }
  664. if (stdout) {
  665. try {
  666. return resolve(JSON.parse(stdout));
  667. }
  668. catch (err) {
  669. const msg = `An error occured while parsing the output "${stdout}", of ` +
  670. `the cmd "${cmd}": ${err.stack}.`;
  671. return reject(new Error(msg));
  672. }
  673. }
  674. return resolve();
  675. });
  676. });
  677. });
  678. }
  679. exports.execAz = execAz;
  680. //# sourceMappingURL=login.js.map