fix(3112): the callout-exempt user needs its own credential
argus caught it and reproduced it: a users entry carrying only a name
has no credential, so CONNECT {"user":"auth"} is accepted with no
password. The name is a literal in this module, so on the shared netns
that identity was walk-in-able from every agent container -- the same
hole the module exists to close, moved rather than closed.
An nkey rather than a password: only the public half appears in config,
the seed reaches the responder alone, so a hive with no responder has
nobody who can authenticate as it. Asserted at eval, because the
rendered config is valid and the server starts either way.
This commit is contained in:
parent
467cb347ad
commit
c0df04320a
1 changed files with 59 additions and 1 deletions
|
|
@ -70,6 +70,33 @@ in
|
|||
'';
|
||||
};
|
||||
|
||||
calloutUserPublicKey = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "";
|
||||
example = "UDXU4RCSJNZOIQHZNWXHXORDPRTGNJAHAHFRGZNEEJCPQTT2M7NLCBBQ";
|
||||
description = ''
|
||||
Public half of the **user** nkey the auth-callout responder
|
||||
authenticates as.
|
||||
|
||||
`auth_callout.auth_users` exempts this identity from needing
|
||||
callout approval — it is the one that answers auth requests, so
|
||||
it cannot wait for itself. **That exemption is exactly why it
|
||||
needs a credential of its own**: without one the escape hatch is
|
||||
an open door, and on a container sharing the host netns it is an
|
||||
open door reachable from every agent container.
|
||||
|
||||
An nkey rather than a password for the same reason
|
||||
`calloutIssuerPublicKey` is: only the public half appears here,
|
||||
and nix renders it into the world-readable store harmlessly. The
|
||||
seed reaches the responder and nothing else, so until the
|
||||
responder exists **nobody can authenticate as this user at all**
|
||||
— which is what makes a hive with no responder genuinely closed
|
||||
rather than merely gated.
|
||||
|
||||
Required when `enable` is set.
|
||||
'';
|
||||
};
|
||||
|
||||
calloutIssuerPublicKey = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "";
|
||||
|
|
@ -109,6 +136,23 @@ in
|
|||
docs/swarm/secrets.md for which is which.
|
||||
'';
|
||||
}
|
||||
{
|
||||
# Without this the callout-exempt user has no credential, and
|
||||
# NATS accepts `CONNECT {"user":"auth"}` from anyone. An eval
|
||||
# failure is the only place to catch that: the rendered config is
|
||||
# valid, the server starts, and the hole is invisible until
|
||||
# somebody connects.
|
||||
assertion = cfg.calloutUserPublicKey != "";
|
||||
message = ''
|
||||
services.hyperhive.swarm.nats.enable requires
|
||||
nats.calloutUserPublicKey — the public half of the user nkey
|
||||
the auth-callout responder authenticates as.
|
||||
|
||||
It is exempt from callout approval by design, which is exactly
|
||||
why it needs its own credential: a `users` entry with a name
|
||||
and no key authenticates anyone who sends that name.
|
||||
'';
|
||||
}
|
||||
{
|
||||
assertion = autheliaUrl != null;
|
||||
message = ''
|
||||
|
|
@ -174,7 +218,21 @@ in
|
|||
# Two accounts, and the callout user lives in neither of
|
||||
# the accounts it authorizes into.
|
||||
accounts = {
|
||||
${calloutAccount}.users = [ { user = calloutUser; } ];
|
||||
# ⚠️ The nkey is not decoration and its absence was a real
|
||||
# hole: a `users` entry carrying only a `user` name has no
|
||||
# credential, and `CONNECT {"user":"auth"}` is then
|
||||
# accepted with no password at all. Since the name is a
|
||||
# literal in this public module, that made the
|
||||
# callout-exempt identity walk-in-able from every
|
||||
# container on the shared netns — the same class of hole
|
||||
# this module exists to close, moved rather than fixed.
|
||||
# Caught in review on the first version of this file.
|
||||
${calloutAccount}.users = [
|
||||
{
|
||||
user = calloutUser;
|
||||
nkey = cfg.calloutUserPublicKey;
|
||||
}
|
||||
];
|
||||
${clientAccount} = { };
|
||||
};
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue