Exercise backend bootstrap portability and full terminal restoration

Cover setup, Proxmox and container callers with a real PTY, isolated standalone and BusyBox tool selection, distinct fail-closed modes, private root/sudo history and one bounded command body. These controls expose the unchanged backend reader before its repair.

Change-source: pulse-maintainer
This commit is contained in:
pulse-triage[bot]
2026-10-13 17:14:10 +01:00
parent 9dc664aea3
commit 44ef70ed3e
2 changed files with 283 additions and 4 deletions
+11 -4
View File
@@ -17,6 +17,11 @@ import errno, fcntl, json, os, pty, select, signal, subprocess, sys, termios, ti
p = json.load(sys.stdin)
master, slave = pty.openpty()
tty_watch = os.dup(slave)
if p.get("alternate_tty"):
alternate = termios.tcgetattr(tty_watch)
alternate[0] &= ~termios.IXON
alternate[3] &= ~termios.ECHOK
termios.tcsetattr(tty_watch, termios.TCSANOW, alternate)
initial_tty = termios.tcgetattr(tty_watch)
def session():
os.setsid()
@@ -76,7 +81,10 @@ while time.monotonic() < deadline:
# the real bootstrap disables it before printing the input prompt.
silent = not (termios.tcgetattr(tty_watch)[3] & termios.ECHO)
if output.endswith(b"(paste at this prompt, not in the command): ") and command_ready and silent and not sent:
os.write(master, (p["input"] + "\n").encode())
if p.get("signal_on_prompt"):
os.killpg(child.pid, getattr(signal, "SIG" + p["signal_on_prompt"]))
else:
os.write(master, (p["input"] + "\n").encode())
sent = True
if child.poll() is not None and not ready: break
else:
@@ -84,9 +92,8 @@ else:
output += b"\nPTY fixture deadline expired\n"
code = child.wait()
final_tty = termios.tcgetattr(tty_watch)
mode_mask = termios.ECHO | termios.ICANON
if (initial_tty[3] & mode_mask) != (final_tty[3] & mode_mask):
output += b"\nBootstrap did not restore terminal echo/canonical mode\n"
if initial_tty != final_tty:
output += b"\nBootstrap did not restore complete terminal settings\n"
code = 1
os.close(tty_watch)
os.close(master)
@@ -0,0 +1,272 @@
package configapi
import (
"encoding/json"
"fmt"
"os"
"os/exec"
"path/filepath"
"strings"
"testing"
)
type portableBootstrapCaller struct {
name string
build func(string) string
}
func portableBootstrapCallers() []portableBootstrapCaller {
return []portableBootstrapCaller{
{"proxmox", func(token string) string {
return BuildProxmoxAgentInstallCommand(AgentInstallCommandOptions{BaseURL: "https://pulse.example", Token: token, InstallType: "pbs", IncludeInstallType: true})
}},
{"setup", func(token string) string {
return BuildSetupScriptCommand("https://pulse.example/api/setup-script?type=pbs", token)
}},
{"container", func(token string) string {
return BuildContainerRuntimeAgentInstallCommand("https://pulse.example", token, false)
}},
}
}
// PATH contains only the prerequisite tools and our closed download/privilege
// fixtures. The real controlling PTY is never a customer or appliance terminal.
// Explicit proof inputs can supply the exact static BusyBox used on CI hosts.
func portableBootstrapFixture(t *testing.T, mode string) (string, []string) {
t.Helper()
root, env := bootstrapFixture(t, recordingInstaller)
bin := filepath.Join(root, "bin")
for _, name := range []string{"bash", "cp", "rm", "rmdir", "cat", "stat", "dirname", "touch"} {
path, err := exec.LookPath(name)
if err != nil {
t.Fatal(err)
}
if err := os.Symlink(path, filepath.Join(bin, name)); err != nil {
t.Fatal(err)
}
}
if mode == "standalone" || mode == "prefer-standalone" {
stty, err := exec.LookPath("stty")
if err != nil {
t.Fatal(err)
}
writeExecutable(t, filepath.Join(bin, "stty"), `#!/bin/sh
printf '%s\n' "$*" >> "$FAKE_ROOT/tty-calls"
case "${FAKE_TTY_FAILURE:-}:$1" in
empty:-g) exit 0 ;;
snapshot:-g) exit 1 ;;
echo:-echo) exit 1 ;;
esac
if [ "${FAKE_TTY_FAILURE:-}" = restore ] && [ "$1" != -g ] && [ "$1" != -echo ] && [ ! -e "$FAKE_ROOT/restore-failed" ]; then
touch "$FAKE_ROOT/restore-failed"
exit 1
fi
exec `+posixShellQuote(stty)+` "$@"
`)
}
if mode == "busybox" {
path := os.Getenv("PULSE_TEST_BUSYBOX")
if path == "" {
var err error
path, err = exec.LookPath("busybox")
if err != nil {
t.Skip("real BusyBox input unavailable; modeled tool and standalone controls still run")
}
}
body, err := os.ReadFile(path)
if err != nil {
t.Fatal(err)
}
if err := os.Mkdir(filepath.Join(root, "native"), 0700); err != nil {
t.Fatal(err)
}
if err := os.WriteFile(filepath.Join(root, "native", "busybox"), body, 0700); err != nil {
t.Fatal(err)
}
writeExecutable(t, filepath.Join(bin, "busybox"), `#!/bin/sh
printf '%s\n' "$*" >> "$FAKE_ROOT/tty-calls"
exec "$FAKE_ROOT/native/busybox" "$@"
`)
} else if mode == "unsupported-busybox" || mode == "prefer-standalone" {
writeExecutable(t, filepath.Join(bin, "busybox"), `#!/bin/sh
printf '%s\n' "$*" >> "$FAKE_ROOT/busybox-calls"
exit 97
`)
}
return root, append(env, "PATH="+bin)
}
func runPortableBootstrap(t *testing.T, command, input string, env []string, history, signalName string) ([]byte, error) {
t.Helper()
payload, err := json.Marshal(map[string]any{
"command": command, "input": input, "history": history,
"signal_on_prompt": signalName, "alternate_tty": true,
})
if err != nil {
t.Fatal(err)
}
python, err := exec.LookPath("python3")
if err != nil {
t.Fatal(err)
}
cmd := exec.Command(python, "-c", bootstrapPTYRunner)
cmd.Stdin = strings.NewReader(string(payload))
cmd.Env = append(os.Environ(), env...)
return cmd.CombinedOutput()
}
func assertPortableBootstrapPrivate(t *testing.T, root, token string, out []byte) {
t.Helper()
for _, name := range []string{"argv", "shell-history", "secret-env"} {
body, err := os.ReadFile(filepath.Join(root, name))
if err != nil && !os.IsNotExist(err) {
t.Fatal(err)
}
if token != "" && strings.Contains(string(body), token) {
t.Fatalf("private input reached %s", name)
}
if name == "secret-env" && err == nil && string(body) != ":" {
t.Fatal("installer received a credential through the environment")
}
}
if token != "" && strings.Contains(string(out), token) {
t.Fatal("private input was echoed")
}
if strings.Contains(string(out), "Bootstrap did not restore") || strings.Contains(string(out), "PTY fixture deadline expired") {
t.Fatal("complete terminal restoration or bounded execution failed")
}
assertContainerBootstrapCleanup(t, root)
}
func TestPrivateBootstrapPortableToolFailures(t *testing.T) {
for _, caller := range portableBootstrapCallers() {
for _, tc := range []struct {
name, mode, fault, message string
tty bool
}{
{"no-terminal", "absent", "", "A terminal is required to enter the token.", false},
{"no-tool", "absent", "", "Silent token input requires stty or BusyBox stty.", true},
{"unsupported-applet", "unsupported-busybox", "", "Cannot read terminal settings with stty or BusyBox stty.", true},
{"empty-state", "standalone", "empty", "Cannot read terminal settings with stty or BusyBox stty.", true},
{"failed-state", "standalone", "snapshot", "Cannot read terminal settings with stty or BusyBox stty.", true},
{"failed-echo", "standalone", "echo", "Cannot disable terminal echo.", true},
{"failed-restore", "standalone", "restore", "Cannot restore terminal settings.", true},
} {
t.Run(caller.name+"/"+tc.name, func(t *testing.T) {
root, env := portableBootstrapFixture(t, tc.mode)
env = append(env, "FAKE_TTY_FAILURE="+tc.fault)
command := caller.build("issued-but-not-in-command")
var out []byte
var err error
if tc.tty {
out, err = runPortableBootstrap(t, command, "synthetic-private-token", env, "", "")
} else {
out, err = runBootstrap(t, command, "", env, false)
}
if err == nil || !strings.Contains(string(out), tc.message) {
t.Fatalf("expected distinct fail-closed %s diagnostic; exit=%v, matched=%t", tc.name, err, strings.Contains(string(out), tc.message))
}
if _, err := os.Stat(filepath.Join(root, "captured-token")); !os.IsNotExist(err) {
t.Fatal("installation preceded safe terminal restoration")
}
if tc.name != "failed-restore" && strings.Contains(string(out), "(paste at this prompt, not in the command): ") {
t.Fatal("credential requested before silent input was available")
}
if tc.name == "failed-restore" {
calls, err := os.ReadFile(filepath.Join(root, "tty-calls"))
lines := strings.Split(strings.TrimSpace(string(calls)), "\n")
if err != nil || len(lines) != 4 || lines[0] != "-g" || lines[1] != "-echo" || lines[2] != lines[3] {
t.Fatal("cleanup did not retry the same full state with the selected tool")
}
}
assertPortableBootstrapPrivate(t, root, "synthetic-private-token", out)
})
}
}
}
func TestPrivateBootstrapRealBusyBoxInput(t *testing.T) {
for _, caller := range portableBootstrapCallers() {
for _, tc := range []struct {
name, input, signalName string
failure bool
}{
{"ordinary", strings.Repeat("p", 32), "", false},
{"maximum", strings.Repeat("q", 4096), "", false},
{"overflow", strings.Repeat("r", 10000) + "-DISCARDED-CREDENTIAL", "", true},
{"empty", "", "", true},
{"interrupt", "\x03", "", true},
{"hangup", "", "HUP", true},
{"terminate", "", "TERM", true},
} {
t.Run(caller.name+"/"+tc.name, func(t *testing.T) {
root, env := portableBootstrapFixture(t, "busybox")
command := caller.build("issued-separately")
out, err := runPortableBootstrap(t, command, tc.input, env, "", tc.signalName)
if (err != nil) != tc.failure {
t.Fatalf("BusyBox bootstrap result=%v, expected failure=%t", err, tc.failure)
}
captured, captureErr := os.ReadFile(filepath.Join(root, "captured-token"))
if tc.failure {
if !os.IsNotExist(captureErr) {
t.Fatal("invalid or interrupted entry reached installation")
}
} else if captureErr != nil || string(captured) != tc.input {
t.Fatal("BusyBox reader lost accepted input")
}
calls, err := os.ReadFile(filepath.Join(root, "tty-calls"))
lines := strings.Split(strings.TrimSpace(string(calls)), "\n")
if err != nil || len(lines) != 3 || lines[0] != "stty -g" || lines[1] != "stty -echo" || !strings.HasPrefix(lines[2], "stty ") {
t.Fatal("snapshot, silent mode and full restoration did not use the selected real BusyBox applet")
}
assertPortableBootstrapPrivate(t, root, tc.input, out)
})
}
}
}
func TestPrivateBootstrapStandalonePreferredAndBusyBoxHistory(t *testing.T) {
for _, caller := range portableBootstrapCallers() {
for _, mode := range []string{"prefer-standalone", "busybox"} {
for _, uid := range []string{"0", "1000"} {
t.Run(fmt.Sprintf("%s/%s/uid-%s", caller.name, mode, uid), func(t *testing.T) {
root, env := portableBootstrapFixture(t, mode)
env = append(env, "FAKE_ID_UID="+uid)
token := "synthetic-history-token-0123456789"
command := caller.build(token)
out, err := runPortableBootstrap(t, command, token, env, filepath.Join(root, "shell-history"), "")
if err != nil {
t.Fatalf("interactive portable bootstrap failed: %v", err)
}
history, err := os.ReadFile(filepath.Join(root, "shell-history"))
if err != nil || !strings.Contains(string(history), command) || !strings.HasSuffix(string(history), "exit\n") {
t.Fatal("caller did not record the complete command and regain the terminal")
}
captured, err := os.ReadFile(filepath.Join(root, "captured-token"))
if err != nil || string(captured) != token {
t.Fatal("interactive private handoff lost input")
}
if _, err := os.Stat(filepath.Join(root, "busybox-calls")); !os.IsNotExist(err) {
t.Fatal("failed standalone tool selection fell back to another utility")
}
assertPortableBootstrapPrivate(t, root, token, out)
})
}
}
}
}
func TestPrivateBootstrapSinglePrivilegedBody(t *testing.T) {
for _, caller := range portableBootstrapCallers() {
t.Run(caller.name, func(t *testing.T) {
command := caller.build("private-not-in-command")
if strings.Count(command, "bash -c ") != 1 || !strings.Contains(command, `then set --; else set -- sudo; fi;`) || !strings.Contains(command, `"$@" bash -c `) {
t.Fatal("private reader is duplicated or root/sudo prefix escaped its subshell")
}
if len(command) >= 4096 || strings.ContainsAny(command, "\r\n") {
t.Fatalf("ordinary single-line command does not fit the common terminal limit: %d bytes", len(command))
}
t.Logf("ordinary %s command: %d bytes", caller.name, len(command))
})
}
}