Documentation
¶
Overview ¶
Package state persists the bits of agent identity that have to survive across runs: the machine UUID (when /etc/machine-id is unavailable) and the monotonic scan sequence counter.
The token credential is NOT here; it lives at /etc/ghostpsy/agent.conf (see internal/agentconfig). State is read/written by every scan and is kept under /var/lib/ghostpsy/ because the agent runs as root via cron or systemd; per-user XDG locations would land in /root/.config which is not a sensible home for system-service state.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func MachineUUIDFromOS ¶
MachineUUIDFromOS returns a UUID derived from the host D-Bus/machine ID when available.
We do not use github.com/shirou/gopsutil/v4/host.HostID (see host_linux.go): that API tries /sys/class/dmi/id/product_uuid first, then /etc/machine-id, then /proc/sys/kernel/random/boot_id. For Ghostpsy we need (1) stable OS identity from /etc/machine-id (e.g. Docker audit entrypoint may seed it), not DMI product UUID, and (2) never boot_id, which changes every reboot and would create a new machine row after each boot. Linux writes 32 lowercase hex bytes to /etc/machine-id (or /var/lib/dbus/machine-id). The value is formatted as a standard UUID string for ingest (backend stores uuid.UUID).
func RecordLastScan ¶ added in v0.54.1
RecordLastScan writes the time of the last scan, and changes nothing else.
The daemon reads this file once, when it starts, and keeps that copy for as long as it runs. A scan is a child process, and it writes the file itself — the scan sequence in particular. So by the time the daemon has a scan time to record, its own copy is already out of date, and saving it would put the scan sequence back to what it was at start-up.
That is not a small thing. The server refuses a sequence number it has already stored, so once the two disagree every later scan is rejected as a duplicate and the machine stops reporting. The file is therefore read again here, and only this one field is touched.
func Save ¶
func Save(s *AgentState) error
Save writes the state file with mode 0600 owner=root and creates the containing directory if missing.
Types ¶
type AgentState ¶
type AgentState struct {
MachineUUID string `json:"machine_uuid"`
ScanSeq int `json:"scan_seq"`
// LastUpdateNotifiedVersion + LastUpdateNotifiedAt back the weekly upgrade
// reminder (printed at the end of `ghostpsy scan` when a newer release is
// available). Empty/zero on agents that have never seen an upgrade nudge.
LastUpdateNotifiedVersion string `json:"last_update_notified_version,omitempty"`
LastUpdateNotifiedAt int64 `json:"last_update_notified_at,omitempty"`
// LastScanAt is when the service last completed a scan, in unix seconds.
// Zero on an agent that has never scanned, which is why the service treats
// zero as "never" rather than as 1970.
LastScanAt int64 `json:"last_scan_at,omitempty"`
}
AgentState is persisted after the first successful scan: a stable machine identity and the scan_seq counter.
func Load ¶
func Load() (*AgentState, error)
Load reads the state file. Returns an error when the file is missing, malformed, or has no machine UUID.