diff --git a/nix/host-modules/swarm-authelia-service.nix b/nix/host-modules/swarm-authelia-service.nix index 0f7feee8..53dbeb7d 100644 --- a/nix/host-modules/swarm-authelia-service.nix +++ b/nix/host-modules/swarm-authelia-service.nix @@ -75,21 +75,15 @@ in type = lib.types.bool; default = true; description = '' - Mint machine clients per hive in + Mint one machine client per hive in {option}`services.hyperhive.swarm.hives`, so each hive can - authenticate to swarm services as itself: `hive-` for the - hive's own daemons, and `hive--agent` for the agent containers - running on it. + authenticate to swarm services as itself: `hive-`, for the + hive's own daemons. - Two clients rather than one because they are not the same - principal — a hive's daemons run on the host and an agent runs - in a container the host hands a credential to, so a swarm - service has to be able to grant them different things. It is - one client per *hive* on the agent side, not per agent: agents - are created at runtime, and a per-agent client would make - creating one a config change plus an authelia reload. The cost - is that agents on a hive are indistinguishable from each other, - tracked as a follow-up rather than papered over. + Agent containers get no client here: agents are created at runtime, + and a per-agent client would make creating one a config change plus + an authelia reload. An agent authenticates with its own secret from + the swarm store instead. On by default: a swarm's hives have identities, and that is a fact about the swarm rather than about any one host. It does not diff --git a/nix/host-modules/swarm.nix b/nix/host-modules/swarm.nix index b7e287c0..e01cc179 100644 --- a/nix/host-modules/swarm.nix +++ b/nix/host-modules/swarm.nix @@ -360,8 +360,9 @@ in fragments = reservedFragments; why = '' Hive-scoped identifiers are composed from a hive name — - `hive-`, `hive--agent` — so a name containing one of - these produces an identifier that is also somebody else's. The + `hive-`, and that id with a suffix the queue's responder + refuses — so a name containing one of these produces an identifier + that is also somebody else's, or one the responder refuses. The failure is a wrong grant rather than an error: the client authenticates and receives another principal's permissions, and a NATS denial arrives as a timeout. Rename the hive. diff --git a/nix/reserved-hive-fragments.nix b/nix/reserved-hive-fragments.nix index f13b8e88..e418a01f 100644 --- a/nix/reserved-hive-fragments.nix +++ b/nix/reserved-hive-fragments.nix @@ -9,8 +9,8 @@ # `hive-` — every hive's OIDC client id, and the string the queue's # auth-callout responder strips to decide which hive a connection is. "hive" - # `hive--agent` — the client its agent containers present. A hive named - # `foo-agent` mints exactly the id hive `foo`'s agents do. + # `hive--agent` — an id the queue's responder refuses. A hive named + # `foo-agent` would mint exactly that id for itself. "agent" # Also an exact-match entry next door, for the collector's `/` # components. Here because it is the word this swarm composes identifiers diff --git a/swarm-nats-auth/src/main.rs b/swarm-nats-auth/src/main.rs index ef44589f..39cd2571 100644 --- a/swarm-nats-auth/src/main.rs +++ b/swarm-nats-auth/src/main.rs @@ -125,15 +125,10 @@ struct Args { #[arg(long, default_value = "hive-")] hive_client_prefix: String, - /// Suffix that marks an agent container, appended to the hive's own client - /// id: `swarm-authelia.nix` mints one machine client per roster entry as - /// `hive--agent` — per **hive**, not per agent, because agents are - /// created at runtime and a per-agent client would make creating one a - /// config change plus a reload. - /// - /// So this identity says which hive an agent belongs to and never which - /// agent: two agents on one hive are indistinguishable under it. The - /// responder refuses it; the suffix is what tells it apart from a hive. + /// Suffix appended to a hive's own client id: `hive--agent`. No + /// client is minted with it — agents authenticate with their own secret — + /// so the responder refuses it; the suffix is what tells such an id apart + /// from the hive `-agent`. /// /// A suffix on the hive's id rather than a prefix of its own, because /// `agent-` reads as *the agent called ``* — the one thing @@ -413,8 +408,8 @@ impl Responder { }; // The caller is an identifier, not a credential: a client id, or // `agent:` for an agent token. One line per auth request, a connect - // or a reconnect, so `hive--agent` lines count requests made on a - // hive's shared credential, not agents. + // or a reconnect, so a `hive-` line counts requests made on + // a hive's own credential. tracing::info!( user_nkey = %req.user_nkey, server_id = %req.server_id.id, diff --git a/swarm-nats-auth/src/policy.rs b/swarm-nats-auth/src/policy.rs index 05bd88ee..2cb41226 100644 --- a/swarm-nats-auth/src/policy.rs +++ b/swarm-nats-auth/src/policy.rs @@ -63,7 +63,7 @@ const AGENT_PLACEHOLDER: &str = "{agent}"; impl Policy { /// `hive_prefix` is the client-id prefix that marks a hive and - /// `agent_suffix` what a hive's agent containers carry **on top of** it — + /// `agent_suffix` the suffix the responder refuses **on top of** it — /// `hive-` and `hive--agent`. `bucket` is the KV bucket hives /// report status in, `readers` the client ids allowed to read every hive's /// key, and `extra_hive_subjects` additional subjects a hive may publish to diff --git a/swarm-secret-client/src/policy.rs b/swarm-secret-client/src/policy.rs index 6b721391..9f8ce2ac 100644 --- a/swarm-secret-client/src/policy.rs +++ b/swarm-secret-client/src/policy.rs @@ -65,8 +65,9 @@ pub fn hive_object_name(hive: &str) -> Result { /// `hive-`, so a collision needs a hive named `agent-` — and /// `nix/reserved-hive-fragments.nix` forbids the substring `agent` in any hive /// name (and `hive` too), applied to every entry of the swarm directory in -/// `swarm.nix`. That guard was written for the queue's `hive--agent` -/// client ids; this is a second identifier family leaning on it, which is why +/// `swarm.nix`. That guard also keeps a hive's client id clear of the +/// `hive--agent` form the queue refuses; this is a second identifier +/// family leaning on it, which is why /// the fragment list is what to read before renaming either. /// /// Host principals' **common names** are operator-set options