subscriptionUtils.ts 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. // Copyright (c) Microsoft Corporation. All rights reserved.
  2. // Licensed under the MIT License. See License.txt in the project root for license information.
  3. import * as msRest from "@azure/ms-rest-js";
  4. import { TokenCredentialsBase } from "../credentials/tokenCredentialsBase";
  5. import { ApplicationTokenCredentialsBase } from "../credentials/applicationTokenCredentialsBase";
  6. import { AuthConstants } from "../util/authConstants";
  7. /**
  8. * @interface UserType Provides information about user type. It can currently be "user" or "servicePrincipal".
  9. */
  10. export type UserType = "user" | "servicePrincipal";
  11. /**
  12. * @interface LinkedUser Provides information about a user from the authentication perspective.
  13. */
  14. export interface LinkedUser {
  15. /**
  16. * @property {string} name - The user name. For ApplicationTokenCredentials it can be the clientId or SPN.
  17. */
  18. name: string;
  19. /**
  20. * @property {string} type - The user type. "user" | "servicePrincipal".
  21. */
  22. type: UserType;
  23. }
  24. /**
  25. * @interface LinkedSubscription Provides information about subscription that was found
  26. * during the authentication process. The structure of this type is different from the
  27. * subscription object that one gets by making a request to the ResourceManager API.
  28. */
  29. export interface LinkedSubscription {
  30. /**
  31. * @property {string} tenantId - The tenant that the subscription belongs to.
  32. */
  33. readonly tenantId: string;
  34. /**
  35. * @property {string} user - The user associated with the subscription. This could be a user or a serviceprincipal.
  36. */
  37. readonly user: LinkedUser;
  38. /**
  39. * @property {string} environmentName - The environment name in which the subscription exists.
  40. * Possible values: "AzureCloud", "AzureChinaCloud", "AzureUSGovernment", "AzureGermanCloud" or
  41. * some other custom/internal environment name like "Dogfood".
  42. */
  43. readonly environmentName: string;
  44. /**
  45. * @property {string} name - The display name of the subscription.
  46. */
  47. readonly name: string;
  48. /**
  49. * @property {string} id - The subscription id, usually a GUID.
  50. */
  51. readonly id: string;
  52. /**
  53. * @property {string} authorizationSource - The authorization source of the subscription: "RoleBased",
  54. * "Legacy", "Bypassed"," Direct", "Management". It could also be a comma separated string containing
  55. * more values "Bypassed, Direct, Management".
  56. */
  57. readonly authorizationSource: string;
  58. /**
  59. * @property {string} state - The state of the subscription. Example values: "Enabled", "Disabled",
  60. * "Warned", "PastDue", "Deleted".
  61. */
  62. readonly state: string;
  63. /**
  64. * @property {any} any Placeholder for unknown properties.
  65. */
  66. readonly [x: string]: any;
  67. }
  68. /**
  69. * Builds an array of tenantIds.
  70. * @param {TokenCredentialsBase} credentials The credentials.
  71. * @param {string} apiVersion default value 2016-06-01
  72. * @returns {Promise<string[]>} resolves to an array of tenantIds and rejects with an error.
  73. */
  74. export async function buildTenantList(credentials: TokenCredentialsBase, apiVersion = "2016-06-01"): Promise<string[]> {
  75. if (credentials.domain && credentials.domain !== AuthConstants.AAD_COMMON_TENANT) {
  76. return Promise.resolve([credentials.domain]);
  77. }
  78. const client = new msRest.ServiceClient(credentials);
  79. const baseUrl = credentials.environment.resourceManagerEndpointUrl;
  80. const reqUrl = `${baseUrl}${baseUrl.endsWith("/") ? "" : "/"}tenants?api-version=${apiVersion}`;
  81. const req: msRest.RequestPrepareOptions = {
  82. url: reqUrl,
  83. method: "GET",
  84. };
  85. let res: msRest.HttpOperationResponse;
  86. try {
  87. res = await client.sendRequest(req);
  88. } catch (err) {
  89. return Promise.reject(err);
  90. }
  91. const result: string[] = [];
  92. const tenants: any = res.parsedBody;
  93. for (const tenant in tenants.value) {
  94. result.push((<any>tenant).tenantId);
  95. }
  96. return Promise.resolve(result);
  97. }
  98. export async function getSubscriptionsFromTenants(credentials: TokenCredentialsBase, tenantList: string[], apiVersion = "2016-06-01"): Promise<LinkedSubscription[]> {
  99. let subscriptions: LinkedSubscription[] = [];
  100. let userType = "user";
  101. let username: string;
  102. const originalDomain = credentials.domain;
  103. if (credentials instanceof ApplicationTokenCredentialsBase) {
  104. userType = "servicePrincipal";
  105. username = credentials.clientId;
  106. } else {
  107. username = (<any>credentials).username;
  108. }
  109. for (const tenant of tenantList) {
  110. credentials.domain = tenant;
  111. const client = new msRest.ServiceClient(credentials);
  112. const baseUrl = credentials.environment.resourceManagerEndpointUrl;
  113. const reqUrl = `${baseUrl}${baseUrl.endsWith("/") ? "" : "/"}subscriptions?api-version=${apiVersion}`;
  114. const req: msRest.RequestPrepareOptions = {
  115. url: reqUrl,
  116. method: "GET",
  117. };
  118. let res: msRest.HttpOperationResponse;
  119. try {
  120. res = await client.sendRequest(req);
  121. } catch (err) {
  122. return Promise.reject(err);
  123. }
  124. const subscriptionList: any[] = (<any>res.parsedBody).value;
  125. subscriptions = subscriptions.concat(subscriptionList.map((s: any) => {
  126. s.tenantId = tenant;
  127. s.user = { name: username, type: userType };
  128. s.environmentName = credentials.environment.name;
  129. s.name = s.displayName;
  130. s.id = s.subscriptionId;
  131. delete s.displayName;
  132. delete s.subscriptionId;
  133. delete s.subscriptionPolicies;
  134. return s;
  135. }));
  136. }
  137. // Reset the original domain.
  138. credentials.domain = originalDomain;
  139. return Promise.resolve(subscriptions);
  140. }