require network isolation, deleting the residual non-isolated branch
Per mara on #3725: the on/off toggle is removed, and required env vars unset lead to a crash. HIVE_NETWORK_ISOLATION is gone from hive-network.nix -- it was the toggle. Validation happens once at daemon startup rather than per container. The variables are process-global, so a bad value breaks every container rather than one: failing at boot gives a single diagnostic naming the bad value, and cannot reach a state where some containers were configured before it was noticed. Option<NetworkIsolation> collapses to NetworkIsolation through the wire type, client and helper, which deletes the branch instead of leaving it unreachable. serde(default) is dropped on that field deliberately: a request omitting isolation is now rejected rather than defaulting to a container sharing the host's network namespace. What this replaces was a silent security downgrade. Of the four ways into the old fallback, two logged nothing at all -- a container came up without isolation and the journal agreed it was fine. Doc comments that still described the removed branch are updated (argus's note on #3723 scoped that to this issue). The hive-priv one is a minimal edit inside the block #3723 rewrites; de-splicing is that PR's job.
This commit is contained in:
parent
16ac84ca63
commit
83c0e4b4bf
8 changed files with 166 additions and 83 deletions
|
|
@ -125,6 +125,56 @@ pub fn bridge_gateway_ip(subnet_cidr: &str) -> Option<String> {
|
|||
Some(ip_str.to_owned())
|
||||
}
|
||||
|
||||
/// Build the network-isolation settings every container is configured
|
||||
/// with, from the variables `hive-network.nix` sets on the `hive-c0re`
|
||||
/// unit.
|
||||
///
|
||||
/// Isolation is the only supported mode: the on/off toggle is gone, so
|
||||
/// there is no non-isolated branch to fall back to and a missing or
|
||||
/// malformed value means the daemon is misconfigured — not that a
|
||||
/// container should quietly come up sharing the host's netns. Silently
|
||||
/// degrading here dropped a security boundary with nothing in the log
|
||||
/// to say so.
|
||||
///
|
||||
/// Split from [`network_isolation_from_env`] so the parsing is testable
|
||||
/// without touching process environment.
|
||||
pub fn network_isolation_from_vars(
|
||||
bridge: Option<&str>,
|
||||
subnet: Option<&str>,
|
||||
) -> Result<hive_priv_sock::NetworkIsolation> {
|
||||
let bridge = bridge.filter(|s| !s.is_empty()).context(
|
||||
"HIVE_NETWORK_BRIDGE is unset or empty — hive-network.nix sets it on the \
|
||||
hive-c0re unit, so this means the daemon is running outside its unit or \
|
||||
with a broken module evaluation",
|
||||
)?;
|
||||
let subnet = subnet.filter(|s| !s.is_empty()).context(
|
||||
"HIVE_NETWORK_SUBNET is unset or empty — hive-network.nix sets it on the \
|
||||
hive-c0re unit, so this means the daemon is running outside its unit or \
|
||||
with a broken module evaluation",
|
||||
)?;
|
||||
let gateway_ip = bridge_gateway_ip(subnet).with_context(|| {
|
||||
format!(
|
||||
"HIVE_NETWORK_SUBNET={subnet} is not a valid <ipv4>/<prefix> pair; \
|
||||
it comes from services.hyperhive.network.bridgeIp + bridgePrefixLength"
|
||||
)
|
||||
})?;
|
||||
Ok(hive_priv_sock::NetworkIsolation {
|
||||
bridge: bridge.to_owned(),
|
||||
gateway_ip,
|
||||
})
|
||||
}
|
||||
|
||||
/// [`network_isolation_from_vars`] over the real process environment.
|
||||
///
|
||||
/// Called once at daemon startup so a bad value fails the unit loudly,
|
||||
/// and again per container — the variables are process-global, so the
|
||||
/// second call cannot start failing once the first has passed.
|
||||
pub fn network_isolation_from_env() -> Result<hive_priv_sock::NetworkIsolation> {
|
||||
let bridge = std::env::var("HIVE_NETWORK_BRIDGE").ok();
|
||||
let subnet = std::env::var("HIVE_NETWORK_SUBNET").ok();
|
||||
network_isolation_from_vars(bridge.as_deref(), subnet.as_deref())
|
||||
}
|
||||
|
||||
/// Read the agent user's `(uid, gid)` from the container's nixos-managed
|
||||
/// `/etc/passwd`. Returns `None` when the container hasn't been built
|
||||
/// yet, the passwd file is unparseable, or the agent user is missing
|
||||
|
|
|
|||
Loading…
Reference in a new issue