say that the backend env leaf and file are agent-writable, and why that is accepted
This commit is contained in:
parent
75e9e205e3
commit
be3a3af093
4 changed files with 22 additions and 4 deletions
|
|
@ -305,7 +305,11 @@ The file lives in the agent's bind-mounted **harness** dir, not `state/`
|
||||||
— `harness/` survives container rebuilds exactly like `state/` does, but
|
— `harness/` survives container rebuilds exactly like `state/` does, but
|
||||||
(unlike `state/`) is never bind-mounted into a parent agent's container
|
(unlike `state/`) is never bind-mounted into a parent agent's container
|
||||||
(see `docs/agent-lifecycle/persistence.md`'s "Parent access to child state"), so an API
|
(see `docs/agent-lifecycle/persistence.md`'s "Parent access to child state"), so an API
|
||||||
key placed here is reachable by nothing but this agent and the host.
|
key placed here is reachable by nothing but this agent and the host. The
|
||||||
|
file doesn't stay root-owned, though: the container's activation chowns the
|
||||||
|
whole harness dir to the agent, so after the next boot the file is agent-owned
|
||||||
|
whatever owner you installed it with, and the agent can rewrite it. That holds
|
||||||
|
until the swarm secret store replaces the file.
|
||||||
|
|
||||||
<!-- vale write-good.Passive = NO -->
|
<!-- vale write-good.Passive = NO -->
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -192,7 +192,10 @@ in
|
||||||
read-write for recovery — see `docs/agent-lifecycle/persistence.md`'s "Cross-agent access to
|
read-write for recovery — see `docs/agent-lifecycle/persistence.md`'s "Cross-agent access to
|
||||||
state"), so this credential is reachable by nothing but this agent
|
state"), so this credential is reachable by nothing but this agent
|
||||||
and the host. Permissions should be `0600`, owned by the agent's
|
and the host. Permissions should be `0600`, owned by the agent's
|
||||||
unix user. Loaded with a leading `-` (optional `EnvironmentFile`),
|
unix user. Whatever owner it was installed with, the file becomes
|
||||||
|
agent-owned at the container's next boot, so the agent can rewrite it;
|
||||||
|
it is no boundary the agent can't cross until the swarm secret store
|
||||||
|
replaces the file. Loaded with a leading `-` (optional `EnvironmentFile`),
|
||||||
so a path that doesn't exist yet — an operator setting this option
|
so a path that doesn't exist yet — an operator setting this option
|
||||||
before creating the file, or a fresh host rebuild before state is
|
before creating the file, or a fresh host rebuild before state is
|
||||||
restored — makes systemd skip it rather than refuse to start the
|
restored — makes systemd skip it rather than refuse to start the
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,12 @@
|
||||||
# systemd lets a later file override an earlier one, so the store's value wins
|
# systemd lets a later file override an earlier one, so the store's value wins
|
||||||
# when there is one, and the file carries the agent when the store is down.
|
# when there is one, and the file carries the agent when the store is down.
|
||||||
#
|
#
|
||||||
|
# The leaf's create grant cannot constrain content, so while the leaf is empty
|
||||||
|
# the agent's own process can also create it with any text, and the store's
|
||||||
|
# value then wins over the file. That is no wider than the file the agent
|
||||||
|
# already owns: `./user.nix`'s `heal_own_dir` chowns the harness dir to the
|
||||||
|
# agent at every activation, a gap the issue tracker has an open bug for.
|
||||||
|
#
|
||||||
# The unit runs as root because the file is root-owned `0600` where an operator
|
# The unit runs as root because the file is root-owned `0600` where an operator
|
||||||
# placed it. Root can still read the agent's `0400` store identity.
|
# placed it. Root can still read the agent's `0400` store identity.
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -205,8 +205,13 @@ const ENTITY_NAME_TEMPLATE: &str = "{{identity.entity.name}}";
|
||||||
///
|
///
|
||||||
/// The one write is `create` on the agent's own [`backend_env`] leaf, without
|
/// The one write is `create` on the agent's own [`backend_env`] leaf, without
|
||||||
/// `update`: the agent seeds it from the file it has today, once, and cannot
|
/// `update`: the agent seeds it from the file it has today, once, and cannot
|
||||||
/// replace it. Any other write would let an agent hand itself an identity it
|
/// replace it. The stanza cannot constrain the content, and the agent's own
|
||||||
/// was never issued. An agent has no business with another agent's
|
/// process holds the identity, so while the leaf is empty it can also create it
|
||||||
|
/// with any text, and the store's value then wins over the file. That is no
|
||||||
|
/// wider than the harness-dir file the agent already owns:
|
||||||
|
/// `nix/agent-modules/user.nix`'s `heal_own_dir` chowns that dir to the agent at
|
||||||
|
/// every activation, a gap the issue tracker has an open bug for. Any other
|
||||||
|
/// write would let an agent hand itself an identity it was never issued. An agent has no business with another agent's
|
||||||
/// credentials, a hive's, a service's, or the controller's, so none of
|
/// credentials, a hive's, a service's, or the controller's, so none of
|
||||||
/// [`render_shared_hives`]'s breadth applies. A hive still reads this
|
/// [`render_shared_hives`]'s breadth applies. A hive still reads this
|
||||||
/// agent's secrets, and closing that is its own decision.
|
/// agent's secrets, and closing that is its own decision.
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue