swarm CA: retire the host-held root CA, the store holds the only anchor
The secret store's pki root issues every hive's gateway leaf and the
swarm's service names, so the root swarm-ca.service generated on the
host anchors nothing and its key is a secret outside the store.
- swarm-ca.nix is gone: swarm-ca.service, root.pem and root-key.pem,
and the swarm.ca.{autoConfigure,stateDir,validityDays} options. A
definition of any of them fails evaluation with a removal message
(swarm-ca-removed.nix), and a tmpfiles rule deletes /var/lib/swarm-ca
on every host. singleHostSwarm no longer sets a swarm.* option.
- hive-tls-ca drops the $root slot: trust-bundle.pem holds the store's
pki root and a hive CA's public ca.pem/ca-previous.pem only.
- hivectl peer-config no longer prints the scp line for the swarm root;
the store's pki root is the one step.
- The gateway's cert import no longer stands a hive leaf or a throwaway
in for a missing swarm-services leaf where it Requires= the issuing
unit: it fails, naming swarm-services-cert.service. The stand-in stays
where the gateway does not wait (no swarm name, or the store's UI
only, whose passthrough must start with the store sealed).
Comments and docs that named swarm-ca.nix, swarm.ca.* or the host root
now name the store's pki root.
Refs #4588
This commit is contained in:
parent
5d6ebda3e8
commit
93f1a76ea7
22 changed files with 305 additions and 395 deletions
|
|
@ -16,31 +16,17 @@ const WG_INTERFACE: &str = "wg-hive";
|
|||
|
||||
/// Host path of this hive's TLS trust bundle (matches the
|
||||
/// `services.hyperhive.deploy.hive-controller.tls.stateDir` default in
|
||||
/// hive-tls.nix). Its
|
||||
/// existence means the gateway serves a self-signed, hive-CA-signed
|
||||
/// leaf, so a federating peer needs an anchor for it — which is now the
|
||||
/// swarm root, not a per-hive CA. Absent = ACME / operator cert, trusted
|
||||
/// by the default CA bundle with nothing to distribute.
|
||||
///
|
||||
/// The bundle rather than `ca.pem`: the hive CA is an intermediate under
|
||||
/// the swarm root, so `ca.pem` alone is not a chain a peer can validate
|
||||
/// against (openssl will not stop at a trusted non-self-signed cert).
|
||||
/// The bundle is whatever this hive is currently rooted at — the CA
|
||||
/// alone on a hive that predates the swarm root — so this stays a single
|
||||
/// path with no mode to branch on.
|
||||
/// hive-tls.nix). Its existence means the gateway is in self-signed mode,
|
||||
/// serving a leaf the secret store issued, so a federating peer needs an
|
||||
/// anchor for it. Absent = ACME / operator cert, trusted by the default CA
|
||||
/// bundle with nothing to distribute.
|
||||
const HIVE_TLS_TRUST_BUNDLE_PATH: &str = "/var/lib/hive-tls/trust-bundle.pem";
|
||||
|
||||
/// Host path of the swarm root CA cert (matches the
|
||||
/// `services.hyperhive.swarm.ca.stateDir` default in swarm-ca.nix). The
|
||||
/// anchor a whole swarm shares: install it once per host and every
|
||||
/// present *and future* hive under it validates, which is what replaced
|
||||
/// the per-hive CA pinning.
|
||||
const SWARM_CA_ROOT_PATH: &str = "/var/lib/swarm-ca/root.pem";
|
||||
|
||||
/// Host path of the secret store's `pki` root (hive-tls.nix's
|
||||
/// `$svcroot`, folded into the trust bundle). The swarm's service names
|
||||
/// are issued under it, so a peer trusting only the swarm root above
|
||||
/// cannot validate them.
|
||||
/// `$svcroot`, folded into the trust bundle). The anchor a whole swarm
|
||||
/// shares: every hive's gateway leaf and the swarm's service names are
|
||||
/// issued under it, so a peer host installs it once and every present
|
||||
/// *and future* hive validates.
|
||||
const STORE_PKI_ROOT_PATH: &str = "/var/lib/hive-tls/swarm-services-root.pem";
|
||||
|
||||
/// Attrset key for a hive in `services.hyperhive.swarm.hives`, derived
|
||||
|
|
@ -190,8 +176,8 @@ pub(crate) fn wg_peer(domain: &str, pubkey: &str, address: &str, endpoint: Optio
|
|||
/// certificate itself, or where it will appear when this hive has not
|
||||
/// fetched it yet.
|
||||
fn store_root_step(pem: Option<&str>) -> String {
|
||||
const HEAD: &str = "# 2. trust the SECRET STORE's pki root on the peer host (once, not per hive);\n\
|
||||
# the swarm's service names are issued under it:\n";
|
||||
const HEAD: &str = "# 1. trust the SECRET STORE's pki root on the peer host (once, not per hive);\n\
|
||||
# every hive's gateway leaf and the swarm's service names are issued under it:\n";
|
||||
match pem.map(str::trim_end).filter(|p| !p.is_empty()) {
|
||||
Some(p) => format!(
|
||||
"{HEAD}{p}\n\
|
||||
|
|
@ -205,8 +191,8 @@ fn store_root_step(pem: Option<&str>) -> String {
|
|||
}
|
||||
|
||||
/// `peer-config` — print the `swarm.hives."<name>"` block a peer
|
||||
/// operator pastes to federate with THIS hive, plus the swarm-root and
|
||||
/// store-root steps when this hive serves a self-signed chain. Reads
|
||||
/// operator pastes to federate with THIS hive, plus the store-root step
|
||||
/// when this hive serves a self-signed chain. Reads
|
||||
/// local state only (the TLS trust bundle, the store root + the wg key);
|
||||
/// prints, never mutates.
|
||||
pub(crate) fn peer_config(domain: &str, wg_address: Option<&str>, wg_endpoint: Option<&str>) {
|
||||
|
|
@ -219,17 +205,10 @@ pub(crate) fn peer_config(domain: &str, wg_address: Option<&str>, wg_endpoint: O
|
|||
.and_then(|k| wg_pubkey(&k).ok());
|
||||
|
||||
if self_signed {
|
||||
// One anchor for the whole swarm, installed once per host — not
|
||||
// a file per peer. That is the point of the hierarchy: a hive
|
||||
// joining later needs no edit on the hives already running.
|
||||
println!("# 1. install the SWARM ROOT on the peer host (once, not per hive):");
|
||||
println!("scp {SWARM_CA_ROOT_PATH} <peer-host>:{SWARM_CA_ROOT_PATH}");
|
||||
println!("# (skip if that host already has the swarm root)");
|
||||
println!();
|
||||
let store_root = std::fs::read_to_string(STORE_PKI_ROOT_PATH).ok();
|
||||
print!("{}", store_root_step(store_root.as_deref()));
|
||||
println!();
|
||||
println!("# 3. paste into the peer hive's NixOS config:");
|
||||
println!("# 2. paste into the peer hive's NixOS config:");
|
||||
} else {
|
||||
println!("# paste into the peer hive's NixOS config:");
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue