fix: harden ssh script shell compatibility
This commit is contained in:
+16
-7
@@ -88,6 +88,7 @@ const windowsCmdExeNativePath = "C:\\Windows\\System32\\cmd.exe";
|
||||
const defaultSshSlowWarningMs = 10_000;
|
||||
const defaultSshRuntimeTimeoutMs = 60_000;
|
||||
const maxSshRuntimeTimeoutMs = 60_000;
|
||||
export const sshShellCompatibilityPrelude = 'printf(){ if [ "${1+x}" = x ] && [ "$1" = "-v" ] && [ -n "${BASH_VERSION:-}" ]; then command printf "$@"; return $?; fi; if [ "${1+x}" = x ] && [ "$1" = "--" ]; then shift; fi; command printf -- "$@"; }';
|
||||
const k3sResourceKindAliases = new Set(["pod", "po", "pods", "deployment", "deploy", "deployments", "statefulset", "sts", "daemonset", "ds", "job", "jobs"]);
|
||||
const legacyK3sOperationRouteSegments = new Set([
|
||||
"guard",
|
||||
@@ -1326,7 +1327,7 @@ function parseK3sControlPlaneOperation(route: ParsedSshRoute, args: string[]): P
|
||||
}
|
||||
if (operation === "shell") {
|
||||
const parsed = parseShellStringOperationArgs(args.slice(1), `ssh ${route.providerId}:k3s shell`);
|
||||
return { remoteCommand: shellArgv(["env", `KUBECONFIG=${nativeK3sKubeconfig}`, parsed.shell, "-c", parsed.command]), requiresStdin: false, invocationKind: "helper" };
|
||||
return { remoteCommand: shellArgv(["env", `KUBECONFIG=${nativeK3sKubeconfig}`, parsed.shell, "-c", shellScriptWithCompatibility(parsed.command)]), requiresStdin: false, invocationKind: "helper" };
|
||||
}
|
||||
if (operation === "guard") {
|
||||
if (args.length > 1) throw new Error(`ssh ${route.providerId}:k3s guard does not accept extra arguments`);
|
||||
@@ -1362,7 +1363,7 @@ function parseK3sTargetOperation(route: ParsedSshRoute, args: string[]): ParsedS
|
||||
if (operation === "script") return buildK3sScriptOperation([...targetArgs, ...operationArgs]);
|
||||
if (operation === "shell") {
|
||||
const parsed = parseShellStringOperationArgs(operationArgs, `ssh ${route.raw} shell`);
|
||||
return { remoteCommand: buildK3sExecCommand([...targetArgs, "--", parsed.shell, "-c", parsed.command]), requiresStdin: false, invocationKind: "helper" };
|
||||
return { remoteCommand: buildK3sExecCommand([...targetArgs, "--", parsed.shell, "-c", shellScriptWithCompatibility(parsed.command)]), requiresStdin: false, invocationKind: "helper" };
|
||||
}
|
||||
if (operation === "logs") return { remoteCommand: buildK3sLogsCommand([...targetArgs, ...operationArgs]), requiresStdin: false, invocationKind: "helper" };
|
||||
if (operation === "argv") return { remoteCommand: buildK3sExecCommand([...targetArgs, ...k3sRouteCommandArgs(operationArgs)]), requiresStdin: false, invocationKind: "argv" };
|
||||
@@ -1520,7 +1521,7 @@ function buildK3sScriptOperation(args: string[]): ParsedSshArgs {
|
||||
if (parsed.shell === null && parsed.command.length > 0) {
|
||||
return { remoteCommand: buildK3sInlineScriptCommand(parsed), requiresStdin: false, invocationKind: "helper" };
|
||||
}
|
||||
return { remoteCommand: buildK3sStdinScriptCommand(parsed), requiresStdin: true, invocationKind: "helper" };
|
||||
return { remoteCommand: buildK3sStdinScriptCommand(parsed), requiresStdin: true, invocationKind: "helper", stdinPrefix: shellScriptStdinPrefix() };
|
||||
}
|
||||
|
||||
function buildK3sStdinScriptCommand(parsed: K3sTargetOptions): string {
|
||||
@@ -1546,7 +1547,7 @@ function buildK3sInlineScriptCommand(parsed: K3sTargetOptions): string {
|
||||
if (parsed.command.length === 0) throw new Error("ssh k3s script -- requires a command");
|
||||
if (parsed.tty) throw new Error("ssh k3s script does not support --tty; stdin is reserved for the script body");
|
||||
if (parsed.stdin) throw new Error("ssh k3s script -- does not accept --stdin");
|
||||
const command = parsed.command.length === 1 ? ["sh", "-c", parsed.command[0] ?? ""] : parsed.command;
|
||||
const command = parsed.command.length === 1 ? ["sh", "-c", shellScriptWithCompatibility(parsed.command[0] ?? "")] : parsed.command;
|
||||
if (parsed.namespace === null && parsed.resource === null) {
|
||||
if (parsed.container !== null) throw new Error("ssh k3s script without a workload does not accept --container");
|
||||
if (parsed.workspace !== null) throw new Error("ssh k3s script without a workload does not accept --workdir");
|
||||
@@ -1770,6 +1771,14 @@ function k3sScriptShell(value: string, option: string): string {
|
||||
return value;
|
||||
}
|
||||
|
||||
function shellScriptWithCompatibility(command: string): string {
|
||||
return `${sshShellCompatibilityPrelude}\n${command}`;
|
||||
}
|
||||
|
||||
function shellScriptStdinPrefix(): string {
|
||||
return `${sshShellCompatibilityPrelude}\n`;
|
||||
}
|
||||
|
||||
function buildShellCommand(args: string[]): ParsedSshArgs {
|
||||
let shell = "sh";
|
||||
const scriptArgs: string[] = [];
|
||||
@@ -1802,15 +1811,15 @@ function buildShellCommand(args: string[]): ParsedSshArgs {
|
||||
}
|
||||
if (directArgvMode) {
|
||||
if (scriptArgs.length === 0) throw new Error("ssh script -- requires a command");
|
||||
if (scriptArgs.length === 1) return { remoteCommand: shellArgv([shell, "-c", scriptArgs[0] ?? ""]), requiresStdin: false, invocationKind: "helper" };
|
||||
if (scriptArgs.length === 1) return { remoteCommand: shellArgv([shell, "-c", shellScriptWithCompatibility(scriptArgs[0] ?? "")]), requiresStdin: false, invocationKind: "helper" };
|
||||
return { remoteCommand: shellArgv(scriptArgs), requiresStdin: false, invocationKind: "argv" };
|
||||
}
|
||||
return { remoteCommand: shellArgv([shell, "-s", "--", ...scriptArgs]), requiresStdin: true, invocationKind: "helper" };
|
||||
return { remoteCommand: shellArgv([shell, "-s", "--", ...scriptArgs]), requiresStdin: true, invocationKind: "helper", stdinPrefix: shellScriptStdinPrefix() };
|
||||
}
|
||||
|
||||
function buildShellStringCommand(args: string[]): ParsedSshArgs {
|
||||
const parsed = parseShellStringOperationArgs(args, "ssh shell");
|
||||
return { remoteCommand: shellArgv([parsed.shell, "-c", parsed.command]), requiresStdin: false, invocationKind: "helper" };
|
||||
return { remoteCommand: shellArgv([parsed.shell, "-c", shellScriptWithCompatibility(parsed.command)]), requiresStdin: false, invocationKind: "helper" };
|
||||
}
|
||||
|
||||
function podApplyPatchStdinWrapper(): { prefix: string; suffix: string } {
|
||||
|
||||
Reference in New Issue
Block a user