20261015_4 修复Manifest编号与改名抗重放校验
Some checks failed
ci / rust (push) Failing after 17s
ci / docker (push) Failing after 1m12s
ci / audit (push) Failing after 8s

This commit is contained in:
2026-10-16 11:16:20 +08:00
parent 385af349ae
commit 5f46837b61
34 changed files with 1346 additions and 149 deletions

View File

@@ -27,10 +27,45 @@ impl<'a> Rpkiv1PublicationPointRunner<'a> {
let snapshot_prepare_started = std::time::Instant::now();
let issuer_ca_der = ca_certificate_der_for_validation(ca, self.store, self.timing.as_ref())
.map_err(|detail| FreshPublicationPointStageError {
warnings: Vec::new(),
error: ManifestFreshError::IssuerCaLoadFailed { detail },
snapshot_prepare_ms: snapshot_prepare_started.elapsed().as_millis() as u64,
})?;
let issuer_ca_der: Arc<[u8]> = Arc::from(issuer_ca_der.as_ref());
let identity = ResourceCertificate::decode_der(&issuer_ca_der)
.map(|cert| {
crate::repository::storage::CaIdentity::from_spki(
ca.anchor_namespace,
&cert.tbs.subject_public_key_info,
)
})
.map_err(|e| FreshPublicationPointStageError {
warnings: Vec::new(),
error: ManifestFreshError::IssuerCaLoadFailed {
detail: e.to_string(),
},
snapshot_prepare_ms: snapshot_prepare_started.elapsed().as_millis() as u64,
})?;
let rename_warnings: Vec<Warning> = crate::validation::manifest::manifest_rename_warning(
self.store,
&identity,
&ca.manifest_sia_uris,
&ca.manifest_rsync_uri,
)
.map_err(|error| FreshPublicationPointStageError {
warnings: Vec::new(),
error,
snapshot_prepare_ms: snapshot_prepare_started.elapsed().as_millis() as u64,
})?
.into_iter()
.collect();
for warning in &rename_warnings {
crate::logging::emit(
crate::logging::Level::Warn,
"manifest_filename_changed",
|| serde_json::json!({"manifest_rsync_uri": ca.manifest_rsync_uri, "message": warning.message, "candidate_accepted": null}),
);
}
let fresh_publication_point = {
let _manifest_total = self
.timing
@@ -38,6 +73,7 @@ impl<'a> Rpkiv1PublicationPointRunner<'a> {
.map(|t| t.span_phase("manifest_processing_total"));
process_manifest_publication_point_fresh_after_repo_sync_with_timing(
self.store,
&ca.anchor_namespace,
&ca.manifest_rsync_uri,
&ca.publication_point_rsync_uri,
self.current_repo_index.as_ref(),
@@ -51,6 +87,16 @@ impl<'a> Rpkiv1PublicationPointRunner<'a> {
let snapshot_prepare_ms = snapshot_prepare_started.elapsed().as_millis() as u64;
let (fresh_point, snapshot_prepare_timing) =
fresh_publication_point.map_err(|error| FreshPublicationPointStageError {
warnings: rename_warnings
.iter()
.cloned()
.map(|mut warning| {
warning
.message
.push_str(&format!(" candidate_accepted=false reason={error}"));
warning
})
.collect(),
error,
snapshot_prepare_ms,
})?;
@@ -152,7 +198,7 @@ impl<'a> Rpkiv1PublicationPointRunner<'a> {
self.policy,
)
};
let (discovered_children, child_audits, discovered_router_keys, warnings) = match out {
let (discovered_children, child_audits, discovered_router_keys, mut warnings) = match out {
Ok(out) => (out.children, out.audits, out.router_keys, Vec::new()),
Err(e) => (
Vec::new(),
@@ -188,6 +234,7 @@ impl<'a> Rpkiv1PublicationPointRunner<'a> {
child_discovery_ms,
);
warnings.extend(rename_warnings);
Ok(FreshPublicationPointStage {
fresh_point,
issuer_ca_der,
@@ -205,7 +252,7 @@ impl<'a> Rpkiv1PublicationPointRunner<'a> {
&self,
ca: &CaInstanceHandle,
fresh_point: &FreshValidatedPublicationPoint,
warnings: Vec<Warning>,
mut warnings: Vec<Warning>,
objects: crate::validation::objects::ObjectsOutput,
child_audits: Vec<ObjectAuditEntry>,
discovered_children: Vec<DiscoveredChildCaInstance>,
@@ -229,6 +276,7 @@ impl<'a> Rpkiv1PublicationPointRunner<'a> {
snapshot_pack_ms,
);
let mut ccr_projection = None;
let mut ccr_projection_build_ms = 0;
let mut ccr_append_ms = 0;
if self.ccr_accumulator.is_some() {
@@ -254,9 +302,30 @@ impl<'a> Rpkiv1PublicationPointRunner<'a> {
let ccr_manifest_projection =
crate::ccr::projection::from_snapshot(ca, &pack, subordinate_skis)?;
ccr_projection_build_ms = ccr_projection_build_started.elapsed().as_millis() as u64;
let ccr_append_started = std::time::Instant::now();
self.append_ccr_manifest_projection(&ccr_manifest_projection)?;
ccr_append_ms = ccr_append_started.elapsed().as_millis() as u64;
ccr_projection = Some(ccr_manifest_projection);
}
let (_, commit_warning) = crate::validation::manifest::commit_manifest_history(
self.store,
&fresh_point.history_candidate,
)
.map_err(|error| format!("persist manifest freshness failed: {error}"))?;
if let Some(warning) = commit_warning {
warnings.retain(|item| !item.message.starts_with("manifest filename changed:"));
warnings.push(warning);
}
for warning in &mut warnings {
if warning.message.starts_with("manifest filename changed:") {
warning.message.push_str(&format!(
" new_number={} new_this_update={} candidate_accepted=true",
hex::encode_upper(&pack.manifest_number_be),
pack.this_update.rfc3339_utc
));
}
}
if let Some(projection) = ccr_projection {
let started = std::time::Instant::now();
self.append_ccr_manifest_projection(&projection)?;
ccr_append_ms = started.elapsed().as_millis() as u64;
}
if let Some(timing) = self.timing.as_ref() {
timing.record_phase_nanos(
@@ -305,21 +374,6 @@ impl<'a> Rpkiv1PublicationPointRunner<'a> {
audit_build_ms,
);
// Commit protocol freshness only after successful publication-point
// validation/finalization, independently of optional CCR output.
self.store
.put_manifest_anti_rollback_meta(
&crate::repository::storage::ManifestAntiRollbackMeta {
manifest_rsync_uri: pack.manifest_rsync_uri.clone(),
manifest_number_be: pack.manifest_number_be.clone(),
manifest_this_update: pack.this_update.clone(),
manifest_sha256: <sha2::Sha256 as sha2::Digest>::digest(&pack.manifest_bytes)
.to_vec(),
updated_at_validation_time: pack.verified_at.clone(),
},
)
.map_err(|error| format!("persist manifest freshness failed: {error}"))?;
Ok(FreshPublicationPointFinalizeOutput {
result: PublicationPointRunResult {
source: PublicationPointSource::Fresh,