feat(nix): the matrix container gets the swarm-internal trust anchor
`security.pki.certificateFiles` is read when the system is BUILT and the
swarm root is deliberately a runtime file (its key must never enter the
world-readable store), so there was nothing build-time to name and the
container trusted no swarm-internal CA. Federation with a peer whose
cert chains to the swarm root did not validate.
The bridge already existed: `lib/hive-ca-trust.nix`, which `hive-ci` and
`hive-forge` both cross. This wires the matrix container to it -- read-only
bind of the trust bundle, container ordered after `hive-tls-ca.service` --
rather than inventing a second mechanism.
Consumption is the per-runtime half, and it is not what it looks like.
tuwunel links no openssl, which makes `SSL_CERT_FILE` appear inapplicable.
It isn't: the outbound client is `reqwest` with the `rustls` feature,
which builds a `rustls_platform_verifier::Verifier`, and because tuwunel
calls `tls_certs_merge` (additive) rather than `tls_certs_only`, the
platform roots stay alongside its compiled-in webpki set. On Linux that
verifier resolves through `rustls-native-certs` to `openssl-probe`, which
reads `SSL_CERT_FILE`. Established by reading tuwunel 1.8.0 and reqwest
0.13.4 source, not inferred from the feature list -- an earlier reading of
mine concluded the opposite from the absence of a `native-roots` feature
name and was wrong.
The variable therefore names a CONCATENATION (system CAs + the bundle),
never the anchor alone: `openssl-probe` uses it *instead of* the default
store, so pointing it at the bundle would drop every public CA and break
federation with the wider matrix network -- trading a small outage for a
much larger one.
`container@hive-matrix` needed `mkMerge`: it already assigned `after` for
the gateway ordering and the helper contributes its own `after`/`requires`,
so two bare assignments would have conflicted rather than combined.
⚠️ Gate honesty: `state/eval-3093.sh` proves the mount, the ordering, the
bundle service and the env var are RENDERED -- 6 probes, including two
separate absence probes (mount and consumption are wired at different
sites, and the gateway outage happened precisely because two of three
sites tolerated a missing cert and the third did not). It CANNOT prove
tuwunel loads them: a build that ignores the variable evaluates
identically to one that honours it, and the chain above is
version-specific. That half wants an executed check on a real deploy.
This commit is contained in:
parent
2024848251
commit
038d085001
2 changed files with 89 additions and 25 deletions
|
|
@ -148,11 +148,26 @@ Two consumers, and only one of them is fine:
|
|||
`HIVE_TLS_CA_PATH`, and the meta-flake renderer embeds that one file
|
||||
next to every agent's flake. The bundle is the runtime-to-build-time
|
||||
bridge.
|
||||
- **The Matrix container is not.** It has no equivalent bridge, so it
|
||||
trusts no swarm-internal CA and federation with a self-signed peer
|
||||
does not validate. Giving it the root needs a runtime mechanism —
|
||||
bind-mount plus a bundle assembled at unit start, appending to the
|
||||
system bundle rather than replacing it — which is tracked separately.
|
||||
- **The Matrix container crosses the same bridge**, via the shared
|
||||
`lib/hive-ca-trust.nix` helper that `hive-ci` and `hive-forge` already
|
||||
use: the bundle is bind-mounted read-only into the container, and a
|
||||
oneshot concatenates it with the system CAs before tuwunel starts.
|
||||
|
||||
The consumption differs per runtime and is the part worth knowing.
|
||||
tuwunel links no openssl, which makes `SSL_CERT_FILE` look inapplicable
|
||||
— it isn't. Its outbound client is `reqwest` with the `rustls` feature,
|
||||
which builds a `rustls_platform_verifier::Verifier`; because tuwunel
|
||||
calls `tls_certs_merge` (additive) rather than `tls_certs_only`, the
|
||||
platform roots stay alongside its compiled-in webpki set. On Linux that
|
||||
verifier resolves through `rustls-native-certs` → `openssl-probe`,
|
||||
which reads `SSL_CERT_FILE`.
|
||||
|
||||
> ⚠️ **Concatenate; never point `SSL_CERT_FILE` at the anchor alone.**
|
||||
> `openssl-probe` uses it *instead of* the default store, so naming
|
||||
> just the bundle would drop every public CA and break federation with
|
||||
> the wider matrix network — a much bigger outage than the one being
|
||||
> fixed. The same caveat applies to `hive-forge` (Go) for the same
|
||||
> reason.
|
||||
|
||||
To put the root on another host, copy the certificate to the same path
|
||||
there (`scp <stateDir>/root.pem <host>:<stateDir>/root.pem`). One anchor
|
||||
|
|
|
|||
Loading…
Reference in a new issue