125 lines
4.3 KiB
Rust
125 lines
4.3 KiB
Rust
use std::path::PathBuf;
|
|
use std::process::Command;
|
|
|
|
use rpki::ccr::{
|
|
CcrContentInfo, CcrDigestAlgorithm, RpkiCanonicalCacheRepresentation, TrustAnchorState,
|
|
encode_content_info,
|
|
};
|
|
use rpki::cir::{
|
|
CIR_VERSION_V1, CanonicalInputRepresentation, CirHashAlgorithm, CirObject, CirTal, 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 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")
|
|
);
|
|
}
|