Skip to content

fix(agent,install): make a refused enrollment visible and bounded - #7077

Draft
geovannewashington wants to merge 15 commits into
masterfrom
fix/agent-enrollment-diagnostics
Draft

fix(agent,install): make a refused enrollment visible and bounded#7077
geovannewashington wants to merge 15 commits into
masterfrom
fix/agent-enrollment-diagnostics

Conversation

@geovannewashington

@geovannewashington geovannewashington commented Sep 11, 2026

Copy link
Copy Markdown
Member

Part of #7064. Covers tiers 1 and 2 only: the wedge becomes diagnosable and bounded. The recovery mechanism is still under discussion and is not here.

What

The agent and the installer now say what actually happened to an enrollment instead of predicting success.

Why

A device given a tenant ID that names no namespace retried a 404 forever while the installer had already reported a successful install. The only evidence was in the agent's own container log.

Changes

  • A malformed tenant ID is rejected at config load, whether it came from the environment or the persisted file.
  • The tenant's provenance (environment, file, pairing) is recorded and named in the refusal.
  • Device authorization stops retrying after a deadline (24h default, SHELLHUB_AUTHORIZATION_DEADLINE) instead of never.
  • An unchanged refusal resurfaces at warn level every 10 attempts rather than decaying to debug forever.
  • The fatal log names the tenant and its origin; it no longer dumps the install key.
  • The installer reports the real enrollment outcome where the runtime's output is readable, and names the command to inspect it where it is not.
  • Uninstall dispatches before any install work, and names the tenant file it leaves behind.

Testing

Go: 20 packages green, new cases for tenant validation, provenance, the refusal message and the retry deadline. Installer: 98 bats tests, shellcheck POSIX clean, syntax checked under dash and busybox ash.

Not yet done by hand: an end-to-end install against a live stack with a well-formed tenant ID naming no namespace.

A mistyped tenant reached the network and was retried forever, because the
server answers it with the same not-found it uses for a namespace that does not
exist yet. Validate at load instead, after the persisted tenant is adopted so a
corrupted tenant file is refused the same way.
Adopting a persisted tenant assigned it into the field the environment uses, so
nothing downstream could tell an operator's tenant from one the agent wrote. Any
recovery that clears a stale tenant has to, or a wrong server address would
destroy a valid enrollment. Recorded only; nothing branches on it yet.
The server answers the same 404 for a namespace that does not exist yet and one
that was deleted, so the agent waited forever on a change that could never come.
Retry as before until a deadline, then return the refusal. Default is a day,
long enough for a namespace created after a fleet rollout.
Severity decayed to debug after the first attempt, so an agent stuck on a
namespace that no longer exists looked exactly like an idle one. An unreachable
server resolves itself and can stay quiet; a refusal may never resolve, so raise
it back to warn every ten attempts.
The failure read "Failed to initialize agent" and dumped the whole
configuration, which named nothing useful and put the install key in the log.
Say which credential was refused and where it came from, and log the tenant and
its origin instead of the struct.
Devices are sometimes deployed well ahead of the namespace they enroll into, and
the default day is a guess rather than a rule. Leave it unset to keep the
client's default.
The summary read only the variables given to this run, so a machine wedged on a
stale tenant was told its enrollment was none, which is the opposite of what was
about to happen. A credential passed to this run still wins.
It does not override a persisted tenant. The guard above never passes an empty
value, and the agent treats absent and blank the same, adopting the persisted
tenant either way.
The tenant helpers were inserted between the comment and the function it
describes.
Uninstall named the private key but not the tenant beside it, so an operator who
cleaned up by hand cleaned the wrong file and the reinstall enrolled into the
same namespace. Reported, not removed: it is the operator's to keep.
Uninstall ran the version lookup, arch detection and settings summary
first, so it reported install findings and hit the network for nothing.
Detection and both dispatches move into functions so uninstall can run
detection alone.
@geovannewashington
geovannewashington force-pushed the fix/agent-enrollment-diagnostics branch from 80c0fdb to b6c54bc Compare September 11, 2026 19:11
The three credential branches printed a prediction and returned, so a
refused device still read as a successful install. Where the runtime's
output is reachable the installer now polls it briefly and reports what
happened; where it is not, it names the command to inspect instead of
claiming an outcome. A refusal is reported, not returned: the agent is
installed and still retrying, so there is nothing to undo.
Adding the observe step split enroll_agent_interactively from its
parameter block again. The unquoted log command in observe_enrollment is
deliberate, so its doc block now says so; the unexported connectivity
const loses a comment code-style does not allow.
The pairing-code and install-key branches were only covered through
observe_enrollment itself, and the tenant file uninstall names was only
covered for docker.
The validator reports Go field names and rule names, so a typo surfaced
as 'TenantID=uuid' over two log lines. It now reads
'SHELLHUB_TENANT_ID must be a UUID', once. Values are never echoed:
InstallKey and SingleUserPassword pass through the same map.
@geovannewashington
geovannewashington force-pushed the fix/agent-enrollment-diagnostics branch from b6c54bc to f75192d Compare September 11, 2026 19:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant