@p0security/cli 0.7.1 → 0.8.1

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.
@@ -1,10 +1,4 @@
1
- import { AgentArgs, SshAgentEnv } from "./types";
2
- /** Spawns a subprocess with the ssh-agent command.
3
- * Detects the auth socket and agent PID from stdout.
4
- * Stdout and stderr of the subprocess is printed to stderr in debug mode.
5
- * The returned promise resolves with an object that contains the auth socket and agent PID,
6
- * or rejects with the contents of stderr. */
7
- export declare const sshAgent: (cmdArgs: AgentArgs) => Promise<SshAgentEnv>;
8
- export declare const sshAdd: (args: AgentArgs, sshAgentEnv: SshAgentEnv, privateKey: string) => Promise<number>;
9
- export declare const sshAddList: (args: AgentArgs, sshAgentEnv: SshAgentEnv) => Promise<number>;
10
- export declare const withSshAgent: <T>(args: AgentArgs, fn: (sshAgentEnv: SshAgentEnv) => Promise<T>) => Promise<T>;
1
+ import { AgentArgs } from "./types";
2
+ export declare const privateKeyExists: (args: AgentArgs) => Promise<boolean>;
3
+ export declare const addPrivateKey: (args: AgentArgs) => Promise<boolean>;
4
+ export declare const withSshAgent: <T>(args: AgentArgs, fn: () => Promise<T>) => Promise<T>;
@@ -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.withSshAgent = exports.sshAddList = exports.sshAdd = exports.sshAgent = void 0;
12
+ exports.withSshAgent = exports.addPrivateKey = exports.privateKeyExists = void 0;
13
13
  /** Copyright © 2024-present P0 Security
14
14
 
15
15
  This file is part of @p0security/cli
@@ -20,123 +20,83 @@ This file is part of @p0security/cli
20
20
 
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
- const __1 = require("../..");
23
+ const keys_1 = require("../../common/keys");
24
+ const subprocess_1 = require("../../common/subprocess");
24
25
  const stdio_1 = require("../../drivers/stdio");
25
- const node_child_process_1 = require("node:child_process");
26
- const AUTH_SOCK_MESSAGE = /SSH_AUTH_SOCK=(.+?);/;
27
- const AGENT_PID_MESSAGE = /SSH_AGENT_PID=(\d+?);/;
28
- /** Spawns a subprocess with given command, args, and options.
29
- * May write content to its standard input.
30
- * Stdout and stderr of the subprocess is printed to stderr in debug mode.
31
- * The returned promise resolves or rejects with the exit code. */
32
- const asyncSpawn = ({ debug }, command, args, options, writeStdin) => __awaiter(void 0, void 0, void 0, function* () {
33
- return new Promise((resolve, reject) => {
34
- var _a;
35
- const child = (0, node_child_process_1.spawn)(command, args, options);
36
- if (writeStdin) {
37
- if (!child.stdin)
38
- return reject("Child process has no stdin");
39
- child.stdin.write(writeStdin);
40
- }
41
- child.stdout.on("data", (data) => {
42
- if (debug) {
43
- (0, stdio_1.print2)(data.toString("utf-8"));
44
- }
45
- });
46
- child.stderr.on("data", (data) => {
47
- if (debug) {
48
- (0, stdio_1.print2)(data.toString("utf-8"));
49
- }
50
- });
51
- child.on("exit", (code) => {
52
- if (code !== 0) {
53
- return reject(code);
54
- }
55
- resolve(code);
56
- });
57
- if (writeStdin) {
58
- (_a = child.stdin) === null || _a === void 0 ? void 0 : _a.end();
59
- }
60
- });
61
- });
62
- /** Spawns a subprocess with the ssh-agent command.
63
- * Detects the auth socket and agent PID from stdout.
64
- * Stdout and stderr of the subprocess is printed to stderr in debug mode.
65
- * The returned promise resolves with an object that contains the auth socket and agent PID,
66
- * or rejects with the contents of stderr. */
67
- const sshAgent = (cmdArgs) => __awaiter(void 0, void 0, void 0, function* () {
68
- return new Promise((resolve, reject) => {
69
- let stderr = "";
70
- let stdout = "";
71
- // There is a debug flag in ssh-agent but it causes the ssh-agent process to NOT fork
72
- const child = (0, node_child_process_1.spawn)("ssh-agent");
73
- child.stdout.on("data", (data) => {
74
- const str = data.toString("utf-8");
75
- if (cmdArgs.debug) {
76
- (0, stdio_1.print2)(str);
77
- }
78
- stdout += str;
79
- });
80
- child.stderr.on("data", (data) => {
81
- const str = data.toString("utf-8");
82
- if (cmdArgs.debug) {
83
- (0, stdio_1.print2)(str);
84
- }
85
- stderr += str;
86
- });
87
- const exitListener = child.on("exit", (code) => {
88
- exitListener.unref();
89
- if (code !== 0) {
90
- return reject(stderr);
91
- }
92
- const authSockMatch = stdout.match(AUTH_SOCK_MESSAGE);
93
- const agentPidMatch = stdout.match(AGENT_PID_MESSAGE);
94
- if (!(authSockMatch === null || authSockMatch === void 0 ? void 0 : authSockMatch[1]) || !(agentPidMatch === null || agentPidMatch === void 0 ? void 0 : agentPidMatch[1])) {
95
- return reject("Failed to parse ssh-agent stdout:\n" + stdout);
96
- }
97
- resolve({
98
- SSH_AUTH_SOCK: authSockMatch[1],
99
- SSH_AGENT_PID: agentPidMatch[1],
100
- });
101
- });
102
- });
26
+ const isSshAgentRunning = (args) => __awaiter(void 0, void 0, void 0, function* () {
27
+ try {
28
+ if (args.debug)
29
+ (0, stdio_1.print2)("Searching for active ssh-agents");
30
+ // TODO: There's a possible edge-case but unlikely that ssh-agent has an invalid process or PID.
31
+ // We can check to see if the active PID matches the current socket to mitigate this.
32
+ yield (0, subprocess_1.asyncSpawn)(args, `pgrep`, ["-x", "ssh-agent"]);
33
+ if (args.debug)
34
+ (0, stdio_1.print2)("At least one SSH agent is running");
35
+ return true;
36
+ }
37
+ catch (_a) {
38
+ if (args.debug)
39
+ (0, stdio_1.print2)("No SSH agent is running!");
40
+ return false;
41
+ }
103
42
  });
104
- exports.sshAgent = sshAgent;
105
- const sshAgentKill = (args, sshAgentEnv) => __awaiter(void 0, void 0, void 0, function* () {
106
- return asyncSpawn(args, "ssh-agent", ["-k"], {
107
- env: Object.assign(Object.assign({}, process.env), sshAgentEnv),
108
- });
43
+ const isSshAgentAuthSocketSet = (args) => __awaiter(void 0, void 0, void 0, function* () {
44
+ try {
45
+ yield (0, subprocess_1.asyncSpawn)(args, `sh`, ["-c", '[ -n "$SSH_AUTH_SOCK" ]']);
46
+ if (args.debug)
47
+ (0, stdio_1.print2)(`SSH_AUTH_SOCK=${process.env.SSH_AUTH_SOCK}`);
48
+ return true;
49
+ }
50
+ catch (_b) {
51
+ if (args.debug)
52
+ (0, stdio_1.print2)("SSH_AUTH_SOCK is not set!");
53
+ return false;
54
+ }
109
55
  });
110
- const sshAdd = (args, sshAgentEnv, privateKey) => __awaiter(void 0, void 0, void 0, function* () {
111
- return asyncSpawn(args, "ssh-add",
112
- // In debug mode do not use the quiet flag. There is no debug flag in ssh-add.
113
- // Instead increase to maximum verbosity of 3 with -v flag.
114
- args.debug ? ["-v", "-v", "-v", "-"] : ["-q", "-"], { env: Object.assign(Object.assign({}, process.env), sshAgentEnv) }, privateKey);
56
+ const privateKeyExists = (args) => __awaiter(void 0, void 0, void 0, function* () {
57
+ try {
58
+ yield (0, subprocess_1.asyncSpawn)(args, `sh`, [
59
+ "-c",
60
+ `KEY_PATH="${keys_1.PRIVATE_KEY_PATH}" && KEY_FINGERPRINT=$(ssh-keygen -lf "$KEY_PATH" | awk '{print $2}') && ssh-add -l | grep -q "$KEY_FINGERPRINT" && exit 0 || exit 1`,
61
+ ]);
62
+ if (args.debug)
63
+ (0, stdio_1.print2)("Private key exists in ssh agent");
64
+ return true;
65
+ }
66
+ catch (_c) {
67
+ if (args.debug)
68
+ (0, stdio_1.print2)("Private key does not exist in ssh agent");
69
+ return false;
70
+ }
115
71
  });
116
- exports.sshAdd = sshAdd;
117
- const sshAddList = (args, sshAgentEnv) => __awaiter(void 0, void 0, void 0, function* () {
118
- return asyncSpawn(args, "ssh-add", ["-l"], {
119
- env: Object.assign(Object.assign({}, process.env), sshAgentEnv),
120
- });
72
+ exports.privateKeyExists = privateKeyExists;
73
+ const addPrivateKey = (args) => __awaiter(void 0, void 0, void 0, function* () {
74
+ try {
75
+ yield (0, subprocess_1.asyncSpawn)(args, `ssh-add`, [
76
+ keys_1.PRIVATE_KEY_PATH,
77
+ ...(args.debug ? ["-v", "-v", "-v"] : ["-q"]),
78
+ ]);
79
+ if (args.debug)
80
+ (0, stdio_1.print2)("Private key added to ssh agent");
81
+ return true;
82
+ }
83
+ catch (_d) {
84
+ if (args.debug)
85
+ (0, stdio_1.print2)("Failed to add private key to ssh agent");
86
+ return false;
87
+ }
121
88
  });
122
- exports.sshAddList = sshAddList;
89
+ exports.addPrivateKey = addPrivateKey;
123
90
  const withSshAgent = (args, fn) => __awaiter(void 0, void 0, void 0, function* () {
124
- const sshAgentEnv = yield (0, exports.sshAgent)(args);
125
- // The ssh-agent runs in a process that is not automatically terminated.
126
- // 1. Kill it when catching the main process termination signal.
127
- // 2. Also kill it if the encapsulated function throws an error.
128
- const abortListener = (_code) => {
129
- __1.TERMINATION_CONTROLLER.signal.removeEventListener("abort", abortListener);
130
- void sshAgentKill(args, sshAgentEnv);
131
- };
132
- __1.TERMINATION_CONTROLLER.signal.addEventListener("abort", abortListener);
133
- try {
134
- return yield fn(sshAgentEnv);
91
+ const isRunning = yield isSshAgentRunning(args);
92
+ const hasSocket = yield isSshAgentAuthSocketSet(args);
93
+ if (!isRunning || !hasSocket) {
94
+ throw "SSH agent is not running. Please start it by running: eval $(ssh-agent)";
135
95
  }
136
- finally {
137
- // keep the ssh-agent alive in debug mode
138
- if (!args.debug)
139
- yield sshAgentKill(args, sshAgentEnv);
96
+ const hasKey = yield (0, exports.privateKeyExists)(args);
97
+ if (!hasKey) {
98
+ yield (0, exports.addPrivateKey)(args);
140
99
  }
100
+ return yield fn();
141
101
  });
142
102
  exports.withSshAgent = withSshAgent;
@@ -11,7 +11,3 @@ You should have received a copy of the GNU General Public License along with @p0
11
11
  export declare type AgentArgs = {
12
12
  debug?: boolean;
13
13
  };
14
- export declare type SshAgentEnv = {
15
- SSH_AUTH_SOCK: string;
16
- SSH_AGENT_PID: string;
17
- };
@@ -8,22 +8,25 @@ This file is part of @p0security/cli
8
8
 
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
+ import { AwsPermissionSpec, AwsSsh } from "../plugins/aws/types";
12
+ import { GcpPermissionSpec, GcpSsh } from "../plugins/google/types";
11
13
  export declare const DONE_STATUSES: readonly ["DONE", "DONE_NOTIFIED"];
12
14
  export declare const DENIED_STATUSES: readonly ["DENIED", "DENIED_NOTIFIED"];
13
15
  export declare const ERROR_STATUSES: readonly ["ERRORED", "ERRORED", "ERRORED_NOTIFIED"];
14
- export declare type PluginRequest = {
15
- permission: object;
16
- generated?: object;
16
+ export declare type CliRequest = AwsSsh | GcpSsh;
17
+ export declare type PluginRequest = AwsPermissionSpec | GcpPermissionSpec;
18
+ export declare type CliPermissionSpec<P extends PluginRequest, C extends object | undefined = undefined> = P & {
19
+ cliLocalData: C;
17
20
  };
18
- export declare type Request<P extends PluginRequest = {
19
- permission: object;
20
- }> = {
21
+ export declare type PermissionSpec<K extends string, P extends {
22
+ type: string;
23
+ }, G extends object | undefined = undefined> = {
24
+ type: K;
25
+ permission: P;
26
+ generated: G;
27
+ };
28
+ export declare type Request<P extends PluginRequest> = P & {
21
29
  status: string;
22
- generatedRoles: {
23
- role: string;
24
- }[];
25
- generated: P["generated"];
26
- permission: P["permission"];
27
30
  principal: string;
28
31
  };
29
32
  export declare type RequestResponse<T> = {
@@ -1,16 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.ERROR_STATUSES = exports.DENIED_STATUSES = exports.DONE_STATUSES = 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
4
  exports.DONE_STATUSES = ["DONE", "DONE_NOTIFIED"];
15
5
  exports.DENIED_STATUSES = ["DENIED", "DENIED_NOTIFIED"];
16
6
  exports.ERROR_STATUSES = [
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@p0security/cli",
3
- "version": "0.7.1",
3
+ "version": "0.8.1",
4
4
  "description": "Execute infra CLI commands with P0 grants",
5
5
  "main": "index.ts",
6
6
  "repository": {
@@ -1,221 +0,0 @@
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.sshOrScp = void 0;
13
- const stdio_1 = require("../../../drivers/stdio");
14
- const aws_1 = require("../../okta/aws");
15
- const ssh_agent_1 = require("../../ssh-agent");
16
- const install_1 = require("./install");
17
- const node_child_process_1 = require("node:child_process");
18
- /** Matches the error message that AWS SSM print1 when access is not propagated */
19
- // Note that the resource will randomly be either the SSM document or the EC2 instance
20
- const UNPROVISIONED_ACCESS_MESSAGE = /An error occurred \(AccessDeniedException\) when calling the StartSession operation: User: arn:aws:sts::.*:assumed-role\/P0GrantsRole.* is not authorized to perform: ssm:StartSession on resource: arn:aws:.*:.*:.* because no identity-based policy allows the ssm:StartSession action/;
21
- /**
22
- * Matches the following error messages that AWS SSM print1 when ssh authorized
23
- * key access hasn't propagated to the instance yet.
24
- * - Connection closed by UNKNOWN port 65535
25
- * - scp: Connection closed
26
- * - kex_exchange_identification: Connection closed by remote host
27
- */
28
- const UNPROVISIONED_SCP_ACCESS_MESSAGE = /\bConnection closed\b.*\b(?:by UNKNOWN port \d+|by remote host)?/;
29
- /** Maximum amount of time after AWS SSM process starts to check for {@link UNPROVISIONED_ACCESS_MESSAGE}
30
- * in the process's stderr
31
- */
32
- const UNPROVISIONED_ACCESS_VALIDATION_WINDOW_MS = 5e3;
33
- /** Maximum number of attempts to start an SSM session
34
- *
35
- * Note that each attempt consumes ~ 1 s.
36
- */
37
- const MAX_SSM_RETRIES = 30;
38
- /** The name of the SessionManager port forwarding document. This document is managed by AWS. */
39
- const START_SSH_SESSION_DOCUMENT_NAME = "AWS-StartSSHSession";
40
- /** Checks if access has propagated through AWS to the SSM agent
41
- *
42
- * AWS takes about 8 minutes to fully resolve access after it is granted. During
43
- * this time, calls to `aws ssm start-session` will fail randomly with an
44
- * access denied exception.
45
- *
46
- * This function checks AWS to see if this exception is print1d to the SSM
47
- * error output within the first 5 seconds of startup. If it is, the returned
48
- * `isAccessPropagated()` function will return false. When this occurs, the
49
- * consumer of this function should retry the AWS SSM session.
50
- *
51
- * Note that this function requires interception of the AWS SSM stderr stream.
52
- * This works because AWS SSM wraps the session in a single-stream pty, so we
53
- * do not capture stderr emitted from the wrapped shell session.
54
- */
55
- const accessPropagationGuard = (child) => {
56
- let isEphemeralAccessDeniedException = false;
57
- const beforeStart = Date.now();
58
- child.stderr.on("data", (chunk) => {
59
- const chunkString = chunk.toString("utf-8");
60
- const match = chunkString.match(UNPROVISIONED_ACCESS_MESSAGE) ||
61
- chunkString.match(UNPROVISIONED_SCP_ACCESS_MESSAGE);
62
- if (match &&
63
- Date.now() <= beforeStart + UNPROVISIONED_ACCESS_VALIDATION_WINDOW_MS) {
64
- isEphemeralAccessDeniedException = true;
65
- return;
66
- }
67
- (0, stdio_1.print2)(chunkString);
68
- });
69
- return {
70
- isAccessPropagated: () => !isEphemeralAccessDeniedException,
71
- };
72
- };
73
- const createBaseSsmCommand = (args) => {
74
- return [
75
- "aws",
76
- "ssm",
77
- "start-session",
78
- "--region",
79
- args.region,
80
- "--target",
81
- args.instance,
82
- ];
83
- };
84
- const spawnChildProcess = (credential, command, args, stdio, sshAgentEnv) => (0, node_child_process_1.spawn)(command, args, {
85
- env: Object.assign(Object.assign(Object.assign({}, process.env), credential), (sshAgentEnv || {})),
86
- stdio,
87
- shell: false,
88
- });
89
- /** Starts an SSM session in the terminal by spawning `aws ssm` as a subprocess
90
- *
91
- * Requires `aws ssm` to be installed on the client machine.
92
- */
93
- function spawnSsmNode(options) {
94
- return __awaiter(this, void 0, void 0, function* () {
95
- return new Promise((resolve, reject) => {
96
- const child = spawnChildProcess(options.credential, options.command, options.args, options.stdio, options.sshAgentEnv);
97
- const { isAccessPropagated } = accessPropagationGuard(child);
98
- const exitListener = child.on("exit", (code) => {
99
- var _a, _b;
100
- exitListener.unref();
101
- // In the case of ephemeral AccessDenied exceptions due to unpropagated
102
- // permissions, continually retry access until success
103
- if (!isAccessPropagated()) {
104
- const attemptsRemaining = (_a = options === null || options === void 0 ? void 0 : options.attemptsRemaining) !== null && _a !== void 0 ? _a : MAX_SSM_RETRIES;
105
- if (attemptsRemaining <= 0) {
106
- reject("Access did not propagate through AWS before max retry attempts were exceeded. Please contact support@p0.dev for assistance.");
107
- return;
108
- }
109
- spawnSsmNode(Object.assign(Object.assign({}, options), { attemptsRemaining: attemptsRemaining - 1 }))
110
- .then((code) => resolve(code))
111
- .catch(reject);
112
- return;
113
- }
114
- (_b = options.abortController) === null || _b === void 0 ? void 0 : _b.abort(code);
115
- (0, stdio_1.print2)(`SSH session terminated`);
116
- resolve(code);
117
- });
118
- });
119
- });
120
- }
121
- const createProxyCommands = (data, args, sshAuthSock, debug) => {
122
- const ssmCommand = [
123
- ...createBaseSsmCommand({
124
- region: data.instance.region,
125
- instance: "%h",
126
- }),
127
- "--document-name",
128
- START_SSH_SESSION_DOCUMENT_NAME,
129
- "--parameters",
130
- '"portNumber=%p"',
131
- ];
132
- const commonArgs = [
133
- ...(debug ? ["-v"] : []),
134
- // ignore any overrides in the user's config file, we only want to use the ssh-agent we've set up for the session
135
- "-o",
136
- `IdentityAgent=${sshAuthSock}`,
137
- "-o",
138
- `ProxyCommand=${ssmCommand.join(" ")}`,
139
- ];
140
- if ("source" in args) {
141
- return {
142
- command: "scp",
143
- args: [
144
- ...commonArgs,
145
- // if a response is not received after three 5 minute attempts,
146
- // the connection will be closed.
147
- "-o",
148
- "ServerAliveCountMax=3",
149
- `-o`,
150
- "ServerAliveInterval=300",
151
- ...(args.recursive ? ["-r"] : []),
152
- args.source,
153
- args.destination,
154
- ],
155
- };
156
- }
157
- return {
158
- command: "ssh",
159
- args: [
160
- ...commonArgs,
161
- ...(args.A ? ["-A"] : []),
162
- ...(args.L ? ["-L", args.L] : []),
163
- ...(args.N ? ["-N"] : []),
164
- `${data.linuxUserName}@${data.instance.id}`,
165
- ...(args.command ? [args.command] : []),
166
- ...args.arguments.map((argument) =>
167
- // escape all double quotes (") in commands such as `p0 ssh <instance>> echo 'hello; "world"'` because we
168
- // need to encapsulate command arguments in double quotes as we pass them along to the remote shell
169
- `"${String(argument).replace(/"/g, '\\"')}"`),
170
- ],
171
- };
172
- };
173
- /** Converts arguments for manual execution - arguments may have to be quoted or certain characters escaped when executing the commands from a shell */
174
- const transformForShell = (args) => {
175
- return args.map((arg) => {
176
- // The ProxyCommand option must be surrounded by single quotes
177
- if (arg.startsWith("ProxyCommand=")) {
178
- const [name, ...value] = arg.split("="); // contains the '=' character in the parameters option: ProxyCommand=aws ssm start-session ... --parameters "portNumber=%p"
179
- return `${name}='${value.join("=")}'`;
180
- }
181
- return arg;
182
- });
183
- };
184
- const sshOrScp = (authn, data, cmdArgs, privateKey) => __awaiter(void 0, void 0, void 0, function* () {
185
- if (!(yield (0, install_1.ensureSsmInstall)())) {
186
- throw "Please try again after installing the required AWS utilities";
187
- }
188
- if (!privateKey) {
189
- throw "Failed to load a private key for this request. Please contact support@p0.dev for assistance.";
190
- }
191
- const credential = yield (0, aws_1.assumeRoleWithOktaSaml)(authn, {
192
- account: data.instance.accountId,
193
- role: data.role,
194
- });
195
- return (0, ssh_agent_1.withSshAgent)(cmdArgs, (sshAgentEnv) => __awaiter(void 0, void 0, void 0, function* () {
196
- yield (0, ssh_agent_1.sshAdd)(cmdArgs, sshAgentEnv, privateKey);
197
- if (cmdArgs.debug) {
198
- (0, stdio_1.print2)("SSH Agent Keys:");
199
- yield (0, ssh_agent_1.sshAddList)(cmdArgs, sshAgentEnv);
200
- }
201
- const { command, args } = createProxyCommands(data, cmdArgs, sshAgentEnv.SSH_AUTH_SOCK, cmdArgs.debug);
202
- if (cmdArgs.debug) {
203
- const reproCommands = [
204
- `eval $(p0 aws role assume ${data.role} --account ${data.instance.accountId})`,
205
- `export SSH_AUTH_SOCK=${sshAgentEnv.SSH_AUTH_SOCK}`,
206
- `export SSH_AGENT_PID=${sshAgentEnv.SSH_AGENT_PID}`,
207
- `${command} ${transformForShell(args).join(" ")}`,
208
- ];
209
- (0, stdio_1.print2)(`Execute the following commands to create a similar SSH/SCP session:\n*** COMMANDS BEGIN ***\n${reproCommands.join("\n")}\n*** COMMANDS END ***\n\nTHE SSH AGENT PROCESS WILL NOT BE KILLED AUTOMATICALLY IN DEBUG MODE\nYou can kill it with "sudo kill ${sshAgentEnv.SSH_AGENT_PID}"\n`);
210
- }
211
- return spawnSsmNode({
212
- credential,
213
- sshAgentEnv,
214
- abortController: new AbortController(),
215
- command,
216
- args,
217
- stdio: ["inherit", "inherit", "pipe"],
218
- });
219
- }));
220
- });
221
- exports.sshOrScp = sshOrScp;