20260727 修复缓存回放丢失reject reason(#132):缓存artifact增加reject_reason字段,fresh验证记录真实原因,VCIR/PP cache回放还原,旧缓存给后备文案
This commit is contained in:
@@ -708,6 +708,7 @@ fn sample_vcir_for_projection(
|
||||
sha256: manifest_hash,
|
||||
object_type: Some("mft".to_string()),
|
||||
validation_status: VcirArtifactValidationStatus::Accepted,
|
||||
reject_reason: None,
|
||||
},
|
||||
VcirRelatedArtifact {
|
||||
artifact_role: VcirArtifactRole::CurrentCrl,
|
||||
@@ -716,6 +717,7 @@ fn sample_vcir_for_projection(
|
||||
sha256: current_crl_hash,
|
||||
object_type: Some("crl".to_string()),
|
||||
validation_status: VcirArtifactValidationStatus::Accepted,
|
||||
reject_reason: None,
|
||||
},
|
||||
VcirRelatedArtifact {
|
||||
artifact_role: VcirArtifactRole::ChildCaCert,
|
||||
@@ -724,6 +726,7 @@ fn sample_vcir_for_projection(
|
||||
sha256: child_cert_hash.to_string(),
|
||||
object_type: Some("cer".to_string()),
|
||||
validation_status: VcirArtifactValidationStatus::Accepted,
|
||||
reject_reason: None,
|
||||
},
|
||||
VcirRelatedArtifact {
|
||||
artifact_role: VcirArtifactRole::SignedObject,
|
||||
@@ -732,6 +735,7 @@ fn sample_vcir_for_projection(
|
||||
sha256: roa_hash,
|
||||
object_type: Some("roa".to_string()),
|
||||
validation_status: VcirArtifactValidationStatus::Accepted,
|
||||
reject_reason: None,
|
||||
},
|
||||
VcirRelatedArtifact {
|
||||
artifact_role: VcirArtifactRole::SignedObject,
|
||||
@@ -740,6 +744,7 @@ fn sample_vcir_for_projection(
|
||||
sha256: aspa_hash,
|
||||
object_type: Some("aspa".to_string()),
|
||||
validation_status: VcirArtifactValidationStatus::Accepted,
|
||||
reject_reason: None,
|
||||
},
|
||||
],
|
||||
summary: VcirSummary {
|
||||
@@ -1455,10 +1460,12 @@ fn build_vcir_related_artifacts_classifies_snapshot_files_and_audit_statuses() {
|
||||
&& artifact.artifact_role == VcirArtifactRole::ChildCaCert));
|
||||
assert!(artifacts.iter().any(|artifact| artifact.uri.as_deref()
|
||||
== Some("rsync://example.test/repo/issuer/a.roa")
|
||||
&& artifact.validation_status == VcirArtifactValidationStatus::Rejected));
|
||||
&& artifact.validation_status == VcirArtifactValidationStatus::Rejected
|
||||
&& artifact.reject_reason.as_deref() == Some("bad roa")));
|
||||
assert!(artifacts.iter().any(|artifact| artifact.uri.as_deref()
|
||||
== Some("rsync://example.test/repo/issuer/a.asa")
|
||||
&& artifact.validation_status == VcirArtifactValidationStatus::WarningOnly));
|
||||
&& artifact.validation_status == VcirArtifactValidationStatus::WarningOnly
|
||||
&& artifact.reject_reason.is_none()));
|
||||
assert!(artifacts.iter().any(|artifact| artifact.uri.as_deref()
|
||||
== Some("rsync://example.test/repo/issuer/a.gbr")
|
||||
&& artifact.artifact_kind == VcirArtifactKind::Gbr));
|
||||
@@ -4510,6 +4517,7 @@ fn build_objects_output_from_vcir_tracks_expired_and_invalid_cached_outputs() {
|
||||
.to_string(),
|
||||
),
|
||||
validation_status: VcirArtifactValidationStatus::Accepted,
|
||||
reject_reason: None,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -4732,6 +4740,173 @@ fn build_publication_point_audit_from_vcir_uses_vcir_metadata_and_overlays_child
|
||||
}));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn build_publication_point_audit_from_vcir_restores_reject_reason_with_legacy_fallback() {
|
||||
let now = time::OffsetDateTime::now_utc();
|
||||
let child_cert_hash = sha256_hex(b"child-cert");
|
||||
let mut vcir = sample_vcir_for_projection(now, &child_cert_hash);
|
||||
vcir.related_artifacts.push(VcirRelatedArtifact {
|
||||
artifact_role: VcirArtifactRole::SignedObject,
|
||||
artifact_kind: VcirArtifactKind::Roa,
|
||||
uri: Some("rsync://example.test/repo/issuer/rejected-with-reason.roa".to_string()),
|
||||
sha256: sha256_hex(b"rejected-with-reason"),
|
||||
object_type: Some("roa".to_string()),
|
||||
validation_status: VcirArtifactValidationStatus::Rejected,
|
||||
reject_reason: Some("EE certificate path validation failed: test".to_string()),
|
||||
});
|
||||
vcir.related_artifacts.push(VcirRelatedArtifact {
|
||||
artifact_role: VcirArtifactRole::SignedObject,
|
||||
artifact_kind: VcirArtifactKind::Roa,
|
||||
uri: Some("rsync://example.test/repo/issuer/rejected-legacy.roa".to_string()),
|
||||
sha256: sha256_hex(b"rejected-legacy"),
|
||||
object_type: Some("roa".to_string()),
|
||||
validation_status: VcirArtifactValidationStatus::Rejected,
|
||||
reject_reason: None,
|
||||
});
|
||||
|
||||
let ca = CaInstanceHandle {
|
||||
depth: 0,
|
||||
tal_id: "test-tal".to_string(),
|
||||
parent_manifest_rsync_uri: None,
|
||||
ca_certificate: CaCertificateRef::inline_der(Vec::new()),
|
||||
ca_certificate_rsync_uri: None,
|
||||
effective_ip_resources: None,
|
||||
effective_as_resources: None,
|
||||
rsync_base_uri: "rsync://example.test/repo/issuer/".to_string(),
|
||||
manifest_rsync_uri: vcir.manifest_rsync_uri.clone(),
|
||||
publication_point_rsync_uri: "rsync://example.test/repo/issuer/".to_string(),
|
||||
rrdp_notification_uri: None,
|
||||
};
|
||||
let objects = crate::validation::objects::ObjectsOutput {
|
||||
vrps: Vec::new(),
|
||||
aspas: Vec::new(),
|
||||
router_keys: Vec::new(),
|
||||
local_outputs_cache: Vec::new(),
|
||||
warnings: Vec::new(),
|
||||
stats: crate::validation::objects::ObjectsStats::default(),
|
||||
audit: Vec::new(),
|
||||
roa_cache_stats: crate::validation::objects::RoaValidationCacheStats::default(),
|
||||
roa_cache_object_meta: Vec::new(),
|
||||
};
|
||||
|
||||
let audit = build_publication_point_audit_from_vcir(
|
||||
&ca,
|
||||
PublicationPointSource::VcirCurrentInstance,
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
Some(&vcir),
|
||||
None,
|
||||
&[],
|
||||
&objects,
|
||||
&[],
|
||||
&[],
|
||||
);
|
||||
|
||||
assert!(audit.objects.iter().any(|entry| {
|
||||
entry.rsync_uri == "rsync://example.test/repo/issuer/rejected-with-reason.roa"
|
||||
&& matches!(entry.result, AuditObjectResult::Error)
|
||||
&& entry.detail.as_deref()
|
||||
== Some("EE certificate path validation failed: test")
|
||||
}));
|
||||
assert!(audit.objects.iter().any(|entry| {
|
||||
entry.rsync_uri == "rsync://example.test/repo/issuer/rejected-legacy.roa"
|
||||
&& matches!(entry.result, AuditObjectResult::Error)
|
||||
&& entry.detail.as_deref() == Some(CACHED_REJECT_REASON_NOT_RECORDED)
|
||||
}));
|
||||
assert!(audit.objects.iter().all(|entry| {
|
||||
!matches!(entry.result, AuditObjectResult::Ok) || entry.detail.is_none()
|
||||
}));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn build_publication_point_audit_from_pp_cache_projection_restores_reject_reason() {
|
||||
let now = time::OffsetDateTime::now_utc();
|
||||
let child_cert_hash = sha256_hex(b"child-cert");
|
||||
let mut vcir = sample_vcir_for_projection(now, &child_cert_hash);
|
||||
vcir.related_artifacts.push(VcirRelatedArtifact {
|
||||
artifact_role: VcirArtifactRole::SignedObject,
|
||||
artifact_kind: VcirArtifactKind::Roa,
|
||||
uri: Some("rsync://example.test/repo/issuer/rejected-with-reason.roa".to_string()),
|
||||
sha256: sha256_hex(b"rejected-with-reason"),
|
||||
object_type: Some("roa".to_string()),
|
||||
validation_status: VcirArtifactValidationStatus::Rejected,
|
||||
reject_reason: Some("EE certificate path validation failed: test".to_string()),
|
||||
});
|
||||
vcir.related_artifacts.push(VcirRelatedArtifact {
|
||||
artifact_role: VcirArtifactRole::SignedObject,
|
||||
artifact_kind: VcirArtifactKind::Roa,
|
||||
uri: Some("rsync://example.test/repo/issuer/rejected-legacy.roa".to_string()),
|
||||
sha256: sha256_hex(b"rejected-legacy"),
|
||||
object_type: Some("roa".to_string()),
|
||||
validation_status: VcirArtifactValidationStatus::Rejected,
|
||||
reject_reason: None,
|
||||
});
|
||||
let projection = PublicationPointCacheProjection::from_vcir_with_context(
|
||||
&vcir,
|
||||
"rsync://example.test/repo/issuer/".to_string(),
|
||||
None,
|
||||
[0x11; 32],
|
||||
[0x22; 32],
|
||||
[0x33; 32],
|
||||
[0x44; 32],
|
||||
[0x55; 32],
|
||||
)
|
||||
.expect("build publication point projection");
|
||||
|
||||
let ca = CaInstanceHandle {
|
||||
depth: 0,
|
||||
tal_id: "test-tal".to_string(),
|
||||
parent_manifest_rsync_uri: None,
|
||||
ca_certificate: CaCertificateRef::inline_der(Vec::new()),
|
||||
ca_certificate_rsync_uri: None,
|
||||
effective_ip_resources: None,
|
||||
effective_as_resources: None,
|
||||
rsync_base_uri: "rsync://example.test/repo/issuer/".to_string(),
|
||||
manifest_rsync_uri: vcir.manifest_rsync_uri.clone(),
|
||||
publication_point_rsync_uri: "rsync://example.test/repo/issuer/".to_string(),
|
||||
rrdp_notification_uri: None,
|
||||
};
|
||||
let objects = crate::validation::objects::ObjectsOutput {
|
||||
vrps: Vec::new(),
|
||||
aspas: Vec::new(),
|
||||
router_keys: Vec::new(),
|
||||
local_outputs_cache: Vec::new(),
|
||||
warnings: Vec::new(),
|
||||
stats: crate::validation::objects::ObjectsStats::default(),
|
||||
audit: Vec::new(),
|
||||
roa_cache_stats: crate::validation::objects::RoaValidationCacheStats::default(),
|
||||
roa_cache_object_meta: Vec::new(),
|
||||
};
|
||||
|
||||
let audit = build_publication_point_audit_from_publication_point_cache_projection(
|
||||
&ca,
|
||||
PublicationPointSource::PublicationPointCache,
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
&projection,
|
||||
now,
|
||||
&[],
|
||||
&objects,
|
||||
&[],
|
||||
);
|
||||
|
||||
assert!(audit.objects.iter().any(|entry| {
|
||||
entry.rsync_uri == "rsync://example.test/repo/issuer/rejected-with-reason.roa"
|
||||
&& matches!(entry.result, AuditObjectResult::Error)
|
||||
&& entry.detail.as_deref()
|
||||
== Some("EE certificate path validation failed: test")
|
||||
}));
|
||||
assert!(audit.objects.iter().any(|entry| {
|
||||
entry.rsync_uri == "rsync://example.test/repo/issuer/rejected-legacy.roa"
|
||||
&& matches!(entry.result, AuditObjectResult::Error)
|
||||
&& entry.detail.as_deref() == Some(CACHED_REJECT_REASON_NOT_RECORDED)
|
||||
}));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn build_publication_point_audit_from_vcir_failed_no_cache_keeps_current_reject_only() {
|
||||
let now = time::OffsetDateTime::now_utc();
|
||||
@@ -4948,6 +5123,7 @@ fn reconstruct_snapshot_from_vcir_reports_missing_manifest_and_related_raw_bytes
|
||||
sha256: sha256_hex(b"dup-roa-1"),
|
||||
object_type: Some("roa".to_string()),
|
||||
validation_status: VcirArtifactValidationStatus::Accepted,
|
||||
reject_reason: None,
|
||||
});
|
||||
vcir.related_artifacts.push(VcirRelatedArtifact {
|
||||
artifact_role: VcirArtifactRole::SignedObject,
|
||||
@@ -4956,6 +5132,7 @@ fn reconstruct_snapshot_from_vcir_reports_missing_manifest_and_related_raw_bytes
|
||||
sha256: sha256_hex(b"dup-roa-2"),
|
||||
object_type: Some("roa".to_string()),
|
||||
validation_status: VcirArtifactValidationStatus::Accepted,
|
||||
reject_reason: None,
|
||||
});
|
||||
vcir.related_artifacts.push(VcirRelatedArtifact {
|
||||
artifact_role: VcirArtifactRole::IssuerCert,
|
||||
@@ -4964,6 +5141,7 @@ fn reconstruct_snapshot_from_vcir_reports_missing_manifest_and_related_raw_bytes
|
||||
sha256: sha256_hex(b"issuer-cert"),
|
||||
object_type: Some("cer".to_string()),
|
||||
validation_status: VcirArtifactValidationStatus::Accepted,
|
||||
reject_reason: None,
|
||||
});
|
||||
|
||||
let ca = CaInstanceHandle {
|
||||
|
||||
Reference in New Issue
Block a user