opal-security 3.1.1-beta.01fe2fd → 3.1.1-beta.03364ed
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 -148
- package/lib/commands/login.js +2 -6
- package/lib/commands/request/create.d.ts +2 -1
- package/lib/commands/request/create.js +12 -17
- package/lib/commands/request/get.d.ts +1 -0
- package/lib/commands/request/get.js +4 -1
- package/lib/commands/request/list.d.ts +1 -1
- package/lib/commands/request/list.js +4 -1
- package/lib/lib/apollo.js +4 -3
- package/lib/lib/credentials/index.d.ts +1 -2
- package/lib/lib/credentials/index.js +1 -2
- package/lib/lib/requests.d.ts +1 -3
- package/lib/lib/requests.js +88 -48
- package/lib/utils/displays.d.ts +1 -1
- package/lib/utils/displays.js +2 -8
- package/oclif.manifest.json +9 -36
- package/package.json +5 -4
- package/lib/commands/whoami.d.ts +0 -8
- package/lib/commands/whoami.js +0 -34
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.03364ed linux-x64 node-v20.19.2
|
|
26
26
|
$ opal --help [COMMAND]
|
|
27
27
|
USAGE
|
|
28
28
|
$ opal COMMAND
|
|
@@ -44,10 +44,6 @@ USAGE
|
|
|
44
44
|
* [`opal login`](#opal-login)
|
|
45
45
|
* [`opal logout`](#opal-logout)
|
|
46
46
|
* [`opal postgres-instances start`](#opal-postgres-instances-start)
|
|
47
|
-
* [`opal request create`](#opal-request-create)
|
|
48
|
-
* [`opal request get`](#opal-request-get)
|
|
49
|
-
* [`opal request list`](#opal-request-list)
|
|
50
|
-
* [`opal request ls`](#opal-request-ls)
|
|
51
47
|
* [`opal resources get`](#opal-resources-get)
|
|
52
48
|
* [`opal set-auth-provider`](#opal-set-auth-provider)
|
|
53
49
|
* [`opal set-custom-header`](#opal-set-custom-header)
|
|
@@ -57,7 +53,6 @@ USAGE
|
|
|
57
53
|
* [`opal ssh copyTo`](#opal-ssh-copyto)
|
|
58
54
|
* [`opal ssh start`](#opal-ssh-start)
|
|
59
55
|
* [`opal version`](#opal-version)
|
|
60
|
-
* [`opal whoami`](#opal-whoami)
|
|
61
56
|
|
|
62
57
|
## `opal autocomplete [SHELL]`
|
|
63
58
|
|
|
@@ -106,7 +101,7 @@ EXAMPLES
|
|
|
106
101
|
$ opal aws:identity
|
|
107
102
|
```
|
|
108
103
|
|
|
109
|
-
_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.03364ed/src/commands/aws/identity.ts)_
|
|
110
105
|
|
|
111
106
|
## `opal clear-auth-provider`
|
|
112
107
|
|
|
@@ -126,7 +121,7 @@ EXAMPLES
|
|
|
126
121
|
$ opal clear-auth-provider
|
|
127
122
|
```
|
|
128
123
|
|
|
129
|
-
_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.03364ed/src/commands/clear-auth-provider.ts)_
|
|
130
125
|
|
|
131
126
|
## `opal curl-example`
|
|
132
127
|
|
|
@@ -143,7 +138,7 @@ DESCRIPTION
|
|
|
143
138
|
Prints out an example cURL command containing the parameters the CLI uses to query the Opal server.
|
|
144
139
|
```
|
|
145
140
|
|
|
146
|
-
_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.03364ed/src/commands/curl-example.ts)_
|
|
147
142
|
|
|
148
143
|
## `opal groups get`
|
|
149
144
|
|
|
@@ -164,7 +159,7 @@ EXAMPLES
|
|
|
164
159
|
$ opal groups:get --id 54052a3e-5375-4392-aeaf-0c6c44c131d4
|
|
165
160
|
```
|
|
166
161
|
|
|
167
|
-
_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.03364ed/src/commands/groups/get.ts)_
|
|
168
163
|
|
|
169
164
|
## `opal help [COMMANDS]`
|
|
170
165
|
|
|
@@ -214,7 +209,7 @@ EXAMPLES
|
|
|
214
209
|
$ opal iam-roles:start --id 51f7176b-0464-4a6f-8369-e951e187b398 --profileName "custom-profile"
|
|
215
210
|
```
|
|
216
211
|
|
|
217
|
-
_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.03364ed/src/commands/iam-roles/start.ts)_
|
|
218
213
|
|
|
219
214
|
## `opal kube-roles start`
|
|
220
215
|
|
|
@@ -245,7 +240,7 @@ EXAMPLES
|
|
|
245
240
|
$ opal kube-roles:start --id 51f7176b-0464-4a6f-8369-e951e187b398 --accessLevelRemoteId "arn:aws:iam::712234975475:role/acme-eks-cluster-admin-role"
|
|
246
241
|
```
|
|
247
242
|
|
|
248
|
-
_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.03364ed/src/commands/kube-roles/start.ts)_
|
|
249
244
|
|
|
250
245
|
## `opal login`
|
|
251
246
|
|
|
@@ -266,7 +261,7 @@ EXAMPLES
|
|
|
266
261
|
$ opal login
|
|
267
262
|
```
|
|
268
263
|
|
|
269
|
-
_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.03364ed/src/commands/login.ts)_
|
|
270
265
|
|
|
271
266
|
## `opal logout`
|
|
272
267
|
|
|
@@ -286,7 +281,7 @@ EXAMPLES
|
|
|
286
281
|
$ opal logout
|
|
287
282
|
```
|
|
288
283
|
|
|
289
|
-
_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.03364ed/src/commands/logout.ts)_
|
|
290
285
|
|
|
291
286
|
## `opal postgres-instances start`
|
|
292
287
|
|
|
@@ -323,115 +318,7 @@ EXAMPLES
|
|
|
323
318
|
$ opal postgres-instances:start --id 51f7176b-0464-4a6f-8369-e951e187b398 --accessLevelRemoteId fullaccess --action view
|
|
324
319
|
```
|
|
325
320
|
|
|
326
|
-
_See code: [src/commands/postgres-instances/start.ts](https://github.com/opalsecurity/opal-cli/blob/v3.1.1-beta.
|
|
327
|
-
|
|
328
|
-
## `opal request create`
|
|
329
|
-
|
|
330
|
-
Creates an Opal access request via an interactive form
|
|
331
|
-
|
|
332
|
-
```
|
|
333
|
-
USAGE
|
|
334
|
-
$ opal request create [-h] [-a <value>...] [-r <value>] [-d <value>]
|
|
335
|
-
|
|
336
|
-
FLAGS
|
|
337
|
-
-a, --assets=<value>... The ids of the assets (resource, group) to request access to. Append a role ID using a colon
|
|
338
|
-
if needed, e.g. `--assets 123:456`.
|
|
339
|
-
If not provided, an interactive selection flow will be available to select assets to request.
|
|
340
|
-
-d, --duration=<value> The duration of access for the request in minutes. If not provided, you will be prompted.
|
|
341
|
-
-h, --help Show CLI help.
|
|
342
|
-
-r, --reason=<value> The reason for the request, contained in quotes. If not provided, you will be prompted.
|
|
343
|
-
|
|
344
|
-
DESCRIPTION
|
|
345
|
-
Creates an Opal access request via an interactive form
|
|
346
|
-
```
|
|
347
|
-
|
|
348
|
-
_See code: [src/commands/request/create.ts](https://github.com/opalsecurity/opal-cli/blob/v3.1.1-beta.01fe2fd/src/commands/request/create.ts)_
|
|
349
|
-
|
|
350
|
-
## `opal request get`
|
|
351
|
-
|
|
352
|
-
Lists access requests
|
|
353
|
-
|
|
354
|
-
```
|
|
355
|
-
USAGE
|
|
356
|
-
$ opal request get [-h] [-i <value>] [-v]
|
|
357
|
-
|
|
358
|
-
FLAGS
|
|
359
|
-
-h, --help Show CLI help.
|
|
360
|
-
-i, --id=<value> The Opal ID of the asset. You can find this from the URL, e.g. https://opal.dev/resources/[ID]
|
|
361
|
-
-v, --verbose Enable verbose output, prints full response in JSON format. Defaults to false.
|
|
362
|
-
|
|
363
|
-
DESCRIPTION
|
|
364
|
-
Lists access requests
|
|
365
|
-
|
|
366
|
-
EXAMPLES
|
|
367
|
-
$ opal request get --id 54052a3e-5375-4392-aeaf-0c6c44c131d4
|
|
368
|
-
|
|
369
|
-
$ opal request get --id 54052a3e-5375-4392-aeaf-0c6c44c131d4 --verbose
|
|
370
|
-
```
|
|
371
|
-
|
|
372
|
-
_See code: [src/commands/request/get.ts](https://github.com/opalsecurity/opal-cli/blob/v3.1.1-beta.01fe2fd/src/commands/request/get.ts)_
|
|
373
|
-
|
|
374
|
-
## `opal request list`
|
|
375
|
-
|
|
376
|
-
Lists your n recent outgoing access requests
|
|
377
|
-
|
|
378
|
-
```
|
|
379
|
-
USAGE
|
|
380
|
-
$ opal request list [-h] [-n <value>] [-p] [-v]
|
|
381
|
-
|
|
382
|
-
FLAGS
|
|
383
|
-
-h, --help Show CLI help.
|
|
384
|
-
-n, --n=<value> [default: 10] Defines number of requests to be returned. 1 <= n <= 100.
|
|
385
|
-
-p, --pending Show only pending requests. Defaults to false.
|
|
386
|
-
-v, --verbose Enable verbose output, prints full response in JSON format. Defaults to false.
|
|
387
|
-
|
|
388
|
-
DESCRIPTION
|
|
389
|
-
Lists your n recent outgoing access requests
|
|
390
|
-
|
|
391
|
-
ALIASES
|
|
392
|
-
$ opal request ls
|
|
393
|
-
|
|
394
|
-
EXAMPLES
|
|
395
|
-
$ opal request list --n 5
|
|
396
|
-
|
|
397
|
-
$ opal request list --n 5 --pending
|
|
398
|
-
|
|
399
|
-
$ opal request list --n 5 --verbose
|
|
400
|
-
|
|
401
|
-
$ opal request list --n 5 --pending --verbose
|
|
402
|
-
```
|
|
403
|
-
|
|
404
|
-
_See code: [src/commands/request/list.ts](https://github.com/opalsecurity/opal-cli/blob/v3.1.1-beta.01fe2fd/src/commands/request/list.ts)_
|
|
405
|
-
|
|
406
|
-
## `opal request ls`
|
|
407
|
-
|
|
408
|
-
Lists your n recent outgoing access requests
|
|
409
|
-
|
|
410
|
-
```
|
|
411
|
-
USAGE
|
|
412
|
-
$ opal request ls [-h] [-n <value>] [-p] [-v]
|
|
413
|
-
|
|
414
|
-
FLAGS
|
|
415
|
-
-h, --help Show CLI help.
|
|
416
|
-
-n, --n=<value> [default: 10] Defines number of requests to be returned. 1 <= n <= 100.
|
|
417
|
-
-p, --pending Show only pending requests. Defaults to false.
|
|
418
|
-
-v, --verbose Enable verbose output, prints full response in JSON format. Defaults to false.
|
|
419
|
-
|
|
420
|
-
DESCRIPTION
|
|
421
|
-
Lists your n recent outgoing access requests
|
|
422
|
-
|
|
423
|
-
ALIASES
|
|
424
|
-
$ opal request ls
|
|
425
|
-
|
|
426
|
-
EXAMPLES
|
|
427
|
-
$ opal request list --n 5
|
|
428
|
-
|
|
429
|
-
$ opal request list --n 5 --pending
|
|
430
|
-
|
|
431
|
-
$ opal request list --n 5 --verbose
|
|
432
|
-
|
|
433
|
-
$ opal request list --n 5 --pending --verbose
|
|
434
|
-
```
|
|
321
|
+
_See code: [src/commands/postgres-instances/start.ts](https://github.com/opalsecurity/opal-cli/blob/v3.1.1-beta.03364ed/src/commands/postgres-instances/start.ts)_
|
|
435
322
|
|
|
436
323
|
## `opal resources get`
|
|
437
324
|
|
|
@@ -452,7 +339,7 @@ EXAMPLES
|
|
|
452
339
|
$ opal resources:get --id 54052a3e-5375-4392-aeaf-0c6c44c131d4
|
|
453
340
|
```
|
|
454
341
|
|
|
455
|
-
_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.03364ed/src/commands/resources/get.ts)_
|
|
456
343
|
|
|
457
344
|
## `opal set-auth-provider`
|
|
458
345
|
|
|
@@ -478,7 +365,7 @@ EXAMPLES
|
|
|
478
365
|
$ opal set-auth-provider --clientID 1234asdf --issuerUrl https://auth.example.com
|
|
479
366
|
```
|
|
480
367
|
|
|
481
|
-
_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.03364ed/src/commands/set-auth-provider.ts)_
|
|
482
369
|
|
|
483
370
|
## `opal set-custom-header`
|
|
484
371
|
|
|
@@ -499,7 +386,7 @@ EXAMPLES
|
|
|
499
386
|
$ opal set-custom-header --header 'cf-access-token: $TOKEN'
|
|
500
387
|
```
|
|
501
388
|
|
|
502
|
-
_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.03364ed/src/commands/set-custom-header.ts)_
|
|
503
390
|
|
|
504
391
|
## `opal set-token`
|
|
505
392
|
|
|
@@ -519,7 +406,7 @@ EXAMPLES
|
|
|
519
406
|
$ opal set-token
|
|
520
407
|
```
|
|
521
408
|
|
|
522
|
-
_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.03364ed/src/commands/set-token.ts)_
|
|
523
410
|
|
|
524
411
|
## `opal set-url [URL]`
|
|
525
412
|
|
|
@@ -543,7 +430,7 @@ EXAMPLES
|
|
|
543
430
|
$ opal set-url
|
|
544
431
|
```
|
|
545
432
|
|
|
546
|
-
_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.03364ed/src/commands/set-url.ts)_
|
|
547
434
|
|
|
548
435
|
## `opal ssh copyFrom`
|
|
549
436
|
|
|
@@ -574,7 +461,7 @@ EXAMPLES
|
|
|
574
461
|
$ opal ssh:copyFrom --src instance/dir --dest my/dir --id 51f7176b-0464-4a6f-8369-e951e187b398
|
|
575
462
|
```
|
|
576
463
|
|
|
577
|
-
_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.03364ed/src/commands/ssh/copyFrom.ts)_
|
|
578
465
|
|
|
579
466
|
## `opal ssh copyTo`
|
|
580
467
|
|
|
@@ -605,7 +492,7 @@ EXAMPLES
|
|
|
605
492
|
$ opal ssh:copyTo --src my/dir --dest instance/dir --id 51f7176b-0464-4a6f-8369-e951e187b398
|
|
606
493
|
```
|
|
607
494
|
|
|
608
|
-
_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.03364ed/src/commands/ssh/copyTo.ts)_
|
|
609
496
|
|
|
610
497
|
## `opal ssh start`
|
|
611
498
|
|
|
@@ -632,7 +519,7 @@ EXAMPLES
|
|
|
632
519
|
$ opal ssh:start --id 51f7176b-0464-4a6f-8369-e951e187b398
|
|
633
520
|
```
|
|
634
521
|
|
|
635
|
-
_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.03364ed/src/commands/ssh/start.ts)_
|
|
636
523
|
|
|
637
524
|
## `opal version`
|
|
638
525
|
|
|
@@ -653,21 +540,4 @@ FLAG DESCRIPTIONS
|
|
|
653
540
|
```
|
|
654
541
|
|
|
655
542
|
_See code: [@oclif/plugin-version](https://github.com/oclif/plugin-version/blob/v2.2.27/src/commands/version.ts)_
|
|
656
|
-
|
|
657
|
-
## `opal whoami`
|
|
658
|
-
|
|
659
|
-
Describes current url set, organization name, and logged in user if applicable.
|
|
660
|
-
|
|
661
|
-
```
|
|
662
|
-
USAGE
|
|
663
|
-
$ opal whoami [-h]
|
|
664
|
-
|
|
665
|
-
FLAGS
|
|
666
|
-
-h, --help Show CLI help.
|
|
667
|
-
|
|
668
|
-
DESCRIPTION
|
|
669
|
-
Describes current url set, organization name, and logged in user if applicable.
|
|
670
|
-
```
|
|
671
|
-
|
|
672
|
-
_See code: [src/commands/whoami.ts](https://github.com/opalsecurity/opal-cli/blob/v3.1.1-beta.01fe2fd/src/commands/whoami.ts)_
|
|
673
543
|
<!-- commandsstop -->
|
package/lib/commands/login.js
CHANGED
|
@@ -88,14 +88,12 @@ class Login extends core_1.Command {
|
|
|
88
88
|
const configData = (0, config_1.getOrCreateConfigData)(configDir);
|
|
89
89
|
let email = flags.email;
|
|
90
90
|
let organizationId;
|
|
91
|
-
let organizationName;
|
|
92
91
|
let clientIDCandidate;
|
|
93
92
|
const existingCreds = await (0, credentials_1.getOpalCredentials)(this, false);
|
|
94
93
|
// Only use the previous email + organizationID if email isn't explicitly specified.
|
|
95
94
|
if (!email) {
|
|
96
95
|
email = existingCreds.email;
|
|
97
96
|
organizationId = existingCreds.organizationID;
|
|
98
|
-
organizationName = existingCreds.organizationName;
|
|
99
97
|
clientIDCandidate = existingCreds.clientIDCandidate;
|
|
100
98
|
}
|
|
101
99
|
await (0, credentials_1.removeOpalCredentials)(this);
|
|
@@ -151,7 +149,6 @@ class Login extends core_1.Command {
|
|
|
151
149
|
if (signInOrganizations && signInOrganizations.length > 0) {
|
|
152
150
|
if (signInOrganizations.length === 1) {
|
|
153
151
|
organizationId = signInOrganizations[0].organizationId;
|
|
154
|
-
organizationName = signInOrganizations[0].organizationName;
|
|
155
152
|
clientIDCandidate = signInOrganizations[0].cliClientId;
|
|
156
153
|
}
|
|
157
154
|
else {
|
|
@@ -167,7 +164,6 @@ class Login extends core_1.Command {
|
|
|
167
164
|
},
|
|
168
165
|
]);
|
|
169
166
|
organizationId = responses.signInOrganization.organizationId;
|
|
170
|
-
organizationName = responses.signInOrganization.organizationName;
|
|
171
167
|
clientIDCandidate = responses.signInOrganization.cliClientId;
|
|
172
168
|
}
|
|
173
169
|
}
|
|
@@ -242,10 +238,10 @@ class Login extends core_1.Command {
|
|
|
242
238
|
if (tokenExchangeError) {
|
|
243
239
|
this.log("WARN: Failed to exchange access token for session in Opal. Falling back to using access token for authenticating requests\n");
|
|
244
240
|
// TODO: consider adding a warn line recommending upgrading Opal to version XYZ, once accompanying PR is pushed to prod
|
|
245
|
-
await (0, credentials_1.setOpalCredentials)(this, email, organizationId !== null && organizationId !== void 0 ? organizationId : "", clientIDCandidate, (tokenSet === null || tokenSet === void 0 ? void 0 : tokenSet.access_token) || "", credentials_1.SecretType.ApiToken
|
|
241
|
+
await (0, credentials_1.setOpalCredentials)(this, email, organizationId !== null && organizationId !== void 0 ? organizationId : "", clientIDCandidate, (tokenSet === null || tokenSet === void 0 ? void 0 : tokenSet.access_token) || "", credentials_1.SecretType.ApiToken);
|
|
246
242
|
}
|
|
247
243
|
else {
|
|
248
|
-
await (0, credentials_1.setOpalCredentials)(this, email, organizationId !== null && organizationId !== void 0 ? organizationId : "", clientIDCandidate, apollo_1.cookieStr, credentials_1.SecretType.Cookie
|
|
244
|
+
await (0, credentials_1.setOpalCredentials)(this, email, organizationId !== null && organizationId !== void 0 ? organizationId : "", clientIDCandidate, apollo_1.cookieStr, credentials_1.SecretType.Cookie);
|
|
249
245
|
}
|
|
250
246
|
// "Representative" authenticated call to check the log-in worked as expected.
|
|
251
247
|
const { resp: authCheckResp, error: authCheckErr } = await (0, handler_1.runQueryDeprecated)({
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { Command } from "@oclif/core";
|
|
2
2
|
export default class RequestCreate extends Command {
|
|
3
|
+
static hidden: boolean;
|
|
3
4
|
static description: string;
|
|
4
5
|
static flags: {
|
|
5
6
|
help: import("@oclif/core/lib/interfaces").BooleanFlag<void>;
|
|
6
|
-
|
|
7
|
+
id: import("@oclif/core/lib/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
7
8
|
reason: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
8
9
|
duration: import("@oclif/core/lib/interfaces").OptionFlag<number | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
9
10
|
};
|
|
@@ -2,20 +2,20 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
const core_1 = require("@oclif/core");
|
|
4
4
|
const apollo_1 = require("../../lib/apollo");
|
|
5
|
-
const cmd_1 = require("../../lib/cmd");
|
|
6
5
|
const flags_1 = require("../../lib/flags");
|
|
7
6
|
const requests_1 = require("../../lib/requests");
|
|
8
7
|
const displays_1 = require("../../utils/displays");
|
|
8
|
+
const utils_1 = require("../../utils/utils");
|
|
9
9
|
class RequestCreate extends core_1.Command {
|
|
10
10
|
async run() {
|
|
11
|
-
(0, cmd_1.setMostRecentCommand)(this);
|
|
12
11
|
await (0, apollo_1.initClient)(this, true);
|
|
13
12
|
const client = await (0, apollo_1.getClient)(this, true);
|
|
13
|
+
(0, utils_1.restrictToDev)(); //TODO: Remove after development is complete
|
|
14
14
|
const { flags } = await this.parse(RequestCreate);
|
|
15
15
|
const metadata = (0, requests_1.initEmptyRequestMetadata)();
|
|
16
|
-
if (flags.
|
|
16
|
+
if (flags.id) {
|
|
17
17
|
// if IDs are provided, bypass the interactive selection process
|
|
18
|
-
await (0, requests_1.bypassRequestSelection)(this, client, flags.
|
|
18
|
+
await (0, requests_1.bypassRequestSelection)(this, client, flags.id, metadata);
|
|
19
19
|
}
|
|
20
20
|
else {
|
|
21
21
|
(0, displays_1.headerMessage)(this);
|
|
@@ -36,9 +36,7 @@ class RequestCreate extends core_1.Command {
|
|
|
36
36
|
if (flags.reason) {
|
|
37
37
|
metadata.reason = flags.reason;
|
|
38
38
|
}
|
|
39
|
-
else
|
|
40
|
-
flags.assets &&
|
|
41
|
-
flags.duration)) {
|
|
39
|
+
else {
|
|
42
40
|
await (0, requests_1.promptForReason)(metadata);
|
|
43
41
|
}
|
|
44
42
|
// Step 5: Prompt for expiration
|
|
@@ -49,24 +47,21 @@ class RequestCreate extends core_1.Command {
|
|
|
49
47
|
await (0, requests_1.promptForExpiration)(metadata);
|
|
50
48
|
}
|
|
51
49
|
// Step 6: Display final summary of request
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
flags.duration &&
|
|
55
|
-
(metadata.requestDefaults.reasonOptional || flags.reason))) {
|
|
56
|
-
canSubmit = await (0, requests_1.promptRequestSubmission)(this, metadata);
|
|
50
|
+
if (!(flags.id && flags.reason && flags.duration)) {
|
|
51
|
+
await (0, requests_1.promptRequestSubmission)(this, metadata);
|
|
57
52
|
}
|
|
58
53
|
// Step 7: Prompt for final submission
|
|
59
|
-
|
|
60
|
-
await (0, requests_1.submitFinalRequest)(this, client, metadata);
|
|
54
|
+
await (0, requests_1.submitFinalRequest)(this, client, metadata);
|
|
61
55
|
}
|
|
62
56
|
}
|
|
57
|
+
RequestCreate.hidden = true;
|
|
63
58
|
RequestCreate.description = "Creates an Opal access request via an interactive form";
|
|
64
59
|
RequestCreate.flags = {
|
|
65
60
|
help: flags_1.SHARED_FLAGS.help,
|
|
66
|
-
|
|
67
|
-
char: "
|
|
61
|
+
id: core_1.Flags.string({
|
|
62
|
+
char: "i",
|
|
68
63
|
multiple: true,
|
|
69
|
-
description: "The
|
|
64
|
+
description: "The id of the asset (resource, group) to request access to. Append a role ID using a colon if needed, e.g. `--id 123:456`.\
|
|
70
65
|
\n If not provided, an interactive selection flow will be available to select assets to request.",
|
|
71
66
|
}),
|
|
72
67
|
reason: core_1.Flags.string({
|
|
@@ -8,6 +8,7 @@ const cmd_1 = require("../../lib/cmd");
|
|
|
8
8
|
const config_1 = require("../../lib/config");
|
|
9
9
|
const flags_1 = require("../../lib/flags");
|
|
10
10
|
const displays_1 = require("../../utils/displays");
|
|
11
|
+
const utils_1 = require("../../utils/utils");
|
|
11
12
|
const GET_REQUEST = (0, graphql_1.graphql)(`
|
|
12
13
|
query GetRequest(
|
|
13
14
|
$id: RequestId!
|
|
@@ -57,13 +58,14 @@ const GET_REQUEST = (0, graphql_1.graphql)(`
|
|
|
57
58
|
`);
|
|
58
59
|
class GetRequest extends core_1.Command {
|
|
59
60
|
async run() {
|
|
61
|
+
(0, utils_1.restrictToDev)(); //TODO: Remove after development is complete
|
|
60
62
|
(0, cmd_1.setMostRecentCommand)(this);
|
|
61
63
|
const configData = (0, config_1.getOrCreateConfigData)(this.config.configDir);
|
|
62
64
|
const client = await (0, apollo_1.getClient)(this, true);
|
|
63
65
|
// Verify id tag was provided
|
|
64
66
|
const { flags } = await this.parse(GetRequest);
|
|
65
67
|
if (!flags.id) {
|
|
66
|
-
this.log("Error: Please provide a
|
|
68
|
+
this.log("Error: Please provide a group ID using the --id flag.");
|
|
67
69
|
this.log("ex. opal request get --id 54052a3e-5375-4392-aeaf-0c6c44c131d4");
|
|
68
70
|
return;
|
|
69
71
|
}
|
|
@@ -94,6 +96,7 @@ class GetRequest extends core_1.Command {
|
|
|
94
96
|
}
|
|
95
97
|
}
|
|
96
98
|
}
|
|
99
|
+
GetRequest.hidden = true;
|
|
97
100
|
GetRequest.description = "Lists access requests";
|
|
98
101
|
GetRequest.flags = {
|
|
99
102
|
help: flags_1.SHARED_FLAGS.help,
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { Command } from "@oclif/core";
|
|
2
2
|
export default class ListRequests extends Command {
|
|
3
|
+
static hidden: boolean;
|
|
3
4
|
static description: string;
|
|
4
5
|
static examples: string[];
|
|
5
|
-
static aliases: string[];
|
|
6
6
|
static flags: {
|
|
7
7
|
help: import("@oclif/core/lib/interfaces").BooleanFlag<void>;
|
|
8
8
|
n: import("@oclif/core/lib/interfaces").OptionFlag<number, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
@@ -6,6 +6,7 @@ const apollo_1 = require("../../lib/apollo");
|
|
|
6
6
|
const cmd_1 = require("../../lib/cmd");
|
|
7
7
|
const flags_1 = require("../../lib/flags");
|
|
8
8
|
const displays_1 = require("../../utils/displays");
|
|
9
|
+
const utils_1 = require("../../utils/utils");
|
|
9
10
|
// Add date filters, search query,
|
|
10
11
|
const GET_REQUESTS = (0, graphql_1.graphql)(`
|
|
11
12
|
query GetRequests($pageSize: Int, $showPendingOnly: Boolean!) {
|
|
@@ -58,6 +59,7 @@ const GET_REQUESTS = (0, graphql_1.graphql)(`
|
|
|
58
59
|
}`);
|
|
59
60
|
class ListRequests extends core_1.Command {
|
|
60
61
|
async run() {
|
|
62
|
+
(0, utils_1.restrictToDev)(); //TODO: Remove after development is complete
|
|
61
63
|
(0, cmd_1.setMostRecentCommand)(this);
|
|
62
64
|
const client = await (0, apollo_1.getClient)(this, true);
|
|
63
65
|
let pageSize = 10;
|
|
@@ -86,6 +88,7 @@ class ListRequests extends core_1.Command {
|
|
|
86
88
|
}
|
|
87
89
|
}
|
|
88
90
|
}
|
|
91
|
+
ListRequests.hidden = true;
|
|
89
92
|
ListRequests.description = "Lists your n recent outgoing access requests";
|
|
90
93
|
ListRequests.examples = [
|
|
91
94
|
"opal request list --n 5",
|
|
@@ -93,7 +96,7 @@ ListRequests.examples = [
|
|
|
93
96
|
"opal request list --n 5 --verbose",
|
|
94
97
|
"opal request list --n 5 --pending --verbose",
|
|
95
98
|
];
|
|
96
|
-
|
|
99
|
+
// static aliases = ["request:ls"]; // uncomment when ready for release
|
|
97
100
|
ListRequests.flags = {
|
|
98
101
|
help: flags_1.SHARED_FLAGS.help,
|
|
99
102
|
n: core_1.Flags.integer({
|
package/lib/lib/apollo.js
CHANGED
|
@@ -155,7 +155,7 @@ const initClient = async (command, fetchAccessToken = true) => {
|
|
|
155
155
|
return response;
|
|
156
156
|
});
|
|
157
157
|
});
|
|
158
|
-
const errorLink = (0, error_1.onError)(({ networkError, operation
|
|
158
|
+
const errorLink = (0, error_1.onError)(({ networkError, operation }) => {
|
|
159
159
|
var _a;
|
|
160
160
|
// There's a few GQL operations where we don't want to use this error handler:
|
|
161
161
|
const customErrorOperations = [
|
|
@@ -186,7 +186,7 @@ const initClient = async (command, fetchAccessToken = true) => {
|
|
|
186
186
|
case 401: {
|
|
187
187
|
command.log("Your session is invalid or expired. Authenticating now...\n");
|
|
188
188
|
const loginCommand = new login_1.default([], command.config);
|
|
189
|
-
|
|
189
|
+
loginCommand.run().then(() => {
|
|
190
190
|
if (cmd_1.mostRecentCommandTime && cmd_1.mostRecentCommand) {
|
|
191
191
|
const lastCommandReexecutionDuration = moment.duration(2, "minutes");
|
|
192
192
|
const lastCommandReexecutionDurationHasElapsed = cmd_1.mostRecentCommandTime.add(lastCommandReexecutionDuration) >
|
|
@@ -195,7 +195,8 @@ const initClient = async (command, fetchAccessToken = true) => {
|
|
|
195
195
|
cmd_1.mostRecentCommand.run();
|
|
196
196
|
}
|
|
197
197
|
}
|
|
198
|
-
})
|
|
198
|
+
});
|
|
199
|
+
break;
|
|
199
200
|
}
|
|
200
201
|
default:
|
|
201
202
|
return (0, exports.handleError)(command, `Received status code ${networkError.statusCode} from server${errorMessage ? ` with message "${errorMessage}"` : ""}`);
|
|
@@ -5,13 +5,12 @@ interface OpalCredentials {
|
|
|
5
5
|
clientIDCandidate?: string;
|
|
6
6
|
secret?: string;
|
|
7
7
|
secretType?: SecretType;
|
|
8
|
-
organizationName?: string;
|
|
9
8
|
}
|
|
10
9
|
export declare enum SecretType {
|
|
11
10
|
Cookie = "COOKIE",
|
|
12
11
|
ApiToken = "API_TOKEN"
|
|
13
12
|
}
|
|
14
|
-
export declare const setOpalCredentials: (command: Command, email: string | undefined, organizationID: string, clientIDCandidate: string | undefined | null, secret: string, secretType: SecretType
|
|
13
|
+
export declare const setOpalCredentials: (command: Command, email: string | undefined, organizationID: string, clientIDCandidate: string | undefined | null, secret: string, secretType: SecretType) => Promise<void>;
|
|
15
14
|
export declare const getOpalCredentials: (command: Command, includeAuthSecret?: boolean) => Promise<OpalCredentials>;
|
|
16
15
|
export declare const removeOpalCredentials: (command: Command) => Promise<void>;
|
|
17
16
|
export {};
|
|
@@ -9,14 +9,13 @@ var SecretType;
|
|
|
9
9
|
SecretType["Cookie"] = "COOKIE";
|
|
10
10
|
SecretType["ApiToken"] = "API_TOKEN";
|
|
11
11
|
})(SecretType || (exports.SecretType = SecretType = {}));
|
|
12
|
-
const setOpalCredentials = async (command, email, organizationID, clientIDCandidate, secret, secretType
|
|
12
|
+
const setOpalCredentials = async (command, email, organizationID, clientIDCandidate, secret, secretType) => {
|
|
13
13
|
const givenEmail = email || "email-unset";
|
|
14
14
|
const configData = (0, config_1.getOrCreateConfigData)(command.config.configDir);
|
|
15
15
|
configData.creds = {
|
|
16
16
|
clientIDCandidate,
|
|
17
17
|
email,
|
|
18
18
|
organizationID,
|
|
19
|
-
organizationName,
|
|
20
19
|
secretType,
|
|
21
20
|
};
|
|
22
21
|
(0, config_1.writeConfigData)(command.config.configDir, configData);
|
package/lib/lib/requests.d.ts
CHANGED
|
@@ -19,7 +19,6 @@ type RoleNode = {
|
|
|
19
19
|
roleName: string;
|
|
20
20
|
};
|
|
21
21
|
export type RequestMap = Record<string, AppNode>;
|
|
22
|
-
export declare const DISPLAY_LABELS: Partial<Record<EntityType, string>>;
|
|
23
22
|
type DurationOption = {
|
|
24
23
|
durationInMinutes: number;
|
|
25
24
|
label: string;
|
|
@@ -46,9 +45,8 @@ export declare function doneSelectingAssets(): Promise<boolean>;
|
|
|
46
45
|
export declare function setRequestDefaults(cmd: Command, client: ApolloClient<NormalizedCacheObject>, metadata: RequestMetadata): Promise<void>;
|
|
47
46
|
export declare function promptForReason(metadata: RequestMetadata): Promise<void>;
|
|
48
47
|
export declare function promptForExpiration(metadata: RequestMetadata): Promise<void>;
|
|
49
|
-
export declare function promptRequestSubmission(cmd: Command, metadata: RequestMetadata): Promise<
|
|
48
|
+
export declare function promptRequestSubmission(cmd: Command, metadata: RequestMetadata): Promise<void>;
|
|
50
49
|
export declare function submitFinalRequest(cmd: Command, client: ApolloClient<NormalizedCacheObject>, metadata: RequestMetadata): Promise<void>;
|
|
51
|
-
export declare function getRequestLink(cmd: Command, id: string): string;
|
|
52
50
|
export declare function bypassRequestSelection(cmd: Command, client: ApolloClient<NormalizedCacheObject>, flagValue: string[], metadata: RequestMetadata): Promise<void>;
|
|
53
51
|
export declare function bypassDuration(cmd: Command, duration: number, metadata: RequestMetadata): void;
|
|
54
52
|
export {};
|
package/lib/lib/requests.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.DISPLAY_LABELS = void 0;
|
|
4
3
|
exports.initEmptyRequestMetadata = initEmptyRequestMetadata;
|
|
5
4
|
exports.selectRequestableItems = selectRequestableItems;
|
|
6
5
|
exports.doneSelectingAssets = doneSelectingAssets;
|
|
@@ -9,30 +8,25 @@ exports.promptForReason = promptForReason;
|
|
|
9
8
|
exports.promptForExpiration = promptForExpiration;
|
|
10
9
|
exports.promptRequestSubmission = promptRequestSubmission;
|
|
11
10
|
exports.submitFinalRequest = submitFinalRequest;
|
|
12
|
-
exports.getRequestLink = getRequestLink;
|
|
13
11
|
exports.bypassRequestSelection = bypassRequestSelection;
|
|
14
12
|
exports.bypassDuration = bypassDuration;
|
|
15
13
|
const chalk_1 = require("chalk");
|
|
14
|
+
const inquirer = require("inquirer");
|
|
16
15
|
const graphql_1 = require("../graphql");
|
|
17
16
|
const graphql_2 = require("../graphql/graphql");
|
|
18
17
|
const displays_1 = require("../utils/displays");
|
|
19
18
|
const config_1 = require("./config");
|
|
20
19
|
const { AutoComplete, Select, prompt, Form } = require("enquirer");
|
|
21
20
|
function entityTypeFromString(str) {
|
|
22
|
-
|
|
23
|
-
if (capStr === "RESOURCE") {
|
|
21
|
+
if (str === "Resource") {
|
|
24
22
|
return graphql_2.EntityType.Resource;
|
|
25
23
|
}
|
|
26
|
-
if (
|
|
24
|
+
if (str === "Group") {
|
|
27
25
|
return graphql_2.EntityType.Group;
|
|
28
26
|
}
|
|
29
27
|
// if type unknown, default to resource
|
|
30
28
|
return graphql_2.EntityType.Resource;
|
|
31
29
|
}
|
|
32
|
-
exports.DISPLAY_LABELS = {
|
|
33
|
-
[graphql_2.EntityType.Resource]: "Resource",
|
|
34
|
-
[graphql_2.EntityType.Group]: "Group",
|
|
35
|
-
};
|
|
36
30
|
function initEmptyRequestMetadata() {
|
|
37
31
|
// Initialize with empty defaults
|
|
38
32
|
const requestDefaults = {
|
|
@@ -185,7 +179,7 @@ async function queryRequestableAssets(cmd, client, appId, input) {
|
|
|
185
179
|
value: {
|
|
186
180
|
name: name || "",
|
|
187
181
|
id: id || "",
|
|
188
|
-
type:
|
|
182
|
+
type: ((_g = item.resource) === null || _g === void 0 ? void 0 : _g.__typename) || ((_h = item.group) === null || _h === void 0 ? void 0 : _h.__typename) || "",
|
|
189
183
|
},
|
|
190
184
|
};
|
|
191
185
|
});
|
|
@@ -244,7 +238,7 @@ async function queryAssetRoles(cmd, client, assetType, assetId) {
|
|
|
244
238
|
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
245
239
|
try {
|
|
246
240
|
switch (assetType) {
|
|
247
|
-
case
|
|
241
|
+
case "Resource": {
|
|
248
242
|
const resp = await client.query({
|
|
249
243
|
query: RESOURCE_ROLES_QUERY,
|
|
250
244
|
variables: {
|
|
@@ -273,7 +267,7 @@ async function queryAssetRoles(cmd, client, assetType, assetId) {
|
|
|
273
267
|
}
|
|
274
268
|
return;
|
|
275
269
|
}
|
|
276
|
-
case
|
|
270
|
+
case "Group": {
|
|
277
271
|
const resp = await client.query({
|
|
278
272
|
query: GROUP_ROLES_QUERY,
|
|
279
273
|
variables: {
|
|
@@ -629,8 +623,8 @@ async function queryAssociatedItems(cmd, client, id, input) {
|
|
|
629
623
|
}
|
|
630
624
|
}
|
|
631
625
|
// Helper functions
|
|
632
|
-
const selectInstructions = chalk_1.default.dim("
|
|
633
|
-
const multiSelectInstructions = chalk_1.default.dim("
|
|
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");
|
|
634
628
|
async function selectRequestableItems(cmd, client, requestMap) {
|
|
635
629
|
const initial = (await queryRequestableApps(cmd, client, "")) || [];
|
|
636
630
|
const appPrompt = new AutoComplete({
|
|
@@ -675,7 +669,7 @@ async function chooseOktaAzureRoles(cmd, client, app, requestMap) {
|
|
|
675
669
|
},
|
|
676
670
|
validate: (answer) => {
|
|
677
671
|
if (answer.length !== 1) {
|
|
678
|
-
return "
|
|
672
|
+
return "You must select only one item.";
|
|
679
673
|
}
|
|
680
674
|
return true;
|
|
681
675
|
},
|
|
@@ -703,7 +697,7 @@ function appRolesFromEdge(edge) {
|
|
|
703
697
|
value: {
|
|
704
698
|
id: edge.node.id + accessLevel.accessLevelRemoteId,
|
|
705
699
|
name: accessLevel.accessLevelName,
|
|
706
|
-
type:
|
|
700
|
+
type: graphql_2.EntityType.Resource,
|
|
707
701
|
toString: () => accessLevel.accessLevelName,
|
|
708
702
|
},
|
|
709
703
|
}));
|
|
@@ -714,7 +708,7 @@ function appRolesFromEdge(edge) {
|
|
|
714
708
|
value: {
|
|
715
709
|
id: edge.node.id,
|
|
716
710
|
name: (_b = edge.alias) !== null && _b !== void 0 ? _b : edge.node.name,
|
|
717
|
-
type:
|
|
711
|
+
type: graphql_2.EntityType.Resource,
|
|
718
712
|
toString: () => { var _a; return (_a = edge.alias) !== null && _a !== void 0 ? _a : edge.node.name; },
|
|
719
713
|
},
|
|
720
714
|
},
|
|
@@ -723,11 +717,11 @@ function appRolesFromEdge(edge) {
|
|
|
723
717
|
case "Group":
|
|
724
718
|
return [
|
|
725
719
|
{
|
|
726
|
-
message:
|
|
720
|
+
message: (_c = edge.alias) !== null && _c !== void 0 ? _c : edge.node.name,
|
|
727
721
|
value: {
|
|
728
722
|
id: edge.node.id,
|
|
729
723
|
name: (_d = edge.alias) !== null && _d !== void 0 ? _d : edge.node.name,
|
|
730
|
-
type:
|
|
724
|
+
type: graphql_2.EntityType.Group,
|
|
731
725
|
toString: () => { var _a; return (_a = edge.alias) !== null && _a !== void 0 ? _a : edge.node.name; },
|
|
732
726
|
},
|
|
733
727
|
},
|
|
@@ -919,7 +913,6 @@ async function promptForExpiration(metadata) {
|
|
|
919
913
|
const expirationSelect = new AutoComplete({
|
|
920
914
|
name: "expiration",
|
|
921
915
|
message: "When should access expire?",
|
|
922
|
-
hint: "Type to filter",
|
|
923
916
|
type: "list",
|
|
924
917
|
choices: durations,
|
|
925
918
|
pageSize: 15,
|
|
@@ -1007,13 +1000,26 @@ async function promptRequestSubmission(cmd, metadata) {
|
|
|
1007
1000
|
(0, displays_1.displayFinalRequestSummary)(cmd, metadata);
|
|
1008
1001
|
const submitMessage = "✅ Yes, submit request";
|
|
1009
1002
|
const cancelMessage = "❌ No, cancel request";
|
|
1010
|
-
const
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1003
|
+
const { submit } = await inquirer.prompt([
|
|
1004
|
+
{
|
|
1005
|
+
name: "submit",
|
|
1006
|
+
message: "Submit request?",
|
|
1007
|
+
type: "list",
|
|
1008
|
+
choices: [submitMessage, cancelMessage],
|
|
1009
|
+
},
|
|
1010
|
+
]);
|
|
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
|
+
}
|
|
1022
|
+
}
|
|
1017
1023
|
}
|
|
1018
1024
|
async function submitFinalRequest(cmd, client, metadata) {
|
|
1019
1025
|
var _a, _b, _c, _d;
|
|
@@ -1059,29 +1065,24 @@ async function submitFinalRequest(cmd, client, metadata) {
|
|
|
1059
1065
|
}
|
|
1060
1066
|
const resp = await createRequest(cmd, client, requestedResources, requestedGroups, metadata.reason, metadata.durationInMinutes);
|
|
1061
1067
|
// Build link to request
|
|
1068
|
+
const configData = (0, config_1.getOrCreateConfigData)(cmd.config.configDir);
|
|
1062
1069
|
if (resp === null || resp === void 0 ? void 0 : resp.id) {
|
|
1063
1070
|
cmd.log("\n🎉 Your Access Request has been submitted!\n");
|
|
1064
1071
|
cmd.log(`${chalk_1.default.bold("ID: ")} ${chalk_1.default.cyan(resp === null || resp === void 0 ? void 0 : resp.id)}`);
|
|
1065
1072
|
if (resp === null || resp === void 0 ? void 0 : resp.status) {
|
|
1066
1073
|
cmd.log((0, displays_1.getStyledStatus)(resp === null || resp === void 0 ? void 0 : resp.status));
|
|
1067
1074
|
}
|
|
1068
|
-
const requestLink =
|
|
1075
|
+
const requestLink = `${configData[config_1.urlKey]}/requests/sent/${resp === null || resp === void 0 ? void 0 : resp.id}`;
|
|
1069
1076
|
cmd.log(`${chalk_1.default.bold("Link:")} ${chalk_1.default.underline(requestLink)}\n`);
|
|
1070
1077
|
}
|
|
1071
1078
|
return;
|
|
1072
1079
|
}
|
|
1073
|
-
function getRequestLink(cmd, id) {
|
|
1074
|
-
const configData = (0, config_1.getOrCreateConfigData)(cmd.config.configDir);
|
|
1075
|
-
return `${configData[config_1.urlKey]}/requests/sent/${id}`;
|
|
1076
|
-
}
|
|
1077
1080
|
async function bypassRequestSelection(cmd, client, flagValue, metadata) {
|
|
1078
|
-
var _a, _b;
|
|
1081
|
+
var _a, _b, _c, _d;
|
|
1079
1082
|
try {
|
|
1080
1083
|
// Query Catalog Item endpoint to identify what the id belongs to (resource or group)
|
|
1081
|
-
for (const
|
|
1082
|
-
const
|
|
1083
|
-
const assetId = val.substring(0, delimiterIndex);
|
|
1084
|
-
const roleName = val.substring(delimiterIndex + 1);
|
|
1084
|
+
for (const id of flagValue) {
|
|
1085
|
+
const [assetId, roleName] = id.split(":");
|
|
1085
1086
|
const resp = await client.query({
|
|
1086
1087
|
query: CATALOG_ITEM,
|
|
1087
1088
|
variables: {
|
|
@@ -1090,30 +1091,28 @@ async function bypassRequestSelection(cmd, client, flagValue, metadata) {
|
|
|
1090
1091
|
fetchPolicy: "network-only", // to avoid caching
|
|
1091
1092
|
});
|
|
1092
1093
|
switch (resp.data.catalogItem.__typename) {
|
|
1093
|
-
case "Group":
|
|
1094
1094
|
case "Resource": {
|
|
1095
|
-
const
|
|
1096
|
-
const
|
|
1097
|
-
const requestableRoles = (item.accessLevels || [])
|
|
1095
|
+
const resourceName = resp.data.catalogItem.displayName;
|
|
1096
|
+
const requestableRoles = (resp.data.catalogItem.accessLevels || [])
|
|
1098
1097
|
// TODO: Support okta azure apps ?.filter((role) => role.accessLevelName !== "") // This assumes length == 1
|
|
1099
1098
|
.map((role) => ({
|
|
1100
1099
|
id: role.accessLevelRemoteId,
|
|
1101
1100
|
name: role.accessLevelName,
|
|
1102
1101
|
}));
|
|
1103
|
-
const appId = ((_a =
|
|
1102
|
+
const appId = ((_a = resp.data.catalogItem.connection) === null || _a === void 0 ? void 0 : _a.id) || "";
|
|
1104
1103
|
if (!(appId in metadata.requestMap)) {
|
|
1105
1104
|
metadata.requestMap[appId] = {
|
|
1106
|
-
appName: ((_b =
|
|
1105
|
+
appName: ((_b = resp.data.catalogItem.connection) === null || _b === void 0 ? void 0 : _b.displayName) || "",
|
|
1107
1106
|
appId: appId,
|
|
1108
1107
|
assets: {},
|
|
1109
1108
|
};
|
|
1110
1109
|
}
|
|
1111
|
-
const assetEntry = metadata.requestMap[appId].assets[
|
|
1110
|
+
const assetEntry = metadata.requestMap[appId].assets[id];
|
|
1112
1111
|
if (!assetEntry) {
|
|
1113
1112
|
metadata.requestMap[appId].assets[assetId] = {
|
|
1114
1113
|
assetId: assetId,
|
|
1115
|
-
assetName:
|
|
1116
|
-
type:
|
|
1114
|
+
assetName: resourceName,
|
|
1115
|
+
type: graphql_2.EntityType.Resource,
|
|
1117
1116
|
roles: {},
|
|
1118
1117
|
};
|
|
1119
1118
|
}
|
|
@@ -1130,13 +1129,54 @@ async function bypassRequestSelection(cmd, client, flagValue, metadata) {
|
|
|
1130
1129
|
};
|
|
1131
1130
|
}
|
|
1132
1131
|
else {
|
|
1133
|
-
cmd.error(`Access level specified does not match one of ${
|
|
1132
|
+
cmd.error(`Access level specified does not match one of ${resourceName}'s defined access levels:${requestableRoles.map((role) => role.name)}`);
|
|
1133
|
+
}
|
|
1134
|
+
}
|
|
1135
|
+
break;
|
|
1136
|
+
}
|
|
1137
|
+
case "Group": {
|
|
1138
|
+
const groupName = resp.data.catalogItem.name;
|
|
1139
|
+
const roles = (resp.data.catalogItem.accessLevels || []).map((role) => ({
|
|
1140
|
+
id: role.accessLevelRemoteId,
|
|
1141
|
+
name: role.accessLevelName,
|
|
1142
|
+
}));
|
|
1143
|
+
if (roles.length > 0 &&
|
|
1144
|
+
!(roles.length === 1 && roles[0].name === "")) {
|
|
1145
|
+
cmd.log(`Roles not implemented yet for group ${groupName}. Skipping roles selection.`); //TODO: Implement group roles support
|
|
1146
|
+
continue;
|
|
1147
|
+
}
|
|
1148
|
+
const appId = ((_c = resp.data.catalogItem.connection) === null || _c === void 0 ? void 0 : _c.id) || "";
|
|
1149
|
+
if (!(appId in metadata.requestMap)) {
|
|
1150
|
+
metadata.requestMap[appId] = {
|
|
1151
|
+
appName: ((_d = resp.data.catalogItem.connection) === null || _d === void 0 ? void 0 : _d.displayName) || "",
|
|
1152
|
+
appId: appId,
|
|
1153
|
+
assets: {},
|
|
1154
|
+
};
|
|
1155
|
+
}
|
|
1156
|
+
const assetEntry = metadata.requestMap[appId].assets[id];
|
|
1157
|
+
if (!assetEntry) {
|
|
1158
|
+
metadata.requestMap[appId].assets[id] = {
|
|
1159
|
+
assetId: id,
|
|
1160
|
+
assetName: groupName,
|
|
1161
|
+
type: graphql_2.EntityType.Group,
|
|
1162
|
+
roles: {},
|
|
1163
|
+
};
|
|
1164
|
+
}
|
|
1165
|
+
if (roles) {
|
|
1166
|
+
if (!metadata.requestMap[appId].assets[id].roles) {
|
|
1167
|
+
metadata.requestMap[appId].assets[id].roles = {};
|
|
1168
|
+
}
|
|
1169
|
+
for (const role of roles) {
|
|
1170
|
+
metadata.requestMap[appId].assets[id].roles[role.id] = {
|
|
1171
|
+
roleId: role.id,
|
|
1172
|
+
roleName: role.name,
|
|
1173
|
+
};
|
|
1134
1174
|
}
|
|
1135
1175
|
}
|
|
1136
1176
|
break;
|
|
1137
1177
|
}
|
|
1138
1178
|
default:
|
|
1139
|
-
cmd.error("
|
|
1179
|
+
cmd.error("Invad asset id was passed in using the --id flag.");
|
|
1140
1180
|
}
|
|
1141
1181
|
}
|
|
1142
1182
|
}
|
package/lib/utils/displays.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { ApolloQueryResult } from "@apollo/client";
|
|
2
2
|
import type { Command } from "@oclif/core/lib/command";
|
|
3
3
|
import type { GetRequestQuery, GetRequestsQuery } from "../graphql/graphql";
|
|
4
|
-
import {
|
|
4
|
+
import type { RequestMap, RequestMetadata } from "../lib/requests";
|
|
5
5
|
export declare function headerMessage(cmd: Command): void;
|
|
6
6
|
export declare function treeifyRequestMap(cmd: Command, requestMap: RequestMap): void;
|
|
7
7
|
export declare function displayFinalRequestSummary(cmd: Command, metadata: RequestMetadata): void;
|
package/lib/utils/displays.js
CHANGED
|
@@ -7,8 +7,6 @@ exports.getStyledStatus = getStyledStatus;
|
|
|
7
7
|
exports.displayRequestDetails = displayRequestDetails;
|
|
8
8
|
exports.displayRequestListTable = displayRequestListTable;
|
|
9
9
|
const chalk_1 = require("chalk");
|
|
10
|
-
const terminal_link_1 = require("terminal-link");
|
|
11
|
-
const requests_1 = require("../lib/requests");
|
|
12
10
|
const Table = require("cli-table3");
|
|
13
11
|
const treeify = require("object-treeify").default;
|
|
14
12
|
function headerMessage(cmd) {
|
|
@@ -32,7 +30,7 @@ function treeifyRequestMap(cmd, requestMap) {
|
|
|
32
30
|
for (const [_assetId, assetNode] of Object.entries(appNode.assets)) {
|
|
33
31
|
// If okta/azure asset with no role, change asset name
|
|
34
32
|
const assetName = assetNode.assetName || "No Role (Direct access)";
|
|
35
|
-
const assetKey = `${assetName} ${chalk_1.default.dim(`[${
|
|
33
|
+
const assetKey = `${assetName} ${chalk_1.default.dim(`[${assetNode.type}]`)}`;
|
|
36
34
|
if (assetNode.roles !== undefined) {
|
|
37
35
|
assetsTree[assetKey] = {};
|
|
38
36
|
for (const [_roleId, roleNode] of Object.entries(assetNode.roles)) {
|
|
@@ -173,12 +171,8 @@ function displayRequestListTable(cmd, requestResp) {
|
|
|
173
171
|
...requestedResources,
|
|
174
172
|
...requestedGroups,
|
|
175
173
|
].join(", ");
|
|
176
|
-
const requestLink = (0, requests_1.getRequestLink)(cmd, request.id);
|
|
177
|
-
const clickableId = (0, terminal_link_1.default)(request.id, requestLink, {
|
|
178
|
-
fallback: false,
|
|
179
|
-
});
|
|
180
174
|
table.push([
|
|
181
|
-
|
|
175
|
+
request.id,
|
|
182
176
|
status,
|
|
183
177
|
targetUser,
|
|
184
178
|
formattedDuration,
|
package/oclif.manifest.json
CHANGED
|
@@ -316,34 +316,6 @@
|
|
|
316
316
|
"set-url.js"
|
|
317
317
|
]
|
|
318
318
|
},
|
|
319
|
-
"whoami": {
|
|
320
|
-
"aliases": [],
|
|
321
|
-
"args": {},
|
|
322
|
-
"description": "Describes current url set, organization name, and logged in user if applicable.",
|
|
323
|
-
"flags": {
|
|
324
|
-
"help": {
|
|
325
|
-
"char": "h",
|
|
326
|
-
"description": "Show CLI help.",
|
|
327
|
-
"name": "help",
|
|
328
|
-
"allowNo": false,
|
|
329
|
-
"type": "boolean"
|
|
330
|
-
}
|
|
331
|
-
},
|
|
332
|
-
"hasDynamicHelp": false,
|
|
333
|
-
"hiddenAliases": [],
|
|
334
|
-
"id": "whoami",
|
|
335
|
-
"pluginAlias": "opal-security",
|
|
336
|
-
"pluginName": "opal-security",
|
|
337
|
-
"pluginType": "core",
|
|
338
|
-
"strict": true,
|
|
339
|
-
"enableJsonFlag": false,
|
|
340
|
-
"isESM": false,
|
|
341
|
-
"relativePath": [
|
|
342
|
-
"lib",
|
|
343
|
-
"commands",
|
|
344
|
-
"whoami.js"
|
|
345
|
-
]
|
|
346
|
-
},
|
|
347
319
|
"aws:identity": {
|
|
348
320
|
"aliases": [],
|
|
349
321
|
"args": {},
|
|
@@ -634,10 +606,10 @@
|
|
|
634
606
|
"allowNo": false,
|
|
635
607
|
"type": "boolean"
|
|
636
608
|
},
|
|
637
|
-
"
|
|
638
|
-
"char": "
|
|
639
|
-
"description": "The
|
|
640
|
-
"name": "
|
|
609
|
+
"id": {
|
|
610
|
+
"char": "i",
|
|
611
|
+
"description": "The id of the asset (resource, group) to request access to. Append a role ID using a colon if needed, e.g. `--id 123:456`. \n If not provided, an interactive selection flow will be available to select assets to request.",
|
|
612
|
+
"name": "id",
|
|
641
613
|
"hasDynamicHelp": false,
|
|
642
614
|
"multiple": true,
|
|
643
615
|
"type": "option"
|
|
@@ -660,6 +632,7 @@
|
|
|
660
632
|
}
|
|
661
633
|
},
|
|
662
634
|
"hasDynamicHelp": false,
|
|
635
|
+
"hidden": true,
|
|
663
636
|
"hiddenAliases": [],
|
|
664
637
|
"id": "request:create",
|
|
665
638
|
"pluginAlias": "opal-security",
|
|
@@ -708,6 +681,7 @@
|
|
|
708
681
|
}
|
|
709
682
|
},
|
|
710
683
|
"hasDynamicHelp": false,
|
|
684
|
+
"hidden": true,
|
|
711
685
|
"hiddenAliases": [],
|
|
712
686
|
"id": "request:get",
|
|
713
687
|
"pluginAlias": "opal-security",
|
|
@@ -724,9 +698,7 @@
|
|
|
724
698
|
]
|
|
725
699
|
},
|
|
726
700
|
"request:list": {
|
|
727
|
-
"aliases": [
|
|
728
|
-
"request:ls"
|
|
729
|
-
],
|
|
701
|
+
"aliases": [],
|
|
730
702
|
"args": {},
|
|
731
703
|
"description": "Lists your n recent outgoing access requests",
|
|
732
704
|
"examples": [
|
|
@@ -768,6 +740,7 @@
|
|
|
768
740
|
}
|
|
769
741
|
},
|
|
770
742
|
"hasDynamicHelp": false,
|
|
743
|
+
"hidden": true,
|
|
771
744
|
"hiddenAliases": [],
|
|
772
745
|
"id": "request:list",
|
|
773
746
|
"pluginAlias": "opal-security",
|
|
@@ -1030,5 +1003,5 @@
|
|
|
1030
1003
|
]
|
|
1031
1004
|
}
|
|
1032
1005
|
},
|
|
1033
|
-
"version": "3.1.1-beta.
|
|
1006
|
+
"version": "3.1.1-beta.03364ed"
|
|
1034
1007
|
}
|
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.03364ed",
|
|
5
5
|
"author": "Stephen Cobbe",
|
|
6
6
|
"bin": {
|
|
7
7
|
"opal": "./bin/run"
|
|
@@ -29,7 +29,6 @@
|
|
|
29
29
|
"openid-client": "^5.6.5",
|
|
30
30
|
"prettyjson": "^1.2.1",
|
|
31
31
|
"semver": "^7.5.4",
|
|
32
|
-
"terminal-link": "^4.0.0",
|
|
33
32
|
"tslib": "^2.8.1"
|
|
34
33
|
},
|
|
35
34
|
"devDependencies": {
|
|
@@ -64,7 +63,9 @@
|
|
|
64
63
|
"/scripts"
|
|
65
64
|
],
|
|
66
65
|
"homepage": "https://github.com/opalsecurity/opal-cli/",
|
|
67
|
-
"keywords": [
|
|
66
|
+
"keywords": [
|
|
67
|
+
"oclif"
|
|
68
|
+
],
|
|
68
69
|
"license": "MIT",
|
|
69
70
|
"main": "lib/index.js",
|
|
70
71
|
"oclif": {
|
|
@@ -90,7 +91,7 @@
|
|
|
90
91
|
"prepack": "npm run build && oclif manifest && oclif readme",
|
|
91
92
|
"test": "vitest",
|
|
92
93
|
"coverage": "vitest run --coverage",
|
|
93
|
-
"version": "oclif readme && git add README.md
|
|
94
|
+
"version": "oclif readme && git add README.md",
|
|
94
95
|
"posttest": "biome check",
|
|
95
96
|
"biome-ci": "biome ci --reporter=github",
|
|
96
97
|
"gql-codegen": "graphql-codegen",
|
package/lib/commands/whoami.d.ts
DELETED
package/lib/commands/whoami.js
DELETED
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
const core_1 = require("@oclif/core");
|
|
4
|
-
const config_1 = require("../lib/config");
|
|
5
|
-
const credentials_1 = require("../lib/credentials");
|
|
6
|
-
const flags_1 = require("../lib/flags");
|
|
7
|
-
class WhoAmI extends core_1.Command {
|
|
8
|
-
async run() {
|
|
9
|
-
const opalCreds = await (0, credentials_1.getOpalCredentials)(this, false);
|
|
10
|
-
const organizationName = opalCreds === null || opalCreds === void 0 ? void 0 : opalCreds.organizationName;
|
|
11
|
-
const email = opalCreds === null || opalCreds === void 0 ? void 0 : opalCreds.email;
|
|
12
|
-
const configData = (0, config_1.getOrCreateConfigData)(this.config.configDir);
|
|
13
|
-
const url = configData[config_1.urlKey];
|
|
14
|
-
if (email) {
|
|
15
|
-
this.log(`User: ${email}`);
|
|
16
|
-
}
|
|
17
|
-
if (organizationName) {
|
|
18
|
-
if (organizationName === "unset-org-id") {
|
|
19
|
-
this.log("Authenticated with Opal API Token.");
|
|
20
|
-
}
|
|
21
|
-
else {
|
|
22
|
-
this.log(`Organization: ${organizationName}`);
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
if (url) {
|
|
26
|
-
this.log(`Server: ${url}`);
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
WhoAmI.description = "Describes current url set, organization name, and logged in user if applicable.";
|
|
31
|
-
WhoAmI.flags = {
|
|
32
|
-
help: flags_1.SHARED_FLAGS.help,
|
|
33
|
-
};
|
|
34
|
-
exports.default = WhoAmI;
|