| package main |
|
|
| import ( |
| "io" |
| "os" |
| "path/filepath" |
| "strings" |
| "testing" |
|
|
| "github.com/pinchtab/pinchtab/internal/config" |
| ) |
|
|
| func TestHandleSecurityCommandDefaultConfigSkipsEmptySections(t *testing.T) { |
| cfg := testRuntimeConfig() |
|
|
| output := captureStdout(t, func() { |
| handleSecurityCommand(cfg) |
| }) |
|
|
| required := []string{ |
| "Security", |
| "All recommended security defaults are active.", |
| } |
| for _, needle := range required { |
| if !strings.Contains(output, needle) { |
| t.Fatalf("expected output to contain %q\n%s", needle, output) |
| } |
| } |
|
|
| unwanted := []string{ |
| "Security posture", |
| "Warnings", |
| "Recommended security defaults", |
| "Recommended defaults", |
| "Restore recommended security defaults in config?", |
| "Interactive restore skipped because stdin/stdout is not a terminal.", |
| } |
| for _, needle := range unwanted { |
| if strings.Contains(output, needle) { |
| t.Fatalf("expected output to skip %q\n%s", needle, output) |
| } |
| } |
| } |
|
|
| func captureStdout(t *testing.T, fn func()) string { |
| t.Helper() |
|
|
| orig := os.Stdout |
| r, w, err := os.Pipe() |
| if err != nil { |
| t.Fatalf("os.Pipe() error = %v", err) |
| } |
| os.Stdout = w |
| defer func() { |
| os.Stdout = orig |
| }() |
|
|
| fn() |
|
|
| if err := w.Close(); err != nil { |
| t.Fatalf("close writer error = %v", err) |
| } |
| data, err := io.ReadAll(r) |
| if err != nil { |
| t.Fatalf("ReadAll() error = %v", err) |
| } |
| if err := r.Close(); err != nil { |
| t.Fatalf("close reader error = %v", err) |
| } |
| return string(data) |
| } |
|
|
| func TestApplyGuardsDownPreset(t *testing.T) { |
| configPath := filepath.Join(t.TempDir(), "pinchtab", "config.json") |
| t.Setenv("PINCHTAB_CONFIG", configPath) |
|
|
| fc := config.DefaultFileConfig() |
| fc.Server.Token = "guarded-token" |
| if err := os.MkdirAll(filepath.Dir(configPath), 0o755); err != nil { |
| t.Fatalf("MkdirAll() error = %v", err) |
| } |
| if err := config.SaveFileConfig(&fc, configPath); err != nil { |
| t.Fatalf("SaveFileConfig() error = %v", err) |
| } |
|
|
| cfg, gotPath, changed, err := applyGuardsDownPreset() |
| if err != nil { |
| t.Fatalf("applyGuardsDownPreset() error = %v", err) |
| } |
| if !changed { |
| t.Fatal("expected guards down preset to change config") |
| } |
| if gotPath != configPath { |
| t.Fatalf("config path = %q, want %q", gotPath, configPath) |
| } |
|
|
| if cfg.Bind != "127.0.0.1" { |
| t.Fatalf("Bind = %q, want 127.0.0.1", cfg.Bind) |
| } |
| if cfg.Token != "guarded-token" { |
| t.Fatalf("Token = %q, want existing token to remain", cfg.Token) |
| } |
| if !cfg.AllowEvaluate || !cfg.AllowMacro || !cfg.AllowScreencast || !cfg.AllowDownload || !cfg.AllowUpload { |
| t.Fatalf("expected sensitive endpoints enabled, got %+v", cfg) |
| } |
| if !cfg.AttachEnabled { |
| t.Fatal("expected attach endpoint enabled") |
| } |
| if got := strings.Join(cfg.AttachAllowHosts, ","); got != "127.0.0.1,localhost,::1" { |
| t.Fatalf("AttachAllowHosts = %q", got) |
| } |
| if got := strings.Join(cfg.AttachAllowSchemes, ","); got != "ws,wss" { |
| t.Fatalf("AttachAllowSchemes = %q", got) |
| } |
| if cfg.IDPI.Enabled || cfg.IDPI.StrictMode || cfg.IDPI.ScanContent || cfg.IDPI.WrapContent { |
| t.Fatalf("expected IDPI protections disabled, got %+v", cfg.IDPI) |
| } |
| } |
|
|
| func testRuntimeConfig() *config.RuntimeConfig { |
| return &config.RuntimeConfig{ |
| Bind: "127.0.0.1", |
| Token: "abcd1234efgh5678", |
| AllowEvaluate: false, |
| AllowMacro: false, |
| AllowScreencast: false, |
| AllowDownload: false, |
| AllowUpload: false, |
| AttachEnabled: false, |
| AttachAllowHosts: []string{"127.0.0.1", "localhost", "::1"}, |
| AttachAllowSchemes: []string{"ws", "wss"}, |
| IDPI: config.IDPIConfig{ |
| Enabled: true, |
| AllowedDomains: []string{"127.0.0.1", "localhost", "::1"}, |
| StrictMode: true, |
| ScanContent: true, |
| WrapContent: true, |
| }, |
| } |
| } |
|
|