Allow disabling boolean flags from the CLI
Pair --hardened, --dry-run, and --unshare-net (renamed from --no-net) with negation counterparts so a CLI invocation can override a truthy config-file or profile value.
This commit is contained in:
+83
-13
@@ -28,9 +28,21 @@ pub fn build(args: Args, file_config: Option<FileConfig>) -> Result<SandboxConfi
|
||||
|
||||
Ok(SandboxConfig {
|
||||
mode: merge_mode(args.blacklist, args.whitelist, &profile, &globals),
|
||||
hardened: merge_flag(args.hardened, profile.hardened, globals.hardened),
|
||||
no_net: merge_flag(args.no_net, profile.no_net, globals.no_net),
|
||||
dry_run: merge_flag(args.dry_run, profile.dry_run, globals.dry_run),
|
||||
hardened: merge_flag(
|
||||
merge_flag_pair(args.hardened, args.no_hardened),
|
||||
profile.hardened,
|
||||
globals.hardened,
|
||||
),
|
||||
unshare_net: merge_flag(
|
||||
merge_flag_pair(args.unshare_net, args.share_net),
|
||||
profile.unshare_net,
|
||||
globals.unshare_net,
|
||||
),
|
||||
dry_run: merge_flag(
|
||||
merge_flag_pair(args.dry_run, args.no_dry_run),
|
||||
profile.dry_run,
|
||||
globals.dry_run,
|
||||
),
|
||||
chdir: resolve_chdir(args.chdir, profile.chdir, globals.chdir)?,
|
||||
extra_rw: merge_paths(args.extra_rw, &profile.rw, &globals.rw)?,
|
||||
extra_ro: merge_paths(args.extra_ro, &profile.ro, &globals.ro)?,
|
||||
@@ -70,11 +82,18 @@ fn resolve_mode(opts: &Options) -> Option<SandboxMode> {
|
||||
}
|
||||
}
|
||||
|
||||
fn merge_flag(cli: bool, profile: Option<bool>, globals: Option<bool>) -> bool {
|
||||
if cli {
|
||||
return true;
|
||||
fn merge_flag(cli: Option<bool>, profile: Option<bool>, globals: Option<bool>) -> bool {
|
||||
cli.or(profile).or(globals).unwrap_or(false)
|
||||
}
|
||||
|
||||
fn merge_flag_pair(enable: bool, disable: bool) -> Option<bool> {
|
||||
if enable {
|
||||
Some(true)
|
||||
} else if disable {
|
||||
Some(false)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
profile.or(globals).unwrap_or(false)
|
||||
}
|
||||
|
||||
fn resolve_chdir(
|
||||
@@ -224,7 +243,7 @@ pub struct Options {
|
||||
pub blacklist: Option<bool>,
|
||||
pub whitelist: Option<bool>,
|
||||
pub hardened: Option<bool>,
|
||||
pub no_net: Option<bool>,
|
||||
pub unshare_net: Option<bool>,
|
||||
pub entrypoint: Option<CommandValue>,
|
||||
pub command: Option<CommandValue>,
|
||||
pub dry_run: Option<bool>,
|
||||
@@ -360,7 +379,7 @@ mod tests {
|
||||
|
||||
const FULL_CONFIG_TOML: &str = r#"
|
||||
hardened = true
|
||||
no-net = true
|
||||
unshare-net = true
|
||||
rw = ["/tmp/a", "/tmp/b"]
|
||||
command = "zsh"
|
||||
|
||||
@@ -383,7 +402,7 @@ mod tests {
|
||||
#[test]
|
||||
fn globals_scalars() {
|
||||
assert_eq!(CONFIG.options.hardened, Some(true));
|
||||
assert_eq!(CONFIG.options.no_net, Some(true));
|
||||
assert_eq!(CONFIG.options.unshare_net, Some(true));
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -488,7 +507,7 @@ mod tests {
|
||||
profile: HashMap::from([(
|
||||
"nonet".into(),
|
||||
Options {
|
||||
no_net: Some(false),
|
||||
unshare_net: Some(false),
|
||||
..Options::default()
|
||||
},
|
||||
)]),
|
||||
@@ -496,11 +515,62 @@ mod tests {
|
||||
};
|
||||
let args = Args {
|
||||
profile: Some("nonet".into()),
|
||||
no_net: true,
|
||||
unshare_net: true,
|
||||
..args_with_command()
|
||||
};
|
||||
let config = build(args, Some(file_config)).unwrap();
|
||||
assert!(config.no_net);
|
||||
assert!(config.unshare_net);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn build_cli_no_hardened_overrides_profile() {
|
||||
let file_config = FileConfig {
|
||||
options: Options {
|
||||
hardened: Some(true),
|
||||
..Options::default()
|
||||
},
|
||||
..FileConfig::default()
|
||||
};
|
||||
let args = Args {
|
||||
no_hardened: true,
|
||||
..args_with_command()
|
||||
};
|
||||
let config = build(args, Some(file_config)).unwrap();
|
||||
assert!(!config.hardened);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn build_cli_share_net_overrides_profile() {
|
||||
let file_config = FileConfig {
|
||||
options: Options {
|
||||
unshare_net: Some(true),
|
||||
..Options::default()
|
||||
},
|
||||
..FileConfig::default()
|
||||
};
|
||||
let args = Args {
|
||||
share_net: true,
|
||||
..args_with_command()
|
||||
};
|
||||
let config = build(args, Some(file_config)).unwrap();
|
||||
assert!(!config.unshare_net);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn build_cli_no_dry_run_overrides_profile() {
|
||||
let file_config = FileConfig {
|
||||
options: Options {
|
||||
dry_run: Some(true),
|
||||
..Options::default()
|
||||
},
|
||||
..FileConfig::default()
|
||||
};
|
||||
let args = Args {
|
||||
no_dry_run: true,
|
||||
..args_with_command()
|
||||
};
|
||||
let config = build(args, Some(file_config)).unwrap();
|
||||
assert!(!config.dry_run);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
Reference in New Issue
Block a user