Harden first-release validation and dependency hygiene
This commit is contained in:
@@ -13,7 +13,11 @@ pub(crate) fn run_config(args: RunConfig) -> Result<(), String> {
|
||||
}
|
||||
policy.ta_constraints = args.ta_constraints.clone();
|
||||
for warning in policy.ta_constraints.configuration_warnings() {
|
||||
crate::logging::emit(crate::logging::Level::Warn, "constraint_warning", || serde_json::json!({"reason": warning}));
|
||||
crate::logging::emit(
|
||||
crate::logging::Level::Warn,
|
||||
"constraint_warning",
|
||||
|| serde_json::json!({"reason": warning}),
|
||||
);
|
||||
}
|
||||
let validation_time = args
|
||||
.validation_time
|
||||
@@ -45,8 +49,7 @@ pub(crate) fn run_config(args: RunConfig) -> Result<(), String> {
|
||||
let config = TreeRunConfig {
|
||||
max_depth: Some(args.max_ca_depth),
|
||||
max_instances: args.max_instances,
|
||||
compact_audit: args.skip_report_build
|
||||
&& args.report_json_path.is_none(),
|
||||
compact_audit: args.skip_report_build && args.report_json_path.is_none(),
|
||||
build_ccr_accumulator: args.ccr_out_path.is_some(),
|
||||
};
|
||||
|
||||
@@ -66,7 +69,7 @@ pub(crate) fn run_config(args: RunConfig) -> Result<(), String> {
|
||||
let fmt = time::format_description::parse_borrowed::<2>(
|
||||
"[year][month][day]T[hour][minute][second]Z",
|
||||
)
|
||||
.map_err(|e| format!("format description parse failed: {e}"))?;
|
||||
.map_err(|e| format!("format description parse failed: {e}"))?;
|
||||
time::OffsetDateTime::now_utc()
|
||||
.format(&fmt)
|
||||
.map_err(|e| format!("format timestamp failed: {e}"))?
|
||||
@@ -157,7 +160,11 @@ pub(crate) fn run_config(args: RunConfig) -> Result<(), String> {
|
||||
};
|
||||
|
||||
let validation_ms = validation_started.elapsed().as_millis() as u64;
|
||||
crate::logging::emit(crate::logging::Level::Info, "validation_phase_completed", || serde_json::json!({"elapsed_ms": validation_ms}));
|
||||
crate::logging::emit(
|
||||
crate::logging::Level::Info,
|
||||
"validation_phase_completed",
|
||||
|| serde_json::json!({"elapsed_ms": validation_ms}),
|
||||
);
|
||||
let shared = PostValidationShared::from_run_output(out);
|
||||
record_memory_checkpoint(
|
||||
&mut memory_checkpoints,
|
||||
@@ -222,56 +229,50 @@ pub(crate) fn run_config(args: RunConfig) -> Result<(), String> {
|
||||
.compare_view_trust_anchor
|
||||
.as_deref()
|
||||
.unwrap_or("unknown");
|
||||
let (report_result, ccr_result, compare_view_result) =
|
||||
std::thread::scope(|scope| {
|
||||
// Reborrow `shared` as a plain reference so the scoped output tasks
|
||||
// capture the reference instead of moving fields out of the owned value.
|
||||
let shared = &shared;
|
||||
let report_handle = if args.skip_report_build {
|
||||
None
|
||||
} else {
|
||||
Some(scope.spawn(|| {
|
||||
run_report_task(
|
||||
&policy,
|
||||
validation_time,
|
||||
shared,
|
||||
args.report_json_path.as_deref(),
|
||||
report_json_format,
|
||||
)
|
||||
}))
|
||||
};
|
||||
let ccr_handle = scope.spawn(|| {
|
||||
run_ccr_task(
|
||||
let (report_result, ccr_result, compare_view_result) = std::thread::scope(|scope| {
|
||||
// Reborrow `shared` as a plain reference so the scoped output tasks
|
||||
// capture the reference instead of moving fields out of the owned value.
|
||||
let shared = &shared;
|
||||
let report_handle = if args.skip_report_build {
|
||||
None
|
||||
} else {
|
||||
Some(scope.spawn(|| {
|
||||
run_report_task(
|
||||
&policy,
|
||||
validation_time,
|
||||
shared,
|
||||
args.ccr_out_path.as_deref(),
|
||||
ccr_produced_at,
|
||||
args.report_json_path.as_deref(),
|
||||
report_json_format,
|
||||
)
|
||||
});
|
||||
let compare_view_handle = scope.spawn(|| {
|
||||
run_compare_view_task(
|
||||
shared,
|
||||
args.vrps_csv_out_path.as_deref(),
|
||||
args.vaps_csv_out_path.as_deref(),
|
||||
compare_view_trust_anchor,
|
||||
)
|
||||
});
|
||||
let report_result = match report_handle {
|
||||
Some(handle) => handle
|
||||
.join()
|
||||
.map_err(|_| "report task panicked".to_string())
|
||||
.and_then(|result| result),
|
||||
None => Ok(ReportTaskOutput::skipped()),
|
||||
};
|
||||
let ccr_result = ccr_handle
|
||||
.join()
|
||||
.map_err(|_| "ccr task panicked".to_string())
|
||||
.and_then(|result| result);
|
||||
let compare_view_result = compare_view_handle
|
||||
.join()
|
||||
.map_err(|_| "compare view task panicked".to_string())
|
||||
.and_then(|result| result);
|
||||
(report_result, ccr_result, compare_view_result)
|
||||
}))
|
||||
};
|
||||
let ccr_handle =
|
||||
scope.spawn(|| run_ccr_task(shared, args.ccr_out_path.as_deref(), ccr_produced_at));
|
||||
let compare_view_handle = scope.spawn(|| {
|
||||
run_compare_view_task(
|
||||
shared,
|
||||
args.vrps_csv_out_path.as_deref(),
|
||||
args.vaps_csv_out_path.as_deref(),
|
||||
compare_view_trust_anchor,
|
||||
)
|
||||
});
|
||||
let report_result = match report_handle {
|
||||
Some(handle) => handle
|
||||
.join()
|
||||
.map_err(|_| "report task panicked".to_string())
|
||||
.and_then(|result| result),
|
||||
None => Ok(ReportTaskOutput::skipped()),
|
||||
};
|
||||
let ccr_result = ccr_handle
|
||||
.join()
|
||||
.map_err(|_| "ccr task panicked".to_string())
|
||||
.and_then(|result| result);
|
||||
let compare_view_result = compare_view_handle
|
||||
.join()
|
||||
.map_err(|_| "compare view task panicked".to_string())
|
||||
.and_then(|result| result);
|
||||
(report_result, ccr_result, compare_view_result)
|
||||
});
|
||||
let report_output = report_result?;
|
||||
let ccr_output = ccr_result?;
|
||||
let compare_view_output = compare_view_result?;
|
||||
@@ -374,9 +375,7 @@ pub(crate) fn run_config(args: RunConfig) -> Result<(), String> {
|
||||
// the transport/validation stages rather than by the compact publication
|
||||
// point audit, so the final summary can use those authoritative counts.
|
||||
if let Some(path) = args.summary_out_path.as_deref() {
|
||||
let analysis_counts = timing
|
||||
.as_ref()
|
||||
.map(|(_, handle)| handle.counts_snapshot());
|
||||
let analysis_counts = timing.as_ref().map(|(_, handle)| handle.counts_snapshot());
|
||||
write_summary(
|
||||
path,
|
||||
&shared,
|
||||
@@ -458,9 +457,7 @@ fn write_summary(
|
||||
summary.synchronized_objects += point.objects.len();
|
||||
match point.repo_sync_phase.as_deref() {
|
||||
Some(phase) if phase.contains("fallback") => summary.rrdp_snapshot_fallbacks += 1,
|
||||
Some(phase) if phase.contains("snapshot") => {
|
||||
summary.rrdp_snapshot_repositories += 1
|
||||
}
|
||||
Some(phase) if phase.contains("snapshot") => summary.rrdp_snapshot_repositories += 1,
|
||||
Some(phase) if phase.contains("delta") => summary.rrdp_delta_repositories += 1,
|
||||
Some(phase) if phase.contains("noop") => summary.rrdp_noop_repositories += 1,
|
||||
_ => {}
|
||||
@@ -469,13 +466,25 @@ fn write_summary(
|
||||
let accepted = object.result == AuditObjectResult::Ok;
|
||||
match &object.kind {
|
||||
AuditObjectKind::Manifest => {
|
||||
if accepted { summary.validated_manifests += 1; } else { summary.rejected_manifests += 1; }
|
||||
if accepted {
|
||||
summary.validated_manifests += 1;
|
||||
} else {
|
||||
summary.rejected_manifests += 1;
|
||||
}
|
||||
}
|
||||
AuditObjectKind::Crl => {
|
||||
if accepted { summary.validated_crls += 1; } else { summary.rejected_crls += 1; }
|
||||
if accepted {
|
||||
summary.validated_crls += 1;
|
||||
} else {
|
||||
summary.rejected_crls += 1;
|
||||
}
|
||||
}
|
||||
AuditObjectKind::Roa => {
|
||||
if accepted { summary.validated_roas += 1; } else { summary.rejected_roas += 1; }
|
||||
if accepted {
|
||||
summary.validated_roas += 1;
|
||||
} else {
|
||||
summary.rejected_roas += 1;
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
@@ -522,15 +531,17 @@ fn write_summary(
|
||||
.and_then(|counts| {
|
||||
let snapshot = counts.get("rrdp_snapshot_objects_applied_total").copied();
|
||||
let delta = counts.get("rrdp_delta_ops_applied_total").copied();
|
||||
snapshot.zip(delta).map(|(snapshot, delta)| snapshot + delta)
|
||||
snapshot
|
||||
.zip(delta)
|
||||
.map(|(snapshot, delta)| snapshot + delta)
|
||||
})
|
||||
.unwrap_or_else(|| {
|
||||
shared
|
||||
.download_stats
|
||||
.by_kind
|
||||
.values()
|
||||
.filter_map(|stats| stats.objects_count_total)
|
||||
.sum()
|
||||
.download_stats
|
||||
.by_kind
|
||||
.values()
|
||||
.filter_map(|stats| stats.objects_count_total)
|
||||
.sum()
|
||||
});
|
||||
if downloaded_objects > 0 {
|
||||
summary.synchronized_objects = downloaded_objects as usize;
|
||||
@@ -538,8 +549,12 @@ fn write_summary(
|
||||
summary.synchronized_repositories = notification_uris.len();
|
||||
|
||||
if let Some(parent) = path.parent() {
|
||||
std::fs::create_dir_all(parent)
|
||||
.map_err(|error| format!("create Panda RPKI summary parent {}: {error}", parent.display()))?;
|
||||
std::fs::create_dir_all(parent).map_err(|error| {
|
||||
format!(
|
||||
"create Panda RPKI summary parent {}: {error}",
|
||||
parent.display()
|
||||
)
|
||||
})?;
|
||||
}
|
||||
let bytes = serde_json::to_vec_pretty(&summary)
|
||||
.map_err(|error| format!("serialize Panda RPKI summary: {error}"))?;
|
||||
|
||||
Reference in New Issue
Block a user