secure validation cache reuse

This commit is contained in:
2026-07-11 21:57:46 +08:00
parent 8613cfae60
commit 60796299b0
7 changed files with 428 additions and 107 deletions

View File

@@ -753,6 +753,28 @@ fn sample_vcir_for_projection(
}
}
fn put_vcir_for_failed_fetch_reuse(
store: &RocksStore,
ca: &CaInstanceHandle,
policy: &Policy,
vcir: &ValidatedCaInstanceResult,
) {
let validation_time = vcir
.last_successful_validation_time
.parse()
.expect("parse VCIR validation time");
let identity = failed_fetch_reuse_identity_for_fresh_result(
ca,
policy,
validation_time,
vcir.instance_gate.instance_effective_until.clone(),
)
.expect("build VCIR failed-fetch reuse identity");
store
.put_vcir_with_failed_fetch_reuse_identity(vcir, &identity)
.expect("put reusable VCIR");
}
#[test]
fn never_http_fetcher_returns_error() {
let f = NeverHttpFetcher;
@@ -3827,7 +3849,6 @@ fn project_current_instance_vcir_reuses_local_outputs_and_restores_children() {
let repo_bytes_db = store_dir.path().join("repo-bytes.db");
let store = RocksStore::open_with_external_repo_bytes(&main_db, &repo_bytes_db)
.expect("open rocksdb with external repo bytes");
store.put_vcir(&vcir).expect("put vcir");
store
.put_blob_bytes_batch(&[(child_cert_hash.clone(), g.child_ca_der.clone())])
.expect("put child cert repo bytes");
@@ -3852,6 +3873,8 @@ fn project_current_instance_vcir_reuses_local_outputs_and_restores_children() {
publication_point_rsync_uri: "rsync://example.test/repo/issuer/".to_string(),
rrdp_notification_uri: Some("https://example.test/notify.xml".to_string()),
};
let policy = Policy::default();
put_vcir_for_failed_fetch_reuse(&store, &ca, &policy, &vcir);
let projection = project_current_instance_vcir_on_failed_fetch(
&store,
@@ -3859,6 +3882,7 @@ fn project_current_instance_vcir_reuses_local_outputs_and_restores_children() {
&ManifestFreshError::RepoSyncFailed {
detail: "synthetic".to_string(),
},
&policy,
now,
)
.expect("project vcir");
@@ -3950,6 +3974,7 @@ fn project_current_instance_vcir_returns_no_output_when_instance_gate_expired()
&ManifestFreshError::RepoSyncFailed {
detail: "synthetic".to_string(),
},
&Policy::default(),
now,
)
.expect("project vcir");
@@ -3975,7 +4000,6 @@ fn project_current_instance_vcir_keeps_real_fresh_validation_warning() {
let repo_bytes_db = store_dir.path().join("repo-bytes.db");
let store = RocksStore::open_with_external_repo_bytes(&main_db, &repo_bytes_db)
.expect("open rocksdb with external repo bytes");
store.put_vcir(&vcir).expect("put vcir");
store
.put_blob_bytes_batch(&[(child_cert_hash, b"child-cert".to_vec())])
.expect("put child cert repo bytes");
@@ -3993,6 +4017,8 @@ fn project_current_instance_vcir_keeps_real_fresh_validation_warning() {
publication_point_rsync_uri: "rsync://example.test/repo/issuer/".to_string(),
rrdp_notification_uri: None,
};
let policy = Policy::default();
put_vcir_for_failed_fetch_reuse(&store, &ca, &policy, &vcir);
let projection = project_current_instance_vcir_on_failed_fetch(
&store,
@@ -4000,6 +4026,7 @@ fn project_current_instance_vcir_keeps_real_fresh_validation_warning() {
&ManifestFreshError::HashMismatch {
rsync_uri: "rsync://example.test/repo/issuer/a.roa".to_string(),
},
&policy,
now,
)
.expect("project vcir");
@@ -4048,6 +4075,7 @@ fn project_current_instance_vcir_returns_no_output_when_latest_result_missing()
&ManifestFreshError::RepoSyncFailed {
detail: "synthetic".to_string(),
},
&Policy::default(),
now,
)
.expect("project without cached vcir");
@@ -4099,6 +4127,7 @@ fn project_current_instance_vcir_returns_no_output_when_latest_result_is_ineligi
&ManifestFreshError::RepoSyncFailed {
detail: "synthetic".to_string(),
},
&Policy::default(),
now,
)
.expect("project ineligible vcir");
@@ -4128,7 +4157,6 @@ fn project_current_instance_vcir_rejects_mismatched_ccr_projection_uri() {
let store_dir = tempfile::tempdir().expect("store dir");
let store = RocksStore::open(store_dir.path()).expect("open rocksdb");
store.put_vcir(&vcir).expect("put vcir");
let ca = CaInstanceHandle {
depth: 0,
@@ -4143,6 +4171,8 @@ fn project_current_instance_vcir_rejects_mismatched_ccr_projection_uri() {
publication_point_rsync_uri: "rsync://example.test/repo/issuer/".to_string(),
rrdp_notification_uri: None,
};
let policy = Policy::default();
put_vcir_for_failed_fetch_reuse(&store, &ca, &policy, &vcir);
let err = project_current_instance_vcir_on_failed_fetch(
&store,
@@ -4150,6 +4180,7 @@ fn project_current_instance_vcir_rejects_mismatched_ccr_projection_uri() {
&ManifestFreshError::RepoSyncFailed {
detail: "synthetic".to_string(),
},
&policy,
now,
)
.unwrap_err();