cleanup: remove 2,369 lines of dead code

Removed backup files and unused legacy scanner function.
All code verified as unreferenced.
This commit is contained in:
Fimeg
2025-11-10 21:20:42 -05:00
parent 1f2b1b7179
commit c95cc7d91f
32 changed files with 5899 additions and 567 deletions

View File

@@ -0,0 +1,186 @@
package handlers
import (
"net/http"
"os"
"path/filepath"
"github.com/Fimeg/RedFlag/aggregator-server/internal/services"
"github.com/gin-gonic/gin"
)
// BuildAgent handles the agent build endpoint
func BuildAgent(c *gin.Context) {
var req services.AgentSetupRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
// Create config builder
configBuilder := services.NewConfigBuilder(req.ServerURL)
// Build agent configuration
config, err := configBuilder.BuildAgentConfig(req)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
// Create agent builder
agentBuilder := services.NewAgentBuilder()
// Generate build artifacts
buildResult, err := agentBuilder.BuildAgentWithConfig(config)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
// Create response with native binary instructions
response := gin.H{
"agent_id": config.AgentID,
"config_file": buildResult.ConfigFile,
"platform": buildResult.Platform,
"config_version": config.ConfigVersion,
"agent_version": config.AgentVersion,
"build_time": buildResult.BuildTime,
"next_steps": []string{
"1. Download native binary from server",
"2. Place binary in /usr/local/bin/redflag-agent",
"3. Set permissions: chmod 755 /usr/local/bin/redflag-agent",
"4. Create config directory: mkdir -p /etc/redflag",
"5. Save config to /etc/redflag/config.json",
"6. Set config permissions: chmod 600 /etc/redflag/config.json",
"7. Start service: systemctl enable --now redflag-agent",
},
"configuration": config.PublicConfig,
}
c.JSON(http.StatusOK, response)
}
// GetBuildInstructions returns build instructions for manual setup
func GetBuildInstructions(c *gin.Context) {
agentID := c.Param("agentID")
if agentID == "" {
c.JSON(http.StatusBadRequest, gin.H{"error": "agent ID is required"})
return
}
instructions := gin.H{
"title": "RedFlag Agent Build Instructions",
"agent_id": agentID,
"steps": []gin.H{
{
"step": 1,
"title": "Prepare Build Environment",
"commands": []string{
"mkdir -p redflag-build",
"cd redflag-build",
},
},
{
"step": 2,
"title": "Copy Agent Source Code",
"commands": []string{
"cp -r ../aggregator-agent/* .",
"ls -la",
},
},
{
"step": 3,
"title": "Build Docker Image",
"commands": []string{
"docker build -t redflag-agent:" + agentID[:8] + " .",
},
},
{
"step": 4,
"title": "Create Docker Network",
"commands": []string{
"docker network create redflag 2>/dev/null || true",
},
},
{
"step": 5,
"title": "Deploy Agent",
"commands": []string{
"docker compose up -d",
},
},
{
"step": 6,
"title": "Verify Deployment",
"commands": []string{
"docker compose logs -f",
"docker ps",
},
},
},
"troubleshooting": []gin.H{
{
"issue": "Build fails with 'go mod download' errors",
"solution": "Ensure go.mod and go.sum are copied correctly and internet connectivity is available",
},
{
"issue": "Container fails to start",
"solution": "Check docker-compose.yml and ensure Docker secrets are created with 'echo \"secret-value\" | docker secret create secret-name -'",
},
{
"issue": "Agent cannot connect to server",
"solution": "Verify server URL is accessible from container and firewall rules allow traffic",
},
},
}
c.JSON(http.StatusOK, instructions)
}
// DownloadBuildArtifacts provides download links for generated files
func DownloadBuildArtifacts(c *gin.Context) {
agentID := c.Param("agentID")
fileType := c.Param("fileType")
buildDir := c.Query("buildDir")
// Validate agent ID parameter
if agentID == "" {
c.JSON(http.StatusBadRequest, gin.H{"error": "agent ID is required"})
return
}
if buildDir == "" {
c.JSON(http.StatusBadRequest, gin.H{"error": "build directory is required"})
return
}
// Security check: ensure the buildDir is within expected path
absBuildDir, err := filepath.Abs(buildDir)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid build directory"})
return
}
// Construct file path based on type
var filePath string
switch fileType {
case "compose":
filePath = filepath.Join(absBuildDir, "docker-compose.yml")
case "dockerfile":
filePath = filepath.Join(absBuildDir, "Dockerfile")
case "config":
filePath = filepath.Join(absBuildDir, "pkg", "embedded", "config.go")
default:
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid file type"})
return
}
// Check if file exists
if _, err := os.Stat(filePath); os.IsNotExist(err) {
c.JSON(http.StatusNotFound, gin.H{"error": "file not found"})
return
}
// Serve file for download
c.FileAttachment(filePath, filepath.Base(filePath))
}

View File

@@ -0,0 +1,79 @@
package handlers
import (
"net/http"
"github.com/Fimeg/RedFlag/aggregator-server/internal/services"
"github.com/gin-gonic/gin"
)
// SetupAgent handles the agent setup endpoint
func SetupAgent(c *gin.Context) {
var req services.AgentSetupRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
// Create config builder
configBuilder := services.NewConfigBuilder(req.ServerURL)
// Build agent configuration
config, err := configBuilder.BuildAgentConfig(req)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
// Create response
response := gin.H{
"agent_id": config.AgentID,
"registration_token": config.Secrets["registration_token"],
"server_public_key": config.Secrets["server_public_key"],
"configuration": config.PublicConfig,
"secrets": config.Secrets,
"template": config.Template,
"setup_time": config.BuildTime,
"secrets_created": config.SecretsCreated,
"secrets_path": config.SecretsPath,
}
c.JSON(http.StatusOK, response)
}
// GetTemplates returns available agent templates
func GetTemplates(c *gin.Context) {
configBuilder := services.NewConfigBuilder("")
templates := configBuilder.GetTemplates()
c.JSON(http.StatusOK, gin.H{"templates": templates})
}
// ValidateConfiguration validates a configuration before deployment
func ValidateConfiguration(c *gin.Context) {
var config map[string]interface{}
if err := c.ShouldBindJSON(&config); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
agentType, exists := config["agent_type"].(string)
if !exists {
c.JSON(http.StatusBadRequest, gin.H{"error": "agent_type is required"})
return
}
configBuilder := services.NewConfigBuilder("")
template, exists := configBuilder.GetTemplate(agentType)
if !exists {
c.JSON(http.StatusBadRequest, gin.H{"error": "Unknown agent type"})
return
}
// Simple validation response
c.JSON(http.StatusOK, gin.H{
"valid": true,
"message": "Configuration appears valid",
"agent_type": agentType,
"template": template.Name,
})
}

View File

@@ -0,0 +1,229 @@
package handlers
import (
"fmt"
"net/http"
"github.com/Fimeg/RedFlag/aggregator-server/internal/services"
"github.com/gin-gonic/gin"
)
// NewAgentBuild handles new agent installation requests
func NewAgentBuild(c *gin.Context) {
var req services.NewBuildRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
// Validate registration token
if req.RegistrationToken == "" {
c.JSON(http.StatusBadRequest, gin.H{"error": "registration token is required for new installations"})
return
}
// Convert to setup request format
setupReq := services.AgentSetupRequest{
ServerURL: req.ServerURL,
Environment: req.Environment,
AgentType: req.AgentType,
Organization: req.Organization,
CustomSettings: req.CustomSettings,
DeploymentID: req.DeploymentID,
}
// Create config builder
configBuilder := services.NewConfigBuilder(req.ServerURL)
// Build agent configuration
config, err := configBuilder.BuildAgentConfig(setupReq)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
// Override generated agent ID if provided (for upgrades)
if req.AgentID != "" {
config.AgentID = req.AgentID
// Update public config with existing agent ID
if config.PublicConfig == nil {
config.PublicConfig = make(map[string]interface{})
}
config.PublicConfig["agent_id"] = req.AgentID
}
// Create agent builder
agentBuilder := services.NewAgentBuilder()
// Generate build artifacts
buildResult, err := agentBuilder.BuildAgentWithConfig(config)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
// Construct download URL
binaryURL := fmt.Sprintf("%s/api/v1/downloads/%s", req.ServerURL, config.Platform)
// Create response with native binary instructions
response := gin.H{
"agent_id": config.AgentID,
"binary_url": binaryURL,
"platform": config.Platform,
"config_version": config.ConfigVersion,
"agent_version": config.AgentVersion,
"build_time": buildResult.BuildTime,
"install_type": "new",
"consumes_seat": true,
"next_steps": []string{
"1. Download native binary: curl -sL " + binaryURL + " -o /usr/local/bin/redflag-agent",
"2. Set permissions: chmod 755 /usr/local/bin/redflag-agent",
"3. Create config directory: mkdir -p /etc/redflag",
"4. Save configuration (provided in this response) to /etc/redflag/config.json",
"5. Set config permissions: chmod 600 /etc/redflag/config.json",
"6. Start service: systemctl enable --now redflag-agent",
},
"configuration": config.PublicConfig,
}
c.JSON(http.StatusOK, response)
}
// UpgradeAgentBuild handles agent upgrade requests
func UpgradeAgentBuild(c *gin.Context) {
agentID := c.Param("agentID")
if agentID == "" {
c.JSON(http.StatusBadRequest, gin.H{"error": "agent ID is required"})
return
}
var req services.UpgradeBuildRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
// Validate required fields
if req.ServerURL == "" {
c.JSON(http.StatusBadRequest, gin.H{"error": "server URL is required"})
return
}
// Convert to setup request format
setupReq := services.AgentSetupRequest{
ServerURL: req.ServerURL,
Environment: req.Environment,
AgentType: req.AgentType,
Organization: req.Organization,
CustomSettings: req.CustomSettings,
DeploymentID: req.DeploymentID,
}
// Create config builder
configBuilder := services.NewConfigBuilder(req.ServerURL)
// Build agent configuration
config, err := configBuilder.BuildAgentConfig(setupReq)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
// Override with existing agent ID (this is the key for upgrades)
config.AgentID = agentID
if config.PublicConfig == nil {
config.PublicConfig = make(map[string]interface{})
}
config.PublicConfig["agent_id"] = agentID
// For upgrades, we might want to preserve certain existing settings
if req.PreserveExisting {
// TODO: Load existing agent config and merge/override as needed
// This would involve reading the existing agent's configuration
// and selectively preserving certain fields
}
// Create agent builder
agentBuilder := services.NewAgentBuilder()
// Generate build artifacts
buildResult, err := agentBuilder.BuildAgentWithConfig(config)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
// Construct download URL
binaryURL := fmt.Sprintf("%s/api/v1/downloads/%s?version=%s", req.ServerURL, config.Platform, config.AgentVersion)
// Create response with native binary upgrade instructions
response := gin.H{
"agent_id": config.AgentID,
"binary_url": binaryURL,
"platform": config.Platform,
"config_version": config.ConfigVersion,
"agent_version": config.AgentVersion,
"build_time": buildResult.BuildTime,
"install_type": "upgrade",
"consumes_seat": false,
"preserves_agent_id": true,
"next_steps": []string{
"1. Stop agent service: systemctl stop redflag-agent",
"2. Download updated binary: curl -sL " + binaryURL + " -o /usr/local/bin/redflag-agent",
"3. Set permissions: chmod 755 /usr/local/bin/redflag-agent",
"4. Update config (provided in this response) to /etc/redflag/config.json if needed",
"5. Start service: systemctl start redflag-agent",
"6. Verify: systemctl status redflag-agent",
},
"configuration": config.PublicConfig,
"upgrade_notes": []string{
"This upgrade preserves the existing agent ID: " + agentID,
"No additional seat will be consumed",
"Config version: " + config.ConfigVersion,
"Agent binary version: " + config.AgentVersion,
"Agent will receive latest security enhancements and bug fixes",
},
}
c.JSON(http.StatusOK, response)
}
// DetectAgentInstallation detects existing agent installations
func DetectAgentInstallation(c *gin.Context) {
// This endpoint helps the installer determine what type of installation to perform
var req struct {
AgentID string `json:"agent_id"`
}
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
// Create detector service
detector := services.NewInstallationDetector()
// Detect existing installation
detection, err := detector.DetectExistingInstallation(req.AgentID)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
response := gin.H{
"detection_result": detection,
"recommended_action": func() string {
if detection.HasExistingAgent {
return "upgrade"
}
return "new_installation"
}(),
"installation_type": func() string {
if detection.HasExistingAgent {
return "upgrade"
}
return "new"
}(),
}
c.JSON(http.StatusOK, response)
}

File diff suppressed because it is too large Load Diff

View File

@@ -180,6 +180,8 @@ func (h *SecurityHandler) MachineBindingStatus(c *gin.Context) {
// Get total agents for comparison
if totalAgents, err := h.agentQueries.GetTotalAgentCount(); err == nil {
response["checks"].(map[string]interface{})["total_agents"] = totalAgents
// Calculate version compliance (agents meeting minimum version requirement)
if compliantAgents, err := h.agentQueries.GetAgentCountByVersion("0.1.22"); err == nil {
response["checks"].(map[string]interface{})["version_compliance"] = compliantAgents

View File

@@ -425,6 +425,13 @@ func (h *SetupHandler) GenerateSigningKeys(c *gin.Context) {
c.Header("Pragma", "no-cache")
c.Header("Expires", "0")
// Load configuration to check for existing key
cfg, err := config.Load() // This will load from .env file
if err == nil && cfg.SigningPrivateKey != "" {
c.JSON(http.StatusConflict, gin.H{"error": "A signing key is already configured for this server."})
return
}
// Generate Ed25519 keypair
publicKey, privateKey, err := ed25519.GenerateKey(rand.Reader)
if err != nil {