opal-security 3.0.0 → 3.0.1-beta.4f1a7ce
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 +59 -44
- package/bin/run +1 -1
- package/lib/commands/aws/identity.d.ts +1 -1
- package/lib/commands/aws/identity.js +2 -2
- package/lib/commands/clear-auth-provider.d.ts +1 -1
- package/lib/commands/clear-auth-provider.js +3 -3
- package/lib/commands/curl-example.d.ts +1 -1
- package/lib/commands/curl-example.js +2 -2
- package/lib/commands/iam-roles/start.d.ts +1 -1
- package/lib/commands/iam-roles/start.js +14 -14
- package/lib/commands/kube-roles/start.d.ts +1 -1
- package/lib/commands/kube-roles/start.js +10 -10
- package/lib/commands/login.d.ts +1 -1
- package/lib/commands/login.js +71 -63
- package/lib/commands/logout.d.ts +1 -1
- package/lib/commands/logout.js +3 -3
- package/lib/commands/postgres-instances/start.d.ts +1 -1
- package/lib/commands/postgres-instances/start.js +35 -34
- package/lib/commands/request/create.d.ts +6 -0
- package/lib/commands/request/create.js +37 -0
- package/lib/commands/request/get.d.ts +6 -0
- package/lib/commands/request/get.js +13 -0
- package/lib/commands/request/list.d.ts +7 -0
- package/lib/commands/request/list.js +14 -0
- package/lib/commands/resources/get.d.ts +1 -1
- package/lib/commands/resources/get.js +11 -4
- package/lib/commands/set-auth-provider.d.ts +1 -1
- package/lib/commands/set-auth-provider.js +6 -4
- package/lib/commands/set-custom-header.d.ts +1 -1
- package/lib/commands/set-custom-header.js +5 -3
- package/lib/commands/set-token.d.ts +1 -1
- package/lib/commands/set-token.js +26 -19
- package/lib/commands/set-url.d.ts +1 -1
- package/lib/commands/set-url.js +13 -12
- package/lib/commands/ssh/copyFrom.d.ts +1 -1
- package/lib/commands/ssh/copyFrom.js +13 -13
- package/lib/commands/ssh/copyTo.d.ts +1 -1
- package/lib/commands/ssh/copyTo.js +13 -13
- package/lib/commands/ssh/start.d.ts +1 -1
- package/lib/commands/ssh/start.js +14 -15
- package/lib/graphql/fragment-masking.d.ts +19 -0
- package/lib/graphql/fragment-masking.js +21 -0
- package/lib/graphql/gql.d.ts +46 -0
- package/lib/graphql/gql.js +14 -0
- package/lib/graphql/graphql.d.ts +11476 -0
- package/lib/graphql/graphql.js +1819 -0
- package/lib/graphql/index.d.ts +2 -0
- package/lib/graphql/index.js +5 -0
- package/lib/handler.d.ts +5 -5
- package/lib/handler.js +7 -7
- package/lib/index.d.ts +1 -1
- package/lib/lib/apollo.d.ts +3 -2
- package/lib/lib/apollo.js +59 -46
- package/lib/lib/aws.js +15 -12
- package/lib/lib/cmd.d.ts +4 -6
- package/lib/lib/cmd.js +11 -11
- package/lib/lib/config.js +14 -14
- package/lib/lib/credentials/index.d.ts +1 -1
- package/lib/lib/credentials/index.js +6 -6
- package/lib/lib/credentials/keychain.js +5 -5
- package/lib/lib/credentials/localEncryption.d.ts +2 -2
- package/lib/lib/credentials/localEncryption.js +33 -24
- package/lib/lib/flags.js +9 -9
- package/lib/lib/requests.d.ts +22 -0
- package/lib/lib/requests.js +274 -0
- package/lib/lib/resources.d.ts +2 -2
- package/lib/lib/resources.js +29 -23
- package/lib/lib/sessions.d.ts +2 -2
- package/lib/lib/sessions.js +18 -17
- package/lib/lib/ssh.d.ts +1 -1
- package/lib/lib/ssh.js +8 -8
- package/lib/lib/util.d.ts +0 -1
- package/lib/lib/util.js +13 -13
- package/lib/types.d.ts +1787 -1787
- package/lib/utils/displays.d.ts +5 -0
- package/lib/utils/displays.js +65 -0
- package/lib/utils/utils.d.ts +1 -0
- package/lib/utils/utils.js +18 -0
- package/oclif.manifest.json +70 -3
- package/package.json +25 -29
package/lib/handler.d.ts
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import type { ApolloError, OperationVariables } from "@apollo/client/core";
|
|
2
|
+
import type { Command } from "@oclif/core";
|
|
3
3
|
interface QueryHandlerProps<TVar = Record<string, any>> {
|
|
4
4
|
command: Command;
|
|
5
5
|
query: string;
|
|
6
6
|
variables?: TVar;
|
|
7
7
|
}
|
|
8
8
|
export declare const runMutation: ({ command, query, variables, }: QueryHandlerProps) => Promise<{
|
|
9
|
-
resp: import("@apollo/client/core").FetchResult<any> | null;
|
|
9
|
+
resp: import("@apollo/client/core").FetchResult<any> | null | undefined;
|
|
10
10
|
error: unknown;
|
|
11
11
|
}>;
|
|
12
|
-
export declare const
|
|
13
|
-
resp: import("@apollo/client/core").ApolloQueryResult<TResponse> | null;
|
|
12
|
+
export declare const runQueryDeprecated: <TResponse = any, TVar extends OperationVariables = Record<string, any>>({ command, query, variables, }: QueryHandlerProps<TVar>) => Promise<{
|
|
13
|
+
resp: import("@apollo/client/core").ApolloQueryResult<TResponse> | null | undefined;
|
|
14
14
|
error: ApolloError;
|
|
15
15
|
}>;
|
|
16
16
|
export {};
|
package/lib/handler.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.runQueryDeprecated = exports.runMutation = void 0;
|
|
4
4
|
const graphql_tag_1 = require("graphql-tag");
|
|
5
5
|
const apollo_1 = require("./lib/apollo");
|
|
6
6
|
const runMutation = async ({ command, query, variables, }) => {
|
|
@@ -8,12 +8,12 @@ const runMutation = async ({ command, query, variables, }) => {
|
|
|
8
8
|
let mutationResp = null;
|
|
9
9
|
let mutationError = null;
|
|
10
10
|
try {
|
|
11
|
-
mutationResp = await apollo_1.client.mutate({
|
|
11
|
+
mutationResp = await (apollo_1.client === null || apollo_1.client === void 0 ? void 0 : apollo_1.client.mutate({
|
|
12
12
|
mutation: (0, graphql_tag_1.default) `
|
|
13
13
|
${query}
|
|
14
14
|
`,
|
|
15
15
|
variables: variables,
|
|
16
|
-
});
|
|
16
|
+
}));
|
|
17
17
|
}
|
|
18
18
|
catch (error) {
|
|
19
19
|
mutationError = error;
|
|
@@ -21,21 +21,21 @@ const runMutation = async ({ command, query, variables, }) => {
|
|
|
21
21
|
return { resp: mutationResp, error: mutationError };
|
|
22
22
|
};
|
|
23
23
|
exports.runMutation = runMutation;
|
|
24
|
-
const
|
|
24
|
+
const runQueryDeprecated = async ({ command, query, variables, }) => {
|
|
25
25
|
await (0, apollo_1.initClient)(command);
|
|
26
26
|
let queryResp = null;
|
|
27
27
|
let queryError = null;
|
|
28
28
|
try {
|
|
29
|
-
queryResp = await apollo_1.client.query({
|
|
29
|
+
queryResp = await (apollo_1.client === null || apollo_1.client === void 0 ? void 0 : apollo_1.client.query({
|
|
30
30
|
query: (0, graphql_tag_1.default) `
|
|
31
31
|
${query}
|
|
32
32
|
`,
|
|
33
33
|
variables: variables,
|
|
34
|
-
});
|
|
34
|
+
}));
|
|
35
35
|
}
|
|
36
36
|
catch (error) {
|
|
37
37
|
queryError = error;
|
|
38
38
|
}
|
|
39
39
|
return { resp: queryResp, error: queryError };
|
|
40
40
|
};
|
|
41
|
-
exports.
|
|
41
|
+
exports.runQueryDeprecated = runQueryDeprecated;
|
package/lib/index.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export { run } from
|
|
1
|
+
export { run } from "@oclif/core";
|
package/lib/lib/apollo.d.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import { ApolloClient, NormalizedCacheObject } from
|
|
2
|
-
import { Command } from
|
|
1
|
+
import { ApolloClient, type NormalizedCacheObject } from "@apollo/client/core";
|
|
2
|
+
import type { Command } from "@oclif/core";
|
|
3
3
|
export declare let client: ApolloClient<NormalizedCacheObject> | null;
|
|
4
4
|
export declare let cookieStr: string;
|
|
5
5
|
export declare const printResponse: (command: Command, resp: any) => void;
|
|
6
6
|
export declare const handleError: (command: Command, err: any, resp?: any) => void;
|
|
7
7
|
export declare const initClient: (command: Command, fetchAccessToken?: boolean) => Promise<void>;
|
|
8
|
+
export declare function getClient(command: Command, fetchAccessToken?: boolean): Promise<ApolloClient<NormalizedCacheObject>>;
|
package/lib/lib/apollo.js
CHANGED
|
@@ -1,27 +1,32 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.initClient = exports.handleError = exports.printResponse = exports.cookieStr = exports.client = void 0;
|
|
4
|
+
exports.getClient = getClient;
|
|
4
5
|
const core_1 = require("@apollo/client/core");
|
|
5
6
|
const context_1 = require("@apollo/client/link/context");
|
|
6
7
|
const error_1 = require("@apollo/client/link/error");
|
|
7
|
-
const prettyjson_1 = require("prettyjson");
|
|
8
|
-
const semver_1 = require("semver");
|
|
9
8
|
const chalk_1 = require("chalk");
|
|
10
9
|
const moment = require("moment");
|
|
11
|
-
const
|
|
12
|
-
const
|
|
10
|
+
const prettyjson_1 = require("prettyjson");
|
|
11
|
+
const semver_1 = require("semver");
|
|
12
|
+
const globals_1 = require("@apollo/client/utilities/globals");
|
|
13
13
|
const login_1 = require("../commands/login");
|
|
14
14
|
const cmd_1 = require("../lib/cmd");
|
|
15
|
-
const
|
|
16
|
-
const
|
|
17
|
-
const
|
|
15
|
+
const config_1 = require("../lib/config");
|
|
16
|
+
const credentials_1 = require("../lib/credentials");
|
|
17
|
+
const fetch = require("node-fetch");
|
|
18
|
+
const https = require("node:https");
|
|
19
|
+
const http = require("node:http");
|
|
20
|
+
// DO NOT USE DIRECTLY, use getClient instead
|
|
18
21
|
exports.client = null;
|
|
19
22
|
// This is used to keep track of the auth-session cookie during login, before we can persist it into the credential store
|
|
20
|
-
exports.cookieStr =
|
|
23
|
+
exports.cookieStr = "";
|
|
21
24
|
let alreadyWarnedAboutVersion = false;
|
|
22
25
|
const printResponse = (command, resp) => {
|
|
23
26
|
const filteredJson = JSON.parse(JSON.stringify(resp.data, (k, v) => {
|
|
24
|
-
if (k ===
|
|
27
|
+
if (k === "__typename" ||
|
|
28
|
+
v === null ||
|
|
29
|
+
(Array.isArray(v) && v.length === 0)) {
|
|
25
30
|
return undefined;
|
|
26
31
|
}
|
|
27
32
|
return v;
|
|
@@ -30,27 +35,32 @@ const printResponse = (command, resp) => {
|
|
|
30
35
|
};
|
|
31
36
|
exports.printResponse = printResponse;
|
|
32
37
|
const handleError = (command, err, resp) => {
|
|
33
|
-
if (err &&
|
|
38
|
+
if (err &&
|
|
39
|
+
typeof err === "object" &&
|
|
40
|
+
"networkError" in err &&
|
|
41
|
+
"statusCode" in err.networkError) {
|
|
34
42
|
// Status code errors are already handled in the global Apollo handler, so we can just return here.
|
|
35
43
|
return;
|
|
36
44
|
}
|
|
37
45
|
let errorMsg;
|
|
38
46
|
if (!err) {
|
|
39
|
-
errorMsg =
|
|
47
|
+
errorMsg =
|
|
48
|
+
"Unexpected response from server (see below). Please contact Opal support if this issue persists.";
|
|
40
49
|
}
|
|
41
|
-
else if (typeof err ===
|
|
42
|
-
|
|
50
|
+
else if (typeof err === "object" &&
|
|
51
|
+
err.toString().includes("self signed certificate")) {
|
|
52
|
+
errorMsg =
|
|
53
|
+
'Request failed due to a self-signed certificate appearing in the certificate chain. Try setting your CLI to allow self-signed certs by running: "opal set-url --custom INSERT_URL_HERE --allowSelfSignedCerts"';
|
|
43
54
|
}
|
|
44
55
|
else {
|
|
45
56
|
errorMsg = `Error: ${err}`;
|
|
46
57
|
}
|
|
47
|
-
errorMsg =
|
|
58
|
+
errorMsg = `❗ ${errorMsg}`;
|
|
48
59
|
command.log(errorMsg);
|
|
49
60
|
if (resp) {
|
|
50
61
|
(0, exports.printResponse)(command, resp);
|
|
51
62
|
}
|
|
52
63
|
// OPAL-6579: Use process.exit to avoid UnhandledPromiseRejectionWarning
|
|
53
|
-
// eslint-disable-next-line no-process-exit,unicorn/no-process-exit
|
|
54
64
|
process.exit(1);
|
|
55
65
|
};
|
|
56
66
|
exports.handleError = handleError;
|
|
@@ -66,24 +76,20 @@ const initClient = async (command, fetchAccessToken = true) => {
|
|
|
66
76
|
const httpAgent = new http.Agent({});
|
|
67
77
|
const specifiedUrl = configData[config_1.urlKey];
|
|
68
78
|
const customHeader = configData[config_1.customHttpHeaderKey];
|
|
69
|
-
const customHeaderKey = customHeader === undefined ?
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
const customHeaderValue = customHeader === undefined ?
|
|
73
|
-
'' :
|
|
74
|
-
customHeader.split(':')[1];
|
|
75
|
-
const agent = specifiedUrl.includes('https') ? httpsAgent : httpAgent;
|
|
79
|
+
const customHeaderKey = customHeader === undefined ? "" : customHeader.split(":")[0];
|
|
80
|
+
const customHeaderValue = customHeader === undefined ? "" : customHeader.split(":")[1];
|
|
81
|
+
const agent = specifiedUrl.includes("https") ? httpsAgent : httpAgent;
|
|
76
82
|
const httpLink = (0, core_1.createHttpLink)({
|
|
77
83
|
uri: `${specifiedUrl}/query`,
|
|
78
|
-
credentials:
|
|
84
|
+
credentials: "include",
|
|
79
85
|
fetch,
|
|
80
86
|
fetchOptions: {
|
|
81
87
|
agent: agent,
|
|
82
|
-
credentials:
|
|
88
|
+
credentials: "include",
|
|
83
89
|
},
|
|
84
90
|
});
|
|
85
91
|
const authLink = (0, context_1.setContext)((_, { headers }) => {
|
|
86
|
-
const baseHeaders = Object.assign(Object.assign({}, headers), {
|
|
92
|
+
const baseHeaders = Object.assign(Object.assign({}, headers), { "User-Agent": `Opal CLI v${currentCLIVersion}`, "X-Opal-Organization-ID": organizationID, "X-Opal-Cli-Version": currentCLIVersion });
|
|
87
93
|
if (opalCreds.secretType === credentials_1.SecretType.ApiToken) {
|
|
88
94
|
baseHeaders.authorization = `Bearer ${opalCreds.secret}`;
|
|
89
95
|
}
|
|
@@ -113,37 +119,38 @@ const initClient = async (command, fetchAccessToken = true) => {
|
|
|
113
119
|
const headers = (_a = operation.getContext().response) === null || _a === void 0 ? void 0 : _a.headers;
|
|
114
120
|
if (!alreadyWarnedAboutVersion && headers) {
|
|
115
121
|
// we expect these versions to be a single number - a major version
|
|
116
|
-
const expectedCLIMajorVersion = headers.get(
|
|
117
|
-
if (expectedCLIMajorVersion
|
|
122
|
+
const expectedCLIMajorVersion = headers.get("Opal-CLI-Expected-Major-Version");
|
|
123
|
+
if (expectedCLIMajorVersion === null || expectedCLIMajorVersion === void 0 ? void 0 : expectedCLIMajorVersion.match(/^\d+$/)) {
|
|
118
124
|
const semverExpectedMinCLIVersion = `${expectedCLIMajorVersion}.0.0`;
|
|
119
125
|
if ((0, semver_1.major)(currentCLIVersion) < (0, semver_1.major)(semverExpectedMinCLIVersion)) {
|
|
120
126
|
command.log(chalk_1.default.yellow(`
|
|
121
|
-
|
|
127
|
+
❗ Your CLI is outdated and is incompatible with your Opal server.
|
|
122
128
|
Expected major version ${chalk_1.default.blueBright(semverExpectedMinCLIVersion)}, but version ${chalk_1.default.blueBright(currentCLIVersion)} is installed.
|
|
123
|
-
Upgrade using the following command: ${chalk_1.default.blueBright(
|
|
129
|
+
Upgrade using the following command: ${chalk_1.default.blueBright("brew upgrade opalsecurity/brew/opal-security")}\n`));
|
|
124
130
|
alreadyWarnedAboutVersion = true;
|
|
125
131
|
}
|
|
126
132
|
else if ((0, semver_1.major)(currentCLIVersion) > (0, semver_1.major)(semverExpectedMinCLIVersion)) {
|
|
127
133
|
command.log(chalk_1.default.yellow(`
|
|
128
|
-
|
|
134
|
+
❗ Uh oh! The currently installed Opal server is outdated. Please contact your Opal admins to let them know they need to upgrade their deployment.\n`));
|
|
129
135
|
alreadyWarnedAboutVersion = true;
|
|
130
136
|
}
|
|
131
137
|
}
|
|
132
|
-
const recommendedCLIMajorVersion = headers.get(
|
|
133
|
-
if (recommendedCLIMajorVersion
|
|
138
|
+
const recommendedCLIMajorVersion = headers.get("Opal-CLI-Recommended-Version");
|
|
139
|
+
if (recommendedCLIMajorVersion === null || recommendedCLIMajorVersion === void 0 ? void 0 : recommendedCLIMajorVersion.match(/^\d+$/)) {
|
|
134
140
|
const recommendedSemverString = `${recommendedCLIMajorVersion}.0.0`;
|
|
135
|
-
if (recommendedSemverString &&
|
|
141
|
+
if (recommendedSemverString &&
|
|
142
|
+
(0, semver_1.major)(currentCLIVersion) < (0, semver_1.major)(recommendedSemverString)) {
|
|
136
143
|
command.log(chalk_1.default.yellow(`
|
|
137
|
-
|
|
144
|
+
❗ Opal recommends that you upgrade your CLI.
|
|
138
145
|
Recommended version >=${chalk_1.default.blueBright(recommendedSemverString)}, but version ${chalk_1.default.blueBright(currentCLIVersion)} is installed.
|
|
139
|
-
Upgrade using the following command: ${chalk_1.default.blueBright(
|
|
146
|
+
Upgrade using the following command: ${chalk_1.default.blueBright("brew upgrade opalsecurity/brew/opal-security")}\n`));
|
|
140
147
|
}
|
|
141
148
|
alreadyWarnedAboutVersion = true;
|
|
142
149
|
}
|
|
143
150
|
}
|
|
144
151
|
};
|
|
145
152
|
const checkCLIVersionLink = new core_1.ApolloLink((operation, forward) => {
|
|
146
|
-
return forward(operation).map(response => {
|
|
153
|
+
return forward(operation).map((response) => {
|
|
147
154
|
checkCLIVersion(operation);
|
|
148
155
|
return response;
|
|
149
156
|
});
|
|
@@ -164,9 +171,9 @@ const initClient = async (command, fetchAccessToken = true) => {
|
|
|
164
171
|
if (customErrorOperations.includes(operation.operationName)) {
|
|
165
172
|
return;
|
|
166
173
|
}
|
|
167
|
-
if (networkError &&
|
|
174
|
+
if (networkError && "statusCode" in networkError) {
|
|
168
175
|
let errorMessage = null;
|
|
169
|
-
if (
|
|
176
|
+
if ("result" in networkError) {
|
|
170
177
|
const result = networkError.result;
|
|
171
178
|
// result is now of type string | Record<string, any>
|
|
172
179
|
if (typeof result === "string")
|
|
@@ -177,12 +184,13 @@ const initClient = async (command, fetchAccessToken = true) => {
|
|
|
177
184
|
}
|
|
178
185
|
switch (networkError.statusCode) {
|
|
179
186
|
case 401: {
|
|
180
|
-
command.log(
|
|
187
|
+
command.log("Your session is invalid or expired. Authenticating now...\n");
|
|
181
188
|
const loginCommand = new login_1.default([], command.config);
|
|
182
189
|
loginCommand.run().then(() => {
|
|
183
190
|
if (cmd_1.mostRecentCommandTime && cmd_1.mostRecentCommand) {
|
|
184
|
-
const lastCommandReexecutionDuration = moment.duration(2,
|
|
185
|
-
const lastCommandReexecutionDurationHasElapsed = cmd_1.mostRecentCommandTime.add(lastCommandReexecutionDuration) >
|
|
191
|
+
const lastCommandReexecutionDuration = moment.duration(2, "minutes");
|
|
192
|
+
const lastCommandReexecutionDurationHasElapsed = cmd_1.mostRecentCommandTime.add(lastCommandReexecutionDuration) >
|
|
193
|
+
moment(new Date());
|
|
186
194
|
if (lastCommandReexecutionDurationHasElapsed) {
|
|
187
195
|
cmd_1.mostRecentCommand.run();
|
|
188
196
|
}
|
|
@@ -191,17 +199,17 @@ const initClient = async (command, fetchAccessToken = true) => {
|
|
|
191
199
|
break;
|
|
192
200
|
}
|
|
193
201
|
default:
|
|
194
|
-
return (0, exports.handleError)(command, `Received status code ${networkError.statusCode} from server${errorMessage ? ` with message "${errorMessage}"` :
|
|
202
|
+
return (0, exports.handleError)(command, `Received status code ${networkError.statusCode} from server${errorMessage ? ` with message "${errorMessage}"` : ""}`);
|
|
195
203
|
}
|
|
196
204
|
}
|
|
197
205
|
});
|
|
198
206
|
// Parses our auth-session cookie out of the Set-Cookie response header, saving it locally so we can use it for future requests
|
|
199
207
|
const preserveCookiesLink = new core_1.ApolloLink((operation, forward) => {
|
|
200
|
-
return forward(operation).map(response => {
|
|
208
|
+
return forward(operation).map((response) => {
|
|
201
209
|
var _a, _b, _c, _d;
|
|
202
|
-
const cookieHeaderStr = (_c = (_b = (_a = operation.getContext().response) === null || _a === void 0 ? void 0 : _a.headers) === null || _b === void 0 ? void 0 : _b.get(
|
|
210
|
+
const cookieHeaderStr = (_c = (_b = (_a = operation.getContext().response) === null || _a === void 0 ? void 0 : _a.headers) === null || _b === void 0 ? void 0 : _b.get("Set-Cookie")) !== null && _c !== void 0 ? _c : "";
|
|
203
211
|
const authSessionCookie = (_d = cookieHeaderStr.match(/auth-session=[^;]+;/)) === null || _d === void 0 ? void 0 : _d[0];
|
|
204
|
-
if (
|
|
212
|
+
if (authSessionCookie) {
|
|
205
213
|
exports.cookieStr = authSessionCookie;
|
|
206
214
|
}
|
|
207
215
|
return response;
|
|
@@ -213,8 +221,13 @@ const initClient = async (command, fetchAccessToken = true) => {
|
|
|
213
221
|
link = errorLink.concat(link);
|
|
214
222
|
exports.client = new core_1.ApolloClient({
|
|
215
223
|
link: link,
|
|
216
|
-
credentials:
|
|
224
|
+
credentials: "include",
|
|
217
225
|
cache: new core_1.InMemoryCache(),
|
|
218
226
|
});
|
|
219
227
|
};
|
|
220
228
|
exports.initClient = initClient;
|
|
229
|
+
async function getClient(command, fetchAccessToken = true) {
|
|
230
|
+
await (0, exports.initClient)(command, fetchAccessToken);
|
|
231
|
+
(0, globals_1.invariant)(exports.client, "Failed to initialize Opal Client");
|
|
232
|
+
return exports.client;
|
|
233
|
+
}
|
package/lib/lib/aws.js
CHANGED
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.getAwsEnvVarMessage = exports.getAwsConfigUpdateCmd = void 0;
|
|
4
|
-
const opalProfileKey =
|
|
4
|
+
const opalProfileKey = "opal";
|
|
5
5
|
const sanitize = (str) => {
|
|
6
6
|
// Remove non standard characters.
|
|
7
7
|
// Note: AWS supports profile names containing alphanumeric characters, symbols, and white spaces
|
|
8
8
|
// from the ASCII character set.
|
|
9
|
-
let sanitizedStr = str.replace(/[^A-Za-z0-9-_ ]/g,
|
|
9
|
+
let sanitizedStr = str.replace(/[^A-Za-z0-9-_ ]/g, "");
|
|
10
10
|
// De-dupe spaces
|
|
11
|
-
sanitizedStr = sanitizedStr.replace(/\s+/g,
|
|
11
|
+
sanitizedStr = sanitizedStr.replace(/\s+/g, " ");
|
|
12
12
|
// Map remaining spaces to '-'
|
|
13
|
-
sanitizedStr = sanitizedStr.replace(/ /g,
|
|
13
|
+
sanitizedStr = sanitizedStr.replace(/ /g, "-");
|
|
14
14
|
return sanitizedStr;
|
|
15
15
|
};
|
|
16
16
|
const getAwsConfigUpdateCmd = (itemName, awsAccessKeyId, awsSecretAccessKey, awsSessionToken) => {
|
|
17
|
-
let updateProfilesCmd =
|
|
17
|
+
let updateProfilesCmd = "";
|
|
18
18
|
const sanitizedProfileName = sanitize(itemName);
|
|
19
19
|
const profileNames = [opalProfileKey, sanitizedProfileName];
|
|
20
20
|
profileNames.forEach((profileName, i) => {
|
|
@@ -25,25 +25,28 @@ const getAwsConfigUpdateCmd = (itemName, awsAccessKeyId, awsSecretAccessKey, aws
|
|
|
25
25
|
const cmd = `${updateAccessKeyCmd} && ${updateAccessSecretCmd} && ${updateSessionTokenCmd}`;
|
|
26
26
|
updateProfilesCmd += cmd;
|
|
27
27
|
if (i !== profileNames.length - 1) {
|
|
28
|
-
updateProfilesCmd +=
|
|
28
|
+
updateProfilesCmd += "&& ";
|
|
29
29
|
}
|
|
30
30
|
});
|
|
31
31
|
return updateProfilesCmd;
|
|
32
32
|
};
|
|
33
33
|
exports.getAwsConfigUpdateCmd = getAwsConfigUpdateCmd;
|
|
34
34
|
const getAwsEnvVarMessage = () => {
|
|
35
|
-
if (!process.env.AWS_DEFAULT_PROFILE ||
|
|
36
|
-
|
|
35
|
+
if (!process.env.AWS_DEFAULT_PROFILE ||
|
|
36
|
+
process.env.AWS_DEFAULT_PROFILE !== opalProfileKey) {
|
|
37
|
+
let envVarPhrase = "";
|
|
37
38
|
if (!process.env.AWS_DEFAULT_PROFILE) {
|
|
38
|
-
envVarPhrase =
|
|
39
|
+
envVarPhrase = "unset";
|
|
39
40
|
}
|
|
40
41
|
else if (process.env.AWS_DEFAULT_PROFILE !== opalProfileKey) {
|
|
41
42
|
envVarPhrase = `set to "${process.env.AWS_DEFAULT_PROFILE}"`;
|
|
42
43
|
}
|
|
43
|
-
return
|
|
44
|
+
return (
|
|
45
|
+
// biome-ignore lint/style/useTemplate: it's more readable if split across lines
|
|
46
|
+
"\n\n💡 Did you know you can set your AWS_DEFAULT_PROFILE environment " +
|
|
44
47
|
`variable to "${opalProfileKey}" to avoid explicitly specifying profile in each command? ` +
|
|
45
|
-
`Currently, this variable is ${envVarPhrase}
|
|
48
|
+
`Currently, this variable is ${envVarPhrase}.`);
|
|
46
49
|
}
|
|
47
|
-
return
|
|
50
|
+
return "";
|
|
48
51
|
};
|
|
49
52
|
exports.getAwsEnvVarMessage = getAwsEnvVarMessage;
|
package/lib/lib/cmd.d.ts
CHANGED
|
@@ -1,12 +1,10 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
import
|
|
4
|
-
import { Command } from '@oclif/core';
|
|
5
|
-
import * as moment from 'moment';
|
|
1
|
+
import type { ExecException } from "node:child_process";
|
|
2
|
+
import type { Command } from "@oclif/core";
|
|
3
|
+
import * as moment from "moment";
|
|
6
4
|
export declare let mostRecentCommand: Command | null;
|
|
7
5
|
export declare let mostRecentCommandTime: moment.Moment | null;
|
|
8
6
|
export declare const setMostRecentCommand: (cmd: Command) => void;
|
|
9
7
|
export declare const startInteractiveShell: (runCmd: string, shellName?: string) => void;
|
|
10
8
|
export declare const runCommandExec: (runCmd: string, successMessage: string, errorMessage: string, envVars?: Record<string, any>) => void;
|
|
11
|
-
export declare const runCommandExecWithCallback: (cmd: string, callback?: (
|
|
9
|
+
export declare const runCommandExecWithCallback: (cmd: string, callback?: (error: ExecException | null, stdout: Buffer, stderr: Buffer) => void) => Promise<unknown>;
|
|
12
10
|
export declare const runCommandSpawn: (runCmd: string, successMessage: string, errorMessage: string, envVars?: Record<string, any>) => void;
|
package/lib/lib/cmd.js
CHANGED
|
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.runCommandSpawn = exports.runCommandExecWithCallback = exports.runCommandExec = exports.startInteractiveShell = exports.setMostRecentCommand = exports.mostRecentCommandTime = exports.mostRecentCommand = void 0;
|
|
4
4
|
const _ = require("lodash");
|
|
5
5
|
const moment = require("moment");
|
|
6
|
-
const { exec, spawn } = require(
|
|
6
|
+
const { exec, spawn } = require("node:child_process");
|
|
7
7
|
exports.mostRecentCommand = null;
|
|
8
8
|
exports.mostRecentCommandTime = null;
|
|
9
9
|
const setMostRecentCommand = (cmd) => {
|
|
@@ -14,10 +14,10 @@ exports.setMostRecentCommand = setMostRecentCommand;
|
|
|
14
14
|
const startInteractiveShell = (runCmd, shellName) => {
|
|
15
15
|
const shell = spawn(`${runCmd}`, [], {
|
|
16
16
|
env: Object.assign(Object.assign({}, process.env), { SCRIPT_PATH: __dirname }),
|
|
17
|
-
stdio:
|
|
17
|
+
stdio: "inherit",
|
|
18
18
|
shell: true,
|
|
19
19
|
});
|
|
20
|
-
shell.on(
|
|
20
|
+
shell.on("close", (code) => {
|
|
21
21
|
if (shellName) {
|
|
22
22
|
if (code === 0) {
|
|
23
23
|
console.log(`The previously launched ${shellName} has successfully terminated.`);
|
|
@@ -30,10 +30,10 @@ const startInteractiveShell = (runCmd, shellName) => {
|
|
|
30
30
|
console.log(`❗ Error: shell terminated with code ${code}.`);
|
|
31
31
|
}
|
|
32
32
|
});
|
|
33
|
-
process.on(
|
|
33
|
+
process.on("SIGINT", () => {
|
|
34
34
|
// intercepting SIGINT
|
|
35
35
|
});
|
|
36
|
-
process.on(
|
|
36
|
+
process.on("SIGTSTP", () => {
|
|
37
37
|
// intercepting SIGTSTP
|
|
38
38
|
});
|
|
39
39
|
};
|
|
@@ -42,7 +42,7 @@ const runCommandExec = (runCmd, successMessage, errorMessage, envVars) => {
|
|
|
42
42
|
const envVarsToUse = envVars || {};
|
|
43
43
|
exec(`${runCmd}`, {
|
|
44
44
|
env: Object.assign(Object.assign(Object.assign({}, process.env), { SCRIPT_PATH: __dirname }), envVarsToUse),
|
|
45
|
-
},
|
|
45
|
+
}, (error, stdOut, stdErr) => {
|
|
46
46
|
if (error) {
|
|
47
47
|
console.log(`\n❗ Error: ${_.upperFirst(errorMessage)}`);
|
|
48
48
|
}
|
|
@@ -59,9 +59,9 @@ const runCommandExec = (runCmd, successMessage, errorMessage, envVars) => {
|
|
|
59
59
|
};
|
|
60
60
|
exports.runCommandExec = runCommandExec;
|
|
61
61
|
const runCommandExecWithCallback = (cmd, callback) => {
|
|
62
|
-
return new Promise(resolve => {
|
|
63
|
-
exec(cmd,
|
|
64
|
-
callback
|
|
62
|
+
return new Promise((resolve) => {
|
|
63
|
+
exec(cmd, (error, stdOut, stdErr) => {
|
|
64
|
+
callback === null || callback === void 0 ? void 0 : callback(error, stdOut, stdErr);
|
|
65
65
|
resolve(stdOut);
|
|
66
66
|
});
|
|
67
67
|
});
|
|
@@ -71,10 +71,10 @@ const runCommandSpawn = (runCmd, successMessage, errorMessage, envVars) => {
|
|
|
71
71
|
const envVarsToUse = envVars || {};
|
|
72
72
|
const shell = spawn(`${runCmd}`, [], {
|
|
73
73
|
env: Object.assign(Object.assign(Object.assign({}, process.env), { SCRIPT_PATH: __dirname }), envVarsToUse),
|
|
74
|
-
stdio:
|
|
74
|
+
stdio: "inherit",
|
|
75
75
|
shell: true,
|
|
76
76
|
});
|
|
77
|
-
shell.on(
|
|
77
|
+
shell.on("close", (code) => {
|
|
78
78
|
if (code === 0) {
|
|
79
79
|
console.log(`🎉 Success! ${_.upperFirst(successMessage)}`);
|
|
80
80
|
}
|
package/lib/lib/config.js
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.isProduction = exports.writeConfigData = exports.getOrCreateConfigData = exports.customHttpHeaderKey = exports.defaultAllowSelfSignedCerts = exports.allowSelfSignedCertsKey = exports.defaultUrl = exports.urlKey = void 0;
|
|
4
|
-
const fs = require("fs");
|
|
5
|
-
const path = require("path");
|
|
6
|
-
exports.urlKey =
|
|
7
|
-
exports.defaultUrl =
|
|
8
|
-
exports.allowSelfSignedCertsKey =
|
|
4
|
+
const fs = require("node:fs");
|
|
5
|
+
const path = require("node:path");
|
|
6
|
+
exports.urlKey = "url";
|
|
7
|
+
exports.defaultUrl = "https://app.opal.dev";
|
|
8
|
+
exports.allowSelfSignedCertsKey = "allowSelfSignedCerts";
|
|
9
9
|
exports.defaultAllowSelfSignedCerts = false;
|
|
10
|
-
exports.customHttpHeaderKey =
|
|
10
|
+
exports.customHttpHeaderKey = "customHttpHeader";
|
|
11
11
|
const getOrCreateConfigData = (configDir) => {
|
|
12
12
|
if (!fs.existsSync(configDir)) {
|
|
13
13
|
fs.mkdirSync(configDir, { recursive: true });
|
|
14
14
|
}
|
|
15
|
-
const configFilePath = path.join(configDir,
|
|
15
|
+
const configFilePath = path.join(configDir, "config.json");
|
|
16
16
|
if (!fs.existsSync(configFilePath)) {
|
|
17
17
|
fs.writeFileSync(configFilePath, JSON.stringify({
|
|
18
18
|
[exports.urlKey]: exports.defaultUrl,
|
|
@@ -22,10 +22,10 @@ const getOrCreateConfigData = (configDir) => {
|
|
|
22
22
|
let configData = {};
|
|
23
23
|
try {
|
|
24
24
|
const configDataRaw = fs.readFileSync(configFilePath);
|
|
25
|
-
configData = JSON.parse(configDataRaw.toString());
|
|
25
|
+
configData = JSON.parse(configDataRaw === null || configDataRaw === void 0 ? void 0 : configDataRaw.toString());
|
|
26
26
|
}
|
|
27
27
|
catch (error) {
|
|
28
|
-
if (error.code !==
|
|
28
|
+
if (error.code !== "ENOENT") {
|
|
29
29
|
throw error;
|
|
30
30
|
}
|
|
31
31
|
}
|
|
@@ -37,7 +37,7 @@ const writeConfigData = (configDir, newConfigData) => {
|
|
|
37
37
|
for (const [key, value] of Object.entries(newConfigData)) {
|
|
38
38
|
existingData[key] = value;
|
|
39
39
|
}
|
|
40
|
-
const configFilePath = path.join(configDir,
|
|
40
|
+
const configFilePath = path.join(configDir, "config.json");
|
|
41
41
|
fs.writeFileSync(configFilePath, JSON.stringify(existingData), {
|
|
42
42
|
mode: 0o0600,
|
|
43
43
|
});
|
|
@@ -46,9 +46,9 @@ exports.writeConfigData = writeConfigData;
|
|
|
46
46
|
const isProduction = (configDir) => {
|
|
47
47
|
const configData = (0, exports.getOrCreateConfigData)(configDir);
|
|
48
48
|
// Custom URLs are considered production since it includes on-prem
|
|
49
|
-
return configData[exports.urlKey] !==
|
|
50
|
-
configData[exports.urlKey] !==
|
|
51
|
-
configData[exports.urlKey] !==
|
|
52
|
-
!configData[exports.urlKey].match(/https?:\/\/localhost/);
|
|
49
|
+
return (configData[exports.urlKey] !== "https://dev.opal.dev" &&
|
|
50
|
+
configData[exports.urlKey] !== "https://demo.opal.dev" &&
|
|
51
|
+
configData[exports.urlKey] !== "https://staging.opal.dev" &&
|
|
52
|
+
!configData[exports.urlKey].match(/https?:\/\/localhost/));
|
|
53
53
|
};
|
|
54
54
|
exports.isProduction = isProduction;
|
|
@@ -10,17 +10,17 @@ var SecretType;
|
|
|
10
10
|
SecretType["ApiToken"] = "API_TOKEN";
|
|
11
11
|
})(SecretType || (exports.SecretType = SecretType = {}));
|
|
12
12
|
const setOpalCredentials = async (command, email, organizationID, clientIDCandidate, secret, secretType) => {
|
|
13
|
-
|
|
13
|
+
const givenEmail = email || "email-unset";
|
|
14
14
|
const configData = (0, config_1.getOrCreateConfigData)(command.config.configDir);
|
|
15
15
|
configData.creds = {
|
|
16
16
|
clientIDCandidate,
|
|
17
17
|
email,
|
|
18
18
|
organizationID,
|
|
19
|
-
secretType
|
|
19
|
+
secretType,
|
|
20
20
|
};
|
|
21
21
|
(0, config_1.writeConfigData)(command.config.configDir, configData);
|
|
22
22
|
if (process.platform === "darwin") {
|
|
23
|
-
await (0, keychain_1.setSecretInKeychain)(
|
|
23
|
+
await (0, keychain_1.setSecretInKeychain)(givenEmail, secret);
|
|
24
24
|
}
|
|
25
25
|
else {
|
|
26
26
|
await (0, localEncryption_1.setSecretInConfig)(command, configData, secret);
|
|
@@ -29,13 +29,13 @@ const setOpalCredentials = async (command, email, organizationID, clientIDCandid
|
|
|
29
29
|
exports.setOpalCredentials = setOpalCredentials;
|
|
30
30
|
const getOpalCredentials = async (command, includeAuthSecret = true) => {
|
|
31
31
|
var _a, _b;
|
|
32
|
-
|
|
32
|
+
const creds = (_b = (_a = (0, config_1.getOrCreateConfigData)(command.config.configDir)) === null || _a === void 0 ? void 0 : _a.creds) !== null && _b !== void 0 ? _b : {};
|
|
33
33
|
if (!includeAuthSecret) {
|
|
34
34
|
return creds;
|
|
35
35
|
}
|
|
36
36
|
let secret = null;
|
|
37
37
|
if (process.platform === "darwin") {
|
|
38
|
-
secret = await (0, keychain_1.getSecretFromKeychain)((creds === null || creds === void 0 ? void 0 : creds.email) ||
|
|
38
|
+
secret = await (0, keychain_1.getSecretFromKeychain)((creds === null || creds === void 0 ? void 0 : creds.email) || "email-unset");
|
|
39
39
|
}
|
|
40
40
|
else {
|
|
41
41
|
secret = await (0, localEncryption_1.getSecretFromConfig)(creds);
|
|
@@ -54,7 +54,7 @@ exports.getOpalCredentials = getOpalCredentials;
|
|
|
54
54
|
const removeOpalCredentials = async (command) => {
|
|
55
55
|
var _a;
|
|
56
56
|
const configData = (0, config_1.getOrCreateConfigData)(command.config.configDir);
|
|
57
|
-
const email = ((_a = configData === null || configData === void 0 ? void 0 : configData.creds) === null || _a === void 0 ? void 0 : _a.email) ||
|
|
57
|
+
const email = ((_a = configData === null || configData === void 0 ? void 0 : configData.creds) === null || _a === void 0 ? void 0 : _a.email) || "email-unset";
|
|
58
58
|
// On linux, the access token is stored encrypted in configData.creds, so this effectively removes it
|
|
59
59
|
configData.creds = {};
|
|
60
60
|
(0, config_1.writeConfigData)(command.config.configDir, configData);
|
|
@@ -2,11 +2,11 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.deleteSecretFromKeychain = exports.getSecretFromKeychain = exports.setSecretInKeychain = void 0;
|
|
4
4
|
const keychain = require("keychain");
|
|
5
|
-
const OPAL_KEYCHAIN_SERVICE =
|
|
5
|
+
const OPAL_KEYCHAIN_SERVICE = "opal-cli";
|
|
6
6
|
// On OSX, we can easily work with the system Keychain to store the access token.
|
|
7
7
|
const setSecretInKeychain = async (email, secret) => {
|
|
8
8
|
return new Promise((resolve, reject) => {
|
|
9
|
-
keychain.setPassword({ account: email, service: OPAL_KEYCHAIN_SERVICE, password: secret },
|
|
9
|
+
keychain.setPassword({ account: email, service: OPAL_KEYCHAIN_SERVICE, password: secret }, (err) => {
|
|
10
10
|
if (err) {
|
|
11
11
|
reject(err);
|
|
12
12
|
}
|
|
@@ -19,8 +19,8 @@ const setSecretInKeychain = async (email, secret) => {
|
|
|
19
19
|
exports.setSecretInKeychain = setSecretInKeychain;
|
|
20
20
|
const getSecretFromKeychain = async (email) => {
|
|
21
21
|
return new Promise((resolve, reject) => {
|
|
22
|
-
keychain.getPassword({ account: email, service: OPAL_KEYCHAIN_SERVICE },
|
|
23
|
-
if (err && (err === null || err === void 0 ? void 0 : err.type) !==
|
|
22
|
+
keychain.getPassword({ account: email, service: OPAL_KEYCHAIN_SERVICE }, (err, password) => {
|
|
23
|
+
if (err && (err === null || err === void 0 ? void 0 : err.type) !== "PasswordNotFoundError") {
|
|
24
24
|
reject(err);
|
|
25
25
|
}
|
|
26
26
|
else {
|
|
@@ -32,7 +32,7 @@ const getSecretFromKeychain = async (email) => {
|
|
|
32
32
|
exports.getSecretFromKeychain = getSecretFromKeychain;
|
|
33
33
|
const deleteSecretFromKeychain = async (email) => {
|
|
34
34
|
return new Promise((resolve) => {
|
|
35
|
-
keychain.deletePassword({ service: OPAL_KEYCHAIN_SERVICE, account: email },
|
|
35
|
+
keychain.deletePassword({ service: OPAL_KEYCHAIN_SERVICE, account: email }, () => {
|
|
36
36
|
// we might get errors here if the password doesn't exist, which we want to swallow
|
|
37
37
|
resolve();
|
|
38
38
|
});
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { Command } from
|
|
1
|
+
import type { Command } from "@oclif/core";
|
|
2
2
|
export declare const setSecretInConfig: (command: Command, configData: Record<string, any>, secret: string) => Promise<void>;
|
|
3
|
-
export declare const getSecretFromConfig: (credsConfig: Record<string, any>) => Promise<string
|
|
3
|
+
export declare const getSecretFromConfig: (credsConfig: Record<string, any>) => Promise<string>;
|