use super::*;
use tempfile::tempdir;
#[test]
fn nothing_declared_is_the_shipped_state() {
let shipped = Policy::default();
assert!(!shipped.confinement_required);
for (effect, want) in [
(Effect::Read, Ruling::Pass),
(Effect::TargetWrite, Ruling::Pass),
(Effect::Process, Ruling::Pass),
(Effect::OpenWorld, Ruling::Pass),
(Effect::Destructive, Ruling::Refuse),
(Effect::Secret, Ruling::Refuse),
] {
assert_eq!(shipped.ruling(effect), want, "{}", effect.word());
}
assert_eq!(shipped.rows().len(), DEFAULT.len());
assert_eq!(shipped.secret_fragments().len(), SECRET_FRAGMENTS.len());
assert_eq!(Policy::parse(""), shipped);
assert_eq!(Policy::parse("# nothing but a comment\n"), shipped);
}
#[test]
fn a_table_row_overrides_one_class_and_leaves_the_rest() {
let policy = Policy::parse("table:\n open-world: refuse\n");
assert_eq!(policy.ruling(Effect::OpenWorld), Ruling::Refuse);
assert_eq!(policy.ruling(Effect::Read), Ruling::Pass);
assert_eq!(policy.ruling(Effect::Destructive), Ruling::Refuse);
let parked = Policy::parse("table:\n open-world: hold\n");
assert_eq!(parked.ruling(Effect::OpenWorld), Ruling::Hold);
assert_eq!(parked.ruling(Effect::Process), Ruling::Pass);
}
#[test]
fn the_last_statement_of_a_class_wins() {
let policy = Policy::parse("table:\n open-world: refuse\n open-world: pass\n");
assert_eq!(policy.ruling(Effect::OpenWorld), Ruling::Pass);
}
#[test]
fn an_operator_rule_leads_the_shipped_ones() {
let policy = Policy::parse("rules:\n python: target-write\n git push: read\n");
let rows = policy.rows();
assert_eq!(rows.first().map(|r| r.program.as_str()), Some("python"));
assert_eq!(rows.first().map(|r| r.reach), Some(Reach::Fixed(TARGET)));
let git = rows.get(1).expect("second operator row");
assert_eq!(git.program, "git");
assert_eq!(git.words, vec!["push".to_owned()]);
assert_eq!(rows.len(), DEFAULT.len() + 2);
assert!(rows.iter().any(|r| r.program == "curl"));
}
const TARGET: Effect = Effect::TargetWrite;
#[test]
fn secrets_are_additive_only() {
let policy = Policy::parse("secrets:\n - .kube\n - vault-token\n");
let fragments = policy.secret_fragments();
assert!(fragments.iter().any(|f| f == ".kube"));
assert!(fragments.iter().any(|f| f == "vault-token"));
for shipped in SECRET_FRAGMENTS {
assert!(fragments.iter().any(|f| f == shipped), "{shipped}");
}
}
#[test]
fn confinement_is_required_only_when_it_says_so() {
assert!(Policy::parse("confinement: required\n").confinement_required);
assert!(!Policy::parse("confinement: optional\n").confinement_required);
assert!(!Policy::parse("confinement:\n").confinement_required);
}
#[test]
fn unreadable_lines_contribute_nothing_and_never_panic() {
let policy = Policy::parse(concat!(
"gibberish\n",
"table:\n",
" nonesuch: refuse\n",
" read: nonesuch\n",
"rules:\n",
" : read\n",
" curl: nonesuch\n",
"unknown-block:\n",
" anything: at all\n",
));
assert_eq!(policy, Policy::default());
}
#[test]
fn a_comment_and_a_blank_line_do_not_end_a_block() {
let policy = Policy::parse("rules:\n # why we do this\n\n python: read\n");
assert_eq!(
policy.rows().first().map(|r| r.program.as_str()),
Some("python")
);
}
#[test]
fn a_workspace_with_no_repo_reads_the_shipped_state() {
let dir = tempdir().unwrap();
assert_eq!(Policy::read(dir.path()), Policy::default());
}