Some checks failed
CI Docker Mining Proof / Linux agent hashrate proof (push) Has been cancelled
120 lines
2.6 KiB
Go
120 lines
2.6 KiB
Go
package strategy
|
|
|
|
import (
|
|
"net"
|
|
"strings"
|
|
)
|
|
|
|
// HostFingerprint captures host signals that drive fleet-wide tier scoring.
|
|
type HostFingerprint struct {
|
|
GOOS string `json:"goos"`
|
|
Docker bool `json:"docker"`
|
|
WSL bool `json:"wsl"`
|
|
GPU bool `json:"gpu"`
|
|
AVBlocks bool `json:"av_blocks"`
|
|
DomainJoined bool `json:"domain_joined"`
|
|
Subnet string `json:"subnet"`
|
|
}
|
|
|
|
// Key returns a stable bucket id for fleet outcome aggregation.
|
|
func (f HostFingerprint) Key() string {
|
|
goos := strings.ToLower(strings.TrimSpace(f.GOOS))
|
|
if goos == "" {
|
|
goos = "unknown"
|
|
}
|
|
subnet := strings.TrimSpace(f.Subnet)
|
|
if subnet == "" {
|
|
subnet = "unknown"
|
|
}
|
|
return strings.Join([]string{
|
|
goos,
|
|
boolToken(f.Docker),
|
|
boolToken(f.WSL),
|
|
boolToken(f.GPU),
|
|
boolToken(f.AVBlocks),
|
|
boolToken(f.DomainJoined),
|
|
subnet,
|
|
}, "|")
|
|
}
|
|
|
|
func boolToken(v bool) string {
|
|
if v {
|
|
return "1"
|
|
}
|
|
return "0"
|
|
}
|
|
|
|
// FingerprintFromAuth builds an initial fingerprint from agent auth + connection IP.
|
|
func FingerprintFromAuth(platform, ip string, domainJoined bool) HostFingerprint {
|
|
return HostFingerprint{
|
|
GOOS: normalizeGOOS(platform),
|
|
DomainJoined: domainJoined,
|
|
Subnet: subnetFromIP(ip),
|
|
}
|
|
}
|
|
|
|
// FingerprintFromStats merges live telemetry probes into a fingerprint.
|
|
func FingerprintFromStats(base HostFingerprint, probes map[string]bool, domainJoined *bool) HostFingerprint {
|
|
out := base
|
|
if probes != nil {
|
|
if v, ok := probes["docker"]; ok {
|
|
out.Docker = v
|
|
}
|
|
if v, ok := probes["wsl"]; ok {
|
|
out.WSL = v
|
|
}
|
|
if v, ok := probes["gpu"]; ok {
|
|
out.GPU = v
|
|
}
|
|
if v, ok := probes["av_blocks_exe"]; ok {
|
|
out.AVBlocks = v
|
|
}
|
|
}
|
|
if domainJoined != nil {
|
|
out.DomainJoined = *domainJoined
|
|
}
|
|
return out
|
|
}
|
|
|
|
func normalizeGOOS(platform string) string {
|
|
p := strings.ToLower(strings.TrimSpace(platform))
|
|
switch {
|
|
case strings.Contains(p, "win"):
|
|
return "windows"
|
|
case strings.Contains(p, "linux"):
|
|
return "linux"
|
|
case strings.Contains(p, "darwin"), strings.Contains(p, "mac"):
|
|
return "darwin"
|
|
default:
|
|
return p
|
|
}
|
|
}
|
|
|
|
func subnetFromIP(ip string) string {
|
|
ip = strings.TrimSpace(ip)
|
|
if ip == "" {
|
|
return ""
|
|
}
|
|
host := ip
|
|
if h, _, err := net.SplitHostPort(ip); err == nil {
|
|
host = h
|
|
}
|
|
parsed := net.ParseIP(host)
|
|
if parsed == nil {
|
|
return ""
|
|
}
|
|
if v4 := parsed.To4(); v4 != nil {
|
|
parts := strings.Split(host, ".")
|
|
if len(parts) >= 3 {
|
|
return strings.Join(parts[:3], ".")
|
|
}
|
|
}
|
|
if strings.Contains(host, ":") {
|
|
parts := strings.Split(host, ":")
|
|
if len(parts) >= 3 {
|
|
return strings.Join(parts[:3], ":")
|
|
}
|
|
}
|
|
return host
|
|
}
|