20260324_2 增加ccr & router key support
This commit is contained in:
59
src/bin/ccr_dump.rs
Normal file
59
src/bin/ccr_dump.rs
Normal file
@@ -0,0 +1,59 @@
|
||||
use rpki::ccr::dump::dump_content_info_json_value;
|
||||
|
||||
#[derive(Debug, Default, PartialEq, Eq)]
|
||||
struct Args {
|
||||
ccr_path: Option<std::path::PathBuf>,
|
||||
}
|
||||
|
||||
fn usage() -> &'static str {
|
||||
"Usage: ccr_dump --ccr <path>"
|
||||
}
|
||||
|
||||
fn parse_args(argv: &[String]) -> Result<Args, String> {
|
||||
let mut args = Args::default();
|
||||
let mut i = 1usize;
|
||||
while i < argv.len() {
|
||||
match argv[i].as_str() {
|
||||
"--help" | "-h" => return Err(usage().to_string()),
|
||||
"--ccr" => {
|
||||
i += 1;
|
||||
let v = argv.get(i).ok_or("--ccr requires a value")?;
|
||||
args.ccr_path = Some(v.into());
|
||||
}
|
||||
other => return Err(format!("unknown argument: {other}\n{}", usage())),
|
||||
}
|
||||
i += 1;
|
||||
}
|
||||
if args.ccr_path.is_none() {
|
||||
return Err(format!("--ccr is required\n{}", usage()));
|
||||
}
|
||||
Ok(args)
|
||||
}
|
||||
|
||||
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 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())?);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn parse_args_accepts_ccr_path() {
|
||||
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")));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_args_rejects_missing_required_ccr() {
|
||||
let argv = vec!["ccr_dump".to_string()];
|
||||
let err = parse_args(&argv).unwrap_err();
|
||||
assert!(err.contains("--ccr is required"), "{err}");
|
||||
}
|
||||
}
|
||||
109
src/bin/ccr_to_routinator_csv.rs
Normal file
109
src/bin/ccr_to_routinator_csv.rs
Normal file
@@ -0,0 +1,109 @@
|
||||
use rpki::ccr::{decode_content_info, extract_vrp_rows};
|
||||
use std::io::Write;
|
||||
|
||||
#[derive(Default, Debug)]
|
||||
struct Args {
|
||||
ccr_path: Option<std::path::PathBuf>,
|
||||
out_path: Option<std::path::PathBuf>,
|
||||
trust_anchor: String,
|
||||
}
|
||||
|
||||
fn usage() -> &'static str {
|
||||
"Usage: ccr_to_routinator_csv --ccr <path> --out <path> [--trust-anchor <name>]"
|
||||
}
|
||||
|
||||
fn parse_args(argv: &[String]) -> Result<Args, String> {
|
||||
let mut args = Args {
|
||||
trust_anchor: "unknown".to_string(),
|
||||
..Args::default()
|
||||
};
|
||||
let mut i = 1usize;
|
||||
while i < argv.len() {
|
||||
match argv[i].as_str() {
|
||||
"--ccr" => {
|
||||
i += 1;
|
||||
let v = argv.get(i).ok_or("--ccr requires a value")?;
|
||||
args.ccr_path = Some(v.into());
|
||||
}
|
||||
"--out" => {
|
||||
i += 1;
|
||||
let v = argv.get(i).ok_or("--out requires a value")?;
|
||||
args.out_path = Some(v.into());
|
||||
}
|
||||
"--trust-anchor" => {
|
||||
i += 1;
|
||||
let v = argv.get(i).ok_or("--trust-anchor requires a value")?;
|
||||
args.trust_anchor = v.clone();
|
||||
}
|
||||
"-h" | "--help" => return Err(usage().to_string()),
|
||||
other => return Err(format!("unknown argument: {other}\n{}", usage())),
|
||||
}
|
||||
i += 1;
|
||||
}
|
||||
if args.ccr_path.is_none() {
|
||||
return Err(format!("--ccr is required\n{}", usage()));
|
||||
}
|
||||
if args.out_path.is_none() {
|
||||
return Err(format!("--out is required\n{}", usage()));
|
||||
}
|
||||
Ok(args)
|
||||
}
|
||||
|
||||
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())
|
||||
}
|
||||
|
||||
fn main() -> Result<(), String> {
|
||||
let argv: Vec<String> = std::env::args().collect();
|
||||
let args = parse_args(&argv)?;
|
||||
let ccr_path = args.ccr_path.as_ref().unwrap();
|
||||
let out_path = args.out_path.as_ref().unwrap();
|
||||
let bytes = std::fs::read(ccr_path)
|
||||
.map_err(|e| format!("read ccr failed: {}: {e}", ccr_path.display()))?;
|
||||
let rows = collect_vrp_rows(&bytes)?;
|
||||
if let Some(parent) = out_path.parent() {
|
||||
std::fs::create_dir_all(parent)
|
||||
.map_err(|e| format!("create parent dirs failed: {}: {e}", parent.display()))?;
|
||||
}
|
||||
let mut file = std::io::BufWriter::new(
|
||||
std::fs::File::create(out_path)
|
||||
.map_err(|e| format!("create output failed: {}: {e}", out_path.display()))?,
|
||||
);
|
||||
writeln!(file, "ASN,IP Prefix,Max Length,Trust Anchor").map_err(|e| e.to_string())?;
|
||||
for (asn, prefix, max_len) in rows {
|
||||
writeln!(file, "AS{asn},{prefix},{max_len},{}", args.trust_anchor)
|
||||
.map_err(|e| e.to_string())?;
|
||||
}
|
||||
println!("{}", out_path.display());
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn parse_args_accepts_required_flags() {
|
||||
let argv = vec![
|
||||
"ccr_to_routinator_csv".to_string(),
|
||||
"--ccr".to_string(),
|
||||
"a.ccr".to_string(),
|
||||
"--out".to_string(),
|
||||
"out.csv".to_string(),
|
||||
"--trust-anchor".to_string(),
|
||||
"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.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 err = parse_args(&argv).unwrap_err();
|
||||
assert!(err.contains("--out is required"), "{err}");
|
||||
}
|
||||
}
|
||||
88
src/bin/ccr_verify.rs
Normal file
88
src/bin/ccr_verify.rs
Normal file
@@ -0,0 +1,88 @@
|
||||
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 {
|
||||
ccr_path: Option<std::path::PathBuf>,
|
||||
report_json: Option<std::path::PathBuf>,
|
||||
db_path: Option<std::path::PathBuf>,
|
||||
}
|
||||
|
||||
fn usage() -> &'static str {
|
||||
"Usage: ccr_verify --ccr <path> [--report-json <path>] [--db <path>]"
|
||||
}
|
||||
|
||||
fn parse_args(argv: &[String]) -> Result<Args, String> {
|
||||
let mut args = Args::default();
|
||||
let mut i = 1usize;
|
||||
while i < argv.len() {
|
||||
match argv[i].as_str() {
|
||||
"--help" | "-h" => return Err(usage().to_string()),
|
||||
"--ccr" => {
|
||||
i += 1;
|
||||
let v = argv.get(i).ok_or("--ccr requires a value")?;
|
||||
args.ccr_path = Some(v.into());
|
||||
}
|
||||
"--report-json" => {
|
||||
i += 1;
|
||||
let v = argv.get(i).ok_or("--report-json requires a value")?;
|
||||
args.report_json = Some(v.into());
|
||||
}
|
||||
"--db" => {
|
||||
i += 1;
|
||||
let v = argv.get(i).ok_or("--db requires a value")?;
|
||||
args.db_path = Some(v.into());
|
||||
}
|
||||
other => return Err(format!("unknown argument: {other}\n{}", usage())),
|
||||
}
|
||||
i += 1;
|
||||
}
|
||||
if args.ccr_path.is_none() {
|
||||
return Err(format!("--ccr is required\n{}", usage()));
|
||||
}
|
||||
Ok(args)
|
||||
}
|
||||
|
||||
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 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() {
|
||||
verify_against_report_json_path(&ci, report_json).map_err(|e| e.to_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())?);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn parse_args_accepts_all_flags() {
|
||||
let argv = vec![
|
||||
"ccr_verify".to_string(),
|
||||
"--ccr".to_string(),
|
||||
"a.ccr".to_string(),
|
||||
"--report-json".to_string(),
|
||||
"report.json".to_string(),
|
||||
"--db".to_string(),
|
||||
"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.db_path.as_deref(), Some(std::path::Path::new("db")));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_args_rejects_missing_required_ccr() {
|
||||
let argv = vec!["ccr_verify".to_string()];
|
||||
let err = parse_args(&argv).unwrap_err();
|
||||
assert!(err.contains("--ccr is required"), "{err}");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user