forked from mirrors/kingfisher
82 lines
2.2 KiB
Rust
82 lines
2.2 KiB
Rust
use anyhow::Result;
|
|
use assert_cmd::Command;
|
|
use serde_json::Value;
|
|
|
|
#[test]
|
|
fn scan_rules_has_no_validated_findings() -> Result<()> {
|
|
let output = Command::new(assert_cmd::cargo::cargo_bin!("kingfisher"))
|
|
.args([
|
|
"scan",
|
|
"crates/kingfisher-rules/data/rules",
|
|
"--format",
|
|
"json",
|
|
"--no-update-check",
|
|
"--only-valid",
|
|
])
|
|
.output()?;
|
|
|
|
let stdout = String::from_utf8_lossy(&output.stdout);
|
|
|
|
// Find the first '[' — start of array
|
|
let start = match stdout.find('[') {
|
|
Some(i) => i,
|
|
None => return Ok(()), // no array found
|
|
};
|
|
|
|
let mut depth = 0usize;
|
|
let mut end = None;
|
|
for (i, ch) in stdout.char_indices().skip(start) {
|
|
match ch {
|
|
'[' => depth += 1,
|
|
']' => {
|
|
depth -= 1;
|
|
if depth == 0 {
|
|
end = Some(i);
|
|
break;
|
|
}
|
|
}
|
|
_ => {}
|
|
}
|
|
}
|
|
|
|
let json_array_str = match end {
|
|
Some(end_idx) => &stdout[start..=end_idx],
|
|
None => return Ok(()), // no matching close found
|
|
};
|
|
|
|
if json_array_str.trim().is_empty() {
|
|
return Ok(());
|
|
}
|
|
|
|
let findings: Vec<Value> = serde_json::from_str(json_array_str)?;
|
|
let validated_rule_ids: Vec<String> = findings
|
|
.iter()
|
|
.filter_map(|finding| {
|
|
let status = finding["finding"]["validation"]["status"]
|
|
.as_str()
|
|
.unwrap_or("")
|
|
.to_ascii_lowercase();
|
|
if status == "active credential" {
|
|
Some(finding["rule"]["id"].as_str().unwrap_or("unknown").to_string())
|
|
} else {
|
|
None
|
|
}
|
|
})
|
|
.collect();
|
|
|
|
assert!(
|
|
validated_rule_ids.is_empty(),
|
|
"Validated findings detected in rules: {}",
|
|
validated_rule_ids.join(", ")
|
|
);
|
|
|
|
if !output.status.success() {
|
|
let stderr = String::from_utf8_lossy(&output.stderr);
|
|
panic!(
|
|
"kingfisher scan exited non-zero without validated findings in output.\nstdout:\n{}\nstderr:\n{}",
|
|
stdout, stderr
|
|
);
|
|
}
|
|
|
|
Ok(())
|
|
}
|