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

119 lines
4.1 KiB
Rust

use std::path::Path;
use rpki::data_model::manifest::ManifestObject;
use rpki::policy::{CaFailedFetchPolicy, Policy};
use rpki::storage::{RocksStore, VerifiedKey, VerifiedPublicationPointPack};
use rpki::validation::manifest::process_manifest_publication_point;
fn fixture_to_rsync_uri(path: &Path) -> String {
let rel = path
.strip_prefix("tests/fixtures/repository")
.expect("path under tests/fixtures/repository");
let mut it = rel.components();
let host = it
.next()
.expect("host component")
.as_os_str()
.to_string_lossy();
let rest = it.as_path().to_string_lossy();
format!("rsync://{host}/{rest}")
}
fn fixture_dir_to_rsync_uri(dir: &Path) -> String {
let mut s = fixture_to_rsync_uri(dir);
if !s.ends_with('/') {
s.push('/');
}
s
}
#[test]
fn cache_is_not_used_when_missing_and_fresh_manifest_is_missing() {
let temp = tempfile::tempdir().expect("tempdir");
let store = RocksStore::open(temp.path()).expect("open rocksdb");
let mut policy = Policy::default();
policy.ca_failed_fetch_policy = CaFailedFetchPolicy::UseVerifiedCache;
let err = process_manifest_publication_point(
&store,
&policy,
"rsync://example.net/repo/manifest.mft",
"rsync://example.net/repo/",
time::OffsetDateTime::from_unix_timestamp(0).unwrap(),
)
.expect_err("no raw and no verified cache should fail");
assert!(err.to_string().contains("verified cache entry missing"));
}
#[test]
fn cache_pack_publication_point_mismatch_is_rejected() {
let manifest_path = Path::new(
"tests/fixtures/repository/rpki.cernet.net/repo/cernet/0/05FC9C5B88506F7C0D3F862C8895BED67E9F8EBA.mft",
);
let manifest_bytes = std::fs::read(manifest_path).expect("read manifest fixture");
let manifest = ManifestObject::decode_der(&manifest_bytes).expect("decode manifest fixture");
let validation_time = manifest.manifest.this_update + time::Duration::seconds(1);
let manifest_rsync_uri = fixture_to_rsync_uri(manifest_path);
let publication_point_rsync_uri = fixture_dir_to_rsync_uri(manifest_path.parent().unwrap());
let temp = tempfile::tempdir().expect("tempdir");
let store = RocksStore::open(temp.path()).expect("open rocksdb");
store
.put_raw(&manifest_rsync_uri, &manifest_bytes)
.expect("store manifest");
for entry in &manifest.manifest.files {
let file_path = manifest_path.parent().unwrap().join(&entry.file_name);
let bytes = std::fs::read(&file_path)
.unwrap_or_else(|_| panic!("read fixture file referenced by manifest: {file_path:?}"));
let rsync_uri = format!("{publication_point_rsync_uri}{}", entry.file_name);
store.put_raw(&rsync_uri, &bytes).expect("store file");
}
let policy = Policy::default();
let _ = process_manifest_publication_point(
&store,
&policy,
&manifest_rsync_uri,
&publication_point_rsync_uri,
validation_time,
)
.expect("first run stores verified pack");
// Corrupt the cached pack by changing the publication point.
let key = VerifiedKey::from_manifest_rsync_uri(&manifest_rsync_uri);
let bytes = store
.get_verified(&key)
.expect("get verified")
.expect("verified exists");
let mut pack = VerifiedPublicationPointPack::decode(&bytes).expect("decode pack");
pack.publication_point_rsync_uri = "rsync://evil.invalid/repo/".to_string();
let bytes = pack.encode().expect("re-encode pack");
store
.put_verified(&key, &bytes)
.expect("overwrite verified");
// Remove raw manifest to force cache path.
store
.delete_raw(&manifest_rsync_uri)
.expect("delete raw manifest");
let err = process_manifest_publication_point(
&store,
&policy,
&manifest_rsync_uri,
&publication_point_rsync_uri,
validation_time,
)
.expect_err("cache pack mismatch should fail");
assert!(
err.to_string()
.contains("publication_point_rsync_uri does not match expected")
);
}