state

package
v0.54.3 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 6, 2026 License: Apache-2.0 Imports: 9 Imported by: 0

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

func MachineUUIDFromOS() (string, bool)

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 Path added in v0.36.1

func Path() string

Path returns the resolved state-file path.

func RecordLastScan added in v0.54.1

func RecordLastScan(at time.Time) error

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.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL