From 6e2841cc65bf8e15c9a90bebbe51aff68c89a092 Mon Sep 17 00:00:00 2001 From: "pulse-triage[bot]" <249995291+pulse-triage[bot]@users.noreply.github.com> Date: Tue, 22 Sep 2026 18:42:51 +0100 Subject: [PATCH] test(agent): exercise offline FreeBSD preflight through local downloads Cover real installer and local HTTP handlers with an explicit uname shim. Distinguish bundled artifacts from missing binaries or signature sidecars without claiming native pfSense installation acceptance. Change-source: pulse-maintainer --- .../unified_agent_offline_preflight_test.go | 151 ++++++++++++++++++ 1 file changed, 151 insertions(+) create mode 100644 internal/api/unified_agent_offline_preflight_test.go diff --git a/internal/api/unified_agent_offline_preflight_test.go b/internal/api/unified_agent_offline_preflight_test.go new file mode 100644 index 000000000..85e655f2c --- /dev/null +++ b/internal/api/unified_agent_offline_preflight_test.go @@ -0,0 +1,151 @@ +package api + +import ( + "bytes" + "context" + "crypto/sha256" + "errors" + "fmt" + "io" + "net/http" + "net/http/httptest" + "os" + "os/exec" + "path/filepath" + "strings" + "sync/atomic" + "testing" + "time" +) + +// This is an offline HTTP/preflight contract, NOT native pfSense acceptance. +// Only uname is simulated. Bash, curl, the served installer and download +// handler are real; the agent bytes and signature sidecars are fixtures and +// are never executed or claimed to be cryptographically qualified artifacts. +func TestFreeBSDOfflineAgentPreflight(t *testing.T) { + for _, tc := range []struct { + name string + binary, sidecars bool + wantExit int + }{ + {"bundled", true, true, 0}, + {"missing_binary", false, false, 11}, + {"missing_sidecars", true, false, 11}, + } { + t.Run(tc.name, func(t *testing.T) { + dir := t.TempDir() + binDir := setupTempPulseBin(t) + payload := validTestUnifiedAgentBinary("offline-freebsd-fixture") + binaryPath := filepath.Join(binDir, "pulse-agent-freebsd-amd64") + write := func(path string, data []byte) { + t.Helper() + if err := os.WriteFile(path, data, 0700); err != nil { + t.Fatal(err) + } + } + if tc.binary { + write(binaryPath, payload) + } + if tc.sidecars { + write(binaryPath+".sig", []byte("synthetic-signature")) + write(binaryPath+".sshsig", []byte("synthetic-ssh-signature")) + } + var externalAttempts, healthRequests, downloadRequests atomic.Int32 + router := &Router{ + projectRoot: dir, serverVersion: "v6.4.5-rc.1", + checksumCache: make(map[string]checksumCacheEntry), + installScriptClient: &http.Client{Transport: roundTripFunc(func(req *http.Request) (*http.Response, error) { + externalAttempts.Add(1) + if req.URL.Host != "github.com" || !strings.HasSuffix(req.URL.Path, "/pulse-agent-freebsd-amd64") { + t.Errorf("unexpected fallback destination: %s", req.URL) + } + return nil, errors.New("fixture: server has no external connectivity") + })}, + } + script, err := filepath.Abs(filepath.Join("..", "..", "scripts", "install.sh")) + if err != nil { + t.Fatal(err) + } + mux := http.NewServeMux() + mux.HandleFunc("/install.sh", func(w http.ResponseWriter, r *http.Request) { + handleDownloadInstallScriptCommon(w, r, "dev", filepath.Join(dir, "absent.sh"), script, "install.sh", "text/x-shellscript") + }) + mux.HandleFunc("/api/health", func(w http.ResponseWriter, r *http.Request) { healthRequests.Add(1); w.WriteHeader(http.StatusOK) }) + mux.HandleFunc("/download/pulse-agent", func(w http.ResponseWriter, r *http.Request) { + downloadRequests.Add(1) + if r.URL.Query().Get("arch") != "freebsd-amd64" { + t.Errorf("wrong arch: %s", r.URL) + } + router.handleDownloadUnifiedAgent(w, r) + }) + server := httptest.NewServer(mux) + defer server.Close() + + downloadedScript := filepath.Join(dir, "install.sh") + ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) + defer cancel() + fetch := exec.CommandContext(ctx, "curl", "--noproxy", "*", "-fsS", server.URL+"/install.sh", "-o", downloadedScript) + if out, err := fetch.CombinedOutput(); err != nil { + t.Fatalf("fetch installer: %v\n%s", err, out) + } + original, err := os.ReadFile(script) + if err != nil { + t.Fatal(err) + } + downloaded, err := os.ReadFile(downloadedScript) + if err != nil { + t.Fatal(err) + } + if !bytes.Equal(original, downloaded) { + t.Fatal("served installer differs from source") + } + shimDir := filepath.Join(dir, "shim") + if err := os.Mkdir(shimDir, 0700); err != nil { + t.Fatal(err) + } + write(filepath.Join(shimDir, "uname"), []byte("#!/bin/sh\ncase \"$1\" in -s) echo FreeBSD;; -m) echo amd64;; *) exec /usr/bin/uname \"$@\";; esac\n")) + cmd := exec.CommandContext(ctx, "bash", downloadedScript, "--url", server.URL, "--preflight-only", "--output", "json", "--non-interactive") + cmd.Env = append(os.Environ(), "PATH="+shimDir+":"+os.Getenv("PATH"), "NO_PROXY=*", "no_proxy=*") + out, runErr := cmd.CombinedOutput() + exitCode := 0 + if runErr != nil { + var ee *exec.ExitError + if !errors.As(runErr, &ee) { + t.Fatalf("preflight: %v\n%s", runErr, out) + } + exitCode = ee.ExitCode() + } + t.Logf("preflight exit=%d; external attempts=%d\n%s", exitCode, externalAttempts.Load(), out) + if exitCode != tc.wantExit { + t.Fatalf("exit=%d, want %d", exitCode, tc.wantExit) + } + if healthRequests.Load() != 1 || downloadRequests.Load() != 1 { + t.Fatalf("health/download requests = %d/%d", healthRequests.Load(), downloadRequests.Load()) + } + if tc.wantExit != 0 { + if externalAttempts.Load() != 1 || !strings.Contains(string(out), `"code":"agent_download_unavailable"`) { + t.Fatal("missing artifact must fail visibly at preflight") + } + return + } + if externalAttempts.Load() != 0 || !strings.Contains(string(out), `"code":"agent_download_available"`) { + t.Fatal("bundled artifact must preflight without external fetch") + } + response, err := server.Client().Get(server.URL + "/download/pulse-agent?arch=freebsd-amd64") + if err != nil { + t.Fatal(err) + } + defer response.Body.Close() + data, err := io.ReadAll(response.Body) + if err != nil { + t.Fatal(err) + } + if response.StatusCode != http.StatusOK || !bytes.Equal(data, payload) || response.Header.Get(checksumHeaderName) != fmt.Sprintf("%x", sha256.Sum256(payload)) { + t.Fatal("local payload/checksum mismatch") + } + if externalAttempts.Load() != 0 { + t.Fatal("local download attempted external access") + } + }) + } +}