Skip to main content
Version: v3.9.2

EdgeGuard module

Edge Guard is the daemon hardware attestation loop. It fingerprints the host, signs a baseline JWT, stores it in SQLite, and on fingerprint drift triggers controller warning + agent deprovision.

Code: internal/edgeguard/

Operator guide: EdgeGuard (configuration, fingerprint sources, mismatch behavior)

Purpose​

  • Periodic hardware fingerprint collection (platform-specific)
  • Sign stable hash claim into Edge Guard JWT
  • Compare new fingerprint hash to stored baseline (not full JWT string)
  • POST warning + deprovision on real hardware change
  • Disable cleanly when edgeGuardFrequency=0

Dependencies​

Depends onReason
authGenerateEdgeGuardJWT, EdgeGuardHashFromJWT()
storeagent_edgeguard_signature singleton row
configedgeGuardFrequency, iofogUuid, private key
fieldagentDeprovision + status POST on mismatch
statusreporterWarning message on supervisor status
Used byReason
supervisorStarted last in module sequence

Lifecycle​

Start​

(*Manager).Start():

  1. If unprovisioned or no private key → force frequency to 0, delete stored signature if disabled
  2. If frequency ≤ 0 → no-op (disabled)
  3. Load signature cache from DB
  4. Run initial checkHardwareSignature()
  5. Start attestationWorker ticker at edgeGuardFrequency seconds

Stop​

Cancel attestation context; stop ticker.

Config update​

InstanceConfigUpdated() reschedules attestation interval; cancels prior worker goroutine to avoid leaks.

Attestation flow​

Comparison uses auth.EdgeGuardHashFromJWT() on the stored JWT vs newly computed hash. Avoids false deprovision when only iat/exp/jti rotate.

What counts as a hardware change​

A hardware change is any difference in the canonical fingerprint JSON. Edge Guard lowercases and trims strings, sorts device lists, then SHA-256 hashes that JSON. The stored Edge Guard JWT is compared by its hash claim. A new JWT whose only changes are iat, exp, or jti is not a hardware change.

The next attestation tick that samples a different hash sets daemon status to WARNING, sets warningMessage to HW signature changed (20 characters), PUTs that status to the controller, then deprovisions. securityViolationInfo is not sent by Edgelet. The controller builds that field from the warning.

Fields that change the hash​

FieldHashed valuesA change means
SystemProduct UUID, serial, vendor, modelBoard identity or a VM move
BIOSVendor, versionFirmware change
MotherboardProduct, serialBoard swap
CPUVendor, model name, family, model, stepping, physical core countCPU identity change. Load and frequency are not included.
PCISlot, class, vendor, device, subsystem vendor, subsystem deviceCard added, removed, or moved to another slot
GPUDerived from PCI class 0x03Follows the PCI list
Root diskDevice path, serial, WWN, modelRoot disk replaced or the root device path changed
NICsName, MAC, link stateSee below
USBBus path, vendor, product, manufacturer, product name, serialPlug, unplug, or a different port. USB hubs are skipped.
OptionalMemory-module locator, serial, part number; secure boot; TPM present, EK hash, PCR hash; board serial; /etc/machine-idDIMM, secure-boot, TPM, or machine-id change
ARM onlyDevice-tree model, compatible, serialBoard identity on arm and arm64

Empty DMI placeholders (none, not specified, not available, unknown, to be filled by o.e.m.) are omitted before hashing.

Linux link state is /sys/class/net/<iface>/carrier. Edge Guard stores one of three values:

ValueMeaning
1Interface is administratively up and the PHY has carrier
0Interface is administratively up and the PHY has no carrier
unknowncarrier could not be read, which is what Linux returns when the interface is administratively down

1, 0, and unknown are different hashes. IP addresses, routes, and whether packets flow are not part of the fingerprint.

Included interfaces are those with a real MAC whose names start with eth, en, em, eno, ens, enp, wlan, wlp, or wwan. That includes USB Ethernet names such as enx*. Ignored names start with lo, docker, br-, veth, virbr, tun, tap, vmnet, vnet, cni, flannel, or cali.

Any included NIC moving between 1, 0, and unknown deprovisions the agent if an attestation tick samples the new value. A short flap is invisible when the tick falls outside it.

Ethernet cabled to a modem. A direct cable into a modem that is powered off drops carrier from 1 to 0 while the host interface stays up. A switch left powered between the host and the modem keeps the host link up, so shutting the modem down does not change linkState.

USB modem. The hashed link is the USB-Ethernet connection to the modem, not the cellular session inside it. Powering the modem off removes the interface or moves it to unknown. Losing cellular data while the stick stays plugged in and enumerated leaves linkState unchanged.

Wi-Fi (wlp*, wlan*). Losing association (access point gone, radio off, out of range) normally moves carrier from 1 to 0. Staying associated while only the upstream path dies leaves linkState at 1.

WWAN (wwan*). When the driver ties carrier to the data session, a session drop changes the hash. Bringing the interface down is stored as unknown, which also changes the hash. An interface that stays up with carrier while packets stop does not change linkState.

Configuration​

KeyEffect
edgeGuardFrequencyInterval seconds; 0 disables
iofogUuidMust be set (provisioned) for attestation to run

Unprovisioned agents force frequency to 0 at Field Agent and Edge Guard start.

Data and persistence​

TableContent
agent_edgeguard_signatureLatest attestation JWT (id=1)

On disable, signature row is deleted.

External APIs​

No direct HTTP. Side effects:

  • Field Agent deprovision path
  • Controller status POST with warning
  • Clears supervisor warning after successful re-provision (Field Agent)

Observability​

  • Log module name: "Edge Guard Manager"
  • Not in modulesStatus[] fixed array; warning via SupervisorStatus.warningMessage

Failure modes​

SymptomTypical cause
Unexpected deprovisionHardware change; NIC link flap (1 / 0 / unknown); USB plug or unplug; TPM PCR change; VM migration; fingerprint source drift
Attestation skippedFrequency 0 or unprovisioned
Start errorDB signature load failure on enabled config

Platform fingerprint collection: fingerprint_linux.go, fingerprint_darwin.go, etc.

Code map​

FileRole
manager.goStart/stop, attestation worker, deprovision trigger
fingerprint_*.goPlatform fingerprint collectors
fingerprint_types.go, fingerprint_diff.goCanonical payload + diff

Related: Auth, Field agent, Store, EdgeGuard.

Group 3See anything wrong with the document? Help us improve it!