rpki/tests/test_run_tree_from_tal_offline_m17.rs
2026-02-09 19:35:54 +08:00

223 lines
7.3 KiB
Rust

use rpki::validation::from_tal::discover_root_ca_instance_from_tal_and_ta_der;
use rpki::validation::run_tree_from_tal::root_handle_from_trust_anchor;
use rpki::validation::run_tree_from_tal::{
run_tree_from_tal_and_ta_der_serial, run_tree_from_tal_url_serial,
run_tree_from_tal_and_ta_der_serial_audit, run_tree_from_tal_url_serial_audit,
};
use rpki::validation::tree::TreeRunConfig;
use std::collections::HashMap;
struct MapHttpFetcher {
map: HashMap<String, Vec<u8>>,
}
impl rpki::sync::rrdp::Fetcher for MapHttpFetcher {
fn fetch(&self, uri: &str) -> Result<Vec<u8>, String> {
self.map
.get(uri)
.cloned()
.ok_or_else(|| format!("no fixture mapped for {uri}"))
}
}
struct EmptyRsyncFetcher;
impl rpki::fetch::rsync::RsyncFetcher for EmptyRsyncFetcher {
fn fetch_objects(&self, _rsync_base_uri: &str) -> Result<Vec<(String, Vec<u8>)>, rpki::fetch::rsync::RsyncFetchError> {
Ok(Vec::new())
}
}
#[test]
fn root_handle_is_constructible_from_fixture_tal_and_ta() {
let tal_bytes = std::fs::read("tests/fixtures/tal/apnic-rfc7730-https.tal")
.expect("read apnic tal fixture");
let ta_der = std::fs::read("tests/fixtures/ta/apnic-ta.cer").expect("read apnic ta fixture");
let discovery =
discover_root_ca_instance_from_tal_and_ta_der(&tal_bytes, &ta_der, None).expect("discover");
let root =
root_handle_from_trust_anchor(&discovery.trust_anchor, None, &discovery.ca_instance);
assert_eq!(root.depth, 0);
assert_eq!(root.manifest_rsync_uri, discovery.ca_instance.manifest_rsync_uri);
assert_eq!(root.rsync_base_uri, discovery.ca_instance.rsync_base_uri);
assert!(root.ca_certificate_der.len() > 100, "TA der should be non-empty");
}
#[test]
fn run_tree_from_tal_url_entry_executes_and_records_failure_when_repo_empty() {
let tal_url = "mock:apnic.tal";
let tal_bytes = std::fs::read("tests/fixtures/tal/apnic-rfc7730-https.tal")
.expect("read apnic tal fixture");
let ta_der = std::fs::read("tests/fixtures/ta/apnic-ta.cer").expect("read apnic ta fixture");
let mut map = HashMap::new();
map.insert(tal_url.to_string(), tal_bytes);
map.insert(
"https://rpki.apnic.net/repository/apnic-rpki-root-iana-origin.cer".to_string(),
ta_der.clone(),
);
map.insert(
"rsync://rpki.apnic.net/repository/apnic-rpki-root-iana-origin.cer".to_string(),
ta_der.clone(),
);
let http = MapHttpFetcher { map };
let rsync = EmptyRsyncFetcher;
let temp = tempfile::tempdir().expect("tempdir");
let store = rpki::storage::RocksStore::open(temp.path()).expect("open rocksdb");
let policy = rpki::policy::Policy {
sync_preference: rpki::policy::SyncPreference::RsyncOnly,
..rpki::policy::Policy::default()
};
let out = run_tree_from_tal_url_serial(
&store,
&policy,
tal_url,
&http,
&rsync,
time::OffsetDateTime::now_utc(),
&TreeRunConfig {
max_depth: Some(0),
max_instances: Some(1),
},
)
.expect("run tree");
assert_eq!(out.tree.instances_processed, 0);
assert_eq!(out.tree.instances_failed, 1);
assert!(
out.tree
.warnings
.iter()
.any(|w| w.message.contains("publication point failed")),
"expected failure warning"
);
}
#[test]
fn run_tree_from_tal_and_ta_der_entry_executes_and_records_failure_when_repo_empty() {
let tal_bytes = std::fs::read("tests/fixtures/tal/apnic-rfc7730-https.tal")
.expect("read apnic tal fixture");
let ta_der = std::fs::read("tests/fixtures/ta/apnic-ta.cer").expect("read apnic ta fixture");
let http = MapHttpFetcher { map: HashMap::new() };
let rsync = EmptyRsyncFetcher;
let temp = tempfile::tempdir().expect("tempdir");
let store = rpki::storage::RocksStore::open(temp.path()).expect("open rocksdb");
let policy = rpki::policy::Policy {
sync_preference: rpki::policy::SyncPreference::RsyncOnly,
..rpki::policy::Policy::default()
};
let out = run_tree_from_tal_and_ta_der_serial(
&store,
&policy,
&tal_bytes,
&ta_der,
None,
&http,
&rsync,
time::OffsetDateTime::now_utc(),
&TreeRunConfig {
max_depth: Some(0),
max_instances: Some(1),
},
)
.expect("run tree");
assert_eq!(out.tree.instances_processed, 0);
assert_eq!(out.tree.instances_failed, 1);
assert!(
out.tree
.warnings
.iter()
.any(|w| w.message.contains("publication point failed")),
"expected failure warning"
);
}
#[test]
fn run_tree_from_tal_url_audit_entry_collects_no_publication_points_when_repo_empty() {
let tal_url = "mock:apnic.tal";
let tal_bytes = std::fs::read("tests/fixtures/tal/apnic-rfc7730-https.tal")
.expect("read apnic tal fixture");
let ta_der = std::fs::read("tests/fixtures/ta/apnic-ta.cer").expect("read apnic ta fixture");
let mut map = HashMap::new();
map.insert(tal_url.to_string(), tal_bytes);
map.insert(
"https://rpki.apnic.net/repository/apnic-rpki-root-iana-origin.cer".to_string(),
ta_der.clone(),
);
map.insert(
"rsync://rpki.apnic.net/repository/apnic-rpki-root-iana-origin.cer".to_string(),
ta_der.clone(),
);
let http = MapHttpFetcher { map };
let rsync = EmptyRsyncFetcher;
let temp = tempfile::tempdir().expect("tempdir");
let store = rpki::storage::RocksStore::open(temp.path()).expect("open rocksdb");
let policy = rpki::policy::Policy {
sync_preference: rpki::policy::SyncPreference::RsyncOnly,
..rpki::policy::Policy::default()
};
let out = run_tree_from_tal_url_serial_audit(
&store,
&policy,
tal_url,
&http,
&rsync,
time::OffsetDateTime::now_utc(),
&TreeRunConfig {
max_depth: Some(0),
max_instances: Some(1),
},
)
.expect("run tree audit");
assert_eq!(out.tree.instances_processed, 0);
assert_eq!(out.tree.instances_failed, 1);
assert!(out.publication_points.is_empty());
}
#[test]
fn run_tree_from_tal_and_ta_der_audit_entry_collects_no_publication_points_when_repo_empty() {
let tal_bytes = std::fs::read("tests/fixtures/tal/apnic-rfc7730-https.tal")
.expect("read apnic tal fixture");
let ta_der = std::fs::read("tests/fixtures/ta/apnic-ta.cer").expect("read apnic ta fixture");
let http = MapHttpFetcher { map: HashMap::new() };
let rsync = EmptyRsyncFetcher;
let temp = tempfile::tempdir().expect("tempdir");
let store = rpki::storage::RocksStore::open(temp.path()).expect("open rocksdb");
let policy = rpki::policy::Policy {
sync_preference: rpki::policy::SyncPreference::RsyncOnly,
..rpki::policy::Policy::default()
};
let out = run_tree_from_tal_and_ta_der_serial_audit(
&store,
&policy,
&tal_bytes,
&ta_der,
None,
&http,
&rsync,
time::OffsetDateTime::now_utc(),
&TreeRunConfig {
max_depth: Some(0),
max_instances: Some(1),
},
)
.expect("run tree audit");
assert_eq!(out.tree.instances_processed, 0);
assert_eq!(out.tree.instances_failed, 1);
assert!(out.publication_points.is_empty());
}