`become` runs a second agent under `sudo`
| Status | Date |
|---|---|
| accepted; the bound on live connections is superseded by ADR 0005 | 2026-09-09 |
Context
Section titled “Context”Ansible escalates privileges per task, wrapping each module invocation in sudo. Volant runs tasks through a long-lived agent per host, so wrapping each task would mean either an agent that calls sudo for every module, or an agent that is itself privileged for the whole play.
Decision
Section titled “Decision”The controller opens one agent connection per (host, target user). A task with become runs through the agent started as sudo -H <form> -u <user> -- volant-agent, where <form> is -n or -k -S -p '' as the probe described below decides; tasks without it keep the unprivileged agent. Only sudo is supported; other methods are not supported yet and stop the run. The agent itself does not know about escalation.
Consequences
Section titled “Consequences”- A change of target user between two consecutive tasks ends the batch; the common case, a whole play under
become, keeps one batch. - The form of the
sudoinvocation is settled by a probe, not by whether a password was supplied. Asudothat needs no authentication does not read its standard input, so on a host with a cached authentication or aNOPASSWDrule, a password written there is left on the pipe and the agent reads it as the header of its first frame. The controller therefore askssudo -nfirst and only falls back tosudo -k -S -p ''oncesudohas itself rejected the request for want of authentication. Guessing the form from the password alone hangs the link, and only on the second escalated connection inside the timestamp window, which is why the probe is not optional. - The password, when one is given, is written once to
sudo’s standard input and never appears in a command line, a log or a result. The two types that carry it have hand-writtenDebugimplementations that print<redacted>, so a-vvvdump cannot leak it, andsudo’s own captured standard error is scrubbed of it before it can reach a message. - A failed escalation is a failed task, not an unreachable host: the connection worked.
- Live agent connections per host are not bounded.
forksbounds how many hosts run at once, not how many links one host holds, and the map keeps one link per distinct target user until the recap, each of them a separatesshprocess. An escalated link also costs one extrasshconnection for the probe, two when a password is wanted. This decision adds no connection multiplexing: every link is its ownsshprocess, and a wide inventory pays for each of them separately. su,doas,pbrunand the rest can be added as other ways to start the agent, without a protocol change.