opal-security 2.0.10 → 2.0.13

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 (-v|--version|version)
25
- opal-security/2.0.10 darwin-x64 node-v14.16.1
25
+ opal-security/2.0.13 darwin-x64 node-v14.16.1
26
26
  $ opal --help [COMMAND]
27
27
  USAGE
28
28
  $ opal COMMAND
@@ -86,7 +86,7 @@ EXAMPLE
86
86
  opal aws:identity
87
87
  ```
88
88
 
89
- _See code: [src/commands/aws/identity.ts](https://github.com/opalsecurity/opal-cli/blob/v2.0.10/src/commands/aws/identity.ts)_
89
+ _See code: [src/commands/aws/identity.ts](https://github.com/opalsecurity/opal-cli/blob/v2.0.13/src/commands/aws/identity.ts)_
90
90
 
91
91
  ## `opal curl-example`
92
92
 
@@ -100,7 +100,7 @@ OPTIONS
100
100
  -h, --help show CLI help
101
101
  ```
102
102
 
103
- _See code: [src/commands/curl-example.ts](https://github.com/opalsecurity/opal-cli/blob/v2.0.10/src/commands/curl-example.ts)_
103
+ _See code: [src/commands/curl-example.ts](https://github.com/opalsecurity/opal-cli/blob/v2.0.13/src/commands/curl-example.ts)_
104
104
 
105
105
  ## `opal help [COMMAND]`
106
106
 
@@ -128,15 +128,16 @@ USAGE
128
128
  $ opal iam-roles:start
129
129
 
130
130
  OPTIONS
131
- -h, --help show CLI help
132
- --id=id The ID of the Opal role resource.
131
+ -h, --help show CLI help
132
+ --id=id The ID of the Opal role resource.
133
+ --sessionId=sessionId SessionId of a session that has already been created via the web flow.
133
134
 
134
135
  EXAMPLES
135
136
  opal iam-roles:start
136
137
  opal iam-roles:start --id 51f7176b-0464-4a6f-8369-e951e187b398
137
138
  ```
138
139
 
139
- _See code: [src/commands/iam-roles/start.ts](https://github.com/opalsecurity/opal-cli/blob/v2.0.10/src/commands/iam-roles/start.ts)_
140
+ _See code: [src/commands/iam-roles/start.ts](https://github.com/opalsecurity/opal-cli/blob/v2.0.13/src/commands/iam-roles/start.ts)_
140
141
 
141
142
  ## `opal kube-roles:start`
142
143
 
@@ -150,6 +151,7 @@ OPTIONS
150
151
  -h, --help show CLI help
151
152
  --accessLevelRemoteId=accessLevelRemoteId The remote ID of the access level with which to access the cluster.
152
153
  --id=id The ID of the Opal role resource.
154
+ --sessionId=sessionId SessionId of a session that has already been created via the web flow.
153
155
 
154
156
  EXAMPLES
155
157
  opal kube-roles:start
@@ -158,7 +160,7 @@ EXAMPLES
158
160
  "arn:aws:iam::712234975475:role/acme-eks-cluster-admin-role"
159
161
  ```
160
162
 
161
- _See code: [src/commands/kube-roles/start.ts](https://github.com/opalsecurity/opal-cli/blob/v2.0.10/src/commands/kube-roles/start.ts)_
163
+ _See code: [src/commands/kube-roles/start.ts](https://github.com/opalsecurity/opal-cli/blob/v2.0.13/src/commands/kube-roles/start.ts)_
162
164
 
163
165
  ## `opal login`
164
166
 
@@ -175,7 +177,7 @@ EXAMPLE
175
177
  $ opal login
176
178
  ```
177
179
 
178
- _See code: [src/commands/login.ts](https://github.com/opalsecurity/opal-cli/blob/v2.0.10/src/commands/login.ts)_
180
+ _See code: [src/commands/login.ts](https://github.com/opalsecurity/opal-cli/blob/v2.0.13/src/commands/login.ts)_
179
181
 
180
182
  ## `opal logout`
181
183
 
@@ -192,7 +194,7 @@ EXAMPLE
192
194
  $ opal logout
193
195
  ```
194
196
 
195
- _See code: [src/commands/logout.ts](https://github.com/opalsecurity/opal-cli/blob/v2.0.10/src/commands/logout.ts)_
197
+ _See code: [src/commands/logout.ts](https://github.com/opalsecurity/opal-cli/blob/v2.0.13/src/commands/logout.ts)_
196
198
 
197
199
  ## `opal postgres-instances:start`
198
200
 
@@ -206,6 +208,7 @@ OPTIONS
206
208
  -h, --help show CLI help
207
209
  --accessLevelRemoteId=accessLevelRemoteId The remote ID of the access level with which to access the database.
208
210
  --id=id The ID of the Opal instance resource.
211
+ --sessionId=sessionId SessionId of a session that has already been created via the web flow.
209
212
 
210
213
  EXAMPLES
211
214
  opal postgres-instances:start
@@ -213,7 +216,7 @@ EXAMPLES
213
216
  opal postgres-instances:start --id 51f7176b-0464-4a6f-8369-e951e187b398 --accessLevelRemoteId "fullaccess"
214
217
  ```
215
218
 
216
- _See code: [src/commands/postgres-instances/start.ts](https://github.com/opalsecurity/opal-cli/blob/v2.0.10/src/commands/postgres-instances/start.ts)_
219
+ _See code: [src/commands/postgres-instances/start.ts](https://github.com/opalsecurity/opal-cli/blob/v2.0.13/src/commands/postgres-instances/start.ts)_
217
220
 
218
221
  ## `opal resources:get`
219
222
 
@@ -231,7 +234,7 @@ EXAMPLE
231
234
  opal resources:get --id 54052a3e-5375-4392-aeaf-0c6c44c131d4
232
235
  ```
233
236
 
234
- _See code: [src/commands/resources/get.ts](https://github.com/opalsecurity/opal-cli/blob/v2.0.10/src/commands/resources/get.ts)_
237
+ _See code: [src/commands/resources/get.ts](https://github.com/opalsecurity/opal-cli/blob/v2.0.13/src/commands/resources/get.ts)_
235
238
 
236
239
  ## `opal set-url`
237
240
 
@@ -249,12 +252,13 @@ OPTIONS
249
252
  --dev
250
253
  --devLocal
251
254
  --prod
255
+ --staging
252
256
 
253
257
  EXAMPLE
254
258
  $ opal set-host
255
259
  ```
256
260
 
257
- _See code: [src/commands/set-url.ts](https://github.com/opalsecurity/opal-cli/blob/v2.0.10/src/commands/set-url.ts)_
261
+ _See code: [src/commands/set-url.ts](https://github.com/opalsecurity/opal-cli/blob/v2.0.13/src/commands/set-url.ts)_
258
262
 
259
263
  ## `opal ssh:copyFrom`
260
264
 
@@ -265,22 +269,23 @@ USAGE
265
269
  $ opal ssh:copyFrom
266
270
 
267
271
  OPTIONS
268
- -h, --help show CLI help
269
- --dest=dest [default: .] Pick which directory you want your files to be copied to.
270
- --id=id The ID of the Opal instance resource.
272
+ -h, --help show CLI help
273
+ --dest=dest [default: .] Pick which directory you want your files to be copied to.
274
+ --id=id The ID of the Opal instance resource.
275
+ --sessionId=sessionId SessionId of a session that has already been created via the web flow.
271
276
 
272
- --src=src (required) The path of the directory or file you would like to copy over SCP. Note we only support one
273
- file or directory at a time.
277
+ --src=src (required) The path of the directory or file you would like to copy over SCP. Note we only
278
+ support one file or directory at a time.
274
279
 
275
- --user=user [default: ssm-user] Pick which user you want to run SCP over. Keep in mind not all users will have access
276
- to each other's home directory.
280
+ --user=user [default: ssm-user] Pick which user you want to run SCP over. Keep in mind not all users will
281
+ have access to each other's home directory.
277
282
 
278
283
  EXAMPLES
279
284
  opal ssh:copyFrom --src instance/dir --dest my/dir
280
285
  opal ssh:copyFrom --src instance/dir --dest my/dir --id 51f7176b-0464-4a6f-8369-e951e187b398
281
286
  ```
282
287
 
283
- _See code: [src/commands/ssh/copyFrom.ts](https://github.com/opalsecurity/opal-cli/blob/v2.0.10/src/commands/ssh/copyFrom.ts)_
288
+ _See code: [src/commands/ssh/copyFrom.ts](https://github.com/opalsecurity/opal-cli/blob/v2.0.13/src/commands/ssh/copyFrom.ts)_
284
289
 
285
290
  ## `opal ssh:copyTo`
286
291
 
@@ -291,22 +296,23 @@ USAGE
291
296
  $ opal ssh:copyTo
292
297
 
293
298
  OPTIONS
294
- -h, --help show CLI help
295
- --dest=dest [default: .] Pick which directory you want your files to be copied to.
296
- --id=id The ID of the Opal instance resource.
299
+ -h, --help show CLI help
300
+ --dest=dest [default: .] Pick which directory you want your files to be copied to.
301
+ --id=id The ID of the Opal instance resource.
302
+ --sessionId=sessionId SessionId of a session that has already been created via the web flow.
297
303
 
298
- --src=src (required) The path of the directory or file you would like to copy over SCP. Note we only support one
299
- file or directory at a time.
304
+ --src=src (required) The path of the directory or file you would like to copy over SCP. Note we only
305
+ support one file or directory at a time.
300
306
 
301
- --user=user [default: ssm-user] Pick which user you want to run SCP over. Keep in mind not all users will have access
302
- to each other's home directory.
307
+ --user=user [default: ssm-user] Pick which user you want to run SCP over. Keep in mind not all users will
308
+ have access to each other's home directory.
303
309
 
304
310
  EXAMPLES
305
311
  opal ssh:copyTo --src my/dir --dest instance/dir
306
312
  opal ssh:copyTo --src my/dir --dest instance/dir --id 51f7176b-0464-4a6f-8369-e951e187b398
307
313
  ```
308
314
 
309
- _See code: [src/commands/ssh/copyTo.ts](https://github.com/opalsecurity/opal-cli/blob/v2.0.10/src/commands/ssh/copyTo.ts)_
315
+ _See code: [src/commands/ssh/copyTo.ts](https://github.com/opalsecurity/opal-cli/blob/v2.0.13/src/commands/ssh/copyTo.ts)_
310
316
 
311
317
  ## `opal ssh:start`
312
318
 
@@ -317,13 +323,14 @@ USAGE
317
323
  $ opal ssh:start
318
324
 
319
325
  OPTIONS
320
- -h, --help show CLI help
321
- --id=id The ID of the Opal instance resource.
326
+ -h, --help show CLI help
327
+ --id=id The ID of the Opal instance resource.
328
+ --sessionId=sessionId SessionId of a session that has already been created via the web flow.
322
329
 
323
330
  EXAMPLES
324
331
  opal ssh:start
325
332
  opal ssh:start --id 51f7176b-0464-4a6f-8369-e951e187b398
326
333
  ```
327
334
 
328
- _See code: [src/commands/ssh/start.ts](https://github.com/opalsecurity/opal-cli/blob/v2.0.10/src/commands/ssh/start.ts)_
335
+ _See code: [src/commands/ssh/start.ts](https://github.com/opalsecurity/opal-cli/blob/v2.0.13/src/commands/ssh/start.ts)_
329
336
  <!-- commandsstop -->
@@ -5,6 +5,7 @@ export default class StartIAMRoleSession extends Command {
5
5
  static flags: {
6
6
  help: import("@oclif/parser/lib/flags").IBooleanFlag<void>;
7
7
  id: flags.IOptionFlag<string | undefined>;
8
+ sessionId: flags.IOptionFlag<string | undefined>;
8
9
  };
9
10
  run(): Promise<void>;
10
11
  }
@@ -8,9 +8,10 @@ const inquirer = require("inquirer");
8
8
  const aws_1 = require("../../lib/aws");
9
9
  const resources_1 = require("../../lib/resources");
10
10
  const get_1 = require("../../commands/resources/get");
11
+ const common_1 = require("../../lib/common");
11
12
  const StartIAMRoleSessionDocument = `
12
- mutation StartIAMRoleSession($id: ResourceId!, $accessLevel: ResourceAccessLevelInput!) {
13
- createSession(input: {resourceId: $id, accessLevel: $accessLevel}) {
13
+ mutation StartIAMRoleSession($id: ResourceId!, $accessLevel: ResourceAccessLevelInput!, $sessionId: SessionId) {
14
+ createSession(input: {resourceId: $id, accessLevel: $accessLevel, sessionId: $sessionId}) {
14
15
  __typename
15
16
  ... on CreateSessionResult {
16
17
  session {
@@ -27,9 +28,18 @@ mutation StartIAMRoleSession($id: ResourceId!, $accessLevel: ResourceAccessLevel
27
28
  }
28
29
  }
29
30
  }
31
+ ... on SessionNotFoundError {
32
+ message
33
+ }
34
+ ... on MfaInvalidError {
35
+ message
36
+ }
30
37
  ... on ResourceNotFoundError {
31
38
  message
32
39
  }
40
+ ... on EndSystemAuthorizationError {
41
+ message
42
+ }
33
43
  }
34
44
  }`;
35
45
  const ListIamRolesDocument = `
@@ -51,6 +61,7 @@ class StartIAMRoleSession extends command_1.Command {
51
61
  const { flags } = this.parse(StartIAMRoleSession);
52
62
  let roleId = flags.id;
53
63
  let roleName = null;
64
+ const sessionId = flags.sessionId;
54
65
  if (!roleId) {
55
66
  const { resp: iamRolesResp, error } = await handler_1.runQuery({
56
67
  command: this,
@@ -106,7 +117,7 @@ class StartIAMRoleSession extends command_1.Command {
106
117
  const { resp, error } = await handler_1.runMutation({
107
118
  command: this,
108
119
  query: StartIAMRoleSessionDocument,
109
- variables: { id: roleId, accessLevel: cmd_1.DEFAULT_ACCESS_LEVEL },
120
+ variables: { id: roleId, accessLevel: cmd_1.DEFAULT_ACCESS_LEVEL, sessionId: sessionId },
110
121
  });
111
122
  switch (resp === null || resp === void 0 ? void 0 : resp.data.createSession.__typename) {
112
123
  case 'CreateSessionResult': {
@@ -125,6 +136,10 @@ class StartIAMRoleSession extends command_1.Command {
125
136
  }
126
137
  break;
127
138
  }
139
+ case 'MfaInvalidError': {
140
+ common_1.handleMfaRedirect(this, roleId);
141
+ break;
142
+ }
128
143
  default:
129
144
  apollo_1.printRequestOutput(this, resp, error);
130
145
  }
@@ -142,4 +157,8 @@ StartIAMRoleSession.flags = {
142
157
  multiple: false,
143
158
  description: 'The ID of the Opal role resource.',
144
159
  }),
160
+ sessionId: command_1.flags.string({
161
+ multiple: false,
162
+ description: 'SessionId of a session that has already been created via the web flow.',
163
+ }),
145
164
  };
@@ -6,6 +6,7 @@ export default class StartKubeIAMRoleSession extends Command {
6
6
  help: import("@oclif/parser/lib/flags").IBooleanFlag<void>;
7
7
  id: flags.IOptionFlag<string | undefined>;
8
8
  accessLevelRemoteId: flags.IOptionFlag<string | undefined>;
9
+ sessionId: flags.IOptionFlag<string | undefined>;
9
10
  };
10
11
  run(): Promise<void>;
11
12
  }
@@ -8,9 +8,10 @@ const inquirer = require("inquirer");
8
8
  const types_1 = require("../../types");
9
9
  const aws_1 = require("../../lib/aws");
10
10
  const resources_1 = require("../../lib/resources");
11
+ const common_1 = require("../../lib/common");
11
12
  const StartKubeIAMRoleSessionDocument = `
12
- mutation StartKubeIAMRoleSession($id: ResourceId!, $accessLevel: ResourceAccessLevelInput!) {
13
- createSession(input: {resourceId: $id, accessLevel: $accessLevel}) {
13
+ mutation StartKubeIAMRoleSession($id: ResourceId!, $accessLevel: ResourceAccessLevelInput!, $sessionId: SessionId) {
14
+ createSession(input: {resourceId: $id, accessLevel: $accessLevel, sessionId: $sessionId}) {
14
15
  __typename
15
16
  ... on CreateSessionResult {
16
17
  session {
@@ -27,9 +28,18 @@ mutation StartKubeIAMRoleSession($id: ResourceId!, $accessLevel: ResourceAccessL
27
28
  }
28
29
  }
29
30
  }
31
+ ... on SessionNotFoundError {
32
+ message
33
+ }
34
+ ... on MfaInvalidError {
35
+ message
36
+ }
30
37
  ... on ResourceNotFoundError {
31
38
  message
32
39
  }
40
+ ... on EndSystemAuthorizationError {
41
+ message
42
+ }
33
43
  }
34
44
  }`;
35
45
  const ListKubeIamRolesDocument = `
@@ -54,6 +64,7 @@ class StartKubeIAMRoleSession extends command_1.Command {
54
64
  const { flags } = this.parse(StartKubeIAMRoleSession);
55
65
  // TODO: RESOURCES-1: How do we grant access to a perm using ID
56
66
  let clusterId = flags.id;
67
+ const sessionId = flags.sessionId;
57
68
  if (!clusterId) {
58
69
  const { resp: kubeIamRolesResp, error } = await handler_1.runQuery({
59
70
  command: this,
@@ -101,7 +112,7 @@ class StartKubeIAMRoleSession extends command_1.Command {
101
112
  const { resp, error } = await handler_1.runMutation({
102
113
  command: this,
103
114
  query: StartKubeIAMRoleSessionDocument,
104
- variables: { id: clusterId, accessLevel },
115
+ variables: { id: clusterId, accessLevel, sessionId },
105
116
  });
106
117
  switch (resp === null || resp === void 0 ? void 0 : resp.data.createSession.__typename) {
107
118
  case 'CreateSessionResult': {
@@ -120,6 +131,10 @@ class StartKubeIAMRoleSession extends command_1.Command {
120
131
  }
121
132
  break;
122
133
  }
134
+ case 'MfaInvalidError': {
135
+ common_1.handleMfaRedirect(this, clusterId);
136
+ break;
137
+ }
123
138
  default:
124
139
  apollo_1.printRequestOutput(this, resp, error);
125
140
  }
@@ -142,4 +157,8 @@ StartKubeIAMRoleSession.flags = {
142
157
  multiple: false,
143
158
  description: 'The remote ID of the access level with which to access the cluster.',
144
159
  }),
160
+ sessionId: command_1.flags.string({
161
+ multiple: false,
162
+ description: 'SessionId of a session that has already been created via the web flow.',
163
+ }),
145
164
  };
@@ -10,9 +10,11 @@ const inquirer = require("inquirer");
10
10
  const handler_1 = require("../handler");
11
11
  const credentials_2 = require("../lib/credentials");
12
12
  const config_1 = require("../lib/config");
13
- const ISSUER = 'https://auth.opal.dev';
13
+ const ISSUER_PROD = 'https://auth.opal.dev';
14
+ const ISSUER_DEV = 'https://authdev.opal.dev';
14
15
  const GRANT_TYPE = 'urn:ietf:params:oauth:grant-type:device_code';
15
- const CLIENT_ID = '42rm6E5v7o67LBpRfjdT9KhnjrQHr9UF';
16
+ const CLIENT_ID_PROD = '42rm6E5v7o67LBpRfjdT9KhnjrQHr9UF';
17
+ const CLIENT_ID_DEV = 'XYV8qoAvZG7dHnhRp2g5XMJ1zX9fBP6s';
16
18
  const CLISignInMethodDocument = `
17
19
  query CLISignInMethod($input: SignInMethodInput!) {
18
20
  signInMethod(input: $input) {
@@ -41,52 +43,69 @@ class Login extends command_1.Command {
41
43
  var _a, _b, _c, _d, _e;
42
44
  try {
43
45
  await apollo_1.initClient(this);
46
+ let email;
47
+ let organizationID;
44
48
  if (await credentials_2.cred.accessToken) {
45
- this.log('Please use `opal logout` to log out before logging in.');
46
- return;
49
+ email = await credentials_2.cred.email;
50
+ organizationID = await credentials_2.cred.organizationID;
51
+ await credentials_2.cred.removeCredentials(-1);
47
52
  }
48
53
  const configDir = this.config.configDir;
49
54
  const configData = config_1.getOrCreateConfigData(configDir);
50
- this.log('Welcome to Opal! ⚡️\n');
51
- this.log('Please confirm your Opal instance URL:', configData[config_1.urlKey]);
52
- this.log('If this is not correct, please first use `opal set-url --help`\n');
53
- const { email } = await inquirer.prompt([{
54
- name: 'email',
55
- message: 'Enter your email:',
56
- type: 'input',
57
- validate: email => Boolean(email),
58
- }]);
59
- const { resp: signInOrganizationsResponse, error } = await handler_1.runQuery({
60
- command: this,
61
- query: CLISignInMethodDocument,
62
- variables: { input: { email } },
63
- });
64
- if (error) {
65
- this.log('Could not connect to Opal. Did you set the right URL? (`opal set-url --help`)');
55
+ if (email && organizationID) {
56
+ console.log('Signing in as ' + email + ' - to use a different account, run `opal logout`');
66
57
  }
67
- const signInOrganizations = (_b = (_a = signInOrganizationsResponse === null || signInOrganizationsResponse === void 0 ? void 0 : signInOrganizationsResponse.data) === null || _a === void 0 ? void 0 : _a.signInMethod) === null || _b === void 0 ? void 0 : _b.signInOrganizations;
68
- let organizationID = '';
69
- if (signInOrganizations) {
70
- if (signInOrganizations.length === 1) {
71
- organizationID = signInOrganizations[0].organizationId;
58
+ else {
59
+ this.log('Welcome to Opal! ⚡️\n');
60
+ this.log('Please confirm your Opal instance URL:', configData[config_1.urlKey]);
61
+ this.log('If this is not correct, please first use `opal set-url --help`\n');
62
+ const { email: promptEmail } = await inquirer.prompt([{
63
+ name: 'email',
64
+ message: 'Enter your email:',
65
+ type: 'input',
66
+ validate: email => Boolean(email),
67
+ }]);
68
+ email = promptEmail;
69
+ const { resp: signInOrganizationsResponse, error } = await handler_1.runQuery({
70
+ command: this,
71
+ query: CLISignInMethodDocument,
72
+ variables: { input: { email } },
73
+ });
74
+ if (error) {
75
+ this.log('Could not connect to Opal. Did you set the right URL? (`opal set-url --help`)');
72
76
  }
73
- else {
74
- const responses = await inquirer.prompt([{
75
- name: 'organizationID',
76
- message: 'Select an organization:',
77
- type: 'list',
78
- choices: signInOrganizations.map(signInOrganization => ({
79
- name: signInOrganization.organizationName,
80
- value: signInOrganization.organizationId,
81
- })),
82
- }]);
83
- organizationID = responses.organizationID;
77
+ const signInOrganizations = (_b = (_a = signInOrganizationsResponse === null || signInOrganizationsResponse === void 0 ? void 0 : signInOrganizationsResponse.data) === null || _a === void 0 ? void 0 : _a.signInMethod) === null || _b === void 0 ? void 0 : _b.signInOrganizations;
78
+ if (signInOrganizations) {
79
+ if (signInOrganizations.length === 1) {
80
+ organizationID = signInOrganizations[0].organizationId;
81
+ }
82
+ else {
83
+ const responses = await inquirer.prompt([{
84
+ name: 'organizationID',
85
+ message: 'Select an organization:',
86
+ type: 'list',
87
+ choices: signInOrganizations.map(signInOrganization => ({
88
+ name: signInOrganization.organizationName,
89
+ value: signInOrganization.organizationId,
90
+ })),
91
+ }]);
92
+ organizationID = responses.organizationID;
93
+ }
84
94
  }
85
95
  }
86
- const issuer = await openid_client_1.Issuer.discover(ISSUER);
96
+ let issuer;
97
+ let clientId;
98
+ if (config_1.isProduction(this.config.configDir)) {
99
+ issuer = await openid_client_1.Issuer.discover(ISSUER_PROD);
100
+ clientId = CLIENT_ID_PROD;
101
+ }
102
+ else {
103
+ issuer = await openid_client_1.Issuer.discover(ISSUER_DEV);
104
+ clientId = CLIENT_ID_DEV;
105
+ }
87
106
  const client = new issuer.Client({
88
107
  grant_types: [GRANT_TYPE],
89
- client_id: CLIENT_ID,
108
+ client_id: clientId,
90
109
  response_types: [],
91
110
  redirect_uris: [],
92
111
  token_endpoint_auth_method: 'none',
@@ -6,6 +6,7 @@ export default class StartPostgresInstanceSession extends Command {
6
6
  help: import("@oclif/parser/lib/flags").IBooleanFlag<void>;
7
7
  id: flags.IOptionFlag<string | undefined>;
8
8
  accessLevelRemoteId: flags.IOptionFlag<string | undefined>;
9
+ sessionId: flags.IOptionFlag<string | undefined>;
9
10
  };
10
11
  run(): Promise<void>;
11
12
  }
@@ -6,6 +6,7 @@ const cmd_1 = require("../../lib/cmd");
6
6
  const apollo_1 = require("../../lib/apollo");
7
7
  const inquirer = require("inquirer");
8
8
  const resources_1 = require("../../lib/resources");
9
+ const common_1 = require("../../lib/common");
9
10
  const ListPostgresInstancesDocument = `
10
11
  query ListPostgresInstances {
11
12
  resources(input: {serviceType: POSTGRES, onlyMine: true, maxNumEntries: 1000}) {
@@ -20,8 +21,8 @@ query ListPostgresInstances {
20
21
  }
21
22
  }`;
22
23
  const StartPostgresInstanceSessionDocument = `
23
- mutation StartPostgresInstanceSession($id: ResourceId!, $accessLevel: ResourceAccessLevelInput!) {
24
- createSession(input: {resourceId: $id, accessLevel: $accessLevel}) {
24
+ mutation StartPostgresInstanceSession($id: ResourceId!, $accessLevel: ResourceAccessLevelInput!, $sessionId: SessionId) {
25
+ createSession(input: {resourceId: $id, accessLevel: $accessLevel, sessionId: $sessionId}) {
25
26
  __typename
26
27
  ... on CreateSessionResult {
27
28
  session {
@@ -38,9 +39,18 @@ mutation StartPostgresInstanceSession($id: ResourceId!, $accessLevel: ResourceAc
38
39
  }
39
40
  }
40
41
  }
42
+ ... on SessionNotFoundError {
43
+ message
44
+ }
45
+ ... on MfaInvalidError {
46
+ message
47
+ }
41
48
  ... on ResourceNotFoundError {
42
49
  message
43
50
  }
51
+ ... on EndSystemAuthorizationError {
52
+ message
53
+ }
44
54
  }
45
55
  }`;
46
56
  class StartPostgresInstanceSession extends command_1.Command {
@@ -49,6 +59,7 @@ class StartPostgresInstanceSession extends command_1.Command {
49
59
  const { flags } = this.parse(StartPostgresInstanceSession);
50
60
  let instanceId = flags.id;
51
61
  let instanceName = null;
62
+ const sessionId = flags.sessionId;
52
63
  // TODO: RESOURCES-1: How do we grant access to a perm using ID
53
64
  if (!instanceId) {
54
65
  const { resp: postgresInstancesResp, error } = await handler_1.runQuery({
@@ -100,6 +111,7 @@ class StartPostgresInstanceSession extends command_1.Command {
100
111
  variables: {
101
112
  id: instanceId,
102
113
  accessLevel,
114
+ sessionId,
103
115
  },
104
116
  });
105
117
  switch (resp === null || resp === void 0 ? void 0 : resp.data.createSession.__typename) {
@@ -138,6 +150,10 @@ class StartPostgresInstanceSession extends command_1.Command {
138
150
  }
139
151
  break;
140
152
  }
153
+ case 'MfaInvalidError': {
154
+ common_1.handleMfaRedirect(this, instanceId);
155
+ break;
156
+ }
141
157
  default:
142
158
  apollo_1.printRequestOutput(this, resp, error);
143
159
  }
@@ -160,4 +176,8 @@ StartPostgresInstanceSession.flags = {
160
176
  multiple: false,
161
177
  description: 'The remote ID of the access level with which to access the database.',
162
178
  }),
179
+ sessionId: command_1.flags.string({
180
+ multiple: false,
181
+ description: 'SessionId of a session that has already been created via the web flow.',
182
+ }),
163
183
  };
@@ -7,6 +7,7 @@ export default class SetUrl extends Command {
7
7
  custom: flags.IOptionFlag<string | undefined>;
8
8
  allowSelfSignedCerts: import("@oclif/parser/lib/flags").IBooleanFlag<boolean>;
9
9
  prod: import("@oclif/parser/lib/flags").IBooleanFlag<boolean>;
10
+ staging: import("@oclif/parser/lib/flags").IBooleanFlag<boolean>;
10
11
  demo: import("@oclif/parser/lib/flags").IBooleanFlag<boolean>;
11
12
  dev: import("@oclif/parser/lib/flags").IBooleanFlag<boolean>;
12
13
  devLocal: import("@oclif/parser/lib/flags").IBooleanFlag<boolean>;
@@ -14,6 +14,9 @@ class SetUrl extends command_1.Command {
14
14
  else if (flags.prod) {
15
15
  url = 'https://app.opal.dev';
16
16
  }
17
+ else if (flags.staging) {
18
+ url = 'https://staging.opal.dev';
19
+ }
17
20
  else if (flags.demo) {
18
21
  url = 'https://demo.opal.dev';
19
22
  }
@@ -46,6 +49,7 @@ SetUrl.flags = {
46
49
  }),
47
50
  allowSelfSignedCerts: command_1.flags.boolean(),
48
51
  prod: command_1.flags.boolean(),
52
+ staging: command_1.flags.boolean(),
49
53
  demo: command_1.flags.boolean(),
50
54
  dev: command_1.flags.boolean(),
51
55
  devLocal: command_1.flags.boolean(),
@@ -8,6 +8,7 @@ export default class StartSCPSession extends Command {
8
8
  dest: flags.IOptionFlag<string>;
9
9
  user: flags.IOptionFlag<string>;
10
10
  id: flags.IOptionFlag<string | undefined>;
11
+ sessionId: flags.IOptionFlag<string | undefined>;
11
12
  };
12
13
  run(): Promise<void>;
13
14
  }
@@ -5,9 +5,10 @@ const handler_1 = require("../../handler");
5
5
  const apollo_1 = require("../../lib/apollo");
6
6
  const cmd_1 = require("../../lib/cmd");
7
7
  const ssh_1 = require("../../lib/ssh");
8
+ const common_1 = require("../../lib/common");
8
9
  const StartSSHSessionDocument = `
9
- mutation StartSSHSession($id: ResourceId!, $accessLevel: ResourceAccessLevelInput!) {
10
- createSession(input: {resourceId: $id, accessLevel: $accessLevel}) {
10
+ mutation StartSSHSession($id: ResourceId!, $accessLevel: ResourceAccessLevelInput!, $sessionId: SessionId) {
11
+ createSession(input: {resourceId: $id, accessLevel: $accessLevel, sessionId: $sessionId}) {
11
12
  __typename
12
13
  ... on CreateSessionResult {
13
14
  session {
@@ -26,9 +27,18 @@ mutation StartSSHSession($id: ResourceId!, $accessLevel: ResourceAccessLevelInpu
26
27
  }
27
28
  }
28
29
  }
30
+ ... on SessionNotFoundError {
31
+ message
32
+ }
33
+ ... on MfaInvalidError {
34
+ message
35
+ }
29
36
  ... on ResourceNotFoundError {
30
37
  message
31
38
  }
39
+ ... on EndSystemAuthorizationError {
40
+ message
41
+ }
32
42
  }
33
43
  }`;
34
44
  class StartSCPSession extends command_1.Command {
@@ -41,6 +51,7 @@ class StartSCPSession extends command_1.Command {
41
51
  }
42
52
  let instanceId = flags.id;
43
53
  let instanceName = null;
54
+ const sessionId = flags.sessionId;
44
55
  if (!instanceId) {
45
56
  const selectedInstance = await ssh_1.selectComputeInstance(this, 'SCP into');
46
57
  if (!selectedInstance) {
@@ -52,7 +63,7 @@ class StartSCPSession extends command_1.Command {
52
63
  const { resp, error } = await handler_1.runMutation({
53
64
  command: this,
54
65
  query: StartSSHSessionDocument,
55
- variables: { id: instanceId, accessLevel: cmd_1.DEFAULT_ACCESS_LEVEL },
66
+ variables: { id: instanceId, accessLevel: cmd_1.DEFAULT_ACCESS_LEVEL, sessionId },
56
67
  });
57
68
  switch (resp === null || resp === void 0 ? void 0 : resp.data.createSession.__typename) {
58
69
  case 'CreateSessionResult': {
@@ -75,6 +86,10 @@ class StartSCPSession extends command_1.Command {
75
86
  }
76
87
  break;
77
88
  }
89
+ case 'MfaInvalidError': {
90
+ common_1.handleMfaRedirect(this, instanceId);
91
+ break;
92
+ }
78
93
  default:
79
94
  apollo_1.printRequestOutput(this, resp, error);
80
95
  }
@@ -109,4 +124,8 @@ StartSCPSession.flags = {
109
124
  multiple: false,
110
125
  description: 'The ID of the Opal instance resource.',
111
126
  }),
127
+ sessionId: command_1.flags.string({
128
+ multiple: false,
129
+ description: 'SessionId of a session that has already been created via the web flow.',
130
+ }),
112
131
  };
@@ -8,6 +8,7 @@ export default class StartSCPSession extends Command {
8
8
  dest: flags.IOptionFlag<string>;
9
9
  user: flags.IOptionFlag<string>;
10
10
  id: flags.IOptionFlag<string | undefined>;
11
+ sessionId: flags.IOptionFlag<string | undefined>;
11
12
  };
12
13
  run(): Promise<void>;
13
14
  }
@@ -5,9 +5,10 @@ const handler_1 = require("../../handler");
5
5
  const apollo_1 = require("../../lib/apollo");
6
6
  const cmd_1 = require("../../lib/cmd");
7
7
  const ssh_1 = require("../../lib/ssh");
8
+ const common_1 = require("../../lib/common");
8
9
  const StartSSHSessionDocument = `
9
- mutation StartSSHSession($id: ResourceId!, $accessLevel: ResourceAccessLevelInput!) {
10
- createSession(input: {resourceId: $id, accessLevel: $accessLevel}) {
10
+ mutation StartSSHSession($id: ResourceId!, $accessLevel: ResourceAccessLevelInput!, $sessionId: SessionId) {
11
+ createSession(input: {resourceId: $id, accessLevel: $accessLevel, sessionId: $sessionId}) {
11
12
  __typename
12
13
  ... on CreateSessionResult {
13
14
  session {
@@ -26,9 +27,18 @@ mutation StartSSHSession($id: ResourceId!, $accessLevel: ResourceAccessLevelInpu
26
27
  }
27
28
  }
28
29
  }
30
+ ... on SessionNotFoundError {
31
+ message
32
+ }
33
+ ... on MfaInvalidError {
34
+ message
35
+ }
29
36
  ... on ResourceNotFoundError {
30
37
  message
31
38
  }
39
+ ... on EndSystemAuthorizationError {
40
+ message
41
+ }
32
42
  }
33
43
  }`;
34
44
  class StartSCPSession extends command_1.Command {
@@ -41,6 +51,7 @@ class StartSCPSession extends command_1.Command {
41
51
  }
42
52
  let instanceId = flags.id;
43
53
  let instanceName = null;
54
+ const sessionId = flags.sessionId;
44
55
  if (!instanceId) {
45
56
  const selectedInstance = await ssh_1.selectComputeInstance(this, 'SCP into');
46
57
  if (!selectedInstance) {
@@ -52,7 +63,7 @@ class StartSCPSession extends command_1.Command {
52
63
  const { resp, error } = await handler_1.runMutation({
53
64
  command: this,
54
65
  query: StartSSHSessionDocument,
55
- variables: { id: instanceId, accessLevel: cmd_1.DEFAULT_ACCESS_LEVEL },
66
+ variables: { id: instanceId, accessLevel: cmd_1.DEFAULT_ACCESS_LEVEL, sessionId },
56
67
  });
57
68
  switch (resp === null || resp === void 0 ? void 0 : resp.data.createSession.__typename) {
58
69
  case 'CreateSessionResult': {
@@ -75,6 +86,10 @@ class StartSCPSession extends command_1.Command {
75
86
  }
76
87
  break;
77
88
  }
89
+ case 'MfaInvalidError': {
90
+ common_1.handleMfaRedirect(this, instanceId);
91
+ break;
92
+ }
78
93
  default:
79
94
  apollo_1.printRequestOutput(this, resp, error);
80
95
  }
@@ -109,4 +124,8 @@ StartSCPSession.flags = {
109
124
  multiple: false,
110
125
  description: 'The ID of the Opal instance resource.',
111
126
  }),
127
+ sessionId: command_1.flags.string({
128
+ multiple: false,
129
+ description: 'SessionId of a session that has already been created via the web flow.',
130
+ }),
112
131
  };
@@ -5,6 +5,7 @@ export default class StartSSHSession extends Command {
5
5
  static flags: {
6
6
  help: import("@oclif/parser/lib/flags").IBooleanFlag<void>;
7
7
  id: flags.IOptionFlag<string | undefined>;
8
+ sessionId: flags.IOptionFlag<string | undefined>;
8
9
  };
9
10
  run(): Promise<void>;
10
11
  }
@@ -7,9 +7,10 @@ const apollo_1 = require("../../lib/apollo");
7
7
  const ssh_1 = require("../../lib/ssh");
8
8
  const get_1 = require("../../commands/resources/get");
9
9
  const aws_1 = require("../../lib/aws");
10
+ const common_1 = require("../../lib/common");
10
11
  const StartSSHSessionDocument = `
11
- mutation StartSSHSession($id: ResourceId!, $accessLevel: ResourceAccessLevelInput!) {
12
- createSession(input: {resourceId: $id, accessLevel: $accessLevel}) {
12
+ mutation StartSSHSession($id: ResourceId!, $accessLevel: ResourceAccessLevelInput!, $sessionId: SessionId) {
13
+ createSession(input: {resourceId: $id, accessLevel: $accessLevel, sessionId: $sessionId}) {
13
14
  __typename
14
15
  ... on CreateSessionResult {
15
16
  session {
@@ -28,9 +29,18 @@ mutation StartSSHSession($id: ResourceId!, $accessLevel: ResourceAccessLevelInpu
28
29
  }
29
30
  }
30
31
  }
32
+ ... on SessionNotFoundError {
33
+ message
34
+ }
35
+ ... on MfaInvalidError {
36
+ message
37
+ }
31
38
  ... on ResourceNotFoundError {
32
39
  message
33
40
  }
41
+ ... on EndSystemAuthorizationError {
42
+ message
43
+ }
34
44
  }
35
45
  }`;
36
46
  class StartSSHSession extends command_1.Command {
@@ -43,6 +53,7 @@ class StartSSHSession extends command_1.Command {
43
53
  }
44
54
  let instanceId = flags.id;
45
55
  let instanceName = null;
56
+ const sessionId = flags.sessionId;
46
57
  // TODO: RESOURCES-1: How do we grant access to a perm using ID
47
58
  if (!instanceId) {
48
59
  const selectedInstance = await ssh_1.selectComputeInstance(this, 'SSH into');
@@ -69,7 +80,7 @@ class StartSSHSession extends command_1.Command {
69
80
  const { resp, error } = await handler_1.runMutation({
70
81
  command: this,
71
82
  query: StartSSHSessionDocument,
72
- variables: { id: instanceId, accessLevel: cmd_1.DEFAULT_ACCESS_LEVEL },
83
+ variables: { id: instanceId, accessLevel: cmd_1.DEFAULT_ACCESS_LEVEL, sessionId },
73
84
  });
74
85
  switch (resp === null || resp === void 0 ? void 0 : resp.data.createSession.__typename) {
75
86
  case 'CreateSessionResult': {
@@ -90,6 +101,10 @@ class StartSSHSession extends command_1.Command {
90
101
  }
91
102
  break;
92
103
  }
104
+ case 'MfaInvalidError': {
105
+ common_1.handleMfaRedirect(this, instanceId);
106
+ break;
107
+ }
93
108
  default:
94
109
  apollo_1.printRequestOutput(this, resp, error);
95
110
  }
@@ -107,4 +122,14 @@ StartSSHSession.flags = {
107
122
  multiple: false,
108
123
  description: 'The ID of the Opal instance resource.',
109
124
  }),
125
+ // TODO: Unfortunately allowing SSM over SSH disables logging
126
+ // user: flags.string({
127
+ // multiple: false,
128
+ // required: false,
129
+ // default: "ssm-user",
130
+ // }),
131
+ sessionId: command_1.flags.string({
132
+ multiple: false,
133
+ description: 'SessionId of a session that has already been created via the web flow.',
134
+ }),
110
135
  };
@@ -0,0 +1,2 @@
1
+ import { Command } from '@oclif/command';
2
+ export declare const handleMfaRedirect: (command: Command, resourceId: string) => void;
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.handleMfaRedirect = void 0;
4
+ const config_1 = require("./config");
5
+ const open = require("open");
6
+ exports.handleMfaRedirect = (command, resourceId) => {
7
+ command.log('❗ MFA validation needed. Please connect via browser. Redirecting...');
8
+ const configData = config_1.getOrCreateConfigData(command.config.configDir);
9
+ const url = configData[config_1.urlKey];
10
+ setTimeout(() => {
11
+ open(url + `/resources/${resourceId}?showModal=true`);
12
+ }, 2000);
13
+ };
@@ -4,3 +4,4 @@ export declare const allowSelfSignedCertsKey = "allowSelfSignedCerts";
4
4
  export declare const defaultAllowSelfSignedCerts = false;
5
5
  export declare const getOrCreateConfigData: (configDir: string) => Record<string, any>;
6
6
  export declare const writeConfigData: (configDir: string, newConfigData: Record<string, any>) => void;
7
+ export declare const isProduction: (configDir: string) => boolean;
package/lib/lib/config.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.writeConfigData = exports.getOrCreateConfigData = exports.defaultAllowSelfSignedCerts = exports.allowSelfSignedCertsKey = exports.defaultUrl = exports.urlKey = void 0;
3
+ exports.isProduction = exports.writeConfigData = exports.getOrCreateConfigData = exports.defaultAllowSelfSignedCerts = exports.allowSelfSignedCertsKey = exports.defaultUrl = exports.urlKey = void 0;
4
4
  const fs = require("fs");
5
5
  const path = require("path");
6
6
  exports.urlKey = 'url';
@@ -50,3 +50,12 @@ exports.writeConfigData = (configDir, newConfigData) => {
50
50
  mode: 0o0600,
51
51
  });
52
52
  };
53
+ exports.isProduction = (configDir) => {
54
+ const configData = exports.getOrCreateConfigData(configDir);
55
+ // Custom URLs are considered production since it includes on-prem
56
+ return configData[exports.urlKey] !== 'https://dev.opal.dev' &&
57
+ configData[exports.urlKey] !== 'http://localhost:3000' &&
58
+ configData[exports.urlKey] !== 'http://localhost:4000' &&
59
+ configData[exports.urlKey] !== 'https://demo.opal.dev' &&
60
+ configData[exports.urlKey] !== 'https://staging.opal.dev';
61
+ };
@@ -3,5 +3,6 @@ export declare const cred: {
3
3
  removeCredentials(after: number): Promise<void>;
4
4
  readonly accountId: Promise<string | undefined>;
5
5
  readonly organizationID: Promise<string | undefined>;
6
+ readonly email: Promise<string | undefined>;
6
7
  readonly accessToken: Promise<string | undefined>;
7
8
  };
@@ -50,6 +50,25 @@ exports.cred = {
50
50
  }
51
51
  })();
52
52
  },
53
+ get email() {
54
+ return (async () => {
55
+ try {
56
+ const keyContents = await keytar.findCredentials(exports.OPAL_CREDS_KEY);
57
+ if (!keyContents[0]) {
58
+ return undefined;
59
+ }
60
+ const { account } = keyContents[0];
61
+ const parts = account.split('|');
62
+ if (!parts || parts.length <= 1) {
63
+ return undefined;
64
+ }
65
+ return parts[0];
66
+ }
67
+ catch (error) {
68
+ throw error;
69
+ }
70
+ })();
71
+ },
53
72
  get accessToken() {
54
73
  return (async () => {
55
74
  try {
@@ -1 +1 @@
1
- {"version":"2.0.10","commands":{"curl-example":{"id":"curl-example","description":"Prints out an example cURL command containing the parameters the CLI uses to query the Opal server.","pluginName":"opal-security","pluginType":"core","aliases":[],"flags":{"help":{"name":"help","type":"boolean","char":"h","description":"show CLI help","allowNo":false}},"args":[]},"login":{"id":"login","description":"Authenticates you with the Opal server.","pluginName":"opal-security","pluginType":"core","aliases":[],"examples":["$ opal login"],"flags":{"help":{"name":"help","type":"boolean","char":"h","description":"show CLI help","allowNo":false}},"args":[]},"logout":{"id":"logout","description":"Clears locally stored Opal server authentication credentials.","pluginName":"opal-security","pluginType":"core","aliases":[],"examples":["$ opal logout"],"flags":{"help":{"name":"help","type":"boolean","char":"h","description":"show CLI help","allowNo":false}},"args":[]},"set-url":{"id":"set-url","description":"Sets the url of the Opal server. Defaults to https://app.opal.dev.","pluginName":"opal-security","pluginType":"core","aliases":[],"examples":["$ opal set-host"],"flags":{"help":{"name":"help","type":"boolean","char":"h","description":"show CLI help","allowNo":false},"custom":{"name":"custom","type":"option"},"allowSelfSignedCerts":{"name":"allowSelfSignedCerts","type":"boolean","allowNo":false},"prod":{"name":"prod","type":"boolean","allowNo":false},"demo":{"name":"demo","type":"boolean","allowNo":false},"dev":{"name":"dev","type":"boolean","allowNo":false},"devLocal":{"name":"devLocal","type":"boolean","allowNo":false}},"args":[]},"aws:identity":{"id":"aws:identity","description":"Gets the current caller identity for the \"opal\" AWS profile.","pluginName":"opal-security","pluginType":"core","aliases":[],"examples":["opal aws:identity"],"flags":{"help":{"name":"help","type":"boolean","char":"h","description":"show CLI help","allowNo":false}},"args":[]},"iam-roles:start":{"id":"iam-roles:start","description":"Starts a session to assume an IAM role.","pluginName":"opal-security","pluginType":"core","aliases":[],"examples":["opal iam-roles:start","opal iam-roles:start --id 51f7176b-0464-4a6f-8369-e951e187b398"],"flags":{"help":{"name":"help","type":"boolean","char":"h","description":"show CLI help","allowNo":false},"id":{"name":"id","type":"option","description":"The ID of the Opal role resource."}},"args":[]},"kube-roles:start":{"id":"kube-roles:start","description":"Starts a session to assume a Kubernetes cluster IAM role.","pluginName":"opal-security","pluginType":"core","aliases":[],"examples":["opal kube-roles:start","opal kube-roles:start --id 51f7176b-0464-4a6f-8369-e951e187b398","opal kube-roles:start --id 51f7176b-0464-4a6f-8369-e951e187b398 --accessLevelRemoteId \"arn:aws:iam::712234975475:role/acme-eks-cluster-admin-role\""],"flags":{"help":{"name":"help","type":"boolean","char":"h","description":"show CLI help","allowNo":false},"id":{"name":"id","type":"option","description":"The ID of the Opal role resource."},"accessLevelRemoteId":{"name":"accessLevelRemoteId","type":"option","description":"The remote ID of the access level with which to access the cluster."}},"args":[]},"postgres-instances:start":{"id":"postgres-instances:start","description":"Starts a session to query a Postgres database.","pluginName":"opal-security","pluginType":"core","aliases":[],"examples":["opal postgres-instances:start","opal postgres-instances:start --id 51f7176b-0464-4a6f-8369-e951e187b398","opal postgres-instances:start --id 51f7176b-0464-4a6f-8369-e951e187b398 --accessLevelRemoteId \"fullaccess\""],"flags":{"help":{"name":"help","type":"boolean","char":"h","description":"show CLI help","allowNo":false},"id":{"name":"id","type":"option","description":"The ID of the Opal instance resource."},"accessLevelRemoteId":{"name":"accessLevelRemoteId","type":"option","description":"The remote ID of the access level with which to access the database."}},"args":[]},"resources:get":{"id":"resources:get","description":"Get resource info for a particular resource.","pluginName":"opal-security","pluginType":"core","aliases":[],"examples":["opal resources:get --id 54052a3e-5375-4392-aeaf-0c6c44c131d4"],"flags":{"help":{"name":"help","type":"boolean","char":"h","description":"show CLI help","allowNo":false},"id":{"name":"id","type":"option","required":true}},"args":[]},"ssh:copyFrom":{"id":"ssh:copyFrom","description":"Use SCP to copy files from a compute instance.","pluginName":"opal-security","pluginType":"core","aliases":[],"examples":["opal ssh:copyFrom --src instance/dir --dest my/dir","opal ssh:copyFrom --src instance/dir --dest my/dir --id 51f7176b-0464-4a6f-8369-e951e187b398"],"flags":{"help":{"name":"help","type":"boolean","char":"h","description":"show CLI help","allowNo":false},"src":{"name":"src","type":"option","description":"The path of the directory or file you would like to copy over SCP. Note we only support one file or directory at a time.","required":true},"dest":{"name":"dest","type":"option","description":"Pick which directory you want your files to be copied to.","required":false,"default":"."},"user":{"name":"user","type":"option","description":"Pick which user you want to run SCP over. Keep in mind not all users will have access to each other's home directory.","required":false,"default":"ssm-user"},"id":{"name":"id","type":"option","description":"The ID of the Opal instance resource."}},"args":[]},"ssh:copyTo":{"id":"ssh:copyTo","description":"Use SCP to copy files to a compute instance.","pluginName":"opal-security","pluginType":"core","aliases":[],"examples":["opal ssh:copyTo --src my/dir --dest instance/dir","opal ssh:copyTo --src my/dir --dest instance/dir --id 51f7176b-0464-4a6f-8369-e951e187b398"],"flags":{"help":{"name":"help","type":"boolean","char":"h","description":"show CLI help","allowNo":false},"src":{"name":"src","type":"option","description":"The path of the directory or file you would like to copy over SCP. Note we only support one file or directory at a time.","required":true},"dest":{"name":"dest","type":"option","description":"Pick which directory you want your files to be copied to.","required":false,"default":"."},"user":{"name":"user","type":"option","description":"Pick which user you want to run SCP over. Keep in mind not all users will have access to each other's home directory.","required":false,"default":"ssm-user"},"id":{"name":"id","type":"option","description":"The ID of the Opal instance resource."}},"args":[]},"ssh:start":{"id":"ssh:start","description":"Start an SSH session to access a particular compute instance.","pluginName":"opal-security","pluginType":"core","aliases":[],"examples":["opal ssh:start","opal ssh:start --id 51f7176b-0464-4a6f-8369-e951e187b398"],"flags":{"help":{"name":"help","type":"boolean","char":"h","description":"show CLI help","allowNo":false},"id":{"name":"id","type":"option","description":"The ID of the Opal instance resource."}},"args":[]}}}
1
+ {"version":"2.0.13","commands":{"curl-example":{"id":"curl-example","description":"Prints out an example cURL command containing the parameters the CLI uses to query the Opal server.","pluginName":"opal-security","pluginType":"core","aliases":[],"flags":{"help":{"name":"help","type":"boolean","char":"h","description":"show CLI help","allowNo":false}},"args":[]},"login":{"id":"login","description":"Authenticates you with the Opal server.","pluginName":"opal-security","pluginType":"core","aliases":[],"examples":["$ opal login"],"flags":{"help":{"name":"help","type":"boolean","char":"h","description":"show CLI help","allowNo":false}},"args":[]},"logout":{"id":"logout","description":"Clears locally stored Opal server authentication credentials.","pluginName":"opal-security","pluginType":"core","aliases":[],"examples":["$ opal logout"],"flags":{"help":{"name":"help","type":"boolean","char":"h","description":"show CLI help","allowNo":false}},"args":[]},"set-url":{"id":"set-url","description":"Sets the url of the Opal server. Defaults to https://app.opal.dev.","pluginName":"opal-security","pluginType":"core","aliases":[],"examples":["$ opal set-host"],"flags":{"help":{"name":"help","type":"boolean","char":"h","description":"show CLI help","allowNo":false},"custom":{"name":"custom","type":"option"},"allowSelfSignedCerts":{"name":"allowSelfSignedCerts","type":"boolean","allowNo":false},"prod":{"name":"prod","type":"boolean","allowNo":false},"staging":{"name":"staging","type":"boolean","allowNo":false},"demo":{"name":"demo","type":"boolean","allowNo":false},"dev":{"name":"dev","type":"boolean","allowNo":false},"devLocal":{"name":"devLocal","type":"boolean","allowNo":false}},"args":[]},"aws:identity":{"id":"aws:identity","description":"Gets the current caller identity for the \"opal\" AWS profile.","pluginName":"opal-security","pluginType":"core","aliases":[],"examples":["opal aws:identity"],"flags":{"help":{"name":"help","type":"boolean","char":"h","description":"show CLI help","allowNo":false}},"args":[]},"iam-roles:start":{"id":"iam-roles:start","description":"Starts a session to assume an IAM role.","pluginName":"opal-security","pluginType":"core","aliases":[],"examples":["opal iam-roles:start","opal iam-roles:start --id 51f7176b-0464-4a6f-8369-e951e187b398"],"flags":{"help":{"name":"help","type":"boolean","char":"h","description":"show CLI help","allowNo":false},"id":{"name":"id","type":"option","description":"The ID of the Opal role resource."},"sessionId":{"name":"sessionId","type":"option","description":"SessionId of a session that has already been created via the web flow."}},"args":[]},"kube-roles:start":{"id":"kube-roles:start","description":"Starts a session to assume a Kubernetes cluster IAM role.","pluginName":"opal-security","pluginType":"core","aliases":[],"examples":["opal kube-roles:start","opal kube-roles:start --id 51f7176b-0464-4a6f-8369-e951e187b398","opal kube-roles:start --id 51f7176b-0464-4a6f-8369-e951e187b398 --accessLevelRemoteId \"arn:aws:iam::712234975475:role/acme-eks-cluster-admin-role\""],"flags":{"help":{"name":"help","type":"boolean","char":"h","description":"show CLI help","allowNo":false},"id":{"name":"id","type":"option","description":"The ID of the Opal role resource."},"accessLevelRemoteId":{"name":"accessLevelRemoteId","type":"option","description":"The remote ID of the access level with which to access the cluster."},"sessionId":{"name":"sessionId","type":"option","description":"SessionId of a session that has already been created via the web flow."}},"args":[]},"postgres-instances:start":{"id":"postgres-instances:start","description":"Starts a session to query a Postgres database.","pluginName":"opal-security","pluginType":"core","aliases":[],"examples":["opal postgres-instances:start","opal postgres-instances:start --id 51f7176b-0464-4a6f-8369-e951e187b398","opal postgres-instances:start --id 51f7176b-0464-4a6f-8369-e951e187b398 --accessLevelRemoteId \"fullaccess\""],"flags":{"help":{"name":"help","type":"boolean","char":"h","description":"show CLI help","allowNo":false},"id":{"name":"id","type":"option","description":"The ID of the Opal instance resource."},"accessLevelRemoteId":{"name":"accessLevelRemoteId","type":"option","description":"The remote ID of the access level with which to access the database."},"sessionId":{"name":"sessionId","type":"option","description":"SessionId of a session that has already been created via the web flow."}},"args":[]},"resources:get":{"id":"resources:get","description":"Get resource info for a particular resource.","pluginName":"opal-security","pluginType":"core","aliases":[],"examples":["opal resources:get --id 54052a3e-5375-4392-aeaf-0c6c44c131d4"],"flags":{"help":{"name":"help","type":"boolean","char":"h","description":"show CLI help","allowNo":false},"id":{"name":"id","type":"option","required":true}},"args":[]},"ssh:copyFrom":{"id":"ssh:copyFrom","description":"Use SCP to copy files from a compute instance.","pluginName":"opal-security","pluginType":"core","aliases":[],"examples":["opal ssh:copyFrom --src instance/dir --dest my/dir","opal ssh:copyFrom --src instance/dir --dest my/dir --id 51f7176b-0464-4a6f-8369-e951e187b398"],"flags":{"help":{"name":"help","type":"boolean","char":"h","description":"show CLI help","allowNo":false},"src":{"name":"src","type":"option","description":"The path of the directory or file you would like to copy over SCP. Note we only support one file or directory at a time.","required":true},"dest":{"name":"dest","type":"option","description":"Pick which directory you want your files to be copied to.","required":false,"default":"."},"user":{"name":"user","type":"option","description":"Pick which user you want to run SCP over. Keep in mind not all users will have access to each other's home directory.","required":false,"default":"ssm-user"},"id":{"name":"id","type":"option","description":"The ID of the Opal instance resource."},"sessionId":{"name":"sessionId","type":"option","description":"SessionId of a session that has already been created via the web flow."}},"args":[]},"ssh:copyTo":{"id":"ssh:copyTo","description":"Use SCP to copy files to a compute instance.","pluginName":"opal-security","pluginType":"core","aliases":[],"examples":["opal ssh:copyTo --src my/dir --dest instance/dir","opal ssh:copyTo --src my/dir --dest instance/dir --id 51f7176b-0464-4a6f-8369-e951e187b398"],"flags":{"help":{"name":"help","type":"boolean","char":"h","description":"show CLI help","allowNo":false},"src":{"name":"src","type":"option","description":"The path of the directory or file you would like to copy over SCP. Note we only support one file or directory at a time.","required":true},"dest":{"name":"dest","type":"option","description":"Pick which directory you want your files to be copied to.","required":false,"default":"."},"user":{"name":"user","type":"option","description":"Pick which user you want to run SCP over. Keep in mind not all users will have access to each other's home directory.","required":false,"default":"ssm-user"},"id":{"name":"id","type":"option","description":"The ID of the Opal instance resource."},"sessionId":{"name":"sessionId","type":"option","description":"SessionId of a session that has already been created via the web flow."}},"args":[]},"ssh:start":{"id":"ssh:start","description":"Start an SSH session to access a particular compute instance.","pluginName":"opal-security","pluginType":"core","aliases":[],"examples":["opal ssh:start","opal ssh:start --id 51f7176b-0464-4a6f-8369-e951e187b398"],"flags":{"help":{"name":"help","type":"boolean","char":"h","description":"show CLI help","allowNo":false},"id":{"name":"id","type":"option","description":"The ID of the Opal instance resource."},"sessionId":{"name":"sessionId","type":"option","description":"SessionId of a session that has already been created via the web flow."}},"args":[]}}}
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": "2.0.10",
4
+ "version": "2.0.13",
5
5
  "author": "Stephen Cobbe",
6
6
  "bin": {
7
7
  "opal": "./bin/run"