opal-security 3.1.1-beta.4ab1987 ā 3.1.1-beta.4e22fcc
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.
- package/README.md +26 -26
- package/lib/commands/request/create.d.ts +6 -0
- package/lib/commands/request/create.js +52 -15
- package/lib/commands/request/list.js +2 -2
- package/lib/graphql/gql.d.ts +17 -2
- package/lib/graphql/gql.js +4 -1
- package/lib/graphql/graphql.d.ts +162 -0
- package/lib/graphql/graphql.js +1075 -17
- package/lib/lib/flags.js +1 -1
- package/lib/lib/requests.d.ts +28 -19
- package/lib/lib/requests.js +723 -94
- package/lib/utils/displays.d.ts +5 -4
- package/lib/utils/displays.js +70 -69
- package/oclif.manifest.json +43 -11
- package/package.json +2 -1
package/lib/lib/requests.js
CHANGED
|
@@ -1,19 +1,33 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.initEmptyRequestMetadata = initEmptyRequestMetadata;
|
|
4
4
|
exports.selectRequestableItems = selectRequestableItems;
|
|
5
|
-
exports.chooseAssets = chooseAssets;
|
|
6
|
-
exports.chooseRoles = chooseRoles;
|
|
7
5
|
exports.doneSelectingAssets = doneSelectingAssets;
|
|
8
6
|
exports.setRequestDefaults = setRequestDefaults;
|
|
9
7
|
exports.promptForReason = promptForReason;
|
|
10
8
|
exports.promptForExpiration = promptForExpiration;
|
|
9
|
+
exports.promptRequestSubmission = promptRequestSubmission;
|
|
11
10
|
exports.submitFinalRequest = submitFinalRequest;
|
|
11
|
+
exports.bypassRequestSelection = bypassRequestSelection;
|
|
12
|
+
exports.bypassDuration = bypassDuration;
|
|
13
|
+
const chalk_1 = require("chalk");
|
|
12
14
|
const inquirer = require("inquirer");
|
|
13
15
|
const graphql_1 = require("../graphql");
|
|
14
|
-
|
|
15
|
-
const
|
|
16
|
-
|
|
16
|
+
const graphql_2 = require("../graphql/graphql");
|
|
17
|
+
const displays_1 = require("../utils/displays");
|
|
18
|
+
const config_1 = require("./config");
|
|
19
|
+
const { AutoComplete, Select, prompt, Form } = require("enquirer");
|
|
20
|
+
function entityTypeFromString(str) {
|
|
21
|
+
if (str === "Resource") {
|
|
22
|
+
return graphql_2.EntityType.Resource;
|
|
23
|
+
}
|
|
24
|
+
if (str === "Group") {
|
|
25
|
+
return graphql_2.EntityType.Group;
|
|
26
|
+
}
|
|
27
|
+
// if type unknown, default to resource
|
|
28
|
+
return graphql_2.EntityType.Resource;
|
|
29
|
+
}
|
|
30
|
+
function initEmptyRequestMetadata() {
|
|
17
31
|
// Initialize with empty defaults
|
|
18
32
|
const requestDefaults = {
|
|
19
33
|
durationOptions: [],
|
|
@@ -29,6 +43,9 @@ function createEmptyRequestMetadata() {
|
|
|
29
43
|
return {
|
|
30
44
|
requestMap,
|
|
31
45
|
requestDefaults,
|
|
46
|
+
durationLabel: "",
|
|
47
|
+
durationInMinutes: 0,
|
|
48
|
+
reason: "",
|
|
32
49
|
};
|
|
33
50
|
}
|
|
34
51
|
// Queries and Mutations
|
|
@@ -74,19 +91,23 @@ async function queryRequestableApps(cmd, client, input) {
|
|
|
74
91
|
});
|
|
75
92
|
return (_b = (_a = resp === null || resp === void 0 ? void 0 : resp.data) === null || _a === void 0 ? void 0 : _a.appsV2) === null || _b === void 0 ? void 0 : _b.edges.map((edge) => {
|
|
76
93
|
let type = undefined;
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
94
|
+
switch (edge.node.__typename) {
|
|
95
|
+
case "Resource":
|
|
96
|
+
type = edge.node.resourceType;
|
|
97
|
+
break;
|
|
98
|
+
case "Connection":
|
|
99
|
+
type = edge.node.connectionType;
|
|
100
|
+
break;
|
|
101
|
+
default:
|
|
102
|
+
type = edge.node.__typename;
|
|
82
103
|
}
|
|
83
|
-
const label = `${edge.node.displayName} (${type})`;
|
|
84
104
|
return {
|
|
85
|
-
message:
|
|
105
|
+
message: `${edge.node.displayName} [${type}]`,
|
|
86
106
|
value: {
|
|
87
107
|
id: edge.node.id,
|
|
88
|
-
name:
|
|
89
|
-
|
|
108
|
+
name: edge.node.displayName,
|
|
109
|
+
type: type,
|
|
110
|
+
toString: () => edge.node.displayName,
|
|
90
111
|
},
|
|
91
112
|
};
|
|
92
113
|
});
|
|
@@ -153,13 +174,12 @@ async function queryRequestableAssets(cmd, client, appId, input) {
|
|
|
153
174
|
const name = ((_a = item.resource) === null || _a === void 0 ? void 0 : _a.name) || ((_b = item.group) === null || _b === void 0 ? void 0 : _b.name);
|
|
154
175
|
const id = ((_c = item.resource) === null || _c === void 0 ? void 0 : _c.id) || ((_d = item.group) === null || _d === void 0 ? void 0 : _d.id);
|
|
155
176
|
const type = ((_e = item.resource) === null || _e === void 0 ? void 0 : _e.__typename) || ((_f = item.group) === null || _f === void 0 ? void 0 : _f.__typename);
|
|
156
|
-
const label = `${name} (${type})`;
|
|
157
177
|
return {
|
|
158
|
-
message:
|
|
178
|
+
message: `${name} [${type}]`,
|
|
159
179
|
value: {
|
|
160
|
-
name:
|
|
161
|
-
id: id,
|
|
162
|
-
type: ((_g = item.resource) === null || _g === void 0 ? void 0 : _g.__typename) || ((_h = item.group) === null || _h === void 0 ? void 0 : _h.__typename),
|
|
180
|
+
name: name || "",
|
|
181
|
+
id: id || "",
|
|
182
|
+
type: entityTypeFromString(((_g = item.resource) === null || _g === void 0 ? void 0 : _g.__typename) || ((_h = item.group) === null || _h === void 0 ? void 0 : _h.__typename)),
|
|
163
183
|
},
|
|
164
184
|
};
|
|
165
185
|
});
|
|
@@ -232,10 +252,10 @@ async function queryAssetRoles(cmd, client, assetType, assetId) {
|
|
|
232
252
|
case "ResourceAccessLevelsResult":
|
|
233
253
|
return (_c = (_b = (_a = 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((role) => {
|
|
234
254
|
return {
|
|
235
|
-
|
|
255
|
+
message: role.accessLevelName || "",
|
|
236
256
|
value: {
|
|
237
|
-
name: role.accessLevelName,
|
|
238
|
-
id: role.accessLevelRemoteId,
|
|
257
|
+
name: role.accessLevelName || "",
|
|
258
|
+
id: role.accessLevelRemoteId || "",
|
|
239
259
|
},
|
|
240
260
|
};
|
|
241
261
|
});
|
|
@@ -261,7 +281,7 @@ async function queryAssetRoles(cmd, client, assetType, assetId) {
|
|
|
261
281
|
case "GroupAccessLevelsResult":
|
|
262
282
|
return (_h = (_g = (_f = resp.data) === null || _f === void 0 ? void 0 : _f.groupAccessLevels) === null || _g === void 0 ? void 0 : _g.accessLevels) === null || _h === void 0 ? void 0 : _h.map((role) => {
|
|
263
283
|
return {
|
|
264
|
-
|
|
284
|
+
message: role.accessLevelName,
|
|
265
285
|
value: {
|
|
266
286
|
name: role.accessLevelName,
|
|
267
287
|
id: role.accessLevelRemoteId,
|
|
@@ -291,16 +311,18 @@ const REQUEST_DEFAULTS_QUERY = (0, graphql_1.graphql)(`
|
|
|
291
311
|
requestedGroups: $requestedGroups,
|
|
292
312
|
}
|
|
293
313
|
) {
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
314
|
+
... on RequestDefaults {
|
|
315
|
+
durationOptions {
|
|
316
|
+
durationInMinutes
|
|
317
|
+
label
|
|
318
|
+
}
|
|
319
|
+
recommendedDurationInMinutes
|
|
320
|
+
defaultDurationInMinutes
|
|
321
|
+
maxDurationInMinutes
|
|
322
|
+
requireSupportTicket
|
|
323
|
+
reasonOptional
|
|
324
|
+
requesterIsAdmin
|
|
297
325
|
}
|
|
298
|
-
recommendedDurationInMinutes
|
|
299
|
-
defaultDurationInMinutes
|
|
300
|
-
maxDurationInMinutes
|
|
301
|
-
requireSupportTicket
|
|
302
|
-
reasonOptional
|
|
303
|
-
requesterIsAdmin
|
|
304
326
|
}
|
|
305
327
|
}`);
|
|
306
328
|
async function queryRequestDefaults(cmd, client, requestedResources, requestedGroups) {
|
|
@@ -321,39 +343,405 @@ async function queryRequestDefaults(cmd, client, requestedResources, requestedGr
|
|
|
321
343
|
}
|
|
322
344
|
}
|
|
323
345
|
}
|
|
346
|
+
const CREATE_REQUEST_MUTATION = (0, graphql_1.graphql)(`
|
|
347
|
+
mutation CreateRequest(
|
|
348
|
+
$requestedResources: [RequestedResourceInput!]!
|
|
349
|
+
$requestedGroups: [RequestedGroupInput!]!
|
|
350
|
+
$reason: String!
|
|
351
|
+
$durationInMinutes: Int
|
|
352
|
+
) {
|
|
353
|
+
createRequest(
|
|
354
|
+
input: {
|
|
355
|
+
requestedResources: $requestedResources
|
|
356
|
+
requestedGroups: $requestedGroups
|
|
357
|
+
reason: $reason
|
|
358
|
+
durationInMinutes: $durationInMinutes
|
|
359
|
+
}
|
|
360
|
+
) {
|
|
361
|
+
... on CreateRequestResult {
|
|
362
|
+
request {
|
|
363
|
+
id
|
|
364
|
+
status
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
... on RequestDurationTooLargeError {
|
|
368
|
+
message
|
|
369
|
+
}
|
|
370
|
+
... on RequestRequiresUserAuthTokenForConnectionError {
|
|
371
|
+
message
|
|
372
|
+
}
|
|
373
|
+
... on NoReviewersSetForOwnerError {
|
|
374
|
+
message
|
|
375
|
+
ownerId
|
|
376
|
+
}
|
|
377
|
+
... on NoReviewersSetForResourceError {
|
|
378
|
+
message
|
|
379
|
+
resourceId
|
|
380
|
+
}
|
|
381
|
+
... on NoReviewersSetForGroupError {
|
|
382
|
+
message
|
|
383
|
+
groupId
|
|
384
|
+
}
|
|
385
|
+
... on NoManagerSetForRequestingUserError {
|
|
386
|
+
message
|
|
387
|
+
}
|
|
388
|
+
... on MfaInvalidError {
|
|
389
|
+
message
|
|
390
|
+
}
|
|
391
|
+
... on BulkRequestTooLargeError {
|
|
392
|
+
message
|
|
393
|
+
}
|
|
394
|
+
... on ItemCannotBeRequestedError {
|
|
395
|
+
message
|
|
396
|
+
}
|
|
397
|
+
... on UserCannotRequestAccessForTargetGroupError {
|
|
398
|
+
message
|
|
399
|
+
groupId
|
|
400
|
+
userId
|
|
401
|
+
}
|
|
402
|
+
... on GroupNestingNotAllowedError {
|
|
403
|
+
message
|
|
404
|
+
fromGroupId
|
|
405
|
+
toGroupId
|
|
406
|
+
}
|
|
407
|
+
... on TargetUserHasNestedAccessError {
|
|
408
|
+
message
|
|
409
|
+
groupIds
|
|
410
|
+
}
|
|
411
|
+
... on RequestReasonMissingError {
|
|
412
|
+
message
|
|
413
|
+
}
|
|
414
|
+
... on RequestFieldValueMissingError {
|
|
415
|
+
message
|
|
416
|
+
fieldName
|
|
417
|
+
}
|
|
418
|
+
... on LinkedGroupNotRequestableError {
|
|
419
|
+
message
|
|
420
|
+
sourceGroupId
|
|
421
|
+
groupBindingId
|
|
422
|
+
}
|
|
423
|
+
... on RequestReasonBelowMinLengthError {
|
|
424
|
+
message
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
`);
|
|
430
|
+
async function createRequest(cmd, client, requestedResources, requestedGroups, reason, durationInMinutes) {
|
|
431
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t;
|
|
432
|
+
try {
|
|
433
|
+
const resp = await client.mutate({
|
|
434
|
+
mutation: CREATE_REQUEST_MUTATION,
|
|
435
|
+
variables: {
|
|
436
|
+
requestedResources: requestedResources,
|
|
437
|
+
requestedGroups: requestedGroups,
|
|
438
|
+
reason: reason,
|
|
439
|
+
durationInMinutes: durationInMinutes,
|
|
440
|
+
},
|
|
441
|
+
});
|
|
442
|
+
switch ((_a = resp.data) === null || _a === void 0 ? void 0 : _a.createRequest.__typename) {
|
|
443
|
+
case "CreateRequestResult":
|
|
444
|
+
return (_b = resp.data) === null || _b === void 0 ? void 0 : _b.createRequest.request;
|
|
445
|
+
case "RequestDurationTooLargeError":
|
|
446
|
+
cmd.log((_c = resp.data) === null || _c === void 0 ? void 0 : _c.createRequest.message);
|
|
447
|
+
break;
|
|
448
|
+
case "RequestRequiresUserAuthTokenForConnectionError":
|
|
449
|
+
cmd.log((_d = resp.data) === null || _d === void 0 ? void 0 : _d.createRequest.message);
|
|
450
|
+
break;
|
|
451
|
+
case "NoReviewersSetForOwnerError":
|
|
452
|
+
cmd.log((_e = resp.data) === null || _e === void 0 ? void 0 : _e.createRequest.message);
|
|
453
|
+
break;
|
|
454
|
+
case "NoReviewersSetForResourceError":
|
|
455
|
+
cmd.log((_f = resp.data) === null || _f === void 0 ? void 0 : _f.createRequest.message);
|
|
456
|
+
break;
|
|
457
|
+
case "NoReviewersSetForGroupError":
|
|
458
|
+
cmd.log((_g = resp.data) === null || _g === void 0 ? void 0 : _g.createRequest.message);
|
|
459
|
+
break;
|
|
460
|
+
case "NoManagerSetForRequestingUserError":
|
|
461
|
+
cmd.log((_h = resp.data) === null || _h === void 0 ? void 0 : _h.createRequest.message);
|
|
462
|
+
break;
|
|
463
|
+
case "MfaInvalidError":
|
|
464
|
+
cmd.log((_j = resp.data) === null || _j === void 0 ? void 0 : _j.createRequest.message);
|
|
465
|
+
break;
|
|
466
|
+
case "BulkRequestTooLargeError":
|
|
467
|
+
cmd.log((_k = resp.data) === null || _k === void 0 ? void 0 : _k.createRequest.message);
|
|
468
|
+
break;
|
|
469
|
+
case "ItemCannotBeRequestedError":
|
|
470
|
+
cmd.log((_l = resp.data) === null || _l === void 0 ? void 0 : _l.createRequest.message);
|
|
471
|
+
break;
|
|
472
|
+
case "UserCannotRequestAccessForTargetGroupError":
|
|
473
|
+
cmd.log((_m = resp.data) === null || _m === void 0 ? void 0 : _m.createRequest.message);
|
|
474
|
+
break;
|
|
475
|
+
case "GroupNestingNotAllowedError":
|
|
476
|
+
cmd.log((_o = resp.data) === null || _o === void 0 ? void 0 : _o.createRequest.message);
|
|
477
|
+
break;
|
|
478
|
+
case "TargetUserHasNestedAccessError":
|
|
479
|
+
cmd.log((_p = resp.data) === null || _p === void 0 ? void 0 : _p.createRequest.message);
|
|
480
|
+
break;
|
|
481
|
+
case "RequestReasonMissingError":
|
|
482
|
+
cmd.log((_q = resp.data) === null || _q === void 0 ? void 0 : _q.createRequest.message);
|
|
483
|
+
break;
|
|
484
|
+
case "RequestFieldValueMissingError":
|
|
485
|
+
cmd.log((_r = resp.data) === null || _r === void 0 ? void 0 : _r.createRequest.message);
|
|
486
|
+
break;
|
|
487
|
+
case "LinkedGroupNotRequestableError":
|
|
488
|
+
cmd.log((_s = resp.data) === null || _s === void 0 ? void 0 : _s.createRequest.message);
|
|
489
|
+
break;
|
|
490
|
+
case "RequestReasonBelowMinLengthError":
|
|
491
|
+
cmd.log((_t = resp.data) === null || _t === void 0 ? void 0 : _t.createRequest.message);
|
|
492
|
+
break;
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
catch (error) {
|
|
496
|
+
if (error instanceof Error || typeof error === "string") {
|
|
497
|
+
cmd.error(error);
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
const CATALOG_ITEM = (0, graphql_1.graphql)(`
|
|
502
|
+
query GetCatalogItem($uuid: UUID!) {
|
|
503
|
+
catalogItem(id: $uuid) {
|
|
504
|
+
__typename
|
|
505
|
+
... on Connection {
|
|
506
|
+
id
|
|
507
|
+
displayName
|
|
508
|
+
}
|
|
509
|
+
... on Resource {
|
|
510
|
+
id
|
|
511
|
+
displayName
|
|
512
|
+
connection {
|
|
513
|
+
id
|
|
514
|
+
displayName
|
|
515
|
+
}
|
|
516
|
+
accessLevels{
|
|
517
|
+
accessLevelName
|
|
518
|
+
accessLevelRemoteId
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
...on Group {
|
|
522
|
+
id
|
|
523
|
+
name
|
|
524
|
+
connection {
|
|
525
|
+
id
|
|
526
|
+
displayName
|
|
527
|
+
}
|
|
528
|
+
accessLevels{
|
|
529
|
+
accessLevelName
|
|
530
|
+
accessLevelRemoteId
|
|
531
|
+
}
|
|
532
|
+
}
|
|
533
|
+
... on UserFacingError {
|
|
534
|
+
message
|
|
535
|
+
}
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
`);
|
|
539
|
+
const ASSOCIATED_ITEMS_QUERY = (0, graphql_1.graphql)(`
|
|
540
|
+
query GetAssociatedItems($resourceId: ResourceId!, $searchQuery: String) {
|
|
541
|
+
resource(input: {
|
|
542
|
+
id: $resourceId
|
|
543
|
+
}) {
|
|
544
|
+
__typename
|
|
545
|
+
... on ResourceResult {
|
|
546
|
+
__typename
|
|
547
|
+
resource {
|
|
548
|
+
associatedItems(
|
|
549
|
+
first: 200
|
|
550
|
+
filters: {
|
|
551
|
+
searchQuery: {
|
|
552
|
+
contains: $searchQuery
|
|
553
|
+
}
|
|
554
|
+
access: REQUESTABLE
|
|
555
|
+
endUserVisible: true
|
|
556
|
+
entityType: {
|
|
557
|
+
in: [GROUP, RESOURCE]
|
|
558
|
+
}
|
|
559
|
+
}
|
|
560
|
+
) {
|
|
561
|
+
edges {
|
|
562
|
+
__typename
|
|
563
|
+
... on ResourceAssociatedItemEdge {
|
|
564
|
+
alias
|
|
565
|
+
node {
|
|
566
|
+
__typename
|
|
567
|
+
id
|
|
568
|
+
name
|
|
569
|
+
... on Resource {
|
|
570
|
+
accessLevels(
|
|
571
|
+
filters: {
|
|
572
|
+
skipRemoteAccessLevels: false # azure app roles are remote
|
|
573
|
+
}
|
|
574
|
+
) {
|
|
575
|
+
__typename
|
|
576
|
+
accessLevelName
|
|
577
|
+
accessLevelRemoteId
|
|
578
|
+
}
|
|
579
|
+
}
|
|
580
|
+
}
|
|
581
|
+
}
|
|
582
|
+
}
|
|
583
|
+
}
|
|
584
|
+
}
|
|
585
|
+
}
|
|
586
|
+
... on ResourceNotFoundError {
|
|
587
|
+
message
|
|
588
|
+
}
|
|
589
|
+
}
|
|
590
|
+
}
|
|
591
|
+
`);
|
|
592
|
+
async function queryAssociatedItems(cmd, client, id, input) {
|
|
593
|
+
var _a, _b;
|
|
594
|
+
try {
|
|
595
|
+
const resp = await client.query({
|
|
596
|
+
query: ASSOCIATED_ITEMS_QUERY,
|
|
597
|
+
variables: {
|
|
598
|
+
resourceId: id || "",
|
|
599
|
+
searchQuery: input || "",
|
|
600
|
+
},
|
|
601
|
+
fetchPolicy: "network-only", // to avoid caching
|
|
602
|
+
});
|
|
603
|
+
switch (resp.data.resource.__typename) {
|
|
604
|
+
case "ResourceResult": {
|
|
605
|
+
const associatedItems = resp.data.resource.resource.associatedItems.edges.filter((edge) => edge.__typename === "ResourceAssociatedItemEdge");
|
|
606
|
+
const initial = [];
|
|
607
|
+
for (const edge of associatedItems) {
|
|
608
|
+
initial.push(...appRolesFromEdge(edge));
|
|
609
|
+
}
|
|
610
|
+
return initial;
|
|
611
|
+
}
|
|
612
|
+
case "ResourceNotFoundError":
|
|
613
|
+
cmd.log((_b = (_a = resp.data) === null || _a === void 0 ? void 0 : _a.resource) === null || _b === void 0 ? void 0 : _b.message);
|
|
614
|
+
break;
|
|
615
|
+
default:
|
|
616
|
+
cmd.error(resp.error || "Unknown error occurred.");
|
|
617
|
+
}
|
|
618
|
+
}
|
|
619
|
+
catch (error) {
|
|
620
|
+
if (error instanceof Error || typeof error === "string") {
|
|
621
|
+
cmd.error(error);
|
|
622
|
+
}
|
|
623
|
+
}
|
|
624
|
+
}
|
|
324
625
|
// Helper functions
|
|
626
|
+
const selectInstructions = chalk_1.default.dim("āā Navigate Ā· Enter Select Ā· Type to filter");
|
|
627
|
+
const multiSelectInstructions = chalk_1.default.dim("āā Navigate Ā· Space Select Ā· Enter Confirm Ā· Type to filter");
|
|
325
628
|
async function selectRequestableItems(cmd, client, requestMap) {
|
|
326
|
-
const
|
|
629
|
+
const initial = (await queryRequestableApps(cmd, client, "")) || [];
|
|
327
630
|
const appPrompt = new AutoComplete({
|
|
328
631
|
name: "App",
|
|
329
|
-
message: "Select an app
|
|
632
|
+
message: "Select an app",
|
|
633
|
+
hint: selectInstructions,
|
|
330
634
|
limit: 15,
|
|
331
|
-
choices:
|
|
635
|
+
choices: initial,
|
|
332
636
|
async suggest(input) {
|
|
333
637
|
const filteredChoices = await queryRequestableApps(cmd, client, input || "");
|
|
334
|
-
return filteredChoices ||
|
|
638
|
+
return filteredChoices || initial;
|
|
335
639
|
},
|
|
336
640
|
});
|
|
337
641
|
const App = await appPrompt.run();
|
|
338
642
|
// Set the app in the requestMap and call choose assets step
|
|
339
643
|
if (!(App.id in requestMap)) {
|
|
340
644
|
requestMap[App.id] = {
|
|
645
|
+
appId: App.id,
|
|
341
646
|
appName: App.name,
|
|
342
647
|
assets: {},
|
|
343
648
|
};
|
|
344
649
|
}
|
|
650
|
+
if (App.type === "OKTA_APP" || App.type === "AZURE_ENTERPRISE_APP") {
|
|
651
|
+
await chooseOktaAzureRoles(cmd, client, App, requestMap);
|
|
652
|
+
return;
|
|
653
|
+
}
|
|
345
654
|
await chooseAssets(cmd, client, App.id, requestMap);
|
|
346
655
|
}
|
|
656
|
+
async function chooseOktaAzureRoles(cmd, client, app, requestMap) {
|
|
657
|
+
const associatedItems = (await queryAssociatedItems(cmd, client, app.id, "")) || [];
|
|
658
|
+
const rolePrompt = new AutoComplete({
|
|
659
|
+
name: "Roles",
|
|
660
|
+
message: `Select a role for ${app.name}:`,
|
|
661
|
+
hint: multiSelectInstructions,
|
|
662
|
+
limit: 15,
|
|
663
|
+
multiple: true,
|
|
664
|
+
async choices(input) {
|
|
665
|
+
if (!input)
|
|
666
|
+
return associatedItems;
|
|
667
|
+
const filteredChoices = await queryAssociatedItems(cmd, client, app.id, input);
|
|
668
|
+
return filteredChoices || associatedItems;
|
|
669
|
+
},
|
|
670
|
+
validate: (answer) => {
|
|
671
|
+
if (answer.length !== 1) {
|
|
672
|
+
return "You must select only one item.";
|
|
673
|
+
}
|
|
674
|
+
return true;
|
|
675
|
+
},
|
|
676
|
+
});
|
|
677
|
+
const Roles = await rolePrompt.run();
|
|
678
|
+
const entry = requestMap[app.id];
|
|
679
|
+
for (const role of Roles) {
|
|
680
|
+
if (!(role.id in entry.assets)) {
|
|
681
|
+
entry.assets[role.id] = {
|
|
682
|
+
assetId: role.id,
|
|
683
|
+
assetName: role.name,
|
|
684
|
+
type: entityTypeFromString(role.type),
|
|
685
|
+
roles: {},
|
|
686
|
+
};
|
|
687
|
+
}
|
|
688
|
+
}
|
|
689
|
+
}
|
|
690
|
+
function appRolesFromEdge(edge) {
|
|
691
|
+
var _a, _b, _c, _d;
|
|
692
|
+
switch (edge.node.__typename) {
|
|
693
|
+
case "Resource": {
|
|
694
|
+
if (edge.node.accessLevels && edge.node.accessLevels.length > 0) {
|
|
695
|
+
return edge.node.accessLevels.map((accessLevel) => ({
|
|
696
|
+
message: accessLevel.accessLevelName || "No Role (Direct access)",
|
|
697
|
+
value: {
|
|
698
|
+
id: edge.node.id + accessLevel.accessLevelRemoteId,
|
|
699
|
+
name: accessLevel.accessLevelName,
|
|
700
|
+
type: graphql_2.EntityType.Resource,
|
|
701
|
+
toString: () => accessLevel.accessLevelName,
|
|
702
|
+
},
|
|
703
|
+
}));
|
|
704
|
+
}
|
|
705
|
+
return [
|
|
706
|
+
{
|
|
707
|
+
message: (_a = edge.alias) !== null && _a !== void 0 ? _a : edge.node.name,
|
|
708
|
+
value: {
|
|
709
|
+
id: edge.node.id,
|
|
710
|
+
name: (_b = edge.alias) !== null && _b !== void 0 ? _b : edge.node.name,
|
|
711
|
+
type: graphql_2.EntityType.Resource,
|
|
712
|
+
toString: () => { var _a; return (_a = edge.alias) !== null && _a !== void 0 ? _a : edge.node.name; },
|
|
713
|
+
},
|
|
714
|
+
},
|
|
715
|
+
];
|
|
716
|
+
}
|
|
717
|
+
case "Group":
|
|
718
|
+
return [
|
|
719
|
+
{
|
|
720
|
+
message: (_c = edge.alias) !== null && _c !== void 0 ? _c : edge.node.name,
|
|
721
|
+
value: {
|
|
722
|
+
id: edge.node.id,
|
|
723
|
+
name: (_d = edge.alias) !== null && _d !== void 0 ? _d : edge.node.name,
|
|
724
|
+
type: graphql_2.EntityType.Group,
|
|
725
|
+
toString: () => { var _a; return (_a = edge.alias) !== null && _a !== void 0 ? _a : edge.node.name; },
|
|
726
|
+
},
|
|
727
|
+
},
|
|
728
|
+
];
|
|
729
|
+
}
|
|
730
|
+
}
|
|
347
731
|
async function chooseAssets(cmd, client, appId, requestMap) {
|
|
348
|
-
const
|
|
732
|
+
const initial = (await queryRequestableAssets(cmd, client, appId, "")) || [];
|
|
349
733
|
const assetPrompt = new AutoComplete({
|
|
350
734
|
name: "Assets",
|
|
351
735
|
message: "Select one or more assets:",
|
|
736
|
+
hint: multiSelectInstructions,
|
|
352
737
|
limit: 15,
|
|
353
738
|
multiple: true,
|
|
354
739
|
async choices(input) {
|
|
740
|
+
if (!input) {
|
|
741
|
+
return initial;
|
|
742
|
+
}
|
|
355
743
|
const filteredChoices = await queryRequestableAssets(cmd, client, appId, input);
|
|
356
|
-
return filteredChoices ||
|
|
744
|
+
return filteredChoices || initial;
|
|
357
745
|
},
|
|
358
746
|
validate: (answer) => {
|
|
359
747
|
if (answer.length < 1) {
|
|
@@ -370,6 +758,7 @@ async function chooseAssets(cmd, client, appId, requestMap) {
|
|
|
370
758
|
}
|
|
371
759
|
if (!(asset.id in entry.assets)) {
|
|
372
760
|
entry.assets[asset.id] = {
|
|
761
|
+
assetId: asset.id,
|
|
373
762
|
assetName: asset.name,
|
|
374
763
|
type: asset.type,
|
|
375
764
|
roles: {},
|
|
@@ -382,32 +771,36 @@ async function chooseRoles(cmd, client, appId, assetId, requestMap) {
|
|
|
382
771
|
var _a;
|
|
383
772
|
const entry = requestMap[appId];
|
|
384
773
|
const assetEntry = entry === null || entry === void 0 ? void 0 : entry.assets[assetId];
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
774
|
+
if (entry === undefined || assetEntry === undefined) {
|
|
775
|
+
throw new Error(`App ${appId} or Asset ${assetId} not found in requestMap`);
|
|
776
|
+
}
|
|
777
|
+
const assetRoles = (_a = (await queryAssetRoles(cmd, client, assetEntry.type, assetId))) !== null && _a !== void 0 ? _a : [];
|
|
778
|
+
if (assetRoles !== undefined &&
|
|
779
|
+
(assetRoles.length === 0 ||
|
|
780
|
+
(assetRoles.length === 1 && assetRoles[0].value.name === ""))) {
|
|
389
781
|
return;
|
|
390
782
|
}
|
|
391
|
-
const
|
|
392
|
-
name: "
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
783
|
+
const rolePrompt = new AutoComplete({
|
|
784
|
+
name: "Roles",
|
|
785
|
+
message: `Select one or more roles for ${assetEntry.assetName}:`,
|
|
786
|
+
hint: multiSelectInstructions,
|
|
787
|
+
limit: 15,
|
|
788
|
+
multiple: true,
|
|
789
|
+
choices: assetRoles,
|
|
396
790
|
validate: (answer) => {
|
|
397
|
-
if (
|
|
398
|
-
return "You must select at least one
|
|
791
|
+
if (answer.length < 1) {
|
|
792
|
+
return "You must select at least one item.";
|
|
399
793
|
}
|
|
400
794
|
return true;
|
|
401
795
|
},
|
|
402
796
|
});
|
|
403
|
-
|
|
404
|
-
throw new Error(`App ${appId} or Asset ${assetId} not found in requestMap`);
|
|
405
|
-
}
|
|
797
|
+
const roles = await rolePrompt.run();
|
|
406
798
|
if (!assetEntry.roles) {
|
|
407
799
|
assetEntry.roles = {};
|
|
408
800
|
}
|
|
409
801
|
for (const role of roles) {
|
|
410
802
|
assetEntry.roles[role.id] = {
|
|
803
|
+
roleId: role.id,
|
|
411
804
|
roleName: role.name,
|
|
412
805
|
};
|
|
413
806
|
}
|
|
@@ -415,14 +808,12 @@ async function chooseRoles(cmd, client, appId, assetId, requestMap) {
|
|
|
415
808
|
async function doneSelectingAssets() {
|
|
416
809
|
const submitMessage = "ā
Yes, proceed with request";
|
|
417
810
|
const addMoreMessage = "ā No, add more items";
|
|
418
|
-
const
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
},
|
|
425
|
-
]);
|
|
811
|
+
const prompt = new Select({
|
|
812
|
+
name: "submitOrAdd",
|
|
813
|
+
message: "Is this all you want to request?",
|
|
814
|
+
choices: [submitMessage, addMoreMessage],
|
|
815
|
+
});
|
|
816
|
+
const submitOrAdd = await prompt.run();
|
|
426
817
|
return submitOrAdd === submitMessage;
|
|
427
818
|
}
|
|
428
819
|
async function setRequestDefaults(cmd, client, metadata) {
|
|
@@ -432,18 +823,34 @@ async function setRequestDefaults(cmd, client, metadata) {
|
|
|
432
823
|
for (const appNode of Object.values(requestMap)) {
|
|
433
824
|
for (const [assetId, assetNode] of Object.entries(appNode.assets)) {
|
|
434
825
|
if (assetNode.roles !== undefined) {
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
826
|
+
const mappedRoles = Object.entries(assetNode.roles).map(([roleId, _roleNode]) => {
|
|
827
|
+
return roleId;
|
|
828
|
+
});
|
|
829
|
+
const roleIds = mappedRoles.length ? mappedRoles : [""];
|
|
830
|
+
for (const roleId of roleIds) {
|
|
831
|
+
switch (assetNode.type) {
|
|
832
|
+
case graphql_2.EntityType.Resource: {
|
|
833
|
+
requestedResources.push({
|
|
834
|
+
resourceId: assetId,
|
|
835
|
+
accessLevelRemoteId: roleId,
|
|
836
|
+
});
|
|
837
|
+
break;
|
|
838
|
+
}
|
|
839
|
+
case graphql_2.EntityType.Group: {
|
|
840
|
+
requestedGroups.push({
|
|
841
|
+
groupId: assetId,
|
|
842
|
+
accessLevelRemoteId: roleId,
|
|
843
|
+
});
|
|
844
|
+
break;
|
|
845
|
+
}
|
|
846
|
+
}
|
|
440
847
|
}
|
|
441
848
|
}
|
|
442
849
|
}
|
|
443
850
|
}
|
|
444
851
|
try {
|
|
445
852
|
const requestDefaults = await queryRequestDefaults(cmd, client, requestedResources, requestedGroups);
|
|
446
|
-
if (
|
|
853
|
+
if (requestDefaults !== undefined) {
|
|
447
854
|
metadata.requestDefaults.durationOptions =
|
|
448
855
|
requestDefaults.durationOptions;
|
|
449
856
|
metadata.requestDefaults.recommendedDurationInMinutes =
|
|
@@ -464,49 +871,133 @@ async function setRequestDefaults(cmd, client, metadata) {
|
|
|
464
871
|
}
|
|
465
872
|
}
|
|
466
873
|
async function promptForReason(metadata) {
|
|
467
|
-
|
|
874
|
+
const { reason } = await prompt([
|
|
468
875
|
{
|
|
469
876
|
name: "reason",
|
|
470
|
-
message: "
|
|
877
|
+
message: "Why do you need access?",
|
|
471
878
|
type: "input",
|
|
472
879
|
validate: (answer) => {
|
|
473
|
-
if (metadata.requestDefaults.reasonOptional && answer.length < 1) {
|
|
880
|
+
if (!metadata.requestDefaults.reasonOptional && answer.length < 1) {
|
|
474
881
|
return "A reason for requesting these assets is required.";
|
|
475
882
|
}
|
|
476
883
|
return true;
|
|
477
884
|
},
|
|
478
885
|
},
|
|
479
886
|
]);
|
|
887
|
+
metadata.reason = reason;
|
|
480
888
|
}
|
|
481
889
|
async function promptForExpiration(metadata) {
|
|
482
890
|
var _a, _b;
|
|
483
891
|
const durations = ((_b = (_a = metadata.requestDefaults) === null || _a === void 0 ? void 0 : _a.durationOptions) === null || _b === void 0 ? void 0 : _b.map((option) => {
|
|
892
|
+
var _a;
|
|
893
|
+
let label = option.label;
|
|
894
|
+
if (option.durationInMinutes ===
|
|
895
|
+
((_a = metadata.requestDefaults) === null || _a === void 0 ? void 0 : _a.maxDurationInMinutes)) {
|
|
896
|
+
label = `${label} (MAX)`;
|
|
897
|
+
}
|
|
898
|
+
if (option.durationInMinutes ===
|
|
899
|
+
metadata.requestDefaults.recommendedDurationInMinutes) {
|
|
900
|
+
label = `${label} (RECOMMENDED)`;
|
|
901
|
+
}
|
|
484
902
|
return {
|
|
485
|
-
|
|
486
|
-
metadata.requestDefaults.recommendedDurationInMinutes
|
|
487
|
-
? `${option.label} (Recommended)`
|
|
488
|
-
: option.label,
|
|
903
|
+
message: label,
|
|
489
904
|
value: {
|
|
490
|
-
label:
|
|
905
|
+
label: label,
|
|
491
906
|
durationInMinutes: option.durationInMinutes,
|
|
907
|
+
toString: () => label,
|
|
492
908
|
},
|
|
493
909
|
};
|
|
494
910
|
})) || [];
|
|
495
|
-
//
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
911
|
+
// Sort durations by minutes
|
|
912
|
+
durations.sort((a, b) => a.value.durationInMinutes - b.value.durationInMinutes);
|
|
913
|
+
const expirationSelect = new AutoComplete({
|
|
914
|
+
name: "expiration",
|
|
915
|
+
message: "When should access expire?",
|
|
916
|
+
type: "list",
|
|
917
|
+
choices: durations,
|
|
918
|
+
pageSize: 15,
|
|
919
|
+
});
|
|
920
|
+
let selected = await expirationSelect.run();
|
|
921
|
+
switch (selected.label) {
|
|
922
|
+
case "Custom": {
|
|
923
|
+
selected = await setCustomDuration(metadata);
|
|
924
|
+
break;
|
|
925
|
+
}
|
|
926
|
+
case "Permanent": {
|
|
927
|
+
selected.durationInMinutes = undefined;
|
|
928
|
+
break;
|
|
929
|
+
}
|
|
930
|
+
}
|
|
931
|
+
metadata.durationInMinutes = selected.durationInMinutes;
|
|
932
|
+
metadata.durationLabel = selected.label;
|
|
933
|
+
}
|
|
934
|
+
function getDurationNumbers(duration) {
|
|
935
|
+
const d = +duration.days || 0;
|
|
936
|
+
const h = +duration.hours || 0;
|
|
937
|
+
const m = +duration.minutes || 0;
|
|
938
|
+
return { d, h, m };
|
|
939
|
+
}
|
|
940
|
+
function getDurationInMinutes(duration) {
|
|
941
|
+
const { d, h, m } = getDurationNumbers(duration);
|
|
942
|
+
const minutesInDay = 1440; // 24 hours * 60 minutes
|
|
943
|
+
const minutesInHour = 60;
|
|
944
|
+
return d * minutesInDay + h * minutesInHour + m;
|
|
945
|
+
}
|
|
946
|
+
function getDHMFromMinutes(minutes) {
|
|
947
|
+
const label = [];
|
|
948
|
+
const d = Math.floor(minutes / 1440);
|
|
949
|
+
if (d > 0) {
|
|
950
|
+
label.push(`${d}d`);
|
|
951
|
+
}
|
|
952
|
+
const remainingMinutes = minutes % 1440;
|
|
953
|
+
const h = Math.floor(remainingMinutes / 60);
|
|
954
|
+
if (h > 0) {
|
|
955
|
+
label.push(`${h}h`);
|
|
956
|
+
}
|
|
957
|
+
const m = remainingMinutes % 60;
|
|
958
|
+
if (m > 0) {
|
|
959
|
+
label.push(`${m}m`);
|
|
960
|
+
}
|
|
961
|
+
return label.join(" ");
|
|
962
|
+
}
|
|
963
|
+
async function setCustomDuration(metadata) {
|
|
964
|
+
const durationForm = new Form({
|
|
965
|
+
name: "user",
|
|
966
|
+
message: "Please set a custom access duration:",
|
|
967
|
+
choices: [
|
|
968
|
+
{ name: "days", message: "Days", initial: "0" },
|
|
969
|
+
{ name: "hours", message: "Hours", initial: "0" },
|
|
970
|
+
{ name: "minutes", message: "Minutes", initial: "0" },
|
|
971
|
+
],
|
|
972
|
+
validate: (answer) => {
|
|
973
|
+
var _a, _b, _c;
|
|
974
|
+
const { d, h, m } = getDurationNumbers(answer);
|
|
975
|
+
const durationInMinutes = getDurationInMinutes(answer);
|
|
976
|
+
if (d < 0 || h < 0 || m < 0 || d + h + m === 0 || (h > 23 && m > 59)) {
|
|
977
|
+
return "Please enter a valid duration.";
|
|
978
|
+
}
|
|
979
|
+
if (((_a = metadata.requestDefaults) === null || _a === void 0 ? void 0 : _a.maxDurationInMinutes) &&
|
|
980
|
+
durationInMinutes > ((_b = metadata.requestDefaults) === null || _b === void 0 ? void 0 : _b.maxDurationInMinutes)) {
|
|
981
|
+
const maxDHM = getDHMFromMinutes((_c = metadata.requestDefaults) === null || _c === void 0 ? void 0 : _c.maxDurationInMinutes);
|
|
982
|
+
return `The max duration for the selected assets is ${maxDHM}.`;
|
|
983
|
+
}
|
|
984
|
+
return true;
|
|
506
985
|
},
|
|
507
|
-
|
|
986
|
+
return: (answer) => {
|
|
987
|
+
return getDurationInMinutes(answer);
|
|
988
|
+
},
|
|
989
|
+
});
|
|
990
|
+
const durationResult = await durationForm.run();
|
|
991
|
+
const { d, h, m } = getDurationNumbers(durationResult);
|
|
992
|
+
const durationInMinutes = getDurationInMinutes(durationResult);
|
|
993
|
+
const durationLabel = getDHMFromMinutes(durationInMinutes);
|
|
994
|
+
return {
|
|
995
|
+
durationInMinutes: durationInMinutes,
|
|
996
|
+
label: durationLabel,
|
|
997
|
+
};
|
|
508
998
|
}
|
|
509
|
-
async function
|
|
999
|
+
async function promptRequestSubmission(cmd, metadata) {
|
|
1000
|
+
(0, displays_1.displayFinalRequestSummary)(cmd, metadata);
|
|
510
1001
|
const submitMessage = "ā
Yes, submit request";
|
|
511
1002
|
const cancelMessage = "ā No, cancel request";
|
|
512
1003
|
const { submit } = await inquirer.prompt([
|
|
@@ -517,12 +1008,150 @@ async function submitFinalRequest(cmd) {
|
|
|
517
1008
|
choices: [submitMessage, cancelMessage],
|
|
518
1009
|
},
|
|
519
1010
|
]);
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
1011
|
+
switch (submit) {
|
|
1012
|
+
case submitMessage: {
|
|
1013
|
+
return;
|
|
1014
|
+
}
|
|
1015
|
+
case cancelMessage: {
|
|
1016
|
+
cmd.log("š« Access Request has been cancelled.");
|
|
1017
|
+
return;
|
|
1018
|
+
}
|
|
1019
|
+
default: {
|
|
1020
|
+
cmd.error("Unknown error occurred.");
|
|
1021
|
+
}
|
|
524
1022
|
}
|
|
525
|
-
|
|
526
|
-
|
|
1023
|
+
}
|
|
1024
|
+
async function submitFinalRequest(cmd, client, metadata) {
|
|
1025
|
+
var _a, _b, _c, _d;
|
|
1026
|
+
// Build requested assets lists for the mutation
|
|
1027
|
+
const requestedResources = [];
|
|
1028
|
+
const requestedGroups = [];
|
|
1029
|
+
for (const appNode of Object.values(metadata.requestMap)) {
|
|
1030
|
+
// This extraction is different than the one in setRequestDefaults.
|
|
1031
|
+
// Both extract the requestedResources and requestedGroups,
|
|
1032
|
+
// use different formats.
|
|
1033
|
+
for (const [assetId, assetNode] of Object.entries(appNode.assets)) {
|
|
1034
|
+
if (assetNode.roles) {
|
|
1035
|
+
const mappedRoles = Object.entries(assetNode.roles).map(([roleId, _roleNode]) => {
|
|
1036
|
+
return roleId;
|
|
1037
|
+
});
|
|
1038
|
+
const roleIds = mappedRoles.length > 0 ? mappedRoles : [""];
|
|
1039
|
+
for (const roleId of roleIds) {
|
|
1040
|
+
switch (assetNode.type) {
|
|
1041
|
+
case graphql_2.EntityType.Resource: {
|
|
1042
|
+
requestedResources.push({
|
|
1043
|
+
resourceId: assetId,
|
|
1044
|
+
accessLevel: {
|
|
1045
|
+
accessLevelName: ((_b = (_a = assetNode.roles) === null || _a === void 0 ? void 0 : _a[roleId]) === null || _b === void 0 ? void 0 : _b.roleName) || "",
|
|
1046
|
+
accessLevelRemoteId: roleId,
|
|
1047
|
+
},
|
|
1048
|
+
});
|
|
1049
|
+
break;
|
|
1050
|
+
}
|
|
1051
|
+
case graphql_2.EntityType.Group: {
|
|
1052
|
+
requestedGroups.push({
|
|
1053
|
+
groupId: assetId,
|
|
1054
|
+
accessLevel: {
|
|
1055
|
+
accessLevelName: ((_d = (_c = assetNode.roles) === null || _c === void 0 ? void 0 : _c[roleId]) === null || _d === void 0 ? void 0 : _d.roleName) || "",
|
|
1056
|
+
accessLevelRemoteId: roleId,
|
|
1057
|
+
},
|
|
1058
|
+
});
|
|
1059
|
+
break;
|
|
1060
|
+
}
|
|
1061
|
+
}
|
|
1062
|
+
}
|
|
1063
|
+
}
|
|
1064
|
+
}
|
|
1065
|
+
}
|
|
1066
|
+
const resp = await createRequest(cmd, client, requestedResources, requestedGroups, metadata.reason, metadata.durationInMinutes);
|
|
1067
|
+
// Build link to request
|
|
1068
|
+
const configData = (0, config_1.getOrCreateConfigData)(cmd.config.configDir);
|
|
1069
|
+
if (resp === null || resp === void 0 ? void 0 : resp.id) {
|
|
1070
|
+
cmd.log("\nš Your Access Request has been submitted!\n");
|
|
1071
|
+
cmd.log(`${chalk_1.default.bold("ID: ")} ${chalk_1.default.cyan(resp === null || resp === void 0 ? void 0 : resp.id)}`);
|
|
1072
|
+
if (resp === null || resp === void 0 ? void 0 : resp.status) {
|
|
1073
|
+
cmd.log((0, displays_1.getStyledStatus)(resp === null || resp === void 0 ? void 0 : resp.status));
|
|
1074
|
+
}
|
|
1075
|
+
const requestLink = `${configData[config_1.urlKey]}/requests/sent/${resp === null || resp === void 0 ? void 0 : resp.id}`;
|
|
1076
|
+
cmd.log(`${chalk_1.default.bold("Link:")} ${chalk_1.default.underline(requestLink)}\n`);
|
|
1077
|
+
}
|
|
1078
|
+
return;
|
|
1079
|
+
}
|
|
1080
|
+
async function bypassRequestSelection(cmd, client, flagValue, metadata) {
|
|
1081
|
+
var _a, _b;
|
|
1082
|
+
try {
|
|
1083
|
+
// Query Catalog Item endpoint to identify what the id belongs to (resource or group)
|
|
1084
|
+
for (const id of flagValue) {
|
|
1085
|
+
const [assetId, roleName] = id.split(":");
|
|
1086
|
+
const resp = await client.query({
|
|
1087
|
+
query: CATALOG_ITEM,
|
|
1088
|
+
variables: {
|
|
1089
|
+
uuid: assetId || "",
|
|
1090
|
+
},
|
|
1091
|
+
fetchPolicy: "network-only", // to avoid caching
|
|
1092
|
+
});
|
|
1093
|
+
switch (resp.data.catalogItem.__typename) {
|
|
1094
|
+
case "Group":
|
|
1095
|
+
case "Resource": {
|
|
1096
|
+
const item = resp.data.catalogItem;
|
|
1097
|
+
const assetName = item.__typename === "Resource" ? item.displayName : item.name;
|
|
1098
|
+
const requestableRoles = (item.accessLevels || [])
|
|
1099
|
+
// TODO: Support okta azure apps ?.filter((role) => role.accessLevelName !== "") // This assumes length == 1
|
|
1100
|
+
.map((role) => ({
|
|
1101
|
+
id: role.accessLevelRemoteId,
|
|
1102
|
+
name: role.accessLevelName,
|
|
1103
|
+
}));
|
|
1104
|
+
const appId = ((_a = item.connection) === null || _a === void 0 ? void 0 : _a.id) || "";
|
|
1105
|
+
if (!(appId in metadata.requestMap)) {
|
|
1106
|
+
metadata.requestMap[appId] = {
|
|
1107
|
+
appName: ((_b = item.connection) === null || _b === void 0 ? void 0 : _b.displayName) || "",
|
|
1108
|
+
appId: appId,
|
|
1109
|
+
assets: {},
|
|
1110
|
+
};
|
|
1111
|
+
}
|
|
1112
|
+
const assetEntry = metadata.requestMap[appId].assets[id];
|
|
1113
|
+
if (!assetEntry) {
|
|
1114
|
+
metadata.requestMap[appId].assets[assetId] = {
|
|
1115
|
+
assetId: assetId,
|
|
1116
|
+
assetName: assetName,
|
|
1117
|
+
type: entityTypeFromString(item.__typename),
|
|
1118
|
+
roles: {},
|
|
1119
|
+
};
|
|
1120
|
+
}
|
|
1121
|
+
if (requestableRoles.length > 0 &&
|
|
1122
|
+
!(requestableRoles.length === 1 && requestableRoles[0].name === "")) {
|
|
1123
|
+
const selectedRole = requestableRoles.find((role) => role.name === roleName);
|
|
1124
|
+
if (selectedRole !== undefined) {
|
|
1125
|
+
if (!metadata.requestMap[appId].assets[assetId].roles) {
|
|
1126
|
+
metadata.requestMap[appId].assets[assetId].roles = {};
|
|
1127
|
+
}
|
|
1128
|
+
metadata.requestMap[appId].assets[assetId].roles[selectedRole.id] = {
|
|
1129
|
+
roleId: selectedRole.id,
|
|
1130
|
+
roleName: selectedRole.name,
|
|
1131
|
+
};
|
|
1132
|
+
}
|
|
1133
|
+
else {
|
|
1134
|
+
cmd.error(`Access level specified does not match one of ${assetName}'s defined access levels:${requestableRoles.map((role) => role.name)}`);
|
|
1135
|
+
}
|
|
1136
|
+
}
|
|
1137
|
+
break;
|
|
1138
|
+
}
|
|
1139
|
+
default:
|
|
1140
|
+
cmd.error("Invalid asset id was passed in using the --id flag.");
|
|
1141
|
+
}
|
|
1142
|
+
}
|
|
1143
|
+
}
|
|
1144
|
+
catch (error) {
|
|
1145
|
+
if (error instanceof Error || typeof error === "string") {
|
|
1146
|
+
cmd.error(error);
|
|
1147
|
+
}
|
|
1148
|
+
}
|
|
1149
|
+
return;
|
|
1150
|
+
}
|
|
1151
|
+
function bypassDuration(cmd, duration, metadata) {
|
|
1152
|
+
const maxDuration = metadata.requestDefaults.maxDurationInMinutes;
|
|
1153
|
+
if (maxDuration && duration > maxDuration) {
|
|
1154
|
+
cmd.error(`The requested duration exceeds the allowed limit of ${maxDuration}`);
|
|
527
1155
|
}
|
|
1156
|
+
metadata.durationInMinutes = duration;
|
|
528
1157
|
}
|