Files
neural-hunt/cmd/client/main.go
jbergner 005fd6ca51
Some checks failed
release-tag / release-image (push) Failing after 1m18s
RC-1
2026-08-10 05:48:55 +02:00

90 lines
2.8 KiB
Go

package main
import (
"context"
"flag"
"fmt"
"log"
"os"
"os/signal"
"strings"
"syscall"
)
func main() {
base := flag.String("url", envOr("NEURALHUNT_URL", "http://127.0.0.1:8080"), "Neural Hunt server URL")
identityPath := flag.String("identity", envOr("NEURALHUNT_IDENTITY", defaultIdentityPath()), "persistent terminal identity file")
taskSelector := flag.String("task", "", "initial task: number, ID prefix or display name")
maxNodes := flag.Int("max-nodes", 500, "maximum target-field working set")
nonInteractive := flag.Bool("non-interactive", false, "run unattended without command prompt")
quiet := flag.Bool("quiet", false, "suppress connection/status chatter")
importPath := flag.String("import", "", "import browser/terminal identity JSON before login")
exportPath := flag.String("export", "", "export current identity in browser-compatible encrypted format and exit")
passphrase := flag.String("passphrase", os.Getenv("NEURALHUNT_IDENTITY_PASSPHRASE"), "identity import/export passphrase (prefer environment variable)")
flag.Parse()
if strings.TrimSpace(*importPath) != "" {
id, err := readIdentityImport(*importPath, *passphrase)
if err != nil {
log.Fatal("identity import: ", err)
}
if err := saveIdentity(*identityPath, id); err != nil {
log.Fatal("save imported identity: ", err)
}
fmt.Println("Identity importiert nach", *identityPath)
}
id, key, created, err := loadOrCreateIdentity(*identityPath)
if err != nil {
log.Fatal(err)
}
if *exportPath != "" {
if err := exportBrowserIdentity(*exportPath, *passphrase, id); err != nil {
log.Fatal("identity export: ", err)
}
fmt.Println("Browser-kompatibler verschlüsselter Export:", *exportPath)
return
}
ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM)
defer stop()
api := newAPI(*base, id, key)
if err := api.login(ctx); err != nil {
log.Fatal(err)
}
if created {
fmt.Println("Neue Terminal-Identität erzeugt:", *identityPath)
}
fmt.Println("NEURAL HUNT SHELL")
fmt.Println("Identity:", api.cid)
fmt.Println("Server :", strings.TrimRight(*base, "/"))
fmt.Println("Hinweis : Dieselbe Identity darf nicht gleichzeitig im Browser verbunden sein.")
a := newApp(api, *identityPath, *passphrase, *maxNodes, *quiet, *nonInteractive)
initial, err := selectInitialTask(ctx, a, *taskSelector, !*nonInteractive)
if err != nil {
log.Fatal(err)
}
if err := a.startTask(ctx, initial); err != nil {
log.Fatal(err)
}
go a.watcher(ctx)
if *nonInteractive {
<-ctx.Done()
a.stopSession()
return
}
if err := a.commandLoop(ctx, os.Stdin); err != nil && ctx.Err() == nil {
log.Println(err)
}
a.stopSession()
}
func envOr(name, fallback string) string {
if v := strings.TrimSpace(os.Getenv(name)); v != "" {
return v
}
return fallback
}