source: advance the checked projection

Source-Sha: 194a59adfd6c901635da7a9c18253bb2210e2426
Policy-Sha: b9b0be0ee74e55f561a803b8aef6be3c2134f5a83b46816a069a372f2eb04f4d
Tree-Digest: 4697f2e281c1c6ecafff17cf6eeb391a0a1ac0fa6e5fc429f5b473f4579c252c
This commit is contained in:
Source publisher 2026-09-21 14:39:08 +00:00
commit ffdccba10f
42 changed files with 2516 additions and 554 deletions

View file

@ -13,93 +13,18 @@ import (
"github.com/Fimeg/RedFlag/agent/internal/scanner"
"github.com/Fimeg/RedFlag/agent/internal/system"
"github.com/Fimeg/RedFlag/agent/internal/version"
"github.com/gofrs/uuid/v5"
)
// RegisterAgent registers the agent with the server
func RegisterAgent(cfg *config.Config, serverURL string) error {
// Get detailed system information
sysInfo, err := system.GetSystemInfo(version.Version)
req, err := collectRegistrationRequest()
if err != nil {
log.Printf("Warning: Failed to get detailed system info: %v\n", err)
// Fall back to basic detection
hostname, _ := os.Hostname()
osType, osVersion, osArch := client.DetectSystem()
sysInfo = &system.SystemInfo{
Hostname: hostname,
OSType: osType,
OSVersion: osVersion,
OSArchitecture: osArch,
AgentVersion: version.Version,
Metadata: make(map[string]string),
}
return err
}
// Use registration token from config if available
apiClient := client.NewClient(serverURL, cfg.RegistrationToken)
// Create metadata with system information
metadata := map[string]string{
"installation_time": time.Now().Format(time.RFC3339),
}
// Add system info to metadata
if sysInfo.CPUInfo.ModelName != "" {
metadata["cpu_model"] = sysInfo.CPUInfo.ModelName
}
if sysInfo.CPUInfo.Cores > 0 {
metadata["cpu_cores"] = fmt.Sprintf("%d", sysInfo.CPUInfo.Cores)
}
if sysInfo.MemoryInfo.Total > 0 {
metadata["memory_total"] = fmt.Sprintf("%d", sysInfo.MemoryInfo.Total)
}
if sysInfo.RunningProcesses > 0 {
metadata["processes"] = fmt.Sprintf("%d", sysInfo.RunningProcesses)
}
if sysInfo.Uptime != "" {
metadata["uptime"] = sysInfo.Uptime
}
// Add disk information
for i, disk := range sysInfo.DiskInfo {
if i == 0 {
metadata["disk_mount"] = disk.Mountpoint
metadata["disk_total"] = fmt.Sprintf("%d", disk.Total)
metadata["disk_used"] = fmt.Sprintf("%d", disk.Used)
break // Only add primary disk info
}
}
// Get machine ID for binding
machineID, err := system.GetMachineID()
if err != nil {
return fmt.Errorf("machine_id_unavailable: %w - cannot register without consistent machine ID", err)
}
// Get embedded public key fingerprint
publicKeyFingerprint := system.GetPublicKeyFingerprint()
if publicKeyFingerprint == "" {
log.Printf("Warning: No embedded public key fingerprint found")
}
// Detect available scanners for platform-specific subsystem creation
availableScanners := scanner.DetectAvailable()
log.Printf("[INFO] [agent] [registration] detected_scanners=%v", availableScanners)
req := client.RegisterRequest{
Hostname: sysInfo.Hostname,
OSType: sysInfo.OSType,
OSVersion: sysInfo.OSVersion,
OSArchitecture: sysInfo.OSArchitecture,
AgentVersion: sysInfo.AgentVersion,
MachineID: machineID,
PublicKeyFingerprint: publicKeyFingerprint,
Metadata: metadata,
AvailableScanners: availableScanners,
DeviceType: sysInfo.DeviceType,
DeviceModel: sysInfo.DeviceModel,
OSDistro: sysInfo.OSDistro,
}
resp, err := apiClient.Register(req)
if err != nil {
return err
@ -136,9 +61,121 @@ func RegisterAgent(cfg *config.Config, serverURL string) error {
return nil
}
func collectRegistrationRequest() (client.RegisterRequest, error) {
// Get detailed system information
sysInfo, err := system.GetSystemInfo(version.Version)
if err != nil {
log.Printf("Warning: Failed to get detailed system info: %v\n", err)
// Fall back to basic detection
hostname, _ := os.Hostname()
osType, osVersion, osArch := client.DetectSystem()
sysInfo = &system.SystemInfo{
Hostname: hostname,
OSType: osType,
OSVersion: osVersion,
OSArchitecture: osArch,
AgentVersion: version.Version,
Metadata: make(map[string]string),
}
}
// Create metadata with system information
metadata := map[string]string{
"installation_time": time.Now().Format(time.RFC3339),
}
// Add system info to metadata
if sysInfo.CPUInfo.ModelName != "" {
metadata["cpu_model"] = sysInfo.CPUInfo.ModelName
}
if sysInfo.CPUInfo.Cores > 0 {
metadata["cpu_cores"] = fmt.Sprintf("%d", sysInfo.CPUInfo.Cores)
}
if sysInfo.MemoryInfo.Total > 0 {
metadata["memory_total"] = fmt.Sprintf("%d", sysInfo.MemoryInfo.Total)
}
if sysInfo.RunningProcesses > 0 {
metadata["processes"] = fmt.Sprintf("%d", sysInfo.RunningProcesses)
}
if sysInfo.Uptime != "" {
metadata["uptime"] = sysInfo.Uptime
}
// Add disk information
for i, disk := range sysInfo.DiskInfo {
if i == 0 {
metadata["disk_mount"] = disk.Mountpoint
metadata["disk_total"] = fmt.Sprintf("%d", disk.Total)
metadata["disk_used"] = fmt.Sprintf("%d", disk.Used)
break // Only add primary disk info
}
}
// Get machine ID for binding
machineID, err := system.GetMachineID()
if err != nil {
return client.RegisterRequest{}, fmt.Errorf("machine_id_unavailable: %w - cannot register without consistent machine ID", err)
}
// Get embedded public key fingerprint
publicKeyFingerprint := system.GetPublicKeyFingerprint()
if publicKeyFingerprint == "" {
log.Printf("Warning: No embedded public key fingerprint found")
}
// Detect available scanners for platform-specific subsystem creation
availableScanners := scanner.DetectAvailable()
log.Printf("[INFO] [agent] [registration] detected_scanners=%v", availableScanners)
return client.RegisterRequest{
Hostname: sysInfo.Hostname,
OSType: sysInfo.OSType,
OSVersion: sysInfo.OSVersion,
OSArchitecture: sysInfo.OSArchitecture,
AgentVersion: sysInfo.AgentVersion,
MachineID: machineID,
PublicKeyFingerprint: publicKeyFingerprint,
Metadata: metadata,
AvailableScanners: availableScanners,
DeviceType: sysInfo.DeviceType,
DeviceModel: sysInfo.DeviceModel,
OSDistro: sysInfo.OSDistro,
}, nil
}
// JoinFleet registers an existing standalone identity with the fleet Server.
// It returns credentials without persisting them; the caller must first finish
// the privileged authority replacement transaction.
func JoinFleet(cfg *config.Config, requestID, serverURL, registrationToken, seed string) (*client.FleetJoinResponse, error) {
if cfg == nil || !cfg.IsStandalone() {
return nil, fmt.Errorf("fleet join requires a standalone Agent identity")
}
requestUUID, err := uuid.FromString(requestID)
if err != nil {
return nil, fmt.Errorf("fleet join request id is invalid: %w", err)
}
base, err := collectRegistrationRequest()
if err != nil {
return nil, err
}
code, err := fleetJoinTOTPCode(seed, time.Now().UTC())
if err != nil {
return nil, err
}
req := client.FleetJoinRequest{
RequestID: requestUUID, AgentID: cfg.AgentID,
RegistrationToken: registrationToken, TOTPCode: code,
Hostname: base.Hostname, OSType: base.OSType, OSVersion: base.OSVersion,
OSArchitecture: base.OSArchitecture, AgentVersion: base.AgentVersion,
MachineID: base.MachineID, PublicKeyFingerprint: base.PublicKeyFingerprint,
Metadata: base.Metadata, AvailableScanners: base.AvailableScanners,
DeviceType: base.DeviceType, DeviceModel: base.DeviceModel, OSDistro: base.OSDistro,
}
return client.NewClient(serverURL, "").JoinFleet(req)
}
// FetchAndCachePublicKey fetches the server's Ed25519 public key and caches it locally
func FetchAndCachePublicKey(serverURL string) error {
_, err := crypto.FetchAndCacheServerPublicKey(serverURL)
return err
}