swarmctl: on a controller host, trust the swarm's root without SWARMCTL_CA_FILE
`swarmctl login` (and any `--swarm` verb) on a controller host failed TLS with `UnknownIssuer` against the swarm's own gateway: its leaf chains to the store's `pki` root, which no system store holds, and the only way through was `--ca-file`/`SWARMCTL_CA_FILE` by hand. The host's swarmctl wrapper now sets `SSL_CERT_FILE` to the bundle the swarm-controller daemon already trusts (`/run/swarm-controller-ca/ trust-bundle.pem`: system CAs plus the swarm's root), when the gateway is self-signed. swarmctl's reqwest/rustls resolves roots the same way the daemon's does, so this is the path the daemon uses to reach the same gateway. `--set` rather than a default, since a nix shell exports its own `SSL_CERT_FILE`. Pointing `SWARMCTL_CA_FILE` at the bundle instead would not work (#5243): `--ca-file` adds each certificate as a root and fails the whole client on one it can't parse. Hosts without the controller (an operator laptop) still need `--ca-file`. Refs #5239 Fixes #5243
This commit is contained in:
parent
07f093c400
commit
7d24feaf25
3 changed files with 20 additions and 2 deletions
|
|
@ -159,6 +159,15 @@ let
|
||||||
gatewayCfg = config.services.hyperhive.gateway;
|
gatewayCfg = config.services.hyperhive.gateway;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
# `swarmctl --swarm` (and `login`) reach the same gateway as the daemon,
|
||||||
|
# through the same `reqwest`/`rustls` roots, so the wrapper hands it the
|
||||||
|
# daemon's bundle. `--set`, not a default: a nix shell exports its own
|
||||||
|
# `SSL_CERT_FILE`, which would win and lack the swarm's root. The bundle
|
||||||
|
# holds the system CAs too, so public hosts still verify.
|
||||||
|
swarmctlTrustEnv = lib.optionalAttrs caTrust.useSelfSigned {
|
||||||
|
SSL_CERT_FILE = caTrust.bundlePathFor "swarm-controller";
|
||||||
|
};
|
||||||
|
|
||||||
# The controller's own OAuth2 client. It is NOT a hive: the per-hive
|
# The controller's own OAuth2 client. It is NOT a hive: the per-hive
|
||||||
# clients the roster issues belong to hives, and the responder's client
|
# clients the roster issues belong to hives, and the responder's client
|
||||||
# belongs to the responder. One identity per principal — the rule is that
|
# belongs to the responder. One identity per principal — the rule is that
|
||||||
|
|
@ -257,7 +266,7 @@ let
|
||||||
wrapProgram $out/bin/swarmctl ${
|
wrapProgram $out/bin/swarmctl ${
|
||||||
lib.concatStringsSep " " (
|
lib.concatStringsSep " " (
|
||||||
lib.mapAttrsToList (name: value: "--set ${name} ${lib.escapeShellArg value}") (
|
lib.mapAttrsToList (name: value: "--set ${name} ${lib.escapeShellArg value}") (
|
||||||
controllerSocketEnv // deployCfg.swarm-controller.swarmctlEnvironment
|
controllerSocketEnv // swarmctlTrustEnv // deployCfg.swarm-controller.swarmctlEnvironment
|
||||||
)
|
)
|
||||||
++ lib.mapAttrsToList (
|
++ lib.mapAttrsToList (
|
||||||
name: value: "--set-default ${name} ${lib.escapeShellArg value}"
|
name: value: "--set-default ${name} ${lib.escapeShellArg value}"
|
||||||
|
|
|
||||||
|
|
@ -146,6 +146,12 @@ let
|
||||||
&& lib.hasInfix "--set-default SWARMCTL_LOGIN_DEFAULT_SWARM https://t.local" swarmctlWrapperCmd
|
&& lib.hasInfix "--set-default SWARMCTL_LOGIN_DEFAULT_SWARM https://t.local" swarmctlWrapperCmd
|
||||||
&& !(lib.hasInfix "SWARMCTL_SWARM" swarmctlWrapperCmd);
|
&& !(lib.hasInfix "SWARMCTL_SWARM" swarmctlWrapperCmd);
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
# The gateway's leaf chains to the store's root, which no system store
|
||||||
|
# holds; without the bundle `login` fails `UnknownIssuer`.
|
||||||
|
name = "the host's swarmctl trusts the swarm's root through the daemon's bundle";
|
||||||
|
ok = lib.hasInfix "--set SSL_CERT_FILE /run/swarm-controller-ca/trust-bundle.pem" swarmctlWrapperCmd;
|
||||||
|
}
|
||||||
{
|
{
|
||||||
name = "a swarm with no matrix gateway vhost gives the controller no homeserver variable";
|
name = "a swarm with no matrix gateway vhost gives the controller no homeserver variable";
|
||||||
ok =
|
ok =
|
||||||
|
|
|
||||||
|
|
@ -189,5 +189,8 @@ refuses it. When it can't be refreshed, any verb says to run `swarmctl login`
|
||||||
again. To log out, delete the file.
|
again. To log out, delete the file.
|
||||||
|
|
||||||
A swarm whose gateway serves a certificate from the swarm's own CA needs
|
A swarm whose gateway serves a certificate from the swarm's own CA needs
|
||||||
that CA: `--ca-file` or `SWARMCTL_CA_FILE`. The `user` verbs edit the local
|
that CA. On a controller host the swarm-controller module's wrapper sets
|
||||||
|
`SSL_CERT_FILE` to the bundle the daemon itself trusts (the system CAs plus
|
||||||
|
the swarm's root), so nothing needs setting there. Elsewhere, pass the CA
|
||||||
|
with `--ca-file` or `SWARMCTL_CA_FILE`. The `user` verbs edit the local
|
||||||
users file and have no remote form.
|
users file and have no remote form.
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue