opal-security 2.0.20 → 2.1.0

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.
@@ -9,8 +9,8 @@ const apollo_1 = require("../lib/apollo");
9
9
  const credentials_1 = require("../lib/credentials");
10
10
  const inquirer = require("inquirer");
11
11
  const handler_1 = require("../handler");
12
- const credentials_2 = require("../lib/credentials");
13
12
  const config_1 = require("../lib/config");
13
+ const common_1 = require("../lib/common");
14
14
  const ISSUER_PROD = 'https://auth.opal.dev';
15
15
  const ISSUER_DEV = 'https://authdev.opal.dev';
16
16
  const GRANT_TYPE = 'urn:ietf:params:oauth:grant-type:device_code';
@@ -45,22 +45,26 @@ class Login extends command_1.Command {
45
45
  var _a, _b, _c, _d, _e;
46
46
  try {
47
47
  await apollo_1.initClient(this);
48
- let email;
49
- let organizationID;
50
- if (await credentials_2.cred.accessToken) {
51
- email = await credentials_2.cred.email;
52
- organizationID = await credentials_2.cred.organizationID;
53
- await credentials_2.cred.removeCredentials(-1);
54
- }
48
+ const { flags } = this.parse(Login);
55
49
  const configDir = this.config.configDir;
56
50
  const configData = config_1.getOrCreateConfigData(configDir);
57
- if (email && organizationID) {
58
- console.log('Signing in as ' + email + ' - to use a different account, run `opal logout`');
51
+ let email = flags.email;
52
+ let organizationID;
53
+ if (await credentials_1.cred.accessToken) {
54
+ // Only use the previous email + organizationID if email isn't explicitly specified.
55
+ if (!email) {
56
+ email = await credentials_1.cred.email;
57
+ organizationID = await credentials_1.cred.organizationID;
58
+ }
59
+ await credentials_1.cred.removeCredentials(-1);
60
+ }
61
+ this.log('Welcome to Opal! ⚡️\n');
62
+ this.log('Please confirm your Opal instance URL:', configData[config_1.urlKey]);
63
+ this.log('If this is not correct, please first use `opal set-url --help`\n');
64
+ if (email) {
65
+ this.log('Signing in as: ' + email + ' - to use a different account, run `opal login --email [EMAIL]`');
59
66
  }
60
67
  else {
61
- this.log('Welcome to Opal! ⚡️\n');
62
- this.log('Please confirm your Opal instance URL:', configData[config_1.urlKey]);
63
- this.log('If this is not correct, please first use `opal set-url --help`\n');
64
68
  const { email: promptEmail } = await inquirer.prompt([{
65
69
  name: 'email',
66
70
  message: 'Enter your email:',
@@ -68,6 +72,8 @@ class Login extends command_1.Command {
68
72
  validate: email => Boolean(email),
69
73
  }]);
70
74
  email = promptEmail;
75
+ }
76
+ if (!organizationID) {
71
77
  const { resp: signInOrganizationsResponse, error } = await handler_1.runQuery({
72
78
  command: this,
73
79
  query: CLISignInMethodDocument,
@@ -77,7 +83,7 @@ class Login extends command_1.Command {
77
83
  this.log('Could not connect to Opal. Did you set the right URL? (`opal set-url --help`)');
78
84
  }
79
85
  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;
80
- if (signInOrganizations) {
86
+ if (signInOrganizations && signInOrganizations.length > 0) {
81
87
  if (signInOrganizations.length === 1) {
82
88
  organizationID = signInOrganizations[0].organizationId;
83
89
  }
@@ -94,6 +100,10 @@ class Login extends command_1.Command {
94
100
  organizationID = responses.organizationID;
95
101
  }
96
102
  }
103
+ else {
104
+ // If there are no organizations for the user, require the user to login before failing,
105
+ // which is parity with our web app.
106
+ }
97
107
  }
98
108
  let issuer;
99
109
  let clientId;
@@ -121,14 +131,9 @@ class Login extends command_1.Command {
121
131
  });
122
132
  this.log('\nYou are being redirected to your browser to authenticate.\n');
123
133
  this.log(` User Code: ${handle.user_code}\n`);
124
- // Wait 1s before opening the browser window to ensure the user has time to
134
+ // Wait before opening the browser window to ensure the user has time to
125
135
  // see the User Code.
126
- const sleep = (ms) => {
127
- return new Promise(resolve => {
128
- setTimeout(resolve, ms);
129
- });
130
- };
131
- await sleep(1000);
136
+ await common_1.sleep(1000);
132
137
  await open(handle.verification_uri_complete, { wait: false });
133
138
  const tokenSet = await handle.poll();
134
139
  const userInfo = await client.userinfo(tokenSet);
@@ -141,8 +146,8 @@ class Login extends command_1.Command {
141
146
  });
142
147
  if (authCheckErr || !((_e = (_d = (_c = authCheckResp === null || authCheckResp === void 0 ? void 0 : authCheckResp.data) === null || _c === void 0 ? void 0 : _c.organizationSettings) === null || _d === void 0 ? void 0 : _d.settings) === null || _e === void 0 ? void 0 : _e.id)) {
143
148
  this.log('Error verifying log in. Authenticated commands may fail. Please double check your URL and use `opal logout; opal login` to try again.\n');
144
- this.log(authCheckErr + '\n');
145
- return;
149
+ await credentials_1.cred.removeCredentials(-1);
150
+ apollo_1.handleError(this, authCheckErr);
146
151
  }
147
152
  this.log('🎉 You have successfully authenticated with Opal! You can now run authenticated commands.\n');
148
153
  }
@@ -156,5 +161,9 @@ Login.description = 'Authenticates you with the Opal server.';
156
161
  Login.examples = ['$ opal login'];
157
162
  Login.flags = {
158
163
  help: command_1.flags.help({ char: 'h' }),
164
+ email: command_1.flags.string({
165
+ multiple: false,
166
+ description: 'Email address to login with.',
167
+ }),
159
168
  };
160
169
  Login.args = [];
@@ -1,60 +1,19 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const command_1 = require("@oclif/command");
4
- const handler_1 = require("../../handler");
5
4
  const cmd_1 = require("../../lib/cmd");
6
5
  const apollo_1 = require("../../lib/apollo");
7
6
  const inquirer = require("inquirer");
8
7
  const resources_1 = require("../../lib/resources");
9
8
  const common_1 = require("../../lib/common");
10
- const ListPostgresInstancesDocument = `
11
- query ListPostgresInstances {
12
- resources(input: {serviceType: POSTGRES, onlyMine: true, maxNumEntries: 1000}) {
13
- __typename
14
- ... on ResourcesResult {
15
- resources {
16
- name
17
- id
18
- }
19
- cursor
20
- }
21
- }
22
- }`;
23
- const StartPostgresInstanceSessionDocument = `
24
- mutation StartPostgresInstanceSession($id: ResourceId!, $accessLevel: ResourceAccessLevelInput!, $sessionId: SessionId) {
25
- createSession(input: {resourceId: $id, accessLevel: $accessLevel, sessionId: $sessionId}) {
26
- __typename
27
- ... on CreateSessionResult {
28
- session {
29
- id
30
- endTime
31
- metadata {
32
- ... on AwsIamFederatedRdsSession {
33
- dbUser
34
- dbPassword
35
- dbHostname
36
- dbPort
37
- dbName
38
- }
39
- }
40
- }
41
- }
42
- ... on SessionNotFoundError {
43
- message
44
- }
45
- ... on MfaInvalidError {
46
- message
47
- }
48
- ... on OidcIDTokenNotFoundError {
49
- message
50
- }
51
- ... on ResourceNotFoundError {
52
- message
53
- }
54
- ... on EndSystemAuthorizationError {
55
- message
56
- }
57
- }
9
+ const sessions_1 = require("../../lib/sessions");
10
+ const RdsSessionMetadataFragment = `
11
+ ... on AwsIamFederatedRdsSession {
12
+ dbUser
13
+ dbPassword
14
+ dbHostname
15
+ dbPort
16
+ dbName
58
17
  }`;
59
18
  class StartPostgresInstanceSession extends command_1.Command {
60
19
  async run() {
@@ -63,110 +22,76 @@ class StartPostgresInstanceSession extends command_1.Command {
63
22
  let instanceId = flags.id;
64
23
  let instanceName = null;
65
24
  const sessionId = flags.sessionId;
66
- // TODO: RESOURCES-1: How do we grant access to a perm using ID
67
25
  if (!instanceId) {
68
- const { resp: postgresInstancesResp, error } = await handler_1.runQuery({
69
- command: this,
70
- query: ListPostgresInstancesDocument,
71
- variables: {},
72
- });
73
- if (error) {
74
- apollo_1.printRequestOutput(this, postgresInstancesResp, error);
75
- return;
76
- }
77
- const resourceInfos = postgresInstancesResp === null || postgresInstancesResp === void 0 ? void 0 : postgresInstancesResp.data.resources.resources.map((resource) => {
78
- return {
79
- id: resource.id,
80
- name: resource.name,
81
- };
82
- });
83
- const noResourcesFound = resources_1.resourcesAreEmpty(this, resourceInfos);
84
- if (noResourcesFound) {
85
- return;
86
- }
87
- const resourceInfoByName = {};
88
- resourceInfos.forEach(resourceInfo => {
89
- resourceInfoByName[resourceInfo.name] = resourceInfo;
90
- });
91
- inquirer.registerPrompt('autocomplete', require('inquirer-autocomplete-prompt'));
92
- const selectedInstanceInfo = await inquirer.prompt([
93
- {
94
- name: 'instance',
95
- message: 'Select a Postgres RDS instance to login to',
96
- type: 'autocomplete',
97
- source: (answers, input) => cmd_1.filterChoices(input, resourceInfos),
98
- },
99
- ]);
100
- const selectedInstance = resourceInfoByName[selectedInstanceInfo.instance];
26
+ const selectedInstance = await resources_1.promptUserForResource(this, 'AWS_RDS_POSTGRES_INSTANCE', 'Select an RDS Postgres instance to login to');
101
27
  if (!selectedInstance) {
102
28
  return;
103
29
  }
104
30
  instanceId = selectedInstance.id;
105
31
  instanceName = selectedInstance.name;
106
- // TODO: RESOURCES-3: Select the access level for the DB
107
32
  }
108
- // Fetch all access levels for resource
109
33
  const accessLevel = await resources_1.promptUserForAccessLevels(this, instanceId, 'Postgres database', flags.accessLevelRemoteId);
110
34
  if (!accessLevel) {
111
35
  return;
112
36
  }
113
- const { resp, error } = await handler_1.runMutation({
114
- command: this,
115
- query: StartPostgresInstanceSessionDocument,
116
- variables: {
117
- id: instanceId,
118
- accessLevel,
119
- sessionId,
120
- },
121
- });
122
- switch (resp === null || resp === void 0 ? void 0 : resp.data.createSession.__typename) {
123
- case 'CreateSessionResult': {
124
- const metadata = resp.data.createSession.session.metadata;
125
- switch (metadata === null || metadata === void 0 ? void 0 : metadata.__typename) {
126
- case 'AwsIamFederatedRdsSession': {
127
- const dbUrl = `postgresql://${metadata.dbUser}:${encodeURIComponent(metadata.dbPassword)}@${metadata.dbHostname}:${metadata.dbPort}/${metadata.dbName}`;
128
- const externalAppLaunchName = 'Launch external database app';
129
- const psqlSessionLaunchName = 'Launch shell with psql session';
130
- const selectedLaunchInfo = await inquirer.prompt([
37
+ const session = await sessions_1.getOrCreateSession(this, instanceId, accessLevel, sessionId, RdsSessionMetadataFragment);
38
+ const metadata = session.metadata;
39
+ switch (metadata === null || metadata === void 0 ? void 0 : metadata.__typename) {
40
+ case 'AwsIamFederatedRdsSession': {
41
+ // Don't inform the user about RDS session expiration time, since RDS works differently.
42
+ // Opal RDS sessions expire after 15min because after that time they can no longer be used to connect.
43
+ // However, once connected, RDS sessions can be used for up to 12h.
44
+ // Since there's many options for how the user can use RDS credentials, it's unclear which expiration
45
+ // we want to show the user.
46
+ const externalAppLaunchName = 'Launch external database app';
47
+ const psqlSessionLaunchName = 'Launch shell with psql session';
48
+ const viewDetailsName = 'View connection configuration';
49
+ const selectedLaunchInfo = await inquirer.prompt([{
50
+ name: 'launch',
51
+ message: 'Select how to access the database',
52
+ type: 'list',
53
+ choices: [
131
54
  {
132
- name: 'launch',
133
- message: 'Select how to access the database',
134
- type: 'list',
135
- choices: [
136
- {
137
- name: externalAppLaunchName,
138
- },
139
- {
140
- name: psqlSessionLaunchName,
141
- },
142
- ],
55
+ name: externalAppLaunchName,
143
56
  },
144
- ]);
145
- if (selectedLaunchInfo.launch === externalAppLaunchName) {
146
- const startSessionCmd = `open ${dbUrl}`;
147
- cmd_1.runCommandExec(startSessionCmd, `Opened external app for ${instanceName ? `"${instanceName}" instance` : 'instance'}`, `Failed to open external app for ${instanceName ? `"${instanceName}" instance` : 'instance'}`);
148
- }
149
- else if (selectedLaunchInfo.launch === psqlSessionLaunchName) {
150
- const startSessionCmd = `psql ${dbUrl}`;
151
- cmd_1.startInteractiveShell(startSessionCmd, `shell with psql session for ${instanceName ? `"${instanceName}" instance` : 'instance'}`);
152
- }
57
+ {
58
+ name: psqlSessionLaunchName,
59
+ },
60
+ {
61
+ name: viewDetailsName,
62
+ },
63
+ ],
64
+ }]);
65
+ const dbUrl = `postgresql://${metadata.dbUser}:${encodeURIComponent(metadata.dbPassword)}@${metadata.dbHostname}:${metadata.dbPort}/${metadata.dbName}`;
66
+ switch (selectedLaunchInfo.launch) {
67
+ case externalAppLaunchName: {
68
+ const startSessionCmd = `open ${dbUrl}`;
69
+ cmd_1.runCommandExec(startSessionCmd, `Opened external app for ${instanceName ? `"${instanceName}" instance` : 'instance'}`, `Failed to open external app for ${instanceName ? `"${instanceName}" instance` : 'instance'}`);
70
+ break;
71
+ }
72
+ case viewDetailsName: {
73
+ const contentParts = [
74
+ `[Connection URL]\n${dbUrl}`,
75
+ `[Hostname]\n${metadata.dbHostname}`,
76
+ `[Port]\n${metadata.dbPort}`,
77
+ `[User]\n${metadata.dbUser}`,
78
+ `[Password]\n${metadata.dbPassword}`,
79
+ `[Database]\n${metadata.dbName}`,
80
+ ];
81
+ const content = contentParts.join('\n\n');
82
+ common_1.displayContent(content);
83
+ break;
84
+ }
85
+ case psqlSessionLaunchName: {
86
+ const startSessionCmd = `psql ${dbUrl}`;
87
+ cmd_1.startInteractiveShell(startSessionCmd, `shell with psql session for ${instanceName ? `"${instanceName}" instance` : 'instance'}`);
153
88
  break;
154
89
  }
155
- default:
156
- apollo_1.printRequestOutput(this, resp, error);
157
90
  }
158
91
  break;
159
92
  }
160
- case 'MfaInvalidError': {
161
- common_1.handleMfaRedirect(this, instanceId);
162
- break;
163
- }
164
- case 'OidcIDTokenNotFoundError': {
165
- common_1.handleOidcRedirect(this, instanceId);
166
- break;
167
- }
168
93
  default:
169
- apollo_1.printRequestOutput(this, resp, error);
94
+ return apollo_1.handleError(this, undefined, session);
170
95
  }
171
96
  }
172
97
  }
@@ -1,5 +1,5 @@
1
1
  import { Command, flags } from '@oclif/command';
2
- export declare const GetResourceDocument = "\nquery GetResource($id: ResourceId!) {\n resource(input: {id: $id}) {\n __typename\n ... on ResourceResult {\n resource {\n name\n id\n description\n connection {\n name\n id\n }\n resourceUsers {\n user {\n email\n }\n }\n }\n }\n ... on ResourceNotFoundError {\n message\n }\n }\n}";
2
+ export declare const GetResourceDocument = "\nquery GetResource($id: ResourceId!) {\n resource(input: {id: $id}) {\n __typename\n ... on ResourceResult {\n resource {\n name\n id\n description\n resourceType\n connection {\n name\n id\n connectionType\n }\n parentResource {\n name\n id\n resourceType\n }\n resourceUsers {\n user {\n fullName\n email\n id\n }\n }\n }\n }\n ... on ResourceNotFoundError {\n message\n }\n }\n}";
3
3
  export default class GetResource extends Command {
4
4
  static description: string;
5
5
  static examples: string[];
@@ -4,6 +4,7 @@ exports.GetResourceDocument = void 0;
4
4
  const command_1 = require("@oclif/command");
5
5
  const handler_1 = require("../../handler");
6
6
  const cmd_1 = require("../../lib/cmd");
7
+ const apollo_1 = require("../../lib/apollo");
7
8
  exports.GetResourceDocument = `
8
9
  query GetResource($id: ResourceId!) {
9
10
  resource(input: {id: $id}) {
@@ -13,13 +14,22 @@ query GetResource($id: ResourceId!) {
13
14
  name
14
15
  id
15
16
  description
17
+ resourceType
16
18
  connection {
17
19
  name
18
20
  id
21
+ connectionType
22
+ }
23
+ parentResource {
24
+ name
25
+ id
26
+ resourceType
19
27
  }
20
28
  resourceUsers {
21
29
  user {
30
+ fullName
22
31
  email
32
+ id
23
33
  }
24
34
  }
25
35
  }
@@ -33,7 +43,15 @@ class GetResource extends command_1.Command {
33
43
  async run() {
34
44
  cmd_1.setMostRecentCommand(this);
35
45
  const { flags } = this.parse(GetResource);
36
- await handler_1.default({ command: this, query: exports.GetResourceDocument, variables: flags });
46
+ const { resp, error } = await handler_1.runQuery({
47
+ command: this,
48
+ query: exports.GetResourceDocument,
49
+ variables: flags,
50
+ });
51
+ if (error) {
52
+ return apollo_1.handleError(this, error, resp);
53
+ }
54
+ apollo_1.printResponse(this, resp);
37
55
  }
38
56
  }
39
57
  exports.default = GetResource;
@@ -4,14 +4,17 @@ export default class SetUrl extends Command {
4
4
  static examples: string[];
5
5
  static flags: {
6
6
  help: import("@oclif/parser/lib/flags").IBooleanFlag<void>;
7
- custom: flags.IOptionFlag<string | undefined>;
8
7
  allowSelfSignedCerts: import("@oclif/parser/lib/flags").IBooleanFlag<boolean>;
8
+ custom: flags.IOptionFlag<string | undefined>;
9
9
  prod: import("@oclif/parser/lib/flags").IBooleanFlag<boolean>;
10
- staging: import("@oclif/parser/lib/flags").IBooleanFlag<boolean>;
11
10
  demo: import("@oclif/parser/lib/flags").IBooleanFlag<boolean>;
12
11
  dev: import("@oclif/parser/lib/flags").IBooleanFlag<boolean>;
13
12
  devLocal: import("@oclif/parser/lib/flags").IBooleanFlag<boolean>;
14
13
  };
15
- static args: never[];
14
+ static args: {
15
+ name: string;
16
+ description: string;
17
+ required: boolean;
18
+ }[];
16
19
  run(): Promise<void>;
17
20
  }
@@ -7,17 +7,17 @@ const credentials_1 = require("../lib/credentials");
7
7
  class SetUrl extends command_1.Command {
8
8
  async run() {
9
9
  try {
10
- const { flags } = this.parse(SetUrl);
10
+ const { flags, args } = this.parse(SetUrl);
11
11
  let url = config_1.defaultUrl;
12
- if (flags.custom) {
12
+ if (args.url) {
13
+ url = args.url;
14
+ }
15
+ else if (flags.custom) {
13
16
  url = flags.custom;
14
17
  }
15
18
  else if (flags.prod) {
16
19
  url = 'https://app.opal.dev';
17
20
  }
18
- else if (flags.staging) {
19
- url = 'https://staging.opal.dev';
20
- }
21
21
  else if (flags.demo) {
22
22
  url = 'https://demo.opal.dev';
23
23
  }
@@ -27,6 +27,23 @@ class SetUrl extends command_1.Command {
27
27
  else if (flags.devLocal) {
28
28
  url = 'http://localhost:3000';
29
29
  }
30
+ if (!url.startsWith('http://') && !url.startsWith('https://')) {
31
+ // Add protocol if not specified
32
+ if (url.startsWith('localhost')) {
33
+ url = 'http://' + url;
34
+ }
35
+ else {
36
+ url = 'https://' + url;
37
+ }
38
+ }
39
+ if (url.match(/^https?:\/\/[^/]+\/$/)) {
40
+ // URL matches `https://x.y.z/`, so trim trailing slash
41
+ url = url.slice(0, -1);
42
+ }
43
+ else if (!url.match(/^https?:\/\/[^/]+$/)) {
44
+ // Error if URL doesn't match `https://x.y.z` or `http://x.y.z`
45
+ throw new Error('Invalid URL. Please provide only the protocol and domain (e.g. https://app.opal.dev).');
46
+ }
30
47
  const configData = config_1.getOrCreateConfigData(this.config.configDir);
31
48
  configData[config_1.urlKey] = url;
32
49
  configData[config_1.allowSelfSignedCertsKey] = flags.allowSelfSignedCerts !== undefined;
@@ -46,14 +63,21 @@ SetUrl.description = `Sets the url of the Opal server. Defaults to ${config_1.de
46
63
  SetUrl.examples = ['$ opal set-url'];
47
64
  SetUrl.flags = {
48
65
  help: command_1.flags.help({ char: 'h' }),
66
+ allowSelfSignedCerts: command_1.flags.boolean(),
67
+ // Legacy flags
49
68
  custom: command_1.flags.string({
50
69
  multiple: false,
70
+ hidden: true,
51
71
  }),
52
- allowSelfSignedCerts: command_1.flags.boolean(),
53
- prod: command_1.flags.boolean(),
54
- staging: command_1.flags.boolean(),
55
- demo: command_1.flags.boolean(),
56
- dev: command_1.flags.boolean(),
57
- devLocal: command_1.flags.boolean(),
72
+ prod: command_1.flags.boolean({ hidden: true }),
73
+ demo: command_1.flags.boolean({ hidden: true }),
74
+ dev: command_1.flags.boolean({ hidden: true }),
75
+ devLocal: command_1.flags.boolean({ hidden: true }),
58
76
  };
59
- SetUrl.args = [];
77
+ SetUrl.args = [
78
+ {
79
+ name: 'url',
80
+ description: 'URL of the Opal server to use. If unspecified, defaults to https://app.opal.dev',
81
+ required: false,
82
+ },
83
+ ];
@@ -1,46 +1,12 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const command_1 = require("@oclif/command");
4
- const handler_1 = require("../../handler");
5
4
  const apollo_1 = require("../../lib/apollo");
6
5
  const cmd_1 = require("../../lib/cmd");
7
6
  const ssh_1 = require("../../lib/ssh");
8
- const common_1 = require("../../lib/common");
9
- const StartSSHSessionDocument = `
10
- mutation StartSSHSession($id: ResourceId!, $accessLevel: ResourceAccessLevelInput!, $sessionId: SessionId) {
11
- createSession(input: {resourceId: $id, accessLevel: $accessLevel, sessionId: $sessionId}) {
12
- __typename
13
- ... on CreateSessionResult {
14
- session {
15
- id
16
- endTime
17
- metadata {
18
- ... on AwsIamFederatedSSMSession {
19
- awsAccessKeyId
20
- awsSecretAccessKey
21
- awsSessionToken
22
- awsLoginUrl
23
- federatedArn
24
- ec2InstanceId
25
- ec2Region
26
- }
27
- }
28
- }
29
- }
30
- ... on SessionNotFoundError {
31
- message
32
- }
33
- ... on MfaInvalidError {
34
- message
35
- }
36
- ... on ResourceNotFoundError {
37
- message
38
- }
39
- ... on EndSystemAuthorizationError {
40
- message
41
- }
42
- }
43
- }`;
7
+ const resources_1 = require("../../lib/resources");
8
+ const sessions_1 = require("../../lib/sessions");
9
+ const start_1 = require("./start");
44
10
  class StartSCPSession extends command_1.Command {
45
11
  async run() {
46
12
  cmd_1.setMostRecentCommand(this);
@@ -60,38 +26,23 @@ class StartSCPSession extends command_1.Command {
60
26
  instanceId = selectedInstance.id;
61
27
  instanceName = selectedInstance.name;
62
28
  }
63
- const { resp, error } = await handler_1.runMutation({
64
- command: this,
65
- query: StartSSHSessionDocument,
66
- variables: { id: instanceId, accessLevel: cmd_1.DEFAULT_ACCESS_LEVEL, sessionId },
67
- });
68
- switch (resp === null || resp === void 0 ? void 0 : resp.data.createSession.__typename) {
69
- case 'CreateSessionResult': {
70
- const metadata = resp.data.createSession.session.metadata;
71
- switch (metadata === null || metadata === void 0 ? void 0 : metadata.__typename) {
72
- case 'AwsIamFederatedSSMSession': {
73
- const envVars = {
74
- AWS_ACCESS_KEY_ID: metadata.awsAccessKeyId,
75
- AWS_SECRET_ACCESS_KEY: metadata.awsSecretAccessKey,
76
- AWS_SESSION_TOKEN: metadata.awsSessionToken,
77
- };
78
- // Run SCP script
79
- const scpCmd = `$SCRIPT_PATH/../../scripts/ssh_ssm_scp_from_server.sh ${metadata.ec2InstanceId} ${flags.user} ${flags.src} ${metadata.ec2Region} ${flags.dest}`;
80
- const outputMessage = `from "${flags.src}" on ${instanceName ? `"${instanceName}" instance` : 'instance'} to "${flags.dest}" locally.`;
81
- cmd_1.runCommandSpawn(scpCmd, `Copied ${outputMessage}`, `Failed to copy ${outputMessage}`, envVars);
82
- break;
83
- }
84
- default:
85
- apollo_1.printRequestOutput(this, resp, error);
86
- }
87
- break;
88
- }
89
- case 'MfaInvalidError': {
90
- common_1.handleMfaRedirect(this, instanceId);
29
+ const session = await sessions_1.getOrCreateSession(this, instanceId, resources_1.DEFAULT_ACCESS_LEVEL, sessionId, start_1.Ec2SessionMetadataFragment);
30
+ const metadata = session.metadata;
31
+ switch (metadata === null || metadata === void 0 ? void 0 : metadata.__typename) {
32
+ case 'AwsIamFederatedSSMSession': {
33
+ const envVars = {
34
+ AWS_ACCESS_KEY_ID: metadata.awsAccessKeyId,
35
+ AWS_SECRET_ACCESS_KEY: metadata.awsSecretAccessKey,
36
+ AWS_SESSION_TOKEN: metadata.awsSessionToken,
37
+ };
38
+ // Run SCP script
39
+ const scpCmd = `$SCRIPT_PATH/../../scripts/ssh_ssm_scp_from_server.sh ${metadata.ec2InstanceId} ${flags.user} ${flags.src} ${metadata.ec2Region} ${flags.dest}`;
40
+ const outputMessage = `from "${flags.src}" on ${instanceName ? `"${instanceName}" instance` : 'instance'} to "${flags.dest}" locally.`;
41
+ cmd_1.runCommandSpawn(scpCmd, `Copied ${outputMessage}`, `Failed to copy ${outputMessage}`, envVars);
91
42
  break;
92
43
  }
93
44
  default:
94
- apollo_1.printRequestOutput(this, resp, error);
45
+ return apollo_1.handleError(this, undefined, session);
95
46
  }
96
47
  }
97
48
  }
@@ -118,7 +69,7 @@ StartSCPSession.flags = {
118
69
  multiple: false,
119
70
  required: false,
120
71
  default: 'ssm-user',
121
- 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.",
72
+ 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.',
122
73
  }),
123
74
  id: command_1.flags.string({
124
75
  multiple: false,