@p0security/cli 0.9.0 → 0.10.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.
@@ -75,16 +75,17 @@ const scpAction = (args) => __awaiter(void 0, void 0, void 0, function* () {
75
75
  if (!host) {
76
76
  throw "Could not determine host identifier from source or destination";
77
77
  }
78
- const result = yield (0, ssh_3.provisionRequest)(authn, args, host);
79
- if (!result) {
80
- throw "Server did not return a request id. Please contact support@p0.dev for assistance.";
81
- }
82
- const { request, privateKey } = result;
83
- const data = (0, ssh_3.requestToSsh)(request);
78
+ const { request, privateKey, sshProvider } = yield (0, ssh_3.prepareRequest)(authn, args, host);
84
79
  // replace the host with the linuxUserName@instanceId
85
- const { source, destination } = replaceHostWithInstance(data, args);
86
- yield (0, ssh_1.sshOrScp)(authn, data, Object.assign(Object.assign({}, args), { source,
87
- destination }), privateKey);
80
+ const { source, destination } = replaceHostWithInstance(request, args);
81
+ yield (0, ssh_1.sshOrScp)({
82
+ authn,
83
+ request,
84
+ cmdArgs: Object.assign(Object.assign({}, args), { source,
85
+ destination }),
86
+ privateKey,
87
+ sshProvider,
88
+ });
88
89
  });
89
90
  /** If a path is not explicitly local, use this pattern to determine if it's remote */
90
91
  const REMOTE_PATTERN_COLON = /^([^:]+:)(.*)$/; // Matches host:[path]
@@ -1,6 +1,6 @@
1
1
  import { Authn } from "../../types/identity";
2
2
  import { Request } from "../../types/request";
3
- import { CliSshRequest, SshProvider, SshRequest, SupportedSshProvider } from "../../types/ssh";
3
+ import { PluginSshRequest, SshProvider, SupportedSshProvider } from "../../types/ssh";
4
4
  import yargs from "yargs";
5
5
  export declare type BaseSshCommandArgs = {
6
6
  sudo?: boolean;
@@ -18,8 +18,10 @@ export declare type SshCommandArgs = BaseSshCommandArgs & {
18
18
  sudo?: boolean;
19
19
  destination: string;
20
20
  L?: string;
21
+ R?: string;
21
22
  N?: boolean;
22
23
  A?: boolean;
24
+ o?: string;
23
25
  arguments: string[];
24
26
  command?: string;
25
27
  };
@@ -30,8 +32,14 @@ export declare const isSudoCommand: (args: {
30
32
  command?: string;
31
33
  }) => boolean;
32
34
  export declare const provisionRequest: (authn: Authn, args: yargs.ArgumentsCamelCase<BaseSshCommandArgs>, destination: string) => Promise<{
33
- request: Request<CliSshRequest>;
35
+ provisionedRequest: Request<PluginSshRequest>;
34
36
  publicKey: string;
35
37
  privateKey: string;
36
38
  } | undefined>;
37
- export declare const requestToSsh: (request: Request<CliSshRequest>) => SshRequest;
39
+ export declare const prepareRequest: (authn: Authn, args: yargs.ArgumentsCamelCase<BaseSshCommandArgs>, destination: string) => Promise<{
40
+ request: any;
41
+ sshProvider: SshProvider<any, any, any, any>;
42
+ provisionedRequest: Request<PluginSshRequest>;
43
+ publicKey: string;
44
+ privateKey: string;
45
+ }>;
@@ -9,7 +9,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
9
9
  });
10
10
  };
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
- exports.requestToSsh = exports.provisionRequest = exports.isSudoCommand = exports.SSH_PROVIDERS = void 0;
12
+ exports.prepareRequest = exports.provisionRequest = exports.isSudoCommand = exports.SSH_PROVIDERS = void 0;
13
13
  /** Copyright © 2024-present P0 Security
14
14
 
15
15
  This file is part of @p0security/cli
@@ -77,11 +77,21 @@ const provisionRequest = (authn, args, destination) => __awaiter(void 0, void 0,
77
77
  if (provisionedRequest.permission.spec.publicKey !== publicKey) {
78
78
  throw "Public key mismatch. Please revoke the request and try again.";
79
79
  }
80
+ return { provisionedRequest, publicKey, privateKey };
81
+ });
82
+ exports.provisionRequest = provisionRequest;
83
+ const prepareRequest = (authn, args, destination) => __awaiter(void 0, void 0, void 0, function* () {
84
+ const result = yield (0, exports.provisionRequest)(authn, args, destination);
85
+ if (!result) {
86
+ throw "Server did not return a request id. Please contact support@p0.dev for assistance.";
87
+ }
88
+ const { provisionedRequest } = result;
89
+ const sshProvider = exports.SSH_PROVIDERS[provisionedRequest.permission.spec.type];
90
+ yield sshProvider.ensureInstall();
80
91
  const cliRequest = yield pluginToCliRequest(provisionedRequest, {
81
92
  debug: args.debug,
82
93
  });
83
- return { request: cliRequest, publicKey, privateKey };
94
+ const request = sshProvider.requestToSsh(cliRequest);
95
+ return Object.assign(Object.assign({}, result), { request, sshProvider });
84
96
  });
85
- exports.provisionRequest = provisionRequest;
86
- const requestToSsh = (request) => exports.SSH_PROVIDERS[request.permission.spec.type].requestToSsh(request);
87
- exports.requestToSsh = requestToSsh;
97
+ exports.prepareRequest = prepareRequest;
@@ -28,10 +28,6 @@ const sshCommand = (yargs) => yargs.command("ssh <destination> [command [argumen
28
28
  .positional("destination", {
29
29
  type: "string",
30
30
  demandOption: true,
31
- })
32
- .option("sudo", {
33
- type: "boolean",
34
- describe: "Add user to sudoers file",
35
31
  })
36
32
  .positional("command", {
37
33
  type: "string",
@@ -42,11 +38,20 @@ const sshCommand = (yargs) => yargs.command("ssh <destination> [command [argumen
42
38
  array: true,
43
39
  string: true,
44
40
  default: [],
41
+ })
42
+ .option("sudo", {
43
+ type: "boolean",
44
+ describe: "Add user to sudoers file",
45
45
  })
46
46
  .option("L", {
47
47
  type: "string",
48
48
  // Copied from `man ssh`
49
49
  describe: "Specifies that connections to the given TCP port or Unix socket on the local (client) host are to be forwarded to the given host and port, or Unix socket, on the remote side.",
50
+ })
51
+ .option("R", {
52
+ type: "string",
53
+ // Copied from `man ssh`
54
+ describe: "Specifies that connections to the given TCP port or Unix socket on the remote (server) host are to be forwarded to the local side.",
50
55
  })
51
56
  .option("N", {
52
57
  type: "boolean",
@@ -55,6 +60,10 @@ const sshCommand = (yargs) => yargs.command("ssh <destination> [command [argumen
55
60
  .option("A", {
56
61
  type: "boolean",
57
62
  describe: "Enables forwarding of connections from an authentication agent such as ssh-agent",
63
+ })
64
+ .option("o", {
65
+ type: "string",
66
+ describe: "Can be used to give options in the format used in the SSH configuration file.",
58
67
  })
59
68
  // Match `p0 request --reason`
60
69
  .option("reason", {
@@ -85,11 +94,12 @@ exports.sshCommand = sshCommand;
85
94
  const sshAction = (args) => __awaiter(void 0, void 0, void 0, function* () {
86
95
  // Prefix is required because the backend uses it to determine that this is an AWS request
87
96
  const authn = yield (0, auth_1.authenticate)();
88
- const destination = args.destination;
89
- const result = yield (0, ssh_2.provisionRequest)(authn, args, destination);
90
- if (!result) {
91
- throw "Server did not return a request id. Please contact support@p0.dev for assistance.";
92
- }
93
- const { request, privateKey } = result;
94
- yield (0, ssh_1.sshOrScp)(authn, (0, ssh_2.requestToSsh)(request), Object.assign(Object.assign({}, args), { destination }), privateKey);
97
+ const { request, privateKey, sshProvider } = yield (0, ssh_2.prepareRequest)(authn, args, args.destination);
98
+ yield (0, ssh_1.sshOrScp)({
99
+ authn,
100
+ request,
101
+ cmdArgs: args,
102
+ privateKey,
103
+ sshProvider,
104
+ });
95
105
  });
@@ -33,11 +33,13 @@ exports.awsSshProvider = {
33
33
  ? Object.assign(Object.assign({}, common), { role: name, type: "aws", access: "role" }) : Object.assign(Object.assign({}, common), { idc, permissionSet: name, type: "aws", access: "idc" });
34
34
  },
35
35
  toCliRequest: (request) => __awaiter(void 0, void 0, void 0, function* () { return (Object.assign(Object.assign({}, request), { cliLocalData: undefined })); }),
36
- cloudProviderLogin: (authn, request) => __awaiter(void 0, void 0, void 0, function* () {
37
- var _a, _b, _c, _d;
36
+ ensureInstall: () => __awaiter(void 0, void 0, void 0, function* () {
38
37
  if (!(yield (0, install_1.ensureSsmInstall)())) {
39
38
  throw "Please try again after installing the required AWS utilities";
40
39
  }
40
+ }),
41
+ cloudProviderLogin: (authn, request) => __awaiter(void 0, void 0, void 0, function* () {
42
+ var _a, _b, _c, _d;
41
43
  const { config } = yield (0, config_1.getAwsConfig)(authn, request.accountId);
42
44
  if (!((_a = config.login) === null || _a === void 0 ? void 0 : _a.type) || ((_b = config.login) === null || _b === void 0 ? void 0 : _b.type) === "iam") {
43
45
  throw "This account is not configured for SSH access via the P0 CLI";
@@ -1,16 +1,4 @@
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
- var __importDefault = (this && this.__importDefault) || function (mod) {
12
- return (mod && mod.__esModule) ? mod : { "default": mod };
13
- };
14
2
  Object.defineProperty(exports, "__esModule", { value: true });
15
3
  exports.ensureSsmInstall = void 0;
16
4
  /** Copyright © 2024-present P0 Security
@@ -24,8 +12,6 @@ This file is part of @p0security/cli
24
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/>.
25
13
  **/
26
14
  const install_1 = require("../../../common/install");
27
- const types_1 = require("../../../types");
28
- const node_os_1 = __importDefault(require("node:os"));
29
15
  const SsmItems = [...install_1.AwsItems, "session-manager-plugin"];
30
16
  const SsmInstall = Object.assign(Object.assign({}, install_1.AwsInstall), { "session-manager-plugin": {
31
17
  label: "the AWS CLI Session Manager plugin",
@@ -44,11 +30,5 @@ const SsmInstall = Object.assign(Object.assign({}, install_1.AwsInstall), { "ses
44
30
  * the user declines, or if not a TTY, the installation commands are printed to
45
31
  * stdout.
46
32
  */
47
- const ensureSsmInstall = () => __awaiter(void 0, void 0, void 0, function* () {
48
- const platform = node_os_1.default.platform();
49
- // Preserve existing behavior of a hard error on unsupported platforms
50
- if (!(0, types_1.isa)(install_1.SupportedPlatforms)(platform))
51
- throw "SSH to AWS managed instances is only available on MacOS";
52
- return yield (0, install_1.ensureInstall)(SsmItems, SsmInstall);
53
- });
33
+ const ensureSsmInstall = () => (0, install_1.ensureInstall)(SsmItems, SsmInstall);
54
34
  exports.ensureSsmInstall = ensureSsmInstall;
@@ -0,0 +1,2 @@
1
+ export declare const SupportedPlatforms: readonly ["darwin"];
2
+ export declare const ensureGcpSshInstall: () => Promise<boolean>;
@@ -0,0 +1,38 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ensureGcpSshInstall = exports.SupportedPlatforms = 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 install_1 = require("../../common/install");
15
+ exports.SupportedPlatforms = ["darwin"];
16
+ const GcpSshItems = ["gcloud"];
17
+ const GcpSshInstall = {
18
+ gcloud: {
19
+ label: "GCloud CLI",
20
+ commands: {
21
+ darwin: [
22
+ // See https://cloud.google.com/sdk/docs/install-sdk
23
+ "architecture=$(arch)",
24
+ 'package=$([ $architecture = "arm64" ] && echo "https://dl.google.com/dl/cloudsdk/channels/rapid/downloads/google-cloud-cli-darwin-arm.tar.gz" || "https://dl.google.com/dl/cloudsdk/channels/rapid/downloads/google-cloud-cli-darwin-x86_64.tar.gz" )',
25
+ "wget -O ~/google-cloud-cli.tar.gz $package",
26
+ "tar -xzf ~/google-cloud-cli.tar.gz -C ~",
27
+ "~/google-cloud-sdk/install.sh",
28
+ "rm -rf ~/google-cloud-cli.tar.gz",
29
+ // Symlink gcloud to /usr/local/bin - assumes /usr/local/bin is already in $PATH so next time `gcloud` is run it will be found
30
+ "sudo mkdir -p /usr/local/bin",
31
+ "sudo ln -s ~/google-cloud-sdk/bin/gcloud /usr/local/bin/gcloud",
32
+ "sudo chown root: /usr/local/bin/gcloud",
33
+ ],
34
+ },
35
+ },
36
+ };
37
+ const ensureGcpSshInstall = () => (0, install_1.ensureInstall)(GcpSshItems, GcpSshInstall);
38
+ exports.ensureGcpSshInstall = ensureGcpSshInstall;
@@ -21,6 +21,7 @@ This file is part of @p0security/cli
21
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
22
  **/
23
23
  const ssh_1 = require("../../commands/shared/ssh");
24
+ const install_1 = require("./install");
24
25
  const ssh_key_1 = require("./ssh-key");
25
26
  /** Maximum number of attempts to start an SSH session
26
27
  *
@@ -42,6 +43,11 @@ exports.gcpSshProvider = {
42
43
  linuxUserName: yield (0, ssh_key_1.importSshKey)(request.permission.spec.publicKey, options),
43
44
  } }));
44
45
  }),
46
+ ensureInstall: () => __awaiter(void 0, void 0, void 0, function* () {
47
+ if (!(yield (0, install_1.ensureGcpSshInstall)())) {
48
+ throw "Please try again after installing the required GCP utilities";
49
+ }
50
+ }),
45
51
  cloudProviderLogin: () => __awaiter(void 0, void 0, void 0, function* () { return undefined; }),
46
52
  proxyCommand: (request) => {
47
53
  return [
@@ -12,10 +12,14 @@ import { KubeconfigCommandArgs } from "../../commands/kubeconfig";
12
12
  import { Authn } from "../../types/identity";
13
13
  import { Request } from "../../types/request";
14
14
  import { AwsCredentials } from "../aws/types";
15
- import { EksClusterConfig, K8sGenerated, K8sPermissionSpec } from "./types";
15
+ import { K8sGenerated, K8sPermissionSpec } from "./types";
16
16
  import yargs from "yargs";
17
17
  export declare const getAndValidateK8sIntegration: (authn: Authn, clusterId: string) => Promise<{
18
- clusterConfig: EksClusterConfig;
18
+ clusterConfig: {
19
+ clusterId: string;
20
+ awsAccountId: string;
21
+ awsClusterArn: string;
22
+ };
19
23
  awsLoginType: "federated" | "idc";
20
24
  }>;
21
25
  export declare const requestAccessToCluster: (authn: Authn, args: yargs.ArgumentsCamelCase<KubeconfigCommandArgs>, clusterId: string, role: string) => Promise<Request<K8sPermissionSpec>>;
@@ -21,15 +21,18 @@ const aws_1 = require("../okta/aws");
21
21
  const firestore_2 = require("firebase/firestore");
22
22
  const lodash_1 = require("lodash");
23
23
  const getAndValidateK8sIntegration = (authn, clusterId) => __awaiter(void 0, void 0, void 0, function* () {
24
- var _a;
24
+ var _a, _b;
25
25
  const configDoc = yield (0, firestore_2.getDoc)((0, firestore_1.doc)(`o/${authn.identity.org.tenantId}/integrations/k8s`));
26
26
  // Validation done here in lieu of the backend, since the backend doesn't validate until approval. TODO: ENG-2365.
27
- const clusterConfig = (_a = configDoc
28
- .data()) === null || _a === void 0 ? void 0 : _a.workflows.items.find((c) => c.clusterId === clusterId && c.state === "installed");
29
- if (!clusterConfig) {
27
+ const config = (_b = (_a = configDoc.data()) === null || _a === void 0 ? void 0 : _a["iam-write"]) === null || _b === void 0 ? void 0 : _b[clusterId];
28
+ if (!config) {
30
29
  throw `Cluster with ID ${clusterId} not found`;
31
30
  }
32
- const { awsAccountId, awsClusterArn } = clusterConfig;
31
+ if (config.state !== "installed" || config.provider.type !== "aws") {
32
+ throw `Cluster with ID ${clusterId} is not installed`;
33
+ }
34
+ const { provider } = config;
35
+ const { accountId: awsAccountId, clusterArn: awsClusterArn } = provider;
33
36
  if (!awsAccountId || !awsClusterArn) {
34
37
  throw (`This command currently only supports AWS EKS clusters, and ${clusterId} is not configured as one.\n` +
35
38
  "You can request access to the cluster using the `p0 request k8s` command.");
@@ -41,8 +44,11 @@ const getAndValidateK8sIntegration = (authn, clusterId) => __awaiter(void 0, voi
41
44
  throw "This AWS account is not configured for kubectl access via the P0 CLI.\nYou can request access to the cluster using the `p0 request k8s` command.";
42
45
  }
43
46
  return {
44
- clusterConfig: Object.assign(Object.assign({}, clusterConfig), { awsAccountId,
45
- awsClusterArn }),
47
+ clusterConfig: {
48
+ clusterId,
49
+ awsAccountId,
50
+ awsClusterArn,
51
+ },
46
52
  awsLoginType: awsLogin.type,
47
53
  };
48
54
  });
@@ -9,29 +9,24 @@ This file is part of @p0security/cli
9
9
  You should have received a copy of the GNU General Public License along with @p0security/cli. If not, see <https://www.gnu.org/licenses/>.
10
10
  **/
11
11
  import { PermissionSpec } from "../../types/request";
12
- export declare type K8sConfig = {
13
- workflows: {
14
- items: K8sClusterConfig[];
15
- };
16
- };
17
12
  export declare type K8sClusterConfig = {
18
- clusterId: string;
13
+ label?: string;
19
14
  clusterServer: string;
20
15
  clusterCertificate: string;
16
+ isProxy: boolean;
17
+ token: string;
18
+ publicJwk?: string;
19
+ provider: {
20
+ type: "aws";
21
+ clusterArn: string;
22
+ accountId: string;
23
+ } | {
24
+ type: "email";
25
+ };
21
26
  state: string;
22
- awsAccountId?: string;
23
- awsClusterArn?: string;
24
- } & (KubernetesProxyComponentConfig | KubernetesPublicComponentConfig);
25
- export declare type EksClusterConfig = K8sClusterConfig & {
26
- awsAccountId: string;
27
- awsClusterArn: string;
28
- };
29
- declare type KubernetesProxyComponentConfig = {
30
- isProxy: true;
31
- publicJwk: string;
32
27
  };
33
- export declare type KubernetesPublicComponentConfig = {
34
- isProxy: false;
28
+ export declare type K8sConfig = {
29
+ "iam-write": Record<string, K8sClusterConfig>;
35
30
  };
36
31
  export declare type K8sPermissionSpec = PermissionSpec<"k8s", K8sResourcePermission, K8sGenerated>;
37
32
  export declare type K8sResourcePermission = {
@@ -54,4 +49,3 @@ export declare type K8sGenerated = {
54
49
  };
55
50
  role: string;
56
51
  };
57
- export {};
@@ -10,5 +10,11 @@ You should have received a copy of the GNU General Public License along with @p0
10
10
  **/
11
11
  import { CommandArgs } from "../../commands/shared/ssh";
12
12
  import { Authn } from "../../types/identity";
13
- import { SshRequest } from "../../types/ssh";
14
- export declare const sshOrScp: (authn: Authn, request: SshRequest, cmdArgs: CommandArgs, privateKey: string) => Promise<number | null>;
13
+ import { SshProvider, SshRequest } from "../../types/ssh";
14
+ export declare const sshOrScp: (args: {
15
+ authn: Authn;
16
+ request: SshRequest;
17
+ cmdArgs: CommandArgs;
18
+ privateKey: string;
19
+ sshProvider: SshProvider<any, any, any, any>;
20
+ }) => Promise<number | null>;
@@ -137,6 +137,13 @@ function spawnSshNode(options) {
137
137
  return __awaiter(this, void 0, void 0, function* () {
138
138
  return new Promise((resolve, reject) => {
139
139
  const provider = ssh_1.SSH_PROVIDERS[options.provider];
140
+ const attemptsRemaining = options.attemptsRemaining;
141
+ if (options.debug) {
142
+ const gerund = options.isAccessPropagationPreTest
143
+ ? "Pre-testing"
144
+ : "Trying";
145
+ (0, stdio_1.print2)(`Waiting for access to propagate. ${gerund} SSH session... (remaining attempts: ${attemptsRemaining})`);
146
+ }
140
147
  const child = spawnChildProcess(options.credential, options.command, options.args, options.stdio);
141
148
  // TODO ENG-2284 support login with Google Cloud: currently return a boolean to indicate if the exception was a Google login error.
142
149
  const { isAccessPropagated, isGoogleLoginException } = accessPropagationGuard(child, options.debug);
@@ -146,10 +153,6 @@ function spawnSshNode(options) {
146
153
  // In the case of ephemeral AccessDenied exceptions due to unpropagated
147
154
  // permissions, continually retry access until success
148
155
  if (!isAccessPropagated()) {
149
- const attemptsRemaining = options.attemptsRemaining;
150
- if (options.debug) {
151
- (0, stdio_1.print2)(`Waiting for access to propagate. Retrying SSH session... (remaining attempts: ${attemptsRemaining})`);
152
- }
153
156
  if (attemptsRemaining <= 0) {
154
157
  reject(`Access did not propagate through ${provider.friendlyName} before max retry attempts were exceeded. Please contact support@p0.dev for assistance.`);
155
158
  return;
@@ -200,7 +203,9 @@ const createCommand = (data, args, proxyCommand) => {
200
203
  ...commonArgs,
201
204
  ...(args.A ? ["-A"] : []),
202
205
  ...(args.L ? ["-L", args.L] : []),
206
+ ...(args.R ? ["-R", args.R] : []),
203
207
  ...(args.N ? ["-N"] : []),
208
+ ...(args.o ? ["-o", args.o] : []),
204
209
  `${data.linuxUserName}@${data.id}`,
205
210
  ...(args.command ? [args.command] : []),
206
211
  ...args.arguments.map((argument) =>
@@ -243,11 +248,11 @@ const preTestAccessPropagationIfNeeded = (sshProvider, request, cmdArgs, proxyCo
243
248
  }
244
249
  return null;
245
250
  });
246
- const sshOrScp = (authn, request, cmdArgs, privateKey) => __awaiter(void 0, void 0, void 0, function* () {
251
+ const sshOrScp = (args) => __awaiter(void 0, void 0, void 0, function* () {
252
+ const { authn, request, cmdArgs, privateKey, sshProvider } = args;
247
253
  if (!privateKey) {
248
254
  throw "Failed to load a private key for this request. Please contact support@p0.dev for assistance.";
249
255
  }
250
- const sshProvider = ssh_1.SSH_PROVIDERS[request.type];
251
256
  const credential = yield sshProvider.cloudProviderLogin(authn, request);
252
257
  const proxyCommand = sshProvider.proxyCommand(request);
253
258
  return (0, ssh_agent_1.withSshAgent)(cmdArgs, () => __awaiter(void 0, void 0, void 0, function* () {
@@ -26,6 +26,7 @@ export declare type SshProvider<PR extends PluginSshRequest = PluginSshRequest,
26
26
  toCliRequest: (request: Request<PR>, options?: {
27
27
  debug?: boolean;
28
28
  }) => Promise<Request<CliSshRequest>>;
29
+ ensureInstall: () => Promise<void>;
29
30
  /** Logs in the user to the cloud provider */
30
31
  cloudProviderLogin: (authn: Authn, request: SR) => Promise<C>;
31
32
  /** Returns the command and its arguments that are going to be injected as the ssh ProxyCommand option */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@p0security/cli",
3
- "version": "0.9.0",
3
+ "version": "0.10.0",
4
4
  "description": "Execute infra CLI commands with P0 grants",
5
5
  "main": "index.ts",
6
6
  "repository": {