opal-security 3.2.3 → 4.0.2

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.
Files changed (150) hide show
  1. package/README.md +46 -61
  2. package/bin/dev +5 -5
  3. package/bin/run +2 -4
  4. package/build/commands/aws/identity.js +16 -0
  5. package/build/commands/clear-auth-config.d.ts +6 -0
  6. package/build/commands/clear-auth-config.js +22 -0
  7. package/{lib → build}/commands/groups/get.js +14 -16
  8. package/{lib → build}/commands/iam-roles/start.js +28 -30
  9. package/build/commands/kube-roles/start.js +71 -0
  10. package/{lib → build}/commands/login.d.ts +1 -0
  11. package/build/commands/login.js +379 -0
  12. package/build/commands/logout.js +22 -0
  13. package/{lib → build}/commands/postgres-instances/start.js +25 -27
  14. package/{lib → build}/commands/request/create.js +34 -36
  15. package/{lib → build}/commands/request/get.js +22 -24
  16. package/{lib → build}/commands/request/list.js +17 -19
  17. package/{lib → build}/commands/resources/get.js +15 -18
  18. package/build/commands/set-auth-config.d.ts +11 -0
  19. package/build/commands/set-auth-config.js +59 -0
  20. package/build/commands/set-custom-header.js +35 -0
  21. package/{lib → build}/commands/set-token.js +15 -17
  22. package/{lib → build}/commands/set-url.js +26 -28
  23. package/{lib → build}/commands/ssh/copyFrom.js +22 -24
  24. package/{lib → build}/commands/ssh/copyTo.js +22 -24
  25. package/{lib → build}/commands/ssh/start.js +30 -33
  26. package/build/commands/whoami.js +27 -0
  27. package/{lib → build}/graphql/fragment-masking.d.ts +1 -1
  28. package/{lib → build}/graphql/fragment-masking.js +3 -8
  29. package/{lib → build}/graphql/gql.d.ts +1 -1
  30. package/{lib → build}/graphql/gql.js +2 -5
  31. package/{lib → build}/graphql/graphql.js +256 -261
  32. package/build/graphql/index.d.ts +2 -0
  33. package/build/graphql/index.js +2 -0
  34. package/{lib → build}/handler.d.ts +1 -1
  35. package/build/handler.js +36 -0
  36. package/build/index.js +1 -0
  37. package/{lib → build}/labels.d.ts +1 -1
  38. package/build/labels.js +37 -0
  39. package/{lib → build}/lib/apollo.d.ts +2 -2
  40. package/{lib → build}/lib/apollo.js +62 -69
  41. package/build/lib/auth-success-template.d.ts +3 -0
  42. package/build/lib/auth-success-template.js +149 -0
  43. package/{lib → build}/lib/aws.js +2 -7
  44. package/{lib → build}/lib/cmd.d.ts +4 -4
  45. package/{lib → build}/lib/cmd.js +16 -20
  46. package/build/lib/config.js +46 -0
  47. package/{lib → build}/lib/credentials/index.d.ts +3 -2
  48. package/build/lib/credentials/index.js +85 -0
  49. package/{lib → build}/lib/credentials/keychain.js +4 -10
  50. package/{lib → build}/lib/credentials/localEncryption.js +12 -17
  51. package/{lib → build}/lib/flags.js +7 -10
  52. package/build/lib/local-auth-server.d.ts +5 -0
  53. package/build/lib/local-auth-server.js +69 -0
  54. package/build/lib/request/api/index.d.ts +6 -0
  55. package/build/lib/request/api/index.js +8 -0
  56. package/{lib → build}/lib/request/api/mutations/create-request.d.ts +2 -2
  57. package/{lib → build}/lib/request/api/mutations/create-request.js +3 -6
  58. package/{lib → build}/lib/request/api/queries/apps.d.ts +1 -1
  59. package/{lib → build}/lib/request/api/queries/apps.js +3 -6
  60. package/{lib → build}/lib/request/api/queries/assets.d.ts +2 -2
  61. package/{lib → build}/lib/request/api/queries/assets.js +7 -11
  62. package/{lib → build}/lib/request/api/queries/request-defaults.d.ts +2 -2
  63. package/{lib → build}/lib/request/api/queries/request-defaults.js +3 -6
  64. package/{lib → build}/lib/request/api/queries/requests.d.ts +3 -3
  65. package/{lib → build}/lib/request/api/queries/requests.js +10 -16
  66. package/{lib → build}/lib/request/api/queries/roles.d.ts +1 -1
  67. package/{lib → build}/lib/request/api/queries/roles.js +14 -18
  68. package/{lib → build}/lib/request/displays.d.ts +2 -2
  69. package/{lib → build}/lib/request/displays.js +27 -37
  70. package/{lib → build}/lib/request/prompts/apps-prompt.d.ts +1 -1
  71. package/build/lib/request/prompts/apps-prompt.js +33 -0
  72. package/{lib → build}/lib/request/prompts/asset-prompt.d.ts +1 -1
  73. package/build/lib/request/prompts/asset-prompt.js +61 -0
  74. package/{lib → build}/lib/request/prompts/duration-prompt.d.ts +1 -1
  75. package/{lib → build}/lib/request/prompts/duration-prompt.js +6 -10
  76. package/build/lib/request/prompts/index.d.ts +7 -0
  77. package/build/lib/request/prompts/index.js +8 -0
  78. package/{lib → build}/lib/request/prompts/reason-prompt.d.ts +1 -1
  79. package/{lib → build}/lib/request/prompts/reason-prompt.js +3 -6
  80. package/{lib → build}/lib/request/prompts/role-prompt.d.ts +1 -1
  81. package/build/lib/request/prompts/role-prompt.js +33 -0
  82. package/{lib → build}/lib/request/prompts/validate-prompt.d.ts +1 -1
  83. package/{lib → build}/lib/request/prompts/validate-prompt.js +9 -13
  84. package/{lib → build}/lib/request/request-utils.d.ts +2 -2
  85. package/{lib → build}/lib/request/request-utils.js +50 -62
  86. package/{lib → build}/lib/request/types.d.ts +1 -1
  87. package/build/lib/request/types.js +12 -0
  88. package/{lib → build}/lib/resources.d.ts +1 -1
  89. package/{lib → build}/lib/resources.js +18 -23
  90. package/{lib → build}/lib/sessions.d.ts +1 -1
  91. package/{lib → build}/lib/sessions.js +57 -32
  92. package/{lib → build}/lib/ssh.d.ts +1 -1
  93. package/{lib → build}/lib/ssh.js +6 -11
  94. package/{lib → build}/lib/util.js +7 -14
  95. package/{lib → build}/types.js +98 -101
  96. package/oclif.manifest.json +77 -98
  97. package/package.json +24 -14
  98. package/lib/commands/aws/identity.js +0 -18
  99. package/lib/commands/clear-auth-provider.d.ts +0 -9
  100. package/lib/commands/clear-auth-provider.js +0 -28
  101. package/lib/commands/curl-example.d.ts +0 -8
  102. package/lib/commands/curl-example.js +0 -34
  103. package/lib/commands/kube-roles/start.js +0 -73
  104. package/lib/commands/login.js +0 -286
  105. package/lib/commands/logout.js +0 -23
  106. package/lib/commands/set-auth-provider.d.ts +0 -11
  107. package/lib/commands/set-auth-provider.js +0 -44
  108. package/lib/commands/set-custom-header.js +0 -37
  109. package/lib/commands/whoami.js +0 -34
  110. package/lib/graphql/index.d.ts +0 -2
  111. package/lib/graphql/index.js +0 -5
  112. package/lib/handler.js +0 -41
  113. package/lib/index.js +0 -5
  114. package/lib/labels.js +0 -40
  115. package/lib/lib/config.js +0 -54
  116. package/lib/lib/credentials/index.js +0 -67
  117. package/lib/lib/request/api/index.d.ts +0 -6
  118. package/lib/lib/request/api/index.js +0 -20
  119. package/lib/lib/request/prompts/apps-prompt.js +0 -35
  120. package/lib/lib/request/prompts/asset-prompt.js +0 -81
  121. package/lib/lib/request/prompts/index.d.ts +0 -8
  122. package/lib/lib/request/prompts/index.js +0 -20
  123. package/lib/lib/request/prompts/role-prompt.js +0 -44
  124. package/lib/lib/request/types.js +0 -15
  125. /package/{lib → build}/commands/aws/identity.d.ts +0 -0
  126. /package/{lib → build}/commands/groups/get.d.ts +0 -0
  127. /package/{lib → build}/commands/iam-roles/start.d.ts +0 -0
  128. /package/{lib → build}/commands/kube-roles/start.d.ts +0 -0
  129. /package/{lib → build}/commands/logout.d.ts +0 -0
  130. /package/{lib → build}/commands/postgres-instances/start.d.ts +0 -0
  131. /package/{lib → build}/commands/request/create.d.ts +0 -0
  132. /package/{lib → build}/commands/request/get.d.ts +0 -0
  133. /package/{lib → build}/commands/request/list.d.ts +0 -0
  134. /package/{lib → build}/commands/resources/get.d.ts +0 -0
  135. /package/{lib → build}/commands/set-custom-header.d.ts +0 -0
  136. /package/{lib → build}/commands/set-token.d.ts +0 -0
  137. /package/{lib → build}/commands/set-url.d.ts +0 -0
  138. /package/{lib → build}/commands/ssh/copyFrom.d.ts +0 -0
  139. /package/{lib → build}/commands/ssh/copyTo.d.ts +0 -0
  140. /package/{lib → build}/commands/ssh/start.d.ts +0 -0
  141. /package/{lib → build}/commands/whoami.d.ts +0 -0
  142. /package/{lib → build}/graphql/graphql.d.ts +0 -0
  143. /package/{lib → build}/index.d.ts +0 -0
  144. /package/{lib → build}/lib/aws.d.ts +0 -0
  145. /package/{lib → build}/lib/config.d.ts +0 -0
  146. /package/{lib → build}/lib/credentials/keychain.d.ts +0 -0
  147. /package/{lib → build}/lib/credentials/localEncryption.d.ts +0 -0
  148. /package/{lib → build}/lib/flags.d.ts +0 -0
  149. /package/{lib → build}/lib/util.d.ts +0 -0
  150. /package/{lib → build}/types.d.ts +0 -0
@@ -1,28 +1,16 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.initEmptyRequestMetadata = initEmptyRequestMetadata;
4
- exports.setRequestDefaults = setRequestDefaults;
5
- exports.submitFinalRequest = submitFinalRequest;
6
- exports.getRequestLink = getRequestLink;
7
- exports.generateRequestLink = generateRequestLink;
8
- exports.bypassRequestSelection = bypassRequestSelection;
9
- exports.bypassDuration = bypassDuration;
10
- exports.getRequestMessageFromCode = getRequestMessageFromCode;
11
- exports.duplicateRequestTemplate = duplicateRequestTemplate;
12
- exports.copyBundleAssets = copyBundleAssets;
13
- const chalk_1 = require("chalk");
14
- const graphql_1 = require("../../graphql/graphql");
15
- const labels_1 = require("../../labels");
16
- const config_1 = require("../../lib/config");
17
- const api_1 = require("./api");
18
- const requests_1 = require("./api/queries/requests");
19
- const displays_1 = require("./displays");
20
- const types_1 = require("./types");
1
+ import chalk from "chalk";
2
+ import { EntityType, RequestMessageCode, RequestStatus, ThirdPartyProvider, } from "../../graphql/graphql.js";
3
+ import { connectionTypeLabelByType } from "../../labels.js";
4
+ import { getOrCreateConfigData, urlKey } from "../../lib/config.js";
5
+ import { createRequest, queryCatalogItems, queryRequest, queryRequestDefaults, } from "./api/index.js";
6
+ import { queryBundle } from "./api/queries/requests.js";
7
+ import { displayRequestAgain, formatDuration, getStyledStatus, } from "./displays.js";
8
+ import { entityTypeFromString, } from "./types.js";
21
9
  /*
22
10
  Init Request Metadata
23
11
  This function initializes the request metadata with empty defaults and an empty request map.
24
12
  */
25
- function initEmptyRequestMetadata() {
13
+ export function initEmptyRequestMetadata() {
26
14
  // Initialize with empty defaults
27
15
  const requestDefaults = {
28
16
  durationOptions: [],
@@ -48,7 +36,7 @@ After setting up the request map, this function fetches the request defaults
48
36
  from the server based on the requested resources and groups.
49
37
  It updates the metadata with the fetched defaults.
50
38
  */
51
- async function setRequestDefaults(cmd, client, metadata) {
39
+ export async function setRequestDefaults(cmd, client, metadata) {
52
40
  var _a;
53
41
  const requestMap = metadata.requestMap;
54
42
  const requestedResources = [];
@@ -62,14 +50,14 @@ async function setRequestDefaults(cmd, client, metadata) {
62
50
  const roleIds = mappedRoles.length ? mappedRoles : [""];
63
51
  for (const roleId of roleIds) {
64
52
  switch (assetNode.type) {
65
- case graphql_1.EntityType.Resource: {
53
+ case EntityType.Resource: {
66
54
  requestedResources.push({
67
55
  resourceId: assetId,
68
56
  accessLevelRemoteId: roleId,
69
57
  });
70
58
  break;
71
59
  }
72
- case graphql_1.EntityType.Group: {
60
+ case EntityType.Group: {
73
61
  requestedGroups.push({
74
62
  groupId: assetId,
75
63
  accessLevelRemoteId: roleId,
@@ -82,7 +70,7 @@ async function setRequestDefaults(cmd, client, metadata) {
82
70
  }
83
71
  }
84
72
  try {
85
- const requestDefaults = await (0, api_1.queryRequestDefaults)(cmd, client, requestedResources, requestedGroups);
73
+ const requestDefaults = await queryRequestDefaults(cmd, client, requestedResources, requestedGroups);
86
74
  if (requestDefaults !== undefined) {
87
75
  metadata.requestDefaults.durationOptions =
88
76
  requestDefaults.durationOptions;
@@ -113,7 +101,7 @@ async function setRequestDefaults(cmd, client, metadata) {
113
101
  }
114
102
  }
115
103
  // Log the request message based on the code
116
- cmd.log(chalk_1.default.dim(`\n${chalk_1.default.italic(message.level)}:`), getRequestMessageFromCode(cmd, message.code, connectionName, connectionType));
104
+ cmd.log(chalk.dim(`\n${chalk.italic(message.level)}:`), getRequestMessageFromCode(cmd, message.code, connectionName, connectionType));
117
105
  if (message.level === "ERROR") {
118
106
  process.exit(1);
119
107
  }
@@ -121,7 +109,7 @@ async function setRequestDefaults(cmd, client, metadata) {
121
109
  if (requestDefaults.requireSupportTicket) {
122
110
  cmd.log("\nA support ticket is required for this request. Please submit through the Opal website.");
123
111
  const requestLink = generateRequestLink(cmd, (_a = metadata.requestDefaults.defaultDurationInMinutes) !== null && _a !== void 0 ? _a : 60);
124
- cmd.log(`${chalk_1.default.bold("Link:")} ${requestLink}\n`);
112
+ cmd.log(`${chalk.bold("Link:")} ${requestLink}\n`);
125
113
  process.exit(1);
126
114
  }
127
115
  }
@@ -130,7 +118,7 @@ async function setRequestDefaults(cmd, client, metadata) {
130
118
  cmd.error("Error fetching request defaults.");
131
119
  }
132
120
  }
133
- async function submitFinalRequest(cmd, client, metadata) {
121
+ export async function submitFinalRequest(cmd, client, metadata) {
134
122
  var _a, _b, _c, _d;
135
123
  // Build requested assets lists for the mutation
136
124
  const requestedResources = [];
@@ -147,7 +135,7 @@ async function submitFinalRequest(cmd, client, metadata) {
147
135
  const roleIds = mappedRoles.length > 0 ? mappedRoles : [""];
148
136
  for (const roleId of roleIds) {
149
137
  switch (assetNode.type) {
150
- case graphql_1.EntityType.Resource: {
138
+ case EntityType.Resource: {
151
139
  requestedResources.push({
152
140
  resourceId: assetId,
153
141
  accessLevel: {
@@ -157,7 +145,7 @@ async function submitFinalRequest(cmd, client, metadata) {
157
145
  });
158
146
  break;
159
147
  }
160
- case graphql_1.EntityType.Group: {
148
+ case EntityType.Group: {
161
149
  requestedGroups.push({
162
150
  groupId: assetId,
163
151
  accessLevel: {
@@ -172,30 +160,30 @@ async function submitFinalRequest(cmd, client, metadata) {
172
160
  }
173
161
  }
174
162
  }
175
- const resp = await (0, api_1.createRequest)(cmd, client, requestedResources, requestedGroups, metadata.reason, metadata.durationInMinutes);
163
+ const resp = await createRequest(cmd, client, requestedResources, requestedGroups, metadata.reason, metadata.durationInMinutes);
176
164
  // Build link to request
177
165
  if (resp === null || resp === void 0 ? void 0 : resp.id) {
178
166
  cmd.log("\n🎉 Your Access Request has been submitted!\n");
179
- cmd.log(`${chalk_1.default.bold("ID:")} ${chalk_1.default.cyan(resp.id)}`);
167
+ cmd.log(`${chalk.bold("ID:")} ${chalk.cyan(resp.id)}`);
180
168
  if (resp === null || resp === void 0 ? void 0 : resp.status) {
181
- cmd.log((0, displays_1.getStyledStatus)(resp.status));
169
+ cmd.log(getStyledStatus(resp.status));
182
170
  }
183
171
  const requestLink = getRequestLink(cmd, resp.id);
184
- cmd.log(`${chalk_1.default.bold("Link:")} ${chalk_1.default.underline(requestLink)}\n`);
185
- (0, displays_1.displayRequestAgain)(cmd, resp.id);
172
+ cmd.log(`${chalk.bold("Link:")} ${chalk.underline(requestLink)}\n`);
173
+ displayRequestAgain(cmd, resp.id);
186
174
  }
187
175
  return;
188
176
  }
189
- function getRequestLink(cmd, id) {
190
- const configData = (0, config_1.getOrCreateConfigData)(cmd.config.configDir);
191
- return `${configData[config_1.urlKey]}/requests/sent/${id}`;
177
+ export function getRequestLink(cmd, id) {
178
+ const configData = getOrCreateConfigData(cmd.config.configDir);
179
+ return `${configData[urlKey]}/requests/sent/${id}`;
192
180
  }
193
- function generateRequestLink(cmd, defaultDurationInMinutes) {
194
- const configData = (0, config_1.getOrCreateConfigData)(cmd.config.configDir);
181
+ export function generateRequestLink(cmd, defaultDurationInMinutes) {
182
+ const configData = getOrCreateConfigData(cmd.config.configDir);
195
183
  // Including the duration in the URL so that the cancel button on the request page works as expected
196
- return `${configData[config_1.urlKey]}/request-access?durationInMinutes=${defaultDurationInMinutes}`;
184
+ return `${configData[urlKey]}/request-access?durationInMinutes=${defaultDurationInMinutes}`;
197
185
  }
198
- async function bypassRequestSelection(cmd, client, flagValue, metadata) {
186
+ export async function bypassRequestSelection(cmd, client, flagValue, metadata) {
199
187
  var _a, _b, _c, _d;
200
188
  try {
201
189
  // Query Catalog Item endpoint to identify what the id belongs to (resource or group)
@@ -203,7 +191,7 @@ async function bypassRequestSelection(cmd, client, flagValue, metadata) {
203
191
  const delimiterIndex = val.indexOf(":");
204
192
  const assetId = delimiterIndex === -1 ? val : val.substring(0, delimiterIndex);
205
193
  const roleName = delimiterIndex === -1 ? "" : val.substring(delimiterIndex + 1);
206
- const resp = await (0, api_1.queryCatalogItems)(cmd, client, assetId);
194
+ const resp = await queryCatalogItems(cmd, client, assetId);
207
195
  switch ((_a = resp.data) === null || _a === void 0 ? void 0 : _a.catalogItem.__typename) {
208
196
  case "Group":
209
197
  case "Resource": {
@@ -228,7 +216,7 @@ async function bypassRequestSelection(cmd, client, flagValue, metadata) {
228
216
  metadata.requestMap[appId].assets[assetId] = {
229
217
  assetId: assetId,
230
218
  assetName: assetName,
231
- type: (0, types_1.entityTypeFromString)(item.__typename),
219
+ type: entityTypeFromString(item.__typename),
232
220
  roles: {},
233
221
  };
234
222
  }
@@ -262,12 +250,12 @@ async function bypassRequestSelection(cmd, client, flagValue, metadata) {
262
250
  }
263
251
  return;
264
252
  }
265
- function bypassDuration(cmd, duration, metadata) {
253
+ export function bypassDuration(cmd, duration, metadata) {
266
254
  const maxDuration = metadata.requestDefaults.maxDurationInMinutes;
267
255
  // Permanent duration is represented by 0, but should not be allowed
268
256
  // if a max duration is set.
269
257
  if (maxDuration && (duration > maxDuration || duration === 0)) {
270
- cmd.error(`The requested duration exceeds the allowed limit of ${(0, displays_1.formatDuration)(maxDuration)}. Please choose a shorter duration.`);
258
+ cmd.error(`The requested duration exceeds the allowed limit of ${formatDuration(maxDuration)}. Please choose a shorter duration.`);
271
259
  }
272
260
  if (duration === 0) {
273
261
  metadata.durationInMinutes = undefined;
@@ -276,21 +264,21 @@ function bypassDuration(cmd, duration, metadata) {
276
264
  metadata.durationInMinutes = duration;
277
265
  }
278
266
  }
279
- function getRequestMessageFromCode(cmd, code, connectionName, connectionType, extraParams,
267
+ export function getRequestMessageFromCode(cmd, code, connectionName, connectionType, extraParams,
280
268
  // sourceGroup?: PropsFor<typeof GroupBindingGroupLabel>["group"];
281
269
  sourceGroupRedirect) {
282
270
  switch (code) {
283
- case graphql_1.RequestMessageCode.RequireUserAuthToken: {
271
+ case RequestMessageCode.RequireUserAuthToken: {
284
272
  if (connectionType) {
285
- const connectionLabel = labels_1.connectionTypeLabelByType[connectionType];
273
+ const connectionLabel = connectionTypeLabelByType[connectionType];
286
274
  // This case the connection has a third party provider such as GitLab,
287
275
  // GitHub that requires the use to create a manual step into the end
288
276
  // system.
289
- const isThirdPartyProvider = Object.values(graphql_1.ThirdPartyProvider).find((v) => v === connectionType);
277
+ const isThirdPartyProvider = Object.values(ThirdPartyProvider).find((v) => v === connectionType);
290
278
  if (isThirdPartyProvider) {
291
- const configData = (0, config_1.getOrCreateConfigData)(cmd.config.configDir);
279
+ const configData = getOrCreateConfigData(cmd.config.configDir);
292
280
  return `This item requires you to link your ${connectionLabel} account to Opal before requesting access.
293
- You can link your ${connectionLabel} account at ${`${configData[config_1.urlKey]}/user/settings/identities`}`;
281
+ You can link your ${connectionLabel} account at ${`${configData[urlKey]}/user/settings/identities`}`;
294
282
  }
295
283
  const name = connectionName !== null && connectionName !== void 0 ? connectionName : connectionLabel;
296
284
  // This case would be hit in case the user is not provisioned onto the end system, such as AWS, GCP, Okta, etc.
@@ -300,9 +288,9 @@ Please contact your Opal admin to provision your user on ${name}.`;
300
288
  // This should never happen, but just in case we forgot to pass in the third party provider or the connection type
301
289
  return "Your user does not exist on the end system. Please contact your Opal admin to add your user to the end system.";
302
290
  }
303
- case graphql_1.RequestMessageCode.NestedGroupAccessNotAllowed:
291
+ case RequestMessageCode.NestedGroupAccessNotAllowed:
304
292
  return "You cannot request access to this group because you already have nested access.";
305
- case graphql_1.RequestMessageCode.LinkedGroupNotRequestable:
293
+ case RequestMessageCode.LinkedGroupNotRequestable:
306
294
  return "You cannot request access to this group because it is linked to another group";
307
295
  default:
308
296
  return `Unknown request message code: ${code}`;
@@ -314,7 +302,7 @@ function addRequestedResourcesToMetadata(requestedResources, requestMap) {
314
302
  if (!resource)
315
303
  continue;
316
304
  const { id: assetId, displayName: assetName, connection, connectionId, __typename, } = resource;
317
- const type = (0, types_1.entityTypeFromString)(__typename);
305
+ const type = entityTypeFromString(__typename);
318
306
  const roleId = accessLevel.accessLevelRemoteId;
319
307
  const roleName = accessLevel.accessLevelName;
320
308
  if (!requestMap[connectionId]) {
@@ -346,7 +334,7 @@ function addRequestedGroupsToMetadata(requestedGroups, requestMap) {
346
334
  if (!group)
347
335
  continue;
348
336
  const { id: assetId, name: assetName, connection, connectionId, __typename, } = group;
349
- const type = (0, types_1.entityTypeFromString)(__typename);
337
+ const type = entityTypeFromString(__typename);
350
338
  const roleId = accessLevel === null || accessLevel === void 0 ? void 0 : accessLevel.accessLevelRemoteId;
351
339
  const roleName = accessLevel === null || accessLevel === void 0 ? void 0 : accessLevel.accessLevelName;
352
340
  if (!requestMap[connectionId]) {
@@ -376,7 +364,7 @@ function addRequestedGroupsToMetadata(requestedGroups, requestMap) {
376
364
  }
377
365
  async function convertRequestToMetadata(cmd, request, metadata) {
378
366
  const { status, durationInMinutes, reason, requestedResources, requestedGroups, } = request;
379
- if (status === graphql_1.RequestStatus.Pending) {
367
+ if (status === RequestStatus.Pending) {
380
368
  cmd.log("⏳ Request is still in progress");
381
369
  return;
382
370
  }
@@ -389,16 +377,16 @@ async function convertRequestToMetadata(cmd, request, metadata) {
389
377
  addRequestedResourcesToMetadata(requestedResources, metadata.requestMap);
390
378
  addRequestedGroupsToMetadata(requestedGroups, metadata.requestMap);
391
379
  }
392
- async function duplicateRequestTemplate(cmd, client, requestId, metadata) {
380
+ export async function duplicateRequestTemplate(cmd, client, requestId, metadata) {
393
381
  var _a, _b, _c, _d;
394
382
  cmd.log("Loading request template from ID: ", requestId);
395
- const resp = await (0, api_1.queryRequest)(client, requestId);
383
+ const resp = await queryRequest(client, requestId);
396
384
  // no fall through doesn't consider process.exit();
397
385
  let x;
398
386
  switch ((_a = resp.data) === null || _a === void 0 ? void 0 : _a.request.__typename) {
399
387
  case "RequestResult": {
400
388
  if (((_b = resp.data) === null || _b === void 0 ? void 0 : _b.request.request).status ===
401
- graphql_1.RequestStatus.Pending) {
389
+ RequestStatus.Pending) {
402
390
  cmd.error("⏳ Cannot duplicate a request that is still in progress");
403
391
  }
404
392
  cmd.log("Creating new request with same configuration...");
@@ -447,10 +435,10 @@ async function convertBundleToMetadata(cmd, bundle, requestMap) {
447
435
  }
448
436
  cmd.log("Added all requestable items in the bundle");
449
437
  }
450
- async function copyBundleAssets(cmd, client, bundleId, requestMap) {
438
+ export async function copyBundleAssets(cmd, client, bundleId, requestMap) {
451
439
  var _a, _b;
452
440
  cmd.log("Loading assets from bundle: ", bundleId);
453
- const resp = await (0, requests_1.queryBundle)(client, bundleId);
441
+ const resp = await queryBundle(client, bundleId);
454
442
  // no fall through doesn't consider process.exit();
455
443
  let x;
456
444
  switch ((_a = resp.data) === null || _a === void 0 ? void 0 : _a.bundle.__typename) {
@@ -1,4 +1,4 @@
1
- import { type ConnectionType, EntityType, type RequestMessageCode, type RequestMessageLevel } from "../../graphql/graphql";
1
+ import { type ConnectionType, EntityType, type RequestMessageCode, type RequestMessageLevel } from "../../graphql/graphql.js";
2
2
  type AppNode = {
3
3
  appId: string;
4
4
  appName: string;
@@ -0,0 +1,12 @@
1
+ import { EntityType, } from "../../graphql/graphql.js";
2
+ export function entityTypeFromString(str) {
3
+ const capStr = str === null || str === void 0 ? void 0 : str.toLocaleUpperCase();
4
+ if (capStr === "RESOURCE") {
5
+ return EntityType.Resource;
6
+ }
7
+ if (capStr === "GROUP") {
8
+ return EntityType.Group;
9
+ }
10
+ // if type unknown, default to resource
11
+ return EntityType.Resource;
12
+ }
@@ -1,5 +1,5 @@
1
1
  import type { Command } from "@oclif/core";
2
- import type { ResourceAccessLevel, ResourceAccessLevelInput } from "../graphql/graphql";
2
+ import type { ResourceAccessLevel, ResourceAccessLevelInput } from "../graphql/graphql.js";
3
3
  export type ResourceInfo = {
4
4
  id: string;
5
5
  name: string;
@@ -1,21 +1,18 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.promptUserForAccessLevels = exports.promptUserForResource = exports.filterChoices = exports.DEFAULT_ACCESS_LEVEL = void 0;
4
- const inquirer = require("inquirer");
5
- const handler_1 = require("../handler");
6
- const apollo_1 = require("./apollo");
7
- exports.DEFAULT_ACCESS_LEVEL = {
1
+ import inquirer from "inquirer";
2
+ import inquirerPrompt from "inquirer-autocomplete-prompt";
3
+ import { runQueryDeprecated } from "../handler.js";
4
+ import { handleError } from "./apollo.js";
5
+ export const DEFAULT_ACCESS_LEVEL = {
8
6
  accessLevelName: "",
9
7
  accessLevelRemoteId: "",
10
8
  };
11
9
  // Returns a filtered array of items that match the input
12
- const filterChoices = (input, choices) => {
10
+ export const filterChoices = (input, choices) => {
13
11
  if (!input) {
14
12
  return choices;
15
13
  }
16
14
  return choices.filter((choice) => choice.name.toLowerCase().includes(input.toLowerCase()));
17
15
  };
18
- exports.filterChoices = filterChoices;
19
16
  const ListResourcesDocumentTemplate = `
20
17
  query ListResources {
21
18
  resources(input: {resourceTypes: [RESOURCE_TYPE], onlyMine: true, maxNumEntries: 1000}) {
@@ -35,15 +32,15 @@ query ListResources {
35
32
  }
36
33
  }
37
34
  }`;
38
- const promptUserForResource = async (command, resourceType, message) => {
35
+ export const promptUserForResource = async (command, resourceType, message) => {
39
36
  const listResourcesDocument = ListResourcesDocumentTemplate.replace("RESOURCE_TYPE", resourceType);
40
- const { resp, error } = await (0, handler_1.runQueryDeprecated)({
37
+ const { resp, error } = await runQueryDeprecated({
41
38
  command: command,
42
39
  query: listResourcesDocument,
43
40
  variables: {},
44
41
  });
45
42
  if (error) {
46
- return (0, apollo_1.handleError)(command, error, resp);
43
+ return handleError(command, error, resp);
47
44
  }
48
45
  const resourceInfos = resp === null || resp === void 0 ? void 0 : resp.data.resources.resources.map((resource) => {
49
46
  let name = resource.name;
@@ -59,25 +56,24 @@ const promptUserForResource = async (command, resourceType, message) => {
59
56
  };
60
57
  });
61
58
  if (resourceInfos.length === 0) {
62
- return (0, apollo_1.handleError)(command, "You don't have access to any resources of this type. Please go to Opal to request access.");
59
+ return handleError(command, "You don't have access to any resources of this type. Please go to Opal to request access.");
63
60
  }
64
61
  const resourceInfoByName = {};
65
62
  // biome-ignore lint/complexity/noForEach: fix it when you get the chance
66
63
  resourceInfos.forEach((resourceInfo) => {
67
64
  resourceInfoByName[resourceInfo.name] = resourceInfo;
68
65
  });
69
- inquirer.registerPrompt("autocomplete", require("inquirer-autocomplete-prompt"));
66
+ inquirer.registerPrompt("autocomplete", inquirerPrompt);
70
67
  const selectedResourceInfo = await inquirer.prompt([
71
68
  {
72
69
  name: "resource",
73
70
  message: message,
74
71
  type: "autocomplete",
75
- source: (answers, input) => (0, exports.filterChoices)(input, resourceInfos),
72
+ source: (answers, input) => filterChoices(input, resourceInfos),
76
73
  },
77
74
  ]);
78
75
  return resourceInfoByName[selectedResourceInfo.resource];
79
76
  };
80
- exports.promptUserForResource = promptUserForResource;
81
77
  const ListAccessLevelsForResource = `
82
78
  query ListAccessLevelsForResource($resourceId: ResourceId!) {
83
79
  accessLevels(input: {resourceId: $resourceId, onlyMine: true}) {
@@ -90,22 +86,22 @@ query ListAccessLevelsForResource($resourceId: ResourceId!) {
90
86
  }
91
87
  }
92
88
  }`;
93
- const promptUserForAccessLevels = async (command, resourceId, instanceType, accessLevelRemoteId) => {
89
+ export const promptUserForAccessLevels = async (command, resourceId, instanceType, accessLevelRemoteId) => {
94
90
  var _a, _b, _c;
95
- const { resp, error } = await (0, handler_1.runQueryDeprecated)({
91
+ const { resp, error } = await runQueryDeprecated({
96
92
  command: command,
97
93
  query: ListAccessLevelsForResource,
98
94
  variables: { resourceId },
99
95
  });
100
96
  if (error) {
101
- return (0, apollo_1.handleError)(command, error, resp);
97
+ return handleError(command, error, resp);
102
98
  }
103
99
  const accessLevelInfos = (_c = (_b = (_a = resp === null || resp === void 0 ? void 0 : resp.data) === null || _a === void 0 ? void 0 : _a.accessLevels) === null || _b === void 0 ? void 0 : _b.accessLevels) === null || _c === void 0 ? void 0 : _c.map((resp) => ({
104
100
  id: resp.accessLevelRemoteId,
105
101
  name: resp.accessLevelName,
106
102
  }));
107
103
  if (!accessLevelInfos) {
108
- return (0, apollo_1.handleError)(command, "This resource requires an access level, but none have been set up in Opal. Please contact your Opal admin.");
104
+ return handleError(command, "This resource requires an access level, but none have been set up in Opal. Please contact your Opal admin.");
109
105
  }
110
106
  const accessLevelInfoByName = {};
111
107
  const accessLevelInfoByRemoteId = {};
@@ -120,13 +116,13 @@ const promptUserForAccessLevels = async (command, resourceId, instanceType, acce
120
116
  }
121
117
  // Prompt user to pick access levels available to them
122
118
  if (!selectedAccessLevel) {
123
- inquirer.registerPrompt("autocomplete", require("inquirer-autocomplete-prompt"));
119
+ inquirer.registerPrompt("autocomplete", inquirerPrompt);
124
120
  const selectedAccessLevelInfo = await inquirer.prompt([
125
121
  {
126
122
  name: "accessLevel",
127
123
  message: `Select an access level to the ${instanceType}`,
128
124
  type: "autocomplete",
129
- source: (answers, input) => (0, exports.filterChoices)(input, accessLevelInfos),
125
+ source: (answers, input) => filterChoices(input, accessLevelInfos),
130
126
  },
131
127
  ]);
132
128
  selectedAccessLevel =
@@ -137,4 +133,3 @@ const promptUserForAccessLevels = async (command, resourceId, instanceType, acce
137
133
  accessLevelRemoteId: selectedAccessLevel.id,
138
134
  };
139
135
  };
140
- exports.promptUserForAccessLevels = promptUserForAccessLevels;
@@ -1,4 +1,4 @@
1
1
  import type { Command } from "@oclif/core";
2
- import type { ResourceAccessLevelInput } from "../graphql/graphql";
2
+ import type { ResourceAccessLevelInput } from "../graphql/graphql.js";
3
3
  export declare const getOrCreateSession: (command: Command, resourceId: string, accessLevel: ResourceAccessLevelInput, sessionId: string | undefined, metadataFragment: string, wantNewSession?: boolean) => Promise<any>;
4
4
  export declare const getSessionExpirationMessage: (session: any) => string;
@@ -1,12 +1,11 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getSessionExpirationMessage = exports.getOrCreateSession = void 0;
4
- const moment = require("moment");
5
- const open = require("open");
6
- const handler_1 = require("../handler");
7
- const apollo_1 = require("../lib/apollo");
8
- const config_1 = require("../lib/config");
9
- const util_1 = require("./util");
1
+ import { ux } from "@oclif/core";
2
+ import inquirer from "inquirer";
3
+ import moment from "moment";
4
+ import open from "open";
5
+ import { runMutation, runQueryDeprecated } from "../handler.js";
6
+ import { handleError } from "./apollo.js";
7
+ import { getOrCreateConfigData, urlKey } from "./config.js";
8
+ import { sleep } from "./util.js";
10
9
  const CreateSessionDocument = `
11
10
  mutation CreateSession($id: ResourceId!, $accessLevel: ResourceAccessLevelInput!, $sessionId: SessionId) {
12
11
  createSession(input: {resourceId: $id, accessLevel: $accessLevel, sessionId: $sessionId}) {
@@ -59,7 +58,7 @@ query ListSessions($id: ResourceId!) {
59
58
  }
60
59
  `;
61
60
  const getSession = async (command, resourceId, accessLevelRemoteId, sessionId, metadataFragment, minCreatedAt) => {
62
- const { resp, error } = await (0, handler_1.runQueryDeprecated)({
61
+ const { resp, error } = await runQueryDeprecated({
63
62
  command: command,
64
63
  query: ListSessionsDocument.replace("METADATA_FRAGMENT", metadataFragment),
65
64
  variables: {
@@ -67,7 +66,7 @@ const getSession = async (command, resourceId, accessLevelRemoteId, sessionId, m
67
66
  },
68
67
  });
69
68
  if (error) {
70
- return (0, apollo_1.handleError)(command, error);
69
+ return handleError(command, error);
71
70
  }
72
71
  switch (resp === null || resp === void 0 ? void 0 : resp.data.sessions.__typename) {
73
72
  case "SessionsResult": {
@@ -94,32 +93,60 @@ const getSession = async (command, resourceId, accessLevelRemoteId, sessionId, m
94
93
  return selectedSession;
95
94
  }
96
95
  default:
97
- return (0, apollo_1.handleError)(command, error, resp);
96
+ return handleError(command, error, resp);
98
97
  }
99
98
  };
100
- const openBrowserAndPollForSession = async (command, message, resourceId, accessLevelRemoteId, sessionId, metadataFragment, wantNewSession) => {
99
+ const openBrowserAndPollForSession = async (command, authenticationType, resourceId, accessLevelRemoteId, sessionId, metadataFragment, wantNewSession) => {
101
100
  let minCreatedAt;
102
101
  if (wantNewSession) {
103
102
  // Ensure we poll for a new session rather than get an existing one.
104
103
  minCreatedAt = moment();
105
104
  }
106
- command.log(message);
107
- const configData = (0, config_1.getOrCreateConfigData)(command.config.configDir);
108
- const url = configData[config_1.urlKey];
109
- setTimeout(() => {
110
- open(`${url}/resources/${resourceId}?showModal=true&refresh=true`);
111
- }, 2000); // Wait before opening the browser to give the user time to read the message
105
+ const configData = getOrCreateConfigData(command.config.configDir);
106
+ const urlPrefix = configData[urlKey];
107
+ const url = `${urlPrefix}/resources/${resourceId}?showModal=true&refresh=true`;
108
+ command.log(`
109
+ 🔐 ${authenticationType} Required
110
+
111
+ To continue, authenicate in your browser:
112
+
113
+ ⚠️ Security Check:
114
+ • Verify the URL is exactly: ${url}
115
+ • Never enter this code on any other website
116
+ `);
117
+ await inquirer.prompt([
118
+ {
119
+ type: "input",
120
+ name: "continue",
121
+ message: "Press Enter to open your browser and continue",
122
+ },
123
+ ]);
124
+ open(url);
125
+ ux.action.start("Waiting for session approval");
126
+ const timeoutMs = 5 * 60 * 1000; // 5 minutes
127
+ const startTime = Date.now();
112
128
  // biome-ignore lint/suspicious/noImplicitAnyLet: please fix typing for queries
113
129
  let session;
114
- while (!session) {
115
- await (0, util_1.sleep)(2000);
116
- session = await getSession(command, resourceId, accessLevelRemoteId, sessionId, metadataFragment, minCreatedAt);
130
+ try {
131
+ while (!session) {
132
+ if (Date.now() - startTime > timeoutMs) {
133
+ ux.action.stop("✗ Timed out");
134
+ throw new Error(`Timed out waiting for session after ${timeoutMs / 1000} seconds. Please ensure you've approved the access request in your browser.`);
135
+ }
136
+ await sleep(2000);
137
+ session = await getSession(command, resourceId, accessLevelRemoteId, sessionId, metadataFragment, minCreatedAt);
138
+ }
139
+ ux.action.stop("✓ Session approved");
140
+ }
141
+ catch (error) {
142
+ ux.action.stop("✗ Failed");
143
+ throw error;
117
144
  }
118
145
  return session;
119
146
  };
120
147
  const createSession = async (command, resourceId, accessLevel, sessionId, metadataFragment, wantNewSession) => {
121
148
  var _a, _b, _c, _d;
122
- const { resp, error } = await (0, handler_1.runMutation)({
149
+ const { resp, error } = await runMutation({
123
150
  command: command,
124
151
  query: CreateSessionDocument.replace("METADATA_FRAGMENT", metadataFragment),
125
152
  variables: {
@@ -129,23 +156,23 @@ const createSession = async (command, resourceId, accessLevel, sessionId, metada
129
156
  },
130
157
  });
131
158
  if (error) {
132
- return (0, apollo_1.handleError)(command, error);
159
+ return handleError(command, error);
133
160
  }
134
161
  switch ((_b = (_a = resp === null || resp === void 0 ? void 0 : resp.data) === null || _a === void 0 ? void 0 : _a.createSession) === null || _b === void 0 ? void 0 : _b.__typename) {
135
162
  case "CreateSessionResult": {
136
163
  return (_d = (_c = resp.data) === null || _c === void 0 ? void 0 : _c.createSession) === null || _d === void 0 ? void 0 : _d.session;
137
164
  }
138
165
  case "MfaInvalidError": {
139
- return openBrowserAndPollForSession(command, "MFA validation needed. Please connect via browser. Opening browser and awaiting validation...", resourceId, accessLevel.accessLevelRemoteId, sessionId, metadataFragment, wantNewSession);
166
+ return openBrowserAndPollForSession(command, "MFA Validation", resourceId, accessLevel.accessLevelRemoteId, sessionId, metadataFragment, wantNewSession);
140
167
  }
141
168
  case "OidcIDTokenNotFoundError": {
142
- return openBrowserAndPollForSession(command, "OIDC authentication needed. Please connect via browser. Opening browser and awaiting authentication...", resourceId, accessLevel.accessLevelRemoteId, sessionId, metadataFragment, wantNewSession);
169
+ return openBrowserAndPollForSession(command, "OIDC Authenication", resourceId, accessLevel.accessLevelRemoteId, sessionId, metadataFragment, wantNewSession);
143
170
  }
144
171
  default:
145
- return (0, apollo_1.handleError)(command, error, resp);
172
+ return handleError(command, error, resp);
146
173
  }
147
174
  };
148
- const getOrCreateSession = async (command, resourceId, accessLevel, sessionId, metadataFragment, wantNewSession) => {
175
+ export const getOrCreateSession = async (command, resourceId, accessLevel, sessionId, metadataFragment, wantNewSession) => {
149
176
  if (!wantNewSession) {
150
177
  // Use existing session if it exists
151
178
  const existingSession = await getSession(command, resourceId, accessLevel.accessLevelRemoteId, sessionId, metadataFragment);
@@ -154,16 +181,14 @@ const getOrCreateSession = async (command, resourceId, accessLevel, sessionId, m
154
181
  }
155
182
  }
156
183
  if (sessionId) {
157
- return (0, apollo_1.handleError)(command, `Session not found for given id: ${sessionId}`);
184
+ return handleError(command, `Session not found for given id: ${sessionId}`);
158
185
  }
159
186
  // Create new session
160
187
  return createSession(command, resourceId, accessLevel, sessionId, metadataFragment, wantNewSession);
161
188
  };
162
- exports.getOrCreateSession = getOrCreateSession;
163
- const getSessionExpirationMessage = (session) => {
189
+ export const getSessionExpirationMessage = (session) => {
164
190
  const diff = moment(session.endTime).diff(moment(), "minutes");
165
191
  const hours = Math.floor(diff / 60);
166
192
  const minutes = diff % 60;
167
193
  return `${hours}h ${minutes}m`;
168
194
  };
169
- exports.getSessionExpirationMessage = getSessionExpirationMessage;
@@ -1,3 +1,3 @@
1
1
  import type { Command } from "@oclif/core";
2
- export declare const selectComputeInstance: (command: Command, action: string) => Promise<void | import("./resources").ResourceInfo>;
2
+ export declare const selectComputeInstance: (command: Command, action: string) => Promise<void | import("./resources.js").ResourceInfo>;
3
3
  export declare const assertSessionManagerPluginExists: () => Promise<boolean>;