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

305 lines
10 KiB
Rust

use rpki::policy::{Policy, SignedObjectFailurePolicy};
use rpki::storage::{PackFile, PackTime, VerifiedPublicationPointPack};
use rpki::validation::objects::{
IssuerCaCertificateResolver, ObjectsProcessError, process_verified_publication_point_pack,
process_verified_publication_point_pack_for_issuer,
};
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(manifest_bytes: Vec<u8>, files: Vec<PackFile>) -> VerifiedPublicationPointPack {
let now = time::OffsetDateTime::now_utc();
VerifiedPublicationPointPack {
format_version: VerifiedPublicationPointPack::FORMAT_VERSION_V1,
manifest_rsync_uri: "rsync://example.test/repo/pp/manifest.mft".to_string(),
publication_point_rsync_uri: "rsync://example.test/repo/pp/".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,
files,
}
}
struct NoneResolver;
impl IssuerCaCertificateResolver for NoneResolver {
fn resolve_by_subject_dn(&self, _subject_dn: &str) -> Option<Vec<u8>> {
None
}
}
#[test]
fn process_pack_drop_object_on_missing_issuer_ca_for_roa() {
let manifest_bytes = fixture_bytes(
"tests/fixtures/repository/rpki.cernet.net/repo/cernet/0/05FC9C5B88506F7C0D3F862C8895BED67E9F8EBA.mft",
);
let roa_bytes =
fixture_bytes("tests/fixtures/repository/rpki.cernet.net/repo/cernet/0/AS4538.roa");
let pack = dummy_pack(
manifest_bytes,
vec![PackFile::from_bytes_compute_sha256(
"rsync://rpki.cernet.net/repo/cernet/0/AS4538.roa",
roa_bytes,
)],
);
let policy = Policy {
signed_object_failure_policy: SignedObjectFailurePolicy::DropObject,
..Policy::default()
};
let out =
process_verified_publication_point_pack(&pack, &policy, &NoneResolver, time::OffsetDateTime::now_utc())
.expect("drop_object should not error");
assert_eq!(out.stats.roa_total, 1);
assert_eq!(out.stats.roa_ok, 0);
assert_eq!(out.audit.len(), 1);
assert_eq!(out.warnings.len(), 1);
}
#[test]
fn process_pack_drop_publication_point_on_missing_issuer_ca_for_roa_skips_rest() {
let manifest_bytes = fixture_bytes(
"tests/fixtures/repository/rpki.cernet.net/repo/cernet/0/05FC9C5B88506F7C0D3F862C8895BED67E9F8EBA.mft",
);
let roa_bytes =
fixture_bytes("tests/fixtures/repository/rpki.cernet.net/repo/cernet/0/AS4538.roa");
let aspa_bytes = fixture_bytes(
"tests/fixtures/repository/chloe.sobornost.net/rpki/RIPE-nljobsnijders/5m80fwYws_3FiFD7JiQjAqZ1RYQ.asa",
);
let pack = dummy_pack(
manifest_bytes,
vec![
PackFile::from_bytes_compute_sha256(
"rsync://example.test/repo/pp/first.roa",
roa_bytes.clone(),
),
PackFile::from_bytes_compute_sha256(
"rsync://example.test/repo/pp/second.roa",
roa_bytes,
),
PackFile::from_bytes_compute_sha256(
"rsync://example.test/repo/pp/x.asa",
aspa_bytes,
),
],
);
let policy = Policy {
signed_object_failure_policy: SignedObjectFailurePolicy::DropPublicationPoint,
..Policy::default()
};
let err =
process_verified_publication_point_pack(&pack, &policy, &NoneResolver, time::OffsetDateTime::now_utc())
.unwrap_err();
assert!(matches!(err, ObjectsProcessError::PublicationPointDropped { .. }));
assert!(err.to_string().contains("drop_publication_point"));
}
#[test]
fn process_pack_drop_object_on_missing_issuer_ca_for_aspa() {
let manifest_bytes = fixture_bytes(
"tests/fixtures/repository/rpki.cernet.net/repo/cernet/0/05FC9C5B88506F7C0D3F862C8895BED67E9F8EBA.mft",
);
let aspa_bytes = fixture_bytes(
"tests/fixtures/repository/chloe.sobornost.net/rpki/RIPE-nljobsnijders/5m80fwYws_3FiFD7JiQjAqZ1RYQ.asa",
);
let pack = dummy_pack(
manifest_bytes,
vec![PackFile::from_bytes_compute_sha256(
"rsync://example.test/repo/pp/x.asa",
aspa_bytes,
)],
);
let policy = Policy {
signed_object_failure_policy: SignedObjectFailurePolicy::DropObject,
..Policy::default()
};
let out =
process_verified_publication_point_pack(&pack, &policy, &NoneResolver, time::OffsetDateTime::now_utc())
.expect("drop_object should not error");
assert_eq!(out.stats.aspa_total, 1);
assert_eq!(out.stats.aspa_ok, 0);
assert_eq!(out.audit.len(), 1);
assert_eq!(out.warnings.len(), 1);
}
#[test]
fn process_pack_drop_publication_point_on_missing_issuer_ca_for_aspa_skips_rest() {
let manifest_bytes = fixture_bytes(
"tests/fixtures/repository/rpki.cernet.net/repo/cernet/0/05FC9C5B88506F7C0D3F862C8895BED67E9F8EBA.mft",
);
let roa_bytes =
fixture_bytes("tests/fixtures/repository/rpki.cernet.net/repo/cernet/0/AS4538.roa");
let aspa_bytes = fixture_bytes(
"tests/fixtures/repository/chloe.sobornost.net/rpki/RIPE-nljobsnijders/5m80fwYws_3FiFD7JiQjAqZ1RYQ.asa",
);
let pack = dummy_pack(
manifest_bytes,
vec![
PackFile::from_bytes_compute_sha256(
"rsync://example.test/repo/pp/x.asa",
aspa_bytes,
),
PackFile::from_bytes_compute_sha256(
"rsync://example.test/repo/pp/y.roa",
roa_bytes,
),
],
);
let policy = Policy {
signed_object_failure_policy: SignedObjectFailurePolicy::DropPublicationPoint,
..Policy::default()
};
let err =
process_verified_publication_point_pack(&pack, &policy, &NoneResolver, time::OffsetDateTime::now_utc())
.unwrap_err();
assert!(matches!(err, ObjectsProcessError::PublicationPointDropped { .. }));
}
#[test]
fn process_pack_for_issuer_marks_objects_skipped_when_missing_issuer_crl() {
let manifest_bytes = fixture_bytes(
"tests/fixtures/repository/rpki.cernet.net/repo/cernet/0/05FC9C5B88506F7C0D3F862C8895BED67E9F8EBA.mft",
);
let roa_bytes =
fixture_bytes("tests/fixtures/repository/rpki.cernet.net/repo/cernet/0/AS4538.roa");
let aspa_bytes = fixture_bytes(
"tests/fixtures/repository/chloe.sobornost.net/rpki/RIPE-nljobsnijders/5m80fwYws_3FiFD7JiQjAqZ1RYQ.asa",
);
let pack = dummy_pack(
manifest_bytes,
vec![
PackFile::from_bytes_compute_sha256(
"rsync://example.test/repo/pp/a.roa",
roa_bytes,
),
PackFile::from_bytes_compute_sha256(
"rsync://example.test/repo/pp/a.asa",
aspa_bytes,
),
],
);
let policy = Policy {
signed_object_failure_policy: SignedObjectFailurePolicy::DropObject,
..Policy::default()
};
let out = process_verified_publication_point_pack_for_issuer(
&pack,
&policy,
&[0x01, 0x02, 0x03],
None,
None,
None,
time::OffsetDateTime::now_utc(),
);
assert!(out.stats.publication_point_dropped);
assert_eq!(out.stats.roa_total, 1);
assert_eq!(out.stats.aspa_total, 1);
assert_eq!(out.vrps.len(), 0);
assert_eq!(out.aspas.len(), 0);
assert_eq!(out.audit.len(), 2);
assert_eq!(out.warnings.len(), 1);
}
#[test]
fn process_pack_for_issuer_drop_object_records_errors_and_continues() {
let manifest_bytes = fixture_bytes(
"tests/fixtures/repository/rpki.cernet.net/repo/cernet/0/05FC9C5B88506F7C0D3F862C8895BED67E9F8EBA.mft",
);
let pack = dummy_pack(
manifest_bytes,
vec![
PackFile::from_bytes_compute_sha256(
"rsync://example.test/repo/pp/issuer.crl",
vec![0x01],
),
PackFile::from_bytes_compute_sha256("rsync://example.test/repo/pp/a.roa", vec![0x00]),
PackFile::from_bytes_compute_sha256("rsync://example.test/repo/pp/b.asa", vec![0x00]),
],
);
let policy = Policy {
signed_object_failure_policy: SignedObjectFailurePolicy::DropObject,
..Policy::default()
};
let out = process_verified_publication_point_pack_for_issuer(
&pack,
&policy,
&[0x01, 0x02, 0x03],
None,
None,
None,
time::OffsetDateTime::now_utc(),
);
assert!(!out.stats.publication_point_dropped);
assert_eq!(out.stats.roa_total, 1);
assert_eq!(out.stats.aspa_total, 1);
assert_eq!(out.audit.len(), 2);
assert_eq!(out.warnings.len(), 2);
}
#[test]
fn process_pack_for_issuer_drop_publication_point_records_skips_for_rest() {
let manifest_bytes = fixture_bytes(
"tests/fixtures/repository/rpki.cernet.net/repo/cernet/0/05FC9C5B88506F7C0D3F862C8895BED67E9F8EBA.mft",
);
let pack = dummy_pack(
manifest_bytes,
vec![
PackFile::from_bytes_compute_sha256(
"rsync://example.test/repo/pp/issuer.crl",
vec![0x01],
),
PackFile::from_bytes_compute_sha256("rsync://example.test/repo/pp/a.roa", vec![0x00]),
PackFile::from_bytes_compute_sha256("rsync://example.test/repo/pp/b.roa", vec![0x00]),
PackFile::from_bytes_compute_sha256("rsync://example.test/repo/pp/c.asa", vec![0x00]),
],
);
let policy = Policy {
signed_object_failure_policy: SignedObjectFailurePolicy::DropPublicationPoint,
..Policy::default()
};
let out = process_verified_publication_point_pack_for_issuer(
&pack,
&policy,
&[0x01, 0x02, 0x03],
None,
None,
None,
time::OffsetDateTime::now_utc(),
);
assert!(out.stats.publication_point_dropped);
assert_eq!(out.stats.roa_total, 2);
assert_eq!(out.stats.aspa_total, 1);
assert!(out.audit.len() >= 3, "expected error + skipped entries");
assert_eq!(out.warnings.len(), 1);
}