20260410 完成五个rir 基于cir的三方回放,raw by hash 独立db,发现内存占用大,连续大rir 录制发生oom
This commit is contained in:
@@ -311,7 +311,9 @@ fn landing_packfile_cbor_put(store: &RocksStore, obj_type: ObjType, sample: &str
|
||||
entry.origin_uris.push(key);
|
||||
entry.object_type = Some("cbor".to_string());
|
||||
entry.encoding = Some("cbor".to_string());
|
||||
store.put_raw_by_hash_entry(&entry).expect("store raw_by_hash");
|
||||
store
|
||||
.put_raw_by_hash_entry(&entry)
|
||||
.expect("store raw_by_hash");
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, serde::Serialize)]
|
||||
@@ -624,7 +626,9 @@ fn stage2_decode_validate_and_landing_benchmark_selected_der_v2() {
|
||||
println!();
|
||||
}
|
||||
if mode.do_landing() {
|
||||
println!("## landing (PackFile::from_bytes_compute_sha256 + CBOR + RocksDB current-state landing)");
|
||||
println!(
|
||||
"## landing (PackFile::from_bytes_compute_sha256 + CBOR + RocksDB current-state landing)"
|
||||
);
|
||||
println!();
|
||||
println!("| type | sample | size_bytes | complexity | avg ns/op | ops/s |");
|
||||
println!("|---|---|---:|---:|---:|---:|");
|
||||
|
||||
@@ -30,6 +30,7 @@ fn live_http_fetcher() -> BlockingHttpFetcher {
|
||||
timeout: Duration::from_secs(timeout_secs),
|
||||
large_body_timeout: Duration::from_secs(timeout_secs),
|
||||
user_agent: "rpki-dev/0.1 (stage2 live rrdp delta test)".to_string(),
|
||||
..HttpFetcherConfig::default()
|
||||
})
|
||||
.expect("http fetcher")
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
use rpki::ccr::{
|
||||
AspaPayloadSet, AspaPayloadState, CcrContentInfo, CcrDigestAlgorithm, ManifestInstance,
|
||||
ManifestState, RoaPayloadSet, RoaPayloadState, RouterKey, RouterKeySet, RouterKeyState,
|
||||
RpkiCanonicalCacheRepresentation, TrustAnchorState, compute_state_hash,
|
||||
decode_content_info, encode::{
|
||||
RpkiCanonicalCacheRepresentation, TrustAnchorState, compute_state_hash, decode_content_info,
|
||||
encode::{
|
||||
encode_manifest_state_payload_der, encode_router_key_state_payload_der,
|
||||
encode_trust_anchor_state_payload_der,
|
||||
},
|
||||
@@ -22,7 +22,8 @@ fn sample_time() -> time::OffsetDateTime {
|
||||
#[test]
|
||||
fn minimal_trust_anchor_ccr_roundtrips() {
|
||||
let skis = vec![vec![0x11; 20], vec![0x22; 20]];
|
||||
let skis_der = encode_trust_anchor_state_payload_der(&skis).expect("encode trust anchor payload");
|
||||
let skis_der =
|
||||
encode_trust_anchor_state_payload_der(&skis).expect("encode trust anchor payload");
|
||||
let state = TrustAnchorState {
|
||||
skis,
|
||||
hash: compute_state_hash(&skis_der),
|
||||
@@ -47,7 +48,8 @@ fn minimal_trust_anchor_ccr_roundtrips() {
|
||||
#[test]
|
||||
fn decode_rejects_wrong_content_type_oid() {
|
||||
let skis = vec![vec![0x11; 20]];
|
||||
let skis_der = encode_trust_anchor_state_payload_der(&skis).expect("encode trust anchor payload");
|
||||
let skis_der =
|
||||
encode_trust_anchor_state_payload_der(&skis).expect("encode trust anchor payload");
|
||||
let content_info = CcrContentInfo::new(RpkiCanonicalCacheRepresentation {
|
||||
version: 0,
|
||||
hash_alg: CcrDigestAlgorithm::Sha256,
|
||||
@@ -69,7 +71,10 @@ fn decode_rejects_wrong_content_type_oid() {
|
||||
.expect("oid present");
|
||||
der[pos + needle.len() - 1] ^= 0x01;
|
||||
let err = decode_content_info(&der).expect_err("wrong content type must fail");
|
||||
assert!(err.to_string().contains("unexpected contentType OID"), "{err}");
|
||||
assert!(
|
||||
err.to_string().contains("unexpected contentType OID"),
|
||||
"{err}"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -85,13 +90,17 @@ fn ccr_requires_at_least_one_state_aspect() {
|
||||
rks: None,
|
||||
});
|
||||
let err = encode_content_info(&ccr).expect_err("empty state aspects must fail");
|
||||
assert!(err.to_string().contains("at least one of mfts/vrps/vaps/tas/rks"));
|
||||
assert!(
|
||||
err.to_string()
|
||||
.contains("at least one of mfts/vrps/vaps/tas/rks")
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn state_hash_helpers_accept_matching_and_reject_tampered_payload() {
|
||||
let skis = vec![vec![0x11; 20]];
|
||||
let payload_der = encode_trust_anchor_state_payload_der(&skis).expect("encode trust anchor payload");
|
||||
let payload_der =
|
||||
encode_trust_anchor_state_payload_der(&skis).expect("encode trust anchor payload");
|
||||
let hash = compute_state_hash(&payload_der);
|
||||
assert!(verify_state_hash(&hash, &payload_der));
|
||||
let mut tampered = payload_der.clone();
|
||||
@@ -105,12 +114,15 @@ fn manifest_and_router_key_skeletons_encode_payloads_and_validate_sorting() {
|
||||
hash: vec![0x33; 32],
|
||||
size: 2048,
|
||||
aki: vec![0x44; 20],
|
||||
manifest_number: BigUnsigned { bytes_be: vec![0x01] },
|
||||
manifest_number: BigUnsigned {
|
||||
bytes_be: vec![0x01],
|
||||
},
|
||||
this_update: sample_time(),
|
||||
locations: vec![vec![0x30, 0x00]],
|
||||
subordinates: vec![vec![0x55; 20]],
|
||||
}];
|
||||
let mis_der = encode_manifest_state_payload_der(&manifest_instances).expect("encode manifest state payload");
|
||||
let mis_der = encode_manifest_state_payload_der(&manifest_instances)
|
||||
.expect("encode manifest state payload");
|
||||
let manifest_state = ManifestState {
|
||||
mis: manifest_instances,
|
||||
most_recent_update: sample_time(),
|
||||
@@ -239,10 +251,16 @@ fn decode_rejects_wrong_digest_algorithm_oid() {
|
||||
});
|
||||
let mut der = encode_content_info(&ccr).expect("encode ccr");
|
||||
let oid = rpki::data_model::oid::OID_SHA256_RAW;
|
||||
let pos = der.windows(oid.len()).position(|w| w == oid).expect("sha256 oid present");
|
||||
let pos = der
|
||||
.windows(oid.len())
|
||||
.position(|w| w == oid)
|
||||
.expect("sha256 oid present");
|
||||
der[pos + oid.len() - 1] ^= 0x01;
|
||||
let err = decode_content_info(&der).expect_err("decode must reject wrong digest oid");
|
||||
assert!(err.to_string().contains("unexpected digest algorithm OID"), "{err}");
|
||||
assert!(
|
||||
err.to_string().contains("unexpected digest algorithm OID"),
|
||||
"{err}"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -258,7 +276,10 @@ fn decode_rejects_bad_generalized_time() {
|
||||
rks: None,
|
||||
});
|
||||
let mut der = encode_content_info(&ccr).expect("encode ccr");
|
||||
let pos = der.windows(15).position(|w| w == b"20260324000000Z").expect("time present");
|
||||
let pos = der
|
||||
.windows(15)
|
||||
.position(|w| w == b"20260324000000Z")
|
||||
.expect("time present");
|
||||
der[pos + 14] = b'X';
|
||||
let err = decode_content_info(&der).expect_err("bad time must fail");
|
||||
assert!(err.to_string().contains("GeneralizedTime"), "{err}");
|
||||
@@ -268,7 +289,9 @@ fn decode_rejects_bad_generalized_time() {
|
||||
fn manifest_state_validate_rejects_unsorted_subordinates() {
|
||||
let mut state = sample_manifest_state();
|
||||
state.mis[0].subordinates = vec![vec![0x40; 20], vec![0x30; 20]];
|
||||
let err = state.validate().expect_err("unsorted subordinates must fail");
|
||||
let err = state
|
||||
.validate()
|
||||
.expect_err("unsorted subordinates must fail");
|
||||
assert!(err.to_string().contains("subordinates"), "{err}");
|
||||
}
|
||||
|
||||
@@ -276,8 +299,14 @@ fn manifest_state_validate_rejects_unsorted_subordinates() {
|
||||
fn roa_payload_state_validate_rejects_duplicate_asn_sets() {
|
||||
let state = RoaPayloadState {
|
||||
rps: vec![
|
||||
RoaPayloadSet { as_id: 64496, ip_addr_blocks: vec![vec![0x30, 0x00]] },
|
||||
RoaPayloadSet { as_id: 64496, ip_addr_blocks: vec![vec![0x30, 0x00]] },
|
||||
RoaPayloadSet {
|
||||
as_id: 64496,
|
||||
ip_addr_blocks: vec![vec![0x30, 0x00]],
|
||||
},
|
||||
RoaPayloadSet {
|
||||
as_id: 64496,
|
||||
ip_addr_blocks: vec![vec![0x30, 0x00]],
|
||||
},
|
||||
],
|
||||
hash: vec![0u8; 32],
|
||||
};
|
||||
@@ -288,7 +317,10 @@ fn roa_payload_state_validate_rejects_duplicate_asn_sets() {
|
||||
#[test]
|
||||
fn aspa_payload_state_validate_rejects_unsorted_providers() {
|
||||
let state = AspaPayloadState {
|
||||
aps: vec![AspaPayloadSet { customer_as_id: 64496, providers: vec![64498, 64497] }],
|
||||
aps: vec![AspaPayloadSet {
|
||||
customer_as_id: 64496,
|
||||
providers: vec![64498, 64497],
|
||||
}],
|
||||
hash: vec![0u8; 32],
|
||||
};
|
||||
let err = state.validate().expect_err("unsorted providers must fail");
|
||||
@@ -311,13 +343,21 @@ fn router_key_state_validate_rejects_unsorted_router_keys() {
|
||||
rksets: vec![RouterKeySet {
|
||||
as_id: 64496,
|
||||
router_keys: vec![
|
||||
RouterKey { ski: vec![0x42; 20], spki_der: vec![0x30, 0x00] },
|
||||
RouterKey { ski: vec![0x41; 20], spki_der: vec![0x30, 0x00] },
|
||||
RouterKey {
|
||||
ski: vec![0x42; 20],
|
||||
spki_der: vec![0x30, 0x00],
|
||||
},
|
||||
RouterKey {
|
||||
ski: vec![0x41; 20],
|
||||
spki_der: vec![0x30, 0x00],
|
||||
},
|
||||
],
|
||||
}],
|
||||
hash: vec![0u8; 32],
|
||||
};
|
||||
let err = state.validate().expect_err("unsorted router keys must fail");
|
||||
let err = state
|
||||
.validate()
|
||||
.expect_err("unsorted router keys must fail");
|
||||
assert!(err.to_string().contains("router_keys"), "{err}");
|
||||
}
|
||||
|
||||
@@ -332,6 +372,8 @@ fn manifest_instance_validate_rejects_bad_location_tag() {
|
||||
locations: vec![vec![0x04, 0x00]],
|
||||
subordinates: vec![],
|
||||
};
|
||||
let err = instance.validate().expect_err("bad AccessDescription tag must fail");
|
||||
let err = instance
|
||||
.validate()
|
||||
.expect_err("bad AccessDescription tag must fail");
|
||||
assert!(err.to_string().contains("unexpected tag"), "{err}");
|
||||
}
|
||||
|
||||
@@ -1,19 +1,21 @@
|
||||
use rpki::ccr::{
|
||||
CcrContentInfo, CcrDigestAlgorithm, ManifestInstance, ManifestState, RoaPayloadSet,
|
||||
RoaPayloadState, RouterKey, RouterKeySet, RouterKeyState, TrustAnchorState,
|
||||
compute_state_hash, decode_content_info, dump_content_info_json_value,
|
||||
RoaPayloadState, RouterKey, RouterKeySet, RouterKeyState, TrustAnchorState, compute_state_hash,
|
||||
decode_content_info, dump_content_info_json_value,
|
||||
encode::{
|
||||
encode_aspa_payload_state_payload_der, encode_content_info,
|
||||
encode_manifest_state_payload_der, encode_roa_payload_state_payload_der,
|
||||
encode_router_key_state_payload_der, encode_trust_anchor_state_payload_der,
|
||||
},
|
||||
verify::{verify_against_report_json_path, verify_against_vcir_store, verify_content_info_bytes},
|
||||
verify::{
|
||||
verify_against_report_json_path, verify_against_vcir_store, verify_content_info_bytes,
|
||||
},
|
||||
};
|
||||
use rpki::data_model::common::BigUnsigned;
|
||||
use rpki::storage::{
|
||||
PackTime, RocksStore, ValidatedCaInstanceResult, ValidatedManifestMeta,
|
||||
VcirArtifactKind, VcirArtifactRole, VcirArtifactValidationStatus, VcirAuditSummary,
|
||||
VcirChildEntry, VcirInstanceGate, VcirRelatedArtifact, VcirSummary,
|
||||
PackTime, RocksStore, ValidatedCaInstanceResult, ValidatedManifestMeta, VcirArtifactKind,
|
||||
VcirArtifactRole, VcirArtifactValidationStatus, VcirAuditSummary, VcirChildEntry,
|
||||
VcirInstanceGate, VcirRelatedArtifact, VcirSummary,
|
||||
};
|
||||
|
||||
fn sample_time() -> time::OffsetDateTime {
|
||||
@@ -45,28 +47,51 @@ fn sample_manifest_state() -> ManifestState {
|
||||
fn sample_roa_state() -> RoaPayloadState {
|
||||
let rps = vec![RoaPayloadSet {
|
||||
as_id: 64496,
|
||||
ip_addr_blocks: vec![vec![0x30, 0x08, 0x04, 0x02, 0x00, 0x01, 0x30, 0x02, 0x03, 0x00]],
|
||||
ip_addr_blocks: vec![vec![
|
||||
0x30, 0x08, 0x04, 0x02, 0x00, 0x01, 0x30, 0x02, 0x03, 0x00,
|
||||
]],
|
||||
}];
|
||||
let der = encode_roa_payload_state_payload_der(&rps).expect("encode rps");
|
||||
RoaPayloadState { rps, hash: compute_state_hash(&der) }
|
||||
RoaPayloadState {
|
||||
rps,
|
||||
hash: compute_state_hash(&der),
|
||||
}
|
||||
}
|
||||
|
||||
fn sample_aspa_state() -> rpki::ccr::AspaPayloadState {
|
||||
let aps = vec![rpki::ccr::AspaPayloadSet { customer_as_id: 64496, providers: vec![64497] }];
|
||||
let aps = vec![rpki::ccr::AspaPayloadSet {
|
||||
customer_as_id: 64496,
|
||||
providers: vec![64497],
|
||||
}];
|
||||
let der = encode_aspa_payload_state_payload_der(&aps).expect("encode aps");
|
||||
rpki::ccr::AspaPayloadState { aps, hash: compute_state_hash(&der) }
|
||||
rpki::ccr::AspaPayloadState {
|
||||
aps,
|
||||
hash: compute_state_hash(&der),
|
||||
}
|
||||
}
|
||||
|
||||
fn sample_ta_state() -> TrustAnchorState {
|
||||
let skis = vec![vec![0x11; 20]];
|
||||
let der = encode_trust_anchor_state_payload_der(&skis).expect("encode skis");
|
||||
TrustAnchorState { skis, hash: compute_state_hash(&der) }
|
||||
TrustAnchorState {
|
||||
skis,
|
||||
hash: compute_state_hash(&der),
|
||||
}
|
||||
}
|
||||
|
||||
fn sample_rks() -> RouterKeyState {
|
||||
let rksets = vec![RouterKeySet { as_id: 64496, router_keys: vec![RouterKey { ski: vec![0x22; 20], spki_der: vec![0x30, 0x00] }] }];
|
||||
let rksets = vec![RouterKeySet {
|
||||
as_id: 64496,
|
||||
router_keys: vec![RouterKey {
|
||||
ski: vec![0x22; 20],
|
||||
spki_der: vec![0x30, 0x00],
|
||||
}],
|
||||
}];
|
||||
let der = encode_router_key_state_payload_der(&rksets).expect("encode rk");
|
||||
RouterKeyState { rksets, hash: compute_state_hash(&der) }
|
||||
RouterKeyState {
|
||||
rksets,
|
||||
hash: compute_state_hash(&der),
|
||||
}
|
||||
}
|
||||
|
||||
fn sample_ccr() -> Vec<u8> {
|
||||
@@ -102,7 +127,10 @@ fn verify_content_info_bytes_rejects_tampered_manifest_hash() {
|
||||
content_info.content.mfts.as_mut().unwrap().hash[0] ^= 0x01;
|
||||
let der = encode_content_info(&content_info).expect("encode tampered ccr");
|
||||
let err = verify_content_info_bytes(&der).expect_err("tampered hash must fail");
|
||||
assert!(err.to_string().contains("ManifestState hash mismatch"), "{err}");
|
||||
assert!(
|
||||
err.to_string().contains("ManifestState hash mismatch"),
|
||||
"{err}"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -128,8 +156,21 @@ fn verify_against_report_json_path_rejects_mismatching_report() {
|
||||
|
||||
let mut ci = decode_content_info(&sample_ccr()).expect("decode ccr");
|
||||
ci.content.vrps = Some(RoaPayloadState {
|
||||
rps: vec![RoaPayloadSet { as_id: 64496, ip_addr_blocks: vec![vec![0x30, 0x08, 0x04, 0x02, 0x00, 0x01, 0x30, 0x02, 0x03, 0x00]] }],
|
||||
hash: compute_state_hash(&encode_roa_payload_state_payload_der(&[RoaPayloadSet { as_id: 64496, ip_addr_blocks: vec![vec![0x30, 0x08, 0x04, 0x02, 0x00, 0x01, 0x30, 0x02, 0x03, 0x00]] }]).unwrap()),
|
||||
rps: vec![RoaPayloadSet {
|
||||
as_id: 64496,
|
||||
ip_addr_blocks: vec![vec![
|
||||
0x30, 0x08, 0x04, 0x02, 0x00, 0x01, 0x30, 0x02, 0x03, 0x00,
|
||||
]],
|
||||
}],
|
||||
hash: compute_state_hash(
|
||||
&encode_roa_payload_state_payload_der(&[RoaPayloadSet {
|
||||
as_id: 64496,
|
||||
ip_addr_blocks: vec![vec![
|
||||
0x30, 0x08, 0x04, 0x02, 0x00, 0x01, 0x30, 0x02, 0x03, 0x00,
|
||||
]],
|
||||
}])
|
||||
.unwrap(),
|
||||
),
|
||||
});
|
||||
verify_against_report_json_path(&ci, &report_path).expect_err("report mismatch expected");
|
||||
}
|
||||
@@ -184,7 +225,7 @@ fn verify_against_vcir_store_matches_manifest_hashes() {
|
||||
summary: VcirSummary {
|
||||
local_vrp_count: 0,
|
||||
local_aspa_count: 0,
|
||||
local_router_key_count: 0,
|
||||
local_router_key_count: 0,
|
||||
child_count: 1,
|
||||
accepted_object_count: 1,
|
||||
rejected_object_count: 0,
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
use rpki::ccr::{
|
||||
CcrContentInfo, CcrDigestAlgorithm, TrustAnchorState, compute_state_hash,
|
||||
encode::{encode_content_info, encode_trust_anchor_state_payload_der},
|
||||
@@ -20,7 +19,10 @@ fn sample_ccr_file() -> (tempfile::TempDir, std::path::PathBuf) {
|
||||
mfts: None,
|
||||
vrps: None,
|
||||
vaps: None,
|
||||
tas: Some(TrustAnchorState { skis, hash: compute_state_hash(&skis_der) }),
|
||||
tas: Some(TrustAnchorState {
|
||||
skis,
|
||||
hash: compute_state_hash(&skis_der),
|
||||
}),
|
||||
rks: None,
|
||||
});
|
||||
let path = dir.path().join("sample.ccr");
|
||||
@@ -36,7 +38,11 @@ fn ccr_dump_binary_prints_json_summary() {
|
||||
.args(["--ccr", ccr_path.to_string_lossy().as_ref()])
|
||||
.output()
|
||||
.expect("run ccr_dump");
|
||||
assert!(out.status.success(), "stderr={}", String::from_utf8_lossy(&out.stderr));
|
||||
assert!(
|
||||
out.status.success(),
|
||||
"stderr={}",
|
||||
String::from_utf8_lossy(&out.stderr)
|
||||
);
|
||||
let json: serde_json::Value = serde_json::from_slice(&out.stdout).expect("parse json");
|
||||
assert_eq!(json["version"], 0);
|
||||
assert_eq!(json["state_aspects"]["tas"]["ski_count"], 1);
|
||||
@@ -50,22 +56,25 @@ fn ccr_verify_binary_prints_summary() {
|
||||
.args(["--ccr", ccr_path.to_string_lossy().as_ref()])
|
||||
.output()
|
||||
.expect("run ccr_verify");
|
||||
assert!(out.status.success(), "stderr={}", String::from_utf8_lossy(&out.stderr));
|
||||
assert!(
|
||||
out.status.success(),
|
||||
"stderr={}",
|
||||
String::from_utf8_lossy(&out.stderr)
|
||||
);
|
||||
let json: serde_json::Value = serde_json::from_slice(&out.stdout).expect("parse json");
|
||||
assert_eq!(json["version"], 0);
|
||||
assert_eq!(json["trust_anchor_ski_count"], 1);
|
||||
assert_eq!(json["state_hashes_ok"], true);
|
||||
}
|
||||
|
||||
|
||||
#[test]
|
||||
fn ccr_to_routinator_csv_binary_writes_vrp_csv() {
|
||||
use rpki::ccr::{
|
||||
CcrContentInfo, CcrDigestAlgorithm, RpkiCanonicalCacheRepresentation,
|
||||
build_roa_payload_state, encode::encode_content_info,
|
||||
};
|
||||
use rpki::validation::objects::Vrp;
|
||||
use rpki::data_model::roa::{IpPrefix, RoaAfi};
|
||||
use rpki::validation::objects::Vrp;
|
||||
let dir = tempfile::tempdir().expect("tempdir");
|
||||
let ccr_path = dir.path().join("vrp.ccr");
|
||||
let csv_path = dir.path().join("out.csv");
|
||||
@@ -107,7 +116,11 @@ fn ccr_to_routinator_csv_binary_writes_vrp_csv() {
|
||||
])
|
||||
.output()
|
||||
.expect("run ccr_to_routinator_csv");
|
||||
assert!(out.status.success(), "stderr={}", String::from_utf8_lossy(&out.stderr));
|
||||
assert!(
|
||||
out.status.success(),
|
||||
"stderr={}",
|
||||
String::from_utf8_lossy(&out.stderr)
|
||||
);
|
||||
let csv = std::fs::read_to_string(csv_path).expect("read csv");
|
||||
assert!(csv.contains("ASN,IP Prefix,Max Length,Trust Anchor"));
|
||||
assert!(csv.contains("AS64496,203.0.113.0/24,24,apnic"));
|
||||
@@ -171,7 +184,11 @@ fn ccr_to_compare_views_binary_writes_vrp_and_vap_csvs() {
|
||||
])
|
||||
.output()
|
||||
.expect("run ccr_to_compare_views");
|
||||
assert!(out.status.success(), "stderr={}", String::from_utf8_lossy(&out.stderr));
|
||||
assert!(
|
||||
out.status.success(),
|
||||
"stderr={}",
|
||||
String::from_utf8_lossy(&out.stderr)
|
||||
);
|
||||
|
||||
let vrps_csv = std::fs::read_to_string(vrps_path).expect("read vrps csv");
|
||||
let vaps_csv = std::fs::read_to_string(vaps_path).expect("read vaps csv");
|
||||
@@ -234,7 +251,11 @@ fn ccr_to_compare_views_binary_writes_header_only_vap_csv_when_absent() {
|
||||
])
|
||||
.output()
|
||||
.expect("run ccr_to_compare_views");
|
||||
assert!(out.status.success(), "stderr={}", String::from_utf8_lossy(&out.stderr));
|
||||
assert!(
|
||||
out.status.success(),
|
||||
"stderr={}",
|
||||
String::from_utf8_lossy(&out.stderr)
|
||||
);
|
||||
|
||||
let vaps_csv = std::fs::read_to_string(vaps_path).expect("read vaps csv");
|
||||
assert_eq!(vaps_csv, "Customer ASN,Providers,Trust Anchor\n");
|
||||
|
||||
@@ -2,12 +2,18 @@ use std::collections::BTreeSet;
|
||||
use std::path::PathBuf;
|
||||
use std::process::Command;
|
||||
|
||||
use rpki::ccr::{encode_content_info, CcrContentInfo, CcrDigestAlgorithm, RpkiCanonicalCacheRepresentation, TrustAnchorState};
|
||||
use rpki::cir::{encode_cir, CanonicalInputRepresentation, CirHashAlgorithm, CirObject, CirTal, CIR_VERSION_V1};
|
||||
use rpki::ccr::{
|
||||
CcrContentInfo, CcrDigestAlgorithm, RpkiCanonicalCacheRepresentation, TrustAnchorState,
|
||||
encode_content_info,
|
||||
};
|
||||
use rpki::cir::{
|
||||
CIR_VERSION_V1, CanonicalInputRepresentation, CirHashAlgorithm, CirObject, CirTal, encode_cir,
|
||||
};
|
||||
|
||||
#[test]
|
||||
fn cir_full_and_delta_pair_reuses_shared_static_pool() {
|
||||
let script = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("scripts/cir/run_cir_record_full_delta.sh");
|
||||
let script =
|
||||
PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("scripts/cir/run_cir_record_full_delta.sh");
|
||||
let out_dir = tempfile::tempdir().expect("tempdir");
|
||||
let out = out_dir.path().join("cir-pair");
|
||||
let fixture_root = out_dir.path().join("fixture");
|
||||
@@ -16,11 +22,7 @@ fn cir_full_and_delta_pair_reuses_shared_static_pool() {
|
||||
std::fs::create_dir_all(&static_payload_root).unwrap();
|
||||
let base_locks = fixture_root.join("base-locks.json");
|
||||
let delta_locks = fixture_root.join("locks-delta.json");
|
||||
std::fs::write(
|
||||
&base_locks,
|
||||
br#"{"validationTime":"2026-03-16T11:49:15Z"}"#,
|
||||
)
|
||||
.unwrap();
|
||||
std::fs::write(&base_locks, br#"{"validationTime":"2026-03-16T11:49:15Z"}"#).unwrap();
|
||||
std::fs::write(
|
||||
&delta_locks,
|
||||
br#"{"validationTime":"2026-03-16T11:50:15Z"}"#,
|
||||
@@ -84,7 +86,10 @@ fn cir_full_and_delta_pair_reuses_shared_static_pool() {
|
||||
mfts: None,
|
||||
vrps: None,
|
||||
vaps: None,
|
||||
tas: Some(TrustAnchorState { skis: vec![vec![0x11; 20]], hash: vec![0x22; 32] }),
|
||||
tas: Some(TrustAnchorState {
|
||||
skis: vec![vec![0x11; 20]],
|
||||
hash: vec![0x22; 32],
|
||||
}),
|
||||
rks: None,
|
||||
});
|
||||
let full_cir_path = fixture_root.join("full.cir");
|
||||
@@ -97,8 +102,16 @@ fn cir_full_and_delta_pair_reuses_shared_static_pool() {
|
||||
std::fs::write(&delta_cir_path, encode_cir(&delta_cir).unwrap()).unwrap();
|
||||
std::fs::write(&full_ccr_path, encode_content_info(&empty_ccr).unwrap()).unwrap();
|
||||
std::fs::write(&delta_ccr_path, encode_content_info(&empty_ccr).unwrap()).unwrap();
|
||||
std::fs::write(&full_report_path, br#"{"format_version":2,"publication_points":[]}"#).unwrap();
|
||||
std::fs::write(&delta_report_path, br#"{"format_version":2,"publication_points":[]}"#).unwrap();
|
||||
std::fs::write(
|
||||
&full_report_path,
|
||||
br#"{"format_version":2,"publication_points":[]}"#,
|
||||
)
|
||||
.unwrap();
|
||||
std::fs::write(
|
||||
&delta_report_path,
|
||||
br#"{"format_version":2,"publication_points":[]}"#,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let stub = out_dir.path().join("stub-rpki.sh");
|
||||
std::fs::write(
|
||||
@@ -195,8 +208,9 @@ fi
|
||||
String::from_utf8_lossy(&proc.stderr)
|
||||
);
|
||||
|
||||
let full_cir = rpki::cir::decode_cir(&std::fs::read(out.join("full").join("input.cir")).unwrap())
|
||||
.expect("decode full cir");
|
||||
let full_cir =
|
||||
rpki::cir::decode_cir(&std::fs::read(out.join("full").join("input.cir")).unwrap())
|
||||
.expect("decode full cir");
|
||||
let delta_cir =
|
||||
rpki::cir::decode_cir(&std::fs::read(out.join("delta-001").join("input.cir")).unwrap())
|
||||
.expect("decode delta cir");
|
||||
|
||||
@@ -2,10 +2,12 @@ use std::path::PathBuf;
|
||||
use std::process::Command;
|
||||
|
||||
use rpki::ccr::{
|
||||
encode_content_info, CcrContentInfo, CcrDigestAlgorithm, RpkiCanonicalCacheRepresentation,
|
||||
TrustAnchorState,
|
||||
CcrContentInfo, CcrDigestAlgorithm, RpkiCanonicalCacheRepresentation, TrustAnchorState,
|
||||
encode_content_info,
|
||||
};
|
||||
use rpki::cir::{
|
||||
CIR_VERSION_V1, CanonicalInputRepresentation, CirHashAlgorithm, CirObject, CirTal, encode_cir,
|
||||
};
|
||||
use rpki::cir::{encode_cir, CanonicalInputRepresentation, CirHashAlgorithm, CirObject, CirTal, CIR_VERSION_V1};
|
||||
|
||||
#[test]
|
||||
fn cir_drop_report_counts_dropped_roa_objects_and_vrps() {
|
||||
@@ -24,7 +26,10 @@ fn cir_drop_report_counts_dropped_roa_objects_and_vrps() {
|
||||
use sha2::{Digest, Sha256};
|
||||
hex::encode(Sha256::digest(&roa_bytes))
|
||||
};
|
||||
let dir = static_root.join("20260409").join(&hash[0..2]).join(&hash[2..4]);
|
||||
let dir = static_root
|
||||
.join("20260409")
|
||||
.join(&hash[0..2])
|
||||
.join(&hash[2..4]);
|
||||
std::fs::create_dir_all(&dir).unwrap();
|
||||
std::fs::write(dir.join(&hash), &roa_bytes).unwrap();
|
||||
|
||||
@@ -100,12 +105,20 @@ fn cir_drop_report_counts_dropped_roa_objects_and_vrps() {
|
||||
])
|
||||
.output()
|
||||
.expect("run cir_drop_report");
|
||||
assert!(out.status.success(), "stderr={}", String::from_utf8_lossy(&out.stderr));
|
||||
assert!(
|
||||
out.status.success(),
|
||||
"stderr={}",
|
||||
String::from_utf8_lossy(&out.stderr)
|
||||
);
|
||||
|
||||
let output: serde_json::Value =
|
||||
serde_json::from_slice(&std::fs::read(&json_out).unwrap()).unwrap();
|
||||
assert_eq!(output["summary"]["droppedObjectCount"], 1);
|
||||
assert!(output["summary"]["droppedVrpCount"].as_u64().unwrap_or(0) >= 1);
|
||||
assert_eq!(output["summary"]["droppedByKind"]["roa"], 1);
|
||||
assert!(std::fs::read_to_string(&md_out).unwrap().contains("Dropped By Reason"));
|
||||
assert!(
|
||||
std::fs::read_to_string(&md_out)
|
||||
.unwrap()
|
||||
.contains("Dropped By Reason")
|
||||
);
|
||||
}
|
||||
|
||||
@@ -2,8 +2,8 @@ use std::path::{Path, PathBuf};
|
||||
use std::process::Command;
|
||||
|
||||
use rpki::cir::{
|
||||
encode_cir, materialize_cir, CanonicalInputRepresentation, CirHashAlgorithm, CirObject, CirTal,
|
||||
CIR_VERSION_V1,
|
||||
CIR_VERSION_V1, CanonicalInputRepresentation, CirHashAlgorithm, CirObject, CirTal, encode_cir,
|
||||
materialize_cir,
|
||||
};
|
||||
|
||||
fn apnic_tal_path() -> PathBuf {
|
||||
@@ -59,7 +59,11 @@ fn write_static(root: &Path, date: &str, bytes: &[u8]) {
|
||||
std::fs::write(dir.join(hash), bytes).expect("write static object");
|
||||
}
|
||||
|
||||
fn prepare_reference_ccr(work: &Path, cir: &CanonicalInputRepresentation, mirror_root: &Path) -> PathBuf {
|
||||
fn prepare_reference_ccr(
|
||||
work: &Path,
|
||||
cir: &CanonicalInputRepresentation,
|
||||
mirror_root: &Path,
|
||||
) -> PathBuf {
|
||||
let reference_ccr = work.join("reference.ccr");
|
||||
let rpki_bin = env!("CARGO_BIN_EXE_rpki");
|
||||
let wrapper = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("scripts/cir/cir-rsync-wrapper");
|
||||
@@ -91,7 +95,11 @@ fn prepare_reference_ccr(work: &Path, cir: &CanonicalInputRepresentation, mirror
|
||||
])
|
||||
.output()
|
||||
.expect("run reference rpki");
|
||||
assert!(out.status.success(), "stderr={}", String::from_utf8_lossy(&out.stderr));
|
||||
assert!(
|
||||
out.status.success(),
|
||||
"stderr={}",
|
||||
String::from_utf8_lossy(&out.stderr)
|
||||
);
|
||||
reference_ccr
|
||||
}
|
||||
|
||||
@@ -116,7 +124,8 @@ fn cir_replay_matrix_script_matches_reference_for_all_participants() {
|
||||
materialize_cir(&cir, &static_root, &mirror_root, true).expect("materialize");
|
||||
let reference_ccr = prepare_reference_ccr(td.path(), &cir, &mirror_root);
|
||||
|
||||
let script = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("scripts/cir/run_cir_replay_matrix.sh");
|
||||
let script =
|
||||
PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("scripts/cir/run_cir_replay_matrix.sh");
|
||||
let out = Command::new(script)
|
||||
.args([
|
||||
"--cir",
|
||||
@@ -134,13 +143,19 @@ fn cir_replay_matrix_script_matches_reference_for_all_participants() {
|
||||
])
|
||||
.output()
|
||||
.expect("run cir matrix script");
|
||||
assert!(out.status.success(), "stderr={}", String::from_utf8_lossy(&out.stderr));
|
||||
assert!(
|
||||
out.status.success(),
|
||||
"stderr={}",
|
||||
String::from_utf8_lossy(&out.stderr)
|
||||
);
|
||||
|
||||
let summary: serde_json::Value =
|
||||
serde_json::from_slice(&std::fs::read(out_dir.join("summary.json")).expect("read summary"))
|
||||
.expect("parse summary");
|
||||
assert_eq!(summary["allMatch"], true);
|
||||
let participants = summary["participants"].as_array().expect("participants array");
|
||||
let participants = summary["participants"]
|
||||
.as_array()
|
||||
.expect("participants array");
|
||||
assert_eq!(participants.len(), 3);
|
||||
for participant in participants {
|
||||
assert_eq!(participant["exitCode"], 0);
|
||||
|
||||
@@ -59,7 +59,11 @@ fn write_static(root: &Path, date: &str, bytes: &[u8]) {
|
||||
std::fs::write(dir.join(hash), bytes).expect("write static object");
|
||||
}
|
||||
|
||||
fn prepare_reference_ccr(work: &Path, cir: &CanonicalInputRepresentation, mirror_root: &Path) -> PathBuf {
|
||||
fn prepare_reference_ccr(
|
||||
work: &Path,
|
||||
cir: &CanonicalInputRepresentation,
|
||||
mirror_root: &Path,
|
||||
) -> PathBuf {
|
||||
let reference_ccr = work.join("reference.ccr");
|
||||
let rpki_bin = env!("CARGO_BIN_EXE_rpki");
|
||||
let wrapper = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("scripts/cir/cir-rsync-wrapper");
|
||||
@@ -91,7 +95,11 @@ fn prepare_reference_ccr(work: &Path, cir: &CanonicalInputRepresentation, mirror
|
||||
])
|
||||
.output()
|
||||
.expect("run reference rpki");
|
||||
assert!(out.status.success(), "stderr={}", String::from_utf8_lossy(&out.stderr));
|
||||
assert!(
|
||||
out.status.success(),
|
||||
"stderr={}",
|
||||
String::from_utf8_lossy(&out.stderr)
|
||||
);
|
||||
reference_ccr
|
||||
}
|
||||
|
||||
@@ -114,7 +122,8 @@ fn cir_routinator_script_matches_reference_on_ta_only_cir() {
|
||||
materialize_cir(&cir, &static_root, &mirror_root, true).expect("materialize");
|
||||
let reference_ccr = prepare_reference_ccr(td.path(), &cir, &mirror_root);
|
||||
|
||||
let script = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("scripts/cir/run_cir_replay_routinator.sh");
|
||||
let script =
|
||||
PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("scripts/cir/run_cir_replay_routinator.sh");
|
||||
let out = Command::new(script)
|
||||
.args([
|
||||
"--cir",
|
||||
@@ -128,7 +137,11 @@ fn cir_routinator_script_matches_reference_on_ta_only_cir() {
|
||||
])
|
||||
.output()
|
||||
.expect("run routinator cir script");
|
||||
assert!(out.status.success(), "stderr={}", String::from_utf8_lossy(&out.stderr));
|
||||
assert!(
|
||||
out.status.success(),
|
||||
"stderr={}",
|
||||
String::from_utf8_lossy(&out.stderr)
|
||||
);
|
||||
let summary: serde_json::Value = serde_json::from_slice(
|
||||
&std::fs::read(out_dir.join("compare-summary.json")).expect("read summary"),
|
||||
)
|
||||
@@ -156,7 +169,8 @@ fn cir_rpki_client_script_matches_reference_on_ta_only_cir() {
|
||||
materialize_cir(&cir, &static_root, &mirror_root, true).expect("materialize");
|
||||
let reference_ccr = prepare_reference_ccr(td.path(), &cir, &mirror_root);
|
||||
|
||||
let script = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("scripts/cir/run_cir_replay_rpki_client.sh");
|
||||
let script =
|
||||
PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("scripts/cir/run_cir_replay_rpki_client.sh");
|
||||
let out = Command::new(script)
|
||||
.args([
|
||||
"--cir",
|
||||
@@ -172,7 +186,11 @@ fn cir_rpki_client_script_matches_reference_on_ta_only_cir() {
|
||||
])
|
||||
.output()
|
||||
.expect("run rpki-client cir script");
|
||||
assert!(out.status.success(), "stderr={}", String::from_utf8_lossy(&out.stderr));
|
||||
assert!(
|
||||
out.status.success(),
|
||||
"stderr={}",
|
||||
String::from_utf8_lossy(&out.stderr)
|
||||
);
|
||||
let summary: serde_json::Value = serde_json::from_slice(
|
||||
&std::fs::read(out_dir.join("compare-summary.json")).expect("read summary"),
|
||||
)
|
||||
|
||||
@@ -1,27 +1,40 @@
|
||||
use std::path::PathBuf;
|
||||
use std::process::Command;
|
||||
|
||||
use rpki::ccr::{encode_content_info, CcrContentInfo, CcrDigestAlgorithm, RpkiCanonicalCacheRepresentation, TrustAnchorState};
|
||||
use rpki::cir::{encode_cir, CanonicalInputRepresentation, CirHashAlgorithm, CirObject, CirTal, CIR_VERSION_V1};
|
||||
use rpki::ccr::{
|
||||
CcrContentInfo, CcrDigestAlgorithm, RpkiCanonicalCacheRepresentation, TrustAnchorState,
|
||||
encode_content_info,
|
||||
};
|
||||
use rpki::cir::{
|
||||
CIR_VERSION_V1, CanonicalInputRepresentation, CirHashAlgorithm, CirObject, CirTal, encode_cir,
|
||||
};
|
||||
|
||||
#[test]
|
||||
fn cir_offline_sequence_writes_parseable_sequence_json_and_steps() {
|
||||
let out_dir = tempfile::tempdir().expect("tempdir");
|
||||
let out = out_dir.path().join("cir-sequence");
|
||||
let script =
|
||||
PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("scripts/cir/run_cir_record_sequence_offline.sh");
|
||||
let script = PathBuf::from(env!("CARGO_MANIFEST_DIR"))
|
||||
.join("scripts/cir/run_cir_record_sequence_offline.sh");
|
||||
let fixture_root = out_dir.path().join("fixture");
|
||||
let static_payload_root = fixture_root.join("payloads");
|
||||
std::fs::create_dir_all(&static_payload_root).unwrap();
|
||||
let base_locks = fixture_root.join("base-locks.json");
|
||||
let delta_locks = fixture_root.join("locks-delta.json");
|
||||
std::fs::write(&base_locks, br#"{"validationTime":"2026-03-16T11:49:15Z"}"#).unwrap();
|
||||
std::fs::write(&delta_locks, br#"{"validationTime":"2026-03-16T11:50:15Z"}"#).unwrap();
|
||||
std::fs::write(
|
||||
&delta_locks,
|
||||
br#"{"validationTime":"2026-03-16T11:50:15Z"}"#,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let mk_cir = |uri: &str, hash_hex: &str, vt: &str| CanonicalInputRepresentation {
|
||||
version: CIR_VERSION_V1,
|
||||
hash_alg: CirHashAlgorithm::Sha256,
|
||||
validation_time: time::OffsetDateTime::parse(vt, &time::format_description::well_known::Rfc3339).unwrap(),
|
||||
validation_time: time::OffsetDateTime::parse(
|
||||
vt,
|
||||
&time::format_description::well_known::Rfc3339,
|
||||
)
|
||||
.unwrap(),
|
||||
objects: vec![CirObject {
|
||||
rsync_uri: uri.to_string(),
|
||||
sha256: hex::decode(hash_hex).unwrap(),
|
||||
@@ -39,7 +52,11 @@ fn cir_offline_sequence_writes_parseable_sequence_json_and_steps() {
|
||||
use sha2::{Digest, Sha256};
|
||||
hex::encode(Sha256::digest(b"delta-object"))
|
||||
};
|
||||
let full_cir = mk_cir("rsync://example.net/repo/full.roa", &full_hash, "2026-03-16T11:49:15Z");
|
||||
let full_cir = mk_cir(
|
||||
"rsync://example.net/repo/full.roa",
|
||||
&full_hash,
|
||||
"2026-03-16T11:49:15Z",
|
||||
);
|
||||
let delta_cir = CanonicalInputRepresentation {
|
||||
version: CIR_VERSION_V1,
|
||||
hash_alg: CirHashAlgorithm::Sha256,
|
||||
@@ -68,7 +85,10 @@ fn cir_offline_sequence_writes_parseable_sequence_json_and_steps() {
|
||||
mfts: None,
|
||||
vrps: None,
|
||||
vaps: None,
|
||||
tas: Some(TrustAnchorState { skis: vec![vec![0x11; 20]], hash: vec![0x22; 32] }),
|
||||
tas: Some(TrustAnchorState {
|
||||
skis: vec![vec![0x11; 20]],
|
||||
hash: vec![0x22; 32],
|
||||
}),
|
||||
rks: None,
|
||||
});
|
||||
let full_cir_path = fixture_root.join("full.cir");
|
||||
@@ -82,8 +102,16 @@ fn cir_offline_sequence_writes_parseable_sequence_json_and_steps() {
|
||||
std::fs::write(&delta_cir_path, encode_cir(&delta_cir).unwrap()).unwrap();
|
||||
std::fs::write(&full_ccr_path, encode_content_info(&empty_ccr).unwrap()).unwrap();
|
||||
std::fs::write(&delta_ccr_path, encode_content_info(&empty_ccr).unwrap()).unwrap();
|
||||
std::fs::write(&full_report_path, br#"{"format_version":2,"publication_points":[]}"#).unwrap();
|
||||
std::fs::write(&delta_report_path, br#"{"format_version":2,"publication_points":[]}"#).unwrap();
|
||||
std::fs::write(
|
||||
&full_report_path,
|
||||
br#"{"format_version":2,"publication_points":[]}"#,
|
||||
)
|
||||
.unwrap();
|
||||
std::fs::write(
|
||||
&delta_report_path,
|
||||
br#"{"format_version":2,"publication_points":[]}"#,
|
||||
)
|
||||
.unwrap();
|
||||
std::fs::write(static_payload_root.join("full-object"), b"full-object").unwrap();
|
||||
std::fs::write(static_payload_root.join("delta-object"), b"delta-object").unwrap();
|
||||
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::process::Command;
|
||||
|
||||
use rpki::cir::{encode_cir, materialize_cir, CanonicalInputRepresentation, CirHashAlgorithm, CirObject, CirTal, CIR_VERSION_V1};
|
||||
use rpki::cir::{
|
||||
CIR_VERSION_V1, CanonicalInputRepresentation, CirHashAlgorithm, CirObject, CirTal, encode_cir,
|
||||
materialize_cir,
|
||||
};
|
||||
|
||||
fn apnic_tal_path() -> PathBuf {
|
||||
PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("tests/fixtures/tal/apnic-rfc7730-https.tal")
|
||||
@@ -56,7 +59,11 @@ fn write_static(root: &Path, date: &str, bytes: &[u8]) {
|
||||
std::fs::write(dir.join(hash), bytes).expect("write static object");
|
||||
}
|
||||
|
||||
fn prepare_reference_ccr(work: &Path, cir: &CanonicalInputRepresentation, mirror_root: &Path) -> PathBuf {
|
||||
fn prepare_reference_ccr(
|
||||
work: &Path,
|
||||
cir: &CanonicalInputRepresentation,
|
||||
mirror_root: &Path,
|
||||
) -> PathBuf {
|
||||
let reference_ccr = work.join("reference.ccr");
|
||||
let rpki_bin = env!("CARGO_BIN_EXE_rpki");
|
||||
let wrapper = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("scripts/cir/cir-rsync-wrapper");
|
||||
@@ -77,7 +84,9 @@ fn prepare_reference_ccr(work: &Path, cir: &CanonicalInputRepresentation, mirror
|
||||
"--rsync-command",
|
||||
wrapper.to_string_lossy().as_ref(),
|
||||
"--validation-time",
|
||||
&cir.validation_time.format(&time::format_description::well_known::Rfc3339).unwrap(),
|
||||
&cir.validation_time
|
||||
.format(&time::format_description::well_known::Rfc3339)
|
||||
.unwrap(),
|
||||
"--max-depth",
|
||||
"0",
|
||||
"--max-instances",
|
||||
@@ -87,7 +96,11 @@ fn prepare_reference_ccr(work: &Path, cir: &CanonicalInputRepresentation, mirror
|
||||
])
|
||||
.output()
|
||||
.expect("run reference rpki");
|
||||
assert!(out.status.success(), "stderr={}", String::from_utf8_lossy(&out.stderr));
|
||||
assert!(
|
||||
out.status.success(),
|
||||
"stderr={}",
|
||||
String::from_utf8_lossy(&out.stderr)
|
||||
);
|
||||
reference_ccr
|
||||
}
|
||||
|
||||
@@ -102,14 +115,30 @@ fn prepare_sequence_root(td: &Path) -> PathBuf {
|
||||
let (cir, ta_bytes) = build_ta_only_cir();
|
||||
let cir_bytes = encode_cir(&cir).expect("encode cir");
|
||||
std::fs::write(sequence_root.join("full").join("input.cir"), &cir_bytes).unwrap();
|
||||
std::fs::write(sequence_root.join("delta-001").join("input.cir"), &cir_bytes).unwrap();
|
||||
std::fs::write(sequence_root.join("delta-002").join("input.cir"), &cir_bytes).unwrap();
|
||||
std::fs::write(
|
||||
sequence_root.join("delta-001").join("input.cir"),
|
||||
&cir_bytes,
|
||||
)
|
||||
.unwrap();
|
||||
std::fs::write(
|
||||
sequence_root.join("delta-002").join("input.cir"),
|
||||
&cir_bytes,
|
||||
)
|
||||
.unwrap();
|
||||
write_static(&static_root, "20260407", &ta_bytes);
|
||||
materialize_cir(&cir, &static_root, &mirror_root, true).unwrap();
|
||||
let reference = prepare_reference_ccr(td, &cir, &mirror_root);
|
||||
std::fs::copy(&reference, sequence_root.join("full").join("result.ccr")).unwrap();
|
||||
std::fs::copy(&reference, sequence_root.join("delta-001").join("result.ccr")).unwrap();
|
||||
std::fs::copy(&reference, sequence_root.join("delta-002").join("result.ccr")).unwrap();
|
||||
std::fs::copy(
|
||||
&reference,
|
||||
sequence_root.join("delta-001").join("result.ccr"),
|
||||
)
|
||||
.unwrap();
|
||||
std::fs::copy(
|
||||
&reference,
|
||||
sequence_root.join("delta-002").join("result.ccr"),
|
||||
)
|
||||
.unwrap();
|
||||
std::fs::write(sequence_root.join("full").join("report.json"), b"{}").unwrap();
|
||||
std::fs::write(sequence_root.join("delta-001").join("report.json"), b"{}").unwrap();
|
||||
std::fs::write(sequence_root.join("delta-002").join("report.json"), b"{}").unwrap();
|
||||
@@ -122,7 +151,11 @@ fn prepare_sequence_root(td: &Path) -> PathBuf {
|
||||
{"stepId":"delta-002","kind":"delta","validationTime":"2026-04-07T00:00:00Z","cirPath":"delta-002/input.cir","ccrPath":"delta-002/result.ccr","reportPath":"delta-002/report.json","previousStepId":"delta-001"}
|
||||
]
|
||||
});
|
||||
std::fs::write(sequence_root.join("sequence.json"), serde_json::to_vec_pretty(&sequence).unwrap()).unwrap();
|
||||
std::fs::write(
|
||||
sequence_root.join("sequence.json"),
|
||||
serde_json::to_vec_pretty(&sequence).unwrap(),
|
||||
)
|
||||
.unwrap();
|
||||
sequence_root
|
||||
}
|
||||
|
||||
@@ -141,13 +174,14 @@ fn peer_sequence_replay_scripts_replay_all_steps() {
|
||||
let routinator_script = PathBuf::from(env!("CARGO_MANIFEST_DIR"))
|
||||
.join("scripts/cir/run_cir_replay_sequence_routinator.sh");
|
||||
let out = Command::new(routinator_script)
|
||||
.args([
|
||||
"--sequence-root",
|
||||
sequence_root.to_string_lossy().as_ref(),
|
||||
])
|
||||
.args(["--sequence-root", sequence_root.to_string_lossy().as_ref()])
|
||||
.output()
|
||||
.expect("run routinator sequence replay");
|
||||
assert!(out.status.success(), "stderr={}", String::from_utf8_lossy(&out.stderr));
|
||||
assert!(
|
||||
out.status.success(),
|
||||
"stderr={}",
|
||||
String::from_utf8_lossy(&out.stderr)
|
||||
);
|
||||
let r_summary: serde_json::Value = serde_json::from_slice(
|
||||
&std::fs::read(sequence_root.join("sequence-summary-routinator.json")).unwrap(),
|
||||
)
|
||||
@@ -166,7 +200,11 @@ fn peer_sequence_replay_scripts_replay_all_steps() {
|
||||
])
|
||||
.output()
|
||||
.expect("run rpki-client sequence replay");
|
||||
assert!(out.status.success(), "stderr={}", String::from_utf8_lossy(&out.stderr));
|
||||
assert!(
|
||||
out.status.success(),
|
||||
"stderr={}",
|
||||
String::from_utf8_lossy(&out.stderr)
|
||||
);
|
||||
let c_summary: serde_json::Value = serde_json::from_slice(
|
||||
&std::fs::read(sequence_root.join("sequence-summary-rpki-client.json")).unwrap(),
|
||||
)
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::process::Command;
|
||||
|
||||
use rpki::cir::{encode_cir, materialize_cir, CanonicalInputRepresentation, CirHashAlgorithm, CirObject, CirTal, CIR_VERSION_V1};
|
||||
use rpki::cir::{
|
||||
CIR_VERSION_V1, CanonicalInputRepresentation, CirHashAlgorithm, CirObject, CirTal, encode_cir,
|
||||
materialize_cir,
|
||||
};
|
||||
|
||||
fn apnic_tal_path() -> PathBuf {
|
||||
PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("tests/fixtures/tal/apnic-rfc7730-https.tal")
|
||||
@@ -56,7 +59,11 @@ fn write_static(root: &Path, date: &str, bytes: &[u8]) {
|
||||
std::fs::write(dir.join(hash), bytes).expect("write static object");
|
||||
}
|
||||
|
||||
fn prepare_reference_ccr(work: &Path, cir: &CanonicalInputRepresentation, mirror_root: &Path) -> PathBuf {
|
||||
fn prepare_reference_ccr(
|
||||
work: &Path,
|
||||
cir: &CanonicalInputRepresentation,
|
||||
mirror_root: &Path,
|
||||
) -> PathBuf {
|
||||
let reference_ccr = work.join("reference.ccr");
|
||||
let rpki_bin = env!("CARGO_BIN_EXE_rpki");
|
||||
let wrapper = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("scripts/cir/cir-rsync-wrapper");
|
||||
@@ -77,7 +84,9 @@ fn prepare_reference_ccr(work: &Path, cir: &CanonicalInputRepresentation, mirror
|
||||
"--rsync-command",
|
||||
wrapper.to_string_lossy().as_ref(),
|
||||
"--validation-time",
|
||||
&cir.validation_time.format(&time::format_description::well_known::Rfc3339).unwrap(),
|
||||
&cir.validation_time
|
||||
.format(&time::format_description::well_known::Rfc3339)
|
||||
.unwrap(),
|
||||
"--max-depth",
|
||||
"0",
|
||||
"--max-instances",
|
||||
@@ -87,7 +96,11 @@ fn prepare_reference_ccr(work: &Path, cir: &CanonicalInputRepresentation, mirror
|
||||
])
|
||||
.output()
|
||||
.expect("run reference rpki");
|
||||
assert!(out.status.success(), "stderr={}", String::from_utf8_lossy(&out.stderr));
|
||||
assert!(
|
||||
out.status.success(),
|
||||
"stderr={}",
|
||||
String::from_utf8_lossy(&out.stderr)
|
||||
);
|
||||
reference_ccr
|
||||
}
|
||||
|
||||
@@ -107,14 +120,30 @@ fn ours_sequence_replay_script_replays_all_steps() {
|
||||
let (cir, ta_bytes) = build_ta_only_cir();
|
||||
let cir_bytes = encode_cir(&cir).expect("encode cir");
|
||||
std::fs::write(sequence_root.join("full").join("input.cir"), &cir_bytes).unwrap();
|
||||
std::fs::write(sequence_root.join("delta-001").join("input.cir"), &cir_bytes).unwrap();
|
||||
std::fs::write(sequence_root.join("delta-002").join("input.cir"), &cir_bytes).unwrap();
|
||||
std::fs::write(
|
||||
sequence_root.join("delta-001").join("input.cir"),
|
||||
&cir_bytes,
|
||||
)
|
||||
.unwrap();
|
||||
std::fs::write(
|
||||
sequence_root.join("delta-002").join("input.cir"),
|
||||
&cir_bytes,
|
||||
)
|
||||
.unwrap();
|
||||
write_static(&static_root, "20260407", &ta_bytes);
|
||||
materialize_cir(&cir, &static_root, &mirror_root, true).unwrap();
|
||||
let reference = prepare_reference_ccr(td.path(), &cir, &mirror_root);
|
||||
std::fs::copy(&reference, sequence_root.join("full").join("result.ccr")).unwrap();
|
||||
std::fs::copy(&reference, sequence_root.join("delta-001").join("result.ccr")).unwrap();
|
||||
std::fs::copy(&reference, sequence_root.join("delta-002").join("result.ccr")).unwrap();
|
||||
std::fs::copy(
|
||||
&reference,
|
||||
sequence_root.join("delta-001").join("result.ccr"),
|
||||
)
|
||||
.unwrap();
|
||||
std::fs::copy(
|
||||
&reference,
|
||||
sequence_root.join("delta-002").join("result.ccr"),
|
||||
)
|
||||
.unwrap();
|
||||
std::fs::write(sequence_root.join("full").join("report.json"), b"{}").unwrap();
|
||||
std::fs::write(sequence_root.join("delta-001").join("report.json"), b"{}").unwrap();
|
||||
std::fs::write(sequence_root.join("delta-002").join("report.json"), b"{}").unwrap();
|
||||
@@ -134,8 +163,8 @@ fn ours_sequence_replay_script_replays_all_steps() {
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let script =
|
||||
PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("scripts/cir/run_cir_replay_sequence_ours.sh");
|
||||
let script = PathBuf::from(env!("CARGO_MANIFEST_DIR"))
|
||||
.join("scripts/cir/run_cir_replay_sequence_ours.sh");
|
||||
let out = Command::new(script)
|
||||
.args([
|
||||
"--sequence-root",
|
||||
@@ -145,11 +174,16 @@ fn ours_sequence_replay_script_replays_all_steps() {
|
||||
])
|
||||
.output()
|
||||
.expect("run sequence replay");
|
||||
assert!(out.status.success(), "stderr={}", String::from_utf8_lossy(&out.stderr));
|
||||
assert!(
|
||||
out.status.success(),
|
||||
"stderr={}",
|
||||
String::from_utf8_lossy(&out.stderr)
|
||||
);
|
||||
|
||||
let summary: serde_json::Value =
|
||||
serde_json::from_slice(&std::fs::read(sequence_root.join("sequence-summary.json")).unwrap())
|
||||
.unwrap();
|
||||
let summary: serde_json::Value = serde_json::from_slice(
|
||||
&std::fs::read(sequence_root.join("sequence-summary.json")).unwrap(),
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(summary["stepCount"], 3);
|
||||
assert_eq!(summary["allMatch"], true);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use std::os::unix::fs::MetadataExt;
|
||||
use std::path::PathBuf;
|
||||
use std::process::Command;
|
||||
use std::os::unix::fs::MetadataExt;
|
||||
|
||||
fn wrapper_path() -> PathBuf {
|
||||
PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("scripts/cir/cir-rsync-wrapper")
|
||||
@@ -24,7 +24,11 @@ fn cir_rsync_wrapper_passes_through_help() {
|
||||
.arg("-h")
|
||||
.output()
|
||||
.expect("run wrapper -h");
|
||||
assert!(out.status.success(), "stderr={}", String::from_utf8_lossy(&out.stderr));
|
||||
assert!(
|
||||
out.status.success(),
|
||||
"stderr={}",
|
||||
String::from_utf8_lossy(&out.stderr)
|
||||
);
|
||||
let stdout = String::from_utf8_lossy(&out.stdout);
|
||||
let stderr = String::from_utf8_lossy(&out.stderr);
|
||||
assert!(stdout.contains("rsync") || stderr.contains("rsync"));
|
||||
@@ -60,8 +64,15 @@ fn cir_rsync_wrapper_rewrites_rsync_source_to_mirror_tree() {
|
||||
])
|
||||
.output()
|
||||
.expect("run wrapper rewrite");
|
||||
assert!(out.status.success(), "stderr={}", String::from_utf8_lossy(&out.stderr));
|
||||
assert_eq!(std::fs::read(dest_root.join("a.roa")).expect("read copied roa"), b"roa");
|
||||
assert!(
|
||||
out.status.success(),
|
||||
"stderr={}",
|
||||
String::from_utf8_lossy(&out.stderr)
|
||||
);
|
||||
assert_eq!(
|
||||
std::fs::read(dest_root.join("a.roa")).expect("read copied roa"),
|
||||
b"roa"
|
||||
);
|
||||
assert!(!dest_root.join("nested").join("b.txt").exists());
|
||||
}
|
||||
|
||||
@@ -93,13 +104,23 @@ fn cir_rsync_wrapper_rewrites_module_root_without_trailing_slash_as_contents() {
|
||||
])
|
||||
.output()
|
||||
.expect("run wrapper rewrite");
|
||||
assert!(out.status.success(), "stderr={}", String::from_utf8_lossy(&out.stderr));
|
||||
assert_eq!(std::fs::read(dest_root.join("root.cer")).expect("read copied root cer"), b"cer");
|
||||
assert!(
|
||||
out.status.success(),
|
||||
"stderr={}",
|
||||
String::from_utf8_lossy(&out.stderr)
|
||||
);
|
||||
assert_eq!(
|
||||
std::fs::read(dest_root.join("root.cer")).expect("read copied root cer"),
|
||||
b"cer"
|
||||
);
|
||||
assert_eq!(
|
||||
std::fs::read(dest_root.join("sub").join("child.roa")).expect("read copied child roa"),
|
||||
b"roa"
|
||||
);
|
||||
assert!(!dest_root.join("repo").exists(), "module root must not be nested under destination");
|
||||
assert!(
|
||||
!dest_root.join("repo").exists(),
|
||||
"module root must not be nested under destination"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -113,7 +134,11 @@ fn cir_rsync_wrapper_requires_mirror_root_for_rsync_source() {
|
||||
|
||||
let out = Command::new(wrapper_path())
|
||||
.env("REAL_RSYNC_BIN", real)
|
||||
.args(["-rt", "rsync://example.net/repo/", dest_root.to_string_lossy().as_ref()])
|
||||
.args([
|
||||
"-rt",
|
||||
"rsync://example.net/repo/",
|
||||
dest_root.to_string_lossy().as_ref(),
|
||||
])
|
||||
.output()
|
||||
.expect("run wrapper missing env");
|
||||
assert!(!out.status.success());
|
||||
@@ -141,8 +166,15 @@ fn cir_rsync_wrapper_leaves_local_source_untouched() {
|
||||
])
|
||||
.output()
|
||||
.expect("run wrapper local passthrough");
|
||||
assert!(out.status.success(), "stderr={}", String::from_utf8_lossy(&out.stderr));
|
||||
assert_eq!(std::fs::read(dest_root.join("src").join("x.cer")).expect("read copied file"), b"x");
|
||||
assert!(
|
||||
out.status.success(),
|
||||
"stderr={}",
|
||||
String::from_utf8_lossy(&out.stderr)
|
||||
);
|
||||
assert_eq!(
|
||||
std::fs::read(dest_root.join("src").join("x.cer")).expect("read copied file"),
|
||||
b"x"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -177,7 +209,11 @@ fn cir_rsync_wrapper_local_link_mode_uses_hardlinks_for_rewritten_sources() {
|
||||
])
|
||||
.output()
|
||||
.expect("run wrapper local-link mode");
|
||||
assert!(out.status.success(), "stderr={}", String::from_utf8_lossy(&out.stderr));
|
||||
assert!(
|
||||
out.status.success(),
|
||||
"stderr={}",
|
||||
String::from_utf8_lossy(&out.stderr)
|
||||
);
|
||||
|
||||
let dst_file = dest_root.join("a.roa");
|
||||
let dst_nested = dest_root.join("nested").join("b.cer");
|
||||
@@ -186,5 +222,9 @@ fn cir_rsync_wrapper_local_link_mode_uses_hardlinks_for_rewritten_sources() {
|
||||
|
||||
let src_meta = std::fs::metadata(&src_file).expect("src metadata");
|
||||
let dst_meta = std::fs::metadata(&dst_file).expect("dst metadata");
|
||||
assert_eq!(src_meta.ino(), dst_meta.ino(), "expected hardlinked destination file");
|
||||
assert_eq!(
|
||||
src_meta.ino(),
|
||||
dst_meta.ino(),
|
||||
"expected hardlinked destination file"
|
||||
);
|
||||
}
|
||||
|
||||
@@ -19,21 +19,15 @@ fn cli_payload_delta_replay_rejects_wrong_base_locks() {
|
||||
let delta_archive = demo_root.join("payload-delta-archive");
|
||||
let delta_locks = demo_root.join("locks-delta.json");
|
||||
|
||||
assert!(
|
||||
base_archive.is_dir(),
|
||||
"base archive missing: {}",
|
||||
base_archive.display()
|
||||
);
|
||||
assert!(
|
||||
delta_archive.is_dir(),
|
||||
"delta archive missing: {}",
|
||||
delta_archive.display()
|
||||
);
|
||||
assert!(
|
||||
delta_locks.is_file(),
|
||||
"delta locks missing: {}",
|
||||
delta_locks.display()
|
||||
);
|
||||
if !base_archive.is_dir() || !delta_archive.is_dir() || !delta_locks.is_file() {
|
||||
eprintln!(
|
||||
"skipping cli delta replay smoke; missing fixtures: base_archive={} delta_archive={} delta_locks={}",
|
||||
base_archive.display(),
|
||||
delta_archive.display(),
|
||||
delta_locks.display()
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
let out = Command::new(bin)
|
||||
.args([
|
||||
|
||||
@@ -16,16 +16,14 @@ fn cli_payload_replay_root_only_smoke_writes_report_json() {
|
||||
let locks_path = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR"))
|
||||
.join("target/live/payload_replay/locks.json");
|
||||
|
||||
assert!(
|
||||
archive_root.is_dir(),
|
||||
"payload replay archive missing: {}",
|
||||
archive_root.display()
|
||||
);
|
||||
assert!(
|
||||
locks_path.is_file(),
|
||||
"payload replay locks missing: {}",
|
||||
locks_path.display()
|
||||
);
|
||||
if !archive_root.is_dir() || !locks_path.is_file() {
|
||||
eprintln!(
|
||||
"skipping cli payload replay smoke; missing fixtures: archive={} locks={}",
|
||||
archive_root.display(),
|
||||
locks_path.display()
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
let out = Command::new(bin)
|
||||
.args([
|
||||
|
||||
@@ -45,7 +45,6 @@ fn cli_run_offline_mode_executes_and_writes_json_and_ccr() {
|
||||
assert_eq!(v["format_version"], 2);
|
||||
}
|
||||
|
||||
|
||||
#[test]
|
||||
fn cli_run_offline_mode_writes_decodable_ccr() {
|
||||
let db_dir = tempfile::tempdir().expect("db tempdir");
|
||||
@@ -130,10 +129,11 @@ fn cli_run_offline_mode_writes_cir_and_static_pool() {
|
||||
let cir = rpki::cir::decode_cir(&bytes).expect("decode cir");
|
||||
assert_eq!(cir.tals.len(), 1);
|
||||
assert_eq!(cir.tals[0].tal_uri, "https://example.test/root.tal");
|
||||
assert!(cir
|
||||
.objects
|
||||
.iter()
|
||||
.any(|item| item.rsync_uri.contains("apnic-rpki-root-iana-origin.cer")));
|
||||
assert!(
|
||||
cir.objects
|
||||
.iter()
|
||||
.any(|item| item.rsync_uri.contains("apnic-rpki-root-iana-origin.cer"))
|
||||
);
|
||||
|
||||
let mut file_count = 0usize;
|
||||
let mut stack = vec![static_root.clone()];
|
||||
@@ -182,14 +182,18 @@ fn cli_run_blackbox_rsync_wrapper_mode_matches_reference_ccr_without_ta_path() {
|
||||
.expect("write ta into mirror");
|
||||
|
||||
let bin = env!("CARGO_BIN_EXE_rpki");
|
||||
let wrapper = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR"))
|
||||
.join("scripts/cir/cir-rsync-wrapper");
|
||||
let wrapper =
|
||||
std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("scripts/cir/cir-rsync-wrapper");
|
||||
let reference = Command::new(bin)
|
||||
.env("REAL_RSYNC_BIN", real_rsync)
|
||||
.env("CIR_MIRROR_ROOT", &mirror_root)
|
||||
.args([
|
||||
"--db",
|
||||
db_dir.path().join("reference-db").to_string_lossy().as_ref(),
|
||||
db_dir
|
||||
.path()
|
||||
.join("reference-db")
|
||||
.to_string_lossy()
|
||||
.as_ref(),
|
||||
"--tal-path",
|
||||
tal_path.to_string_lossy().as_ref(),
|
||||
"--ta-path",
|
||||
@@ -208,7 +212,11 @@ fn cli_run_blackbox_rsync_wrapper_mode_matches_reference_ccr_without_ta_path() {
|
||||
])
|
||||
.output()
|
||||
.expect("run reference wrapper mode");
|
||||
assert!(reference.status.success(), "stderr={}", String::from_utf8_lossy(&reference.stderr));
|
||||
assert!(
|
||||
reference.status.success(),
|
||||
"stderr={}",
|
||||
String::from_utf8_lossy(&reference.stderr)
|
||||
);
|
||||
|
||||
let out = Command::new(bin)
|
||||
.env("REAL_RSYNC_BIN", real_rsync)
|
||||
@@ -232,7 +240,11 @@ fn cli_run_blackbox_rsync_wrapper_mode_matches_reference_ccr_without_ta_path() {
|
||||
])
|
||||
.output()
|
||||
.expect("run blackbox wrapper mode");
|
||||
assert!(out.status.success(), "stderr={}", String::from_utf8_lossy(&out.stderr));
|
||||
assert!(
|
||||
out.status.success(),
|
||||
"stderr={}",
|
||||
String::from_utf8_lossy(&out.stderr)
|
||||
);
|
||||
|
||||
let reference = rpki::ccr::decode_content_info(&std::fs::read(&ref_ccr_path).unwrap())
|
||||
.expect("decode reference ccr");
|
||||
|
||||
@@ -6,9 +6,9 @@ use rpki::data_model::manifest::ManifestObject;
|
||||
use rpki::policy::{CaFailedFetchPolicy, Policy};
|
||||
use rpki::storage::{
|
||||
PackTime, RawByHashEntry, RepositoryViewEntry, RepositoryViewState, RocksStore,
|
||||
ValidatedCaInstanceResult, ValidatedManifestMeta,
|
||||
VcirArtifactKind, VcirArtifactRole, VcirArtifactValidationStatus, VcirAuditSummary,
|
||||
VcirInstanceGate, VcirRelatedArtifact, VcirSummary,
|
||||
ValidatedCaInstanceResult, ValidatedManifestMeta, VcirArtifactKind, VcirArtifactRole,
|
||||
VcirArtifactValidationStatus, VcirAuditSummary, VcirInstanceGate, VcirRelatedArtifact,
|
||||
VcirSummary,
|
||||
};
|
||||
use rpki::validation::manifest::{PublicationPointSource, process_manifest_publication_point};
|
||||
|
||||
@@ -99,7 +99,7 @@ fn store_validated_manifest_baseline(
|
||||
summary: VcirSummary {
|
||||
local_vrp_count: 0,
|
||||
local_aspa_count: 0,
|
||||
local_router_key_count: 0,
|
||||
local_router_key_count: 0,
|
||||
child_count: 0,
|
||||
accepted_object_count: 1,
|
||||
rejected_object_count: 0,
|
||||
@@ -165,7 +165,12 @@ fn manifest_success_returns_validated_publication_point_data() {
|
||||
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);
|
||||
put_current_object(&store, &rsync_uri, bytes, rsync_uri.rsplit('.').next().unwrap_or("bin"));
|
||||
put_current_object(
|
||||
&store,
|
||||
&rsync_uri,
|
||||
bytes,
|
||||
rsync_uri.rsplit('.').next().unwrap_or("bin"),
|
||||
);
|
||||
}
|
||||
|
||||
let policy = Policy::default();
|
||||
@@ -218,7 +223,12 @@ fn manifest_hash_mismatch_reuses_current_instance_vcir_when_enabled() {
|
||||
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);
|
||||
put_current_object(&store, &rsync_uri, bytes, rsync_uri.rsplit('.').next().unwrap_or("bin"));
|
||||
put_current_object(
|
||||
&store,
|
||||
&rsync_uri,
|
||||
bytes,
|
||||
rsync_uri.rsplit('.').next().unwrap_or("bin"),
|
||||
);
|
||||
}
|
||||
|
||||
let policy = Policy::default();
|
||||
@@ -255,7 +265,12 @@ fn manifest_hash_mismatch_reuses_current_instance_vcir_when_enabled() {
|
||||
.expect("load victim raw")
|
||||
.expect("victim raw exists");
|
||||
tampered[0] ^= 0xFF;
|
||||
put_current_object(&store, &victim_uri, tampered, victim_uri.rsplit('.').next().unwrap_or("bin"));
|
||||
put_current_object(
|
||||
&store,
|
||||
&victim_uri,
|
||||
tampered,
|
||||
victim_uri.rsplit('.').next().unwrap_or("bin"),
|
||||
);
|
||||
|
||||
let second = process_manifest_publication_point(
|
||||
&store,
|
||||
@@ -304,7 +319,12 @@ fn manifest_failed_fetch_stop_all_output() {
|
||||
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);
|
||||
put_current_object(&store, &rsync_uri, bytes, rsync_uri.rsplit('.').next().unwrap_or("bin"));
|
||||
put_current_object(
|
||||
&store,
|
||||
&rsync_uri,
|
||||
bytes,
|
||||
rsync_uri.rsplit('.').next().unwrap_or("bin"),
|
||||
);
|
||||
}
|
||||
|
||||
let mut policy = Policy::default();
|
||||
@@ -332,7 +352,12 @@ fn manifest_failed_fetch_stop_all_output() {
|
||||
.expect("load victim raw")
|
||||
.expect("victim raw exists");
|
||||
tampered[0] ^= 0xFF;
|
||||
put_current_object(&store, &victim_uri, tampered, victim_uri.rsplit('.').next().unwrap_or("bin"));
|
||||
put_current_object(
|
||||
&store,
|
||||
&victim_uri,
|
||||
tampered,
|
||||
victim_uri.rsplit('.').next().unwrap_or("bin"),
|
||||
);
|
||||
|
||||
policy.ca_failed_fetch_policy = CaFailedFetchPolicy::StopAllOutput;
|
||||
let err = process_manifest_publication_point(
|
||||
@@ -378,7 +403,12 @@ fn manifest_failed_fetch_rejects_stale_current_instance_vcir() {
|
||||
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);
|
||||
put_current_object(&store, &rsync_uri, bytes, rsync_uri.rsplit('.').next().unwrap_or("bin"));
|
||||
put_current_object(
|
||||
&store,
|
||||
&rsync_uri,
|
||||
bytes,
|
||||
rsync_uri.rsplit('.').next().unwrap_or("bin"),
|
||||
);
|
||||
}
|
||||
|
||||
let policy = Policy::default();
|
||||
@@ -459,7 +489,12 @@ fn manifest_revalidation_with_unchanged_manifest_is_fresh() {
|
||||
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);
|
||||
put_current_object(&store, &rsync_uri, bytes, rsync_uri.rsplit('.').next().unwrap_or("bin"));
|
||||
put_current_object(
|
||||
&store,
|
||||
&rsync_uri,
|
||||
bytes,
|
||||
rsync_uri.rsplit('.').next().unwrap_or("bin"),
|
||||
);
|
||||
}
|
||||
|
||||
let policy = Policy::default();
|
||||
@@ -539,7 +574,12 @@ fn manifest_rollback_is_treated_as_failed_fetch_and_reuses_current_instance_vcir
|
||||
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);
|
||||
put_current_object(&store, &rsync_uri, bytes, rsync_uri.rsplit('.').next().unwrap_or("bin"));
|
||||
put_current_object(
|
||||
&store,
|
||||
&rsync_uri,
|
||||
bytes,
|
||||
rsync_uri.rsplit('.').next().unwrap_or("bin"),
|
||||
);
|
||||
}
|
||||
|
||||
let policy = Policy::default();
|
||||
|
||||
@@ -6,9 +6,9 @@ use rpki::data_model::manifest::ManifestObject;
|
||||
use rpki::policy::{CaFailedFetchPolicy, Policy};
|
||||
use rpki::storage::{
|
||||
PackTime, RawByHashEntry, RepositoryViewEntry, RepositoryViewState, RocksStore,
|
||||
ValidatedCaInstanceResult, ValidatedManifestMeta,
|
||||
VcirArtifactKind, VcirArtifactRole, VcirArtifactValidationStatus, VcirAuditSummary,
|
||||
VcirInstanceGate, VcirRelatedArtifact, VcirSummary,
|
||||
ValidatedCaInstanceResult, ValidatedManifestMeta, VcirArtifactKind, VcirArtifactRole,
|
||||
VcirArtifactValidationStatus, VcirAuditSummary, VcirInstanceGate, VcirRelatedArtifact,
|
||||
VcirSummary,
|
||||
};
|
||||
use rpki::validation::manifest::{
|
||||
ManifestProcessError, PublicationPointSource, process_manifest_publication_point,
|
||||
@@ -102,7 +102,7 @@ fn store_validated_manifest_baseline(
|
||||
summary: VcirSummary {
|
||||
local_vrp_count: 0,
|
||||
local_aspa_count: 0,
|
||||
local_router_key_count: 0,
|
||||
local_router_key_count: 0,
|
||||
child_count: 0,
|
||||
accepted_object_count: 1,
|
||||
rejected_object_count: 0,
|
||||
@@ -161,7 +161,12 @@ fn store_manifest_and_locked_files(
|
||||
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);
|
||||
put_current_object(&store, &rsync_uri, bytes, rsync_uri.rsplit('.').next().unwrap_or("bin"));
|
||||
put_current_object(
|
||||
&store,
|
||||
&rsync_uri,
|
||||
bytes,
|
||||
rsync_uri.rsplit('.').next().unwrap_or("bin"),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -19,7 +19,11 @@ fn wrapper_script() -> std::path::PathBuf {
|
||||
#[test]
|
||||
fn multi_rir_case_info_resolves_all_five_rirs_and_timings() {
|
||||
let bundle_root = multi_rir_bundle_root();
|
||||
assert!(bundle_root.is_dir(), "bundle root missing: {}", bundle_root.display());
|
||||
assert!(
|
||||
bundle_root.is_dir(),
|
||||
"bundle root missing: {}",
|
||||
bundle_root.display()
|
||||
);
|
||||
|
||||
let expected = [
|
||||
("afrinic", "afrinic", "afrinic.tal", "afrinic-ta.cer"),
|
||||
@@ -53,22 +57,61 @@ fn multi_rir_case_info_resolves_all_five_rirs_and_timings() {
|
||||
serde_json::from_slice(&out.stdout).expect("parse helper json");
|
||||
assert_eq!(json["rir"].as_str(), Some(rir));
|
||||
assert_eq!(json["trust_anchor"].as_str(), Some(trust_anchor));
|
||||
assert!(json["base_archive"].as_str().unwrap_or("").ends_with("base-payload-archive"));
|
||||
assert!(json["delta_archive"].as_str().unwrap_or("").ends_with("payload-delta-archive"));
|
||||
assert!(json["base_locks"].as_str().unwrap_or("").ends_with("base-locks.json"));
|
||||
assert!(json["delta_locks"].as_str().unwrap_or("").ends_with("locks-delta.json"));
|
||||
assert!(json["tal_path"].as_str().unwrap_or("").ends_with(tal_suffix));
|
||||
assert!(
|
||||
json["base_archive"]
|
||||
.as_str()
|
||||
.unwrap_or("")
|
||||
.ends_with("base-payload-archive")
|
||||
);
|
||||
assert!(
|
||||
json["delta_archive"]
|
||||
.as_str()
|
||||
.unwrap_or("")
|
||||
.ends_with("payload-delta-archive")
|
||||
);
|
||||
assert!(
|
||||
json["base_locks"]
|
||||
.as_str()
|
||||
.unwrap_or("")
|
||||
.ends_with("base-locks.json")
|
||||
);
|
||||
assert!(
|
||||
json["delta_locks"]
|
||||
.as_str()
|
||||
.unwrap_or("")
|
||||
.ends_with("locks-delta.json")
|
||||
);
|
||||
assert!(
|
||||
json["tal_path"]
|
||||
.as_str()
|
||||
.unwrap_or("")
|
||||
.ends_with(tal_suffix)
|
||||
);
|
||||
assert!(json["ta_path"].as_str().unwrap_or("").ends_with(ta_suffix));
|
||||
assert!(json["validation_times"]["snapshot"].as_str().unwrap_or("").contains("T"));
|
||||
assert!(json["validation_times"]["delta"].as_str().unwrap_or("").contains("T"));
|
||||
assert!(json["routinator_timings"]["base_replay_seconds"]
|
||||
.as_f64()
|
||||
.unwrap_or(0.0)
|
||||
> 0.0);
|
||||
assert!(json["routinator_timings"]["delta_replay_seconds"]
|
||||
.as_f64()
|
||||
.unwrap_or(0.0)
|
||||
> 0.0);
|
||||
assert!(
|
||||
json["validation_times"]["snapshot"]
|
||||
.as_str()
|
||||
.unwrap_or("")
|
||||
.contains("T")
|
||||
);
|
||||
assert!(
|
||||
json["validation_times"]["delta"]
|
||||
.as_str()
|
||||
.unwrap_or("")
|
||||
.contains("T")
|
||||
);
|
||||
assert!(
|
||||
json["routinator_timings"]["base_replay_seconds"]
|
||||
.as_f64()
|
||||
.unwrap_or(0.0)
|
||||
> 0.0
|
||||
);
|
||||
assert!(
|
||||
json["routinator_timings"]["delta_replay_seconds"]
|
||||
.as_f64()
|
||||
.unwrap_or(0.0)
|
||||
> 0.0
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -113,8 +156,12 @@ fn multi_rir_case_info_prefers_lock_validation_time_over_replay_started_at() {
|
||||
"verification.json",
|
||||
"README.md",
|
||||
] {
|
||||
fs::write(rir_root.join(rel), "placeholder
|
||||
").expect("write required file");
|
||||
fs::write(
|
||||
rir_root.join(rel),
|
||||
"placeholder
|
||||
",
|
||||
)
|
||||
.expect("write required file");
|
||||
}
|
||||
|
||||
let repo_root = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR"));
|
||||
@@ -163,7 +210,11 @@ stderr={}",
|
||||
#[test]
|
||||
fn multi_rir_wrapper_describe_mode_works_for_ripe() {
|
||||
let bundle_root = multi_rir_bundle_root();
|
||||
assert!(bundle_root.is_dir(), "bundle root missing: {}", bundle_root.display());
|
||||
assert!(
|
||||
bundle_root.is_dir(),
|
||||
"bundle root missing: {}",
|
||||
bundle_root.display()
|
||||
);
|
||||
|
||||
let out = Command::new(wrapper_script())
|
||||
.env("BUNDLE_ROOT", &bundle_root)
|
||||
@@ -183,8 +234,10 @@ fn multi_rir_wrapper_describe_mode_works_for_ripe() {
|
||||
serde_json::from_slice(&out.stdout).expect("parse wrapper describe json");
|
||||
assert_eq!(json["rir"].as_str(), Some("ripe"));
|
||||
assert_eq!(json["trust_anchor"].as_str(), Some("ripe"));
|
||||
assert!(json["verification_json"]
|
||||
.as_str()
|
||||
.unwrap_or("")
|
||||
.ends_with("verification.json"));
|
||||
assert!(
|
||||
json["verification_json"]
|
||||
.as_str()
|
||||
.unwrap_or("")
|
||||
.ends_with("verification.json")
|
||||
);
|
||||
}
|
||||
|
||||
@@ -403,7 +403,6 @@ fn process_snapshot_for_issuer_drop_publication_point_on_invalid_aspa_bytes() {
|
||||
assert!(!out.warnings.is_empty());
|
||||
}
|
||||
|
||||
|
||||
#[test]
|
||||
fn process_snapshot_for_issuer_populates_local_outputs_cache_from_real_cernet_fixture() {
|
||||
let (dir, rsync_base_uri, manifest_file) = cernet_fixture();
|
||||
@@ -432,16 +431,21 @@ fn process_snapshot_for_issuer_populates_local_outputs_cache_from_real_cernet_fi
|
||||
None,
|
||||
);
|
||||
|
||||
assert!(!out.local_outputs_cache.is_empty(), "expected cached VCIR local outputs");
|
||||
assert!(
|
||||
!out.local_outputs_cache.is_empty(),
|
||||
"expected cached VCIR local outputs"
|
||||
);
|
||||
assert_eq!(out.local_outputs_cache.len(), out.vrps.len());
|
||||
assert!(out
|
||||
.local_outputs_cache
|
||||
.iter()
|
||||
.all(|entry| entry.output_type == VcirOutputType::Vrp));
|
||||
assert!(out
|
||||
.local_outputs_cache
|
||||
.iter()
|
||||
.all(|entry| entry.source_object_type == "roa"));
|
||||
assert!(
|
||||
out.local_outputs_cache
|
||||
.iter()
|
||||
.all(|entry| entry.output_type == VcirOutputType::Vrp)
|
||||
);
|
||||
assert!(
|
||||
out.local_outputs_cache
|
||||
.iter()
|
||||
.all(|entry| entry.source_object_type == "roa")
|
||||
);
|
||||
}
|
||||
|
||||
// NOTE: DN-based issuer resolution and pack-local CA indexing have been removed for determinism.
|
||||
|
||||
@@ -206,8 +206,14 @@ fn write_multi_rir_case_report_combines_compare_and_timing() {
|
||||
|
||||
let md = std::fs::read_to_string(&out_md).expect("read markdown");
|
||||
assert!(md.contains("AFRINIC Replay Report"), "{md}");
|
||||
assert!(md.contains("| snapshot | true | 12.000 | 6.000 | 2.000 | 0 | 0 |"), "{md}");
|
||||
assert!(md.contains("| delta | true | 8.000 | 4.000 | 2.000 | 0 | 0 |"), "{md}");
|
||||
assert!(
|
||||
md.contains("| snapshot | true | 12.000 | 6.000 | 2.000 | 0 | 0 |"),
|
||||
"{md}"
|
||||
);
|
||||
assert!(
|
||||
md.contains("| delta | true | 8.000 | 4.000 | 2.000 | 0 | 0 |"),
|
||||
"{md}"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -282,7 +288,10 @@ fn write_multi_rir_summary_aggregates_case_reports() {
|
||||
|
||||
let md = std::fs::read_to_string(&out_md).expect("read summary md");
|
||||
assert!(md.contains("Multi-RIR Replay Summary"), "{md}");
|
||||
assert!(md.contains("| afrinic | true | 10.000 | 5.000 | 2.000 | true | 12.000 | 6.000 | 3.000 |"), "{md}");
|
||||
assert!(
|
||||
md.contains("| afrinic | true | 10.000 | 5.000 | 2.000 | true | 12.000 | 6.000 | 3.000 |"),
|
||||
"{md}"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
@@ -4,7 +4,7 @@ use std::sync::{Arc, Mutex};
|
||||
use rpki::fetch::rsync::{LocalDirRsyncFetcher, RsyncFetchError, RsyncFetcher};
|
||||
use rpki::policy::{Policy, SyncPreference};
|
||||
use rpki::storage::RocksStore;
|
||||
use rpki::sync::repo::{RepoSyncSource, sync_publication_point};
|
||||
use rpki::sync::repo::{RepoSyncPhase, RepoSyncSource, sync_publication_point};
|
||||
use rpki::sync::rrdp::Fetcher;
|
||||
|
||||
struct MapFetcher {
|
||||
@@ -98,6 +98,7 @@ fn repo_sync_uses_rrdp_when_available() {
|
||||
.expect("sync");
|
||||
|
||||
assert_eq!(out.source, RepoSyncSource::Rrdp);
|
||||
assert_eq!(out.phase, RepoSyncPhase::RrdpOk);
|
||||
assert_eq!(out.objects_written, 2);
|
||||
assert_eq!(*calls.lock().unwrap(), 0);
|
||||
|
||||
@@ -145,6 +146,7 @@ fn repo_sync_skips_snapshot_when_state_unchanged() {
|
||||
)
|
||||
.expect("sync 1");
|
||||
assert_eq!(out1.source, RepoSyncSource::Rrdp);
|
||||
assert_eq!(out1.phase, RepoSyncPhase::RrdpOk);
|
||||
assert_eq!(out1.objects_written, 2);
|
||||
|
||||
let out2 = sync_publication_point(
|
||||
@@ -159,6 +161,7 @@ fn repo_sync_skips_snapshot_when_state_unchanged() {
|
||||
)
|
||||
.expect("sync 2");
|
||||
assert_eq!(out2.source, RepoSyncSource::Rrdp);
|
||||
assert_eq!(out2.phase, RepoSyncPhase::RrdpOk);
|
||||
assert_eq!(
|
||||
out2.objects_written, 0,
|
||||
"expected to skip snapshot apply when state unchanged"
|
||||
@@ -208,6 +211,7 @@ fn repo_sync_falls_back_to_rsync_on_rrdp_failure() {
|
||||
.expect("fallback sync");
|
||||
|
||||
assert_eq!(out.source, RepoSyncSource::Rsync);
|
||||
assert_eq!(out.phase, RepoSyncPhase::RrdpFailedRsyncOk);
|
||||
assert_eq!(out.objects_written, 1);
|
||||
assert_eq!(*calls.lock().unwrap(), 1);
|
||||
assert!(!out.warnings.is_empty());
|
||||
@@ -252,6 +256,7 @@ fn repo_sync_rsync_populates_current_repository_view() {
|
||||
.expect("rsync-only sync");
|
||||
|
||||
assert_eq!(out.source, RepoSyncSource::Rsync);
|
||||
assert_eq!(out.phase, RepoSyncPhase::RsyncOnlyOk);
|
||||
assert_eq!(out.objects_written, 2);
|
||||
|
||||
assert_current_object(&store, "rsync://example.net/repo/a/one.cer", b"1");
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
use std::process::Command;
|
||||
|
||||
use rpki::data_model::rc::{ResourceCertificate, ResourceCertKind};
|
||||
use rpki::data_model::rc::{ResourceCertKind, ResourceCertificate};
|
||||
use rpki::data_model::router_cert::{
|
||||
BgpsecRouterCertificate, BgpsecRouterCertificateDecodeError,
|
||||
BgpsecRouterCertificatePathError, BgpsecRouterCertificateProfileError,
|
||||
BgpsecRouterCertificate, BgpsecRouterCertificateDecodeError, BgpsecRouterCertificatePathError,
|
||||
BgpsecRouterCertificateProfileError,
|
||||
};
|
||||
|
||||
fn openssl_available() -> bool {
|
||||
@@ -104,7 +104,11 @@ sbgp-autonomousSysNum = critical, AS:64496
|
||||
authorityKeyIdentifier = keyid:always
|
||||
"#,
|
||||
dir = dir.display(),
|
||||
eku_line = if include_eku { "extendedKeyUsage = 1.3.6.1.5.5.7.3.30" } else { "" },
|
||||
eku_line = if include_eku {
|
||||
"extendedKeyUsage = 1.3.6.1.5.5.7.3.30"
|
||||
} else {
|
||||
""
|
||||
},
|
||||
extra_ext = extra_ext
|
||||
);
|
||||
std::fs::write(dir.join("openssl.cnf"), cnf.as_bytes()).expect("write cnf");
|
||||
@@ -266,7 +270,16 @@ fn decode_bgpsec_router_certificate_fixture_smoke() {
|
||||
fn router_certificate_profile_rejects_missing_eku() {
|
||||
let g = generate_router_cert_with_variant("ec-p256", false, "");
|
||||
let err = BgpsecRouterCertificate::decode_der(&g.router_der).unwrap_err();
|
||||
assert!(matches!(err, BgpsecRouterCertificateDecodeError::Validate(BgpsecRouterCertificateProfileError::MissingBgpsecRouterEku | BgpsecRouterCertificateProfileError::MissingExtendedKeyUsage)), "{err}");
|
||||
assert!(
|
||||
matches!(
|
||||
err,
|
||||
BgpsecRouterCertificateDecodeError::Validate(
|
||||
BgpsecRouterCertificateProfileError::MissingBgpsecRouterEku
|
||||
| BgpsecRouterCertificateProfileError::MissingExtendedKeyUsage
|
||||
)
|
||||
),
|
||||
"{err}"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -277,7 +290,15 @@ fn router_certificate_profile_rejects_sia_and_ip_resources_and_ranges() {
|
||||
"subjectInfoAccess = caRepository;URI:rsync://example.test/repo/router/\n",
|
||||
);
|
||||
let err = BgpsecRouterCertificate::decode_der(&g.router_der).unwrap_err();
|
||||
assert!(matches!(err, BgpsecRouterCertificateDecodeError::Validate(BgpsecRouterCertificateProfileError::SubjectInfoAccessPresent)), "{err}");
|
||||
assert!(
|
||||
matches!(
|
||||
err,
|
||||
BgpsecRouterCertificateDecodeError::Validate(
|
||||
BgpsecRouterCertificateProfileError::SubjectInfoAccessPresent
|
||||
)
|
||||
),
|
||||
"{err}"
|
||||
);
|
||||
|
||||
let g = generate_router_cert_with_variant(
|
||||
"ec-p256",
|
||||
@@ -285,7 +306,15 @@ fn router_certificate_profile_rejects_sia_and_ip_resources_and_ranges() {
|
||||
"sbgp-ipAddrBlock = critical, IPv4:10.0.0.0/8\n",
|
||||
);
|
||||
let err = BgpsecRouterCertificate::decode_der(&g.router_der).unwrap_err();
|
||||
assert!(matches!(err, BgpsecRouterCertificateDecodeError::Validate(BgpsecRouterCertificateProfileError::IpResourcesPresent)), "{err}");
|
||||
assert!(
|
||||
matches!(
|
||||
err,
|
||||
BgpsecRouterCertificateDecodeError::Validate(
|
||||
BgpsecRouterCertificateProfileError::IpResourcesPresent
|
||||
)
|
||||
),
|
||||
"{err}"
|
||||
);
|
||||
|
||||
let g = generate_router_cert_with_variant(
|
||||
"ec-p256",
|
||||
@@ -293,18 +322,43 @@ fn router_certificate_profile_rejects_sia_and_ip_resources_and_ranges() {
|
||||
"sbgp-autonomousSysNum = critical, AS:64496-64500\n",
|
||||
);
|
||||
let err = BgpsecRouterCertificate::decode_der(&g.router_der).unwrap_err();
|
||||
assert!(matches!(err, BgpsecRouterCertificateDecodeError::Validate(BgpsecRouterCertificateProfileError::AsResourcesRangeNotAllowed)), "{err}");
|
||||
assert!(
|
||||
matches!(
|
||||
err,
|
||||
BgpsecRouterCertificateDecodeError::Validate(
|
||||
BgpsecRouterCertificateProfileError::AsResourcesRangeNotAllowed
|
||||
)
|
||||
),
|
||||
"{err}"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn router_certificate_profile_rejects_wrong_spki_algorithm_or_curve() {
|
||||
let g = generate_router_cert_with_variant("rsa", true, "");
|
||||
let err = BgpsecRouterCertificate::decode_der(&g.router_der).unwrap_err();
|
||||
assert!(matches!(err, BgpsecRouterCertificateDecodeError::Validate(BgpsecRouterCertificateProfileError::SpkiAlgorithmNotEcPublicKey)), "{err}");
|
||||
assert!(
|
||||
matches!(
|
||||
err,
|
||||
BgpsecRouterCertificateDecodeError::Validate(
|
||||
BgpsecRouterCertificateProfileError::SpkiAlgorithmNotEcPublicKey
|
||||
)
|
||||
),
|
||||
"{err}"
|
||||
);
|
||||
|
||||
let g = generate_router_cert_with_variant("ec-p384", true, "");
|
||||
let err = BgpsecRouterCertificate::decode_der(&g.router_der).unwrap_err();
|
||||
assert!(matches!(err, BgpsecRouterCertificateDecodeError::Validate(BgpsecRouterCertificateProfileError::SpkiWrongCurve | BgpsecRouterCertificateProfileError::SpkiEcPointNotUncompressedP256)), "{err}");
|
||||
assert!(
|
||||
matches!(
|
||||
err,
|
||||
BgpsecRouterCertificateDecodeError::Validate(
|
||||
BgpsecRouterCertificateProfileError::SpkiWrongCurve
|
||||
| BgpsecRouterCertificateProfileError::SpkiEcPointNotUncompressedP256
|
||||
)
|
||||
),
|
||||
"{err}"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -317,11 +371,15 @@ fn router_certificate_path_validation_accepts_valid_and_rejects_wrong_issuer() {
|
||||
|
||||
let g = generate_router_cert_with_variant("ec-p256", true, "");
|
||||
let issuer = ResourceCertificate::decode_der(&g.issuer_ca_der).expect("decode issuer");
|
||||
let wrong_issuer = ResourceCertificate::decode_der(&g.wrong_issuer_der).expect("decode wrong issuer");
|
||||
let wrong_issuer =
|
||||
ResourceCertificate::decode_der(&g.wrong_issuer_der).expect("decode wrong issuer");
|
||||
let issuer_crl = RpkixCrl::decode_der(&g.issuer_crl_der).expect("decode crl");
|
||||
let (rem, issuer_spki) = SubjectPublicKeyInfo::from_der(&issuer.tbs.subject_public_key_info).expect("issuer spki");
|
||||
let (rem, issuer_spki) =
|
||||
SubjectPublicKeyInfo::from_der(&issuer.tbs.subject_public_key_info).expect("issuer spki");
|
||||
assert!(rem.is_empty());
|
||||
let (rem, wrong_spki) = SubjectPublicKeyInfo::from_der(&wrong_issuer.tbs.subject_public_key_info).expect("wrong issuer spki");
|
||||
let (rem, wrong_spki) =
|
||||
SubjectPublicKeyInfo::from_der(&wrong_issuer.tbs.subject_public_key_info)
|
||||
.expect("wrong issuer spki");
|
||||
assert!(rem.is_empty());
|
||||
let now = time::OffsetDateTime::now_utc();
|
||||
|
||||
@@ -334,7 +392,8 @@ fn router_certificate_path_validation_accepts_valid_and_rejects_wrong_issuer() {
|
||||
Some("rsync://example.test/repo/issuer/issuer.cer"),
|
||||
Some("rsync://example.test/repo/issuer/issuer.crl"),
|
||||
now,
|
||||
).expect("router path valid");
|
||||
)
|
||||
.expect("router path valid");
|
||||
assert_eq!(cert.asns, vec![64496]);
|
||||
|
||||
let err = BgpsecRouterCertificate::validate_path_with_prevalidated_issuer(
|
||||
@@ -346,8 +405,12 @@ fn router_certificate_path_validation_accepts_valid_and_rejects_wrong_issuer() {
|
||||
None,
|
||||
None,
|
||||
now,
|
||||
).unwrap_err();
|
||||
assert!(matches!(err, BgpsecRouterCertificatePathError::CertPath(_)), "{err}");
|
||||
)
|
||||
.unwrap_err();
|
||||
assert!(
|
||||
matches!(err, BgpsecRouterCertificatePathError::CertPath(_)),
|
||||
"{err}"
|
||||
);
|
||||
|
||||
let rc = ResourceCertificate::decode_der(&g.router_der).expect("decode router rc");
|
||||
let mut revoked = HashSet::new();
|
||||
@@ -361,6 +424,10 @@ fn router_certificate_path_validation_accepts_valid_and_rejects_wrong_issuer() {
|
||||
Some("rsync://example.test/repo/issuer/issuer.cer"),
|
||||
Some("rsync://example.test/repo/issuer/issuer.crl"),
|
||||
now,
|
||||
).unwrap_err();
|
||||
assert!(matches!(err, BgpsecRouterCertificatePathError::CertPath(_)), "{err}");
|
||||
)
|
||||
.unwrap_err();
|
||||
assert!(
|
||||
matches!(err, BgpsecRouterCertificatePathError::CertPath(_)),
|
||||
"{err}"
|
||||
);
|
||||
}
|
||||
|
||||
@@ -94,12 +94,7 @@ fn rsync_fallback_breakdown_luys_cloud() {
|
||||
let sha256_hex = hex::encode(sha2::Sha256::digest(bytes));
|
||||
let mut raw = RawByHashEntry::from_bytes(sha256_hex.clone(), bytes.clone());
|
||||
raw.origin_uris.push(uri.clone());
|
||||
raw.object_type = Some(
|
||||
uri.rsplit('.')
|
||||
.next()
|
||||
.unwrap_or("bin")
|
||||
.to_ascii_lowercase(),
|
||||
);
|
||||
raw.object_type = Some(uri.rsplit('.').next().unwrap_or("bin").to_ascii_lowercase());
|
||||
raw.encoding = Some("der".to_string());
|
||||
store.put_raw_by_hash_entry(&raw).expect("put raw_by_hash");
|
||||
store
|
||||
@@ -107,12 +102,7 @@ fn rsync_fallback_breakdown_luys_cloud() {
|
||||
rsync_uri: uri.clone(),
|
||||
current_hash: Some(sha256_hex),
|
||||
repository_source: Some(rsync_base_uri.clone()),
|
||||
object_type: Some(
|
||||
uri.rsplit('.')
|
||||
.next()
|
||||
.unwrap_or("bin")
|
||||
.to_ascii_lowercase(),
|
||||
),
|
||||
object_type: Some(uri.rsplit('.').next().unwrap_or("bin").to_ascii_lowercase()),
|
||||
state: RepositoryViewState::Present,
|
||||
})
|
||||
.expect("put repository view");
|
||||
|
||||
@@ -17,7 +17,11 @@ fn signed_object_decode_accepts_real_arin_ber_indefinite_roa_from_multi_rir_bund
|
||||
let xml_path = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR")).join(
|
||||
"../../rpki/target/live/20260316-112341-multi-final3/arin/base-payload-archive/v1/captures/arin-base-arin/rrdp/repos/8bd1405242614aed9f13321d266fe3193db0ca842e0cbffda2b3df05481c331b/4a394319-7460-4141-a416-1addb69284ff/snapshot-160090-880434ae2a6f0e5fff224391c65a22ab037e09ac1d3ebad0ceda18558b49b13e.xml",
|
||||
);
|
||||
assert!(xml_path.is_file(), "xml path missing: {}", xml_path.display());
|
||||
assert!(
|
||||
xml_path.is_file(),
|
||||
"xml path missing: {}",
|
||||
xml_path.display()
|
||||
);
|
||||
let xml = std::fs::read_to_string(&xml_path).expect("read snapshot xml");
|
||||
let uri = "rsync://rpki.arin.net/repository/arin-rpki-ta/5e4a23ea-e80a-403e-b08c-2171da2157d3/2a246947-2d62-4a6c-ba05-87187f0099b2/9ed5ce80-224e-46ab-94f1-1afce8ccf13f/0b13beb5-6bbb-3994-a254-02c5b10175c5.roa";
|
||||
let der = extract_publish_bytes(&xml, uri);
|
||||
@@ -25,8 +29,12 @@ fn signed_object_decode_accepts_real_arin_ber_indefinite_roa_from_multi_rir_bund
|
||||
assert_eq!(der.first().copied(), Some(0x30));
|
||||
assert_eq!(der.get(1).copied(), Some(0x80));
|
||||
|
||||
let signed_object = RpkiSignedObject::decode_der(&der).expect("decode BER-indefinite CMS signed object");
|
||||
assert_eq!(signed_object.signed_data.encap_content_info.econtent_type, "1.2.840.113549.1.9.16.1.24");
|
||||
let signed_object =
|
||||
RpkiSignedObject::decode_der(&der).expect("decode BER-indefinite CMS signed object");
|
||||
assert_eq!(
|
||||
signed_object.signed_data.encap_content_info.econtent_type,
|
||||
"1.2.840.113549.1.9.16.1.24"
|
||||
);
|
||||
|
||||
let roa = RoaObject::decode_der(&der).expect("decode ROA object from BER-indefinite CMS");
|
||||
assert!(!roa.roa.ip_addr_blocks.is_empty());
|
||||
|
||||
@@ -79,7 +79,9 @@ fn rrdp_source_roundtrip_by_notification_uri() {
|
||||
last_snapshot_hash: None,
|
||||
last_error: None,
|
||||
};
|
||||
store.put_rrdp_source_record(&record).expect("put rrdp_source");
|
||||
store
|
||||
.put_rrdp_source_record(&record)
|
||||
.expect("put rrdp_source");
|
||||
|
||||
let got = store
|
||||
.get_rrdp_source_record(notif)
|
||||
|
||||
@@ -395,7 +395,9 @@ fn tree_aggregates_router_keys_from_publication_point_results() {
|
||||
source_object_uri: "rsync://example.test/repo/router1.cer".to_string(),
|
||||
source_object_hash: "11".repeat(32),
|
||||
source_ee_cert_hash: "11".repeat(32),
|
||||
item_effective_until: PackTime { rfc3339_utc: "2026-12-31T00:00:00Z".to_string() },
|
||||
item_effective_until: PackTime {
|
||||
rfc3339_utc: "2026-12-31T00:00:00Z".to_string(),
|
||||
},
|
||||
},
|
||||
RouterKeyPayload {
|
||||
as_id: 64497,
|
||||
@@ -404,7 +406,9 @@ fn tree_aggregates_router_keys_from_publication_point_results() {
|
||||
source_object_uri: "rsync://example.test/repo/router2.cer".to_string(),
|
||||
source_object_hash: "22".repeat(32),
|
||||
source_ee_cert_hash: "22".repeat(32),
|
||||
item_effective_until: PackTime { rfc3339_utc: "2026-12-31T00:00:00Z".to_string() },
|
||||
item_effective_until: PackTime {
|
||||
rfc3339_utc: "2026-12-31T00:00:00Z".to_string(),
|
||||
},
|
||||
},
|
||||
],
|
||||
local_outputs_cache: Vec::new(),
|
||||
|
||||
Reference in New Issue
Block a user