Ga naar inhoud

Auto-patch (opt-in per host)

Auto-patch laat monsys autonoom CVE’s afhandelen op hosts die het expliciet aanzetten. Zonder deze vlag doet monsys niets automatisch — dat is de default en de rest van het platform.

  • Hosts waar downtime van een minuut acceptabel is (install → optionele restart)
  • Hosts waar je vertrouwt op distro-maintainer QA (Ubuntu/Debian/RHEL security updates)
  • Fleet-lagen die je niet meer manueel wilt patchen (dev-boxes, staging, CI-runners)

Niet aanzetten op:

  • Productie-DB primaries (patch pas na canary)
  • Hosts waar app-restart een klant-facing hit is (gebruik dan de EAT-flow met maintenance window)
  • Kernel-updates (die zijn bewust NIET auto-patchable — reboot-risico)
CategorieBronEAT-actieRestart?
OS-packagesapt / dnf / apk / zypperinstall_package per (package, version)door package-manager afgehandeld
Application depsnpm / pip / composer / RubyGems / Goupdate_packages per (project, ecosystem)install-only in v1 — geen automatische service-restart
KernelNIET auto-patchable in v1

Filtering:

  • fixed_version IS NOT NULL — alleen CVE’s waar een fix bekend is
  • Severity ≥ ingestelde drempel (CRITICAL of CRITICAL+HIGH)
  • acknowledged_at IS NULL — CVE’s die de operator eerder heeft dismissed worden overgeslagen
  • Max 25 packages per host per cyclus — sanity-cap tegen runaway
  • Warmup: 2 minuten na hub-start
  • Interval: 30 minuten
  • Rate-limit per host: minstens 25 minuten sinds vorige tick
  • Hosts zonder open CVE’s worden ook getouched — last_run_at update voorkomt re-polling

Governance-tab op agent-detail → sectie Auto-patching (opt-in):

  1. Vink OS-packages en/of Application dependencies
  2. Kies minimum severity: CRITICAL of CRITICAL + HIGH
  3. Klik Opslaan (TOTP) — een dialoog vraagt je TOTP-code
  4. Bevestiging + tijdstempel verschijnt onder de sectie

Uitzetten kan zonder TOTP — de vlag terug op false zetten is per definitie een safe fallback.

Elke fase van auto-patch produceert een entry in de attestation chain.

WanneerEntry-kindPayload
Vlag geflipt op hostremediation.auto_flag_setos_packages, app_deps, min_severity, set_by, turned_on
Worker dispatches EATremediation.auto_proposedcategory, package, target_version, cve_id, severity, eat_nonce, flag_set_by, flag_set_at
Agent rapporteert succesremediation.auto_appliedeat_nonce, exit_code, note
Agent rapporteert rollbackremediation.auto_rolled_backidem, met exit-code ≠ 0 of rollback-note

Een externe auditor walkt van auto_appliedauto_proposed (via eat_nonce) → flag_set_byauto_flag_set (via subject_ref = agent_id). Zo is elke autonome patch cryptografisch verbonden met de user die de consent gaf.

Elke cyclus firet altijd een alert, ook bij succes:

  • infoAuto-patch dispatched: <pkg> → <version> bij elke EAT-uitgifte
  • warningAuto-patch rolled back bij restart-fail of non-zero exit

Zo zie je in de standaard alerts-view welke hosts autonoom draaien, ook als je nooit naar de attestation chain kijkt.

De wrappers op de agent (monsys-action install voor OS-packages, monsys-package-update voor app-deps) doen:

  1. Snapshot — lockfile + node_modules (of dpkg-status voor apt) worden bewaard
  2. Install — de gevraagde upgrade
  3. Restart (als restart_service gezet is) — bestaat niet in v1 auto-patch
  4. Rollback — als een restart faalt, roll back naar de snapshot

Als de install zelf faalt (dpkg-config-conflict, npm ERESOLVE): geen rollback nodig want er is niks gewijzigd. Non-zero exit-code komt terug via PostEmergencyResult en emit auto_rolled_back.

Kernel-updates vereisen een reboot om effect te hebben. Reboots hebben side-effects die de wrapper niet kan rollen back (services die niet automatisch startten, filesystem-mounts, netwerk-config). Het risico weegt niet op tegen het gemak — kernel-CVE’s zijn dringend genoeg dat een operator een handmatig TOTP kan doen via de kernel-CVE pipeline met canary + verify.

npm install swappt files op disk, maar het draaiende proces heeft de oude code al ingeladen. Een service-restart is nodig om de fix effectief te maken. In v1 is er geen automatische mapping van (project_path, ecosystem) → systemd-unit, dus we forceren niet een restart die verkeerd zou kunnen zijn. De patch staat wel klaar; de operator herstart wanneer het uitkomt. Later kan een restart_service-veld per project deze koppeling expliciet maken.

Verhouding tot Root/Aikido en OS auto-updates

Section titled “Verhouding tot Root/Aikido en OS auto-updates”
  • Root (Aikido) doet hardened container-images — dependency-level, drop-in vervanging. Complementair, niet concurrentie. Als je containers draait: Root voor de images, monsys voor de host.
  • Ubuntu unattended-upgrades / dnf-automatic patchen ook OS-packages, maar zonder attestation, zonder centralized policy, zonder rollback-alert-loop. Monsys auto-patch is bruikbaar op distros waar unattended-upgrades te weinig context geeft voor NIS2/CRA-audit.

agents heeft (mig 113):

auto_patch_os_packages BOOLEAN NOT NULL DEFAULT FALSE
auto_patch_app_deps BOOLEAN NOT NULL DEFAULT FALSE
auto_patch_min_severity TEXT NOT NULL DEFAULT 'HIGH'
CHECK IN ('CRITICAL', 'HIGH')
auto_patch_enabled_by UUID REFERENCES users(id)
auto_patch_enabled_at TIMESTAMPTZ
auto_patch_last_run_at TIMESTAMPTZ

De partial index idx_agents_auto_patch_enabled maakt de worker-query O(log n) op enabled-set, ongeacht totale fleet-grootte.

  • GET /api/v1/agents/:id/auto-patch — read (viewer role)
  • PATCH /api/v1/agents/:id/auto-patch — write (admin role + TOTP purpose agent_auto_patch)

Body:

{
"os_packages": true,
"app_deps": false,
"min_severity": "HIGH"
}

Alle drie velden zijn optioneel; alleen de aanwezige worden gewijzigd. enabled_by + enabled_at worden alleen bijgewerkt wanneer je een vlag aan zet — uitzetten laat die audit-velden staan zodat de laatste consent-actor traceerbaar blijft.