Watch
0
0
Fork
You've already forked hyperhive
0

the operator's bao works on a store host without a hive

This commit is contained in:
atlas 2026-11-11 03:09:07 +01:00 • committed by mara
commit 32155f70aa
3 changed files with 169 additions and 9 deletions

View file

@ -133,6 +133,11 @@ in
servicesIssuerClientCertFile = lib.mkDefault "${pkiDir}/services-issuer.pem";
servicesIssuerClientKeyFile = lib.mkDefault "${pkiDir}/services-issuer-key.pem";
# The operator's shell on a store host that runs no hive, which has no
# reader above. See ./swarm-bao.nix's `baoCli`.
operatorClientCertFile = lib.mkDefault "${pkiDir}/operator.pem";
operatorClientKeyFile = lib.mkDefault "${pkiDir}/operator-key.pem";
# The granter: every `swarm-bao-*-policy` unit on this host logs in with
# it. ⚠️ Unlike every other leaf here, never the file an operator copies:
# its policy is root-equivalent and its only reader is this host.
@ -352,6 +357,13 @@ in
[ -s ${pkiDir}/forge-publisher.pem ] || ${signLeaf} ${pkiDir} forge-publisher \
${lib.escapeShellArg deployCfg.bao.forgePublisherCommonName} "" clientAuth
# The operator's shell on this host. No cert-auth role accepts its
# subject, so it opens the TLS handshake and nothing behind it. Minted
# whether or not a hive runs; the `bao` wrapper presents it only when
# none does.
[ -s ${pkiDir}/operator.pem ] || ${signLeaf} ${pkiDir} operator \
${lib.escapeShellArg deployCfg.bao.operatorCommonName} "" clientAuth
${lib.optionalString runsHive ''
# This hive's gateway-leaf identity, which opens
# `pki/issue/<hiveLeafPkiRolePrefix>-<hive>` and nothing else. Its

View file

@ -1590,19 +1590,32 @@ let
# same class of surprise it exists to remove.
baoCli =
let
# The hive reader identity `glue-bao-tls` mints where a hive runs, so
# cert-auth login needs nothing typed either. A store host without a hive
# has no such identity and the operator supplies a token or a leaf; a
# wrapper cannot conjure either.
# The hive reader identity `glue-bao-tls` mints where a hive runs; a
# store host without a hive presents the operator leaf instead. Either
# satisfies the listeners' client-certificate requirement and neither
# supplies a token: a wrapper cannot conjure one.
identity =
if baoDeploy.clientCertFile != null && baoDeploy.clientKeyFile != null then
{
cert = baoDeploy.clientCertFile;
key = baoDeploy.clientKeyFile;
}
else if baoDeploy.operatorClientCertFile != null && baoDeploy.operatorClientKeyFile != null then
{
cert = baoDeploy.operatorClientCertFile;
key = baoDeploy.operatorClientKeyFile;
}
else
null;
wrapArgs = [
"--set-default BAO_ADDR ${lib.escapeShellArg "https://${cfg.domain}:${toString cfg.port}"}"
]
++ lib.optional (
baoDeploy.serverCaFile != null
) "--set-default BAO_CACERT ${lib.escapeShellArg baoDeploy.serverCaFile}"
++ lib.optionals (baoDeploy.clientCertFile != null && baoDeploy.clientKeyFile != null) [
"--set-default BAO_CLIENT_CERT ${lib.escapeShellArg baoDeploy.clientCertFile}"
"--set-default BAO_CLIENT_KEY ${lib.escapeShellArg baoDeploy.clientKeyFile}"
++ lib.optionals (identity != null) [
"--set-default BAO_CLIENT_CERT ${lib.escapeShellArg identity.cert}"
"--set-default BAO_CLIENT_KEY ${lib.escapeShellArg identity.key}"
];
in
pkgs.symlinkJoin {
@ -2859,6 +2872,47 @@ in
'';
};
operatorCommonName = lib.mkOption {
type = lib.types.str;
default = "operator";
description = ''
Subject of the leaf the store's host mints for the operator's `bao`
shell. It authenticates the TLS handshake and nothing else: no
cert-auth role accepts this subject, so a login with it is refused and
it holds no token. Bao answers `init`, `unseal` and `status` without a
token; every other call still needs one.
⚠️ Reserved as a hive name by ./swarm.nix: a hive of this name has a reader
role that accepts this subject, so the operator's leaf would log in as it.
'';
};
operatorClientCertFile = lib.mkOption {
type = lib.types.nullOr lib.types.str;
default = null;
example = "/var/lib/swarm-bao-pki/operator.pem";
description = ''
Certificate the host's `bao` wrapper presents when the host has no
{option}`services.hyperhive.deploy.bao.clientCertFile`, which is a
store host that runs no hive. Its subject must be
{option}`services.hyperhive.deploy.bao.operatorCommonName`.
./glue-bao-tls.nix points it at the leaf it mints on the store's host.
A path, never a value.
'';
};
operatorClientKeyFile = lib.mkOption {
type = lib.types.nullOr lib.types.str;
default = null;
example = "/var/lib/swarm-bao-pki/operator-key.pem";
description = ''
Private key for
{option}`services.hyperhive.deploy.bao.operatorClientCertFile`. A path,
never a value.
'';
};
granterCommonName = lib.mkOption {
type = lib.types.str;
default = "bao-granter";

View file

@ -53,6 +53,7 @@ let
deployCfg.bao.servicesIssuerCommonName
deployCfg.bao.natsCommonName
deployCfg.bao.granterCommonName
deployCfg.bao.operatorCommonName
deployCfg.bao.natsAuthCommonName
deployCfg.bao.ciRunnerCommonName
deployCfg.bao.logsAuthCommonName