mirror of
https://github.com/syntrex-lab/gomcp.git
synced 2026-05-02 07:42:37 +02:00
Release prep: 54 engines, self-hosted signatures, i18n, dashboard updates
This commit is contained in:
parent
694e32be26
commit
41cbfd6e0a
178 changed files with 36008 additions and 399 deletions
130
cmd/soc-ingest/main.go
Normal file
130
cmd/soc-ingest/main.go
Normal file
|
|
@ -0,0 +1,130 @@
|
|||
// Package main provides the SOC Ingest process (SEC-001 Process Isolation).
|
||||
//
|
||||
// Responsibility: HTTP endpoint, authentication, secret scanner,
|
||||
// rate limiting, dedup, SQLite persistence.
|
||||
// Forwards persisted events to soc-correlate via IPC.
|
||||
//
|
||||
// Usage:
|
||||
//
|
||||
// go run ./cmd/soc-ingest/
|
||||
// SOC_DB_PATH=/data/soc.db SOC_INGEST_PORT=9750 go run ./cmd/soc-ingest/
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"os"
|
||||
"os/signal"
|
||||
"runtime"
|
||||
"runtime/debug"
|
||||
"strconv"
|
||||
"syscall"
|
||||
|
||||
"github.com/syntrex/gomcp/internal/application/soc"
|
||||
"github.com/syntrex/gomcp/internal/infrastructure/audit"
|
||||
"github.com/syntrex/gomcp/internal/infrastructure/ipc"
|
||||
"github.com/syntrex/gomcp/internal/infrastructure/logging"
|
||||
"github.com/syntrex/gomcp/internal/infrastructure/sqlite"
|
||||
sochttp "github.com/syntrex/gomcp/internal/transport/http"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// SEC-003: Panic recovery.
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
buf := make([]byte, 4096)
|
||||
n := runtime.Stack(buf, false)
|
||||
fmt.Fprintf(os.Stderr, "SOC-INGEST FATAL PANIC: %v\n%s\n", r, buf[:n])
|
||||
os.Exit(2)
|
||||
}
|
||||
}()
|
||||
|
||||
logger := logging.New(env("SOC_LOG_FORMAT", "text"), env("SOC_LOG_LEVEL", "info"))
|
||||
slog.SetDefault(logger)
|
||||
|
||||
// SEC-003: Memory safety.
|
||||
if limitStr := os.Getenv("GOMEMLIMIT"); limitStr == "" {
|
||||
debug.SetMemoryLimit(256 * 1024 * 1024) // 256 MiB for ingest
|
||||
}
|
||||
|
||||
port, _ := strconv.Atoi(env("SOC_INGEST_PORT", "9750"))
|
||||
dbPath := env("SOC_DB_PATH", "soc.db")
|
||||
|
||||
logger.Info("starting SOC-INGEST (SEC-001 isolated process)",
|
||||
"port", port, "db", dbPath,
|
||||
"ipc_pipe", "soc-ingest-to-correlate",
|
||||
)
|
||||
|
||||
// Infrastructure.
|
||||
db, err := sqlite.Open(dbPath)
|
||||
if err != nil {
|
||||
logger.Error("database open failed", "error", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
defer db.Close()
|
||||
|
||||
socRepo, err := sqlite.NewSOCRepo(db)
|
||||
if err != nil {
|
||||
logger.Error("SOC repo init failed", "error", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
decisionLogger, err := audit.NewDecisionLogger(env("SOC_AUDIT_DIR", "."))
|
||||
if err != nil {
|
||||
logger.Error("decision logger init failed", "error", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// Service (ingest-only mode).
|
||||
socSvc := soc.NewService(socRepo, decisionLogger)
|
||||
|
||||
// IPC: Connect to downstream soc-correlate.
|
||||
ctx, stop := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM)
|
||||
defer stop()
|
||||
|
||||
correlateConn, err := ipc.DialWithRetry(ctx, "soc-ingest-to-correlate", 30)
|
||||
if err != nil {
|
||||
logger.Warn("soc-correlate not available — running in standalone ingest mode", "error", err)
|
||||
} else {
|
||||
ipcSender := ipc.NewBufferedSender(correlateConn, "soc-ingest-to-correlate")
|
||||
defer ipcSender.Close()
|
||||
|
||||
// Subscribe to event bus and forward events via IPC.
|
||||
eventCh := socSvc.EventBus().Subscribe("ipc-forwarder")
|
||||
go func() {
|
||||
for event := range eventCh {
|
||||
msg, err := ipc.NewSOCMessage(ipc.SOCMsgEvent, event)
|
||||
if err != nil {
|
||||
logger.Error("ipc: marshal event", "error", err)
|
||||
continue
|
||||
}
|
||||
if err := ipcSender.Send(msg); err != nil {
|
||||
logger.Error("ipc: forward to correlate", "error", err)
|
||||
}
|
||||
}
|
||||
}()
|
||||
logger.Info("IPC connected to soc-correlate", "pending_buffer", ipc.BufferSize)
|
||||
}
|
||||
|
||||
// HTTP server (ingest endpoints only).
|
||||
srv := sochttp.New(socSvc, port)
|
||||
|
||||
// JWT auth.
|
||||
if jwtSecret := env("SOC_JWT_SECRET", ""); jwtSecret != "" {
|
||||
srv.SetJWTAuth([]byte(jwtSecret))
|
||||
}
|
||||
|
||||
logger.Info("SOC-INGEST ready", "port", port)
|
||||
if err := srv.Start(ctx); err != nil {
|
||||
logger.Error("server failed", "error", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
func env(key, fallback string) string {
|
||||
if v := os.Getenv(key); v != "" {
|
||||
return v
|
||||
}
|
||||
return fallback
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue