rpki/tests/test_deterministic_semantics_m4.rs
2026-02-10 12:09:59 +08:00

137 lines
4.9 KiB
Rust

use rpki::audit::PublicationPointAudit;
use rpki::policy::{Policy, SignedObjectFailurePolicy};
use rpki::storage::{PackFile, PackTime, VerifiedPublicationPointPack};
use rpki::validation::manifest::PublicationPointSource;
use rpki::validation::objects::process_verified_publication_point_pack_for_issuer;
use rpki::validation::tree::{
CaInstanceHandle, PublicationPointRunResult, PublicationPointRunner, TreeRunConfig,
run_tree_serial_audit,
};
fn fixture_bytes(path: &str) -> Vec<u8> {
std::fs::read(std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR")).join(path))
.unwrap_or_else(|e| panic!("read fixture {path}: {e}"))
}
fn dummy_pack(files: Vec<PackFile>) -> VerifiedPublicationPointPack {
let now = time::OffsetDateTime::now_utc();
let manifest_rsync_uri =
"rsync://rpki.cernet.net/repo/cernet/0/05FC9C5B88506F7C0D3F862C8895BED67E9F8EBA.mft";
VerifiedPublicationPointPack {
format_version: VerifiedPublicationPointPack::FORMAT_VERSION_V1,
manifest_rsync_uri: manifest_rsync_uri.to_string(),
publication_point_rsync_uri: "rsync://rpki.cernet.net/repo/cernet/0/".to_string(),
this_update: PackTime::from_utc_offset_datetime(now),
next_update: PackTime::from_utc_offset_datetime(now + time::Duration::hours(1)),
verified_at: PackTime::from_utc_offset_datetime(now),
manifest_bytes: fixture_bytes(
"tests/fixtures/repository/rpki.cernet.net/repo/cernet/0/05FC9C5B88506F7C0D3F862C8895BED67E9F8EBA.mft",
),
files,
}
}
struct SinglePackRunner {
policy: Policy,
pack: VerifiedPublicationPointPack,
}
impl PublicationPointRunner for SinglePackRunner {
fn run_publication_point(
&self,
ca: &CaInstanceHandle,
) -> Result<PublicationPointRunResult, String> {
let objects = process_verified_publication_point_pack_for_issuer(
&self.pack,
&self.policy,
&ca.ca_certificate_der,
ca.ca_certificate_rsync_uri.as_deref(),
ca.effective_ip_resources.as_ref(),
ca.effective_as_resources.as_ref(),
time::OffsetDateTime::now_utc(),
);
Ok(PublicationPointRunResult {
source: PublicationPointSource::Fresh,
pack: self.pack.clone(),
warnings: Vec::new(),
objects,
audit: PublicationPointAudit::default(),
discovered_children: Vec::new(),
})
}
}
#[test]
fn crl_mismatch_drops_publication_point_and_cites_rfc_sections() {
let roa_bytes =
fixture_bytes("tests/fixtures/repository/rpki.cernet.net/repo/cernet/0/AS4538.roa");
// Include at least one CRL file but with a URI that does NOT match the EE certificate's CRLDP.
let pack = dummy_pack(vec![
PackFile::from_bytes_compute_sha256("rsync://example.test/repo/not-it.crl", vec![0x01]),
PackFile::from_bytes_compute_sha256("rsync://example.test/repo/a.roa", roa_bytes),
]);
let mut policy = Policy::default();
policy.signed_object_failure_policy = SignedObjectFailurePolicy::DropPublicationPoint;
let runner = SinglePackRunner { policy, pack };
let root = CaInstanceHandle {
depth: 0,
ca_certificate_der: vec![0x01, 0x02, 0x03],
ca_certificate_rsync_uri: None,
effective_ip_resources: None,
effective_as_resources: None,
rsync_base_uri: "rsync://example.test/repo/".to_string(),
manifest_rsync_uri:
"rsync://rpki.cernet.net/repo/cernet/0/05FC9C5B88506F7C0D3F862C8895BED67E9F8EBA.mft"
.to_string(),
publication_point_rsync_uri: "rsync://example.test/repo/".to_string(),
rrdp_notification_uri: None,
};
let out = run_tree_serial_audit(
root,
&runner,
&TreeRunConfig {
max_depth: Some(0),
max_instances: Some(1),
},
)
.expect("run tree audit");
assert_eq!(out.tree.instances_processed, 1);
assert_eq!(out.tree.instances_failed, 0);
assert!(
out.tree.warnings.iter().any(|w| w
.message
.contains("dropping publication point due to invalid ROA")),
"expected publication point drop warning"
);
let w = out
.tree
.warnings
.iter()
.find(|w| {
w.message
.contains("dropping publication point due to invalid ROA")
})
.expect("warning present");
let refs = w.rfc_refs.iter().map(|r| r.0).collect::<Vec<_>>();
assert!(
refs.contains(&"RFC 6487 §4.8.6"),
"expected CRLDP RFC reference in warning: {refs:?}"
);
assert!(
refs.contains(&"RFC 9286 §4.2.1"),
"expected manifest locked-pack RFC reference in warning: {refs:?}"
);
assert_eq!(out.publication_points.len(), 1);
assert_eq!(out.publication_points[0].node_id, Some(0));
assert_eq!(out.publication_points[0].parent_node_id, None);
}