Rapporteer dit toestel aan Fleet via osquery #3

Open
bbadmin wants to merge 3 commits from feat/osquery-integration into main
Owner

Het toestelgedeelte van de Fleet-koppeling (DAWO-Sextant#106, en de metingen in #107). Sextant stelt het toestel in om aan Fleet te rapporteren; er wordt niets geexporteerd en Fleet krijgt geen zeggenschap.

Vijf opties onder dawo.osquery, die vanzelf op de Integrations-pagina van de console verschijnen: enable, server, enrollSecret, serverCert, refreshSeconds. Beide geheimen zijn secret-refs zoals elke andere credential hier.

Kale osquery, geen fleetd

fleetd bundelt een eigen osquery-binary en werkt die automatisch bij. Dat is precies wat een vastgepinde closure niet toestaat. nixpkgs levert osquery 5.23.1 mét services.osquery, dus dit is configuratie en geen verpakking.

De vlaggen komen niet uit documentatie maar uit een toestel dat zich op 2026-08-23 daadwerkelijk aanmeldde bij een draaiende Fleet. Twee details die dat opleverde:

  • de endpoints staan op /api/v1/.... Een flagfile die je bij Fleet downloadt kan /api/latest/... dragen, en dat 404't op enrolment
  • host_identifier = "instance", zodat een hernoemd toestel dezelfde host blijft in plaats van een nieuwe aan te maken en het oude record te laten staan

Gemeten

nix eval .#catalog levert de vijf sleutels met label en de juiste secret-markering:

osquery.enable          boolean   Fleet inventory (osquery)
osquery.server          string    Fleet server
osquery.enrollSecret    string    Enroll secret            secret
osquery.serverCert      string    Server CA certificate    secret
osquery.refreshSeconds  int >0    Refresh interval (seconds)

Dat vroeg wel DAWO-Sextant#111, want de catalogus was helemaal niet te genereren: vier upstream-opties zonder label lieten de export klappen, ook op main.

Wat NIET bewezen is

De uitbreiding van integrations-acceptance staat erin, in dezelfde vorm als de andere vier: aan, op een dood adres, en getoetst op config-, PATH-, permissie- en secret-signaturen in plaats van op bereikbaarheid.

Maar die check evalueert op main al niet, met of zonder nieuwere Sextant-pin. De eigen testvloot valt over twee assertions: identity op plain ldap:// zonder allowPlaintextLdap, en netbird-setup-key die zowel agenix als de vault claimt (ADR 0018). Dat is er niet bij gefixt, zodat deze wijziging geen krediet krijgt voor een test die niemand kan draaien. Los te melden.

Het toestelgedeelte van de Fleet-koppeling (DAWO-Sextant#106, en de metingen in #107). Sextant stelt het toestel in om aan Fleet te rapporteren; er wordt niets geexporteerd en Fleet krijgt geen zeggenschap. Vijf opties onder `dawo.osquery`, die vanzelf op de Integrations-pagina van de console verschijnen: `enable`, `server`, `enrollSecret`, `serverCert`, `refreshSeconds`. Beide geheimen zijn secret-refs zoals elke andere credential hier. ## Kale osquery, geen fleetd `fleetd` bundelt een eigen osquery-binary en werkt die automatisch bij. Dat is precies wat een vastgepinde closure niet toestaat. nixpkgs levert osquery 5.23.1 mét `services.osquery`, dus dit is configuratie en geen verpakking. De vlaggen komen niet uit documentatie maar uit een toestel dat zich op 2026-08-23 daadwerkelijk aanmeldde bij een draaiende Fleet. Twee details die dat opleverde: - de endpoints staan op `/api/v1/...`. Een flagfile die je bij Fleet downloadt kan `/api/latest/...` dragen, en dat 404't op enrolment - `host_identifier = "instance"`, zodat een hernoemd toestel dezelfde host blijft in plaats van een nieuwe aan te maken en het oude record te laten staan ## Gemeten `nix eval .#catalog` levert de vijf sleutels met label en de juiste `secret`-markering: ``` osquery.enable boolean Fleet inventory (osquery) osquery.server string Fleet server osquery.enrollSecret string Enroll secret secret osquery.serverCert string Server CA certificate secret osquery.refreshSeconds int >0 Refresh interval (seconds) ``` Dat vroeg wel DAWO-Sextant#111, want de catalogus was helemaal niet te genereren: vier upstream-opties zonder label lieten de export klappen, ook op main. ## Wat NIET bewezen is De uitbreiding van `integrations-acceptance` staat erin, in dezelfde vorm als de andere vier: aan, op een dood adres, en getoetst op config-, PATH-, permissie- en secret-signaturen in plaats van op bereikbaarheid. Maar die check **evalueert op main al niet**, met of zonder nieuwere Sextant-pin. De eigen testvloot valt over twee assertions: `identity` op plain `ldap://` zonder `allowPlaintextLdap`, en `netbird-setup-key` die zowel agenix als de vault claimt (ADR 0018). Dat is er niet bij gefixt, zodat deze wijziging geen krediet krijgt voor een test die niemand kan draaien. Los te melden.
feat(integrations): report this device to Fleet over osquery
Some checks failed
ci / evaluate (push) Failing after 17s
ci / update-owned-inputs (push) Has been skipped
ci / evaluate (pull_request) Failing after 0s
ci / update-owned-inputs (pull_request) Has been skipped
1b1a00f675
A fleet rarely runs one operating system. Fleet covers the rest of the
estate; this makes a NixOS device visible there too, on the same screen,
without giving Fleet any say over what the device runs.

The device enrols itself and answers queries. Nothing is pushed back at it
and its configuration keeps coming from this overlay, which is the boundary
in DAWO-Sextant ADR 0028: one source of truth per device.

Plain osqueryd, not fleetd. fleetd bundles its own osquery binary and
auto-updates it, which is the one thing a pinned closure cannot allow.
nixpkgs ships osquery 5.23.1 and a services.osquery module, so this is
configuration rather than packaging.

The flags are not copied from documentation. They are the ones a device
actually enrolled with on 2026-08-23, measured against a real Fleet and
recorded verbatim in DAWO-Sextant#107. Two are worth naming: the endpoints
are pinned at /api/v1/... because a flagfile downloaded from Fleet may
carry /api/latest/... and 404 on enrolment, and host_identifier is
"instance" so a renamed device stays the same host instead of stranding its
old record.

Both secrets are secret-ref names like every other credential here. The
enroll secret enrols any number of devices, so it is not a device
credential and is not treated as one.

Added to integrations-acceptance in the same shape as the other four: on,
pointed at a dead address, and asserted for the config, PATH, permission
and secret signatures rather than for reachability.

That assertion is NOT proven yet. The check does not evaluate on main
either, with or without a newer Sextant pin: its own test fleet trips two
assertions, `identity` on plaintext ldap:// and `netbird-setup-key`
claiming both agenix and the vault (ADR 0018). Filed separately rather than
fixed here, so this change is not credited with a test nobody can run.
test(integrations): make the acceptance check evaluate again, and mean something
Some checks failed
ci / evaluate (push) Failing after 17s
ci / update-owned-inputs (push) Has been skipped
ci / evaluate (pull_request) Failing after 0s
ci / update-owned-inputs (pull_request) Has been skipped
ed3804476a
Two separate things, both about the same check.

FIRST: it has not evaluated since debda24 ("one switch per right, one
backend per secret, one path per credential"). That commit changed three
interfaces at once and the test fleet was never carried over, so all three
of its failures came from the same place:

  - userRights options are booleans now; the fleet still passed "session",
    "group:wheel" and "self"
  - a secret name has exactly one backend (ADR 0018); the fleet gave
    netbird-setup-key to both agenix and the vault
  - plain ldap:// must be recorded rather than implied

The fleet now says allowPlaintextLdap, because that IS what this fleet
does: the directory is reached over the mesh, which already encrypts and
peer-authenticates (ADR 0015). Pointing the test at ldaps:// instead would
prove a configuration nobody runs, and the strict branch already has its
own subtest. The vault gets a name agenix does not own. The three rights
are booleans, and AUTH_SELF_KEEP still appears because selfAuth is declared
with the right rather than chosen per fleet.

SECOND: the osquery entry I added to unitChecks caught nothing. Two
mutations proved it - breaking an endpoint and adding a flag osquery does
not know both left the check green. LoadState only says systemd could read
the unit file, and against a deliberately dead server osquery cannot tell a
wrong endpoint from a refused connection. That is a test that cannot fail,
which is worse than no test.

So there is now a subtest that reads the rendered flagfile out of ExecStart
and asserts the values measured against a real Fleet on 2026-08-23
(DAWO-Sextant#107): the five endpoints, host_identifier=instance, the
configured hostname, an enroll secret read from /run/agenix, and the
absence of /api/latest/ - the form a flagfile downloaded from Fleet
carries, which 404s on enrolment.

Mutations, after: endpoint to /api/latest fails, host_identifier to
hostname fails, a literal secret path instead of the agenix one fails.
Green again with all three reverted.
Author
Owner

Bijgewerkt: de acceptatietest draait weer, en de osquery-controle betekent nu iets.

De check evalueerde sinds debda24 niet meer

Die commit veranderde drie interfaces tegelijk en de testvloot is niet meegegaan. Alle drie de fouten kwamen daarvandaan:

  • userRights-opties zijn booleans geworden; de vloot gaf nog "session", "group:wheel" en "self"
  • een secretnaam heeft nog maar een backend (ADR 0018); netbird-setup-key stond zowel bij agenix als bij de vault
  • plain ldap:// moet vastgelegd worden in plaats van geimpliceerd

De vloot zegt nu allowPlaintextLdap, want dat is wat deze vloot doet: de directory gaat over de mesh, die al versleutelt en peer-authenticeert (ADR 0015). De test op ldaps:// zetten zou een configuratie bewijzen die niemand draait, en de strikte tak heeft al een eigen subtest.

En mijn eigen controle ving niets

De osquery-regel in unitChecks was leeg. Twee mutaties bewezen dat: een endpoint kapotmaken en een vlag toevoegen die osquery niet kent lieten hem allebei groen. LoadState zegt alleen dat systemd het unitbestand kon lezen, en tegen een bewust dood adres kan osquery een verkeerd endpoint niet onderscheiden van een geweigerde verbinding.

Een test die niet kan falen is erger dan geen test, dus er is nu een subtest die de gerenderde flagfile uit ExecStart leest en toetst op wat op 2026-08-23 tegen een echte Fleet gemeten is (#107): de vijf endpoints, host_identifier=instance, de ingestelde hostname, een enroll secret uit /run/agenix, en de afwezigheid van /api/latest/ — de vorm die een bij Fleet gedownloade flagfile draagt en die 404't.

Mutaties, na de fix

endpoint naar /api/latest rood
host_identifier naar hostname rood
letterlijk pad in plaats van de agenix-referentie rood
alle drie teruggedraaid groen

De VM-test draait volledig: osqueryd geladen met journaal, en de andere subtests weer mee — NSS, ldaps met strikte verificatie, de polkit-rechten en de lokale beheerder.

Bijgewerkt: de acceptatietest draait weer, en de osquery-controle betekent nu iets. ## De check evalueerde sinds `debda24` niet meer Die commit veranderde drie interfaces tegelijk en de testvloot is niet meegegaan. Alle drie de fouten kwamen daarvandaan: - `userRights`-opties zijn booleans geworden; de vloot gaf nog `"session"`, `"group:wheel"` en `"self"` - een secretnaam heeft nog maar een backend (ADR 0018); `netbird-setup-key` stond zowel bij agenix als bij de vault - plain `ldap://` moet vastgelegd worden in plaats van geimpliceerd De vloot zegt nu `allowPlaintextLdap`, want dat **is** wat deze vloot doet: de directory gaat over de mesh, die al versleutelt en peer-authenticeert (ADR 0015). De test op `ldaps://` zetten zou een configuratie bewijzen die niemand draait, en de strikte tak heeft al een eigen subtest. ## En mijn eigen controle ving niets De osquery-regel in `unitChecks` was leeg. Twee mutaties bewezen dat: een endpoint kapotmaken en een vlag toevoegen die osquery niet kent lieten hem allebei groen. `LoadState` zegt alleen dat systemd het unitbestand kon lezen, en tegen een bewust dood adres kan osquery een verkeerd endpoint niet onderscheiden van een geweigerde verbinding. Een test die niet kan falen is erger dan geen test, dus er is nu een subtest die de gerenderde flagfile uit `ExecStart` leest en toetst op wat op 2026-08-23 tegen een echte Fleet gemeten is (#107): de vijf endpoints, `host_identifier=instance`, de ingestelde hostname, een enroll secret uit `/run/agenix`, en de **afwezigheid** van `/api/latest/` — de vorm die een bij Fleet gedownloade flagfile draagt en die 404't. ## Mutaties, na de fix | | | |---|---| | endpoint naar `/api/latest` | rood | | `host_identifier` naar `hostname` | rood | | letterlijk pad in plaats van de agenix-referentie | rood | | alle drie teruggedraaid | groen | De VM-test draait volledig: `osqueryd` geladen met journaal, en de andere subtests weer mee — NSS, ldaps met strikte verificatie, de polkit-rechten en de lokale beheerder.
ci: look at the checks, not only at the hosts
Some checks failed
ci / evaluate (push) Failing after 18s
ci / evaluate (pull_request) Failing after 0s
ci / update-owned-inputs (push) Has been skipped
ci / update-owned-inputs (pull_request) Has been skipped
53dd3c2f5c
CI evaluated every host and checked catalog drift, and both did their job.
What nothing looked at was `checks`, and a host does not import them - so
the integrations-acceptance VM test stopped evaluating at debda24 and CI
stayed green for weeks while the only test that proves the integrations was
unrunnable.

Two steps.

`nix flake check --no-build` on every push. Evaluation is where interface
drift shows, it is cheap, and it is exactly what was missing: run against
main today it fails, and against this branch it passes.

`nix flake check` on main and on the weekly schedule. A check that
evaluates and then fails is not caught by the first step, and the
acceptance test is what stands between a broken integration and a device in
a ring. Not on every push, because it boots a VM carrying a directory, a
vault client and four agents, on a runner that also images machines.

The attribute list is asserted non-empty first, so a flake that exposes no
checks fails loudly instead of reporting a pass on nothing - the same shape
the host step already uses.

Worth recording, because it changes where the blame sits: the catalog break
found the same day WAS caught by the existing regen-catalog.sh --check. It
reached nobody because the runner has been down since 21 August. That is an
availability problem, not a coverage one, and no workflow fixes it.
Some checks failed
ci / evaluate (push) Failing after 18s
ci / evaluate (pull_request) Failing after 0s
ci / update-owned-inputs (push) Has been skipped
ci / update-owned-inputs (pull_request) Has been skipped
This pull request can be merged automatically.
You are not authorized to merge this pull request.
View command line instructions

Checkout

From your project repository, check out a new branch and test the changes.
git fetch -u origin feat/osquery-integration:feat/osquery-integration
git switch feat/osquery-integration

Merge

Merge the changes and update on Forgejo.

Warning: The "Autodetect manual merge" setting is not enabled for this repository, you will have to mark this pull request as manually merged afterwards.

git switch main
git merge --no-ff feat/osquery-integration
git switch feat/osquery-integration
git rebase main
git switch main
git merge --ff-only feat/osquery-integration
git switch feat/osquery-integration
git rebase main
git switch main
git merge --no-ff feat/osquery-integration
git switch main
git merge --squash feat/osquery-integration
git switch main
git merge --ff-only feat/osquery-integration
git switch main
git merge feat/osquery-integration
git push origin main
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
bb-open/sextant-overlay-bbopen!3
No description provided.