feat: machine binding and version enforcement
migration 017 adds machine_id to agents table middleware validates X-Machine-ID header on authed routes agent client sends machine ID with requests MIN_AGENT_VERSION config defaults 0.1.22 version utils added for comparison blocks config copying attacks via hardware fingerprint old agents get 426 upgrade required breaking: <0.1.22 agents rejected
This commit is contained in:
@@ -18,15 +18,20 @@ type Agent struct {
|
||||
AgentVersion string `json:"agent_version" db:"agent_version"` // Version at registration
|
||||
CurrentVersion string `json:"current_version" db:"current_version"` // Current running version
|
||||
UpdateAvailable bool `json:"update_available" db:"update_available"` // Whether update is available
|
||||
LastVersionCheck time.Time `json:"last_version_check" db:"last_version_check"` // Last time version was checked
|
||||
LastSeen time.Time `json:"last_seen" db:"last_seen"`
|
||||
Status string `json:"status" db:"status"`
|
||||
Metadata JSONB `json:"metadata" db:"metadata"`
|
||||
RebootRequired bool `json:"reboot_required" db:"reboot_required"`
|
||||
LastRebootAt *time.Time `json:"last_reboot_at,omitempty" db:"last_reboot_at"`
|
||||
RebootReason *string `json:"reboot_reason,omitempty" db:"reboot_reason"`
|
||||
CreatedAt time.Time `json:"created_at" db:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at" db:"updated_at"`
|
||||
LastVersionCheck time.Time `json:"last_version_check" db:"last_version_check"` // Last time version was checked
|
||||
MachineID *string `json:"machine_id,omitempty" db:"machine_id"` // Unique machine identifier
|
||||
PublicKeyFingerprint *string `json:"public_key_fingerprint,omitempty" db:"public_key_fingerprint"` // Public key fingerprint
|
||||
IsUpdating bool `json:"is_updating" db:"is_updating"` // Whether agent is currently updating
|
||||
UpdatingToVersion *string `json:"updating_to_version,omitempty" db:"updating_to_version"` // Target version for ongoing update
|
||||
UpdateInitiatedAt *time.Time `json:"update_initiated_at,omitempty" db:"update_initiated_at"` // When update process started
|
||||
LastSeen time.Time `json:"last_seen" db:"last_seen"`
|
||||
Status string `json:"status" db:"status"`
|
||||
Metadata JSONB `json:"metadata" db:"metadata"`
|
||||
RebootRequired bool `json:"reboot_required" db:"reboot_required"`
|
||||
LastRebootAt *time.Time `json:"last_reboot_at,omitempty" db:"last_reboot_at"`
|
||||
RebootReason *string `json:"reboot_reason,omitempty" db:"reboot_reason"`
|
||||
CreatedAt time.Time `json:"created_at" db:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at" db:"updated_at"`
|
||||
}
|
||||
|
||||
// AgentWithLastScan extends Agent with last scan information
|
||||
@@ -69,13 +74,15 @@ type AgentSpecs struct {
|
||||
|
||||
// AgentRegistrationRequest is the payload for agent registration
|
||||
type AgentRegistrationRequest struct {
|
||||
Hostname string `json:"hostname" binding:"required"`
|
||||
OSType string `json:"os_type" binding:"required"`
|
||||
OSVersion string `json:"os_version"`
|
||||
OSArchitecture string `json:"os_architecture"`
|
||||
AgentVersion string `json:"agent_version" binding:"required"`
|
||||
RegistrationToken string `json:"registration_token"` // Optional, for fallback method
|
||||
Metadata map[string]string `json:"metadata"`
|
||||
Hostname string `json:"hostname" binding:"required"`
|
||||
OSType string `json:"os_type" binding:"required"`
|
||||
OSVersion string `json:"os_version"`
|
||||
OSArchitecture string `json:"os_architecture"`
|
||||
AgentVersion string `json:"agent_version" binding:"required"`
|
||||
RegistrationToken string `json:"registration_token"` // Optional, for fallback method
|
||||
MachineID string `json:"machine_id"` // Unique machine identifier
|
||||
PublicKeyFingerprint string `json:"public_key_fingerprint"` // Embedded public key fingerprint
|
||||
Metadata map[string]string `json:"metadata"`
|
||||
}
|
||||
|
||||
// AgentRegistrationResponse is returned after successful registration
|
||||
|
||||
67
aggregator-server/internal/models/agent_update.go
Normal file
67
aggregator-server/internal/models/agent_update.go
Normal file
@@ -0,0 +1,67 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
// AgentUpdatePackage represents a signed agent binary package
|
||||
type AgentUpdatePackage struct {
|
||||
ID uuid.UUID `json:"id" db:"id"`
|
||||
Version string `json:"version" db:"version"`
|
||||
Platform string `json:"platform" db:"platform"`
|
||||
Architecture string `json:"architecture" db:"architecture"`
|
||||
BinaryPath string `json:"binary_path" db:"binary_path"`
|
||||
Signature string `json:"signature" db:"signature"`
|
||||
Checksum string `json:"checksum" db:"checksum"`
|
||||
FileSize int64 `json:"file_size" db:"file_size"`
|
||||
CreatedAt time.Time `json:"created_at" db:"created_at"`
|
||||
CreatedBy string `json:"created_by" db:"created_by"`
|
||||
IsActive bool `json:"is_active" db:"is_active"`
|
||||
}
|
||||
|
||||
// AgentUpdateRequest represents a request to update an agent
|
||||
type AgentUpdateRequest struct {
|
||||
AgentID uuid.UUID `json:"agent_id" binding:"required"`
|
||||
Version string `json:"version" binding:"required"`
|
||||
Platform string `json:"platform" binding:"required"`
|
||||
Scheduled *string `json:"scheduled_at,omitempty"`
|
||||
}
|
||||
|
||||
// BulkAgentUpdateRequest represents a bulk update request
|
||||
type BulkAgentUpdateRequest struct {
|
||||
AgentIDs []uuid.UUID `json:"agent_ids" binding:"required"`
|
||||
Version string `json:"version" binding:"required"`
|
||||
Platform string `json:"platform" binding:"required"`
|
||||
Scheduled *string `json:"scheduled_at,omitempty"`
|
||||
}
|
||||
|
||||
// AgentUpdateResponse represents the response for an update request
|
||||
type AgentUpdateResponse struct {
|
||||
Message string `json:"message"`
|
||||
UpdateID string `json:"update_id,omitempty"`
|
||||
DownloadURL string `json:"download_url,omitempty"`
|
||||
Signature string `json:"signature,omitempty"`
|
||||
Checksum string `json:"checksum,omitempty"`
|
||||
FileSize int64 `json:"file_size,omitempty"`
|
||||
EstimatedTime int `json:"estimated_time_seconds,omitempty"`
|
||||
}
|
||||
|
||||
// SignatureVerificationRequest represents a request to verify an agent's binary signature
|
||||
type SignatureVerificationRequest struct {
|
||||
AgentID uuid.UUID `json:"agent_id" binding:"required"`
|
||||
BinaryPath string `json:"binary_path" binding:"required"`
|
||||
MachineID string `json:"machine_id" binding:"required"`
|
||||
PublicKey string `json:"public_key" binding:"required"`
|
||||
Signature string `json:"signature" binding:"required"`
|
||||
}
|
||||
|
||||
// SignatureVerificationResponse represents the response for signature verification
|
||||
type SignatureVerificationResponse struct {
|
||||
Valid bool `json:"valid"`
|
||||
AgentID string `json:"agent_id"`
|
||||
MachineID string `json:"machine_id"`
|
||||
Fingerprint string `json:"fingerprint"`
|
||||
Message string `json:"message"`
|
||||
}
|
||||
Reference in New Issue
Block a user