Skip to content

Commit

Permalink
SSH Command: add support for local port forwarding
Browse files Browse the repository at this point in the history
  • Loading branch information
GGonryun committed Feb 26, 2024
1 parent f8c7907 commit 0ce2b44
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 2 deletions.
18 changes: 18 additions & 0 deletions src/commands/ssh.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,13 @@ import yargs from "yargs";
export type SshCommandArgs = {
instance: string;
command?: string;
L?: string;
arguments: string[];
};

// Matches strings with the pattern "digits:digits" (e.g. 1234:5678)
const LOCAL_PORT_FORWARD_PATTERN = /^\d+:\d+$/;

/** Maximum amount of time to wait after access is approved to wait for access
* to be configured
*/
Expand All @@ -57,6 +61,20 @@ export const sshCommand = (yargs: yargs.Argv) =>
array: true,
string: true,
default: [] as string[],
})
.check((argv: yargs.ArgumentsCamelCase<SshCommandArgs>) => {
if (argv.L == null) return true;

return (
argv.L.match(LOCAL_PORT_FORWARD_PATTERN) ||
"Local port forward should be in the format `local_port:remote_port`"
);
})
.option("L", {
type: "string",
describe:
// the order of the sockets in the address matches the ssh man page
"Forward a local port to the remote host; `local_socket:remote_socket`",
}),
guard(ssh)
);
Expand Down
26 changes: 24 additions & 2 deletions src/plugins/aws/ssm/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,13 +37,17 @@ const MAX_SSM_RETRIES = 30;
const INSTANCE_ARN_PATTERN =
/^arn:aws:ssm:([^:]+):([^:]+):managed-instance\/([^:]+)$/;

/** The name of the SessionManager port forwarding document. This document is managed by AWS. */
const LOCAL_PORT_FORWARDING_DOCUMENT_NAME = "AWS-StartPortForwardingSession";

type SsmArgs = {
instance: string;
region: string;
requestId: string;
documentName: string;
credential: AwsCredentials;
command?: string;
forwardPortAddress?: string;
};

/** Checks if access has propagated through AWS to the SSM agent
Expand Down Expand Up @@ -88,6 +92,12 @@ const accessPropagationGuard = (
};

const createSsmCommand = (args: Omit<SsmArgs, "requestId">) => {
const hasCommand = args.command && args.command.trim();

if (hasCommand && args.forwardPortAddress) {
throw "Invalid arguments. Specify either a command or port forwarding, not both.";
}

const ssmCommand = [
"aws",
"ssm",
Expand All @@ -97,11 +107,22 @@ const createSsmCommand = (args: Omit<SsmArgs, "requestId">) => {
"--target",
args.instance,
"--document-name",
args.documentName,
// Port forwarding is a special case that uses an AWS-managed document and
// not the user-generated document we use for an SSH session
args.forwardPortAddress
? LOCAL_PORT_FORWARDING_DOCUMENT_NAME
: args.documentName,
];

if (args.command && args.command.trim()) {
if (hasCommand) {
ssmCommand.push("--parameters", `command='${args.command}'`);
} else if (args.forwardPortAddress) {
const [localPort, remotePort] = args.forwardPortAddress.split(":");

ssmCommand.push(
"--parameters",
`localPortNumber=${localPort},portNumber=${remotePort}`
);
}

return ssmCommand;
Expand Down Expand Up @@ -193,6 +214,7 @@ export const ssm = async (
region: region!,
documentName: request.generated.documentName,
requestId: request.id,
forwardPortAddress: args.L,
credential,
command: commandParameter(args),
};
Expand Down

0 comments on commit 0ce2b44

Please sign in to comment.