129 lines
4.3 KiB
Rust
129 lines
4.3 KiB
Rust
use std::collections::HashMap;
|
|
use std::path::Path;
|
|
|
|
use rpki::data_model::crl::RpkixCrl;
|
|
use rpki::data_model::manifest::ManifestObject;
|
|
use rpki::data_model::rc::ResourceCertificate;
|
|
use rpki::fetch::rsync::LocalDirRsyncFetcher;
|
|
use rpki::policy::{Policy, SyncPreference};
|
|
use rpki::storage::RocksStore;
|
|
use rpki::sync::rrdp::Fetcher;
|
|
use rpki::validation::objects::IssuerCaCertificateResolver;
|
|
use rpki::validation::run::{run_publication_point_once, verified_pack_exists};
|
|
|
|
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
|
|
}
|
|
|
|
struct NeverHttpFetcher;
|
|
|
|
impl Fetcher for NeverHttpFetcher {
|
|
fn fetch(&self, _uri: &str) -> Result<Vec<u8>, String> {
|
|
Err("http fetch disabled in offline test".to_string())
|
|
}
|
|
}
|
|
|
|
struct MapResolver {
|
|
by_subject_dn: HashMap<String, Vec<u8>>,
|
|
}
|
|
|
|
impl IssuerCaCertificateResolver for MapResolver {
|
|
fn resolve_by_subject_dn(&self, subject_dn: &str) -> Option<Vec<u8>> {
|
|
self.by_subject_dn.get(subject_dn).cloned()
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn e2e_offline_uses_rsync_then_writes_verified_pack_then_outputs_vrps() {
|
|
let fixture_dir = Path::new("tests/fixtures/repository/rpki.cernet.net/repo/cernet/0");
|
|
let rsync_base_uri = "rsync://rpki.cernet.net/repo/cernet/0/";
|
|
let manifest_path = fixture_dir.join("05FC9C5B88506F7C0D3F862C8895BED67E9F8EBA.mft");
|
|
let manifest_rsync_uri = fixture_to_rsync_uri(&manifest_path);
|
|
let publication_point_rsync_uri = fixture_dir_to_rsync_uri(fixture_dir);
|
|
|
|
let issuer_ca_der = std::fs::read("tests/fixtures/repository/rpki.apnic.net/repository/B527EF581D6611E2BB468F7C72FD1FF2/BfycW4hQb3wNP4YsiJW-1n6fjro.cer")
|
|
.expect("read issuer ca");
|
|
let issuer_ca = ResourceCertificate::decode_der(&issuer_ca_der).expect("decode issuer ca");
|
|
|
|
// Choose a validation_time that is safely inside:
|
|
// - manifest thisUpdate..nextUpdate
|
|
// - issuer CA validity
|
|
// - CRL thisUpdate..nextUpdate
|
|
let manifest_der = std::fs::read(&manifest_path).expect("read manifest");
|
|
let manifest = ManifestObject::decode_der(&manifest_der).expect("decode manifest");
|
|
|
|
let crl_der = std::fs::read(fixture_dir.join("05FC9C5B88506F7C0D3F862C8895BED67E9F8EBA.crl"))
|
|
.expect("read crl");
|
|
let crl = RpkixCrl::decode_der(&crl_der).expect("decode crl");
|
|
|
|
let mut t = manifest.manifest.this_update;
|
|
if issuer_ca.tbs.validity_not_before > t {
|
|
t = issuer_ca.tbs.validity_not_before;
|
|
}
|
|
if crl.this_update.utc > t {
|
|
t = crl.this_update.utc;
|
|
}
|
|
t += time::Duration::seconds(1);
|
|
|
|
let mut policy = Policy::default();
|
|
policy.sync_preference = SyncPreference::RsyncOnly;
|
|
|
|
let rsync_fetcher = LocalDirRsyncFetcher::new(fixture_dir);
|
|
let http_fetcher = NeverHttpFetcher;
|
|
|
|
let resolver = MapResolver {
|
|
by_subject_dn: HashMap::from([(issuer_ca.tbs.subject_dn, issuer_ca_der)]),
|
|
};
|
|
|
|
let temp = tempfile::tempdir().expect("tempdir");
|
|
let store = RocksStore::open(temp.path()).expect("open rocksdb");
|
|
|
|
let expected_files = std::fs::read_dir(fixture_dir)
|
|
.expect("read fixture dir")
|
|
.filter_map(|e| e.ok())
|
|
.filter_map(|e| e.metadata().ok().map(|m| (e, m)))
|
|
.filter(|(_e, m)| m.is_file())
|
|
.count();
|
|
assert!(expected_files >= 3, "fixture dir seems incomplete");
|
|
|
|
let out = run_publication_point_once(
|
|
&store,
|
|
&policy,
|
|
None,
|
|
rsync_base_uri,
|
|
&manifest_rsync_uri,
|
|
&publication_point_rsync_uri,
|
|
&http_fetcher,
|
|
&rsync_fetcher,
|
|
&resolver,
|
|
t,
|
|
)
|
|
.expect("run publication point once");
|
|
|
|
assert!(verified_pack_exists(&store, &manifest_rsync_uri).expect("exists check"));
|
|
assert_eq!(out.repo_sync.objects_written, expected_files);
|
|
|
|
assert!(
|
|
out.objects.vrps.iter().any(|v| v.asn == 4538),
|
|
"expected VRPs for AS4538"
|
|
);
|
|
}
|