drop the shared hive agent login
Every agent now connects to the queue and reads logs with its own secret from the store (#5181), so the per-hive `hive-<h>-agent` OIDC client has no reader left. Remove it end to end: - hive-c0re no longer forwards `hive-queue-agent-{secret,client-id}` into containers, and no longer forwards HIVE_AGENT_OIDC_TOKEN_ENDPOINT; the agent module that loaded them (nix/agent-modules/queue.nix) is gone, its options refused with a removal message. - The host reader (glue-queue-agent-credential.nix, swarm-bao-queue-agent), its store role and policy unit (swarm-bao-queue-agent-policy), its PKI leaf and the deploy.bao.queueAgent* / queue.agentCredentialDir options are gone; the options are refused with a removal message. - authelia mints no `hive-<h>-agent` client, and swarm-secret-publish no longer writes swarm/hives/<h>/queue/agent. - swarm-secret-client drops queue::agent_client_path / queue::Credential. - HIVE_AGENT_NATS_URL is now gated on the agents' queue address alone. The log store's authelia check stays for operators. swarm-nats-auth still refuses a `-agent` client id; that refusal and `agentClientSuffix` are left for a follow-up. Refs #4459 Refs #4765
This commit is contained in:
parent
d19bd83aa5
commit
868c6cf96c
41 changed files with 286 additions and 1410 deletions
|
|
@ -808,9 +808,9 @@ let
|
|||
}
|
||||
'';
|
||||
|
||||
# One gateway-leaf issuer per hive in the swarm directory, for the reason
|
||||
# `perHiveReaders` below is per hive. One name for the pki role, the policy
|
||||
# and the cert-auth role, as for the readers.
|
||||
# One gateway-leaf issuer per hive in the swarm directory: one subject for
|
||||
# every hive could ask for any hive's certificate. One name for the pki role,
|
||||
# the policy and the cert-auth role, as for the readers below.
|
||||
hiveLeafIssuers = lib.mapAttrsToList (hiveName: hive: {
|
||||
name = "${baoDeploy.hiveLeafPkiRolePrefix}-${hiveName}";
|
||||
cn = "${baoDeploy.hiveLeafCommonNamePrefix}-${hiveName}";
|
||||
|
|
@ -897,48 +897,21 @@ let
|
|||
# `swarm/agents/*` AND `swarm/hives/<hive>/*`, and nothing under
|
||||
# `swarm/services/`.
|
||||
# Principals presenting one certificate are ONE principal to bao, so sharing
|
||||
# the hive's leaf would give each of them everything that leaf reads: the
|
||||
# unit that fetches this hive's queue credential could fetch every agent
|
||||
# credential in the swarm, and a unit that fetches a service's OIDC client
|
||||
# secret could not fetch it at all, as that path is not the hive's to read.
|
||||
# the hive's leaf would give each of them everything that leaf reads: a unit
|
||||
# that fetches a service's OIDC client secret could fetch every agent
|
||||
# credential in the swarm, and could not fetch its own secret at all, as
|
||||
# that path is not the hive's to read.
|
||||
#
|
||||
# Each gets its own leaf, its own cert-auth role and a policy holding the
|
||||
# one `secret/data/…` path that principal's script actually names — spelled
|
||||
# to the LEAF rather than to a prefix, for the reason `matrixCtlPolicyText`
|
||||
# above gives for doing the same.
|
||||
#
|
||||
# ⚠️ The queue-credential reader is PER HIVE and the OIDC readers are not,
|
||||
# and that asymmetry is the shape of the paths rather than a preference. A
|
||||
# queue credential lives under `swarm/hives/<name>/`, and every hive runs a
|
||||
# reader for its own; an OIDC client secret lives under
|
||||
# `swarm/services/<client-id>/` and a swarm registers each of those exactly
|
||||
# once. A single role for a per-hive reader would have to name `hives/*` to
|
||||
# serve every hive — which would let one hive read another's queue
|
||||
# credential, a reach no hive needs.
|
||||
readStanza = path: ''
|
||||
path "${path}" {
|
||||
capabilities = ["read"]
|
||||
}
|
||||
'';
|
||||
|
||||
# One reader per hive in the swarm directory. Written from the directory
|
||||
# rather than from this host's own name because the policy is written where
|
||||
# the STORE is and the reader runs where its hive is, so this host's name is
|
||||
# not the reader's.
|
||||
perHiveReaders =
|
||||
{ rolePrefix, cnPrefix, ... }@spec:
|
||||
lib.mapAttrsToList (hiveName: _: {
|
||||
name = "${rolePrefix}-${hiveName}";
|
||||
cn = "${cnPrefix}-${hiveName}";
|
||||
policyText = readStanza (spec.path hiveName);
|
||||
}) hyperhiveCfg.swarm.hives;
|
||||
|
||||
queueAgentReaders = perHiveReaders {
|
||||
rolePrefix = "swarm-queue-agent";
|
||||
cnPrefix = baoDeploy.queueAgentCommonNamePrefix;
|
||||
path = h: "${credentialMountPath}/data/swarm/hives/${h}/queue/agent";
|
||||
};
|
||||
|
||||
# Singletons, so a list of one rather than a second shape: the granting unit
|
||||
# below takes a list either way and the units stay identical apart from
|
||||
# the objects they write.
|
||||
|
|
@ -1257,9 +1230,9 @@ let
|
|||
|
||||
# One unit per PRINCIPAL, not one unit for all of them: these names are
|
||||
# operator-facing strings, the same reason `swarm-bao-secret-publisher-policy`
|
||||
# below gives for not being more script inside the controller's unit. A hive
|
||||
# whose queue credential never arrives is diagnosed by the state of the unit named
|
||||
# after it.
|
||||
# below gives for not being more script inside the controller's unit. A
|
||||
# reader whose secret never arrives is diagnosed by the state of the unit
|
||||
# named after it.
|
||||
readerPolicyUnit =
|
||||
description: objects:
|
||||
granterPolicyUnit description (
|
||||
|
|
@ -1589,7 +1562,7 @@ in
|
|||
# `serverCaFile` live here too, and they are set by whoever authenticates TO
|
||||
# the store — which includes a host that runs none of it. A reader is defined
|
||||
# by holding a certificate the store accepts, never by sharing a host with
|
||||
# one; ./glue-queue-agent-credential.nix gates on exactly that and not on
|
||||
# one; ./swarm-otel.nix's store reader gates on exactly that and not on
|
||||
# `enable`.
|
||||
# Reading this block as store-runner-only is what makes an off-host reader
|
||||
# look inexpressible when it is already supported.
|
||||
|
|
@ -2102,28 +2075,6 @@ in
|
|||
'';
|
||||
};
|
||||
|
||||
queueAgentCommonNamePrefix = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "swarm-bao-queue-agent";
|
||||
example = "swarm-bao-queue-agent.svc";
|
||||
description = ''
|
||||
Prefix of the subject the store's per-hive queue-credential roles
|
||||
accept. The role for hive `h` accepts `<prefix>-h` and grants read on
|
||||
exactly `swarm/hives/h/queue/agent` — the client credential that hive's
|
||||
agent containers authenticate to the swarm queue with.
|
||||
|
||||
A **prefix** rather than one subject because every hive runs its own
|
||||
reader and the path it reads carries that hive's name. One subject for
|
||||
all of them would need a `hives/*` grant, which would let one hive read
|
||||
another hive's queue credential.
|
||||
|
||||
⚠️ Reserved as a hive name by ./swarm.nix, per hive, for the reason its
|
||||
fixed-subject siblings are: cert auth trusts the CA and
|
||||
`allowed_common_names` is the whole narrowing, so a hive whose own leaf
|
||||
carried one of these spellings would receive that grant.
|
||||
'';
|
||||
};
|
||||
|
||||
hiveLeafCommonNamePrefix = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "swarm-bao-hive-leaf";
|
||||
|
|
@ -2134,9 +2085,8 @@ in
|
|||
`<servicesPkiMountPath>/issue/<hiveLeafPkiRolePrefix>-h`, which issues
|
||||
for `h`'s domain and `*.` that domain and nothing else.
|
||||
|
||||
Per hive for the reason
|
||||
{option}`services.hyperhive.deploy.bao.queueAgentCommonNamePrefix` is:
|
||||
one subject for every hive could ask for any hive's certificate.
|
||||
Per hive because one subject for every hive could ask for any hive's
|
||||
certificate.
|
||||
|
||||
⚠️ Reserved as a hive name by ./swarm.nix, per hive, like its siblings.
|
||||
'';
|
||||
|
|
@ -2163,7 +2113,7 @@ in
|
|||
|
||||
Its grant is one path,
|
||||
`swarm/services/<grafana client id>/oidc/client`, and read only. Not
|
||||
per hive, unlike the two prefixes above: an OIDC client is registered
|
||||
per hive, unlike the prefix above: an OIDC client is registered
|
||||
once per swarm, so the path names the service and never a hive.
|
||||
|
||||
⚠️ Same collision as its siblings, and the same answer: ./swarm.nix
|
||||
|
|
@ -2206,37 +2156,6 @@ in
|
|||
'';
|
||||
};
|
||||
|
||||
queueAgentClientCertFile = lib.mkOption {
|
||||
type = lib.types.nullOr lib.types.str;
|
||||
default = null;
|
||||
example = "/var/lib/swarm-bao-pki/queue-agent.pem";
|
||||
description = ''
|
||||
Certificate the unit that fetches this hive's queue client credential
|
||||
presents to the store. Its subject must be
|
||||
`<queueAgentCommonNamePrefix>-<this hive's name>`; cert auth matches on
|
||||
the CN and the role accepts nothing else.
|
||||
|
||||
⚠️ **Not** {option}`services.hyperhive.deploy.bao.clientCertFile`.
|
||||
Pointing this at the hive's own leaf would evaluate, deploy and log in —
|
||||
and hand a unit that reads one credential a certificate that reads every
|
||||
agent credential in the swarm and this hive's own secrets.
|
||||
|
||||
No default here: ./glue-bao-tls.nix points it at the leaf it mints,
|
||||
wherever this host mints its own PKI. A deployment that reads a store on
|
||||
another host names it by hand, alongside the leaf itself.
|
||||
'';
|
||||
};
|
||||
|
||||
queueAgentClientKeyFile = lib.mkOption {
|
||||
type = lib.types.nullOr lib.types.str;
|
||||
default = null;
|
||||
example = "/var/lib/swarm-bao-pki/queue-agent-key.pem";
|
||||
description = ''
|
||||
Private key for
|
||||
{option}`services.hyperhive.deploy.bao.queueAgentClientCertFile`.
|
||||
'';
|
||||
};
|
||||
|
||||
grafanaOidcClientCertFile = lib.mkOption {
|
||||
type = lib.types.nullOr lib.types.str;
|
||||
default = null;
|
||||
|
|
@ -2246,8 +2165,10 @@ in
|
|||
to the store. Its subject must be
|
||||
{option}`services.hyperhive.deploy.bao.grafanaOidcCommonName`.
|
||||
|
||||
⚠️ Not the hive's own leaf, for the reason
|
||||
{option}`services.hyperhive.deploy.bao.queueAgentClientCertFile` gives.
|
||||
⚠️ **Not** {option}`services.hyperhive.deploy.bao.clientCertFile`.
|
||||
Pointing this at the hive's own leaf would evaluate, deploy and log in —
|
||||
and hand a unit that reads one secret a certificate that reads every
|
||||
agent credential in the swarm and this hive's own secrets.
|
||||
'';
|
||||
};
|
||||
|
||||
|
|
@ -2271,7 +2192,7 @@ in
|
|||
{option}`services.hyperhive.deploy.bao.otelOidcCommonName`.
|
||||
|
||||
⚠️ Not the hive's own leaf, for the reason
|
||||
{option}`services.hyperhive.deploy.bao.queueAgentClientCertFile` gives.
|
||||
{option}`services.hyperhive.deploy.bao.grafanaOidcClientCertFile` gives.
|
||||
'';
|
||||
};
|
||||
|
||||
|
|
@ -2295,7 +2216,7 @@ in
|
|||
{option}`services.hyperhive.deploy.bao.forwarderOidcCommonName`.
|
||||
|
||||
⚠️ Not the hive's own leaf, for the reason
|
||||
{option}`services.hyperhive.deploy.bao.queueAgentClientCertFile` gives.
|
||||
{option}`services.hyperhive.deploy.bao.grafanaOidcClientCertFile` gives.
|
||||
'';
|
||||
};
|
||||
|
||||
|
|
@ -3543,12 +3464,10 @@ in
|
|||
'';
|
||||
|
||||
# 🩸 The principals that each log in with a leaf of their own, not as the
|
||||
# hive. See the block around `perHiveReaders` for what each grant is and
|
||||
# why the first is per hive; the units are identical apart from the
|
||||
# objects they write, so the shape lives in `readerPolicyUnit` and the
|
||||
# difference is visible here in one line each.
|
||||
systemd.services.swarm-bao-queue-agent-policy = readerPolicyUnit "write the per-hive queue-credential bao policies and cert-auth roles" queueAgentReaders;
|
||||
|
||||
# hive. See the block around `readStanza` for what each grant is; the
|
||||
# units are identical apart from the objects they write, so the shape
|
||||
# lives in `readerPolicyUnit` and the difference is visible here in one
|
||||
# line each.
|
||||
systemd.services.swarm-bao-grafana-oidc-policy = readerPolicyUnit "write Grafana's OIDC-secret-reader bao policy and cert-auth role" grafanaOidcReaders;
|
||||
|
||||
systemd.services.swarm-bao-otel-oidc-policy = readerPolicyUnit "write the collector's OIDC-secret-reader bao policy and cert-auth role" otelOidcReaders;
|
||||
|
|
@ -3693,7 +3612,6 @@ in
|
|||
"swarm-bao-controller-policy.service"
|
||||
"swarm-bao-secret-publisher-policy.service"
|
||||
"swarm-bao-matrix-ctl-policy.service"
|
||||
"swarm-bao-queue-agent-policy.service"
|
||||
"swarm-bao-grafana-oidc-policy.service"
|
||||
"swarm-bao-otel-oidc-policy.service"
|
||||
"swarm-bao-forwarder-oidc-policy.service"
|
||||
|
|
|
|||
Loading…
Reference in a new issue