Fix hardware UUID caching by sgress454 · Pull Request #8616 · osquery/osquery
For #7509
For fleetdm/fleet#28535
Details
This PR updates the logic for generating, storing and returning host identifiers when --host-identifier=uuid is used. Previously, once a UUID was determined (either by getting a valid hardware UUID from the device, or failing that, creating a random UUID) it was stored in the local db and returned henceforth on every call to getHostUUID(). With this update, the logic becomes:
- Always check for a hardware UUID the first time
getHostUUID()is called. - If one is found, store it in the db.
- Check the db for a value.
- If one is found, return it.
- Otherwise generate a random UUID, store it in the db and return it.
This handles the most pertinent cases of 1) moving an osquery db between two hosts with different hardware UUIDs and 2) the hardware UUID of a host changing (e.g. due to a motherboard being swapped out). It also maintains the behavior of randomly-generated UUIDs persisting across osquery restarts (provided that no hardware UUID is found) so that VMs using --host-identifier=uuid get a consistent UUID.
The behavior when moving from a system with a hardware UUID to a system without one (or moving between two VMs) may still be considered sub-optimal, but those use-cases don't seem as problematic and I'm not sure what a good solve would be.
Testing
I tested this manually with:
./osquery/osqueryi --verbose --database_path=./osquery.db --disable_database=false
and manipulating the db using ldb. I also simulated VM usage by temporarily adding my laptop's UUID to the "placeholders" list.
I'd love to add a unit test for the new logic but the only way I can think to do that would be to change getHostUUID to use dependency-injection so I could mock generateNewUUID(), getDatabaseValue() and setDatabaseValue(). I haven't seen that pattern elsewhere in osquery though.