rpki/tests/test_cir_drop_report_m5.rs

112 lines
4.2 KiB
Rust

use std::path::PathBuf;
use std::process::Command;
use rpki::ccr::{
encode_content_info, CcrContentInfo, CcrDigestAlgorithm, RpkiCanonicalCacheRepresentation,
TrustAnchorState,
};
use rpki::cir::{encode_cir, CanonicalInputRepresentation, CirHashAlgorithm, CirObject, CirTal, CIR_VERSION_V1};
#[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 static_root = td.path().join("static");
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))
};
let dir = static_root.join("20260409").join(&hash[0..2]).join(&hash[2..4]);
std::fs::create_dir_all(&dir).unwrap();
std::fs::write(dir.join(&hash), &roa_bytes).unwrap();
let cir = CanonicalInputRepresentation {
version: CIR_VERSION_V1,
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(),
}],
};
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(),
"--static-root",
static_root.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"));
}