diff --git a/aggregator-agent/go.mod b/aggregator-agent/go.mod index f2a5f96..9a76862 100644 --- a/aggregator-agent/go.mod +++ b/aggregator-agent/go.mod @@ -12,6 +12,7 @@ require ( ) require ( + github.com/Fimeg/RedFlag/aggregator v0.0.0 github.com/Microsoft/go-winio v0.4.21 // indirect github.com/containerd/log v0.1.0 // indirect github.com/distribution/reference v0.6.0 // indirect @@ -36,3 +37,5 @@ require ( golang.org/x/time v0.5.0 // indirect gotest.tools/v3 v3.5.2 // indirect ) + +replace github.com/Fimeg/RedFlag/aggregator => ../aggregator diff --git a/aggregator-agent/internal/migration/detection.go b/aggregator-agent/internal/migration/detection.go index aca8dd6..d1b7d6b 100644 --- a/aggregator-agent/internal/migration/detection.go +++ b/aggregator-agent/internal/migration/detection.go @@ -9,29 +9,19 @@ import ( "path/filepath" "strings" "time" -) -// AgentFile represents a file associated with the agent -type AgentFile struct { - Path string `json:"path"` - Size int64 `json:"size"` - ModifiedTime time.Time `json:"modified_time"` - Version string `json:"version,omitempty"` - Checksum string `json:"checksum"` - Required bool `json:"required"` - Migrate bool `json:"migrate"` - Description string `json:"description"` -} + "github.com/Fimeg/RedFlag/aggregator/pkg/common" +) // AgentFileInventory represents all files associated with an agent installation type AgentFileInventory struct { - ConfigFiles []AgentFile `json:"config_files"` - StateFiles []AgentFile `json:"state_files"` - BinaryFiles []AgentFile `json:"binary_files"` - LogFiles []AgentFile `json:"log_files"` - CertificateFiles []AgentFile `json:"certificate_files"` - OldDirectoryPaths []string `json:"old_directory_paths"` - NewDirectoryPaths []string `json:"new_directory_paths"` + ConfigFiles []common.AgentFile `json:"config_files"` + StateFiles []common.AgentFile `json:"state_files"` + BinaryFiles []common.AgentFile `json:"binary_files"` + LogFiles []common.AgentFile `json:"log_files"` + CertificateFiles []common.AgentFile `json:"certificate_files"` + OldDirectoryPaths []string `json:"old_directory_paths"` + NewDirectoryPaths []string `json:"new_directory_paths"` } // MigrationDetection represents the result of migration detection @@ -184,8 +174,8 @@ func scanAgentFiles(config *FileDetectionConfig) (*AgentFileInventory, error) { } // scanDirectory scans a directory for files matching specific patterns -func scanDirectory(dirPath string, patterns map[string][]string) ([]AgentFile, error) { - var files []AgentFile +func scanDirectory(dirPath string, patterns map[string][]string) ([]common.AgentFile, error) { + var files []common.AgentFile err := filepath.Walk(dirPath, func(path string, info os.FileInfo, err error) error { if err != nil { @@ -203,7 +193,7 @@ func scanDirectory(dirPath string, patterns map[string][]string) ([]AgentFile, e return nil } - file := AgentFile{ + file := common.AgentFile{ Path: path, Size: info.Size(), ModifiedTime: info.ModTime(), diff --git a/aggregator-agent/internal/migration/docker.go b/aggregator-agent/internal/migration/docker.go index a35cdd3..e0c7163 100644 --- a/aggregator-agent/internal/migration/docker.go +++ b/aggregator-agent/internal/migration/docker.go @@ -14,6 +14,8 @@ import ( "runtime" "strings" "time" + + "github.com/Fimeg/RedFlag/aggregator/pkg/common" ) // DockerDetection represents Docker secrets detection results @@ -23,7 +25,7 @@ type DockerDetection struct { RequiredSecrets []string `json:"required_secrets"` ExistingSecrets []string `json:"existing_secrets"` MigrateToSecrets bool `json:"migrate_to_secrets"` - SecretFiles []AgentFile `json:"secret_files"` + SecretFiles []common.AgentFile `json:"secret_files"` DetectionTime time.Time `json:"detection_time"` } @@ -88,8 +90,8 @@ func DetectDockerSecretsRequirements(config *FileDetectionConfig) (*DockerDetect } // scanSecretFiles scans for files containing sensitive data -func scanSecretFiles(config *FileDetectionConfig) ([]AgentFile, error) { - var secretFiles []AgentFile +func scanSecretFiles(config *FileDetectionConfig) ([]common.AgentFile, error) { + var secretFiles []common.AgentFile // Define sensitive file patterns secretPatterns := []string{ @@ -116,8 +118,8 @@ func scanSecretFiles(config *FileDetectionConfig) ([]AgentFile, error) { } // scanSecretDirectory scans a directory for files that may contain secrets -func scanSecretDirectory(dirPath string, patterns []string) ([]AgentFile, error) { - var files []AgentFile +func scanSecretDirectory(dirPath string, patterns []string) ([]common.AgentFile, error) { + var files []common.AgentFile err := filepath.Walk(dirPath, func(path string, info os.FileInfo, err error) error { if err != nil { @@ -146,13 +148,13 @@ func scanSecretDirectory(dirPath string, patterns []string) ([]AgentFile, error) } // addSecretFile adds a file to the secret files list -func addSecretFile(files *[]AgentFile, path string, info os.FileInfo) error { +func addSecretFile(files *[]common.AgentFile, path string, info os.FileInfo) error { checksum, err := calculateFileChecksum(path) if err != nil { return nil // Skip files we can't read } - file := AgentFile{ + file := common.AgentFile{ Path: path, Size: info.Size(), ModifiedTime: info.ModTime(), @@ -228,7 +230,7 @@ func containsString(s, substr string) bool { } // identifyRequiredSecrets identifies which secrets need to be created -func identifyRequiredSecrets(secretFiles []AgentFile) []string { +func identifyRequiredSecrets(secretFiles []common.AgentFile) []string { var secrets []string for _, file := range secretFiles { secretName := filepath.Base(file.Path) diff --git a/aggregator-agent/internal/migration/docker_executor.go b/aggregator-agent/internal/migration/docker_executor.go index ef85ff6..d41c621 100644 --- a/aggregator-agent/internal/migration/docker_executor.go +++ b/aggregator-agent/internal/migration/docker_executor.go @@ -7,6 +7,8 @@ import ( "path/filepath" "strings" "time" + + "github.com/Fimeg/RedFlag/aggregator/pkg/common" ) // DockerSecretsExecutor handles the execution of Docker secrets migration @@ -96,7 +98,7 @@ func (e *DockerSecretsExecutor) createSecretsBackup() error { } // migrateSecretFile migrates a single secret file to Docker secrets -func (e *DockerSecretsExecutor) migrateSecretFile(secretFile AgentFile) error { +func (e *DockerSecretsExecutor) migrateSecretFile(secretFile common.AgentFile) error { secretName := filepath.Base(secretFile.Path) secretPath := filepath.Join(e.detection.SecretsMountPath, secretName) @@ -120,7 +122,7 @@ func (e *DockerSecretsExecutor) migrateSecretFile(secretFile AgentFile) error { } // migrateConfigFile handles special migration of config.json with encryption -func (e *DockerSecretsExecutor) migrateConfigFile(secretFile AgentFile) error { +func (e *DockerSecretsExecutor) migrateConfigFile(secretFile common.AgentFile) error { // Read original config configData, err := os.ReadFile(secretFile.Path) if err != nil { diff --git a/aggregator-agent/internal/migration/executor.go b/aggregator-agent/internal/migration/executor.go index 39b4c4f..057b74a 100644 --- a/aggregator-agent/internal/migration/executor.go +++ b/aggregator-agent/internal/migration/executor.go @@ -6,6 +6,8 @@ import ( "path/filepath" "strings" "time" + + "github.com/Fimeg/RedFlag/aggregator/pkg/common" ) // MigrationPlan represents a complete migration plan @@ -239,8 +241,8 @@ func (e *MigrationExecutor) validateMigration() error { // Helper methods -func (e *MigrationExecutor) collectAllFiles() []AgentFile { - var allFiles []AgentFile +func (e *MigrationExecutor) collectAllFiles() []common.AgentFile { + var allFiles []common.AgentFile allFiles = append(allFiles, e.plan.Detection.Inventory.ConfigFiles...) allFiles = append(allFiles, e.plan.Detection.Inventory.StateFiles...) allFiles = append(allFiles, e.plan.Detection.Inventory.BinaryFiles...) @@ -249,7 +251,7 @@ func (e *MigrationExecutor) collectAllFiles() []AgentFile { return allFiles } -func (e *MigrationExecutor) backupFile(file AgentFile, backupPath string) error { +func (e *MigrationExecutor) backupFile(file common.AgentFile, backupPath string) error { relPath, err := filepath.Rel(e.plan.Config.OldConfigPath, file.Path) if err != nil { // Try relative to old state path diff --git a/aggregator-server/go.mod b/aggregator-server/go.mod index f1dde0f..801b54c 100644 --- a/aggregator-server/go.mod +++ b/aggregator-server/go.mod @@ -12,6 +12,7 @@ require ( ) require ( + github.com/Fimeg/RedFlag/aggregator v0.0.0 github.com/bytedance/sonic v1.14.0 // indirect github.com/bytedance/sonic/loader v0.3.0 // indirect github.com/cloudwego/base64x v0.1.6 // indirect @@ -43,3 +44,5 @@ require ( golang.org/x/tools v0.34.0 // indirect google.golang.org/protobuf v1.36.9 // indirect ) + +replace github.com/Fimeg/RedFlag/aggregator => ../aggregator diff --git a/aggregator-server/internal/services/build_types.go b/aggregator-server/internal/services/build_types.go index 70a6020..34dd83f 100644 --- a/aggregator-server/internal/services/build_types.go +++ b/aggregator-server/internal/services/build_types.go @@ -10,6 +10,8 @@ import ( "path/filepath" "strings" "time" + + "github.com/Fimeg/RedFlag/aggregator/pkg/common" ) // NewBuildRequest represents a request for a new agent build @@ -57,25 +59,13 @@ type InstallationDetection struct { // AgentFileInventory represents all files associated with an agent installation type AgentFileInventory struct { - ConfigFiles []AgentFile `json:"config_files"` - StateFiles []AgentFile `json:"state_files"` - BinaryFiles []AgentFile `json:"binary_files"` - LogFiles []AgentFile `json:"log_files"` - CertificateFiles []AgentFile `json:"certificate_files"` - ExistingPaths []string `json:"existing_paths"` - MissingPaths []string `json:"missing_paths"` -} - -// AgentFile represents a file associated with the agent -type AgentFile struct { - Path string `json:"path"` - Size int64 `json:"size"` - ModifiedTime string `json:"modified_time"` - Version string `json:"version,omitempty"` - Checksum string `json:"checksum"` - Required bool `json:"required"` - Migrate bool `json:"migrate"` - Description string `json:"description"` + ConfigFiles []common.AgentFile `json:"config_files"` + StateFiles []common.AgentFile `json:"state_files"` + BinaryFiles []common.AgentFile `json:"binary_files"` + LogFiles []common.AgentFile `json:"log_files"` + CertificateFiles []common.AgentFile `json:"certificate_files"` + ExistingPaths []string `json:"existing_paths"` + MissingPaths []string `json:"missing_paths"` } // MigrationDetection represents migration detection results (from existing migration system) @@ -115,8 +105,8 @@ func (id *InstallationDetector) DetectExistingInstallation(agentID string) (*Ins } // scanDirectory scans a directory for agent-related files -func (id *InstallationDetector) scanDirectory(dirPath string) ([]AgentFile, error) { - var files []AgentFile +func (id *InstallationDetector) scanDirectory(dirPath string) ([]common.AgentFile, error) { + var files []common.AgentFile entries, err := os.ReadDir(dirPath) if err != nil { @@ -143,10 +133,10 @@ func (id *InstallationDetector) scanDirectory(dirPath string) ([]AgentFile, erro checksum = "" } - file := AgentFile{ + file := common.AgentFile{ Path: fullPath, Size: info.Size(), - ModifiedTime: info.ModTime().Format(time.RFC3339), + ModifiedTime: info.ModTime(), Checksum: checksum, Required: id.isRequiredFile(entry.Name()), Migrate: id.shouldMigrateFile(entry.Name()), @@ -160,7 +150,7 @@ func (id *InstallationDetector) scanDirectory(dirPath string) ([]AgentFile, erro } // categorizeFile categorizes a file into the appropriate inventory section -func (id *InstallationDetector) categorizeFile(file AgentFile, inventory *AgentFileInventory) { +func (id *InstallationDetector) categorizeFile(file common.AgentFile, inventory *AgentFileInventory) { filename := filepath.Base(file.Path) switch { diff --git a/aggregator/go.mod b/aggregator/go.mod new file mode 100644 index 0000000..c020602 --- /dev/null +++ b/aggregator/go.mod @@ -0,0 +1,3 @@ +module github.com/Fimeg/RedFlag/aggregator + +go 1.23.0 diff --git a/aggregator/pkg/common/agentfile.go b/aggregator/pkg/common/agentfile.go new file mode 100644 index 0000000..9f970bd --- /dev/null +++ b/aggregator/pkg/common/agentfile.go @@ -0,0 +1,44 @@ +package common + +import ( + "crypto/sha256" + "encoding/hex" + "os" + "time" +) + +type AgentFile struct { + Path string `json:"path"` + Size int64 `json:"size"` + ModifiedTime time.Time `json:"modified_time"` + Version string `json:"version,omitempty"` + Checksum string `json:"checksum"` + Required bool `json:"required"` + Migrate bool `json:"migrate"` + Description string `json:"description"` +} + +// CalculateChecksum computes SHA256 checksum of a file +func CalculateChecksum(filePath string) (string, error) { + data, err := os.ReadFile(filePath) + if err != nil { + return "", err + } + hash := sha256.Sum256(data) + return hex.EncodeToString(hash[:]), nil +} + +// IsRequiredFile determines if a file is required for agent operation +func IsRequiredFile(path string) bool { + requiredFiles := []string{ + "/etc/redflag/config.json", + "/usr/local/bin/redflag-agent", + "/etc/systemd/system/redflag-agent.service", + } + for _, rf := range requiredFiles { + if path == rf { + return true + } + } + return false +}