rpki/tests/test_cir_drop_report_m5.rs

127 lines
4.4 KiB
Rust

use std::path::PathBuf;
use std::process::Command;
use rpki::blob_store::ExternalRepoBytesDb;
use rpki::ccr::{
CcrContentInfo, CcrDigestAlgorithm, RpkiCanonicalCacheRepresentation, TrustAnchorState,
encode_content_info,
};
use rpki::cir::{
CIR_VERSION_V2, CanonicalInputRepresentation, CirHashAlgorithm, CirObject, CirTal,
compute_reject_list_sha256, encode_cir,
};
#[test]
fn cir_drop_report_counts_dropped_roa_objects_and_vrps() {
let td = tempfile::tempdir().expect("tempdir");
let cir_path = td.path().join("input.cir");
let ccr_path = td.path().join("output.ccr");
let report_path = td.path().join("report.json");
let repo_bytes_db = td.path().join("repo-bytes.db");
let json_out = td.path().join("drop.json");
let md_out = td.path().join("drop.md");
let roa_path = PathBuf::from(env!("CARGO_MANIFEST_DIR"))
.join("tests/fixtures/repository/rpki.cernet.net/repo/cernet/0/AS4538.roa");
let roa_bytes = std::fs::read(&roa_path).expect("read roa fixture");
let hash = {
use sha2::{Digest, Sha256};
hex::encode(Sha256::digest(&roa_bytes))
};
ExternalRepoBytesDb::open(&repo_bytes_db)
.expect("open repo bytes")
.put_blob_bytes_batch(&[(hash.clone(), roa_bytes.clone())])
.expect("write repo bytes");
let cir = CanonicalInputRepresentation {
version: CIR_VERSION_V2,
hash_alg: CirHashAlgorithm::Sha256,
validation_time: time::OffsetDateTime::parse(
"2026-04-09T00:00:00Z",
&time::format_description::well_known::Rfc3339,
)
.unwrap(),
objects: vec![CirObject {
rsync_uri: "rsync://example.net/repo/AS4538.roa".to_string(),
sha256: hex::decode(&hash).unwrap(),
}],
tals: vec![CirTal {
tal_uri: "https://example.test/root.tal".to_string(),
tal_bytes: b"rsync://example.net/repo/root.cer\nMIIB".to_vec(),
}],
reject_list_sha256: compute_reject_list_sha256(std::iter::empty::<&str>()),
rejected_objects: Vec::new(),
};
std::fs::write(&cir_path, encode_cir(&cir).unwrap()).unwrap();
let ccr = CcrContentInfo::new(RpkiCanonicalCacheRepresentation {
version: 0,
hash_alg: CcrDigestAlgorithm::Sha256,
produced_at: cir.validation_time,
mfts: None,
vrps: None,
vaps: None,
tas: Some(TrustAnchorState {
skis: vec![vec![0x11; 20]],
hash: vec![0x22; 32],
}),
rks: None,
});
std::fs::write(&ccr_path, encode_content_info(&ccr).unwrap()).unwrap();
let report = serde_json::json!({
"format_version": 2,
"publication_points": [
{
"manifest_rsync_uri": "rsync://example.net/repo/example.mft",
"publication_point_rsync_uri": "rsync://example.net/repo/",
"objects": [
{
"rsync_uri": "rsync://example.net/repo/AS4538.roa",
"sha256_hex": hash,
"kind": "roa",
"result": "error",
"detail": "policy rejected"
}
]
}
]
});
std::fs::write(&report_path, serde_json::to_vec_pretty(&report).unwrap()).unwrap();
let bin = env!("CARGO_BIN_EXE_cir_drop_report");
let out = Command::new(bin)
.args([
"--cir",
cir_path.to_string_lossy().as_ref(),
"--ccr",
ccr_path.to_string_lossy().as_ref(),
"--report-json",
report_path.to_string_lossy().as_ref(),
"--repo-bytes-db",
repo_bytes_db.to_string_lossy().as_ref(),
"--json-out",
json_out.to_string_lossy().as_ref(),
"--md-out",
md_out.to_string_lossy().as_ref(),
])
.output()
.expect("run cir_drop_report");
assert!(
out.status.success(),
"stderr={}",
String::from_utf8_lossy(&out.stderr)
);
let output: serde_json::Value =
serde_json::from_slice(&std::fs::read(&json_out).unwrap()).unwrap();
assert_eq!(output["summary"]["droppedObjectCount"], 1);
assert!(output["summary"]["droppedVrpCount"].as_u64().unwrap_or(0) >= 1);
assert_eq!(output["summary"]["droppedByKind"]["roa"], 1);
assert!(
std::fs::read_to_string(&md_out)
.unwrap()
.contains("Dropped By Reason")
);
}