opal-security 3.1.1-beta.5374f36 → 3.1.1-beta.5dc7dd4
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 +18 -18
- package/lib/commands/request/create.js +1 -1
- package/lib/commands/request/list.js +1 -1
- package/lib/lib/requests.js +50 -78
- package/lib/utils/displays.d.ts +2 -2
- package/lib/utils/displays.js +27 -42
- package/oclif.manifest.json +1 -1
- package/package.json +1 -2
package/README.md
CHANGED
|
@@ -22,7 +22,7 @@ $ npm install -g opal-security
|
|
|
22
22
|
$ opal COMMAND
|
|
23
23
|
running command...
|
|
24
24
|
$ opal (--version)
|
|
25
|
-
opal-security/3.1.1-beta.
|
|
25
|
+
opal-security/3.1.1-beta.5dc7dd4 linux-x64 node-v20.19.2
|
|
26
26
|
$ opal --help [COMMAND]
|
|
27
27
|
USAGE
|
|
28
28
|
$ opal COMMAND
|
|
@@ -101,7 +101,7 @@ EXAMPLES
|
|
|
101
101
|
$ opal aws:identity
|
|
102
102
|
```
|
|
103
103
|
|
|
104
|
-
_See code: [src/commands/aws/identity.ts](https://github.com/opalsecurity/opal-cli/blob/v3.1.1-beta.
|
|
104
|
+
_See code: [src/commands/aws/identity.ts](https://github.com/opalsecurity/opal-cli/blob/v3.1.1-beta.5dc7dd4/src/commands/aws/identity.ts)_
|
|
105
105
|
|
|
106
106
|
## `opal clear-auth-provider`
|
|
107
107
|
|
|
@@ -121,7 +121,7 @@ EXAMPLES
|
|
|
121
121
|
$ opal clear-auth-provider
|
|
122
122
|
```
|
|
123
123
|
|
|
124
|
-
_See code: [src/commands/clear-auth-provider.ts](https://github.com/opalsecurity/opal-cli/blob/v3.1.1-beta.
|
|
124
|
+
_See code: [src/commands/clear-auth-provider.ts](https://github.com/opalsecurity/opal-cli/blob/v3.1.1-beta.5dc7dd4/src/commands/clear-auth-provider.ts)_
|
|
125
125
|
|
|
126
126
|
## `opal curl-example`
|
|
127
127
|
|
|
@@ -138,7 +138,7 @@ DESCRIPTION
|
|
|
138
138
|
Prints out an example cURL command containing the parameters the CLI uses to query the Opal server.
|
|
139
139
|
```
|
|
140
140
|
|
|
141
|
-
_See code: [src/commands/curl-example.ts](https://github.com/opalsecurity/opal-cli/blob/v3.1.1-beta.
|
|
141
|
+
_See code: [src/commands/curl-example.ts](https://github.com/opalsecurity/opal-cli/blob/v3.1.1-beta.5dc7dd4/src/commands/curl-example.ts)_
|
|
142
142
|
|
|
143
143
|
## `opal groups get`
|
|
144
144
|
|
|
@@ -159,7 +159,7 @@ EXAMPLES
|
|
|
159
159
|
$ opal groups:get --id 54052a3e-5375-4392-aeaf-0c6c44c131d4
|
|
160
160
|
```
|
|
161
161
|
|
|
162
|
-
_See code: [src/commands/groups/get.ts](https://github.com/opalsecurity/opal-cli/blob/v3.1.1-beta.
|
|
162
|
+
_See code: [src/commands/groups/get.ts](https://github.com/opalsecurity/opal-cli/blob/v3.1.1-beta.5dc7dd4/src/commands/groups/get.ts)_
|
|
163
163
|
|
|
164
164
|
## `opal help [COMMANDS]`
|
|
165
165
|
|
|
@@ -209,7 +209,7 @@ EXAMPLES
|
|
|
209
209
|
$ opal iam-roles:start --id 51f7176b-0464-4a6f-8369-e951e187b398 --profileName "custom-profile"
|
|
210
210
|
```
|
|
211
211
|
|
|
212
|
-
_See code: [src/commands/iam-roles/start.ts](https://github.com/opalsecurity/opal-cli/blob/v3.1.1-beta.
|
|
212
|
+
_See code: [src/commands/iam-roles/start.ts](https://github.com/opalsecurity/opal-cli/blob/v3.1.1-beta.5dc7dd4/src/commands/iam-roles/start.ts)_
|
|
213
213
|
|
|
214
214
|
## `opal kube-roles start`
|
|
215
215
|
|
|
@@ -240,7 +240,7 @@ EXAMPLES
|
|
|
240
240
|
$ opal kube-roles:start --id 51f7176b-0464-4a6f-8369-e951e187b398 --accessLevelRemoteId "arn:aws:iam::712234975475:role/acme-eks-cluster-admin-role"
|
|
241
241
|
```
|
|
242
242
|
|
|
243
|
-
_See code: [src/commands/kube-roles/start.ts](https://github.com/opalsecurity/opal-cli/blob/v3.1.1-beta.
|
|
243
|
+
_See code: [src/commands/kube-roles/start.ts](https://github.com/opalsecurity/opal-cli/blob/v3.1.1-beta.5dc7dd4/src/commands/kube-roles/start.ts)_
|
|
244
244
|
|
|
245
245
|
## `opal login`
|
|
246
246
|
|
|
@@ -261,7 +261,7 @@ EXAMPLES
|
|
|
261
261
|
$ opal login
|
|
262
262
|
```
|
|
263
263
|
|
|
264
|
-
_See code: [src/commands/login.ts](https://github.com/opalsecurity/opal-cli/blob/v3.1.1-beta.
|
|
264
|
+
_See code: [src/commands/login.ts](https://github.com/opalsecurity/opal-cli/blob/v3.1.1-beta.5dc7dd4/src/commands/login.ts)_
|
|
265
265
|
|
|
266
266
|
## `opal logout`
|
|
267
267
|
|
|
@@ -281,7 +281,7 @@ EXAMPLES
|
|
|
281
281
|
$ opal logout
|
|
282
282
|
```
|
|
283
283
|
|
|
284
|
-
_See code: [src/commands/logout.ts](https://github.com/opalsecurity/opal-cli/blob/v3.1.1-beta.
|
|
284
|
+
_See code: [src/commands/logout.ts](https://github.com/opalsecurity/opal-cli/blob/v3.1.1-beta.5dc7dd4/src/commands/logout.ts)_
|
|
285
285
|
|
|
286
286
|
## `opal postgres-instances start`
|
|
287
287
|
|
|
@@ -318,7 +318,7 @@ EXAMPLES
|
|
|
318
318
|
$ opal postgres-instances:start --id 51f7176b-0464-4a6f-8369-e951e187b398 --accessLevelRemoteId fullaccess --action view
|
|
319
319
|
```
|
|
320
320
|
|
|
321
|
-
_See code: [src/commands/postgres-instances/start.ts](https://github.com/opalsecurity/opal-cli/blob/v3.1.1-beta.
|
|
321
|
+
_See code: [src/commands/postgres-instances/start.ts](https://github.com/opalsecurity/opal-cli/blob/v3.1.1-beta.5dc7dd4/src/commands/postgres-instances/start.ts)_
|
|
322
322
|
|
|
323
323
|
## `opal resources get`
|
|
324
324
|
|
|
@@ -339,7 +339,7 @@ EXAMPLES
|
|
|
339
339
|
$ opal resources:get --id 54052a3e-5375-4392-aeaf-0c6c44c131d4
|
|
340
340
|
```
|
|
341
341
|
|
|
342
|
-
_See code: [src/commands/resources/get.ts](https://github.com/opalsecurity/opal-cli/blob/v3.1.1-beta.
|
|
342
|
+
_See code: [src/commands/resources/get.ts](https://github.com/opalsecurity/opal-cli/blob/v3.1.1-beta.5dc7dd4/src/commands/resources/get.ts)_
|
|
343
343
|
|
|
344
344
|
## `opal set-auth-provider`
|
|
345
345
|
|
|
@@ -365,7 +365,7 @@ EXAMPLES
|
|
|
365
365
|
$ opal set-auth-provider --clientID 1234asdf --issuerUrl https://auth.example.com
|
|
366
366
|
```
|
|
367
367
|
|
|
368
|
-
_See code: [src/commands/set-auth-provider.ts](https://github.com/opalsecurity/opal-cli/blob/v3.1.1-beta.
|
|
368
|
+
_See code: [src/commands/set-auth-provider.ts](https://github.com/opalsecurity/opal-cli/blob/v3.1.1-beta.5dc7dd4/src/commands/set-auth-provider.ts)_
|
|
369
369
|
|
|
370
370
|
## `opal set-custom-header`
|
|
371
371
|
|
|
@@ -386,7 +386,7 @@ EXAMPLES
|
|
|
386
386
|
$ opal set-custom-header --header 'cf-access-token: $TOKEN'
|
|
387
387
|
```
|
|
388
388
|
|
|
389
|
-
_See code: [src/commands/set-custom-header.ts](https://github.com/opalsecurity/opal-cli/blob/v3.1.1-beta.
|
|
389
|
+
_See code: [src/commands/set-custom-header.ts](https://github.com/opalsecurity/opal-cli/blob/v3.1.1-beta.5dc7dd4/src/commands/set-custom-header.ts)_
|
|
390
390
|
|
|
391
391
|
## `opal set-token`
|
|
392
392
|
|
|
@@ -406,7 +406,7 @@ EXAMPLES
|
|
|
406
406
|
$ opal set-token
|
|
407
407
|
```
|
|
408
408
|
|
|
409
|
-
_See code: [src/commands/set-token.ts](https://github.com/opalsecurity/opal-cli/blob/v3.1.1-beta.
|
|
409
|
+
_See code: [src/commands/set-token.ts](https://github.com/opalsecurity/opal-cli/blob/v3.1.1-beta.5dc7dd4/src/commands/set-token.ts)_
|
|
410
410
|
|
|
411
411
|
## `opal set-url [URL]`
|
|
412
412
|
|
|
@@ -430,7 +430,7 @@ EXAMPLES
|
|
|
430
430
|
$ opal set-url
|
|
431
431
|
```
|
|
432
432
|
|
|
433
|
-
_See code: [src/commands/set-url.ts](https://github.com/opalsecurity/opal-cli/blob/v3.1.1-beta.
|
|
433
|
+
_See code: [src/commands/set-url.ts](https://github.com/opalsecurity/opal-cli/blob/v3.1.1-beta.5dc7dd4/src/commands/set-url.ts)_
|
|
434
434
|
|
|
435
435
|
## `opal ssh copyFrom`
|
|
436
436
|
|
|
@@ -461,7 +461,7 @@ EXAMPLES
|
|
|
461
461
|
$ opal ssh:copyFrom --src instance/dir --dest my/dir --id 51f7176b-0464-4a6f-8369-e951e187b398
|
|
462
462
|
```
|
|
463
463
|
|
|
464
|
-
_See code: [src/commands/ssh/copyFrom.ts](https://github.com/opalsecurity/opal-cli/blob/v3.1.1-beta.
|
|
464
|
+
_See code: [src/commands/ssh/copyFrom.ts](https://github.com/opalsecurity/opal-cli/blob/v3.1.1-beta.5dc7dd4/src/commands/ssh/copyFrom.ts)_
|
|
465
465
|
|
|
466
466
|
## `opal ssh copyTo`
|
|
467
467
|
|
|
@@ -492,7 +492,7 @@ EXAMPLES
|
|
|
492
492
|
$ opal ssh:copyTo --src my/dir --dest instance/dir --id 51f7176b-0464-4a6f-8369-e951e187b398
|
|
493
493
|
```
|
|
494
494
|
|
|
495
|
-
_See code: [src/commands/ssh/copyTo.ts](https://github.com/opalsecurity/opal-cli/blob/v3.1.1-beta.
|
|
495
|
+
_See code: [src/commands/ssh/copyTo.ts](https://github.com/opalsecurity/opal-cli/blob/v3.1.1-beta.5dc7dd4/src/commands/ssh/copyTo.ts)_
|
|
496
496
|
|
|
497
497
|
## `opal ssh start`
|
|
498
498
|
|
|
@@ -519,7 +519,7 @@ EXAMPLES
|
|
|
519
519
|
$ opal ssh:start --id 51f7176b-0464-4a6f-8369-e951e187b398
|
|
520
520
|
```
|
|
521
521
|
|
|
522
|
-
_See code: [src/commands/ssh/start.ts](https://github.com/opalsecurity/opal-cli/blob/v3.1.1-beta.
|
|
522
|
+
_See code: [src/commands/ssh/start.ts](https://github.com/opalsecurity/opal-cli/blob/v3.1.1-beta.5dc7dd4/src/commands/ssh/start.ts)_
|
|
523
523
|
|
|
524
524
|
## `opal version`
|
|
525
525
|
|
|
@@ -18,7 +18,7 @@ class RequestCreate extends core_1.Command {
|
|
|
18
18
|
await (0, requests_1.selectRequestableItems)(this, client, metadata.requestMap);
|
|
19
19
|
// Step 2: Display the selected items in a tree format
|
|
20
20
|
(0, displays_1.headerMessage)(this);
|
|
21
|
-
(0, displays_1.treeifyRequestMap)(
|
|
21
|
+
this.log((0, displays_1.treeifyRequestMap)(metadata.requestMap), "\n");
|
|
22
22
|
// Step 3: Prompt to add more items, repeat 1-3 if needed
|
|
23
23
|
shouldProceed = await (0, requests_1.doneSelectingAssets)();
|
|
24
24
|
}
|
package/lib/lib/requests.js
CHANGED
|
@@ -89,12 +89,13 @@ async function queryRequestableApps(cmd, client, input) {
|
|
|
89
89
|
default:
|
|
90
90
|
type = edge.node.__typename;
|
|
91
91
|
}
|
|
92
|
+
const label = `${edge.node.displayName} (${type})`;
|
|
92
93
|
return {
|
|
93
|
-
message:
|
|
94
|
+
message: label,
|
|
94
95
|
value: {
|
|
95
96
|
id: edge.node.id,
|
|
96
|
-
name:
|
|
97
|
-
toString: () =>
|
|
97
|
+
name: label,
|
|
98
|
+
toString: () => label,
|
|
98
99
|
},
|
|
99
100
|
};
|
|
100
101
|
});
|
|
@@ -161,10 +162,11 @@ async function queryRequestableAssets(cmd, client, appId, input) {
|
|
|
161
162
|
const name = ((_a = item.resource) === null || _a === void 0 ? void 0 : _a.name) || ((_b = item.group) === null || _b === void 0 ? void 0 : _b.name);
|
|
162
163
|
const id = ((_c = item.resource) === null || _c === void 0 ? void 0 : _c.id) || ((_d = item.group) === null || _d === void 0 ? void 0 : _d.id);
|
|
163
164
|
const type = ((_e = item.resource) === null || _e === void 0 ? void 0 : _e.__typename) || ((_f = item.group) === null || _f === void 0 ? void 0 : _f.__typename);
|
|
165
|
+
const label = `${name} (${type})`;
|
|
164
166
|
return {
|
|
165
|
-
message:
|
|
167
|
+
message: label,
|
|
166
168
|
value: {
|
|
167
|
-
name:
|
|
169
|
+
name: label || "",
|
|
168
170
|
id: id || "",
|
|
169
171
|
type: ((_g = item.resource) === null || _g === void 0 ? void 0 : _g.__typename) || ((_h = item.group) === null || _h === void 0 ? void 0 : _h.__typename) || "",
|
|
170
172
|
},
|
|
@@ -426,56 +428,57 @@ async function createRequest(cmd, client, requestedResources, requestedGroups, r
|
|
|
426
428
|
durationInMinutes: durationInMinutes,
|
|
427
429
|
},
|
|
428
430
|
});
|
|
431
|
+
let x;
|
|
429
432
|
switch ((_a = resp.data) === null || _a === void 0 ? void 0 : _a.createRequest.__typename) {
|
|
430
433
|
case "CreateRequestResult":
|
|
431
434
|
return (_b = resp.data) === null || _b === void 0 ? void 0 : _b.createRequest.request;
|
|
432
435
|
case "RequestDurationTooLargeError":
|
|
433
|
-
cmd.
|
|
436
|
+
x = cmd.error((_c = resp.data) === null || _c === void 0 ? void 0 : _c.createRequest.message);
|
|
434
437
|
break;
|
|
435
438
|
case "RequestRequiresUserAuthTokenForConnectionError":
|
|
436
|
-
cmd.
|
|
439
|
+
x = cmd.error((_d = resp.data) === null || _d === void 0 ? void 0 : _d.createRequest.message);
|
|
437
440
|
break;
|
|
438
441
|
case "NoReviewersSetForOwnerError":
|
|
439
|
-
cmd.
|
|
442
|
+
x = cmd.error((_e = resp.data) === null || _e === void 0 ? void 0 : _e.createRequest.message);
|
|
440
443
|
break;
|
|
441
444
|
case "NoReviewersSetForResourceError":
|
|
442
|
-
cmd.
|
|
445
|
+
x = cmd.error((_f = resp.data) === null || _f === void 0 ? void 0 : _f.createRequest.message);
|
|
443
446
|
break;
|
|
444
447
|
case "NoReviewersSetForGroupError":
|
|
445
|
-
cmd.
|
|
448
|
+
x = cmd.error((_g = resp.data) === null || _g === void 0 ? void 0 : _g.createRequest.message);
|
|
446
449
|
break;
|
|
447
450
|
case "NoManagerSetForRequestingUserError":
|
|
448
|
-
cmd.
|
|
451
|
+
x = cmd.error((_h = resp.data) === null || _h === void 0 ? void 0 : _h.createRequest.message);
|
|
449
452
|
break;
|
|
450
453
|
case "MfaInvalidError":
|
|
451
|
-
cmd.
|
|
454
|
+
x = cmd.error((_j = resp.data) === null || _j === void 0 ? void 0 : _j.createRequest.message);
|
|
452
455
|
break;
|
|
453
456
|
case "BulkRequestTooLargeError":
|
|
454
|
-
cmd.
|
|
457
|
+
x = cmd.error((_k = resp.data) === null || _k === void 0 ? void 0 : _k.createRequest.message);
|
|
455
458
|
break;
|
|
456
459
|
case "ItemCannotBeRequestedError":
|
|
457
|
-
cmd.
|
|
460
|
+
x = cmd.error((_l = resp.data) === null || _l === void 0 ? void 0 : _l.createRequest.message);
|
|
458
461
|
break;
|
|
459
462
|
case "UserCannotRequestAccessForTargetGroupError":
|
|
460
|
-
cmd.
|
|
463
|
+
x = cmd.error((_m = resp.data) === null || _m === void 0 ? void 0 : _m.createRequest.message);
|
|
461
464
|
break;
|
|
462
465
|
case "GroupNestingNotAllowedError":
|
|
463
|
-
cmd.
|
|
466
|
+
x = cmd.error((_o = resp.data) === null || _o === void 0 ? void 0 : _o.createRequest.message);
|
|
464
467
|
break;
|
|
465
468
|
case "TargetUserHasNestedAccessError":
|
|
466
|
-
cmd.
|
|
469
|
+
x = cmd.error((_p = resp.data) === null || _p === void 0 ? void 0 : _p.createRequest.message);
|
|
467
470
|
break;
|
|
468
471
|
case "RequestReasonMissingError":
|
|
469
|
-
cmd.
|
|
472
|
+
x = cmd.error((_q = resp.data) === null || _q === void 0 ? void 0 : _q.createRequest.message);
|
|
470
473
|
break;
|
|
471
474
|
case "RequestFieldValueMissingError":
|
|
472
|
-
cmd.
|
|
475
|
+
x = cmd.error((_r = resp.data) === null || _r === void 0 ? void 0 : _r.createRequest.message);
|
|
473
476
|
break;
|
|
474
477
|
case "LinkedGroupNotRequestableError":
|
|
475
|
-
cmd.
|
|
478
|
+
x = cmd.error((_s = resp.data) === null || _s === void 0 ? void 0 : _s.createRequest.message);
|
|
476
479
|
break;
|
|
477
480
|
case "RequestReasonBelowMinLengthError":
|
|
478
|
-
cmd.
|
|
481
|
+
x = cmd.error((_t = resp.data) === null || _t === void 0 ? void 0 : _t.createRequest.message);
|
|
479
482
|
break;
|
|
480
483
|
}
|
|
481
484
|
}
|
|
@@ -662,16 +665,10 @@ async function promptForReason(metadata) {
|
|
|
662
665
|
async function promptForExpiration(metadata) {
|
|
663
666
|
var _a, _b;
|
|
664
667
|
const durations = ((_b = (_a = metadata.requestDefaults) === null || _a === void 0 ? void 0 : _a.durationOptions) === null || _b === void 0 ? void 0 : _b.map((option) => {
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
label = `${label} (MAX)`;
|
|
670
|
-
}
|
|
671
|
-
if (option.durationInMinutes ===
|
|
672
|
-
metadata.requestDefaults.recommendedDurationInMinutes) {
|
|
673
|
-
label = `${label} (RECOMMENDED)`;
|
|
674
|
-
}
|
|
668
|
+
const label = option.durationInMinutes ===
|
|
669
|
+
metadata.requestDefaults.recommendedDurationInMinutes
|
|
670
|
+
? `${option.label} (Recommended)`
|
|
671
|
+
: option.label;
|
|
675
672
|
return {
|
|
676
673
|
message: label,
|
|
677
674
|
value: {
|
|
@@ -693,7 +690,7 @@ async function promptForExpiration(metadata) {
|
|
|
693
690
|
let selected = await expirationSelect.run();
|
|
694
691
|
switch (selected.label) {
|
|
695
692
|
case "Custom": {
|
|
696
|
-
selected = await setCustomDuration(
|
|
693
|
+
selected = await setCustomDuration();
|
|
697
694
|
break;
|
|
698
695
|
}
|
|
699
696
|
case "Permanent": {
|
|
@@ -704,36 +701,7 @@ async function promptForExpiration(metadata) {
|
|
|
704
701
|
metadata.durationInMinutes = selected.durationInMinutes;
|
|
705
702
|
metadata.durationLabel = selected.label;
|
|
706
703
|
}
|
|
707
|
-
function
|
|
708
|
-
const d = +duration.days || 0;
|
|
709
|
-
const h = +duration.hours || 0;
|
|
710
|
-
const m = +duration.minutes || 0;
|
|
711
|
-
return { d, h, m };
|
|
712
|
-
}
|
|
713
|
-
function getDurationInMinutes(duration) {
|
|
714
|
-
const { d, h, m } = getDurationNumbers(duration);
|
|
715
|
-
const minutesInDay = 1440; // 24 hours * 60 minutes
|
|
716
|
-
const minutesInHour = 60;
|
|
717
|
-
return d * minutesInDay + h * minutesInHour + m;
|
|
718
|
-
}
|
|
719
|
-
function getDHMFromMinutes(minutes) {
|
|
720
|
-
const label = [];
|
|
721
|
-
const d = Math.floor(minutes / 1440);
|
|
722
|
-
if (d > 0) {
|
|
723
|
-
label.push(`${d}d`);
|
|
724
|
-
}
|
|
725
|
-
const remainingMinutes = minutes % 1440;
|
|
726
|
-
const h = Math.floor(remainingMinutes / 60);
|
|
727
|
-
if (h > 0) {
|
|
728
|
-
label.push(`${h}h`);
|
|
729
|
-
}
|
|
730
|
-
const m = remainingMinutes % 60;
|
|
731
|
-
if (m > 0) {
|
|
732
|
-
label.push(`${m}m`);
|
|
733
|
-
}
|
|
734
|
-
return label.join(" ");
|
|
735
|
-
}
|
|
736
|
-
async function setCustomDuration(metadata) {
|
|
704
|
+
async function setCustomDuration() {
|
|
737
705
|
const durationForm = new Form({
|
|
738
706
|
name: "user",
|
|
739
707
|
message: "Please set a custom access duration:",
|
|
@@ -743,27 +711,31 @@ async function setCustomDuration(metadata) {
|
|
|
743
711
|
{ name: "minutes", message: "Minutes", initial: "0" },
|
|
744
712
|
],
|
|
745
713
|
validate: (answer) => {
|
|
746
|
-
|
|
747
|
-
const
|
|
748
|
-
const
|
|
749
|
-
if (
|
|
714
|
+
const days = Number.parseInt(answer.days);
|
|
715
|
+
const hours = Number.parseInt(answer.hours);
|
|
716
|
+
const minutes = Number.parseInt(answer.minutes);
|
|
717
|
+
if (days < 0 ||
|
|
718
|
+
hours < 0 ||
|
|
719
|
+
minutes < 0 ||
|
|
720
|
+
(days === 0 && hours === 0 && minutes === 0)) {
|
|
750
721
|
return "Please enter a valid duration.";
|
|
751
722
|
}
|
|
752
|
-
if (((_a = metadata.requestDefaults) === null || _a === void 0 ? void 0 : _a.maxDurationInMinutes) &&
|
|
753
|
-
durationInMinutes > ((_b = metadata.requestDefaults) === null || _b === void 0 ? void 0 : _b.maxDurationInMinutes)) {
|
|
754
|
-
const maxDHM = getDHMFromMinutes((_c = metadata.requestDefaults) === null || _c === void 0 ? void 0 : _c.maxDurationInMinutes);
|
|
755
|
-
return `The max duration for the selected assets is ${maxDHM}.`;
|
|
756
|
-
}
|
|
757
723
|
return true;
|
|
758
724
|
},
|
|
759
|
-
return: (answer) => {
|
|
760
|
-
return getDurationInMinutes(answer);
|
|
761
|
-
},
|
|
762
725
|
});
|
|
763
|
-
const
|
|
764
|
-
|
|
765
|
-
const durationInMinutes =
|
|
766
|
-
|
|
726
|
+
const duration = await durationForm.run();
|
|
727
|
+
// Convert to minutes, define the new custom label
|
|
728
|
+
const durationInMinutes = duration.days * 1440 + duration.hours * 60 + duration.minutes;
|
|
729
|
+
let durationLabel = "";
|
|
730
|
+
if (duration.days > 0) {
|
|
731
|
+
durationLabel += `${duration.days}d `;
|
|
732
|
+
}
|
|
733
|
+
if (duration.hours > 0) {
|
|
734
|
+
durationLabel += `${duration.hours}h `;
|
|
735
|
+
}
|
|
736
|
+
if (duration.minutes > 0) {
|
|
737
|
+
durationLabel += `${duration.minutes}m`;
|
|
738
|
+
}
|
|
767
739
|
return {
|
|
768
740
|
durationInMinutes: durationInMinutes,
|
|
769
741
|
label: durationLabel,
|
package/lib/utils/displays.d.ts
CHANGED
|
@@ -3,8 +3,8 @@ import type { Command } from "@oclif/core/lib/command";
|
|
|
3
3
|
import type { GetRequestQuery, GetRequestsQuery } from "../graphql/graphql";
|
|
4
4
|
import type { RequestMap, RequestMetadata } from "../lib/requests";
|
|
5
5
|
export declare function headerMessage(cmd: Command): void;
|
|
6
|
-
export declare function treeifyRequestMap(
|
|
6
|
+
export declare function treeifyRequestMap(requestMap: RequestMap): string;
|
|
7
7
|
export declare function displayFinalRequestSummary(cmd: Command, metadata: RequestMetadata): void;
|
|
8
8
|
export declare function getStyledStatus(status: string): string;
|
|
9
9
|
export declare function displayRequestDetails(cmd: Command, requestResp: ApolloQueryResult<GetRequestQuery>): void;
|
|
10
|
-
export declare function
|
|
10
|
+
export declare function displayRequestList(cmd: Command, requestResp: ApolloQueryResult<GetRequestsQuery>): void;
|
package/lib/utils/displays.js
CHANGED
|
@@ -5,64 +5,48 @@ exports.treeifyRequestMap = treeifyRequestMap;
|
|
|
5
5
|
exports.displayFinalRequestSummary = displayFinalRequestSummary;
|
|
6
6
|
exports.getStyledStatus = getStyledStatus;
|
|
7
7
|
exports.displayRequestDetails = displayRequestDetails;
|
|
8
|
-
exports.
|
|
8
|
+
exports.displayRequestList = displayRequestList;
|
|
9
9
|
const chalk_1 = require("chalk");
|
|
10
|
+
const treeify = require("object-treeify");
|
|
10
11
|
const Table = require("cli-table3");
|
|
11
|
-
const treeify = require("object-treeify").default;
|
|
12
12
|
function headerMessage(cmd) {
|
|
13
13
|
console.clear();
|
|
14
14
|
cmd.log("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
|
|
15
15
|
cmd.log("Opal Access Request ✏️");
|
|
16
16
|
cmd.log("Press Ctrl+C to cancel at any time.\n");
|
|
17
17
|
}
|
|
18
|
-
function treeifyRequestMap(
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
spacerNoNeighbour: " ",
|
|
23
|
-
spacerNeighbour: "│ ",
|
|
24
|
-
keyNoNeighbour: "└── ",
|
|
25
|
-
keyNeighbour: "├── ",
|
|
26
|
-
separator: "",
|
|
27
|
-
};
|
|
18
|
+
function treeifyRequestMap(requestMap) {
|
|
19
|
+
const requestTree = {};
|
|
20
|
+
// Create a tree structure from the requestMap
|
|
21
|
+
// Iterate over apps
|
|
28
22
|
for (const [_appId, appNode] of Object.entries(requestMap)) {
|
|
29
|
-
const
|
|
23
|
+
const appKey = `🔧${appNode.appName}`;
|
|
24
|
+
requestTree[appKey] = {}; // Initialize the app key
|
|
25
|
+
// Iterate over assets
|
|
30
26
|
for (const [_assetId, assetNode] of Object.entries(appNode.assets)) {
|
|
31
|
-
const assetKey =
|
|
27
|
+
const assetKey = `📦${assetNode.assetName}`;
|
|
32
28
|
if (assetNode.roles !== undefined) {
|
|
33
|
-
|
|
29
|
+
// If no roles were previously selected
|
|
30
|
+
requestTree[appKey][assetKey] = {}; // Initialize the asset key
|
|
31
|
+
// Iterate over roles
|
|
34
32
|
for (const [_roleId, roleNode] of Object.entries(assetNode.roles)) {
|
|
35
|
-
|
|
36
|
-
assetsTree[assetKey][roleKey] = null;
|
|
33
|
+
requestTree[appKey][assetKey][roleNode.roleName] = null; // Initialize the role key
|
|
37
34
|
}
|
|
38
35
|
}
|
|
39
36
|
else {
|
|
40
|
-
|
|
37
|
+
requestTree[appKey][assetKey] = null;
|
|
41
38
|
}
|
|
42
39
|
}
|
|
43
|
-
// Render tree for this app's assets
|
|
44
|
-
const assetsTreeString = treeify(assetsTree, options);
|
|
45
|
-
// Print App title first (without tree lines)
|
|
46
|
-
cmd.log(`${chalk_1.default.bold(appNode.appName)} ${chalk_1.default.dim("[App]")}`);
|
|
47
|
-
// Print its assets/roles indented underneath
|
|
48
|
-
cmd.log(assetsTreeString);
|
|
49
40
|
}
|
|
50
|
-
|
|
41
|
+
return String(treeify(requestTree));
|
|
51
42
|
}
|
|
52
43
|
function displayFinalRequestSummary(cmd, metadata) {
|
|
53
|
-
|
|
54
|
-
cmd.log("
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
const durationInMinutes = metadata.durationInMinutes;
|
|
60
|
-
cmd.log(`Duration: ${durationInMinutes ? formatDuration(durationInMinutes) : "Permanent"}`);
|
|
61
|
-
const reason = metadata.reason;
|
|
62
|
-
if (reason) {
|
|
63
|
-
cmd.log(`Reason: "${chalk_1.default.italic(reason)}"`);
|
|
64
|
-
}
|
|
65
|
-
cmd.log();
|
|
44
|
+
headerMessage(cmd);
|
|
45
|
+
cmd.log("Final Summary of Request\n");
|
|
46
|
+
const requestedAssets = treeifyRequestMap(metadata.requestMap);
|
|
47
|
+
const table = new Table();
|
|
48
|
+
table.push(["Requested Assets", requestedAssets], ["Reason", metadata.reason], ["Expiration", metadata.durationLabel]);
|
|
49
|
+
cmd.log(table.toString());
|
|
66
50
|
}
|
|
67
51
|
function getStyledStatus(status) {
|
|
68
52
|
switch (status) {
|
|
@@ -124,7 +108,7 @@ function displayRequestDetails(cmd, requestResp) {
|
|
|
124
108
|
}
|
|
125
109
|
}
|
|
126
110
|
}
|
|
127
|
-
function
|
|
111
|
+
function displayRequestList(cmd, requestResp) {
|
|
128
112
|
var _a, _b, _c, _d, _e;
|
|
129
113
|
switch (requestResp.data.requests.__typename) {
|
|
130
114
|
case "RequestsResult": {
|
|
@@ -147,9 +131,10 @@ function displayRequestListTable(cmd, requestResp) {
|
|
|
147
131
|
const targetUser = (_a = request.targetUser) === null || _a === void 0 ? void 0 : _a.displayName;
|
|
148
132
|
const reason = request.reason;
|
|
149
133
|
const status = request.status;
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
134
|
+
let formattedDuration = "";
|
|
135
|
+
if (request.durationInMinutes) {
|
|
136
|
+
formattedDuration = formatDuration(request.durationInMinutes);
|
|
137
|
+
}
|
|
153
138
|
const requestedResources = (_c = (_b = request.requestedResources) === null || _b === void 0 ? void 0 : _b.map((resource) => {
|
|
154
139
|
var _a, _b, _c;
|
|
155
140
|
if (((_a = resource.resource) === null || _a === void 0 ? void 0 : _a.__typename) === "Resource") {
|
package/oclif.manifest.json
CHANGED
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "opal-security",
|
|
3
3
|
"description": "Opal allows you to centrally manage access to all of your sensitive systems.",
|
|
4
|
-
"version": "3.1.1-beta.
|
|
4
|
+
"version": "3.1.1-beta.5dc7dd4",
|
|
5
5
|
"author": "Stephen Cobbe",
|
|
6
6
|
"bin": {
|
|
7
7
|
"opal": "./bin/run"
|
|
@@ -24,7 +24,6 @@
|
|
|
24
24
|
"lodash": "^4.17.21",
|
|
25
25
|
"moment": "^2.30.1",
|
|
26
26
|
"node-fetch": "^2.6.7",
|
|
27
|
-
"object-treeify": "^5.0.1",
|
|
28
27
|
"open": "^8.0.4",
|
|
29
28
|
"openid-client": "^5.6.5",
|
|
30
29
|
"prettyjson": "^1.2.1",
|