fix(#2391): mandatory hive- prefixed snapshot label, nest subvol snapshot create/delete
Per mara's PR review: - snapshot label is now mandatory (was optional w/ timestamp default) and must start with "hive-" — hive-priv enforces this as an allow-list on top of the existing credential-name charset check, so only hivectl-issued labels can reach the btrfs shellout. - nest under `subvol snapshot create`/`subvol snapshot delete` instead of othering delete as a separate top-level `delete-snapshot` verb. Per argus's review: - regenerate docs/tools/hivectl-cli.md (hivectl markdown-docs) to include the new subcommands — CI's hivectl-docs-fresh check compares this file against generated output.
This commit is contained in:
parent
7799e0762a
commit
8f8076b8ed
4 changed files with 106 additions and 32 deletions
|
|
@ -370,7 +370,7 @@ async fn exec(req: PrivRequest, writer: &mut OwnedWriteHalf) -> Result<(String,
|
|||
ref snapshot_name,
|
||||
} => {
|
||||
validate_agent_name(agent_name)?;
|
||||
validate_credential_name(snapshot_name)?;
|
||||
validate_snapshot_name(snapshot_name)?;
|
||||
snapshot_agent_subvolume(agent_name, snapshot_name).await
|
||||
}
|
||||
|
||||
|
|
@ -379,7 +379,7 @@ async fn exec(req: PrivRequest, writer: &mut OwnedWriteHalf) -> Result<(String,
|
|||
ref snapshot_name,
|
||||
} => {
|
||||
validate_agent_name(agent_name)?;
|
||||
validate_credential_name(snapshot_name)?;
|
||||
validate_snapshot_name(snapshot_name)?;
|
||||
delete_agent_snapshot(agent_name, snapshot_name).await
|
||||
}
|
||||
|
||||
|
|
@ -430,6 +430,20 @@ fn handle_write_nspawn_flags(
|
|||
Ok((String::new(), String::new()))
|
||||
}
|
||||
|
||||
/// A btrfs snapshot label must start with `hive-` — this doubles as an
|
||||
/// allow-list: only names hivectl itself constructs (or an operator who
|
||||
/// knows the convention) can reach the `btrfs subvolume snapshot`/`delete`
|
||||
/// shellouts, so an arbitrary caller can't use the snapshot ops to probe or
|
||||
/// churn unrelated paths under `AGENT_STATE_ROOT`. Beyond the prefix, the
|
||||
/// same charset restriction as [`validate_credential_name`] applies (it's
|
||||
/// interpolated straight into a filesystem path).
|
||||
fn validate_snapshot_name(name: &str) -> Result<()> {
|
||||
if !name.starts_with("hive-") {
|
||||
bail!("invalid snapshot label {name:?}: must start with \"hive-\"");
|
||||
}
|
||||
validate_credential_name(name)
|
||||
}
|
||||
|
||||
/// A systemd credential id must be a short token — restrict to
|
||||
/// `[A-Za-z0-9_.-]` so it can't inject extra `--load-credential` argv or
|
||||
/// break the `name:path` shape.
|
||||
|
|
|
|||
Loading…
Reference in a new issue