fix(ops-agent): perms-check en deploy-smoke waren allebei structureel vals-rood #144

Merged
janpeter merged 2 commits from fix/agent-secret-perms-mask-and-smoke-retry into main 2026-08-20 08:50:11 +02:00
Owner

Twee losstaande, elk eenregelige defecten in de ops-agent — beide gemeten, niet afgeleid.

1. De perms-check verwerpt de modus die hij voorschrijft

ops-agent/src/auth.ts maskerde met 0o177. Die mask bevat de group-read-bit (0o040) — precies de bit die het voorgeschreven 0640 heeft, en die de agent nodig heeft: het secret is root:ops-agent 0640 en de agent draait als user ops-agent, dus hij leest via de groep.

0640 & 0o177 = 0o040 ≠ 0 → waarschuwing, altijd. Alleen 0600/0400 zweeg, en dat maakt het secret onleesbaar voor de agent. De waarschuwing was dus door geen enkele correcte configuratie te stillen.

Nieuw masker 0o137: 0600 stil, 0640 stil, 0644/0660/0666 waarschuwen nog steeds. De guard blijft dus een world-readable secret vangen.

Gemeten vóór de fix: srv 17× in 30 dagen, max2 8× — beide hosts, beide met een bestand dat exact 0640 root:ops-agent is.

2. curl_smoke_ops_dashboard verliest de startrace systematisch

Uit het Caddy-access-log van de deploy van 2026-08-20:

moment (UTC) gebeurtenis
06:23:47.644 container StartedAt
06:23:47.876 502 op /login, duur 0,0008 s ← de smoke-stap
06:23:48.365 Next: Ready in 0ms — pas nú luistert de app

De stap vuurt 0,23 s ná containerstart en 0,49 s vóórdat de app luistert. Caddy kan niet dialen → 502 → curl -sf exit 22. De volgorde is machine-getimed, dus dit wordt structureel verloren; beide vastgelegde uitvoeringen (2026-08-02 en 2026-08-20) staan op exit 22.

Fix: --retry 5 --retry-delay 2 --retry-max-time 30; curl herprobeert 5xx vanzelf. --max-time 10 blijft per poging gelden.

Alle drie de repo-kopieën van de key gaan mee, zodat deploy/ops-agent/baseline/commands.yml byte-identiek blijft aan de live whitelist en check-ops-agent-drift.sh niet vals rood slaat.

Opgemerkt, bewust niet meegenomen

  • De stap is in de praktijk nauwelijks zichtbaar: van de 68 update_ops_dashboard-runs heeft er 1 een stap-8-rij, omdat de flow bij docker_compose_up zijn eigen FlowStep-schrijver omlegt. De retry maakt de stap zinvol; het auditgat is een apart probleem.
  • max2's curl_smoke_ops_dashboard wijst naar https://ops.jp-visser.nl/login — dus naar de dashboard van srv, niet naar zijn eigen instance. Daar raakt deze race hem niet, maar het is wel een aparte bug.
Twee losstaande, elk eenregelige defecten in de ops-agent — beide gemeten, niet afgeleid. ## 1. De perms-check verwerpt de modus die hij voorschrijft `ops-agent/src/auth.ts` maskerde met `0o177`. Die mask bevat de **group-read-bit** (`0o040`) — precies de bit die het voorgeschreven `0640` heeft, en die de agent nodig heeft: het secret is `root:ops-agent 0640` en de agent draait als user `ops-agent`, dus hij leest via de groep. `0640 & 0o177 = 0o040 ≠ 0` → waarschuwing, altijd. Alleen `0600`/`0400` zweeg, en dat maakt het secret onleesbaar voor de agent. De waarschuwing was dus door geen enkele correcte configuratie te stillen. Nieuw masker `0o137`: `0600` stil, `0640` stil, `0644`/`0660`/`0666` waarschuwen nog steeds. De guard blijft dus een world-readable secret vangen. Gemeten vóór de fix: srv 17× in 30 dagen, max2 8× — beide hosts, beide met een bestand dat exact `0640 root:ops-agent` is. ## 2. `curl_smoke_ops_dashboard` verliest de startrace systematisch Uit het Caddy-access-log van de deploy van 2026-08-20: | moment (UTC) | gebeurtenis | |---|---| | 06:23:47.644 | container `StartedAt` | | **06:23:47.876** | **502 op `/login`, duur 0,0008 s** ← de smoke-stap | | 06:23:48.365 | Next: `Ready in 0ms` — pas nú luistert de app | De stap vuurt 0,23 s ná containerstart en 0,49 s vóórdat de app luistert. Caddy kan niet dialen → 502 → `curl -sf` exit 22. De volgorde is machine-getimed, dus dit wordt structureel verloren; beide vastgelegde uitvoeringen (2026-08-02 en 2026-08-20) staan op exit 22. Fix: `--retry 5 --retry-delay 2 --retry-max-time 30`; curl herprobeert 5xx vanzelf. `--max-time 10` blijft per poging gelden. Alle drie de repo-kopieën van de key gaan mee, zodat `deploy/ops-agent/baseline/commands.yml` byte-identiek blijft aan de live whitelist en `check-ops-agent-drift.sh` niet vals rood slaat. ## Opgemerkt, bewust niet meegenomen - De stap is in de praktijk nauwelijks zichtbaar: van de 68 `update_ops_dashboard`-runs heeft er **1** een stap-8-rij, omdat de flow bij `docker_compose_up` zijn eigen `FlowStep`-schrijver omlegt. De retry maakt de stap zinvol; het auditgat is een apart probleem. - max2's `curl_smoke_ops_dashboard` wijst naar `https://ops.jp-visser.nl/login` — dus naar de dashboard van **srv**, niet naar zijn eigen instance. Daar raakt deze race hem niet, maar het is wel een aparte bug.
De check maskeerde met 0o177. Die bitmask bevat group-read (0o040) — precies de
bit die het voorgeschreven 0640 heeft en die de agent NODIG heeft: het secret is
root:ops-agent 0640 en de agent draait als ops-agent, dus hij leest het bestand
via de groep. Gevolg: bij elke start "loose permissions — expected 0640" op een
bestand dat exact 0640 is. Alleen 0600/0400 zweeg, en dat maakt het secret
onleesbaar voor de agent — de waarschuwing was dus door geen enkele correcte
configuratie te stillen.

Masker wordt 0o137: group-read toegestaan, group-write/execute en elke
other-bit verworpen. 0600 en 0640 zwijgen; 0644, 0660 en 0666 waarschuwen nog
steeds, dus de guard blijft doen waarvoor hij bedoeld is.

Gemeten op beide hosts vóór de fix: srv 17x in 30 dagen, max2 8x.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
fix(ops-agent): smoke-stap van update_ops_dashboard verliest de startrace
All checks were successful
CI / Root app checks (pull_request) Successful in 5m42s
CI / Ops-agent checks (pull_request) Successful in 15s
CI / Deploy artifact checks (pull_request) Successful in 12s
CI / Docker image build (pull_request) Successful in 1m18s
2f1346f01d
curl_smoke_ops_dashboard draait direct na docker_compose_up en doet exact een
poging zonder retry. Gemeten tijdens de deploy van 2026-08-20 (Caddy-access-log):

  06:23:47.644  container StartedAt
  06:23:47.876  502 op /login, duur 0,0008 s   <- de smoke-stap
  06:23:48.365  Next: Ready in 0ms             <- pas nu luistert de app

De stap vuurt 0,23 s na containerstart en 0,49 s voordat de app luistert; Caddy
kan niet dialen en geeft 502, curl -sf eindigt op 22. De volgorde is
machine-getimed, dus die race wordt systematisch verloren — beide vastgelegde
uitvoeringen (2026-08-02 en 2026-08-20) staan op exit 22.

Niet alleen cosmetisch: de stap kan per definitie niet slagen, dus hij levert
nul signaal over een deploy die hij wel geacht wordt te bewaken.

Fix: --retry 5 --retry-delay 2 --retry-max-time 30 (curl herprobeert 5xx
vanzelf), --max-time 10 blijft per poging gelden.

Alle drie de repo-kopieen van de key mee, zodat de baseline byte-identiek blijft
aan de live whitelist en check-ops-agent-drift.sh niet vals rood slaat.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
s4m-codex-reviewer left a comment

Verdict: APPROVED

Geen gekoppeld plan gevonden — beoordeeld op codekwaliteit + product-standaarden.

Findings

Geen blokkerende of niet-blokkerende findings gevonden.

De wijziging houdt de deploy-command varianten consistent en corrigeert de permissiecheck zodat de gedocumenteerde/verwachte 0640-secret niet langer als te ruim wordt gemeld, terwijl owner-execute, group-write/execute en alle other-bits nog steeds worden afgekeurd.

# Verdict: APPROVED Geen gekoppeld plan gevonden — beoordeeld op codekwaliteit + product-standaarden. ## Findings Geen blokkerende of niet-blokkerende findings gevonden. De wijziging houdt de deploy-command varianten consistent en corrigeert de permissiecheck zodat de gedocumenteerde/verwachte `0640`-secret niet langer als te ruim wordt gemeld, terwijl owner-execute, group-write/execute en alle other-bits nog steeds worden afgekeurd.
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
2 participants
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
janpeter/Ops-dashboard!144
No description provided.