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.
- package/README.md +24 -26
- package/lib/commands/iam-roles/start.js +30 -125
- package/lib/commands/kube-roles/start.js +23 -122
- package/lib/commands/login.d.ts +2 -1
- package/lib/commands/login.js +32 -23
- package/lib/commands/postgres-instances/start.js +59 -134
- package/lib/commands/resources/get.d.ts +1 -1
- package/lib/commands/resources/get.js +19 -1
- package/lib/commands/set-url.d.ts +6 -3
- package/lib/commands/set-url.js +36 -12
- package/lib/commands/ssh/copyFrom.js +18 -67
- package/lib/commands/ssh/copyTo.js +18 -67
- package/lib/commands/ssh/start.d.ts +1 -0
- package/lib/commands/ssh/start.js +33 -80
- package/lib/handler.d.ts +1 -2
- package/lib/handler.js +0 -27
- package/lib/lib/apollo.d.ts +2 -1
- package/lib/lib/apollo.js +57 -22
- package/lib/lib/aws.js +3 -2
- package/lib/lib/cmd.d.ts +0 -11
- package/lib/lib/cmd.js +3 -15
- package/lib/lib/common.d.ts +4 -3
- package/lib/lib/common.js +33 -15
- package/lib/lib/resources.d.ts +13 -5
- package/lib/lib/resources.js +83 -23
- package/lib/lib/sessions.d.ts +4 -0
- package/lib/lib/sessions.js +154 -0
- package/lib/lib/ssh.d.ts +1 -3
- package/lib/lib/ssh.js +3 -49
- package/lib/types.d.ts +1 -0
- package/oclif.manifest.json +1 -1
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -22,7 +22,7 @@ $ npm install -g opal-security
|
|
|
22
22
|
$ opal COMMAND
|
|
23
23
|
running command...
|
|
24
24
|
$ opal (-v|--version|version)
|
|
25
|
-
opal-security/2.0
|
|
25
|
+
opal-security/2.1.0 darwin-x64 node-v14.16.1
|
|
26
26
|
$ opal --help [COMMAND]
|
|
27
27
|
USAGE
|
|
28
28
|
$ opal COMMAND
|
|
@@ -45,7 +45,7 @@ USAGE
|
|
|
45
45
|
* [`opal resources:get`](#opal-resourcesget)
|
|
46
46
|
* [`opal set-custom-header`](#opal-set-custom-header)
|
|
47
47
|
* [`opal set-token`](#opal-set-token)
|
|
48
|
-
* [`opal set-url`](#opal-set-url)
|
|
48
|
+
* [`opal set-url [URL]`](#opal-set-url-url)
|
|
49
49
|
* [`opal ssh:copyFrom`](#opal-sshcopyfrom)
|
|
50
50
|
* [`opal ssh:copyTo`](#opal-sshcopyto)
|
|
51
51
|
* [`opal ssh:start`](#opal-sshstart)
|
|
@@ -88,7 +88,7 @@ EXAMPLE
|
|
|
88
88
|
opal aws:identity
|
|
89
89
|
```
|
|
90
90
|
|
|
91
|
-
_See code: [src/commands/aws/identity.ts](https://github.com/opalsecurity/opal-cli/blob/v2.0
|
|
91
|
+
_See code: [src/commands/aws/identity.ts](https://github.com/opalsecurity/opal-cli/blob/v2.1.0/src/commands/aws/identity.ts)_
|
|
92
92
|
|
|
93
93
|
## `opal curl-example`
|
|
94
94
|
|
|
@@ -102,7 +102,7 @@ OPTIONS
|
|
|
102
102
|
-h, --help show CLI help
|
|
103
103
|
```
|
|
104
104
|
|
|
105
|
-
_See code: [src/commands/curl-example.ts](https://github.com/opalsecurity/opal-cli/blob/v2.0
|
|
105
|
+
_See code: [src/commands/curl-example.ts](https://github.com/opalsecurity/opal-cli/blob/v2.1.0/src/commands/curl-example.ts)_
|
|
106
106
|
|
|
107
107
|
## `opal help [COMMAND]`
|
|
108
108
|
|
|
@@ -141,7 +141,7 @@ EXAMPLES
|
|
|
141
141
|
opal iam-roles:start --id 51f7176b-0464-4a6f-8369-e951e187b398 --profileName "custom-profile"
|
|
142
142
|
```
|
|
143
143
|
|
|
144
|
-
_See code: [src/commands/iam-roles/start.ts](https://github.com/opalsecurity/opal-cli/blob/v2.0
|
|
144
|
+
_See code: [src/commands/iam-roles/start.ts](https://github.com/opalsecurity/opal-cli/blob/v2.1.0/src/commands/iam-roles/start.ts)_
|
|
145
145
|
|
|
146
146
|
## `opal kube-roles:start`
|
|
147
147
|
|
|
@@ -164,7 +164,7 @@ EXAMPLES
|
|
|
164
164
|
"arn:aws:iam::712234975475:role/acme-eks-cluster-admin-role"
|
|
165
165
|
```
|
|
166
166
|
|
|
167
|
-
_See code: [src/commands/kube-roles/start.ts](https://github.com/opalsecurity/opal-cli/blob/v2.0
|
|
167
|
+
_See code: [src/commands/kube-roles/start.ts](https://github.com/opalsecurity/opal-cli/blob/v2.1.0/src/commands/kube-roles/start.ts)_
|
|
168
168
|
|
|
169
169
|
## `opal login`
|
|
170
170
|
|
|
@@ -175,13 +175,14 @@ USAGE
|
|
|
175
175
|
$ opal login
|
|
176
176
|
|
|
177
177
|
OPTIONS
|
|
178
|
-
-h, --help
|
|
178
|
+
-h, --help show CLI help
|
|
179
|
+
--email=email Email address to login with.
|
|
179
180
|
|
|
180
181
|
EXAMPLE
|
|
181
182
|
$ opal login
|
|
182
183
|
```
|
|
183
184
|
|
|
184
|
-
_See code: [src/commands/login.ts](https://github.com/opalsecurity/opal-cli/blob/v2.0
|
|
185
|
+
_See code: [src/commands/login.ts](https://github.com/opalsecurity/opal-cli/blob/v2.1.0/src/commands/login.ts)_
|
|
185
186
|
|
|
186
187
|
## `opal logout`
|
|
187
188
|
|
|
@@ -198,7 +199,7 @@ EXAMPLE
|
|
|
198
199
|
$ opal logout
|
|
199
200
|
```
|
|
200
201
|
|
|
201
|
-
_See code: [src/commands/logout.ts](https://github.com/opalsecurity/opal-cli/blob/v2.0
|
|
202
|
+
_See code: [src/commands/logout.ts](https://github.com/opalsecurity/opal-cli/blob/v2.1.0/src/commands/logout.ts)_
|
|
202
203
|
|
|
203
204
|
## `opal postgres-instances:start`
|
|
204
205
|
|
|
@@ -220,7 +221,7 @@ EXAMPLES
|
|
|
220
221
|
opal postgres-instances:start --id 51f7176b-0464-4a6f-8369-e951e187b398 --accessLevelRemoteId "fullaccess"
|
|
221
222
|
```
|
|
222
223
|
|
|
223
|
-
_See code: [src/commands/postgres-instances/start.ts](https://github.com/opalsecurity/opal-cli/blob/v2.0
|
|
224
|
+
_See code: [src/commands/postgres-instances/start.ts](https://github.com/opalsecurity/opal-cli/blob/v2.1.0/src/commands/postgres-instances/start.ts)_
|
|
224
225
|
|
|
225
226
|
## `opal resources:get`
|
|
226
227
|
|
|
@@ -238,7 +239,7 @@ EXAMPLE
|
|
|
238
239
|
opal resources:get --id 54052a3e-5375-4392-aeaf-0c6c44c131d4
|
|
239
240
|
```
|
|
240
241
|
|
|
241
|
-
_See code: [src/commands/resources/get.ts](https://github.com/opalsecurity/opal-cli/blob/v2.0
|
|
242
|
+
_See code: [src/commands/resources/get.ts](https://github.com/opalsecurity/opal-cli/blob/v2.1.0/src/commands/resources/get.ts)_
|
|
242
243
|
|
|
243
244
|
## `opal set-custom-header`
|
|
244
245
|
|
|
@@ -256,7 +257,7 @@ EXAMPLE
|
|
|
256
257
|
$ opal set-custom-header --header 'cf-access-token: $TOKEN'
|
|
257
258
|
```
|
|
258
259
|
|
|
259
|
-
_See code: [src/commands/set-custom-header.ts](https://github.com/opalsecurity/opal-cli/blob/v2.0
|
|
260
|
+
_See code: [src/commands/set-custom-header.ts](https://github.com/opalsecurity/opal-cli/blob/v2.1.0/src/commands/set-custom-header.ts)_
|
|
260
261
|
|
|
261
262
|
## `opal set-token`
|
|
262
263
|
|
|
@@ -273,31 +274,28 @@ EXAMPLE
|
|
|
273
274
|
$ opal set-token
|
|
274
275
|
```
|
|
275
276
|
|
|
276
|
-
_See code: [src/commands/set-token.ts](https://github.com/opalsecurity/opal-cli/blob/v2.0
|
|
277
|
+
_See code: [src/commands/set-token.ts](https://github.com/opalsecurity/opal-cli/blob/v2.1.0/src/commands/set-token.ts)_
|
|
277
278
|
|
|
278
|
-
## `opal set-url`
|
|
279
|
+
## `opal set-url [URL]`
|
|
279
280
|
|
|
280
281
|
Sets the url of the Opal server. Defaults to https://app.opal.dev.
|
|
281
282
|
|
|
282
283
|
```
|
|
283
284
|
USAGE
|
|
284
|
-
$ opal set-url
|
|
285
|
+
$ opal set-url [URL]
|
|
286
|
+
|
|
287
|
+
ARGUMENTS
|
|
288
|
+
URL URL of the Opal server to use. If unspecified, defaults to https://app.opal.dev
|
|
285
289
|
|
|
286
290
|
OPTIONS
|
|
287
291
|
-h, --help show CLI help
|
|
288
292
|
--allowSelfSignedCerts
|
|
289
|
-
--custom=custom
|
|
290
|
-
--demo
|
|
291
|
-
--dev
|
|
292
|
-
--devLocal
|
|
293
|
-
--prod
|
|
294
|
-
--staging
|
|
295
293
|
|
|
296
294
|
EXAMPLE
|
|
297
295
|
$ opal set-url
|
|
298
296
|
```
|
|
299
297
|
|
|
300
|
-
_See code: [src/commands/set-url.ts](https://github.com/opalsecurity/opal-cli/blob/v2.0
|
|
298
|
+
_See code: [src/commands/set-url.ts](https://github.com/opalsecurity/opal-cli/blob/v2.1.0/src/commands/set-url.ts)_
|
|
301
299
|
|
|
302
300
|
## `opal ssh:copyFrom`
|
|
303
301
|
|
|
@@ -324,7 +322,7 @@ EXAMPLES
|
|
|
324
322
|
opal ssh:copyFrom --src instance/dir --dest my/dir --id 51f7176b-0464-4a6f-8369-e951e187b398
|
|
325
323
|
```
|
|
326
324
|
|
|
327
|
-
_See code: [src/commands/ssh/copyFrom.ts](https://github.com/opalsecurity/opal-cli/blob/v2.0
|
|
325
|
+
_See code: [src/commands/ssh/copyFrom.ts](https://github.com/opalsecurity/opal-cli/blob/v2.1.0/src/commands/ssh/copyFrom.ts)_
|
|
328
326
|
|
|
329
327
|
## `opal ssh:copyTo`
|
|
330
328
|
|
|
@@ -351,11 +349,11 @@ EXAMPLES
|
|
|
351
349
|
opal ssh:copyTo --src my/dir --dest instance/dir --id 51f7176b-0464-4a6f-8369-e951e187b398
|
|
352
350
|
```
|
|
353
351
|
|
|
354
|
-
_See code: [src/commands/ssh/copyTo.ts](https://github.com/opalsecurity/opal-cli/blob/v2.0
|
|
352
|
+
_See code: [src/commands/ssh/copyTo.ts](https://github.com/opalsecurity/opal-cli/blob/v2.1.0/src/commands/ssh/copyTo.ts)_
|
|
355
353
|
|
|
356
354
|
## `opal ssh:start`
|
|
357
355
|
|
|
358
|
-
|
|
356
|
+
Starts an SSH session to access a compute instance.
|
|
359
357
|
|
|
360
358
|
```
|
|
361
359
|
USAGE
|
|
@@ -371,5 +369,5 @@ EXAMPLES
|
|
|
371
369
|
opal ssh:start --id 51f7176b-0464-4a6f-8369-e951e187b398
|
|
372
370
|
```
|
|
373
371
|
|
|
374
|
-
_See code: [src/commands/ssh/start.ts](https://github.com/opalsecurity/opal-cli/blob/v2.0
|
|
372
|
+
_See code: [src/commands/ssh/start.ts](https://github.com/opalsecurity/opal-cli/blob/v2.1.0/src/commands/ssh/start.ts)_
|
|
375
373
|
<!-- commandsstop -->
|
|
@@ -4,59 +4,17 @@ const command_1 = require("@oclif/command");
|
|
|
4
4
|
const handler_1 = require("../../handler");
|
|
5
5
|
const cmd_1 = require("../../lib/cmd");
|
|
6
6
|
const apollo_1 = require("../../lib/apollo");
|
|
7
|
-
const inquirer = require("inquirer");
|
|
8
7
|
const aws_1 = require("../../lib/aws");
|
|
9
8
|
const resources_1 = require("../../lib/resources");
|
|
10
9
|
const get_1 = require("../../commands/resources/get");
|
|
11
|
-
const
|
|
12
|
-
const
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
endTime
|
|
20
|
-
metadata {
|
|
21
|
-
... on AwsIamFederatedRoleSession {
|
|
22
|
-
awsAccessKeyId
|
|
23
|
-
awsSecretAccessKey
|
|
24
|
-
awsSessionToken
|
|
25
|
-
awsLoginUrl
|
|
26
|
-
federatedArn
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
... on SessionNotFoundError {
|
|
32
|
-
message
|
|
33
|
-
}
|
|
34
|
-
... on MfaInvalidError {
|
|
35
|
-
message
|
|
36
|
-
}
|
|
37
|
-
... on OidcIDTokenNotFoundError {
|
|
38
|
-
message
|
|
39
|
-
}
|
|
40
|
-
... on ResourceNotFoundError {
|
|
41
|
-
message
|
|
42
|
-
}
|
|
43
|
-
... on EndSystemAuthorizationError {
|
|
44
|
-
message
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
}`;
|
|
48
|
-
const ListIamRolesDocument = `
|
|
49
|
-
query ListIAMRoles {
|
|
50
|
-
resources(input: {resourceTypes: [AWS_IAM_ROLE], onlyMine: true, maxNumEntries: 1000}) {
|
|
51
|
-
__typename
|
|
52
|
-
... on ResourcesResult {
|
|
53
|
-
resources {
|
|
54
|
-
name
|
|
55
|
-
id
|
|
56
|
-
}
|
|
57
|
-
cursor
|
|
58
|
-
}
|
|
59
|
-
}
|
|
10
|
+
const sessions_1 = require("../../lib/sessions");
|
|
11
|
+
const IamSessionMetadataFragment = `
|
|
12
|
+
... on AwsIamFederatedRoleSession {
|
|
13
|
+
awsAccessKeyId
|
|
14
|
+
awsSecretAccessKey
|
|
15
|
+
awsSessionToken
|
|
16
|
+
awsLoginUrl
|
|
17
|
+
federatedArn
|
|
60
18
|
}`;
|
|
61
19
|
class StartIAMRoleSession extends command_1.Command {
|
|
62
20
|
async run() {
|
|
@@ -66,98 +24,45 @@ class StartIAMRoleSession extends command_1.Command {
|
|
|
66
24
|
let roleName = null;
|
|
67
25
|
const sessionId = flags.sessionId;
|
|
68
26
|
if (!roleId) {
|
|
69
|
-
const
|
|
70
|
-
|
|
71
|
-
query: ListIamRolesDocument,
|
|
72
|
-
variables: {},
|
|
73
|
-
});
|
|
74
|
-
if (error) {
|
|
75
|
-
apollo_1.printRequestOutput(this, iamRolesResp, error);
|
|
76
|
-
return;
|
|
77
|
-
}
|
|
78
|
-
const resourceInfos = iamRolesResp === null || iamRolesResp === void 0 ? void 0 : iamRolesResp.data.resources.resources.map((resource) => {
|
|
79
|
-
return {
|
|
80
|
-
id: resource.id,
|
|
81
|
-
name: resource.name,
|
|
82
|
-
};
|
|
83
|
-
});
|
|
84
|
-
const noResourcesFound = resources_1.resourcesAreEmpty(this, resourceInfos);
|
|
85
|
-
if (noResourcesFound) {
|
|
27
|
+
const selectedRole = await resources_1.promptUserForResource(this, 'AWS_IAM_ROLE', 'Select an IAM role to assume');
|
|
28
|
+
if (!selectedRole) {
|
|
86
29
|
return;
|
|
87
30
|
}
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
resourceInfoByName[resourceInfo.name] = resourceInfo;
|
|
91
|
-
});
|
|
92
|
-
inquirer.registerPrompt('autocomplete', require('inquirer-autocomplete-prompt'));
|
|
93
|
-
const selectedIamRoleInfo = await inquirer.prompt([
|
|
94
|
-
{
|
|
95
|
-
name: 'role',
|
|
96
|
-
message: 'Select an IAM role to assume',
|
|
97
|
-
type: 'autocomplete',
|
|
98
|
-
source: (answers, input) => cmd_1.filterChoices(input, resourceInfos),
|
|
99
|
-
},
|
|
100
|
-
]);
|
|
101
|
-
const selectedIamRole = resourceInfoByName[selectedIamRoleInfo.role];
|
|
102
|
-
if (!selectedIamRole) {
|
|
103
|
-
return;
|
|
104
|
-
}
|
|
105
|
-
roleId = selectedIamRole.id;
|
|
106
|
-
roleName = selectedIamRole.name;
|
|
31
|
+
roleId = selectedRole.id;
|
|
32
|
+
roleName = selectedRole.name;
|
|
107
33
|
}
|
|
108
34
|
else {
|
|
109
|
-
const { resp
|
|
35
|
+
const { resp, error } = await handler_1.runQuery({
|
|
110
36
|
command: this,
|
|
111
37
|
query: get_1.GetResourceDocument,
|
|
112
38
|
variables: {
|
|
113
39
|
id: roleId,
|
|
114
40
|
},
|
|
115
41
|
});
|
|
116
|
-
if (error
|
|
117
|
-
apollo_1.
|
|
118
|
-
|
|
42
|
+
if (error) {
|
|
43
|
+
return apollo_1.handleError(this, error, resp);
|
|
44
|
+
}
|
|
45
|
+
if (!(resp === null || resp === void 0 ? void 0 : resp.data.resource.resource)) {
|
|
46
|
+
return apollo_1.handleError(this, `Resource not found for ID: ${roleId}`);
|
|
119
47
|
}
|
|
120
|
-
roleName = (
|
|
48
|
+
roleName = (resp === null || resp === void 0 ? void 0 : resp.data.resource.resource.name) || 'iam-role';
|
|
121
49
|
}
|
|
122
50
|
if (flags.profileName && flags.profileName !== '') {
|
|
123
51
|
roleName = flags.profileName;
|
|
124
52
|
}
|
|
125
|
-
const
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
switch (resp === null || resp === void 0 ? void 0 : resp.data.createSession.__typename) {
|
|
135
|
-
case 'CreateSessionResult': {
|
|
136
|
-
const metadata = resp.data.createSession.session.metadata;
|
|
137
|
-
switch (metadata === null || metadata === void 0 ? void 0 : metadata.__typename) {
|
|
138
|
-
case 'AwsIamFederatedRoleSession': {
|
|
139
|
-
const updateAwsConfigCommand = aws_1.getAwsConfigUpdateCmd(roleName, metadata.awsAccessKeyId, metadata.awsSecretAccessKey, metadata.awsSessionToken);
|
|
140
|
-
const startSessionCmd = `${updateAwsConfigCommand}`;
|
|
141
|
-
const awsEnvVarMessage = aws_1.getAwsEnvVarMessage();
|
|
142
|
-
cmd_1.runCommandExec(startSessionCmd, `Now set to use ${roleName ? `"${roleName}" role` : 'role'}.${awsEnvVarMessage}`, `Failed to use ${roleName ? `"${roleName}" role` : 'role'}.`);
|
|
143
|
-
this.log();
|
|
144
|
-
break;
|
|
145
|
-
}
|
|
146
|
-
default:
|
|
147
|
-
apollo_1.printRequestOutput(this, resp, error);
|
|
148
|
-
}
|
|
149
|
-
break;
|
|
150
|
-
}
|
|
151
|
-
case 'MfaInvalidError': {
|
|
152
|
-
common_1.handleMfaRedirect(this, roleId);
|
|
153
|
-
break;
|
|
154
|
-
}
|
|
155
|
-
case 'OidcIDTokenNotFoundError': {
|
|
156
|
-
common_1.handleOidcRedirect(this, roleId);
|
|
53
|
+
const session = await sessions_1.getOrCreateSession(this, roleId, resources_1.DEFAULT_ACCESS_LEVEL, sessionId, IamSessionMetadataFragment);
|
|
54
|
+
const metadata = session.metadata;
|
|
55
|
+
switch (metadata === null || metadata === void 0 ? void 0 : metadata.__typename) {
|
|
56
|
+
case 'AwsIamFederatedRoleSession': {
|
|
57
|
+
const updateAwsConfigCommand = aws_1.getAwsConfigUpdateCmd(roleName, metadata.awsAccessKeyId, metadata.awsSecretAccessKey, metadata.awsSessionToken);
|
|
58
|
+
const startSessionCmd = `${updateAwsConfigCommand}`;
|
|
59
|
+
const roleText = roleName ? `"${roleName}" role` : 'role';
|
|
60
|
+
const expirationMessage = sessions_1.getSessionExpirationMessage(session);
|
|
61
|
+
cmd_1.runCommandExec(startSessionCmd, `Now set to use ${roleText}. (session expires in ${expirationMessage})${aws_1.getAwsEnvVarMessage()}`, `Failed to use ${roleText}.`);
|
|
157
62
|
break;
|
|
158
63
|
}
|
|
159
64
|
default:
|
|
160
|
-
apollo_1.
|
|
65
|
+
return apollo_1.handleError(this, undefined, session);
|
|
161
66
|
}
|
|
162
67
|
}
|
|
163
68
|
}
|
|
@@ -180,6 +85,6 @@ StartIAMRoleSession.flags = {
|
|
|
180
85
|
}),
|
|
181
86
|
profileName: command_1.flags.string({
|
|
182
87
|
multiple: false,
|
|
183
|
-
description:
|
|
88
|
+
description: 'Uses a custom AWS profile name for the IAM role. Default value is the role\'s name.',
|
|
184
89
|
}),
|
|
185
90
|
};
|
|
@@ -1,151 +1,52 @@
|
|
|
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
|
-
const inquirer = require("inquirer");
|
|
8
|
-
const types_1 = require("../../types");
|
|
9
6
|
const aws_1 = require("../../lib/aws");
|
|
10
7
|
const resources_1 = require("../../lib/resources");
|
|
11
|
-
const
|
|
12
|
-
const
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
endTime
|
|
20
|
-
metadata {
|
|
21
|
-
... on AwsIamFederatedEksSession {
|
|
22
|
-
awsAccessKeyId
|
|
23
|
-
awsSecretAccessKey
|
|
24
|
-
awsSessionToken
|
|
25
|
-
clusterName
|
|
26
|
-
clusterRegion
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
... on SessionNotFoundError {
|
|
32
|
-
message
|
|
33
|
-
}
|
|
34
|
-
... on MfaInvalidError {
|
|
35
|
-
message
|
|
36
|
-
}
|
|
37
|
-
... on OidcIDTokenNotFoundError {
|
|
38
|
-
message
|
|
39
|
-
}
|
|
40
|
-
... on ResourceNotFoundError {
|
|
41
|
-
message
|
|
42
|
-
}
|
|
43
|
-
... on EndSystemAuthorizationError {
|
|
44
|
-
message
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
}`;
|
|
48
|
-
const ListKubeIamRolesDocument = `
|
|
49
|
-
query ListKubeIAMRoles {
|
|
50
|
-
resources(input: {serviceType: KUBERNETES, onlyMine: true, maxNumEntries: 1000}) {
|
|
51
|
-
__typename
|
|
52
|
-
... on ResourcesResult {
|
|
53
|
-
resources {
|
|
54
|
-
name
|
|
55
|
-
id
|
|
56
|
-
connection {
|
|
57
|
-
connectionType
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
cursor
|
|
61
|
-
}
|
|
62
|
-
}
|
|
8
|
+
const sessions_1 = require("../../lib/sessions");
|
|
9
|
+
const EksSessionMetadataFragment = `
|
|
10
|
+
... on AwsIamFederatedEksSession {
|
|
11
|
+
awsAccessKeyId
|
|
12
|
+
awsSecretAccessKey
|
|
13
|
+
awsSessionToken
|
|
14
|
+
clusterName
|
|
15
|
+
clusterRegion
|
|
63
16
|
}`;
|
|
64
17
|
class StartKubeIAMRoleSession extends command_1.Command {
|
|
65
18
|
async run() {
|
|
66
19
|
cmd_1.setMostRecentCommand(this);
|
|
67
20
|
const { flags } = this.parse(StartKubeIAMRoleSession);
|
|
68
|
-
// TODO: RESOURCES-1: How do we grant access to a perm using ID
|
|
69
21
|
let clusterId = flags.id;
|
|
70
22
|
const sessionId = flags.sessionId;
|
|
71
23
|
if (!clusterId) {
|
|
72
|
-
const
|
|
73
|
-
|
|
74
|
-
query: ListKubeIamRolesDocument,
|
|
75
|
-
variables: {},
|
|
76
|
-
});
|
|
77
|
-
if (error) {
|
|
78
|
-
apollo_1.printRequestOutput(this, kubeIamRolesResp, error);
|
|
79
|
-
return;
|
|
80
|
-
}
|
|
81
|
-
const resourceInfos = kubeIamRolesResp === null || kubeIamRolesResp === void 0 ? void 0 : kubeIamRolesResp.data.resources.resources.filter((resource) => { var _a; return ((_a = resource.connection) === null || _a === void 0 ? void 0 : _a.connectionType) === types_1.ConnectionType.Aws; }).map((resource) => {
|
|
82
|
-
return {
|
|
83
|
-
id: resource.id,
|
|
84
|
-
name: resource.name,
|
|
85
|
-
};
|
|
86
|
-
});
|
|
87
|
-
const noResourcesFound = resources_1.resourcesAreEmpty(this, resourceInfos);
|
|
88
|
-
if (noResourcesFound) {
|
|
89
|
-
return;
|
|
90
|
-
}
|
|
91
|
-
const resourceInfoByName = {};
|
|
92
|
-
resourceInfos.forEach(resourceInfo => {
|
|
93
|
-
resourceInfoByName[resourceInfo.name] = resourceInfo;
|
|
94
|
-
});
|
|
95
|
-
inquirer.registerPrompt('autocomplete', require('inquirer-autocomplete-prompt'));
|
|
96
|
-
const selectedKubeClusterInfo = await inquirer.prompt([
|
|
97
|
-
{
|
|
98
|
-
name: 'role',
|
|
99
|
-
message: 'Select a Kubernetes cluster to connect to',
|
|
100
|
-
type: 'autocomplete',
|
|
101
|
-
source: (answers, input) => cmd_1.filterChoices(input, resourceInfos),
|
|
102
|
-
},
|
|
103
|
-
]);
|
|
104
|
-
const selectedKubeCluster = resourceInfoByName[selectedKubeClusterInfo.role];
|
|
105
|
-
if (!selectedKubeCluster) {
|
|
24
|
+
const selectedCluster = await resources_1.promptUserForResource(this, 'AWS_EKS_CLUSTER', 'Select an EKS Kubernetes cluster to connect to');
|
|
25
|
+
if (!selectedCluster) {
|
|
106
26
|
return;
|
|
107
27
|
}
|
|
108
|
-
clusterId =
|
|
109
|
-
// TODO: RESOURCES-2: Select the access level for the K8s cluster
|
|
28
|
+
clusterId = selectedCluster.id;
|
|
110
29
|
}
|
|
111
30
|
// Fetch all access levels for resource
|
|
112
31
|
const accessLevel = await resources_1.promptUserForAccessLevels(this, clusterId, 'Kubernetes cluster', flags.accessLevelRemoteId);
|
|
113
32
|
if (!accessLevel) {
|
|
114
33
|
return;
|
|
115
34
|
}
|
|
116
|
-
const
|
|
117
|
-
const
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
const
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
const updateAwsConfigCommand = aws_1.getAwsConfigUpdateCmd(roleName, metadata.awsAccessKeyId, metadata.awsSecretAccessKey, metadata.awsSessionToken);
|
|
128
|
-
const updateKubeConfigCmd = `aws eks update-kubeconfig --name ${metadata.clusterName} --region ${metadata.clusterRegion} --alias ${metadata.clusterName} --profile opal`;
|
|
129
|
-
const startSessionCmd = `${updateAwsConfigCommand} && ${updateKubeConfigCmd}`;
|
|
130
|
-
const awsEnvVarMessage = aws_1.getAwsEnvVarMessage();
|
|
131
|
-
cmd_1.runCommandExec(startSessionCmd, `Now set to use ${roleName ? `"${roleName}" role` : 'role'} with updated Kube config pointing to "${metadata.clusterName}" cluster.${awsEnvVarMessage}`, `Failed to assume ${roleName ? `"${roleName}" role` : 'role'} and update Kube config.`);
|
|
132
|
-
break;
|
|
133
|
-
}
|
|
134
|
-
default:
|
|
135
|
-
apollo_1.printRequestOutput(this, resp, error);
|
|
136
|
-
}
|
|
137
|
-
break;
|
|
138
|
-
}
|
|
139
|
-
case 'MfaInvalidError': {
|
|
140
|
-
common_1.handleMfaRedirect(this, clusterId);
|
|
141
|
-
break;
|
|
142
|
-
}
|
|
143
|
-
case 'OidcIDTokenNotFoundError': {
|
|
144
|
-
common_1.handleOidcRedirect(this, clusterId);
|
|
35
|
+
const session = await sessions_1.getOrCreateSession(this, clusterId, accessLevel, sessionId, EksSessionMetadataFragment);
|
|
36
|
+
const metadata = session.metadata;
|
|
37
|
+
switch (metadata === null || metadata === void 0 ? void 0 : metadata.__typename) {
|
|
38
|
+
case 'AwsIamFederatedEksSession': {
|
|
39
|
+
const roleName = accessLevel.accessLevelName;
|
|
40
|
+
const updateAwsConfigCommand = aws_1.getAwsConfigUpdateCmd(roleName, metadata.awsAccessKeyId, metadata.awsSecretAccessKey, metadata.awsSessionToken);
|
|
41
|
+
const updateKubeConfigCmd = `aws eks update-kubeconfig --name ${metadata.clusterName} --region ${metadata.clusterRegion} --alias ${metadata.clusterName} --profile opal`;
|
|
42
|
+
const startSessionCmd = `${updateAwsConfigCommand} && ${updateKubeConfigCmd}`;
|
|
43
|
+
const roleText = roleName ? `"${roleName}" role` : 'role';
|
|
44
|
+
const expirationMessage = sessions_1.getSessionExpirationMessage(session);
|
|
45
|
+
cmd_1.runCommandExec(startSessionCmd, `Now set to use ${roleText} with updated Kube config pointing to "${metadata.clusterName}" cluster. (session expires in ${expirationMessage})${aws_1.getAwsEnvVarMessage()}`, `Failed to assume ${roleText} and update Kube config.`);
|
|
145
46
|
break;
|
|
146
47
|
}
|
|
147
48
|
default:
|
|
148
|
-
apollo_1.
|
|
49
|
+
return apollo_1.handleError(this, undefined, session);
|
|
149
50
|
}
|
|
150
51
|
}
|
|
151
52
|
}
|
package/lib/commands/login.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Command } from '@oclif/command';
|
|
1
|
+
import { Command, flags } from '@oclif/command';
|
|
2
2
|
export declare const CLIAuthSessionCheckName = "CLIAuthSessionCheck";
|
|
3
3
|
export declare const CLIAuthSessionCheckDocument = "\nquery CLIAuthSessionCheck {\n organizationSettings {\n ... on OrganizationSettingsResult {\n settings {\n id\n }\n }\n }\n}\n";
|
|
4
4
|
export default class Login extends Command {
|
|
@@ -6,6 +6,7 @@ export default class Login extends Command {
|
|
|
6
6
|
static examples: string[];
|
|
7
7
|
static flags: {
|
|
8
8
|
help: import("@oclif/parser/lib/flags").IBooleanFlag<void>;
|
|
9
|
+
email: flags.IOptionFlag<string | undefined>;
|
|
9
10
|
};
|
|
10
11
|
static args: never[];
|
|
11
12
|
run(): Promise<void>;
|