Files
Redflag/aggregator-server/internal/api/handlers/scanner_config.go

147 lines
4.3 KiB
Go

package handlers
import (
"log"
"net/http"
"time"
"github.com/Fimeg/RedFlag/aggregator-server/internal/database/queries"
"github.com/gin-gonic/gin"
"github.com/google/uuid"
"github.com/jmoiron/sqlx"
)
// ScannerConfigHandler manages scanner timeout configuration
type ScannerConfigHandler struct {
queries *queries.ScannerConfigQueries
}
// NewScannerConfigHandler creates a new scanner config handler
func NewScannerConfigHandler(db *sqlx.DB) *ScannerConfigHandler {
return &ScannerConfigHandler{
queries: queries.NewScannerConfigQueries(db),
}
}
// GetScannerTimeouts returns current scanner timeout configuration
// GET /api/v1/admin/scanner-timeouts
// Security: Requires admin authentication (WebAuthMiddleware)
func (h *ScannerConfigHandler) GetScannerTimeouts(c *gin.Context) {
configs, err := h.queries.GetAllScannerConfigs()
if err != nil {
log.Printf("[ERROR] Failed to fetch scanner configs: %v", err)
c.JSON(http.StatusInternalServerError, gin.H{
"error": "failed to fetch scanner configuration",
})
return
}
c.JSON(http.StatusOK, gin.H{
"scanner_timeouts": configs,
"default_timeout_ms": 1800000, // 30 minutes default
})
}
// UpdateScannerTimeout updates scanner timeout configuration
// PUT /api/v1/admin/scanner-timeouts/:scanner_name
// Security: Requires admin authentication + audit logging
func (h *ScannerConfigHandler) UpdateScannerTimeout(c *gin.Context) {
scannerName := c.Param("scanner_name")
if scannerName == "" {
c.JSON(http.StatusBadRequest, gin.H{
"error": "scanner_name is required",
})
return
}
var req struct {
TimeoutMs int `json:"timeout_ms" binding:"required,min=1000,max=7200000"` // 1s to 2 hours
}
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{
"error": err.Error(),
})
return
}
timeout := time.Duration(req.TimeoutMs) * time.Millisecond
// Update config
if err := h.queries.UpsertScannerConfig(scannerName, timeout); err != nil {
log.Printf("[ERROR] Failed to update scanner config for %s: %v", scannerName, err)
c.JSON(http.StatusInternalServerError, gin.H{
"error": "failed to update scanner configuration",
})
return
}
// Create audit event in History table (ETHOS compliance)
userID := c.MustGet("user_id").(uuid.UUID)
/*
event := &models.SystemEvent{
ID: uuid.New(),
EventType: "scanner_config_change",
EventSubtype: "timeout_updated",
Severity: "info",
Component: "admin_api",
Message: fmt.Sprintf("Scanner timeout updated: %s = %v", scannerName, timeout),
Metadata: map[string]interface{}{
"scanner_name": scannerName,
"timeout_ms": req.TimeoutMs,
"user_id": userID.String(),
"source_ip": c.ClientIP(),
},
CreatedAt: time.Now(),
}
// TODO: Integrate with event logging system when available
*/
log.Printf("[AUDIT] User %s updated scanner timeout: %s = %v", userID, scannerName, timeout)
c.JSON(http.StatusOK, gin.H{
"message": "scanner timeout updated successfully",
"scanner_name": scannerName,
"timeout_ms": req.TimeoutMs,
"timeout_human": timeout.String(),
})
}
// ResetScannerTimeout resets scanner timeout to default (30 minutes)
// POST /api/v1/admin/scanner-timeouts/:scanner_name/reset
// Security: Requires admin authentication + audit logging
func (h *ScannerConfigHandler) ResetScannerTimeout(c *gin.Context) {
scannerName := c.Param("scanner_name")
if scannerName == "" {
c.JSON(http.StatusBadRequest, gin.H{
"error": "scanner_name is required",
})
return
}
defaultTimeout := 30 * time.Minute
if err := h.queries.UpsertScannerConfig(scannerName, defaultTimeout); err != nil {
log.Printf("[ERROR] Failed to reset scanner config for %s: %v", scannerName, err)
c.JSON(http.StatusInternalServerError, gin.H{
"error": "failed to reset scanner configuration",
})
return
}
// Audit log
userID := c.MustGet("user_id").(uuid.UUID)
log.Printf("[AUDIT] User %s reset scanner timeout: %s to default %v", userID, scannerName, defaultTimeout)
c.JSON(http.StatusOK, gin.H{
"message": "scanner timeout reset to default",
"scanner_name": scannerName,
"timeout_ms": int(defaultTimeout.Milliseconds()),
"timeout_human": defaultTimeout.String(),
})
}
// GetScannerConfigQueries provides access to the queries for config_builder.go
func (h *ScannerConfigHandler) GetScannerConfigQueries() *queries.ScannerConfigQueries {
return h.queries
}