swarm-bao: agent certificates issued by a store-generated agent CA
An agent's store identity was signed in swarm-controller's memory by a CA a controller-host unit generated on disk, and the listener never trusted that CA. Agent leaves now come from the store itself: a `pki-agents` PKI mount whose root openbao generates internally, so the agent CA's key never exists outside the store. - swarm-bao-agent-pki (new, store host, as the bao granter): enables and tunes the mount, generates the root once (guarded on an empty issuer list, no replace branch), upserts the `swarm-agent` role (client certificates named `hive-agent-*` only, 90 days), caches the CA at /var/lib/swarm-bao-tls/agent-ca.pem and composes the listener bundle. - The listener's tls_client_ca_file is a new listener-client-ca.pem (client-ca.pem, then the agent CA). Host cert-auth roles still pin client-ca.pem, so an agent leaf satisfies no host role. swarm-bao-certs composes the same bundle before openbao starts. - openbao reads tls_client_ca_file only at start, so when the bundle changed after openbao started, swarm-bao-agent-pki restarts openbao.service in the container; under `seal = "shamir"` it prints the step instead. Once swarm-bao-certs has a cached CA, later boots start openbao with it and do not restart. - The controller policy gains exactly `update` on pki-agents/issue/swarm-agent. mint_and_verify now asks that role for the leaf (the store generates the key), writes the agent's cert-auth role pinning the issuing CA bao returned, and writes the agent's policy as render_agent alone: the hive-shared queue credential stanza is gone. - deploy.bao.agentPkiRoleName (must start `swarm-`, asserted with the other pki role names); swarm-controller gets SWARM_CONTROLLER_AGENT_PKI_MOUNT/_ROLE from the deploy.bao options. Deleted: swarm-controller-agent-ca and its options (agentCaFile, agentCaKeyFile), env, LoadCredential entries and assertion; agent_identity's Authority, rcgen signing and validity window; the rcgen and time dependencies of swarm-controller (rcgen leaves the workspace); policy::render_agent_with_queue and its tests. The CN-prefix assertion policy.rs said was owed is not: agent and host roles pin different CAs. Migration is re-creating each agent after deploy; that overwrites the stale role and policy. Closes #4756
This commit is contained in:
parent
5cd7f866f4
commit
6170e74a31
16 changed files with 894 additions and 925 deletions
|
|
@ -31,6 +31,15 @@ let
|
|||
deploy.swarm-controller.enable = true;
|
||||
};
|
||||
|
||||
# Store and controller with an agent PKI mount and role no default could
|
||||
# supply.
|
||||
controllerAgentPkiMarker = hive {
|
||||
deploy.bao.enable = true;
|
||||
deploy.bao.agentPkiMountPath = "pki-agents-marker";
|
||||
deploy.bao.agentPkiRoleName = "swarm-agent-marker";
|
||||
deploy.swarm-controller.enable = true;
|
||||
};
|
||||
|
||||
# The controller with no store, which is every spread deployment. Nothing
|
||||
# mints here, so the pairing must leave the paths unset rather than name
|
||||
# files this host will never have.
|
||||
|
|
@ -220,6 +229,47 @@ let
|
|||
in
|
||||
lib.hasInfix "cn-marker-not-a-default" role && lib.hasInfix "cn-marker-not-a-default" pki;
|
||||
}
|
||||
{
|
||||
# Agent leaves come from the store's own agent PKI, so the controller
|
||||
# holds no authority of its own: no minting unit, no key, no variable
|
||||
# naming one.
|
||||
name = "the controller holds no agent CA and is told the store's agent PKI mount and role";
|
||||
ok =
|
||||
let
|
||||
s = baoControllerHere.systemd.services;
|
||||
e = s.swarm-controller.environment;
|
||||
in
|
||||
s ? swarm-controller
|
||||
&& !(s ? swarm-controller-agent-ca)
|
||||
&& !(e ? SWARM_CONTROLLER_AGENT_CA_FILE)
|
||||
&& !(e ? SWARM_CONTROLLER_AGENT_CA_KEY_FILE)
|
||||
&& !(lib.any (c: lib.hasPrefix "agent-ca" c) s.swarm-controller.serviceConfig.LoadCredential)
|
||||
&& (e.SWARM_CONTROLLER_AGENT_PKI_MOUNT or null) == "pki-agents"
|
||||
&& (e.SWARM_CONTROLLER_AGENT_PKI_ROLE or null) == "swarm-agent";
|
||||
}
|
||||
{
|
||||
# The controller issues through whatever mount and role it is told, and
|
||||
# its grant names a path. Both read the store's options, which the
|
||||
# marker values prove: no default could supply them.
|
||||
name = "the controller's issue grant and its environment name one mount and role";
|
||||
ok =
|
||||
let
|
||||
s = controllerAgentPkiMarker.systemd.services;
|
||||
in
|
||||
s.swarm-controller.environment.SWARM_CONTROLLER_AGENT_PKI_MOUNT == "pki-agents-marker"
|
||||
&& s.swarm-controller.environment.SWARM_CONTROLLER_AGENT_PKI_ROLE == "swarm-agent-marker"
|
||||
&& lib.hasInfix ''path "pki-agents-marker/issue/swarm-agent-marker"'' s.swarm-bao-controller-policy.script;
|
||||
}
|
||||
{
|
||||
# Absence arm: without a store identity nothing can be issued, so the
|
||||
# variables are not set.
|
||||
name = "a controller with no store leaf is not told an agent PKI";
|
||||
ok =
|
||||
let
|
||||
e = controllerNoStore.systemd.services.swarm-controller.environment;
|
||||
in
|
||||
!(e ? SWARM_CONTROLLER_AGENT_PKI_MOUNT) && !(e ? SWARM_CONTROLLER_AGENT_PKI_ROLE);
|
||||
}
|
||||
];
|
||||
in
|
||||
runGroup "bao-controller" cases
|
||||
|
|
|
|||
Loading…
Reference in a new issue