opal-security 3.1.1-beta.68e6f48 ā 3.1.1-beta.6b4868b
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.d.ts +1 -0
- package/lib/commands/request/create.js +15 -4
- package/lib/lib/requests.d.ts +5 -2
- package/lib/lib/requests.js +128 -61
- package/lib/utils/displays.js +4 -2
- package/oclif.manifest.json +9 -1
- package/package.json +1 -1
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.6b4868b 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.6b4868b/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.6b4868b/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.6b4868b/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.6b4868b/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.6b4868b/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.6b4868b/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.6b4868b/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.6b4868b/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.6b4868b/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.6b4868b/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.6b4868b/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.6b4868b/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.6b4868b/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.6b4868b/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.6b4868b/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.6b4868b/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.6b4868b/src/commands/ssh/start.ts)_
|
|
523
523
|
|
|
524
524
|
## `opal version`
|
|
525
525
|
|
|
@@ -6,6 +6,7 @@ export default class RequestCreate extends Command {
|
|
|
6
6
|
help: import("@oclif/core/lib/interfaces").BooleanFlag<void>;
|
|
7
7
|
id: import("@oclif/core/lib/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
8
8
|
reason: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
9
|
+
duration: import("@oclif/core/lib/interfaces").OptionFlag<number | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
9
10
|
};
|
|
10
11
|
run(): Promise<void>;
|
|
11
12
|
}
|
|
@@ -15,7 +15,7 @@ class RequestCreate extends core_1.Command {
|
|
|
15
15
|
const metadata = (0, requests_1.initEmptyRequestMetadata)();
|
|
16
16
|
if (flags.id) {
|
|
17
17
|
// if IDs are provided, bypass the interactive selection process
|
|
18
|
-
(0, requests_1.bypassRequestSelection)(this, client, flags.id, metadata);
|
|
18
|
+
await (0, requests_1.bypassRequestSelection)(this, client, flags.id, metadata);
|
|
19
19
|
}
|
|
20
20
|
else {
|
|
21
21
|
(0, displays_1.headerMessage)(this);
|
|
@@ -40,10 +40,17 @@ class RequestCreate extends core_1.Command {
|
|
|
40
40
|
await (0, requests_1.promptForReason)(metadata);
|
|
41
41
|
}
|
|
42
42
|
// Step 5: Prompt for expiration
|
|
43
|
-
|
|
43
|
+
if (flags.duration) {
|
|
44
|
+
(0, requests_1.bypassDuration)(this, flags.duration, metadata);
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
await (0, requests_1.promptForExpiration)(metadata);
|
|
48
|
+
}
|
|
44
49
|
// Step 6: Display final summary of request
|
|
45
|
-
(
|
|
46
|
-
|
|
50
|
+
if (!(flags.id && flags.reason && flags.duration)) {
|
|
51
|
+
await (0, requests_1.promptRequestSubmission)(this, metadata);
|
|
52
|
+
}
|
|
53
|
+
// Step 7: Prompt for final submission
|
|
47
54
|
await (0, requests_1.submitFinalRequest)(this, client, metadata);
|
|
48
55
|
}
|
|
49
56
|
}
|
|
@@ -61,5 +68,9 @@ RequestCreate.flags = {
|
|
|
61
68
|
char: "r",
|
|
62
69
|
description: "The reason for the request, contained in quotes. If not provided, you will be prompted.",
|
|
63
70
|
}),
|
|
71
|
+
duration: core_1.Flags.integer({
|
|
72
|
+
char: "d",
|
|
73
|
+
description: "The duration of access for the request in minutes. If not provided, you will be prompted.",
|
|
74
|
+
}),
|
|
64
75
|
};
|
|
65
76
|
exports.default = RequestCreate;
|
package/lib/lib/requests.d.ts
CHANGED
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
import type { NormalizedCacheObject } from "@apollo/client/core";
|
|
2
2
|
import type { ApolloClient } from "@apollo/client/core/ApolloClient";
|
|
3
3
|
import type { Command } from "@oclif/core/lib/command";
|
|
4
|
+
import { type AppType, type ConnectionType, EntityType } from "../graphql/graphql";
|
|
4
5
|
type AppNode = {
|
|
5
6
|
appId: string;
|
|
6
7
|
appName: string;
|
|
7
|
-
appType?:
|
|
8
|
+
appType?: AppType | ConnectionType;
|
|
8
9
|
assets: Record<string, AssetNode>;
|
|
9
10
|
};
|
|
10
11
|
type AssetNode = {
|
|
11
12
|
assetId: string;
|
|
12
13
|
assetName: string;
|
|
13
|
-
type:
|
|
14
|
+
type: EntityType;
|
|
14
15
|
roles?: Record<string, RoleNode>;
|
|
15
16
|
};
|
|
16
17
|
type RoleNode = {
|
|
@@ -44,6 +45,8 @@ export declare function doneSelectingAssets(): Promise<boolean>;
|
|
|
44
45
|
export declare function setRequestDefaults(cmd: Command, client: ApolloClient<NormalizedCacheObject>, metadata: RequestMetadata): Promise<void>;
|
|
45
46
|
export declare function promptForReason(metadata: RequestMetadata): Promise<void>;
|
|
46
47
|
export declare function promptForExpiration(metadata: RequestMetadata): Promise<void>;
|
|
48
|
+
export declare function promptRequestSubmission(cmd: Command, metadata: RequestMetadata): Promise<void>;
|
|
47
49
|
export declare function submitFinalRequest(cmd: Command, client: ApolloClient<NormalizedCacheObject>, metadata: RequestMetadata): Promise<void>;
|
|
48
50
|
export declare function bypassRequestSelection(cmd: Command, client: ApolloClient<NormalizedCacheObject>, flagValue: string[], metadata: RequestMetadata): Promise<void>;
|
|
51
|
+
export declare function bypassDuration(cmd: Command, duration: number, metadata: RequestMetadata): void;
|
|
49
52
|
export {};
|
package/lib/lib/requests.js
CHANGED
|
@@ -6,8 +6,10 @@ exports.doneSelectingAssets = doneSelectingAssets;
|
|
|
6
6
|
exports.setRequestDefaults = setRequestDefaults;
|
|
7
7
|
exports.promptForReason = promptForReason;
|
|
8
8
|
exports.promptForExpiration = promptForExpiration;
|
|
9
|
+
exports.promptRequestSubmission = promptRequestSubmission;
|
|
9
10
|
exports.submitFinalRequest = submitFinalRequest;
|
|
10
11
|
exports.bypassRequestSelection = bypassRequestSelection;
|
|
12
|
+
exports.bypassDuration = bypassDuration;
|
|
11
13
|
const chalk_1 = require("chalk");
|
|
12
14
|
const inquirer = require("inquirer");
|
|
13
15
|
const graphql_1 = require("../graphql");
|
|
@@ -15,6 +17,16 @@ const graphql_2 = require("../graphql/graphql");
|
|
|
15
17
|
const displays_1 = require("../utils/displays");
|
|
16
18
|
const config_1 = require("./config");
|
|
17
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
|
+
}
|
|
18
30
|
function initEmptyRequestMetadata() {
|
|
19
31
|
// Initialize with empty defaults
|
|
20
32
|
const requestDefaults = {
|
|
@@ -611,11 +623,14 @@ async function queryAssociatedItems(cmd, client, id, input) {
|
|
|
611
623
|
}
|
|
612
624
|
}
|
|
613
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");
|
|
614
628
|
async function selectRequestableItems(cmd, client, requestMap) {
|
|
615
629
|
const initial = (await queryRequestableApps(cmd, client, "")) || [];
|
|
616
630
|
const appPrompt = new AutoComplete({
|
|
617
631
|
name: "App",
|
|
618
|
-
message: "Select an app
|
|
632
|
+
message: "Select an app",
|
|
633
|
+
hint: selectInstructions,
|
|
619
634
|
limit: 15,
|
|
620
635
|
choices: initial,
|
|
621
636
|
async suggest(input) {
|
|
@@ -643,6 +658,7 @@ async function chooseOktaAzureRoles(cmd, client, app, requestMap) {
|
|
|
643
658
|
const rolePrompt = new AutoComplete({
|
|
644
659
|
name: "Roles",
|
|
645
660
|
message: `Select a role for ${app.name}:`,
|
|
661
|
+
hint: multiSelectInstructions,
|
|
646
662
|
limit: 15,
|
|
647
663
|
multiple: true,
|
|
648
664
|
async choices(input) {
|
|
@@ -665,7 +681,7 @@ async function chooseOktaAzureRoles(cmd, client, app, requestMap) {
|
|
|
665
681
|
entry.assets[role.id] = {
|
|
666
682
|
assetId: role.id,
|
|
667
683
|
assetName: role.name,
|
|
668
|
-
type: role.type
|
|
684
|
+
type: entityTypeFromString(role.type),
|
|
669
685
|
roles: {},
|
|
670
686
|
};
|
|
671
687
|
}
|
|
@@ -717,6 +733,7 @@ async function chooseAssets(cmd, client, appId, requestMap) {
|
|
|
717
733
|
const assetPrompt = new AutoComplete({
|
|
718
734
|
name: "Assets",
|
|
719
735
|
message: "Select one or more assets:",
|
|
736
|
+
hint: multiSelectInstructions,
|
|
720
737
|
limit: 15,
|
|
721
738
|
multiple: true,
|
|
722
739
|
async choices(input) {
|
|
@@ -766,6 +783,7 @@ async function chooseRoles(cmd, client, appId, assetId, requestMap) {
|
|
|
766
783
|
const rolePrompt = new AutoComplete({
|
|
767
784
|
name: "Roles",
|
|
768
785
|
message: `Select one or more roles for ${assetEntry.assetName}:`,
|
|
786
|
+
hint: multiSelectInstructions,
|
|
769
787
|
limit: 15,
|
|
770
788
|
multiple: true,
|
|
771
789
|
choices: assetRoles,
|
|
@@ -856,7 +874,7 @@ async function promptForReason(metadata) {
|
|
|
856
874
|
const { reason } = await prompt([
|
|
857
875
|
{
|
|
858
876
|
name: "reason",
|
|
859
|
-
message: "
|
|
877
|
+
message: "Why do you need access?",
|
|
860
878
|
type: "input",
|
|
861
879
|
validate: (answer) => {
|
|
862
880
|
if (!metadata.requestDefaults.reasonOptional && answer.length < 1) {
|
|
@@ -978,8 +996,8 @@ async function setCustomDuration(metadata) {
|
|
|
978
996
|
label: durationLabel,
|
|
979
997
|
};
|
|
980
998
|
}
|
|
981
|
-
async function
|
|
982
|
-
|
|
999
|
+
async function promptRequestSubmission(cmd, metadata) {
|
|
1000
|
+
(0, displays_1.displayFinalRequestSummary)(cmd, metadata);
|
|
983
1001
|
const submitMessage = "ā
Yes, submit request";
|
|
984
1002
|
const cancelMessage = "ā No, cancel request";
|
|
985
1003
|
const { submit } = await inquirer.prompt([
|
|
@@ -992,58 +1010,6 @@ async function submitFinalRequest(cmd, client, metadata) {
|
|
|
992
1010
|
]);
|
|
993
1011
|
switch (submit) {
|
|
994
1012
|
case submitMessage: {
|
|
995
|
-
// Build requested assets lists for the mutation
|
|
996
|
-
const requestedResources = [];
|
|
997
|
-
const requestedGroups = [];
|
|
998
|
-
for (const appNode of Object.values(metadata.requestMap)) {
|
|
999
|
-
// This extraction is different than the one in setRequestDefaults.
|
|
1000
|
-
// Both extract the requestedResources and requestedGroups,
|
|
1001
|
-
// use different formats.
|
|
1002
|
-
for (const [assetId, assetNode] of Object.entries(appNode.assets)) {
|
|
1003
|
-
if (assetNode.roles !== undefined) {
|
|
1004
|
-
const mappedRoles = Object.entries(assetNode.roles).map(([roleId, _roleNode]) => {
|
|
1005
|
-
return roleId;
|
|
1006
|
-
});
|
|
1007
|
-
const roleIds = mappedRoles.length ? mappedRoles : [""];
|
|
1008
|
-
for (const roleId of roleIds) {
|
|
1009
|
-
switch (assetNode.type) {
|
|
1010
|
-
case graphql_2.EntityType.Resource: {
|
|
1011
|
-
requestedResources.push({
|
|
1012
|
-
resourceId: assetId,
|
|
1013
|
-
accessLevel: {
|
|
1014
|
-
accessLevelName: ((_b = (_a = assetNode.roles) === null || _a === void 0 ? void 0 : _a[roleId]) === null || _b === void 0 ? void 0 : _b.roleName) || "",
|
|
1015
|
-
accessLevelRemoteId: roleId,
|
|
1016
|
-
},
|
|
1017
|
-
});
|
|
1018
|
-
break;
|
|
1019
|
-
}
|
|
1020
|
-
case graphql_2.EntityType.Group: {
|
|
1021
|
-
requestedGroups.push({
|
|
1022
|
-
groupId: assetId,
|
|
1023
|
-
accessLevel: {
|
|
1024
|
-
accessLevelName: ((_d = (_c = assetNode.roles) === null || _c === void 0 ? void 0 : _c[roleId]) === null || _d === void 0 ? void 0 : _d.roleName) || "",
|
|
1025
|
-
accessLevelRemoteId: roleId,
|
|
1026
|
-
},
|
|
1027
|
-
});
|
|
1028
|
-
break;
|
|
1029
|
-
}
|
|
1030
|
-
}
|
|
1031
|
-
}
|
|
1032
|
-
}
|
|
1033
|
-
}
|
|
1034
|
-
}
|
|
1035
|
-
const resp = await createRequest(cmd, client, requestedResources, requestedGroups, metadata.reason, metadata.durationInMinutes);
|
|
1036
|
-
// Build link to request
|
|
1037
|
-
const configData = (0, config_1.getOrCreateConfigData)(cmd.config.configDir);
|
|
1038
|
-
if (resp === null || resp === void 0 ? void 0 : resp.id) {
|
|
1039
|
-
cmd.log("\nš Your Access Request has been submitted!\n");
|
|
1040
|
-
cmd.log(`${chalk_1.default.bold("ID: ")} ${chalk_1.default.cyan(resp === null || resp === void 0 ? void 0 : resp.id)}`);
|
|
1041
|
-
if (resp === null || resp === void 0 ? void 0 : resp.status) {
|
|
1042
|
-
cmd.log((0, displays_1.getStyledStatus)(resp === null || resp === void 0 ? void 0 : resp.status));
|
|
1043
|
-
}
|
|
1044
|
-
const requestLink = `${configData[config_1.urlKey]}/requests/sent/${resp === null || resp === void 0 ? void 0 : resp.id}`;
|
|
1045
|
-
cmd.log(`${chalk_1.default.bold("Link:")} ${chalk_1.default.underline(requestLink)}\n`);
|
|
1046
|
-
}
|
|
1047
1013
|
return;
|
|
1048
1014
|
}
|
|
1049
1015
|
case cancelMessage: {
|
|
@@ -1055,9 +1021,66 @@ async function submitFinalRequest(cmd, client, metadata) {
|
|
|
1055
1021
|
}
|
|
1056
1022
|
}
|
|
1057
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
|
+
}
|
|
1058
1080
|
async function bypassRequestSelection(cmd, client, flagValue, metadata) {
|
|
1059
|
-
var _a, _b;
|
|
1081
|
+
var _a, _b, _c, _d;
|
|
1060
1082
|
try {
|
|
1083
|
+
// Query Catalog Item endpoint to identify what the id belongs to (resource or group)
|
|
1061
1084
|
for (const id of flagValue) {
|
|
1062
1085
|
const resp = await client.query({
|
|
1063
1086
|
query: CATALOG_ITEM,
|
|
@@ -1093,11 +1116,11 @@ async function bypassRequestSelection(cmd, client, flagValue, metadata) {
|
|
|
1093
1116
|
metadata.requestMap[appId].assets[id] = {
|
|
1094
1117
|
assetId: id,
|
|
1095
1118
|
assetName: resourceName,
|
|
1096
|
-
type:
|
|
1119
|
+
type: graphql_2.EntityType.Resource,
|
|
1097
1120
|
roles: {},
|
|
1098
1121
|
};
|
|
1099
1122
|
}
|
|
1100
|
-
if (roles) {
|
|
1123
|
+
if (roles && !(roles.length === 1 && roles[0].name === "")) {
|
|
1101
1124
|
if (!metadata.requestMap[appId].assets[id].roles) {
|
|
1102
1125
|
metadata.requestMap[appId].assets[id].roles = {};
|
|
1103
1126
|
}
|
|
@@ -1111,7 +1134,44 @@ async function bypassRequestSelection(cmd, client, flagValue, metadata) {
|
|
|
1111
1134
|
break;
|
|
1112
1135
|
}
|
|
1113
1136
|
case "Group": {
|
|
1114
|
-
|
|
1137
|
+
const groupName = resp.data.catalogItem.name;
|
|
1138
|
+
const roles = (resp.data.catalogItem.accessLevels || []).map((role) => ({
|
|
1139
|
+
id: role.accessLevelRemoteId,
|
|
1140
|
+
name: role.accessLevelName,
|
|
1141
|
+
}));
|
|
1142
|
+
if (roles.length > 0 &&
|
|
1143
|
+
!(roles.length === 1 && roles[0].name === "")) {
|
|
1144
|
+
cmd.log(`Roles not implemented yet for group ${groupName}. Skipping roles selection.`); //TODO: Implement group roles support
|
|
1145
|
+
continue;
|
|
1146
|
+
}
|
|
1147
|
+
const appId = ((_c = resp.data.catalogItem.connection) === null || _c === void 0 ? void 0 : _c.id) || "";
|
|
1148
|
+
if (!(appId in metadata.requestMap)) {
|
|
1149
|
+
metadata.requestMap[appId] = {
|
|
1150
|
+
appName: ((_d = resp.data.catalogItem.connection) === null || _d === void 0 ? void 0 : _d.displayName) || "",
|
|
1151
|
+
appId: appId,
|
|
1152
|
+
assets: {},
|
|
1153
|
+
};
|
|
1154
|
+
}
|
|
1155
|
+
const assetEntry = metadata.requestMap[appId].assets[id];
|
|
1156
|
+
if (!assetEntry) {
|
|
1157
|
+
metadata.requestMap[appId].assets[id] = {
|
|
1158
|
+
assetId: id,
|
|
1159
|
+
assetName: groupName,
|
|
1160
|
+
type: graphql_2.EntityType.Group,
|
|
1161
|
+
roles: {},
|
|
1162
|
+
};
|
|
1163
|
+
}
|
|
1164
|
+
if (roles) {
|
|
1165
|
+
if (!metadata.requestMap[appId].assets[id].roles) {
|
|
1166
|
+
metadata.requestMap[appId].assets[id].roles = {};
|
|
1167
|
+
}
|
|
1168
|
+
for (const role of roles) {
|
|
1169
|
+
metadata.requestMap[appId].assets[id].roles[role.id] = {
|
|
1170
|
+
roleId: role.id,
|
|
1171
|
+
roleName: role.name,
|
|
1172
|
+
};
|
|
1173
|
+
}
|
|
1174
|
+
}
|
|
1115
1175
|
break;
|
|
1116
1176
|
}
|
|
1117
1177
|
case "Connection": {
|
|
@@ -1130,3 +1190,10 @@ async function bypassRequestSelection(cmd, client, flagValue, metadata) {
|
|
|
1130
1190
|
}
|
|
1131
1191
|
return;
|
|
1132
1192
|
}
|
|
1193
|
+
function bypassDuration(cmd, duration, metadata) {
|
|
1194
|
+
const maxDuration = metadata.requestDefaults.maxDurationInMinutes;
|
|
1195
|
+
if (maxDuration && duration > maxDuration) {
|
|
1196
|
+
cmd.error(`The requested duration exceeds the allowed limit of ${maxDuration}`);
|
|
1197
|
+
}
|
|
1198
|
+
metadata.durationInMinutes = duration;
|
|
1199
|
+
}
|
package/lib/utils/displays.js
CHANGED
|
@@ -35,8 +35,10 @@ function treeifyRequestMap(cmd, requestMap) {
|
|
|
35
35
|
assetsTree[assetKey] = {};
|
|
36
36
|
for (const [_roleId, roleNode] of Object.entries(assetNode.roles)) {
|
|
37
37
|
const roleName = roleNode.roleName;
|
|
38
|
-
|
|
39
|
-
|
|
38
|
+
if (roleName !== "") {
|
|
39
|
+
const roleKey = `${roleName} ${chalk_1.default.dim("[Role]")}`;
|
|
40
|
+
assetsTree[assetKey][roleKey] = null;
|
|
41
|
+
}
|
|
40
42
|
}
|
|
41
43
|
}
|
|
42
44
|
else {
|
package/oclif.manifest.json
CHANGED
|
@@ -621,6 +621,14 @@
|
|
|
621
621
|
"hasDynamicHelp": false,
|
|
622
622
|
"multiple": false,
|
|
623
623
|
"type": "option"
|
|
624
|
+
},
|
|
625
|
+
"duration": {
|
|
626
|
+
"char": "d",
|
|
627
|
+
"description": "The duration of access for the request in minutes. If not provided, you will be prompted.",
|
|
628
|
+
"name": "duration",
|
|
629
|
+
"hasDynamicHelp": false,
|
|
630
|
+
"multiple": false,
|
|
631
|
+
"type": "option"
|
|
624
632
|
}
|
|
625
633
|
},
|
|
626
634
|
"hasDynamicHelp": false,
|
|
@@ -995,5 +1003,5 @@
|
|
|
995
1003
|
]
|
|
996
1004
|
}
|
|
997
1005
|
},
|
|
998
|
-
"version": "3.1.1-beta.
|
|
1006
|
+
"version": "3.1.1-beta.6b4868b"
|
|
999
1007
|
}
|
package/package.json
CHANGED