mirror of
https://github.com/rcourtman/Pulse.git
synced 2026-10-13 15:51:39 +00:00
Make action runner rotation activation-safe
This commit is contained in:
@@ -196,12 +196,12 @@ or generic command path.
|
||||
| Platform or capability | Preferred boundary | Safe-profile behavior | Qualification and default implication | Residual owner and removal condition |
|
||||
|---|---|---|---|---|
|
||||
| Proxmox VE/PBS/PMG inventory, status, storage, and ordinary metrics | API-only connection with a narrowly scoped token; no host agent | No collector, helper, or runner authority is required for this data | Supported independently of the safe host-agent profile; it does not prove host-local SMART, LXC filesystem, or action parity | `agent-lifecycle`: keep API permissions and returned telemetry covered by provider tests |
|
||||
| Standard Linux systemd host telemetry and collector update | Unprivileged `pulse-agent` plus the root-owned typed helper | Core `/proc`, filesystem, network, RAID, and hwmon telemetry stays in the collector; signed update activation crosses the fixed helper transaction | **Qualified on disposable Ubuntu 24.04.4 arm64 at committed main** for install, migration, explicit/automatic rollback, update, helper health, reporting continuity, and process/credential separation. Remains opt-in pending exact-RC reproduction and external review | `deployment-installability` and `security-privacy`: reproduce the twelve-scenario receipt from the designated release candidate and accept the external boundary review |
|
||||
| Standard Linux systemd host telemetry and collector update | Unprivileged `pulse-agent` plus the root-owned typed helper | Core `/proc`, filesystem, network, RAID, and hwmon telemetry stays in the collector; helper-backed signed update activation is implemented but its live activation/recovery transaction is not qualified | **Qualified on disposable Ubuntu 24.04.4 arm64 at committed main** for install, migration, explicit/automatic profile rollback, helper health, reporting continuity, and process/credential separation. The receipt's ordinary update ran under the downgraded root monitoring profile and does not prove `agent_update.activate.v1`, executable-digest commit, watchdog rollback, interrupted recovery, or last-known-good restoration. Remains opt-in pending those live scenarios, exact-RC reproduction, and external review | `deployment-installability` and `security-privacy`: qualify helper activation/failure/recovery from the designated release candidate and accept the external boundary review |
|
||||
| Linux SMART telemetry | `smart.snapshot` through the no-network helper; no caller-selected device or arguments | Implemented, unqualified on representative physical disks. Helper failure omits/degrades SMART only; the collector does not retry as root | Does not yet justify SMART parity or a default change | `agent-lifecycle`: record live SATA, SAS/controller, USB bridge, and NVMe evidence, including standby, permission failure, timeout, and partial-data cases |
|
||||
| Proxmox node-local LXC filesystem telemetry | `proxmox.lxc_filesystems` through the no-network helper using fixed bounded `pct` operations | Implemented, unqualified on a representative PVE node. Helper failure omits/degrades this snapshot only | Does not yet justify Proxmox host-agent parity or a default change | `agent-lifecycle`: record live running/stopped LXC, mount, timeout, output-bound, and helper-loss behavior on supported PVE versions |
|
||||
| Rootful Docker or Podman inventory | No direct collector access to a root-equivalent daemon socket | **Unavailable in the safe profile.** Migration disables the provider visibly. A closed helper `container.inventory` operation exists, but collector integration and live parity are not qualified | Rootful container parity is an explicit default blocker; the legacy/root profile is not safe-profile evidence | `agent-lifecycle`: either integrate and qualify bounded helper inventory or retain the explicit degradation permanently |
|
||||
| Collector-owned rootless Docker or Podman | Direct access only to one usable runtime socket owned by the `pulse-agent` UID | Implemented, unqualified live. Ambiguous, root-owned, unreadable, unwritable, or unavailable sockets disable container monitoring | Does not yet justify container-runtime parity or a default change | `deployment-installability`: record fresh install, migration, restart, socket-loss, ambiguity, and telemetry parity on both rootless Docker and rootless Podman |
|
||||
| Separate runner package update and package-cache cleanup | Root-owned `pulse-agent-runner`, host-bound action credential, typed request, postcondition, and durable receipt | A real verified apt-cache mutation, stale-fingerprint refusal, replay, rotation, and self-revocation are qualified in the committed-main systemd receipt | Qualified only for the exercised apt-cache mutation; it does not qualify every runner operation or an exact release candidate | `agent-lifecycle` and `api-contracts`: reproduce from the RC and add representative package-update success/failure/cancellation evidence |
|
||||
| Separate runner package update and package-cache cleanup | Root-owned `pulse-agent-runner`, host-bound action credential, typed request, postcondition, and durable receipt | A real verified apt-cache mutation, stale-fingerprint refusal, replay, and self-revocation are present in the committed-main systemd receipt. Two-phase credential activation and nonce-bound readiness are implemented but need fresh production-path qualification | Qualified only for the exercised apt-cache mutation; the receipt does not prove the current Router/TLS/durable-persistence credential lifecycle, every runner operation, or an exact release candidate | `agent-lifecycle` and `api-contracts`: reproduce through the production Router over HTTPS from the RC, including failed activation/rollback and representative package-update success/failure/cancellation evidence |
|
||||
| Separate runner Proxmox guest and container lifecycle/update actions | Root-owned runner with closed typed protocols; never the monitoring collector | Implemented, unqualified on representative PVE and container-runtime targets | No live-provider action-parity claim and no default change | `agent-lifecycle`: record target-bound success, stale-state refusal, cancellation, reconnect/replay, and independent postconditions on disposable real targets |
|
||||
| Appliance, non-systemd, Windows, and macOS host-agent profiles | Platform API where sufficient; otherwise an explicitly named legacy/full-trust profile | **Unavailable for safe-profile apply.** The installer fails closed instead of silently installing a root-equivalent profile | Excluded from the Linux safe-profile claim | `deployment-installability`: land a platform-specific service, filesystem, update, helper, migration, rollback, and live-proof contract before marking that platform supported |
|
||||
|
||||
|
||||
@@ -106,18 +106,28 @@ proving generic command denial.
|
||||
The runner service persists the same normalized canonical hostname used when
|
||||
its credential was issued; it must not substitute the machine's incidental OS
|
||||
hostname when the collector was enrolled under an override. Credential
|
||||
rotation invalidates exactly the superseded organization/token/agent/hostname
|
||||
session only after the replacement token inventory is durably stored. That
|
||||
invalidation removes the session from dispatch, closes its transport, and
|
||||
unblocks server-side waits; an already-started host mutation remains governed
|
||||
by its typed receipt and best-effort cancellation semantics rather than being
|
||||
described as rolled back. Runner uninstall attempts an authenticated
|
||||
rotation is a prepare/commit transaction. Issuance stores a ten-minute pending
|
||||
replacement beside the active predecessor; the pending transport may register
|
||||
but is not dispatchable. The runner first durably replaces a private health
|
||||
marker carrying the current installer-generated activation nonce, then calls
|
||||
the authenticated activation method. Activation atomically removes the exact
|
||||
predecessor set, removes the replacement expiry/pending state, and promotes the
|
||||
exact registered session. Failure before that commit leaves the predecessor
|
||||
valid, while persistence failure restores both records. The installer removes
|
||||
the prior marker before restart, ignores wall-clock mtime as authority, and
|
||||
accepts only an activated marker whose nonce and canonical agent ID match the
|
||||
current attempt; rollback never restores a prior marker. An already-started
|
||||
host mutation remains governed by its typed receipt and best-effort
|
||||
cancellation semantics rather than being described as rolled back. Runner
|
||||
uninstall attempts an authenticated
|
||||
credential self-revoke before deleting local state. The delete route may
|
||||
remove only the caller's exact host-bound action-runner record; an unreachable
|
||||
server cannot prevent local runner removal and leaves an explicit operator
|
||||
revocation residual.
|
||||
Runner readiness is exposed through a bounded, secret-free health marker that
|
||||
is replaced atomically only after its contents reach stable storage. POSIX
|
||||
is replaced atomically only after its contents reach stable storage. The
|
||||
marker distinguishes registered/pending from activated and carries only the
|
||||
per-attempt nonce, never the bearer credential. POSIX
|
||||
targets must sync the containing directory after rename; Windows targets must
|
||||
use a write-through replacement rather than attempting to flush the read-only
|
||||
directory handle returned by the standard library. The marker and helper-update
|
||||
|
||||
@@ -39,12 +39,22 @@ monitored `agentId` / `hostname` pair and returns a new, separately persisted
|
||||
runtime role `action-runner`, binding version 1, and capability
|
||||
`typed_actions.v1`. The route re-resolves the pair against exactly one live,
|
||||
non-conflicted, non-integration host in the request tenant. Issuing again
|
||||
atomically replaces only the earlier action-runner record for that tenant and
|
||||
agent ID; a persistence failure restores the complete token inventory and
|
||||
returns no usable new secret. Only after that durable replacement may the
|
||||
server close the exact superseded live action-runner session, remove it from
|
||||
new dispatch, and unblock its outstanding server waits. The created response
|
||||
is non-cacheable.
|
||||
atomically prepares a ten-minute replacement beside the current active record;
|
||||
older unactivated replacements are removed, while persistence failure restores
|
||||
the complete token inventory and returns no usable new secret. The created
|
||||
response is non-cacheable and exposes the activation-pending state and
|
||||
deadline, not predecessor secrets.
|
||||
|
||||
`PATCH /api/agents/action-runner/credential` is the runner-owned activation
|
||||
commit. It requires the current `agent:exec` bearer, exact organization,
|
||||
canonical agent/hostname binding, and an exact registered pending transport.
|
||||
A pending transport is visible to this commit proof but unavailable to action
|
||||
dispatch. The commit clears the pending expiry, durably removes only the
|
||||
server-recorded predecessor IDs, restores the complete inventory on persistence
|
||||
failure, promotes the exact replacement session, and invalidates exact stale
|
||||
sessions without allowing a caller-selected token ID. Repeating activation for
|
||||
an already active exact session is idempotent so a lost HTTP response can be
|
||||
reconciled safely.
|
||||
|
||||
`DELETE /api/agents/action-runner/credential` is the runner's narrowly scoped
|
||||
self-revoke operation. It requires the current `agent:exec` bearer credential,
|
||||
|
||||
@@ -146,9 +146,14 @@ The same supported Linux systemd profile can install `pulse-agent-runner` only
|
||||
through the separate `--enable-action-runner` choice, a private token file,
|
||||
and the already selected typed helper profile. The runner binary, unit,
|
||||
configuration, credential, health record, and receipt database are root-owned
|
||||
and independent from collector state. Activation is transactional and restores
|
||||
the previous runner-only files if health does not become current; disable and
|
||||
uninstall remove only remediation and leave monitoring running. The action
|
||||
and independent from collector state. Activation is transactional: the server
|
||||
keeps the prior credential valid while a bounded replacement registers without
|
||||
dispatch authority; the runner durably writes an installer-nonce-bound health
|
||||
marker and commits activation before the installer removes backups. The
|
||||
installer deletes the prior marker before restart, does not trust filesystem
|
||||
timestamps, never restores a prior marker, and restores the previous runner-only
|
||||
files if the current nonce never reaches activated state. Disable and uninstall
|
||||
remove only remediation and leave monitoring running. The action
|
||||
credential is never placed in argv or reused as the collector token. The
|
||||
installer persists the canonical enrollment hostname for runner admission and
|
||||
uses a private curl configuration for best-effort exact self-revocation before
|
||||
|
||||
@@ -89,16 +89,21 @@ set, so `ProtectSystem=strict` is not a valid runner sandbox claim. Its separate
|
||||
credential, no-listener transport, typed admission, target and digest binding,
|
||||
bounded capabilities, state privacy, and durable receipts are the compensating
|
||||
boundary; collector and helper filesystem hardening remains independent.
|
||||
Action-runner issuance and rotation are one durable host-bound transition per
|
||||
organization and canonical agent ID. Re-issuance replaces the prior runner
|
||||
record even when the monitored hostname has changed, returns the new plaintext
|
||||
secret only after persistence succeeds, and restores the complete prior token
|
||||
inventory if persistence fails. A successful rotation invalidates the previous
|
||||
secret immediately; it never widens the collector credential or turns a
|
||||
monitoring session into an action session.
|
||||
Action-runner issuance and rotation are a two-phase durable host-bound
|
||||
transition per organization and canonical agent ID. Re-issuance prepares a
|
||||
ten-minute replacement credential while retaining the prior active record,
|
||||
returns the new plaintext secret only after persistence succeeds, and removes
|
||||
older unactivated replacements. The pending credential may authenticate one
|
||||
exact runner transport but cannot become dispatch authority. After the runner
|
||||
durably records its current activation nonce, its authenticated activation
|
||||
request atomically promotes the replacement and revokes the server-recorded
|
||||
predecessor set. A persistence failure restores both sides of the transition;
|
||||
an unactivated replacement expires without revoking the predecessor.
|
||||
That invalidation is exact and post-persistence: it matches organization,
|
||||
token, canonical agent, hostname, runtime role, and typed capability before
|
||||
closing the session, so a stale rotation cannot evict a replacement. The
|
||||
closing the session, so a stale rotation cannot evict a replacement. Activation
|
||||
is idempotent for the exact live session so transport-level response loss is
|
||||
recoverable. The
|
||||
runner may also delete only its own matching record using its bearer
|
||||
credential; browser sessions and a caller-selected token ID are rejected, and
|
||||
persistence failure restores the prior inventory. Installer teardown keeps the
|
||||
|
||||
@@ -34,10 +34,12 @@ preserves collector identity and installation files only; it must not rewrite
|
||||
storage/recovery evidence or reinterpret a restored legacy collector profile as
|
||||
recovery success. Typed `host.storage_cleanup` remains governed remediation,
|
||||
not storage-recovery authority inferred from the credential itself.
|
||||
Runner credential rotation follows the shared token-inventory commit boundary:
|
||||
failed persistence restores the complete prior inventory and returns no new
|
||||
secret, while successful persistence replaces the previous organization/agent
|
||||
binding and invalidates only that superseded live session. Exact bearer
|
||||
Runner credential rotation follows the shared two-phase token-inventory commit
|
||||
boundary: issuance durably prepares a bounded, non-dispatchable replacement
|
||||
without removing the active predecessor; activation after durable runner health
|
||||
proof promotes the exact registered replacement and removes only its recorded
|
||||
predecessor set. Failed persistence restores the complete inventory, and an
|
||||
unactivated replacement expires without changing the predecessor. Exact bearer
|
||||
self-revocation uses the same durable boundary and cannot select another token,
|
||||
organization, or host. That rollback protects restart-time
|
||||
credential truth only; it is not a customer backup, recovery point, restore
|
||||
|
||||
Reference in New Issue
Block a user