use rpki::audit::PublicationPointAudit; use rpki::policy::{Policy, SignedObjectFailurePolicy}; use rpki::storage::{FetchCachePpPack, PackFile, PackTime}; use rpki::validation::manifest::PublicationPointSource; use rpki::validation::objects::process_fetch_cache_pp_pack_for_issuer; use rpki::validation::tree::{ CaInstanceHandle, PublicationPointRunResult, PublicationPointRunner, TreeRunConfig, run_tree_serial_audit, }; fn fixture_bytes(path: &str) -> Vec { 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) -> FetchCachePpPack { let now = time::OffsetDateTime::now_utc(); let manifest_rsync_uri = "rsync://rpki.cernet.net/repo/cernet/0/05FC9C5B88506F7C0D3F862C8895BED67E9F8EBA.mft"; FetchCachePpPack { format_version: FetchCachePpPack::FORMAT_VERSION_V1, manifest_rsync_uri: manifest_rsync_uri.to_string(), publication_point_rsync_uri: "rsync://rpki.cernet.net/repo/cernet/0/".to_string(), manifest_number_be: vec![1], 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: FetchCachePpPack, } impl PublicationPointRunner for SinglePackRunner { fn run_publication_point( &self, ca: &CaInstanceHandle, ) -> Result { let objects = process_fetch_cache_pp_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::>(); 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); }