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
|
|
@ -376,7 +376,7 @@ async fn exec(
|
|||
ref binds,
|
||||
ref isolation,
|
||||
ref load_credentials,
|
||||
} => handle_write_nspawn_flags(container, binds, isolation.as_ref(), load_credentials),
|
||||
} => handle_write_nspawn_flags(container, binds, isolation, load_credentials),
|
||||
|
||||
PrivRequest::WriteResourceLimits {
|
||||
ref container,
|
||||
|
|
@ -923,7 +923,7 @@ fn single_output_path(stdout: &str) -> Result<&str, usize> {
|
|||
fn handle_write_nspawn_flags(
|
||||
container: &str,
|
||||
binds: &[BindMount],
|
||||
isolation: Option<&NetworkIsolation>,
|
||||
isolation: &NetworkIsolation,
|
||||
load_credentials: &[CredentialMount],
|
||||
) -> Result<(String, String)> {
|
||||
validate_container_system_name(container)?;
|
||||
|
|
@ -2718,13 +2718,13 @@ fn git_overlay_flags(binds: &[BindMount]) -> Vec<String> {
|
|||
/// Update `/etc/nixos-containers/<container>.conf`: strip old network vars
|
||||
/// (`PRIVATE_NETWORK`, `HOST_ADDRESS*`, `LOCAL_ADDRESS*`, `HOST_BRIDGE`),
|
||||
/// write the current network-isolation settings, then append
|
||||
/// `EXTRA_NSPAWN_FLAGS`. When `isolation` is `Some`, writes
|
||||
/// `PRIVATE_NETWORK=1` + veth wiring; when `None`, writes
|
||||
/// `PRIVATE_NETWORK=0`.
|
||||
/// `EXTRA_NSPAWN_FLAGS`. Always writes `PRIVATE_NETWORK=1` + veth
|
||||
/// wiring — isolation is the only mode, so there is no branch that
|
||||
/// leaves a container on the host's network namespace.
|
||||
fn write_nspawn_flags(
|
||||
container: &str,
|
||||
binds: &[BindMount],
|
||||
isolation: Option<&NetworkIsolation>,
|
||||
isolation: &NetworkIsolation,
|
||||
load_credentials: &[CredentialMount],
|
||||
) -> Result<()> {
|
||||
use std::fmt::Write as _;
|
||||
|
|
@ -2747,7 +2747,8 @@ fn write_nspawn_flags(
|
|||
if !out.is_empty() {
|
||||
out.push('\n');
|
||||
}
|
||||
if let Some(iso) = isolation {
|
||||
{
|
||||
let iso = isolation;
|
||||
out.push_str("PRIVATE_NETWORK=1\n");
|
||||
// HOST_ADDRESS = the bridge gateway IP. nixos-container's
|
||||
// container-side setup only installs a default route
|
||||
|
|
@ -2766,13 +2767,6 @@ fn write_nspawn_flags(
|
|||
out.push_str("HOST_ADDRESS6=\n");
|
||||
out.push_str("LOCAL_ADDRESS6=\n");
|
||||
let _ = writeln!(out, "HOST_BRIDGE={}", iso.bridge);
|
||||
} else {
|
||||
out.push_str("PRIVATE_NETWORK=0\n");
|
||||
out.push_str("HOST_ADDRESS=\n");
|
||||
out.push_str("LOCAL_ADDRESS=\n");
|
||||
out.push_str("HOST_ADDRESS6=\n");
|
||||
out.push_str("LOCAL_ADDRESS6=\n");
|
||||
out.push_str("HOST_BRIDGE=\n");
|
||||
}
|
||||
let mut flags: Vec<String> = binds
|
||||
.iter()
|
||||
|
|
@ -2817,29 +2811,19 @@ fn bridge_dns_marker_path(container: &str) -> String {
|
|||
/// Write (isolated) or remove (host-netns) the bridge-DNS marker the
|
||||
/// `hyperhive-isolated-dns` oneshot keys off. The marker file contains
|
||||
/// just the gateway IP. Best-effort on removal (absence is the goal).
|
||||
fn write_bridge_dns_marker(container: &str, isolation: Option<&NetworkIsolation>) -> Result<()> {
|
||||
fn write_bridge_dns_marker(container: &str, isolation: &NetworkIsolation) -> Result<()> {
|
||||
let path = bridge_dns_marker_path(container);
|
||||
match isolation {
|
||||
Some(iso) => {
|
||||
// On a fresh install the container's `/etc` may not exist yet
|
||||
// (rootfs not fully materialised before the first start), so
|
||||
// `write` would fail with ENOENT. Create the parent dir first
|
||||
// — it's the container's own `/etc`, which nixos-container
|
||||
// populates on start; a pre-created dir + our marker persist.
|
||||
if let Some(parent) = std::path::Path::new(&path).parent() {
|
||||
std::fs::create_dir_all(parent).with_context(|| {
|
||||
format!("create bridge-DNS marker dir {}", parent.display())
|
||||
})?;
|
||||
}
|
||||
std::fs::write(&path, format!("{}\n", iso.gateway_ip))
|
||||
.with_context(|| format!("write bridge-DNS marker {path}"))?;
|
||||
}
|
||||
None => match std::fs::remove_file(&path) {
|
||||
Ok(()) => {}
|
||||
Err(e) if e.kind() == std::io::ErrorKind::NotFound => {}
|
||||
Err(e) => return Err(e).with_context(|| format!("remove bridge-DNS marker {path}")),
|
||||
},
|
||||
// On a fresh install the container's `/etc` may not exist yet
|
||||
// (rootfs not fully materialised before the first start), so
|
||||
// `write` would fail with ENOENT. Create the parent dir first
|
||||
// — it's the container's own `/etc`, which nixos-container
|
||||
// populates on start; a pre-created dir + our marker persist.
|
||||
if let Some(parent) = std::path::Path::new(&path).parent() {
|
||||
std::fs::create_dir_all(parent)
|
||||
.with_context(|| format!("create bridge-DNS marker dir {}", parent.display()))?;
|
||||
}
|
||||
std::fs::write(&path, format!("{}\n", isolation.gateway_ip))
|
||||
.with_context(|| format!("write bridge-DNS marker {path}"))?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue