Watch
0
0
Fork
You've already forked hyperhive
0
hyperhive/nix/host-modules/glue-bao-readers-policy-order.nix
atlas c10cc0e018 swarm-nats: take the callout issuer and user keys from the store
`swarm-bao-nats-callout-xkey` runs `ensure-callout-keys`, importing
/var/lib/swarm-nats-callout/{issuer,callout-user}.seed when present so the
keys keep their public halves, then fetches all three public halves from
the store. The verb removes each seed file once a read of the store returns
a seed; when the store's seed differs, it is kept and a warning names the
file. No tmpfiles rule touches those files, since one could run before the
import with the store sealed and leave the next run to mint a new key.

The server renders the issuer and user public halves from the fetched files,
checked for shape as the xkey's is, and does not start without them. The
responder reads both seeds from the store, so the copies into the container
and their LoadCredential entries are gone, and a tmpfiles rule removes the
copies a container still holds. `swarm-nats-callout-keys` is removed.

On the store's host the fetch unit is also ordered after
`swarm-bao-secret-publisher-policy`, so the publisher's denial of the seed
paths is written before the unit creates or keeps a seed there.

`deploy.nats.autoGenerateCallout`, `calloutUserPublicKey`,
`calloutIssuerPublicKey`, `calloutUserSeedFile` and `calloutIssuerSeedFile`
are removed with `mkRemovedOptionModule`, under `swarm.nats` too, each
message saying the keys live in the store.
2026-10-06 14:53:33 +02:00

93 lines
3.6 KiB
Nix

# Glue: where the store and one of its readers share a host, the reader waits
# for the unit that writes the cert-auth role it logs in with, and for any
# other policy unit whose rules it relies on.
#
# ONE PAIRING PER FILE — the store's policy units ← the readers that rely
# on them, and nothing else. Deleting this leaves every reader as it is on a
# host whose store is remote: it may log in before its role exists, and its own
# retries are what carry it past that.
#
# ⚠️ Gated on BOTH the store and that reader being here. Off the store's host
# there is no local policy unit to order against. On the store's host without
# the reader, setting `systemd.services.<reader>.after` would define a unit
# with no ExecStart, so each gate below restates the one the reader's own
# module puts on it. A reader whose gate changes must change here too.
#
# Ordering, never a requirement: a policy unit that failed still counts as
# done, and the reader's own retries carry it past that. `wants` as well as
# `after`, so a reader started on its own pulls its policy unit into the same
# transaction.
{
lib,
config,
...
}:
let
hyperhiveCfg = config.services.hyperhive;
deployCfg = hyperhiveCfg.deploy;
baoDeploy = deployCfg.bao;
havePair = cert: key: cert != null && key != null;
# Reader unit → the gate its own module defines it under.
readersHere = {
# ./glue-queue-agent-credential.nix
swarm-bao-queue-agent =
deployCfg.hive-controller.enable
&& havePair baoDeploy.queueAgentClientCertFile baoDeploy.queueAgentClientKeyFile;
# ./swarm-grafana.nix
swarm-bao-grafana-oidc = deployCfg.grafana.enable;
# ./swarm-otel.nix
swarm-bao-otel-oidc =
deployCfg.swarm-otel.enable
&& havePair baoDeploy.otelOidcClientCertFile baoDeploy.otelOidcClientKeyFile;
# ./swarm-bao.nix: its block is gated on the store, which `orderAfterPolicies`
# already checks.
swarm-bao-forwarder-oidc = true;
# ./swarm-nats.nix: the queue's TLS leaf, not a secret, but the same wait.
swarm-bao-nats-tls = deployCfg.nats.enable;
# ./swarm-ci-runner.nix
swarm-bao-ci-runner = deployCfg.ci-runner.enable;
};
# Readers that log in under another unit's principal: reader unit → the
# gate its own module defines it under, and the policy units it waits for.
readersOfOtherPolicy = {
# ./swarm-nats.nix, under the queue responder's leaf.
swarm-bao-nats-auth-oidc = {
here = deployCfg.nats.enable;
policies = [ "swarm-bao-nats-auth-policy" ];
};
# ./swarm-nats.nix, under the same leaf. Also after the publisher's
# policy, which denies the publisher the callout seeds' paths: until it
# is written the publisher may create them, and this unit keeps a seed it
# finds there.
swarm-bao-nats-callout-xkey = {
here = deployCfg.nats.enable;
policies = [
"swarm-bao-nats-auth-policy"
"swarm-bao-secret-publisher-policy"
];
};
# ./hive-matrix.nix, under matrix-ctl's leaf.
swarm-bao-matrix-oidc = {
here = deployCfg.matrix.enable;
policies = [ "swarm-bao-matrix-ctl-policy" ];
};
};
orderAfterPolicies =
reader: here: policies:
lib.mkIf (baoDeploy.enable && here) {
systemd.services.${reader} = {
after = map (p: "${p}.service") policies;
wants = map (p: "${p}.service") policies;
};
};
in
{
config = lib.mkMerge (
lib.mapAttrsToList (reader: here: orderAfterPolicies reader here [ "${reader}-policy" ]) readersHere
++ lib.mapAttrsToList (reader: r: orderAfterPolicies reader r.here r.policies) readersOfOtherPolicy
);
}