opal-security 3.1.1-beta.28b7d49 → 3.1.1-beta.2c09f5e

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 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.28b7d49 linux-x64 node-v20.19.2
25
+ opal-security/3.1.1-beta.2c09f5e linux-x64 node-v20.19.2
26
26
  $ opal --help [COMMAND]
27
27
  USAGE
28
28
  $ opal COMMAND
@@ -53,7 +53,6 @@ USAGE
53
53
  * [`opal ssh copyTo`](#opal-ssh-copyto)
54
54
  * [`opal ssh start`](#opal-ssh-start)
55
55
  * [`opal version`](#opal-version)
56
- * [`opal whoami`](#opal-whoami)
57
56
 
58
57
  ## `opal autocomplete [SHELL]`
59
58
 
@@ -102,7 +101,7 @@ EXAMPLES
102
101
  $ opal aws:identity
103
102
  ```
104
103
 
105
- _See code: [src/commands/aws/identity.ts](https://github.com/opalsecurity/opal-cli/blob/v3.1.1-beta.28b7d49/src/commands/aws/identity.ts)_
104
+ _See code: [src/commands/aws/identity.ts](https://github.com/opalsecurity/opal-cli/blob/v3.1.1-beta.2c09f5e/src/commands/aws/identity.ts)_
106
105
 
107
106
  ## `opal clear-auth-provider`
108
107
 
@@ -122,7 +121,7 @@ EXAMPLES
122
121
  $ opal clear-auth-provider
123
122
  ```
124
123
 
125
- _See code: [src/commands/clear-auth-provider.ts](https://github.com/opalsecurity/opal-cli/blob/v3.1.1-beta.28b7d49/src/commands/clear-auth-provider.ts)_
124
+ _See code: [src/commands/clear-auth-provider.ts](https://github.com/opalsecurity/opal-cli/blob/v3.1.1-beta.2c09f5e/src/commands/clear-auth-provider.ts)_
126
125
 
127
126
  ## `opal curl-example`
128
127
 
@@ -139,7 +138,7 @@ DESCRIPTION
139
138
  Prints out an example cURL command containing the parameters the CLI uses to query the Opal server.
140
139
  ```
141
140
 
142
- _See code: [src/commands/curl-example.ts](https://github.com/opalsecurity/opal-cli/blob/v3.1.1-beta.28b7d49/src/commands/curl-example.ts)_
141
+ _See code: [src/commands/curl-example.ts](https://github.com/opalsecurity/opal-cli/blob/v3.1.1-beta.2c09f5e/src/commands/curl-example.ts)_
143
142
 
144
143
  ## `opal groups get`
145
144
 
@@ -160,7 +159,7 @@ EXAMPLES
160
159
  $ opal groups:get --id 54052a3e-5375-4392-aeaf-0c6c44c131d4
161
160
  ```
162
161
 
163
- _See code: [src/commands/groups/get.ts](https://github.com/opalsecurity/opal-cli/blob/v3.1.1-beta.28b7d49/src/commands/groups/get.ts)_
162
+ _See code: [src/commands/groups/get.ts](https://github.com/opalsecurity/opal-cli/blob/v3.1.1-beta.2c09f5e/src/commands/groups/get.ts)_
164
163
 
165
164
  ## `opal help [COMMANDS]`
166
165
 
@@ -210,7 +209,7 @@ EXAMPLES
210
209
  $ opal iam-roles:start --id 51f7176b-0464-4a6f-8369-e951e187b398 --profileName "custom-profile"
211
210
  ```
212
211
 
213
- _See code: [src/commands/iam-roles/start.ts](https://github.com/opalsecurity/opal-cli/blob/v3.1.1-beta.28b7d49/src/commands/iam-roles/start.ts)_
212
+ _See code: [src/commands/iam-roles/start.ts](https://github.com/opalsecurity/opal-cli/blob/v3.1.1-beta.2c09f5e/src/commands/iam-roles/start.ts)_
214
213
 
215
214
  ## `opal kube-roles start`
216
215
 
@@ -241,7 +240,7 @@ EXAMPLES
241
240
  $ opal kube-roles:start --id 51f7176b-0464-4a6f-8369-e951e187b398 --accessLevelRemoteId "arn:aws:iam::712234975475:role/acme-eks-cluster-admin-role"
242
241
  ```
243
242
 
244
- _See code: [src/commands/kube-roles/start.ts](https://github.com/opalsecurity/opal-cli/blob/v3.1.1-beta.28b7d49/src/commands/kube-roles/start.ts)_
243
+ _See code: [src/commands/kube-roles/start.ts](https://github.com/opalsecurity/opal-cli/blob/v3.1.1-beta.2c09f5e/src/commands/kube-roles/start.ts)_
245
244
 
246
245
  ## `opal login`
247
246
 
@@ -262,7 +261,7 @@ EXAMPLES
262
261
  $ opal login
263
262
  ```
264
263
 
265
- _See code: [src/commands/login.ts](https://github.com/opalsecurity/opal-cli/blob/v3.1.1-beta.28b7d49/src/commands/login.ts)_
264
+ _See code: [src/commands/login.ts](https://github.com/opalsecurity/opal-cli/blob/v3.1.1-beta.2c09f5e/src/commands/login.ts)_
266
265
 
267
266
  ## `opal logout`
268
267
 
@@ -282,7 +281,7 @@ EXAMPLES
282
281
  $ opal logout
283
282
  ```
284
283
 
285
- _See code: [src/commands/logout.ts](https://github.com/opalsecurity/opal-cli/blob/v3.1.1-beta.28b7d49/src/commands/logout.ts)_
284
+ _See code: [src/commands/logout.ts](https://github.com/opalsecurity/opal-cli/blob/v3.1.1-beta.2c09f5e/src/commands/logout.ts)_
286
285
 
287
286
  ## `opal postgres-instances start`
288
287
 
@@ -319,7 +318,7 @@ EXAMPLES
319
318
  $ opal postgres-instances:start --id 51f7176b-0464-4a6f-8369-e951e187b398 --accessLevelRemoteId fullaccess --action view
320
319
  ```
321
320
 
322
- _See code: [src/commands/postgres-instances/start.ts](https://github.com/opalsecurity/opal-cli/blob/v3.1.1-beta.28b7d49/src/commands/postgres-instances/start.ts)_
321
+ _See code: [src/commands/postgres-instances/start.ts](https://github.com/opalsecurity/opal-cli/blob/v3.1.1-beta.2c09f5e/src/commands/postgres-instances/start.ts)_
323
322
 
324
323
  ## `opal resources get`
325
324
 
@@ -340,7 +339,7 @@ EXAMPLES
340
339
  $ opal resources:get --id 54052a3e-5375-4392-aeaf-0c6c44c131d4
341
340
  ```
342
341
 
343
- _See code: [src/commands/resources/get.ts](https://github.com/opalsecurity/opal-cli/blob/v3.1.1-beta.28b7d49/src/commands/resources/get.ts)_
342
+ _See code: [src/commands/resources/get.ts](https://github.com/opalsecurity/opal-cli/blob/v3.1.1-beta.2c09f5e/src/commands/resources/get.ts)_
344
343
 
345
344
  ## `opal set-auth-provider`
346
345
 
@@ -366,7 +365,7 @@ EXAMPLES
366
365
  $ opal set-auth-provider --clientID 1234asdf --issuerUrl https://auth.example.com
367
366
  ```
368
367
 
369
- _See code: [src/commands/set-auth-provider.ts](https://github.com/opalsecurity/opal-cli/blob/v3.1.1-beta.28b7d49/src/commands/set-auth-provider.ts)_
368
+ _See code: [src/commands/set-auth-provider.ts](https://github.com/opalsecurity/opal-cli/blob/v3.1.1-beta.2c09f5e/src/commands/set-auth-provider.ts)_
370
369
 
371
370
  ## `opal set-custom-header`
372
371
 
@@ -387,7 +386,7 @@ EXAMPLES
387
386
  $ opal set-custom-header --header 'cf-access-token: $TOKEN'
388
387
  ```
389
388
 
390
- _See code: [src/commands/set-custom-header.ts](https://github.com/opalsecurity/opal-cli/blob/v3.1.1-beta.28b7d49/src/commands/set-custom-header.ts)_
389
+ _See code: [src/commands/set-custom-header.ts](https://github.com/opalsecurity/opal-cli/blob/v3.1.1-beta.2c09f5e/src/commands/set-custom-header.ts)_
391
390
 
392
391
  ## `opal set-token`
393
392
 
@@ -407,7 +406,7 @@ EXAMPLES
407
406
  $ opal set-token
408
407
  ```
409
408
 
410
- _See code: [src/commands/set-token.ts](https://github.com/opalsecurity/opal-cli/blob/v3.1.1-beta.28b7d49/src/commands/set-token.ts)_
409
+ _See code: [src/commands/set-token.ts](https://github.com/opalsecurity/opal-cli/blob/v3.1.1-beta.2c09f5e/src/commands/set-token.ts)_
411
410
 
412
411
  ## `opal set-url [URL]`
413
412
 
@@ -431,7 +430,7 @@ EXAMPLES
431
430
  $ opal set-url
432
431
  ```
433
432
 
434
- _See code: [src/commands/set-url.ts](https://github.com/opalsecurity/opal-cli/blob/v3.1.1-beta.28b7d49/src/commands/set-url.ts)_
433
+ _See code: [src/commands/set-url.ts](https://github.com/opalsecurity/opal-cli/blob/v3.1.1-beta.2c09f5e/src/commands/set-url.ts)_
435
434
 
436
435
  ## `opal ssh copyFrom`
437
436
 
@@ -462,7 +461,7 @@ EXAMPLES
462
461
  $ opal ssh:copyFrom --src instance/dir --dest my/dir --id 51f7176b-0464-4a6f-8369-e951e187b398
463
462
  ```
464
463
 
465
- _See code: [src/commands/ssh/copyFrom.ts](https://github.com/opalsecurity/opal-cli/blob/v3.1.1-beta.28b7d49/src/commands/ssh/copyFrom.ts)_
464
+ _See code: [src/commands/ssh/copyFrom.ts](https://github.com/opalsecurity/opal-cli/blob/v3.1.1-beta.2c09f5e/src/commands/ssh/copyFrom.ts)_
466
465
 
467
466
  ## `opal ssh copyTo`
468
467
 
@@ -493,7 +492,7 @@ EXAMPLES
493
492
  $ opal ssh:copyTo --src my/dir --dest instance/dir --id 51f7176b-0464-4a6f-8369-e951e187b398
494
493
  ```
495
494
 
496
- _See code: [src/commands/ssh/copyTo.ts](https://github.com/opalsecurity/opal-cli/blob/v3.1.1-beta.28b7d49/src/commands/ssh/copyTo.ts)_
495
+ _See code: [src/commands/ssh/copyTo.ts](https://github.com/opalsecurity/opal-cli/blob/v3.1.1-beta.2c09f5e/src/commands/ssh/copyTo.ts)_
497
496
 
498
497
  ## `opal ssh start`
499
498
 
@@ -520,7 +519,7 @@ EXAMPLES
520
519
  $ opal ssh:start --id 51f7176b-0464-4a6f-8369-e951e187b398
521
520
  ```
522
521
 
523
- _See code: [src/commands/ssh/start.ts](https://github.com/opalsecurity/opal-cli/blob/v3.1.1-beta.28b7d49/src/commands/ssh/start.ts)_
522
+ _See code: [src/commands/ssh/start.ts](https://github.com/opalsecurity/opal-cli/blob/v3.1.1-beta.2c09f5e/src/commands/ssh/start.ts)_
524
523
 
525
524
  ## `opal version`
526
525
 
@@ -541,21 +540,4 @@ FLAG DESCRIPTIONS
541
540
  ```
542
541
 
543
542
  _See code: [@oclif/plugin-version](https://github.com/oclif/plugin-version/blob/v2.2.27/src/commands/version.ts)_
544
-
545
- ## `opal whoami`
546
-
547
- Describes current url set, organization name, and logged in user if applicabled.
548
-
549
- ```
550
- USAGE
551
- $ opal whoami [-h]
552
-
553
- FLAGS
554
- -h, --help Show CLI help.
555
-
556
- DESCRIPTION
557
- Describes current url set, organization name, and logged in user if applicabled.
558
- ```
559
-
560
- _See code: [src/commands/whoami.ts](https://github.com/opalsecurity/opal-cli/blob/v3.1.1-beta.28b7d49/src/commands/whoami.ts)_
561
543
  <!-- commandsstop -->
@@ -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, organizationName);
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, organizationName);
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)({
@@ -4,7 +4,7 @@ export default class RequestCreate extends Command {
4
4
  static description: string;
5
5
  static flags: {
6
6
  help: import("@oclif/core/lib/interfaces").BooleanFlag<void>;
7
- assets: import("@oclif/core/lib/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
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
9
  duration: import("@oclif/core/lib/interfaces").OptionFlag<number | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
10
10
  };
@@ -13,9 +13,9 @@ class RequestCreate extends core_1.Command {
13
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.assets) {
16
+ if (flags.id) {
17
17
  // if IDs are provided, bypass the interactive selection process
18
- await (0, requests_1.bypassRequestSelection)(this, client, flags.assets, metadata);
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 if (!(metadata.requestDefaults.reasonOptional &&
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,25 +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
- let canSubmit = true;
53
- if (!(flags.assets &&
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
- if (canSubmit)
60
- await (0, requests_1.submitFinalRequest)(this, client, metadata);
54
+ await (0, requests_1.submitFinalRequest)(this, client, metadata);
61
55
  }
62
56
  }
63
57
  RequestCreate.hidden = true;
64
58
  RequestCreate.description = "Creates an Opal access request via an interactive form";
65
59
  RequestCreate.flags = {
66
60
  help: flags_1.SHARED_FLAGS.help,
67
- assets: core_1.Flags.string({
68
- char: "a",
61
+ id: core_1.Flags.string({
62
+ char: "i",
69
63
  multiple: true,
70
- description: "The ids of the assets (resource, group) to request access to. Append a role ID using a colon if needed, e.g. `--assets 123:456`.\
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`.\
71
65
  \n If not provided, an interactive selection flow will be available to select assets to request.",
72
66
  }),
73
67
  reason: core_1.Flags.string({
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, forward }) => {
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
- return (0, core_1.fromPromise)(loginCommand.run().then(() => {
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
- })).flatMap(() => forward(operation));
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, organizationName?: string) => Promise<void>;
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, organizationName) => {
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);
@@ -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,7 +45,7 @@ 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<boolean>;
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
50
  export declare function bypassRequestSelection(cmd: Command, client: ApolloClient<NormalizedCacheObject>, flagValue: string[], metadata: RequestMetadata): Promise<void>;
52
51
  export declare function bypassDuration(cmd: Command, duration: number, metadata: RequestMetadata): void;
@@ -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;
@@ -12,26 +11,22 @@ exports.submitFinalRequest = submitFinalRequest;
12
11
  exports.bypassRequestSelection = bypassRequestSelection;
13
12
  exports.bypassDuration = bypassDuration;
14
13
  const chalk_1 = require("chalk");
14
+ const inquirer = require("inquirer");
15
15
  const graphql_1 = require("../graphql");
16
16
  const graphql_2 = require("../graphql/graphql");
17
17
  const displays_1 = require("../utils/displays");
18
18
  const config_1 = require("./config");
19
19
  const { AutoComplete, Select, prompt, Form } = require("enquirer");
20
20
  function entityTypeFromString(str) {
21
- const capStr = str === null || str === void 0 ? void 0 : str.toLocaleUpperCase();
22
- if (capStr === "RESOURCE") {
21
+ if (str === "Resource") {
23
22
  return graphql_2.EntityType.Resource;
24
23
  }
25
- if (capStr === "GROUP") {
24
+ if (str === "Group") {
26
25
  return graphql_2.EntityType.Group;
27
26
  }
28
27
  // if type unknown, default to resource
29
28
  return graphql_2.EntityType.Resource;
30
29
  }
31
- exports.DISPLAY_LABELS = {
32
- [graphql_2.EntityType.Resource]: "Resource",
33
- [graphql_2.EntityType.Group]: "Group",
34
- };
35
30
  function initEmptyRequestMetadata() {
36
31
  // Initialize with empty defaults
37
32
  const requestDefaults = {
@@ -184,7 +179,7 @@ async function queryRequestableAssets(cmd, client, appId, input) {
184
179
  value: {
185
180
  name: name || "",
186
181
  id: id || "",
187
- type: entityTypeFromString(((_g = item.resource) === null || _g === void 0 ? void 0 : _g.__typename) || ((_h = item.group) === null || _h === void 0 ? void 0 : _h.__typename)),
182
+ type: ((_g = item.resource) === null || _g === void 0 ? void 0 : _g.__typename) || ((_h = item.group) === null || _h === void 0 ? void 0 : _h.__typename) || "",
188
183
  },
189
184
  };
190
185
  });
@@ -628,14 +623,11 @@ async function queryAssociatedItems(cmd, client, id, input) {
628
623
  }
629
624
  }
630
625
  // Helper functions
631
- const selectInstructions = chalk_1.default.dim("[↑↓] Navigate · [Enter] Select · Type to filter");
632
- const multiSelectInstructions = chalk_1.default.dim("[↑↓] Navigate · [Space] Select · [Enter] Confirm · Type to filter");
633
626
  async function selectRequestableItems(cmd, client, requestMap) {
634
627
  const initial = (await queryRequestableApps(cmd, client, "")) || [];
635
628
  const appPrompt = new AutoComplete({
636
629
  name: "App",
637
- message: "Select an app",
638
- hint: selectInstructions,
630
+ message: "Select an app:",
639
631
  limit: 15,
640
632
  choices: initial,
641
633
  async suggest(input) {
@@ -663,7 +655,6 @@ async function chooseOktaAzureRoles(cmd, client, app, requestMap) {
663
655
  const rolePrompt = new AutoComplete({
664
656
  name: "Roles",
665
657
  message: `Select a role for ${app.name}:`,
666
- hint: multiSelectInstructions,
667
658
  limit: 15,
668
659
  multiple: true,
669
660
  async choices(input) {
@@ -674,7 +665,7 @@ async function chooseOktaAzureRoles(cmd, client, app, requestMap) {
674
665
  },
675
666
  validate: (answer) => {
676
667
  if (answer.length !== 1) {
677
- return "Only one role is allowed to be requested for on Okta or Azure apps.";
668
+ return "You must select only one item.";
678
669
  }
679
670
  return true;
680
671
  },
@@ -702,7 +693,7 @@ function appRolesFromEdge(edge) {
702
693
  value: {
703
694
  id: edge.node.id + accessLevel.accessLevelRemoteId,
704
695
  name: accessLevel.accessLevelName,
705
- type: exports.DISPLAY_LABELS[graphql_2.EntityType.Resource],
696
+ type: graphql_2.EntityType.Resource,
706
697
  toString: () => accessLevel.accessLevelName,
707
698
  },
708
699
  }));
@@ -713,7 +704,7 @@ function appRolesFromEdge(edge) {
713
704
  value: {
714
705
  id: edge.node.id,
715
706
  name: (_b = edge.alias) !== null && _b !== void 0 ? _b : edge.node.name,
716
- type: exports.DISPLAY_LABELS[graphql_2.EntityType.Resource],
707
+ type: graphql_2.EntityType.Resource,
717
708
  toString: () => { var _a; return (_a = edge.alias) !== null && _a !== void 0 ? _a : edge.node.name; },
718
709
  },
719
710
  },
@@ -722,11 +713,11 @@ function appRolesFromEdge(edge) {
722
713
  case "Group":
723
714
  return [
724
715
  {
725
- message: `${(_c = edge.alias) !== null && _c !== void 0 ? _c : edge.node.name} ${graphql_2.EntityType.Group}`,
716
+ message: (_c = edge.alias) !== null && _c !== void 0 ? _c : edge.node.name,
726
717
  value: {
727
718
  id: edge.node.id,
728
719
  name: (_d = edge.alias) !== null && _d !== void 0 ? _d : edge.node.name,
729
- type: exports.DISPLAY_LABELS[graphql_2.EntityType.Group],
720
+ type: graphql_2.EntityType.Group,
730
721
  toString: () => { var _a; return (_a = edge.alias) !== null && _a !== void 0 ? _a : edge.node.name; },
731
722
  },
732
723
  },
@@ -738,7 +729,6 @@ async function chooseAssets(cmd, client, appId, requestMap) {
738
729
  const assetPrompt = new AutoComplete({
739
730
  name: "Assets",
740
731
  message: "Select one or more assets:",
741
- hint: multiSelectInstructions,
742
732
  limit: 15,
743
733
  multiple: true,
744
734
  async choices(input) {
@@ -788,7 +778,6 @@ async function chooseRoles(cmd, client, appId, assetId, requestMap) {
788
778
  const rolePrompt = new AutoComplete({
789
779
  name: "Roles",
790
780
  message: `Select one or more roles for ${assetEntry.assetName}:`,
791
- hint: multiSelectInstructions,
792
781
  limit: 15,
793
782
  multiple: true,
794
783
  choices: assetRoles,
@@ -879,7 +868,7 @@ async function promptForReason(metadata) {
879
868
  const { reason } = await prompt([
880
869
  {
881
870
  name: "reason",
882
- message: "Why do you need access?",
871
+ message: "I need access to this because...",
883
872
  type: "input",
884
873
  validate: (answer) => {
885
874
  if (!metadata.requestDefaults.reasonOptional && answer.length < 1) {
@@ -1005,13 +994,26 @@ async function promptRequestSubmission(cmd, metadata) {
1005
994
  (0, displays_1.displayFinalRequestSummary)(cmd, metadata);
1006
995
  const submitMessage = "✅ Yes, submit request";
1007
996
  const cancelMessage = "❌ No, cancel request";
1008
- const prompt = new Select({
1009
- name: "submitOrCancel",
1010
- message: "Is this all you want to request?",
1011
- choices: [submitMessage, cancelMessage],
1012
- });
1013
- const submitOrCancel = await prompt.run();
1014
- return submitOrCancel === submitMessage;
997
+ const { submit } = await inquirer.prompt([
998
+ {
999
+ name: "submit",
1000
+ message: "Submit request?",
1001
+ type: "list",
1002
+ choices: [submitMessage, cancelMessage],
1003
+ },
1004
+ ]);
1005
+ switch (submit) {
1006
+ case submitMessage: {
1007
+ return;
1008
+ }
1009
+ case cancelMessage: {
1010
+ cmd.log("🚫 Access Request has been cancelled.");
1011
+ return;
1012
+ }
1013
+ default: {
1014
+ cmd.error("Unknown error occurred.");
1015
+ }
1016
+ }
1015
1017
  }
1016
1018
  async function submitFinalRequest(cmd, client, metadata) {
1017
1019
  var _a, _b, _c, _d;
@@ -1070,68 +1072,108 @@ async function submitFinalRequest(cmd, client, metadata) {
1070
1072
  return;
1071
1073
  }
1072
1074
  async function bypassRequestSelection(cmd, client, flagValue, metadata) {
1073
- var _a, _b;
1075
+ var _a, _b, _c, _d;
1074
1076
  try {
1075
1077
  // Query Catalog Item endpoint to identify what the id belongs to (resource or group)
1076
- for (const val of flagValue) {
1077
- const delimiterIndex = val.indexOf(":");
1078
- const assetId = val.substring(0, delimiterIndex);
1079
- const roleName = val.substring(delimiterIndex + 1);
1078
+ for (const id of flagValue) {
1080
1079
  const resp = await client.query({
1081
1080
  query: CATALOG_ITEM,
1082
1081
  variables: {
1083
- uuid: assetId || "",
1082
+ uuid: id || "",
1084
1083
  },
1085
1084
  fetchPolicy: "network-only", // to avoid caching
1086
1085
  });
1087
1086
  switch (resp.data.catalogItem.__typename) {
1088
- case "Group":
1089
1087
  case "Resource": {
1090
- const item = resp.data.catalogItem;
1091
- const assetName = item.__typename === "Resource" ? item.displayName : item.name;
1092
- const requestableRoles = (item.accessLevels || [])
1088
+ const resourceName = resp.data.catalogItem.displayName;
1089
+ const roles = (resp.data.catalogItem.accessLevels || [])
1093
1090
  // TODO: Support okta azure apps ?.filter((role) => role.accessLevelName !== "") // This assumes length == 1
1094
1091
  .map((role) => ({
1095
1092
  id: role.accessLevelRemoteId,
1096
1093
  name: role.accessLevelName,
1097
1094
  }));
1098
- const appId = ((_a = item.connection) === null || _a === void 0 ? void 0 : _a.id) || "";
1095
+ if (roles.length > 0 &&
1096
+ !(roles.length === 1 && roles[0].name === "")) {
1097
+ cmd.log(`Roles not implemented yet for resource ${resourceName}. Skipping roles selection.`); //TODO: Implement roles support
1098
+ continue;
1099
+ }
1100
+ const appId = ((_a = resp.data.catalogItem.connection) === null || _a === void 0 ? void 0 : _a.id) || "";
1099
1101
  if (!(appId in metadata.requestMap)) {
1100
1102
  metadata.requestMap[appId] = {
1101
- appName: ((_b = item.connection) === null || _b === void 0 ? void 0 : _b.displayName) || "",
1103
+ appName: ((_b = resp.data.catalogItem.connection) === null || _b === void 0 ? void 0 : _b.displayName) || "",
1102
1104
  appId: appId,
1103
1105
  assets: {},
1104
1106
  };
1105
1107
  }
1106
- const assetEntry = metadata.requestMap[appId].assets[assetId];
1108
+ const assetEntry = metadata.requestMap[appId].assets[id];
1107
1109
  if (!assetEntry) {
1108
- metadata.requestMap[appId].assets[assetId] = {
1109
- assetId: assetId,
1110
- assetName: assetName,
1111
- type: entityTypeFromString(item.__typename),
1110
+ metadata.requestMap[appId].assets[id] = {
1111
+ assetId: id,
1112
+ assetName: resourceName,
1113
+ type: graphql_2.EntityType.Resource,
1112
1114
  roles: {},
1113
1115
  };
1114
1116
  }
1115
- if (requestableRoles.length > 0 &&
1116
- !(requestableRoles.length === 1 && requestableRoles[0].name === "")) {
1117
- const selectedRole = requestableRoles.find((role) => role.name === roleName);
1118
- if (selectedRole !== undefined) {
1119
- if (!metadata.requestMap[appId].assets[assetId].roles) {
1120
- metadata.requestMap[appId].assets[assetId].roles = {};
1121
- }
1122
- metadata.requestMap[appId].assets[assetId].roles[selectedRole.id] = {
1123
- roleId: selectedRole.id,
1124
- roleName: selectedRole.name,
1117
+ if (roles && !(roles.length === 1 && roles[0].name === "")) {
1118
+ if (!metadata.requestMap[appId].assets[id].roles) {
1119
+ metadata.requestMap[appId].assets[id].roles = {};
1120
+ }
1121
+ for (const role of roles) {
1122
+ metadata.requestMap[appId].assets[id].roles[role.id] = {
1123
+ roleId: role.id,
1124
+ roleName: role.name,
1125
1125
  };
1126
1126
  }
1127
- else {
1128
- cmd.error(`Access level specified does not match one of ${assetName}'s defined access levels: ${requestableRoles.map((role) => `"${role.name}"`)}`);
1127
+ }
1128
+ break;
1129
+ }
1130
+ case "Group": {
1131
+ const groupName = resp.data.catalogItem.name;
1132
+ const roles = (resp.data.catalogItem.accessLevels || []).map((role) => ({
1133
+ id: role.accessLevelRemoteId,
1134
+ name: role.accessLevelName,
1135
+ }));
1136
+ if (roles.length > 0 &&
1137
+ !(roles.length === 1 && roles[0].name === "")) {
1138
+ cmd.log(`Roles not implemented yet for group ${groupName}. Skipping roles selection.`); //TODO: Implement group roles support
1139
+ continue;
1140
+ }
1141
+ const appId = ((_c = resp.data.catalogItem.connection) === null || _c === void 0 ? void 0 : _c.id) || "";
1142
+ if (!(appId in metadata.requestMap)) {
1143
+ metadata.requestMap[appId] = {
1144
+ appName: ((_d = resp.data.catalogItem.connection) === null || _d === void 0 ? void 0 : _d.displayName) || "",
1145
+ appId: appId,
1146
+ assets: {},
1147
+ };
1148
+ }
1149
+ const assetEntry = metadata.requestMap[appId].assets[id];
1150
+ if (!assetEntry) {
1151
+ metadata.requestMap[appId].assets[id] = {
1152
+ assetId: id,
1153
+ assetName: groupName,
1154
+ type: graphql_2.EntityType.Group,
1155
+ roles: {},
1156
+ };
1157
+ }
1158
+ if (roles) {
1159
+ if (!metadata.requestMap[appId].assets[id].roles) {
1160
+ metadata.requestMap[appId].assets[id].roles = {};
1161
+ }
1162
+ for (const role of roles) {
1163
+ metadata.requestMap[appId].assets[id].roles[role.id] = {
1164
+ roleId: role.id,
1165
+ roleName: role.name,
1166
+ };
1129
1167
  }
1130
1168
  }
1131
1169
  break;
1132
1170
  }
1171
+ case "Connection": {
1172
+ //TODO
1173
+ break;
1174
+ }
1133
1175
  default:
1134
- cmd.error("Invalid asset id was passed in using the --id flag.");
1176
+ cmd.error("Unknown error occurred.");
1135
1177
  }
1136
1178
  }
1137
1179
  }
@@ -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 { type RequestMap, type RequestMetadata } from "../lib/requests";
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;
@@ -7,7 +7,6 @@ exports.getStyledStatus = getStyledStatus;
7
7
  exports.displayRequestDetails = displayRequestDetails;
8
8
  exports.displayRequestListTable = displayRequestListTable;
9
9
  const chalk_1 = require("chalk");
10
- const requests_1 = require("../lib/requests");
11
10
  const Table = require("cli-table3");
12
11
  const treeify = require("object-treeify").default;
13
12
  function headerMessage(cmd) {
@@ -31,7 +30,7 @@ function treeifyRequestMap(cmd, requestMap) {
31
30
  for (const [_assetId, assetNode] of Object.entries(appNode.assets)) {
32
31
  // If okta/azure asset with no role, change asset name
33
32
  const assetName = assetNode.assetName || "No Role (Direct access)";
34
- const assetKey = `${assetName} ${chalk_1.default.dim(`[${requests_1.DISPLAY_LABELS[assetNode.type]}]`)}`;
33
+ const assetKey = `${assetName} ${chalk_1.default.dim(`[${assetNode.type}]`)}`;
35
34
  if (assetNode.roles !== undefined) {
36
35
  assetsTree[assetKey] = {};
37
36
  for (const [_roleId, roleNode] of Object.entries(assetNode.roles)) {
@@ -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 applicabled.",
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
- "assets": {
638
- "char": "a",
639
- "description": "The ids of the assets (resource, group) to request access to. Append a role ID using a colon if needed, e.g. `--assets 123:456`. \n If not provided, an interactive selection flow will be available to select assets to request.",
640
- "name": "assets",
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"
@@ -1031,5 +1003,5 @@
1031
1003
  ]
1032
1004
  }
1033
1005
  },
1034
- "version": "3.1.1-beta.28b7d49"
1006
+ "version": "3.1.1-beta.2c09f5e"
1035
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.28b7d49",
4
+ "version": "3.1.1-beta.2c09f5e",
5
5
  "author": "Stephen Cobbe",
6
6
  "bin": {
7
7
  "opal": "./bin/run"
@@ -1,8 +0,0 @@
1
- import { Command } from "@oclif/core";
2
- export default class WhoAmI extends Command {
3
- static description: string;
4
- static flags: {
5
- help: import("@oclif/core/lib/interfaces").BooleanFlag<void>;
6
- };
7
- run(): Promise<void>;
8
- }
@@ -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 applicabled.";
31
- WhoAmI.flags = {
32
- help: flags_1.SHARED_FLAGS.help,
33
- };
34
- exports.default = WhoAmI;