20260410 完成五个rir 基于cir的三方回放,raw by hash 独立db,发现内存占用大,连续大rir 录制发生oom
This commit is contained in:
@@ -33,9 +33,13 @@ fn parse_args(argv: &[String]) -> Result<Args, String> {
|
||||
fn main() -> Result<(), String> {
|
||||
let args = parse_args(&std::env::args().collect::<Vec<_>>())?;
|
||||
let ccr_path = args.ccr_path.as_ref().unwrap();
|
||||
let bytes = std::fs::read(ccr_path).map_err(|e| format!("read ccr failed: {}: {e}", ccr_path.display()))?;
|
||||
let bytes = std::fs::read(ccr_path)
|
||||
.map_err(|e| format!("read ccr failed: {}: {e}", ccr_path.display()))?;
|
||||
let json = dump_content_info_json_value(&bytes).map_err(|e| e.to_string())?;
|
||||
println!("{}", serde_json::to_string_pretty(&json).map_err(|e| e.to_string())?);
|
||||
println!(
|
||||
"{}",
|
||||
serde_json::to_string_pretty(&json).map_err(|e| e.to_string())?
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -45,9 +49,16 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn parse_args_accepts_ccr_path() {
|
||||
let argv = vec!["ccr_dump".to_string(), "--ccr".to_string(), "a.ccr".to_string()];
|
||||
let argv = vec![
|
||||
"ccr_dump".to_string(),
|
||||
"--ccr".to_string(),
|
||||
"a.ccr".to_string(),
|
||||
];
|
||||
let args = parse_args(&argv).expect("parse");
|
||||
assert_eq!(args.ccr_path.as_deref(), Some(std::path::Path::new("a.ccr")));
|
||||
assert_eq!(
|
||||
args.ccr_path.as_deref(),
|
||||
Some(std::path::Path::new("a.ccr"))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
@@ -94,7 +94,10 @@ mod tests {
|
||||
"apnic".to_string(),
|
||||
];
|
||||
let args = parse_args(&argv).expect("parse args");
|
||||
assert_eq!(args.ccr_path.as_deref(), Some(std::path::Path::new("a.ccr")));
|
||||
assert_eq!(
|
||||
args.ccr_path.as_deref(),
|
||||
Some(std::path::Path::new("a.ccr"))
|
||||
);
|
||||
assert_eq!(
|
||||
args.vrps_out_path.as_deref(),
|
||||
Some(std::path::Path::new("vrps.csv"))
|
||||
|
||||
@@ -49,7 +49,9 @@ fn parse_args(argv: &[String]) -> Result<Args, String> {
|
||||
Ok(args)
|
||||
}
|
||||
|
||||
fn collect_vrp_rows(bytes: &[u8]) -> Result<std::collections::BTreeSet<(u32, String, u16)>, String> {
|
||||
fn collect_vrp_rows(
|
||||
bytes: &[u8],
|
||||
) -> Result<std::collections::BTreeSet<(u32, String, u16)>, String> {
|
||||
let content_info = decode_content_info(bytes).map_err(|e| e.to_string())?;
|
||||
extract_vrp_rows(&content_info).map_err(|e| e.to_string())
|
||||
}
|
||||
@@ -95,14 +97,24 @@ mod tests {
|
||||
"apnic".to_string(),
|
||||
];
|
||||
let args = parse_args(&argv).expect("parse args");
|
||||
assert_eq!(args.ccr_path.as_deref(), Some(std::path::Path::new("a.ccr")));
|
||||
assert_eq!(args.out_path.as_deref(), Some(std::path::Path::new("out.csv")));
|
||||
assert_eq!(
|
||||
args.ccr_path.as_deref(),
|
||||
Some(std::path::Path::new("a.ccr"))
|
||||
);
|
||||
assert_eq!(
|
||||
args.out_path.as_deref(),
|
||||
Some(std::path::Path::new("out.csv"))
|
||||
);
|
||||
assert_eq!(args.trust_anchor, "apnic");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_args_rejects_missing_required_flags() {
|
||||
let argv = vec!["ccr_to_routinator_csv".to_string(), "--ccr".to_string(), "a.ccr".to_string()];
|
||||
let argv = vec![
|
||||
"ccr_to_routinator_csv".to_string(),
|
||||
"--ccr".to_string(),
|
||||
"a.ccr".to_string(),
|
||||
];
|
||||
let err = parse_args(&argv).unwrap_err();
|
||||
assert!(err.contains("--out is required"), "{err}");
|
||||
}
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
use rpki::ccr::{decode_content_info, verify::verify_content_info, verify_against_report_json_path, verify_against_vcir_store_path};
|
||||
use rpki::ccr::{
|
||||
decode_content_info, verify::verify_content_info, verify_against_report_json_path,
|
||||
verify_against_vcir_store_path,
|
||||
};
|
||||
|
||||
#[derive(Debug, Default, PartialEq, Eq)]
|
||||
struct Args {
|
||||
@@ -45,7 +48,8 @@ fn parse_args(argv: &[String]) -> Result<Args, String> {
|
||||
fn main() -> Result<(), String> {
|
||||
let args = parse_args(&std::env::args().collect::<Vec<_>>())?;
|
||||
let ccr_path = args.ccr_path.as_ref().unwrap();
|
||||
let bytes = std::fs::read(ccr_path).map_err(|e| format!("read ccr failed: {}: {e}", ccr_path.display()))?;
|
||||
let bytes = std::fs::read(ccr_path)
|
||||
.map_err(|e| format!("read ccr failed: {}: {e}", ccr_path.display()))?;
|
||||
let ci = decode_content_info(&bytes).map_err(|e| e.to_string())?;
|
||||
let summary = verify_content_info(&ci).map_err(|e| e.to_string())?;
|
||||
if let Some(report_json) = args.report_json.as_ref() {
|
||||
@@ -54,7 +58,10 @@ fn main() -> Result<(), String> {
|
||||
if let Some(db_path) = args.db_path.as_ref() {
|
||||
verify_against_vcir_store_path(&ci, db_path).map_err(|e| e.to_string())?;
|
||||
}
|
||||
println!("{}", serde_json::to_string_pretty(&summary).map_err(|e| e.to_string())?);
|
||||
println!(
|
||||
"{}",
|
||||
serde_json::to_string_pretty(&summary).map_err(|e| e.to_string())?
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -74,8 +81,14 @@ mod tests {
|
||||
"db".to_string(),
|
||||
];
|
||||
let args = parse_args(&argv).expect("parse");
|
||||
assert_eq!(args.ccr_path.as_deref(), Some(std::path::Path::new("a.ccr")));
|
||||
assert_eq!(args.report_json.as_deref(), Some(std::path::Path::new("report.json")));
|
||||
assert_eq!(
|
||||
args.ccr_path.as_deref(),
|
||||
Some(std::path::Path::new("a.ccr"))
|
||||
);
|
||||
assert_eq!(
|
||||
args.report_json.as_deref(),
|
||||
Some(std::path::Path::new("report.json"))
|
||||
);
|
||||
assert_eq!(args.db_path.as_deref(), Some(std::path::Path::new("db")));
|
||||
}
|
||||
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
use std::collections::{BTreeMap, BTreeSet};
|
||||
use std::path::PathBuf;
|
||||
|
||||
use rpki::blob_store::{ExternalRawStoreDb, RawObjectStore};
|
||||
use rpki::bundle::decode_ccr_compare_views;
|
||||
use rpki::ccr::decode_content_info;
|
||||
use rpki::cir::{decode_cir, resolve_static_pool_file};
|
||||
use rpki::data_model::roa::RoaObject;
|
||||
|
||||
const USAGE: &str = "Usage: cir_drop_report --cir <path> --ccr <path> --report-json <path> --static-root <path> --json-out <path> --md-out <path>";
|
||||
const USAGE: &str = "Usage: cir_drop_report --cir <path> --ccr <path> --report-json <path> (--static-root <path> | --raw-store-db <path>) --json-out <path> --md-out <path>";
|
||||
|
||||
#[derive(serde::Serialize)]
|
||||
struct DroppedObjectRecord {
|
||||
@@ -47,11 +48,25 @@ fn classify_reason(detail: Option<&str>, result: &str) -> String {
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_args(argv: &[String]) -> Result<(PathBuf, PathBuf, PathBuf, PathBuf, PathBuf, PathBuf), String> {
|
||||
fn parse_args(
|
||||
argv: &[String],
|
||||
) -> Result<
|
||||
(
|
||||
PathBuf,
|
||||
PathBuf,
|
||||
PathBuf,
|
||||
Option<PathBuf>,
|
||||
Option<PathBuf>,
|
||||
PathBuf,
|
||||
PathBuf,
|
||||
),
|
||||
String,
|
||||
> {
|
||||
let mut cir = None;
|
||||
let mut ccr = None;
|
||||
let mut report = None;
|
||||
let mut static_root = None;
|
||||
let mut raw_store_db = None;
|
||||
let mut json_out = None;
|
||||
let mut md_out = None;
|
||||
let mut i = 1usize;
|
||||
@@ -77,6 +92,12 @@ fn parse_args(argv: &[String]) -> Result<(PathBuf, PathBuf, PathBuf, PathBuf, Pa
|
||||
argv.get(i).ok_or("--static-root requires a value")?,
|
||||
));
|
||||
}
|
||||
"--raw-store-db" => {
|
||||
i += 1;
|
||||
raw_store_db = Some(PathBuf::from(
|
||||
argv.get(i).ok_or("--raw-store-db requires a value")?,
|
||||
));
|
||||
}
|
||||
"--json-out" => {
|
||||
i += 1;
|
||||
json_out = Some(PathBuf::from(
|
||||
@@ -85,7 +106,9 @@ fn parse_args(argv: &[String]) -> Result<(PathBuf, PathBuf, PathBuf, PathBuf, Pa
|
||||
}
|
||||
"--md-out" => {
|
||||
i += 1;
|
||||
md_out = Some(PathBuf::from(argv.get(i).ok_or("--md-out requires a value")?));
|
||||
md_out = Some(PathBuf::from(
|
||||
argv.get(i).ok_or("--md-out requires a value")?,
|
||||
));
|
||||
}
|
||||
"-h" | "--help" => return Err(USAGE.to_string()),
|
||||
other => return Err(format!("unknown argument: {other}\n\n{USAGE}")),
|
||||
@@ -96,7 +119,8 @@ fn parse_args(argv: &[String]) -> Result<(PathBuf, PathBuf, PathBuf, PathBuf, Pa
|
||||
cir.ok_or_else(|| format!("--cir is required\n\n{USAGE}"))?,
|
||||
ccr.ok_or_else(|| format!("--ccr is required\n\n{USAGE}"))?,
|
||||
report.ok_or_else(|| format!("--report-json is required\n\n{USAGE}"))?,
|
||||
static_root.ok_or_else(|| format!("--static-root is required\n\n{USAGE}"))?,
|
||||
static_root,
|
||||
raw_store_db,
|
||||
json_out.ok_or_else(|| format!("--json-out is required\n\n{USAGE}"))?,
|
||||
md_out.ok_or_else(|| format!("--md-out is required\n\n{USAGE}"))?,
|
||||
))
|
||||
@@ -104,7 +128,14 @@ fn parse_args(argv: &[String]) -> Result<(PathBuf, PathBuf, PathBuf, PathBuf, Pa
|
||||
|
||||
fn main() -> Result<(), String> {
|
||||
let argv: Vec<String> = std::env::args().collect();
|
||||
let (cir_path, ccr_path, report_path, static_root, json_out, md_out) = parse_args(&argv)?;
|
||||
let (cir_path, ccr_path, report_path, static_root, raw_store_db, json_out, md_out) =
|
||||
parse_args(&argv)?;
|
||||
let backend_count = static_root.is_some() as u8 + raw_store_db.is_some() as u8;
|
||||
if backend_count != 1 {
|
||||
return Err(format!(
|
||||
"must specify exactly one of --static-root or --raw-store-db\n\n{USAGE}"
|
||||
));
|
||||
}
|
||||
|
||||
let cir = decode_cir(&std::fs::read(&cir_path).map_err(|e| format!("read cir failed: {e}"))?)
|
||||
.map_err(|e| format!("decode cir failed: {e}"))?;
|
||||
@@ -112,11 +143,12 @@ fn main() -> Result<(), String> {
|
||||
&std::fs::read(&ccr_path).map_err(|e| format!("read ccr failed: {e}"))?,
|
||||
)
|
||||
.map_err(|e| format!("decode ccr failed: {e}"))?;
|
||||
let (vrps, vaps) =
|
||||
decode_ccr_compare_views(&ccr, "unknown").map_err(|e| format!("decode compare views failed: {e}"))?;
|
||||
let report: serde_json::Value =
|
||||
serde_json::from_slice(&std::fs::read(&report_path).map_err(|e| format!("read report failed: {e}"))?)
|
||||
.map_err(|e| format!("parse report failed: {e}"))?;
|
||||
let (vrps, vaps) = decode_ccr_compare_views(&ccr, "unknown")
|
||||
.map_err(|e| format!("decode compare views failed: {e}"))?;
|
||||
let report: serde_json::Value = serde_json::from_slice(
|
||||
&std::fs::read(&report_path).map_err(|e| format!("read report failed: {e}"))?,
|
||||
)
|
||||
.map_err(|e| format!("parse report failed: {e}"))?;
|
||||
|
||||
let mut object_hash_by_uri = BTreeMap::new();
|
||||
for object in &cir.objects {
|
||||
@@ -134,7 +166,9 @@ fn main() -> Result<(), String> {
|
||||
let mut unknown_roa_objects = 0usize;
|
||||
|
||||
for pp in publication_points {
|
||||
let publication_point = pp["publication_point_rsync_uri"].as_str().map(str::to_string);
|
||||
let publication_point = pp["publication_point_rsync_uri"]
|
||||
.as_str()
|
||||
.map(str::to_string);
|
||||
let manifest_uri = pp["manifest_rsync_uri"].as_str().map(str::to_string);
|
||||
for obj in pp["objects"].as_array().into_iter().flatten() {
|
||||
let result = obj["result"].as_str().unwrap_or("unknown");
|
||||
@@ -155,39 +189,52 @@ fn main() -> Result<(), String> {
|
||||
|
||||
let mut derived_vrp_count = 0usize;
|
||||
if kind == "roa" && !hash.is_empty() {
|
||||
match resolve_static_pool_file(&static_root, &hash) {
|
||||
Ok(path) => {
|
||||
if let Ok(bytes) = std::fs::read(&path) {
|
||||
if let Ok(roa) = RoaObject::decode_der(&bytes) {
|
||||
for family in roa.roa.ip_addr_blocks {
|
||||
for addr in family.addresses {
|
||||
let prefix = match addr.prefix.afi {
|
||||
rpki::data_model::roa::RoaAfi::Ipv4 => format!(
|
||||
"{}.{}.{}.{}/{}",
|
||||
addr.prefix.addr[0],
|
||||
addr.prefix.addr[1],
|
||||
addr.prefix.addr[2],
|
||||
addr.prefix.addr[3],
|
||||
let bytes_opt = if let Some(static_root) = static_root.as_ref() {
|
||||
match resolve_static_pool_file(static_root, &hash) {
|
||||
Ok(path) => std::fs::read(&path).ok(),
|
||||
Err(_) => None,
|
||||
}
|
||||
} else if let Some(raw_store_db) = raw_store_db.as_ref() {
|
||||
ExternalRawStoreDb::open(raw_store_db)
|
||||
.ok()
|
||||
.and_then(|store| store.get_raw_entry(&hash).ok().flatten())
|
||||
.map(|entry| entry.bytes)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
match bytes_opt {
|
||||
Some(bytes) => {
|
||||
if let Ok(roa) = RoaObject::decode_der(&bytes) {
|
||||
for family in roa.roa.ip_addr_blocks {
|
||||
for addr in family.addresses {
|
||||
let prefix = match addr.prefix.afi {
|
||||
rpki::data_model::roa::RoaAfi::Ipv4 => format!(
|
||||
"{}.{}.{}.{}/{}",
|
||||
addr.prefix.addr[0],
|
||||
addr.prefix.addr[1],
|
||||
addr.prefix.addr[2],
|
||||
addr.prefix.addr[3],
|
||||
addr.prefix.prefix_len
|
||||
),
|
||||
rpki::data_model::roa::RoaAfi::Ipv6 => {
|
||||
let bytes: [u8; 16] = addr.prefix.addr;
|
||||
format!(
|
||||
"{}/{}",
|
||||
std::net::Ipv6Addr::from(bytes),
|
||||
addr.prefix.prefix_len
|
||||
),
|
||||
rpki::data_model::roa::RoaAfi::Ipv6 => {
|
||||
let bytes: [u8; 16] = addr.prefix.addr;
|
||||
format!("{}/{}", std::net::Ipv6Addr::from(bytes), addr.prefix.prefix_len)
|
||||
}
|
||||
};
|
||||
let max_len = addr.max_length.unwrap_or(addr.prefix.prefix_len);
|
||||
dropped_vrp_rows.insert((roa.roa.as_id, prefix, max_len));
|
||||
derived_vrp_count += 1;
|
||||
}
|
||||
)
|
||||
}
|
||||
};
|
||||
let max_len = addr.max_length.unwrap_or(addr.prefix.prefix_len);
|
||||
dropped_vrp_rows.insert((roa.roa.as_id, prefix, max_len));
|
||||
derived_vrp_count += 1;
|
||||
}
|
||||
} else {
|
||||
unknown_roa_objects += 1;
|
||||
}
|
||||
} else {
|
||||
unknown_roa_objects += 1;
|
||||
}
|
||||
}
|
||||
Err(_) => unknown_roa_objects += 1,
|
||||
None => unknown_roa_objects += 1,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -227,22 +274,40 @@ fn main() -> Result<(), String> {
|
||||
md.push_str("# CIR Drop Report\n\n");
|
||||
md.push_str(&format!("- `final_vrp_count`: `{}`\n", vrps.len()));
|
||||
md.push_str(&format!("- `final_vap_count`: `{}`\n", vaps.len()));
|
||||
md.push_str(&format!("- `dropped_vrp_count`: `{}`\n", output["summary"]["droppedVrpCount"]));
|
||||
md.push_str(&format!("- `dropped_object_count`: `{}`\n", output["summary"]["droppedObjectCount"]));
|
||||
md.push_str(&format!(
|
||||
"- `dropped_vrp_count`: `{}`\n",
|
||||
output["summary"]["droppedVrpCount"]
|
||||
));
|
||||
md.push_str(&format!(
|
||||
"- `dropped_object_count`: `{}`\n",
|
||||
output["summary"]["droppedObjectCount"]
|
||||
));
|
||||
md.push_str(&format!(
|
||||
"- `unknown_dropped_roa_objects`: `{}`\n\n",
|
||||
output["summary"]["unknownDroppedRoaObjects"]
|
||||
));
|
||||
md.push_str("## Dropped By Kind\n\n");
|
||||
for (kind, count) in output["summary"]["droppedByKind"].as_object().into_iter().flatten() {
|
||||
for (kind, count) in output["summary"]["droppedByKind"]
|
||||
.as_object()
|
||||
.into_iter()
|
||||
.flatten()
|
||||
{
|
||||
md.push_str(&format!("- `{kind}`: `{}`\n", count.as_u64().unwrap_or(0)));
|
||||
}
|
||||
md.push_str("\n## Dropped By Reason\n\n");
|
||||
for (reason, count) in output["summary"]["droppedByReason"].as_object().into_iter().flatten() {
|
||||
md.push_str(&format!("- `{reason}`: `{}`\n", count.as_u64().unwrap_or(0)));
|
||||
for (reason, count) in output["summary"]["droppedByReason"]
|
||||
.as_object()
|
||||
.into_iter()
|
||||
.flatten()
|
||||
{
|
||||
md.push_str(&format!(
|
||||
"- `{reason}`: `{}`\n",
|
||||
count.as_u64().unwrap_or(0)
|
||||
));
|
||||
}
|
||||
if let Some(parent) = md_out.parent() {
|
||||
std::fs::create_dir_all(parent).map_err(|e| format!("create markdown parent failed: {e}"))?;
|
||||
std::fs::create_dir_all(parent)
|
||||
.map_err(|e| format!("create markdown parent failed: {e}"))?;
|
||||
}
|
||||
std::fs::write(&md_out, md).map_err(|e| format!("write markdown failed: {e}"))?;
|
||||
|
||||
|
||||
@@ -26,11 +26,15 @@ fn run(argv: Vec<String>) -> Result<(), String> {
|
||||
}
|
||||
"--tals-dir" => {
|
||||
i += 1;
|
||||
tals_dir = Some(PathBuf::from(argv.get(i).ok_or("--tals-dir requires a value")?));
|
||||
tals_dir = Some(PathBuf::from(
|
||||
argv.get(i).ok_or("--tals-dir requires a value")?,
|
||||
));
|
||||
}
|
||||
"--meta-json" => {
|
||||
i += 1;
|
||||
meta_json = Some(PathBuf::from(argv.get(i).ok_or("--meta-json requires a value")?));
|
||||
meta_json = Some(PathBuf::from(
|
||||
argv.get(i).ok_or("--meta-json requires a value")?,
|
||||
));
|
||||
}
|
||||
other => return Err(format!("unknown argument: {other}\n\n{}", usage())),
|
||||
}
|
||||
@@ -76,4 +80,3 @@ fn run(argv: Vec<String>) -> Result<(), String> {
|
||||
.map_err(|e| format!("write meta json failed: {}: {e}", meta_json.display()))?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use std::path::PathBuf;
|
||||
|
||||
fn usage() -> &'static str {
|
||||
"Usage: cir_materialize --cir <path> --static-root <path> --mirror-root <path> [--keep-db]"
|
||||
"Usage: cir_materialize --cir <path> (--static-root <path> | --raw-store-db <path>) --mirror-root <path> [--keep-db]"
|
||||
}
|
||||
|
||||
fn main() {
|
||||
@@ -14,6 +14,7 @@ fn main() {
|
||||
fn run(argv: Vec<String>) -> Result<(), String> {
|
||||
let mut cir_path: Option<PathBuf> = None;
|
||||
let mut static_root: Option<PathBuf> = None;
|
||||
let mut raw_store_db: Option<PathBuf> = None;
|
||||
let mut mirror_root: Option<PathBuf> = None;
|
||||
let mut keep_db = false;
|
||||
|
||||
@@ -31,6 +32,12 @@ fn run(argv: Vec<String>) -> Result<(), String> {
|
||||
argv.get(i).ok_or("--static-root requires a value")?,
|
||||
));
|
||||
}
|
||||
"--raw-store-db" => {
|
||||
i += 1;
|
||||
raw_store_db = Some(PathBuf::from(
|
||||
argv.get(i).ok_or("--raw-store-db requires a value")?,
|
||||
));
|
||||
}
|
||||
"--mirror-root" => {
|
||||
i += 1;
|
||||
mirror_root = Some(PathBuf::from(
|
||||
@@ -44,16 +51,29 @@ fn run(argv: Vec<String>) -> Result<(), String> {
|
||||
}
|
||||
|
||||
let cir_path = cir_path.ok_or_else(|| format!("--cir is required\n\n{}", usage()))?;
|
||||
let static_root =
|
||||
static_root.ok_or_else(|| format!("--static-root is required\n\n{}", usage()))?;
|
||||
let mirror_root =
|
||||
mirror_root.ok_or_else(|| format!("--mirror-root is required\n\n{}", usage()))?;
|
||||
let backend_count = static_root.is_some() as u8 + raw_store_db.is_some() as u8;
|
||||
if backend_count != 1 {
|
||||
return Err(format!(
|
||||
"must specify exactly one of --static-root or --raw-store-db\n\n{}",
|
||||
usage()
|
||||
));
|
||||
}
|
||||
|
||||
let bytes = std::fs::read(&cir_path)
|
||||
.map_err(|e| format!("read CIR failed: {}: {e}", cir_path.display()))?;
|
||||
let cir = rpki::cir::decode_cir(&bytes).map_err(|e| e.to_string())?;
|
||||
|
||||
let result = rpki::cir::materialize_cir(&cir, &static_root, &mirror_root, true);
|
||||
let result = if let Some(static_root) = static_root {
|
||||
rpki::cir::materialize_cir(&cir, &static_root, &mirror_root, true)
|
||||
.map_err(|e| e.to_string())
|
||||
} else if let Some(raw_store_db) = raw_store_db {
|
||||
rpki::cir::materialize_cir_from_raw_store(&cir, &raw_store_db, &mirror_root, true)
|
||||
.map_err(|e| e.to_string())
|
||||
} else {
|
||||
unreachable!("validated backend count")
|
||||
};
|
||||
match result {
|
||||
Ok(summary) => {
|
||||
eprintln!(
|
||||
@@ -74,4 +94,3 @@ fn run(argv: Vec<String>) -> Result<(), String> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,11 +1,26 @@
|
||||
use std::path::PathBuf;
|
||||
|
||||
use rpki::cir::{encode_cir, write_bytes_to_static_pool, CanonicalInputRepresentation, CirHashAlgorithm, CirObject, CirTal, CIR_VERSION_V1};
|
||||
use rpki::cir::{
|
||||
CIR_VERSION_V1, CanonicalInputRepresentation, CirHashAlgorithm, CirObject, CirTal, encode_cir,
|
||||
write_bytes_to_static_pool,
|
||||
};
|
||||
use sha2::Digest;
|
||||
|
||||
const USAGE: &str = "Usage: cir_ta_only_fixture --tal-path <path> --ta-path <path> --tal-uri <url> --validation-time <rfc3339> --cir-out <path> --static-root <path>";
|
||||
|
||||
fn parse_args(argv: &[String]) -> Result<(PathBuf, PathBuf, String, time::OffsetDateTime, PathBuf, PathBuf), String> {
|
||||
fn parse_args(
|
||||
argv: &[String],
|
||||
) -> Result<
|
||||
(
|
||||
PathBuf,
|
||||
PathBuf,
|
||||
String,
|
||||
time::OffsetDateTime,
|
||||
PathBuf,
|
||||
PathBuf,
|
||||
),
|
||||
String,
|
||||
> {
|
||||
let mut tal_path = None;
|
||||
let mut ta_path = None;
|
||||
let mut tal_uri = None;
|
||||
@@ -17,11 +32,15 @@ fn parse_args(argv: &[String]) -> Result<(PathBuf, PathBuf, String, time::Offset
|
||||
match argv[i].as_str() {
|
||||
"--tal-path" => {
|
||||
i += 1;
|
||||
tal_path = Some(PathBuf::from(argv.get(i).ok_or("--tal-path requires a value")?));
|
||||
tal_path = Some(PathBuf::from(
|
||||
argv.get(i).ok_or("--tal-path requires a value")?,
|
||||
));
|
||||
}
|
||||
"--ta-path" => {
|
||||
i += 1;
|
||||
ta_path = Some(PathBuf::from(argv.get(i).ok_or("--ta-path requires a value")?));
|
||||
ta_path = Some(PathBuf::from(
|
||||
argv.get(i).ok_or("--ta-path requires a value")?,
|
||||
));
|
||||
}
|
||||
"--tal-uri" => {
|
||||
i += 1;
|
||||
@@ -40,12 +59,15 @@ fn parse_args(argv: &[String]) -> Result<(PathBuf, PathBuf, String, time::Offset
|
||||
}
|
||||
"--cir-out" => {
|
||||
i += 1;
|
||||
cir_out = Some(PathBuf::from(argv.get(i).ok_or("--cir-out requires a value")?));
|
||||
cir_out = Some(PathBuf::from(
|
||||
argv.get(i).ok_or("--cir-out requires a value")?,
|
||||
));
|
||||
}
|
||||
"--static-root" => {
|
||||
i += 1;
|
||||
static_root =
|
||||
Some(PathBuf::from(argv.get(i).ok_or("--static-root requires a value")?));
|
||||
static_root = Some(PathBuf::from(
|
||||
argv.get(i).ok_or("--static-root requires a value")?,
|
||||
));
|
||||
}
|
||||
"-h" | "--help" => return Err(USAGE.to_string()),
|
||||
other => return Err(format!("unknown argument: {other}\n\n{USAGE}")),
|
||||
|
||||
@@ -4,8 +4,7 @@ use std::path::PathBuf;
|
||||
use rocksdb::{DB, IteratorMode, Options};
|
||||
use rpki::storage::{
|
||||
ALL_COLUMN_FAMILY_NAMES, CF_AUDIT_RULE_INDEX, CF_RAW_BY_HASH, CF_REPOSITORY_VIEW,
|
||||
CF_RRDP_SOURCE, CF_RRDP_SOURCE_MEMBER, CF_RRDP_URI_OWNER, CF_VCIR,
|
||||
column_family_descriptors,
|
||||
CF_RRDP_SOURCE, CF_RRDP_SOURCE_MEMBER, CF_RRDP_URI_OWNER, CF_VCIR, column_family_descriptors,
|
||||
};
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||
@@ -77,9 +76,7 @@ fn cf_group(cf_name: &str) -> CfGroup {
|
||||
match cf_name {
|
||||
CF_REPOSITORY_VIEW | CF_RAW_BY_HASH => CfGroup::CurrentRepositoryView,
|
||||
CF_VCIR | CF_AUDIT_RULE_INDEX => CfGroup::CurrentValidationState,
|
||||
CF_RRDP_SOURCE | CF_RRDP_SOURCE_MEMBER | CF_RRDP_URI_OWNER => {
|
||||
CfGroup::CurrentRrdpState
|
||||
}
|
||||
CF_RRDP_SOURCE | CF_RRDP_SOURCE_MEMBER | CF_RRDP_URI_OWNER => CfGroup::CurrentRrdpState,
|
||||
_ => CfGroup::LegacyCompatibility,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,10 +56,7 @@ fn parse_args() -> Result<Args, String> {
|
||||
i += 1;
|
||||
}
|
||||
if out.bundle_root.is_none() || out.out.is_none() {
|
||||
return Err(format!(
|
||||
"--bundle-root and --out are required\n{}",
|
||||
usage()
|
||||
));
|
||||
return Err(format!("--bundle-root and --out are required\n{}", usage()));
|
||||
}
|
||||
Ok(out)
|
||||
}
|
||||
@@ -188,10 +185,7 @@ fn real_main() -> Result<(), String> {
|
||||
.as_array()
|
||||
.ok_or("bundle missing deltaSequence.steps")?
|
||||
{
|
||||
let step_id = step["id"]
|
||||
.as_str()
|
||||
.ok_or("step missing id")?
|
||||
.to_string();
|
||||
let step_id = step["id"].as_str().ok_or("step missing id")?.to_string();
|
||||
let step_dir = path_join(
|
||||
&rir_dir,
|
||||
step["relativePath"]
|
||||
@@ -210,8 +204,9 @@ fn real_main() -> Result<(), String> {
|
||||
.as_str()
|
||||
.ok_or("step missing relativeTransitionLocksPath")?,
|
||||
);
|
||||
let validation_time = load_validation_time(&delta_locks)
|
||||
.map_err(|e| format!("load step validation time failed for {rir}/{step_id}: {e}"))?;
|
||||
let validation_time = load_validation_time(&delta_locks).map_err(|e| {
|
||||
format!("load step validation time failed for {rir}/{step_id}: {e}")
|
||||
})?;
|
||||
let start = Instant::now();
|
||||
let step_out = run_tree_from_tal_and_ta_der_payload_delta_replay_step_serial_audit(
|
||||
&store,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use rpki::bundle::{
|
||||
RirBundleMetadata, RecordingHttpFetcher, RecordingRsyncFetcher,
|
||||
build_single_rir_bundle_manifest, build_vap_compare_rows, build_vrp_compare_rows,
|
||||
sha256_hex, write_json, write_live_base_replay_bundle_inputs, write_live_bundle_rir_readme,
|
||||
RecordingHttpFetcher, RecordingRsyncFetcher, RirBundleMetadata,
|
||||
build_single_rir_bundle_manifest, build_vap_compare_rows, build_vrp_compare_rows, sha256_hex,
|
||||
write_json, write_live_base_replay_bundle_inputs, write_live_bundle_rir_readme,
|
||||
write_live_bundle_top_readme, write_timing_json, write_vap_csv, write_vrp_csv,
|
||||
};
|
||||
use rpki::ccr::{build_ccr_from_run, verify_content_info, write_ccr_file};
|
||||
@@ -54,15 +54,21 @@ fn parse_args(argv: &[String]) -> Result<Args, String> {
|
||||
}
|
||||
"--out-dir" => {
|
||||
i += 1;
|
||||
args.out_dir = Some(PathBuf::from(argv.get(i).ok_or("--out-dir requires a value")?));
|
||||
args.out_dir = Some(PathBuf::from(
|
||||
argv.get(i).ok_or("--out-dir requires a value")?,
|
||||
));
|
||||
}
|
||||
"--tal-path" => {
|
||||
i += 1;
|
||||
args.tal_path = Some(PathBuf::from(argv.get(i).ok_or("--tal-path requires a value")?));
|
||||
args.tal_path = Some(PathBuf::from(
|
||||
argv.get(i).ok_or("--tal-path requires a value")?,
|
||||
));
|
||||
}
|
||||
"--ta-path" => {
|
||||
i += 1;
|
||||
args.ta_path = Some(PathBuf::from(argv.get(i).ok_or("--ta-path requires a value")?));
|
||||
args.ta_path = Some(PathBuf::from(
|
||||
argv.get(i).ok_or("--ta-path requires a value")?,
|
||||
));
|
||||
}
|
||||
"--validation-time" => {
|
||||
i += 1;
|
||||
@@ -90,8 +96,9 @@ fn parse_args(argv: &[String]) -> Result<Args, String> {
|
||||
}
|
||||
"--rsync-mirror-root" => {
|
||||
i += 1;
|
||||
args.rsync_mirror_root =
|
||||
Some(PathBuf::from(argv.get(i).ok_or("--rsync-mirror-root requires a value")?));
|
||||
args.rsync_mirror_root = Some(PathBuf::from(
|
||||
argv.get(i).ok_or("--rsync-mirror-root requires a value")?,
|
||||
));
|
||||
}
|
||||
"--max-depth" => {
|
||||
i += 1;
|
||||
@@ -113,7 +120,11 @@ fn parse_args(argv: &[String]) -> Result<Args, String> {
|
||||
}
|
||||
"--trust-anchor" => {
|
||||
i += 1;
|
||||
args.trust_anchor = Some(argv.get(i).ok_or("--trust-anchor requires a value")?.clone());
|
||||
args.trust_anchor = Some(
|
||||
argv.get(i)
|
||||
.ok_or("--trust-anchor requires a value")?
|
||||
.clone(),
|
||||
);
|
||||
}
|
||||
other => return Err(format!("unknown argument: {other}\n{}", usage())),
|
||||
}
|
||||
@@ -147,11 +158,13 @@ fn run(args: Args) -> Result<PathBuf, String> {
|
||||
fs::create_dir_all(&rir_dir)
|
||||
.map_err(|e| format!("create rir dir failed: {}: {e}", rir_dir.display()))?;
|
||||
|
||||
let tal_bytes = fs::read(args.tal_path.as_ref().unwrap())
|
||||
.map_err(|e| format!("read tal failed: {e}"))?;
|
||||
let ta_bytes = fs::read(args.ta_path.as_ref().unwrap())
|
||||
.map_err(|e| format!("read ta failed: {e}"))?;
|
||||
let validation_time = args.validation_time.unwrap_or_else(time::OffsetDateTime::now_utc);
|
||||
let tal_bytes =
|
||||
fs::read(args.tal_path.as_ref().unwrap()).map_err(|e| format!("read tal failed: {e}"))?;
|
||||
let ta_bytes =
|
||||
fs::read(args.ta_path.as_ref().unwrap()).map_err(|e| format!("read ta failed: {e}"))?;
|
||||
let validation_time = args
|
||||
.validation_time
|
||||
.unwrap_or_else(time::OffsetDateTime::now_utc);
|
||||
|
||||
let db_dir = out_root.join(".tmp").join(format!("{rir}-live-base-db"));
|
||||
let replay_db_dir = out_root.join(".tmp").join(format!("{rir}-self-replay-db"));
|
||||
@@ -205,8 +218,8 @@ fn run(args: Args) -> Result<PathBuf, String> {
|
||||
.map_err(|e| format!("build ccr failed: {e}"))?;
|
||||
let base_ccr_path = rir_dir.join("base.ccr");
|
||||
write_ccr_file(&base_ccr_path, &ccr).map_err(|e| format!("write ccr failed: {e}"))?;
|
||||
let ccr_bytes =
|
||||
fs::read(&base_ccr_path).map_err(|e| format!("read written ccr failed: {}: {e}", base_ccr_path.display()))?;
|
||||
let ccr_bytes = fs::read(&base_ccr_path)
|
||||
.map_err(|e| format!("read written ccr failed: {}: {e}", base_ccr_path.display()))?;
|
||||
let decoded = rpki::ccr::decode_content_info(&ccr_bytes)
|
||||
.map_err(|e| format!("decode written ccr failed: {e}"))?;
|
||||
let verify = verify_content_info(&decoded).map_err(|e| format!("verify ccr failed: {e}"))?;
|
||||
@@ -235,8 +248,8 @@ fn run(args: Args) -> Result<PathBuf, String> {
|
||||
&rsync.snapshot_fetches(),
|
||||
)?;
|
||||
|
||||
let replay_store =
|
||||
RocksStore::open(&replay_db_dir).map_err(|e| format!("open self replay rocksdb failed: {e}"))?;
|
||||
let replay_store = RocksStore::open(&replay_db_dir)
|
||||
.map_err(|e| format!("open self replay rocksdb failed: {e}"))?;
|
||||
let replay_out = run_tree_from_tal_and_ta_der_payload_replay_serial_audit(
|
||||
&replay_store,
|
||||
&Policy::default(),
|
||||
@@ -320,7 +333,11 @@ fn run(args: Args) -> Result<PathBuf, String> {
|
||||
}),
|
||||
)?;
|
||||
write_live_bundle_top_readme(&out_root.join("README.md"), &rir_normalized)?;
|
||||
write_live_bundle_rir_readme(&rir_dir.join("README.md"), &rir_normalized, &metadata.base_validation_time)?;
|
||||
write_live_bundle_rir_readme(
|
||||
&rir_dir.join("README.md"),
|
||||
&rir_normalized,
|
||||
&metadata.base_validation_time,
|
||||
)?;
|
||||
write_json(
|
||||
&out_root.join("bundle-manifest.json"),
|
||||
&build_single_rir_bundle_manifest(
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use rpki::bundle::{
|
||||
RecordingHttpFetcher, RecordingRsyncFetcher, build_single_rir_bundle_manifest,
|
||||
build_vap_compare_rows, build_vrp_compare_rows, copy_dir_all, load_validation_time,
|
||||
sha256_hex, write_json, write_live_delta_replay_bundle_inputs, write_vap_csv, write_vrp_csv,
|
||||
build_vap_compare_rows, build_vrp_compare_rows, copy_dir_all, load_validation_time, sha256_hex,
|
||||
write_json, write_live_delta_replay_bundle_inputs, write_vap_csv, write_vrp_csv,
|
||||
};
|
||||
use rpki::ccr::{build_ccr_from_run, decode_content_info, verify_content_info, write_ccr_file};
|
||||
use rpki::fetch::http::{BlockingHttpFetcher, HttpFetcherConfig};
|
||||
@@ -54,12 +54,15 @@ fn parse_args(argv: &[String]) -> Result<Args, String> {
|
||||
}
|
||||
"--base-bundle-dir" => {
|
||||
i += 1;
|
||||
args.base_bundle_dir =
|
||||
Some(PathBuf::from(argv.get(i).ok_or("--base-bundle-dir requires a value")?));
|
||||
args.base_bundle_dir = Some(PathBuf::from(
|
||||
argv.get(i).ok_or("--base-bundle-dir requires a value")?,
|
||||
));
|
||||
}
|
||||
"--out-dir" => {
|
||||
i += 1;
|
||||
args.out_dir = Some(PathBuf::from(argv.get(i).ok_or("--out-dir requires a value")?));
|
||||
args.out_dir = Some(PathBuf::from(
|
||||
argv.get(i).ok_or("--out-dir requires a value")?,
|
||||
));
|
||||
}
|
||||
"--validation-time" => {
|
||||
i += 1;
|
||||
@@ -87,8 +90,9 @@ fn parse_args(argv: &[String]) -> Result<Args, String> {
|
||||
}
|
||||
"--rsync-mirror-root" => {
|
||||
i += 1;
|
||||
args.rsync_mirror_root =
|
||||
Some(PathBuf::from(argv.get(i).ok_or("--rsync-mirror-root requires a value")?));
|
||||
args.rsync_mirror_root = Some(PathBuf::from(
|
||||
argv.get(i).ok_or("--rsync-mirror-root requires a value")?,
|
||||
));
|
||||
}
|
||||
"--max-depth" => {
|
||||
i += 1;
|
||||
@@ -110,7 +114,11 @@ fn parse_args(argv: &[String]) -> Result<Args, String> {
|
||||
}
|
||||
"--trust-anchor" => {
|
||||
i += 1;
|
||||
args.trust_anchor = Some(argv.get(i).ok_or("--trust-anchor requires a value")?.clone());
|
||||
args.trust_anchor = Some(
|
||||
argv.get(i)
|
||||
.ok_or("--trust-anchor requires a value")?
|
||||
.clone(),
|
||||
);
|
||||
}
|
||||
other => return Err(format!("unknown argument: {other}\n{}", usage())),
|
||||
}
|
||||
@@ -193,7 +201,10 @@ fn run(args: Args) -> Result<PathBuf, String> {
|
||||
let base_root = args.base_bundle_dir.as_ref().unwrap();
|
||||
let base_rir_dir = base_root.join(&rir_normalized);
|
||||
if !base_rir_dir.is_dir() {
|
||||
return Err(format!("base bundle rir dir not found: {}", base_rir_dir.display()));
|
||||
return Err(format!(
|
||||
"base bundle rir dir not found: {}",
|
||||
base_rir_dir.display()
|
||||
));
|
||||
}
|
||||
if out_root.exists() {
|
||||
fs::remove_dir_all(out_root)
|
||||
@@ -206,12 +217,14 @@ fn run(args: Args) -> Result<PathBuf, String> {
|
||||
.trust_anchor
|
||||
.clone()
|
||||
.unwrap_or_else(|| rir_normalized.clone());
|
||||
let tal_bytes =
|
||||
fs::read(rir_dir.join("tal.tal")).map_err(|e| format!("read tal from base bundle failed: {e}"))?;
|
||||
let ta_bytes =
|
||||
fs::read(rir_dir.join("ta.cer")).map_err(|e| format!("read ta from base bundle failed: {e}"))?;
|
||||
let tal_bytes = fs::read(rir_dir.join("tal.tal"))
|
||||
.map_err(|e| format!("read tal from base bundle failed: {e}"))?;
|
||||
let ta_bytes = fs::read(rir_dir.join("ta.cer"))
|
||||
.map_err(|e| format!("read ta from base bundle failed: {e}"))?;
|
||||
let base_validation_time = load_validation_time(&rir_dir.join("base-locks.json"))?;
|
||||
let target_validation_time = args.validation_time.unwrap_or_else(time::OffsetDateTime::now_utc);
|
||||
let target_validation_time = args
|
||||
.validation_time
|
||||
.unwrap_or_else(time::OffsetDateTime::now_utc);
|
||||
|
||||
let target_store_dir = out_root.join(".tmp").join(format!("{rir}-live-target-db"));
|
||||
let self_replay_dir = out_root.join(".tmp").join(format!("{rir}-self-delta-db"));
|
||||
@@ -221,8 +234,8 @@ fn run(args: Args) -> Result<PathBuf, String> {
|
||||
fs::create_dir_all(parent)
|
||||
.map_err(|e| format!("create tmp dir failed: {}: {e}", parent.display()))?;
|
||||
}
|
||||
let target_store =
|
||||
RocksStore::open(&target_store_dir).map_err(|e| format!("open target rocksdb failed: {e}"))?;
|
||||
let target_store = RocksStore::open(&target_store_dir)
|
||||
.map_err(|e| format!("open target rocksdb failed: {e}"))?;
|
||||
|
||||
let _base = run_tree_from_tal_and_ta_der_payload_replay_serial_audit(
|
||||
&target_store,
|
||||
@@ -282,17 +295,19 @@ fn run(args: Args) -> Result<PathBuf, String> {
|
||||
)
|
||||
.map_err(|e| format!("build delta ccr failed: {e}"))?;
|
||||
let delta_ccr_path = rir_dir.join("delta.ccr");
|
||||
write_ccr_file(&delta_ccr_path, &delta_ccr).map_err(|e| format!("write delta ccr failed: {e}"))?;
|
||||
let delta_ccr_bytes =
|
||||
fs::read(&delta_ccr_path).map_err(|e| format!("read delta ccr failed: {}: {e}", delta_ccr_path.display()))?;
|
||||
let delta_decoded =
|
||||
decode_content_info(&delta_ccr_bytes).map_err(|e| format!("decode delta ccr failed: {e}"))?;
|
||||
write_ccr_file(&delta_ccr_path, &delta_ccr)
|
||||
.map_err(|e| format!("write delta ccr failed: {e}"))?;
|
||||
let delta_ccr_bytes = fs::read(&delta_ccr_path)
|
||||
.map_err(|e| format!("read delta ccr failed: {}: {e}", delta_ccr_path.display()))?;
|
||||
let delta_decoded = decode_content_info(&delta_ccr_bytes)
|
||||
.map_err(|e| format!("decode delta ccr failed: {e}"))?;
|
||||
let delta_verify =
|
||||
verify_content_info(&delta_decoded).map_err(|e| format!("verify delta ccr failed: {e}"))?;
|
||||
|
||||
let delta_vrp_rows = build_vrp_compare_rows(&target_out.tree.vrps, &trust_anchor);
|
||||
let delta_vap_rows = build_vap_compare_rows(&target_out.tree.aspas, &trust_anchor);
|
||||
let (ccr_vrps, ccr_vaps) = rpki::bundle::decode_ccr_compare_views(&delta_decoded, &trust_anchor)?;
|
||||
let (ccr_vrps, ccr_vaps) =
|
||||
rpki::bundle::decode_ccr_compare_views(&delta_decoded, &trust_anchor)?;
|
||||
if delta_vrp_rows != ccr_vrps {
|
||||
return Err("record-delta.csv compare view does not match delta.ccr".to_string());
|
||||
}
|
||||
@@ -312,8 +327,8 @@ fn run(args: Args) -> Result<PathBuf, String> {
|
||||
&rsync.snapshot_fetches(),
|
||||
)?;
|
||||
|
||||
let self_store =
|
||||
RocksStore::open(&self_replay_dir).map_err(|e| format!("open self replay db failed: {e}"))?;
|
||||
let self_store = RocksStore::open(&self_replay_dir)
|
||||
.map_err(|e| format!("open self replay db failed: {e}"))?;
|
||||
let replay_out = run_tree_from_tal_and_ta_der_payload_delta_replay_serial_audit(
|
||||
&self_store,
|
||||
&Policy::default(),
|
||||
@@ -355,7 +370,8 @@ fn run(args: Args) -> Result<PathBuf, String> {
|
||||
)?;
|
||||
|
||||
let mut bundle_json: serde_json::Value = serde_json::from_slice(
|
||||
&fs::read(rir_dir.join("bundle.json")).map_err(|e| format!("read base bundle.json failed: {e}"))?,
|
||||
&fs::read(rir_dir.join("bundle.json"))
|
||||
.map_err(|e| format!("read base bundle.json failed: {e}"))?,
|
||||
)
|
||||
.map_err(|e| format!("parse base bundle.json failed: {e}"))?;
|
||||
bundle_json["deltaValidationTime"] = serde_json::Value::String(
|
||||
|
||||
@@ -65,19 +65,27 @@ fn parse_args(argv: &[String]) -> Result<Args, String> {
|
||||
}
|
||||
"--out-dir" => {
|
||||
i += 1;
|
||||
args.out_dir = Some(PathBuf::from(argv.get(i).ok_or("--out-dir requires a value")?));
|
||||
args.out_dir = Some(PathBuf::from(
|
||||
argv.get(i).ok_or("--out-dir requires a value")?,
|
||||
));
|
||||
}
|
||||
"--tal-path" => {
|
||||
i += 1;
|
||||
args.tal_path = Some(PathBuf::from(argv.get(i).ok_or("--tal-path requires a value")?));
|
||||
args.tal_path = Some(PathBuf::from(
|
||||
argv.get(i).ok_or("--tal-path requires a value")?,
|
||||
));
|
||||
}
|
||||
"--ta-path" => {
|
||||
i += 1;
|
||||
args.ta_path = Some(PathBuf::from(argv.get(i).ok_or("--ta-path requires a value")?));
|
||||
args.ta_path = Some(PathBuf::from(
|
||||
argv.get(i).ok_or("--ta-path requires a value")?,
|
||||
));
|
||||
}
|
||||
"--base-validation-time" => {
|
||||
i += 1;
|
||||
let value = argv.get(i).ok_or("--base-validation-time requires a value")?;
|
||||
let value = argv
|
||||
.get(i)
|
||||
.ok_or("--base-validation-time requires a value")?;
|
||||
args.base_validation_time = Some(
|
||||
time::OffsetDateTime::parse(value, &Rfc3339)
|
||||
.map_err(|e| format!("invalid --base-validation-time: {e}"))?,
|
||||
@@ -117,8 +125,9 @@ fn parse_args(argv: &[String]) -> Result<Args, String> {
|
||||
}
|
||||
"--rsync-mirror-root" => {
|
||||
i += 1;
|
||||
args.rsync_mirror_root =
|
||||
Some(PathBuf::from(argv.get(i).ok_or("--rsync-mirror-root requires a value")?));
|
||||
args.rsync_mirror_root = Some(PathBuf::from(
|
||||
argv.get(i).ok_or("--rsync-mirror-root requires a value")?,
|
||||
));
|
||||
}
|
||||
"--max-depth" => {
|
||||
i += 1;
|
||||
@@ -140,7 +149,11 @@ fn parse_args(argv: &[String]) -> Result<Args, String> {
|
||||
}
|
||||
"--trust-anchor" => {
|
||||
i += 1;
|
||||
args.trust_anchor = Some(argv.get(i).ok_or("--trust-anchor requires a value")?.clone());
|
||||
args.trust_anchor = Some(
|
||||
argv.get(i)
|
||||
.ok_or("--trust-anchor requires a value")?
|
||||
.clone(),
|
||||
);
|
||||
}
|
||||
"--keep-db" => args.keep_db = true,
|
||||
"--capture-inputs-only" => args.capture_inputs_only = true,
|
||||
@@ -164,7 +177,12 @@ fn parse_args(argv: &[String]) -> Result<Args, String> {
|
||||
Ok(args)
|
||||
}
|
||||
|
||||
fn write_v2_top_readme(path: &Path, rir: &str, delta_count: usize, delta_interval_secs: u64) -> Result<(), String> {
|
||||
fn write_v2_top_readme(
|
||||
path: &Path,
|
||||
rir: &str,
|
||||
delta_count: usize,
|
||||
delta_interval_secs: u64,
|
||||
) -> Result<(), String> {
|
||||
if let Some(parent) = path.parent() {
|
||||
fs::create_dir_all(parent)
|
||||
.map_err(|e| format!("create parent failed: {}: {e}", parent.display()))?;
|
||||
@@ -203,11 +221,19 @@ fn ensure_recorded_target_snapshots_for_locks(
|
||||
previous_locks_path: &Path,
|
||||
http: &RecordingHttpFetcher<BlockingHttpFetcher>,
|
||||
) -> Result<(), String> {
|
||||
let previous_locks: serde_json::Value = serde_json::from_slice(
|
||||
&fs::read(previous_locks_path)
|
||||
.map_err(|e| format!("read previous locks failed: {}: {e}", previous_locks_path.display()))?,
|
||||
)
|
||||
.map_err(|e| format!("parse previous locks failed: {}: {e}", previous_locks_path.display()))?;
|
||||
let previous_locks: serde_json::Value =
|
||||
serde_json::from_slice(&fs::read(previous_locks_path).map_err(|e| {
|
||||
format!(
|
||||
"read previous locks failed: {}: {e}",
|
||||
previous_locks_path.display()
|
||||
)
|
||||
})?)
|
||||
.map_err(|e| {
|
||||
format!(
|
||||
"parse previous locks failed: {}: {e}",
|
||||
previous_locks_path.display()
|
||||
)
|
||||
})?;
|
||||
let previous_rrdp = previous_locks
|
||||
.get("rrdp")
|
||||
.and_then(|v| v.as_object())
|
||||
@@ -251,9 +277,7 @@ fn ensure_recorded_target_snapshots_for_locks(
|
||||
if let Err(err) = http.fetch(snapshot_uri) {
|
||||
eprintln!(
|
||||
"[sequence] warning: fetch target snapshot failed notify_uri={} snapshot_uri={} err={}",
|
||||
notify_uri,
|
||||
snapshot_uri,
|
||||
err
|
||||
notify_uri, snapshot_uri, err
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -281,20 +305,30 @@ fn run(args: Args) -> Result<PathBuf, String> {
|
||||
}
|
||||
let rir_dir = out_root.join(&rir_normalized);
|
||||
let delta_steps_root = rir_dir.join("delta-steps");
|
||||
fs::create_dir_all(&delta_steps_root)
|
||||
.map_err(|e| format!("create delta steps dir failed: {}: {e}", delta_steps_root.display()))?;
|
||||
fs::create_dir_all(&delta_steps_root).map_err(|e| {
|
||||
format!(
|
||||
"create delta steps dir failed: {}: {e}",
|
||||
delta_steps_root.display()
|
||||
)
|
||||
})?;
|
||||
|
||||
let tal_bytes = fs::read(args.tal_path.as_ref().unwrap())
|
||||
.map_err(|e| format!("read tal failed: {e}"))?;
|
||||
let ta_bytes = fs::read(args.ta_path.as_ref().unwrap())
|
||||
.map_err(|e| format!("read ta failed: {e}"))?;
|
||||
let tal_bytes =
|
||||
fs::read(args.tal_path.as_ref().unwrap()).map_err(|e| format!("read tal failed: {e}"))?;
|
||||
let ta_bytes =
|
||||
fs::read(args.ta_path.as_ref().unwrap()).map_err(|e| format!("read ta failed: {e}"))?;
|
||||
fs::write(rir_dir.join("tal.tal"), &tal_bytes).map_err(|e| format!("write tal failed: {e}"))?;
|
||||
fs::write(rir_dir.join("ta.cer"), &ta_bytes).map_err(|e| format!("write ta failed: {e}"))?;
|
||||
|
||||
let base_validation_time = args.base_validation_time.unwrap_or_else(time::OffsetDateTime::now_utc);
|
||||
let base_validation_time = args
|
||||
.base_validation_time
|
||||
.unwrap_or_else(time::OffsetDateTime::now_utc);
|
||||
|
||||
let work_db_dir = out_root.join(".tmp").join(format!("{rir}-sequence-work-db"));
|
||||
let base_self_replay_dir = out_root.join(".tmp").join(format!("{rir}-sequence-base-self-replay-db"));
|
||||
let work_db_dir = out_root
|
||||
.join(".tmp")
|
||||
.join(format!("{rir}-sequence-work-db"));
|
||||
let base_self_replay_dir = out_root
|
||||
.join(".tmp")
|
||||
.join(format!("{rir}-sequence-base-self-replay-db"));
|
||||
let _ = fs::remove_dir_all(&work_db_dir);
|
||||
let _ = fs::remove_dir_all(&base_self_replay_dir);
|
||||
if let Some(parent) = work_db_dir.parent() {
|
||||
@@ -356,9 +390,7 @@ fn run(args: Args) -> Result<PathBuf, String> {
|
||||
)?;
|
||||
eprintln!(
|
||||
"[sequence] base input materialization done rir={} rrdp_repos={} rsync_modules={}",
|
||||
rir_normalized,
|
||||
base_capture.rrdp_repo_count,
|
||||
base_capture.rsync_module_count
|
||||
rir_normalized, base_capture.rrdp_repo_count, base_capture.rsync_module_count
|
||||
);
|
||||
let base_ccr_path = rir_dir.join("base.ccr");
|
||||
let base_vrps_path = rir_dir.join("base-vrps.csv");
|
||||
@@ -402,8 +434,8 @@ fn run(args: Args) -> Result<PathBuf, String> {
|
||||
.map_err(|e| format!("read base ccr failed: {}: {e}", base_ccr_path.display()))?;
|
||||
let base_decoded = decode_content_info(&base_ccr_bytes)
|
||||
.map_err(|e| format!("decode base ccr failed: {e}"))?;
|
||||
let base_verify =
|
||||
verify_content_info(&base_decoded).map_err(|e| format!("verify base ccr failed: {e}"))?;
|
||||
let base_verify = verify_content_info(&base_decoded)
|
||||
.map_err(|e| format!("verify base ccr failed: {e}"))?;
|
||||
let base_vrp_rows = build_vrp_compare_rows(&base_out.tree.vrps, &trust_anchor);
|
||||
let base_vap_rows = build_vap_compare_rows(&base_out.tree.aspas, &trust_anchor);
|
||||
let (base_ccr_vrps, base_ccr_vaps) =
|
||||
@@ -464,7 +496,9 @@ fn run(args: Args) -> Result<PathBuf, String> {
|
||||
let mut delta_steps = Vec::new();
|
||||
let mut previous_locks_path = rir_dir.join("base-locks.json");
|
||||
let mut previous_ref = "base".to_string();
|
||||
let sequence_self_replay_dir = out_root.join(".tmp").join(format!("{rir}-sequence-self-replay-db"));
|
||||
let sequence_self_replay_dir = out_root
|
||||
.join(".tmp")
|
||||
.join(format!("{rir}-sequence-self-replay-db"));
|
||||
let _ = fs::remove_dir_all(&sequence_self_replay_dir);
|
||||
let sequence_replay_store = if args.capture_inputs_only {
|
||||
None
|
||||
@@ -499,7 +533,10 @@ fn run(args: Args) -> Result<PathBuf, String> {
|
||||
fs::create_dir_all(&step_dir)
|
||||
.map_err(|e| format!("create step dir failed: {}: {e}", step_dir.display()))?;
|
||||
let step_validation_time = time::OffsetDateTime::now_utc();
|
||||
eprintln!("[sequence] step live run start rir={} step={}", rir_normalized, step_id);
|
||||
eprintln!(
|
||||
"[sequence] step live run start rir={} step={}",
|
||||
rir_normalized, step_id
|
||||
);
|
||||
let step_http = RecordingHttpFetcher::new(
|
||||
BlockingHttpFetcher::new(HttpFetcherConfig {
|
||||
timeout: Duration::from_secs(args.http_timeout_secs),
|
||||
@@ -542,7 +579,10 @@ fn run(args: Args) -> Result<PathBuf, String> {
|
||||
);
|
||||
ensure_recorded_target_snapshots_for_locks(&store, &previous_locks_path, &step_http)?;
|
||||
|
||||
eprintln!("[sequence] step output generation phase start rir={} step={}", rir_normalized, step_id);
|
||||
eprintln!(
|
||||
"[sequence] step output generation phase start rir={} step={}",
|
||||
rir_normalized, step_id
|
||||
);
|
||||
let delta_ccr_path = step_dir.join("delta.ccr");
|
||||
let delta_vrps_path = step_dir.join("record-delta.csv");
|
||||
let delta_vaps_path = step_dir.join("record-delta-vaps.csv");
|
||||
@@ -550,8 +590,7 @@ fn run(args: Args) -> Result<PathBuf, String> {
|
||||
if args.capture_inputs_only {
|
||||
eprintln!(
|
||||
"[sequence] step CCR/self-replay skipped rir={} step={}",
|
||||
rir_normalized,
|
||||
step_id
|
||||
rir_normalized, step_id
|
||||
);
|
||||
(
|
||||
String::new(),
|
||||
@@ -573,7 +612,10 @@ fn run(args: Args) -> Result<PathBuf, String> {
|
||||
false,
|
||||
)
|
||||
} else {
|
||||
eprintln!("[sequence] step CCR/self-replay start rir={} step={}", rir_normalized, step_id);
|
||||
eprintln!(
|
||||
"[sequence] step CCR/self-replay start rir={} step={}",
|
||||
rir_normalized, step_id
|
||||
);
|
||||
let delta_ccr = build_ccr_from_run(
|
||||
&store,
|
||||
&[step_out.discovery.trust_anchor.clone()],
|
||||
@@ -597,31 +639,39 @@ fn run(args: Args) -> Result<PathBuf, String> {
|
||||
let (ccr_vrps, ccr_vaps) =
|
||||
rpki::bundle::decode_ccr_compare_views(&delta_decoded, &trust_anchor)?;
|
||||
if delta_vrp_rows != ccr_vrps {
|
||||
return Err(format!("{step_id} VRP compare view does not match delta.ccr"));
|
||||
return Err(format!(
|
||||
"{step_id} VRP compare view does not match delta.ccr"
|
||||
));
|
||||
}
|
||||
if delta_vap_rows != ccr_vaps {
|
||||
return Err(format!("{step_id} VAP compare view does not match delta.ccr"));
|
||||
return Err(format!(
|
||||
"{step_id} VAP compare view does not match delta.ccr"
|
||||
));
|
||||
}
|
||||
write_vrp_csv(&delta_vrps_path, &delta_vrp_rows)?;
|
||||
write_vap_csv(&delta_vaps_path, &delta_vap_rows)?;
|
||||
let step_replay_out = run_tree_from_tal_and_ta_der_payload_delta_replay_step_serial_audit(
|
||||
sequence_replay_store.as_ref().expect("sequence replay store"),
|
||||
&Policy::default(),
|
||||
&tal_bytes,
|
||||
&ta_bytes,
|
||||
None,
|
||||
&step_dir.join("payload-delta-archive"),
|
||||
&previous_locks_path,
|
||||
&step_dir.join("locks-delta.json"),
|
||||
step_validation_time,
|
||||
&TreeRunConfig {
|
||||
max_depth: args.max_depth,
|
||||
max_instances: args.max_instances,
|
||||
},
|
||||
)
|
||||
.map_err(|e| format!("sequence self replay failed for {step_id}: {e}"))?;
|
||||
let step_replay_out =
|
||||
run_tree_from_tal_and_ta_der_payload_delta_replay_step_serial_audit(
|
||||
sequence_replay_store
|
||||
.as_ref()
|
||||
.expect("sequence replay store"),
|
||||
&Policy::default(),
|
||||
&tal_bytes,
|
||||
&ta_bytes,
|
||||
None,
|
||||
&step_dir.join("payload-delta-archive"),
|
||||
&previous_locks_path,
|
||||
&step_dir.join("locks-delta.json"),
|
||||
step_validation_time,
|
||||
&TreeRunConfig {
|
||||
max_depth: args.max_depth,
|
||||
max_instances: args.max_instances,
|
||||
},
|
||||
)
|
||||
.map_err(|e| format!("sequence self replay failed for {step_id}: {e}"))?;
|
||||
let step_self_replay_ok =
|
||||
build_vrp_compare_rows(&step_replay_out.tree.vrps, &trust_anchor) == delta_vrp_rows
|
||||
build_vrp_compare_rows(&step_replay_out.tree.vrps, &trust_anchor)
|
||||
== delta_vrp_rows
|
||||
&& build_vap_compare_rows(&step_replay_out.tree.aspas, &trust_anchor)
|
||||
== delta_vap_rows;
|
||||
let output = (
|
||||
@@ -631,11 +681,17 @@ fn run(args: Args) -> Result<PathBuf, String> {
|
||||
delta_verify,
|
||||
step_self_replay_ok,
|
||||
);
|
||||
eprintln!("[sequence] step CCR/self-replay done rir={} step={}", rir_normalized, step_id);
|
||||
eprintln!(
|
||||
"[sequence] step CCR/self-replay done rir={} step={}",
|
||||
rir_normalized, step_id
|
||||
);
|
||||
output
|
||||
};
|
||||
|
||||
eprintln!("[sequence] step input materialization start rir={} step={}", rir_normalized, step_id);
|
||||
eprintln!(
|
||||
"[sequence] step input materialization start rir={} step={}",
|
||||
rir_normalized, step_id
|
||||
);
|
||||
let delta_capture = write_live_delta_replay_step_inputs(
|
||||
&step_dir,
|
||||
&rir_normalized,
|
||||
@@ -816,7 +872,12 @@ fn run(args: Args) -> Result<PathBuf, String> {
|
||||
}
|
||||
}),
|
||||
)?;
|
||||
write_v2_top_readme(&out_root.join("README.md"), &rir_normalized, args.delta_count, args.delta_interval_secs)?;
|
||||
write_v2_top_readme(
|
||||
&out_root.join("README.md"),
|
||||
&rir_normalized,
|
||||
args.delta_count,
|
||||
args.delta_interval_secs,
|
||||
)?;
|
||||
write_v2_rir_readme(
|
||||
&rir_dir.join("README.md"),
|
||||
&rir_normalized,
|
||||
|
||||
@@ -48,35 +48,49 @@ fn parse_args(argv: &[String]) -> Result<Args, String> {
|
||||
}
|
||||
"--out-dir" => {
|
||||
i += 1;
|
||||
args.out_dir = Some(PathBuf::from(argv.get(i).ok_or("--out-dir requires a value")?));
|
||||
args.out_dir = Some(PathBuf::from(
|
||||
argv.get(i).ok_or("--out-dir requires a value")?,
|
||||
));
|
||||
}
|
||||
"--tal-path" => {
|
||||
i += 1;
|
||||
args.tal_path = Some(PathBuf::from(argv.get(i).ok_or("--tal-path requires a value")?));
|
||||
args.tal_path = Some(PathBuf::from(
|
||||
argv.get(i).ok_or("--tal-path requires a value")?,
|
||||
));
|
||||
}
|
||||
"--ta-path" => {
|
||||
i += 1;
|
||||
args.ta_path = Some(PathBuf::from(argv.get(i).ok_or("--ta-path requires a value")?));
|
||||
args.ta_path = Some(PathBuf::from(
|
||||
argv.get(i).ok_or("--ta-path requires a value")?,
|
||||
));
|
||||
}
|
||||
"--payload-replay-archive" => {
|
||||
i += 1;
|
||||
args.payload_replay_archive =
|
||||
Some(PathBuf::from(argv.get(i).ok_or("--payload-replay-archive requires a value")?));
|
||||
args.payload_replay_archive = Some(PathBuf::from(
|
||||
argv.get(i)
|
||||
.ok_or("--payload-replay-archive requires a value")?,
|
||||
));
|
||||
}
|
||||
"--payload-replay-locks" => {
|
||||
i += 1;
|
||||
args.payload_replay_locks =
|
||||
Some(PathBuf::from(argv.get(i).ok_or("--payload-replay-locks requires a value")?));
|
||||
args.payload_replay_locks = Some(PathBuf::from(
|
||||
argv.get(i)
|
||||
.ok_or("--payload-replay-locks requires a value")?,
|
||||
));
|
||||
}
|
||||
"--payload-delta-archive" => {
|
||||
i += 1;
|
||||
args.payload_delta_archive =
|
||||
Some(PathBuf::from(argv.get(i).ok_or("--payload-delta-archive requires a value")?));
|
||||
args.payload_delta_archive = Some(PathBuf::from(
|
||||
argv.get(i)
|
||||
.ok_or("--payload-delta-archive requires a value")?,
|
||||
));
|
||||
}
|
||||
"--payload-delta-locks" => {
|
||||
i += 1;
|
||||
args.payload_delta_locks =
|
||||
Some(PathBuf::from(argv.get(i).ok_or("--payload-delta-locks requires a value")?));
|
||||
args.payload_delta_locks = Some(PathBuf::from(
|
||||
argv.get(i)
|
||||
.ok_or("--payload-delta-locks requires a value")?,
|
||||
));
|
||||
}
|
||||
"--validation-time" => {
|
||||
i += 1;
|
||||
@@ -106,7 +120,11 @@ fn parse_args(argv: &[String]) -> Result<Args, String> {
|
||||
}
|
||||
"--trust-anchor" => {
|
||||
i += 1;
|
||||
args.trust_anchor = Some(argv.get(i).ok_or("--trust-anchor requires a value")?.clone());
|
||||
args.trust_anchor = Some(
|
||||
argv.get(i)
|
||||
.ok_or("--trust-anchor requires a value")?
|
||||
.clone(),
|
||||
);
|
||||
}
|
||||
other => return Err(format!("unknown argument: {other}\n{}", usage())),
|
||||
}
|
||||
@@ -155,7 +173,9 @@ fn sha256_hex(bytes: &[u8]) -> String {
|
||||
fn copy_dir_all(src: &Path, dst: &Path) -> Result<(), String> {
|
||||
fs::create_dir_all(dst)
|
||||
.map_err(|e| format!("create directory failed: {}: {e}", dst.display()))?;
|
||||
for entry in fs::read_dir(src).map_err(|e| format!("read_dir failed: {}: {e}", src.display()))? {
|
||||
for entry in
|
||||
fs::read_dir(src).map_err(|e| format!("read_dir failed: {}: {e}", src.display()))?
|
||||
{
|
||||
let entry = entry.map_err(|e| format!("read_dir entry failed: {}: {e}", src.display()))?;
|
||||
let ty = entry
|
||||
.file_type()
|
||||
@@ -168,8 +188,13 @@ fn copy_dir_all(src: &Path, dst: &Path) -> Result<(), String> {
|
||||
fs::create_dir_all(parent)
|
||||
.map_err(|e| format!("create parent failed: {}: {e}", parent.display()))?;
|
||||
}
|
||||
fs::copy(entry.path(), &to)
|
||||
.map_err(|e| format!("copy failed: {} -> {}: {e}", entry.path().display(), to.display()))?;
|
||||
fs::copy(entry.path(), &to).map_err(|e| {
|
||||
format!(
|
||||
"copy failed: {} -> {}: {e}",
|
||||
entry.path().display(),
|
||||
to.display()
|
||||
)
|
||||
})?;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
@@ -222,7 +247,10 @@ fn write_timing_json(
|
||||
)
|
||||
}
|
||||
|
||||
fn rewrite_delta_base_locks_sha(delta_root: &Path, emitted_base_locks_sha256: &str) -> Result<(), String> {
|
||||
fn rewrite_delta_base_locks_sha(
|
||||
delta_root: &Path,
|
||||
emitted_base_locks_sha256: &str,
|
||||
) -> Result<(), String> {
|
||||
let delta_locks = delta_root.join("locks-delta.json");
|
||||
if delta_locks.is_file() {
|
||||
let mut json: serde_json::Value = serde_json::from_slice(
|
||||
@@ -243,7 +271,8 @@ fn rewrite_delta_base_locks_sha(delta_root: &Path, emitted_base_locks_sha256: &s
|
||||
if archive_root.is_dir() {
|
||||
for path in walk_json_files_named(&archive_root, "base.json")? {
|
||||
let mut json: serde_json::Value = serde_json::from_slice(
|
||||
&fs::read(&path).map_err(|e| format!("read base.json failed: {}: {e}", path.display()))?,
|
||||
&fs::read(&path)
|
||||
.map_err(|e| format!("read base.json failed: {}: {e}", path.display()))?,
|
||||
)
|
||||
.map_err(|e| format!("parse base.json failed: {}: {e}", path.display()))?;
|
||||
json.as_object_mut()
|
||||
@@ -265,8 +294,11 @@ fn walk_json_files_named(root: &Path, name: &str) -> Result<Vec<PathBuf>, String
|
||||
}
|
||||
let mut stack = vec![root.to_path_buf()];
|
||||
while let Some(dir) = stack.pop() {
|
||||
for entry in fs::read_dir(&dir).map_err(|e| format!("read_dir failed: {}: {e}", dir.display()))? {
|
||||
let entry = entry.map_err(|e| format!("read_dir entry failed: {}: {e}", dir.display()))?;
|
||||
for entry in
|
||||
fs::read_dir(&dir).map_err(|e| format!("read_dir failed: {}: {e}", dir.display()))?
|
||||
{
|
||||
let entry =
|
||||
entry.map_err(|e| format!("read_dir entry failed: {}: {e}", dir.display()))?;
|
||||
let path = entry.path();
|
||||
let ty = entry
|
||||
.file_type()
|
||||
@@ -308,8 +340,10 @@ fn run(args: Args) -> Result<PathBuf, String> {
|
||||
fs::create_dir_all(&rir_dir)
|
||||
.map_err(|e| format!("create rir dir failed: {}: {e}", rir_dir.display()))?;
|
||||
|
||||
let tal_bytes = fs::read(tal_path).map_err(|e| format!("read tal failed: {}: {e}", tal_path.display()))?;
|
||||
let ta_bytes = fs::read(ta_path).map_err(|e| format!("read ta failed: {}: {e}", ta_path.display()))?;
|
||||
let tal_bytes =
|
||||
fs::read(tal_path).map_err(|e| format!("read tal failed: {}: {e}", tal_path.display()))?;
|
||||
let ta_bytes =
|
||||
fs::read(ta_path).map_err(|e| format!("read ta failed: {}: {e}", ta_path.display()))?;
|
||||
|
||||
let db_dir = run_root.join(".tmp").join(format!("{rir}-base-db"));
|
||||
if db_dir.exists() {
|
||||
@@ -354,7 +388,8 @@ fn run(args: Args) -> Result<PathBuf, String> {
|
||||
write_ccr_file(&base_ccr_path, &ccr).map_err(|e| format!("write ccr failed: {e}"))?;
|
||||
let ccr_bytes = fs::read(&base_ccr_path)
|
||||
.map_err(|e| format!("read written ccr failed: {}: {e}", base_ccr_path.display()))?;
|
||||
let decoded = decode_content_info(&ccr_bytes).map_err(|e| format!("decode written ccr failed: {e}"))?;
|
||||
let decoded =
|
||||
decode_content_info(&ccr_bytes).map_err(|e| format!("decode written ccr failed: {e}"))?;
|
||||
let verify = verify_content_info(&decoded).map_err(|e| format!("verify ccr failed: {e}"))?;
|
||||
|
||||
let vrp_rows = build_vrp_compare_rows(&out.tree.vrps, &trust_anchor);
|
||||
@@ -385,10 +420,13 @@ fn run(args: Args) -> Result<PathBuf, String> {
|
||||
);
|
||||
let emitted_base_locks_path = rir_dir.join("base-locks.json");
|
||||
write_json(&emitted_base_locks_path, &base_locks_json)?;
|
||||
let emitted_base_locks_sha256 = sha256_hex(
|
||||
&fs::read(&emitted_base_locks_path)
|
||||
.map_err(|e| format!("read emitted base locks failed: {}: {e}", emitted_base_locks_path.display()))?,
|
||||
);
|
||||
let emitted_base_locks_sha256 =
|
||||
sha256_hex(&fs::read(&emitted_base_locks_path).map_err(|e| {
|
||||
format!(
|
||||
"read emitted base locks failed: {}: {e}",
|
||||
emitted_base_locks_path.display()
|
||||
)
|
||||
})?);
|
||||
|
||||
if let Some(delta_archive) = args.payload_delta_archive.as_ref() {
|
||||
copy_dir_all(delta_archive, &rir_dir.join("payload-delta-archive"))?;
|
||||
@@ -418,10 +456,8 @@ fn run(args: Args) -> Result<PathBuf, String> {
|
||||
rewrite_delta_base_locks_sha(&rir_dir, &emitted_base_locks_sha256)?;
|
||||
}
|
||||
|
||||
fs::write(rir_dir.join("tal.tal"), &tal_bytes)
|
||||
.map_err(|e| format!("write tal failed: {e}"))?;
|
||||
fs::write(rir_dir.join("ta.cer"), &ta_bytes)
|
||||
.map_err(|e| format!("write ta failed: {e}"))?;
|
||||
fs::write(rir_dir.join("tal.tal"), &tal_bytes).map_err(|e| format!("write tal failed: {e}"))?;
|
||||
fs::write(rir_dir.join("ta.cer"), &ta_bytes).map_err(|e| format!("write ta failed: {e}"))?;
|
||||
|
||||
let mut metadata = RirBundleMetadata {
|
||||
schema_version: "20260330-v1".to_string(),
|
||||
@@ -484,15 +520,19 @@ fn run(args: Args) -> Result<PathBuf, String> {
|
||||
) {
|
||||
let delta_db_dir = run_root.join(".tmp").join(format!("{rir}-delta-db"));
|
||||
if delta_db_dir.exists() {
|
||||
fs::remove_dir_all(&delta_db_dir)
|
||||
.map_err(|e| format!("remove old delta db failed: {}: {e}", delta_db_dir.display()))?;
|
||||
fs::remove_dir_all(&delta_db_dir).map_err(|e| {
|
||||
format!(
|
||||
"remove old delta db failed: {}: {e}",
|
||||
delta_db_dir.display()
|
||||
)
|
||||
})?;
|
||||
}
|
||||
if let Some(parent) = delta_db_dir.parent() {
|
||||
fs::create_dir_all(parent)
|
||||
.map_err(|e| format!("create delta db parent failed: {}: {e}", parent.display()))?;
|
||||
}
|
||||
let delta_store =
|
||||
RocksStore::open(&delta_db_dir).map_err(|e| format!("open delta rocksdb failed: {e}"))?;
|
||||
let delta_store = RocksStore::open(&delta_db_dir)
|
||||
.map_err(|e| format!("open delta rocksdb failed: {e}"))?;
|
||||
let delta_started = Instant::now();
|
||||
let delta_out = run_tree_from_tal_and_ta_der_payload_delta_replay_serial_audit(
|
||||
&delta_store,
|
||||
@@ -527,16 +567,21 @@ fn run(args: Args) -> Result<PathBuf, String> {
|
||||
let delta_ccr_path = rir_dir.join("delta.ccr");
|
||||
write_ccr_file(&delta_ccr_path, &delta_ccr)
|
||||
.map_err(|e| format!("write delta ccr failed: {e}"))?;
|
||||
let delta_ccr_bytes = fs::read(&delta_ccr_path)
|
||||
.map_err(|e| format!("read written delta ccr failed: {}: {e}", delta_ccr_path.display()))?;
|
||||
let delta_ccr_bytes = fs::read(&delta_ccr_path).map_err(|e| {
|
||||
format!(
|
||||
"read written delta ccr failed: {}: {e}",
|
||||
delta_ccr_path.display()
|
||||
)
|
||||
})?;
|
||||
let delta_decoded = decode_content_info(&delta_ccr_bytes)
|
||||
.map_err(|e| format!("decode written delta ccr failed: {e}"))?;
|
||||
let delta_verify =
|
||||
verify_content_info(&delta_decoded).map_err(|e| format!("verify delta ccr failed: {e}"))?;
|
||||
let delta_verify = verify_content_info(&delta_decoded)
|
||||
.map_err(|e| format!("verify delta ccr failed: {e}"))?;
|
||||
|
||||
let delta_vrp_rows = build_vrp_compare_rows(&delta_out.tree.vrps, &trust_anchor);
|
||||
let delta_vap_rows = build_vap_compare_rows(&delta_out.tree.aspas, &trust_anchor);
|
||||
let (delta_ccr_vrps, delta_ccr_vaps) = decode_ccr_compare_views(&delta_decoded, &trust_anchor)?;
|
||||
let (delta_ccr_vrps, delta_ccr_vaps) =
|
||||
decode_ccr_compare_views(&delta_decoded, &trust_anchor)?;
|
||||
if delta_vrp_rows != delta_ccr_vrps {
|
||||
return Err("record-delta.csv compare view does not match delta.ccr".to_string());
|
||||
}
|
||||
@@ -585,7 +630,11 @@ fn run(args: Args) -> Result<PathBuf, String> {
|
||||
write_json(&rir_dir.join("bundle.json"), &metadata)?;
|
||||
write_json(&rir_dir.join("verification.json"), &verification)?;
|
||||
write_top_readme(&run_root.join("README.md"), rir)?;
|
||||
write_rir_readme(&rir_dir.join("README.md"), rir, &metadata.base_validation_time)?;
|
||||
write_rir_readme(
|
||||
&rir_dir.join("README.md"),
|
||||
rir,
|
||||
&metadata.base_validation_time,
|
||||
)?;
|
||||
|
||||
let bundle_manifest = BundleManifest {
|
||||
schema_version: "20260330-v1".to_string(),
|
||||
@@ -654,11 +703,8 @@ mod tests {
|
||||
fn load_validation_time_reads_top_level_validation_time() {
|
||||
let dir = tempdir().expect("tempdir");
|
||||
let path = dir.path().join("locks.json");
|
||||
std::fs::write(
|
||||
&path,
|
||||
r#"{"validationTime":"2026-03-16T11:49:15+08:00"}"#,
|
||||
)
|
||||
.expect("write locks");
|
||||
std::fs::write(&path, r#"{"validationTime":"2026-03-16T11:49:15+08:00"}"#)
|
||||
.expect("write locks");
|
||||
let got = load_validation_time(&path).expect("load validation time");
|
||||
assert_eq!(
|
||||
got.format(&Rfc3339).expect("format"),
|
||||
@@ -722,7 +768,12 @@ mod tests {
|
||||
assert!(out_dir.join("apnic").join("base-vaps.csv").is_file());
|
||||
assert!(out_dir.join("apnic").join("delta.ccr").is_file());
|
||||
assert!(out_dir.join("apnic").join("record-delta.csv").is_file());
|
||||
assert!(out_dir.join("apnic").join("record-delta-vaps.csv").is_file());
|
||||
assert!(
|
||||
out_dir
|
||||
.join("apnic")
|
||||
.join("record-delta-vaps.csv")
|
||||
.is_file()
|
||||
);
|
||||
assert!(out_dir.join("apnic").join("verification.json").is_file());
|
||||
let bundle_json: serde_json::Value = serde_json::from_slice(
|
||||
&std::fs::read(out_dir.join("apnic").join("bundle.json")).expect("read bundle.json"),
|
||||
@@ -734,11 +785,12 @@ mod tests {
|
||||
assert!(bundle_json.get("baseCcrSha256").is_some());
|
||||
assert!(bundle_json.get("deltaVrpCount").is_some());
|
||||
assert!(bundle_json.get("deltaCcrSha256").is_some());
|
||||
let base_locks_bytes =
|
||||
std::fs::read(out_dir.join("apnic").join("base-locks.json")).expect("read emitted base locks");
|
||||
let base_locks_bytes = std::fs::read(out_dir.join("apnic").join("base-locks.json"))
|
||||
.expect("read emitted base locks");
|
||||
let expected_base_locks_sha = sha256_hex(&base_locks_bytes);
|
||||
let delta_locks_json: serde_json::Value = serde_json::from_slice(
|
||||
&std::fs::read(out_dir.join("apnic").join("locks-delta.json")).expect("read delta locks"),
|
||||
&std::fs::read(out_dir.join("apnic").join("locks-delta.json"))
|
||||
.expect("read delta locks"),
|
||||
)
|
||||
.expect("parse delta locks");
|
||||
assert_eq!(delta_locks_json["baseLocksSha256"], expected_base_locks_sha);
|
||||
|
||||
@@ -177,16 +177,24 @@ fn materialize_rsync_module_from_store(
|
||||
.strip_prefix("rsync://")
|
||||
.ok_or_else(|| format!("invalid rsync module uri: {module_uri}"))?
|
||||
.trim_end_matches('/');
|
||||
fs::create_dir_all(tree_root.join(relative_root))
|
||||
.map_err(|e| format!("create rsync tree root failed: {}: {e}", tree_root.join(relative_root).display()))?;
|
||||
fs::create_dir_all(tree_root.join(relative_root)).map_err(|e| {
|
||||
format!(
|
||||
"create rsync tree root failed: {}: {e}",
|
||||
tree_root.join(relative_root).display()
|
||||
)
|
||||
})?;
|
||||
for (uri, bytes) in objects {
|
||||
let rel = uri
|
||||
.strip_prefix(module_uri)
|
||||
.ok_or_else(|| format!("object uri {uri} does not belong to module {module_uri}"))?;
|
||||
let path = tree_root.join(relative_root).join(rel);
|
||||
if let Some(parent) = path.parent() {
|
||||
fs::create_dir_all(parent)
|
||||
.map_err(|e| format!("create rsync object parent failed: {}: {e}", parent.display()))?;
|
||||
fs::create_dir_all(parent).map_err(|e| {
|
||||
format!(
|
||||
"create rsync object parent failed: {}: {e}",
|
||||
parent.display()
|
||||
)
|
||||
})?;
|
||||
}
|
||||
fs::write(&path, bytes)
|
||||
.map_err(|e| format!("write rsync object failed: {}: {e}", path.display()))?;
|
||||
@@ -197,8 +205,8 @@ fn materialize_rsync_module_from_store(
|
||||
fn copy_dir_all(src: &Path, dst: &Path) -> Result<(), String> {
|
||||
fs::create_dir_all(dst)
|
||||
.map_err(|e| format!("create directory failed: {}: {e}", dst.display()))?;
|
||||
for entry in fs::read_dir(src)
|
||||
.map_err(|e| format!("read directory failed: {}: {e}", src.display()))?
|
||||
for entry in
|
||||
fs::read_dir(src).map_err(|e| format!("read directory failed: {}: {e}", src.display()))?
|
||||
{
|
||||
let entry = entry.map_err(|e| format!("read entry failed: {}: {e}", src.display()))?;
|
||||
let file_type = entry
|
||||
@@ -252,8 +260,12 @@ fn keep_rsync_module(pp: &rpki::audit::PublicationPointAudit) -> Result<Option<S
|
||||
if is_failed_fetch_source(&pp.source) {
|
||||
return Ok(None);
|
||||
}
|
||||
let module_uri = canonical_rsync_module(&pp.rsync_base_uri)
|
||||
.map_err(|e| format!("canonicalize rsync module failed for {}: {e}", pp.rsync_base_uri))?;
|
||||
let module_uri = canonical_rsync_module(&pp.rsync_base_uri).map_err(|e| {
|
||||
format!(
|
||||
"canonicalize rsync module failed for {}: {e}",
|
||||
pp.rsync_base_uri
|
||||
)
|
||||
})?;
|
||||
if pp.rrdp_notification_uri.is_none() || pp.repo_sync_source.as_deref() == Some("rsync") {
|
||||
return Ok(Some(module_uri));
|
||||
}
|
||||
@@ -317,8 +329,9 @@ fn repair_base_inputs(
|
||||
for entry in fs::read_dir(&repos_dir)
|
||||
.map_err(|e| format!("scan rrdp repo dir failed: {}: {e}", repos_dir.display()))?
|
||||
{
|
||||
let entry = entry
|
||||
.map_err(|e| format!("read rrdp repo entry failed: {}: {e}", repos_dir.display()))?;
|
||||
let entry = entry.map_err(|e| {
|
||||
format!("read rrdp repo entry failed: {}: {e}", repos_dir.display())
|
||||
})?;
|
||||
let meta = entry.path().join("meta.json");
|
||||
if !meta.exists() {
|
||||
continue;
|
||||
@@ -385,13 +398,13 @@ fn repair_base_inputs(
|
||||
}
|
||||
write_json_value(locks_path, &locks)?;
|
||||
verification.base["capture"]["rrdpRepoCount"] = serde_json::Value::from(
|
||||
locks.get("rrdp")
|
||||
locks
|
||||
.get("rrdp")
|
||||
.and_then(|v| v.as_object())
|
||||
.map(|m| m.len())
|
||||
.unwrap_or(0),
|
||||
);
|
||||
verification.base["capture"]["rsyncModuleCount"] =
|
||||
serde_json::Value::from(final_modules.len());
|
||||
verification.base["capture"]["rsyncModuleCount"] = serde_json::Value::from(final_modules.len());
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -502,8 +515,9 @@ fn repair_delta_step_inputs(
|
||||
for entry in fs::read_dir(&repos_dir)
|
||||
.map_err(|e| format!("scan rrdp repo dir failed: {}: {e}", repos_dir.display()))?
|
||||
{
|
||||
let entry = entry
|
||||
.map_err(|e| format!("read rrdp repo entry failed: {}: {e}", repos_dir.display()))?;
|
||||
let entry = entry.map_err(|e| {
|
||||
format!("read rrdp repo entry failed: {}: {e}", repos_dir.display())
|
||||
})?;
|
||||
let meta = entry.path().join("meta.json");
|
||||
if !meta.exists() {
|
||||
continue;
|
||||
@@ -634,7 +648,8 @@ fn repair_delta_step_inputs(
|
||||
.and_then(|v| v.get("session"))
|
||||
.and_then(|v| v.as_str())
|
||||
.or_else(|| {
|
||||
entry.get("base")
|
||||
entry
|
||||
.get("base")
|
||||
.and_then(|v| v.get("session"))
|
||||
.and_then(|v| v.as_str())
|
||||
});
|
||||
@@ -645,7 +660,10 @@ fn repair_delta_step_inputs(
|
||||
if session_dir.exists() {
|
||||
continue;
|
||||
}
|
||||
let base_bucket_dir = base_capture_root.join("rrdp").join("repos").join(&bucket_hash);
|
||||
let base_bucket_dir = base_capture_root
|
||||
.join("rrdp")
|
||||
.join("repos")
|
||||
.join(&bucket_hash);
|
||||
let base_session_dir = base_bucket_dir.join(session);
|
||||
if !base_session_dir.exists() {
|
||||
continue;
|
||||
@@ -673,13 +691,13 @@ fn repair_delta_step_inputs(
|
||||
write_json_value(&locks_path, &locks)?;
|
||||
|
||||
step_verification["capture"]["rrdpRepoCount"] = serde_json::Value::from(
|
||||
locks.get("rrdp")
|
||||
locks
|
||||
.get("rrdp")
|
||||
.and_then(|v| v.as_object())
|
||||
.map(|m| m.len())
|
||||
.unwrap_or(0),
|
||||
);
|
||||
step_verification["capture"]["rsyncModuleCount"] =
|
||||
serde_json::Value::from(final_modules.len());
|
||||
step_verification["capture"]["rsyncModuleCount"] = serde_json::Value::from(final_modules.len());
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -694,7 +712,12 @@ fn rewrite_delta_base_hash(step_dir: &Path, previous_locks_path: &Path) -> Resul
|
||||
let locks_path = step_dir.join("locks-delta.json");
|
||||
let mut locks = load_json(&locks_path)?;
|
||||
let previous_locks = serde_json::from_slice::<serde_json::Value>(&previous_locks_bytes)
|
||||
.map_err(|e| format!("parse previous locks failed: {}: {e}", previous_locks_path.display()))?;
|
||||
.map_err(|e| {
|
||||
format!(
|
||||
"parse previous locks failed: {}: {e}",
|
||||
previous_locks_path.display()
|
||||
)
|
||||
})?;
|
||||
locks["baseLocksSha256"] = serde_json::Value::String(previous_locks_sha256.clone());
|
||||
let capture = locks
|
||||
.get("capture")
|
||||
@@ -760,17 +783,33 @@ fn real_main() -> Result<(), String> {
|
||||
let bundle_json_path = rir_dir.join("bundle.json");
|
||||
let verification_path = rir_dir.join("verification.json");
|
||||
|
||||
let mut bundle: RirBundleMetadataV2Serde = serde_json::from_slice(
|
||||
&fs::read(&bundle_json_path)
|
||||
.map_err(|e| format!("read bundle.json failed: {}: {e}", bundle_json_path.display()))?,
|
||||
)
|
||||
.map_err(|e| format!("parse bundle.json failed: {}: {e}", bundle_json_path.display()))?;
|
||||
let mut bundle: RirBundleMetadataV2Serde =
|
||||
serde_json::from_slice(&fs::read(&bundle_json_path).map_err(|e| {
|
||||
format!(
|
||||
"read bundle.json failed: {}: {e}",
|
||||
bundle_json_path.display()
|
||||
)
|
||||
})?)
|
||||
.map_err(|e| {
|
||||
format!(
|
||||
"parse bundle.json failed: {}: {e}",
|
||||
bundle_json_path.display()
|
||||
)
|
||||
})?;
|
||||
|
||||
let mut verification: VerificationV2 = serde_json::from_slice(
|
||||
&fs::read(&verification_path)
|
||||
.map_err(|e| format!("read verification.json failed: {}: {e}", verification_path.display()))?,
|
||||
)
|
||||
.map_err(|e| format!("parse verification.json failed: {}: {e}", verification_path.display()))?;
|
||||
let mut verification: VerificationV2 =
|
||||
serde_json::from_slice(&fs::read(&verification_path).map_err(|e| {
|
||||
format!(
|
||||
"read verification.json failed: {}: {e}",
|
||||
verification_path.display()
|
||||
)
|
||||
})?)
|
||||
.map_err(|e| {
|
||||
format!(
|
||||
"parse verification.json failed: {}: {e}",
|
||||
verification_path.display()
|
||||
)
|
||||
})?;
|
||||
|
||||
let tal_bytes = fs::read(rir_dir.join("tal.tal"))
|
||||
.map_err(|e| format!("read tal.tal failed: {}: {e}", rir_dir.display()))?;
|
||||
@@ -787,7 +826,8 @@ fn real_main() -> Result<(), String> {
|
||||
fs::create_dir_all(parent)
|
||||
.map_err(|e| format!("create refresh db parent failed: {}: {e}", parent.display()))?;
|
||||
}
|
||||
let store = RocksStore::open(&work_db).map_err(|e| format!("open refresh rocksdb failed: {e}"))?;
|
||||
let store =
|
||||
RocksStore::open(&work_db).map_err(|e| format!("open refresh rocksdb failed: {e}"))?;
|
||||
|
||||
let base_archive = path_join(&rir_dir, &bundle.base.relative_archive_path);
|
||||
let base_locks = path_join(&rir_dir, &bundle.base.relative_locks_path);
|
||||
@@ -823,8 +863,8 @@ fn real_main() -> Result<(), String> {
|
||||
.map_err(|e| format!("build base ccr failed: {e}"))?;
|
||||
write_ccr_file(&base_ccr, &base_ccr_content)
|
||||
.map_err(|e| format!("write base ccr failed: {}: {e}", base_ccr.display()))?;
|
||||
let base_ccr_bytes =
|
||||
fs::read(&base_ccr).map_err(|e| format!("read base ccr failed: {}: {e}", base_ccr.display()))?;
|
||||
let base_ccr_bytes = fs::read(&base_ccr)
|
||||
.map_err(|e| format!("read base ccr failed: {}: {e}", base_ccr.display()))?;
|
||||
let base_decoded =
|
||||
decode_content_info(&base_ccr_bytes).map_err(|e| format!("decode base ccr failed: {e}"))?;
|
||||
let base_verify =
|
||||
@@ -838,15 +878,18 @@ fn real_main() -> Result<(), String> {
|
||||
bundle.base.vap_count = base_vap_rows.len();
|
||||
|
||||
verification.base["ccr"]["sha256"] = serde_json::Value::String(bundle.base.ccr_sha256.clone());
|
||||
verification.base["ccr"]["stateHashesOk"] = serde_json::Value::Bool(base_verify.state_hashes_ok);
|
||||
verification.base["ccr"]["stateHashesOk"] =
|
||||
serde_json::Value::Bool(base_verify.state_hashes_ok);
|
||||
verification.base["ccr"]["manifestInstances"] =
|
||||
serde_json::Value::from(base_verify.manifest_instances);
|
||||
verification.base["ccr"]["roaVrpCount"] = serde_json::Value::from(base_vrp_rows.len());
|
||||
verification.base["ccr"]["aspaPayloadSets"] = serde_json::Value::from(base_vap_rows.len());
|
||||
verification.base["ccr"]["routerKeyCount"] =
|
||||
serde_json::Value::from(base_verify.router_key_count);
|
||||
verification.base["compareViews"]["baseVrpCount"] = serde_json::Value::from(base_vrp_rows.len());
|
||||
verification.base["compareViews"]["baseVapCount"] = serde_json::Value::from(base_vap_rows.len());
|
||||
verification.base["compareViews"]["baseVrpCount"] =
|
||||
serde_json::Value::from(base_vrp_rows.len());
|
||||
verification.base["compareViews"]["baseVapCount"] =
|
||||
serde_json::Value::from(base_vap_rows.len());
|
||||
verification.base["capture"]["selfReplayOk"] = serde_json::Value::Bool(true);
|
||||
repair_base_inputs(
|
||||
&base_archive,
|
||||
@@ -922,7 +965,8 @@ fn real_main() -> Result<(), String> {
|
||||
step_verification["ccr"]["manifestInstances"] =
|
||||
serde_json::Value::from(delta_verify.manifest_instances);
|
||||
step_verification["ccr"]["roaVrpCount"] = serde_json::Value::from(delta_vrp_rows.len());
|
||||
step_verification["ccr"]["aspaPayloadSets"] = serde_json::Value::from(delta_vap_rows.len());
|
||||
step_verification["ccr"]["aspaPayloadSets"] =
|
||||
serde_json::Value::from(delta_vap_rows.len());
|
||||
step_verification["ccr"]["routerKeyCount"] =
|
||||
serde_json::Value::from(delta_verify.router_key_count);
|
||||
step_verification["compareViews"]["vrpCount"] =
|
||||
@@ -931,28 +975,29 @@ fn real_main() -> Result<(), String> {
|
||||
serde_json::Value::from(delta_vap_rows.len());
|
||||
step_verification["selfReplayOk"] = serde_json::Value::Bool(true);
|
||||
}
|
||||
let step_verification_path = path_join(&rir_dir, &step.relative_path).join("verification.json");
|
||||
let mut step_verification_json: serde_json::Value = serde_json::from_slice(
|
||||
&fs::read(&step_verification_path).map_err(|e| {
|
||||
let step_verification_path =
|
||||
path_join(&rir_dir, &step.relative_path).join("verification.json");
|
||||
let mut step_verification_json: serde_json::Value =
|
||||
serde_json::from_slice(&fs::read(&step_verification_path).map_err(|e| {
|
||||
format!(
|
||||
"read step verification failed: {}: {e}",
|
||||
step_verification_path.display()
|
||||
)
|
||||
})?,
|
||||
)
|
||||
.map_err(|e| {
|
||||
format!(
|
||||
"parse step verification failed: {}: {e}",
|
||||
step_verification_path.display()
|
||||
)
|
||||
})?;
|
||||
})?)
|
||||
.map_err(|e| {
|
||||
format!(
|
||||
"parse step verification failed: {}: {e}",
|
||||
step_verification_path.display()
|
||||
)
|
||||
})?;
|
||||
step_verification_json["ccr"]["sha256"] =
|
||||
serde_json::Value::String(step.delta_ccr_sha256.clone());
|
||||
step_verification_json["ccr"]["stateHashesOk"] =
|
||||
serde_json::Value::Bool(delta_verify.state_hashes_ok);
|
||||
step_verification_json["ccr"]["manifestInstances"] =
|
||||
serde_json::Value::from(delta_verify.manifest_instances);
|
||||
step_verification_json["ccr"]["roaVrpCount"] = serde_json::Value::from(delta_vrp_rows.len());
|
||||
step_verification_json["ccr"]["roaVrpCount"] =
|
||||
serde_json::Value::from(delta_vrp_rows.len());
|
||||
step_verification_json["ccr"]["aspaPayloadSets"] =
|
||||
serde_json::Value::from(delta_vap_rows.len());
|
||||
step_verification_json["ccr"]["routerKeyCount"] =
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use rocksdb::{DB, IteratorMode, Options};
|
||||
use rpki::storage::{column_family_descriptors, CF_REPOSITORY_VIEW};
|
||||
use rpki::storage::{CF_REPOSITORY_VIEW, column_family_descriptors};
|
||||
use std::fs;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
|
||||
@@ -64,12 +64,9 @@ fn main() {
|
||||
println!("rule_hash={}", output.rule_hash);
|
||||
println!("validation_path_hint={:?}", output.validation_path_hint);
|
||||
|
||||
if let Some(trace) = trace_rule_to_root(
|
||||
&store,
|
||||
AuditRuleKind::Roa,
|
||||
&output.rule_hash,
|
||||
)
|
||||
.expect("trace rule")
|
||||
if let Some(trace) =
|
||||
trace_rule_to_root(&store, AuditRuleKind::Roa, &output.rule_hash)
|
||||
.expect("trace rule")
|
||||
{
|
||||
println!(
|
||||
"trace_leaf_manifest={}",
|
||||
@@ -79,11 +76,17 @@ fn main() {
|
||||
.map(|node| node.manifest_rsync_uri.as_str())
|
||||
.unwrap_or("")
|
||||
);
|
||||
println!("trace_source_object_uri={}", trace.resolved_output.source_object_uri);
|
||||
println!(
|
||||
"trace_source_object_uri={}",
|
||||
trace.resolved_output.source_object_uri
|
||||
);
|
||||
println!("trace_chain_len={}", trace.chain_leaf_to_root.len());
|
||||
for (idx, node) in trace.chain_leaf_to_root.iter().enumerate() {
|
||||
println!("chain[{idx}].manifest={}", node.manifest_rsync_uri);
|
||||
println!("chain[{idx}].current_manifest={}", node.current_manifest_rsync_uri);
|
||||
println!(
|
||||
"chain[{idx}].current_manifest={}",
|
||||
node.current_manifest_rsync_uri
|
||||
);
|
||||
println!("chain[{idx}].current_crl={}", node.current_crl_rsync_uri);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user