@p0security/cli 0.8.1 → 0.8.3

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.
Files changed (48) hide show
  1. package/dist/commands/__tests__/grant.test.d.ts +1 -0
  2. package/dist/commands/__tests__/grant.test.js +55 -0
  3. package/dist/commands/grant.d.ts +4 -0
  4. package/dist/commands/grant.js +17 -0
  5. package/dist/commands/index.js +2 -0
  6. package/dist/commands/request.d.ts +0 -8
  7. package/dist/commands/request.js +3 -102
  8. package/dist/commands/scp.d.ts +1 -1
  9. package/dist/commands/scp.js +5 -4
  10. package/dist/commands/shared/index.d.ts +4 -0
  11. package/dist/commands/shared/index.js +67 -0
  12. package/dist/commands/shared/request.d.ts +14 -0
  13. package/dist/commands/shared/request.js +115 -0
  14. package/dist/commands/{shared.d.ts → shared/ssh.d.ts} +12 -22
  15. package/dist/commands/{shared.js → shared/ssh.js} +21 -75
  16. package/dist/commands/ssh.d.ts +1 -1
  17. package/dist/commands/ssh.js +3 -3
  18. package/dist/common/retry.d.ts +9 -0
  19. package/dist/common/retry.js +50 -0
  20. package/dist/drivers/auth.d.ts +1 -1
  21. package/dist/drivers/auth.js +7 -3
  22. package/dist/plugins/aws/config.d.ts +1 -1
  23. package/dist/plugins/aws/idc/index.d.ts +16 -0
  24. package/dist/plugins/aws/idc/index.js +150 -0
  25. package/dist/plugins/aws/ssh.d.ts +3 -3
  26. package/dist/plugins/aws/ssh.js +75 -11
  27. package/dist/plugins/aws/types.d.ts +29 -5
  28. package/dist/plugins/google/ssh.d.ts +5 -13
  29. package/dist/plugins/google/ssh.js +71 -10
  30. package/dist/plugins/google/types.d.ts +11 -3
  31. package/dist/plugins/login.d.ts +3 -0
  32. package/dist/plugins/login.js +10 -0
  33. package/dist/plugins/oidc/login.d.ts +33 -2
  34. package/dist/plugins/oidc/login.js +100 -60
  35. package/dist/plugins/okta/aws.d.ts +1 -1
  36. package/dist/plugins/okta/aws.js +2 -2
  37. package/dist/plugins/okta/login.js +11 -1
  38. package/dist/plugins/ping/login.d.ts +2 -1
  39. package/dist/plugins/ping/login.js +11 -1
  40. package/dist/plugins/ssh/index.d.ts +3 -2
  41. package/dist/plugins/ssh/index.js +65 -84
  42. package/dist/types/aws/oidc.d.ts +36 -0
  43. package/dist/types/aws/oidc.js +12 -0
  44. package/dist/types/oidc.d.ts +21 -0
  45. package/dist/types/request.d.ts +2 -7
  46. package/dist/types/ssh.d.ts +47 -0
  47. package/dist/types/ssh.js +5 -0
  48. package/package.json +4 -3
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,55 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ var __importDefault = (this && this.__importDefault) || function (mod) {
12
+ return (mod && mod.__esModule) ? mod : { "default": mod };
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ /** Copyright © 2024-present P0 Security
16
+
17
+ This file is part of @p0security/cli
18
+
19
+ @p0security/cli is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 3 of the License.
20
+
21
+ @p0security/cli is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
22
+
23
+ You should have received a copy of the GNU General Public License along with @p0security/cli. If not, see <https://www.gnu.org/licenses/>.
24
+ **/
25
+ const api_1 = require("../../drivers/api");
26
+ const stdio_1 = require("../../drivers/stdio");
27
+ const grant_1 = require("../grant");
28
+ const yargs_1 = __importDefault(require("yargs"));
29
+ jest.mock("../../drivers/api");
30
+ jest.mock("../../drivers/auth");
31
+ jest.mock("../../drivers/stdio");
32
+ const mockFetchCommand = api_1.fetchCommand;
33
+ const mockPrint1 = stdio_1.print1;
34
+ const mockPrint2 = stdio_1.print2;
35
+ describe("grant", () => {
36
+ beforeEach(() => jest.clearAllMocks());
37
+ describe("when valid grant command", () => {
38
+ const command = "grant gcloud role viewer --to someone@test.com --principal-type user";
39
+ function mockFetch() {
40
+ mockFetchCommand.mockResolvedValue({
41
+ ok: true,
42
+ message: "a message",
43
+ id: "abcefg",
44
+ isPreexisting: false,
45
+ isPersistent: false,
46
+ });
47
+ }
48
+ it(`should print request response`, () => __awaiter(void 0, void 0, void 0, function* () {
49
+ mockFetch();
50
+ yield (0, grant_1.grantCommand)((0, yargs_1.default)()).parse(command);
51
+ expect(mockPrint2.mock.calls).toMatchSnapshot();
52
+ expect(mockPrint1).not.toHaveBeenCalled();
53
+ }));
54
+ });
55
+ });
@@ -0,0 +1,4 @@
1
+ import yargs from "yargs";
2
+ export declare const grantCommand: (yargs: yargs.Argv<{}>) => yargs.Argv<{
3
+ arguments: string[];
4
+ }>;
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.grantCommand = void 0;
4
+ /** Copyright © 2024-present P0 Security
5
+
6
+ This file is part of @p0security/cli
7
+
8
+ @p0security/cli is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 3 of the License.
9
+
10
+ @p0security/cli is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
11
+
12
+ You should have received a copy of the GNU General Public License along with @p0security/cli. If not, see <https://www.gnu.org/licenses/>.
13
+ **/
14
+ const firestore_1 = require("../drivers/firestore");
15
+ const request_1 = require("./shared/request");
16
+ const grantCommand = (yargs) => yargs.command("grant [arguments..]", "Grant access to another identity", request_1.requestArgs, (0, firestore_1.guard)((0, request_1.request)("grant")));
17
+ exports.grantCommand = grantCommand;
@@ -18,6 +18,7 @@ const stdio_1 = require("../drivers/stdio");
18
18
  const version_1 = require("../middlewares/version");
19
19
  const allow_1 = require("./allow");
20
20
  const aws_1 = require("./aws");
21
+ const grant_1 = require("./grant");
21
22
  const login_1 = require("./login");
22
23
  const ls_1 = require("./ls");
23
24
  const request_1 = require("./request");
@@ -28,6 +29,7 @@ const yargs_1 = __importDefault(require("yargs"));
28
29
  const helpers_1 = require("yargs/helpers");
29
30
  const commands = [
30
31
  aws_1.awsCommand,
32
+ grant_1.grantCommand,
31
33
  login_1.loginCommand,
32
34
  ls_1.lsCommand,
33
35
  request_1.requestCommand,
@@ -1,12 +1,4 @@
1
- import { Authn } from "../types/identity";
2
- import { RequestResponse } from "../types/request";
3
1
  import yargs from "yargs";
4
2
  export declare const requestCommand: (yargs: yargs.Argv<{}>) => yargs.Argv<{
5
3
  arguments: string[];
6
4
  }>;
7
- export declare const request: <T>(args: yargs.ArgumentsCamelCase<{
8
- arguments: string[];
9
- wait?: boolean;
10
- }>, authn?: Authn, options?: {
11
- message?: "all" | "approval-required" | "none";
12
- }) => Promise<RequestResponse<T> | undefined>;
@@ -1,15 +1,6 @@
1
1
  "use strict";
2
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
- return new (P || (P = Promise))(function (resolve, reject) {
5
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
- step((generator = generator.apply(thisArg, _arguments || [])).next());
9
- });
10
- };
11
2
  Object.defineProperty(exports, "__esModule", { value: true });
12
- exports.request = exports.requestCommand = void 0;
3
+ exports.requestCommand = void 0;
13
4
  /** Copyright © 2024-present P0 Security
14
5
 
15
6
  This file is part of @p0security/cli
@@ -20,97 +11,7 @@ This file is part of @p0security/cli
20
11
 
21
12
  You should have received a copy of the GNU General Public License along with @p0security/cli. If not, see <https://www.gnu.org/licenses/>.
22
13
  **/
23
- const api_1 = require("../drivers/api");
24
- const auth_1 = require("../drivers/auth");
25
14
  const firestore_1 = require("../drivers/firestore");
26
- const stdio_1 = require("../drivers/stdio");
27
- const firestore_2 = require("firebase/firestore");
28
- const typescript_1 = require("typescript");
29
- const WAIT_TIMEOUT = 300e3;
30
- const APPROVED = { message: "Your request was approved", code: 0 };
31
- const DENIED = { message: "Your request was denied", code: 2 };
32
- const ERRORED = { message: "Your request encountered an error", code: 1 };
33
- const COMPLETED_REQUEST_STATUSES = {
34
- APPROVED,
35
- APPROVED_NOTIFIED: APPROVED,
36
- DONE: APPROVED,
37
- DONE_NOTIFIED: APPROVED,
38
- DENIED,
39
- ERRORED,
40
- };
41
- const isCompletedStatus = (status) => status in COMPLETED_REQUEST_STATUSES;
42
- const requestArgs = (yargs) => yargs
43
- .parserConfiguration({ "unknown-options-as-args": true })
44
- .help(false) // Turn off help in order to forward the --help command to the backend so P0 can provide the available requestable resources
45
- .option("wait", {
46
- alias: "w",
47
- boolean: true,
48
- default: false,
49
- describe: "Block until the command is completed",
50
- })
51
- .option("arguments", {
52
- array: true,
53
- string: true,
54
- default: [],
55
- });
56
- const requestCommand = (yargs) => yargs.command("request [arguments..]", "Manually request permissions on a resource", requestArgs, (0, firestore_1.guard)(exports.request));
15
+ const request_1 = require("./shared/request");
16
+ const requestCommand = (yargs) => yargs.command("request [arguments..]", "Manually request permissions on a resource", request_1.requestArgs, (0, firestore_1.guard)((0, request_1.request)("request")));
57
17
  exports.requestCommand = requestCommand;
58
- const waitForRequest = (tenantId, requestId, logMessage) => __awaiter(void 0, void 0, void 0, function* () {
59
- return yield new Promise((resolve) => {
60
- if (logMessage)
61
- (0, stdio_1.print2)("Will wait up to 5 minutes for this request to complete...");
62
- let cancel = undefined;
63
- const unsubscribe = (0, firestore_2.onSnapshot)((0, firestore_1.doc)(`o/${tenantId}/permission-requests/${requestId}`), (snap) => {
64
- const data = snap.data();
65
- if (!data)
66
- return;
67
- const { status } = data;
68
- if (isCompletedStatus(status)) {
69
- if (cancel)
70
- clearTimeout(cancel);
71
- unsubscribe === null || unsubscribe === void 0 ? void 0 : unsubscribe();
72
- const { message, code } = COMPLETED_REQUEST_STATUSES[status];
73
- if (code !== 0 || logMessage)
74
- (0, stdio_1.print2)(message);
75
- resolve(code);
76
- }
77
- });
78
- cancel = setTimeout(() => {
79
- unsubscribe === null || unsubscribe === void 0 ? void 0 : unsubscribe();
80
- (0, stdio_1.print2)("Your request did not complete within 5 minutes.");
81
- resolve(4);
82
- }, WAIT_TIMEOUT);
83
- });
84
- });
85
- const request = (args, authn, options) => __awaiter(void 0, void 0, void 0, function* () {
86
- const resolvedAuthn = authn !== null && authn !== void 0 ? authn : (yield (0, auth_1.authenticate)());
87
- const { userCredential } = resolvedAuthn;
88
- const data = yield (0, api_1.fetchCommand)(resolvedAuthn, args, [
89
- "request",
90
- ...args.arguments,
91
- ]);
92
- if (data && "ok" in data && "message" in data && data.ok) {
93
- const logMessage = !(options === null || options === void 0 ? void 0 : options.message) ||
94
- (options === null || options === void 0 ? void 0 : options.message) === "all" ||
95
- ((options === null || options === void 0 ? void 0 : options.message) === "approval-required" &&
96
- !data.isPreexisting &&
97
- !data.isPersistent);
98
- if (logMessage)
99
- (0, stdio_1.print2)(data.message);
100
- const { id } = data;
101
- if (args.wait && id && userCredential.user.tenantId) {
102
- const code = yield waitForRequest(userCredential.user.tenantId, id, logMessage);
103
- if (code) {
104
- typescript_1.sys.exit(code);
105
- return undefined;
106
- }
107
- return data;
108
- }
109
- else
110
- return undefined;
111
- }
112
- else {
113
- throw data;
114
- }
115
- });
116
- exports.request = request;
@@ -1,3 +1,3 @@
1
- import { ScpCommandArgs } from "./shared";
1
+ import { ScpCommandArgs } from "./shared/ssh";
2
2
  import yargs from "yargs";
3
3
  export declare const scpCommand: (yargs: yargs.Argv<{}>) => yargs.Argv<ScpCommandArgs>;
@@ -23,7 +23,8 @@ You should have received a copy of the GNU General Public License along with @p0
23
23
  const auth_1 = require("../drivers/auth");
24
24
  const firestore_1 = require("../drivers/firestore");
25
25
  const ssh_1 = require("../plugins/ssh");
26
- const shared_1 = require("./shared");
26
+ const ssh_2 = require("../types/ssh");
27
+ const ssh_3 = require("./shared/ssh");
27
28
  const scpCommand = (yargs) => yargs.command("scp <source> <destination>",
28
29
  // TODO (ENG-1930): support scp across multiple remote hosts.
29
30
  "SCP copies files between a local and remote host.", (yargs) => yargs
@@ -53,7 +54,7 @@ const scpCommand = (yargs) => yargs.command("scp <source> <destination>",
53
54
  .option("provider", {
54
55
  type: "string",
55
56
  describe: "The cloud provider where the instance is hosted",
56
- choices: shared_1.SUPPORTED_PROVIDERS,
57
+ choices: ssh_2.SupportedSshProviders,
57
58
  })
58
59
  .option("sudo", {
59
60
  type: "boolean",
@@ -74,12 +75,12 @@ const scpAction = (args) => __awaiter(void 0, void 0, void 0, function* () {
74
75
  if (!host) {
75
76
  throw "Could not determine host identifier from source or destination";
76
77
  }
77
- const result = yield (0, shared_1.provisionRequest)(authn, args, host);
78
+ const result = yield (0, ssh_3.provisionRequest)(authn, args, host);
78
79
  if (!result) {
79
80
  throw "Server did not return a request id. Please contact support@p0.dev for assistance.";
80
81
  }
81
82
  const { request, privateKey } = result;
82
- const data = (0, shared_1.requestToSsh)(request);
83
+ const data = (0, ssh_3.requestToSsh)(request);
83
84
  // replace the host with the linuxUserName@instanceId
84
85
  const { source, destination } = replaceHostWithInstance(data, args);
85
86
  yield (0, ssh_1.sshOrScp)(authn, data, Object.assign(Object.assign({}, args), { source,
@@ -0,0 +1,4 @@
1
+ import { Authn } from "../../types/identity";
2
+ import { Request } from "../../types/request";
3
+ /** Waits until P0 grants access for a request */
4
+ export declare const waitForProvisioning: <P extends import("../../types/ssh").PluginSshRequest>(authn: Authn, requestId: string) => Promise<Request<P>>;
@@ -0,0 +1,67 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.waitForProvisioning = void 0;
13
+ /** Copyright © 2024-present P0 Security
14
+
15
+ This file is part of @p0security/cli
16
+
17
+ @p0security/cli is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 3 of the License.
18
+
19
+ @p0security/cli is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
20
+
21
+ You should have received a copy of the GNU General Public License along with @p0security/cli. If not, see <https://www.gnu.org/licenses/>.
22
+ **/
23
+ const firestore_1 = require("../../drivers/firestore");
24
+ const request_1 = require("../../types/request");
25
+ const firestore_2 = require("firebase/firestore");
26
+ /** Maximum amount of time to wait after access is approved to wait for access
27
+ * to be configured
28
+ */
29
+ const GRANT_TIMEOUT_MILLIS = 60e3;
30
+ /** Waits until P0 grants access for a request */
31
+ const waitForProvisioning = (authn, requestId) => __awaiter(void 0, void 0, void 0, function* () {
32
+ let cancel = undefined;
33
+ const result = yield new Promise((resolve, reject) => {
34
+ let isResolved = false;
35
+ const unsubscribe = (0, firestore_2.onSnapshot)((0, firestore_1.doc)(`o/${authn.identity.org.tenantId}/permission-requests/${requestId}`), (snap) => {
36
+ const data = snap.data();
37
+ if (!data)
38
+ return;
39
+ if (request_1.DONE_STATUSES.includes(data.status)) {
40
+ resolve(data);
41
+ }
42
+ else if (request_1.DENIED_STATUSES.includes(data.status)) {
43
+ reject("Your access request was denied");
44
+ }
45
+ else if (request_1.ERROR_STATUSES.includes(data.status)) {
46
+ reject("Your access request encountered an error (see Slack for details)");
47
+ }
48
+ else {
49
+ return;
50
+ }
51
+ isResolved = true;
52
+ unsubscribe();
53
+ });
54
+ // Skip timeout in test; it holds a ref longer than the test lasts
55
+ if (process.env.NODE_ENV === "test")
56
+ return;
57
+ cancel = setTimeout(() => {
58
+ if (!isResolved) {
59
+ unsubscribe();
60
+ reject("Timeout awaiting SSH access grant");
61
+ }
62
+ }, GRANT_TIMEOUT_MILLIS);
63
+ });
64
+ clearTimeout(cancel);
65
+ return result;
66
+ });
67
+ exports.waitForProvisioning = waitForProvisioning;
@@ -0,0 +1,14 @@
1
+ import { Authn } from "../../types/identity";
2
+ import { RequestResponse } from "../../types/request";
3
+ import yargs from "yargs";
4
+ export declare const requestArgs: <T>(yargs: yargs.Argv<T>) => yargs.Argv<T & {
5
+ wait: boolean;
6
+ } & {
7
+ arguments: string[];
8
+ }>;
9
+ export declare const request: (command: "grant" | "request") => <T>(args: yargs.ArgumentsCamelCase<{
10
+ arguments: string[];
11
+ wait?: boolean;
12
+ }>, authn?: Authn, options?: {
13
+ message?: "all" | "approval-required" | "none";
14
+ }) => Promise<RequestResponse<T> | undefined>;
@@ -0,0 +1,115 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.request = exports.requestArgs = void 0;
13
+ /** Copyright © 2024-present P0 Security
14
+
15
+ This file is part of @p0security/cli
16
+
17
+ @p0security/cli is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 3 of the License.
18
+
19
+ @p0security/cli is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
20
+
21
+ You should have received a copy of the GNU General Public License along with @p0security/cli. If not, see <https://www.gnu.org/licenses/>.
22
+ **/
23
+ const api_1 = require("../../drivers/api");
24
+ const auth_1 = require("../../drivers/auth");
25
+ const firestore_1 = require("../../drivers/firestore");
26
+ const stdio_1 = require("../../drivers/stdio");
27
+ const firestore_2 = require("firebase/firestore");
28
+ const typescript_1 = require("typescript");
29
+ const WAIT_TIMEOUT = 300e3;
30
+ const APPROVED = { message: "Your request was approved", code: 0 };
31
+ const DENIED = { message: "Your request was denied", code: 2 };
32
+ const ERRORED = { message: "Your request encountered an error", code: 1 };
33
+ const COMPLETED_REQUEST_STATUSES = {
34
+ APPROVED,
35
+ APPROVED_NOTIFIED: APPROVED,
36
+ DONE: APPROVED,
37
+ DONE_NOTIFIED: APPROVED,
38
+ DENIED,
39
+ ERRORED,
40
+ };
41
+ const isCompletedStatus = (status) => status in COMPLETED_REQUEST_STATUSES;
42
+ const requestArgs = (yargs) => yargs
43
+ .parserConfiguration({ "unknown-options-as-args": true })
44
+ .help(false) // Turn off help in order to forward the --help command to the backend so P0 can provide the available requestable resources
45
+ .option("wait", {
46
+ alias: "w",
47
+ boolean: true,
48
+ default: false,
49
+ describe: "Block until the command is completed",
50
+ })
51
+ .option("arguments", {
52
+ array: true,
53
+ string: true,
54
+ default: [],
55
+ });
56
+ exports.requestArgs = requestArgs;
57
+ const waitForRequest = (tenantId, requestId, logMessage) => __awaiter(void 0, void 0, void 0, function* () {
58
+ return yield new Promise((resolve) => {
59
+ if (logMessage)
60
+ (0, stdio_1.print2)("Will wait up to 5 minutes for this request to complete...");
61
+ let cancel = undefined;
62
+ const unsubscribe = (0, firestore_2.onSnapshot)((0, firestore_1.doc)(`o/${tenantId}/permission-requests/${requestId}`), (snap) => {
63
+ const data = snap.data();
64
+ if (!data)
65
+ return;
66
+ const { status } = data;
67
+ if (isCompletedStatus(status)) {
68
+ if (cancel)
69
+ clearTimeout(cancel);
70
+ unsubscribe === null || unsubscribe === void 0 ? void 0 : unsubscribe();
71
+ const { message, code } = COMPLETED_REQUEST_STATUSES[status];
72
+ if (code !== 0 || logMessage)
73
+ (0, stdio_1.print2)(message);
74
+ resolve(code);
75
+ }
76
+ });
77
+ cancel = setTimeout(() => {
78
+ unsubscribe === null || unsubscribe === void 0 ? void 0 : unsubscribe();
79
+ (0, stdio_1.print2)("Your request did not complete within 5 minutes.");
80
+ resolve(4);
81
+ }, WAIT_TIMEOUT);
82
+ });
83
+ });
84
+ const request = (command) => (args, authn, options) => __awaiter(void 0, void 0, void 0, function* () {
85
+ const resolvedAuthn = authn !== null && authn !== void 0 ? authn : (yield (0, auth_1.authenticate)());
86
+ const { userCredential } = resolvedAuthn;
87
+ const data = yield (0, api_1.fetchCommand)(resolvedAuthn, args, [
88
+ command,
89
+ ...args.arguments,
90
+ ]);
91
+ if (data && "ok" in data && "message" in data && data.ok) {
92
+ const logMessage = !(options === null || options === void 0 ? void 0 : options.message) ||
93
+ (options === null || options === void 0 ? void 0 : options.message) === "all" ||
94
+ ((options === null || options === void 0 ? void 0 : options.message) === "approval-required" &&
95
+ !data.isPreexisting &&
96
+ !data.isPersistent);
97
+ if (logMessage)
98
+ (0, stdio_1.print2)(data.message);
99
+ const { id } = data;
100
+ if (args.wait && id && userCredential.user.tenantId) {
101
+ const code = yield waitForRequest(userCredential.user.tenantId, id, logMessage);
102
+ if (code) {
103
+ typescript_1.sys.exit(code);
104
+ return undefined;
105
+ }
106
+ return data;
107
+ }
108
+ else
109
+ return undefined;
110
+ }
111
+ else {
112
+ throw data;
113
+ }
114
+ });
115
+ exports.request = request;
@@ -1,28 +1,12 @@
1
- import { Authn } from "../types/identity";
2
- import { CliRequest, Request } from "../types/request";
1
+ import { Authn } from "../../types/identity";
2
+ import { Request } from "../../types/request";
3
+ import { CliSshRequest, SshProvider, SshRequest, SupportedSshProvider } from "../../types/ssh";
3
4
  import yargs from "yargs";
4
- export declare const SUPPORTED_PROVIDERS: string[];
5
- export declare type SshRequest = AwsSshRequest | GcpSshRequest;
6
- export declare type AwsSshRequest = {
7
- linuxUserName: string;
8
- role: string;
9
- accountId: string;
10
- region: string;
11
- id: string;
12
- type: "aws";
13
- };
14
- export declare type GcpSshRequest = {
15
- linuxUserName: string;
16
- projectId: string;
17
- zone: string;
18
- id: string;
19
- type: "gcloud";
20
- };
21
5
  export declare type BaseSshCommandArgs = {
22
6
  sudo?: boolean;
23
7
  reason?: string;
24
8
  account?: string;
25
- provider?: "aws" | "gcloud";
9
+ provider?: SupportedSshProvider;
26
10
  debug?: boolean;
27
11
  };
28
12
  export declare type ScpCommandArgs = BaseSshCommandArgs & {
@@ -39,9 +23,15 @@ export declare type SshCommandArgs = BaseSshCommandArgs & {
39
23
  arguments: string[];
40
24
  command?: string;
41
25
  };
26
+ export declare type CommandArgs = ScpCommandArgs | SshCommandArgs;
27
+ export declare const SSH_PROVIDERS: Record<SupportedSshProvider, SshProvider<any, any, any, any>>;
28
+ export declare const isSudoCommand: (args: {
29
+ sudo?: boolean;
30
+ command?: string;
31
+ }) => boolean;
42
32
  export declare const provisionRequest: (authn: Authn, args: yargs.ArgumentsCamelCase<BaseSshCommandArgs>, destination: string) => Promise<{
43
- request: Request<CliRequest>;
33
+ request: Request<CliSshRequest>;
44
34
  publicKey: string;
45
35
  privateKey: string;
46
36
  } | undefined>;
47
- export declare const requestToSsh: (request: Request<CliRequest>) => SshRequest;
37
+ export declare const requestToSsh: (request: Request<CliSshRequest>) => SshRequest;