secure validation cache reuse
This commit is contained in:
@@ -506,6 +506,7 @@ pub struct CachedRoaValidationResult {
|
||||
source_object_hash: [u8; 32],
|
||||
ee_serial: Option<Vec<u8>>,
|
||||
crl_uri: Option<String>,
|
||||
earliest_safe_reuse_time_unix: i64,
|
||||
outputs_effective_until_unix: i64,
|
||||
outputs: Vec<VcirLocalOutput>,
|
||||
}
|
||||
@@ -543,6 +544,12 @@ impl RoaValidationCacheView {
|
||||
}
|
||||
|
||||
for entry in &projection.entries {
|
||||
let Some(earliest_safe_reuse_time_unix) = entry.earliest_safe_reuse_time_unix else {
|
||||
continue;
|
||||
};
|
||||
if time::OffsetDateTime::from_unix_timestamp(earliest_safe_reuse_time_unix).is_err() {
|
||||
continue;
|
||||
}
|
||||
let outputs = entry
|
||||
.outputs
|
||||
.iter()
|
||||
@@ -563,6 +570,7 @@ impl RoaValidationCacheView {
|
||||
source_object_hash: entry.source_object_hash,
|
||||
ee_serial: entry.ee_serial.clone(),
|
||||
crl_uri: entry.crl_uri.clone(),
|
||||
earliest_safe_reuse_time_unix,
|
||||
outputs_effective_until_unix: entry.outputs_effective_until_unix,
|
||||
outputs,
|
||||
},
|
||||
@@ -674,7 +682,9 @@ impl RoaValidationCacheView {
|
||||
if cached.outputs.is_empty() {
|
||||
return_entry_gate!(RoaCacheLookupResult::Miss);
|
||||
}
|
||||
if cached.outputs_effective_until_unix <= validation_time.unix_timestamp() {
|
||||
if validation_time.unix_timestamp() < cached.earliest_safe_reuse_time_unix
|
||||
|| cached.outputs_effective_until_unix <= validation_time.unix_timestamp()
|
||||
{
|
||||
return_entry_gate!(RoaCacheLookupResult::ExpiredBlocked);
|
||||
}
|
||||
|
||||
@@ -760,6 +770,10 @@ impl RoaValidationCacheView {
|
||||
source_object_hash: file.sha256,
|
||||
ee_serial: ee_serial.clone(),
|
||||
crl_uri: crl_uri.to_string(),
|
||||
earliest_safe_reuse_time: PackTime::from_utc_offset_datetime(
|
||||
time::OffsetDateTime::from_unix_timestamp(cached.earliest_safe_reuse_time_unix)
|
||||
.expect("cached ROA safe reuse time must be valid"),
|
||||
),
|
||||
}),
|
||||
};
|
||||
metrics.materialize_nanos = metrics
|
||||
@@ -821,6 +835,14 @@ fn crl_valid_at_time(
|
||||
validation_time >= this_update && validation_time < next_update
|
||||
}
|
||||
|
||||
fn roa_cache_earliest_safe_reuse_time(
|
||||
ee_not_before: time::OffsetDateTime,
|
||||
crl_this_update: time::OffsetDateTime,
|
||||
validation_time: time::OffsetDateTime,
|
||||
) -> PackTime {
|
||||
PackTime::from_utc_offset_datetime(ee_not_before.max(crl_this_update).max(validation_time))
|
||||
}
|
||||
|
||||
fn record_roa_cache_block(
|
||||
stats: &mut RoaValidationCacheStats,
|
||||
lookup_result: &RoaCacheLookupResult,
|
||||
@@ -2736,6 +2758,11 @@ fn process_roa_with_issuer(
|
||||
source_object_hash: file.sha256,
|
||||
ee_serial: BigUnsigned::from_biguint(&ee.resource_cert.tbs.serial_number).bytes_be,
|
||||
crl_uri: issuer_crl_rsync_uri.to_string(),
|
||||
earliest_safe_reuse_time: roa_cache_earliest_safe_reuse_time(
|
||||
ee.resource_cert.tbs.validity_not_before,
|
||||
verified_crl.crl.this_update.utc,
|
||||
validation_time,
|
||||
),
|
||||
};
|
||||
if !collect_vcir_local_outputs {
|
||||
return Ok((vrps, Vec::new(), Some(cache_object_meta)));
|
||||
@@ -2866,6 +2893,11 @@ fn process_roa_with_issuer_parallel_cached(
|
||||
source_object_hash: file.sha256,
|
||||
ee_serial: BigUnsigned::from_biguint(&ee.resource_cert.tbs.serial_number).bytes_be,
|
||||
crl_uri: issuer_crl_rsync_uri.clone(),
|
||||
earliest_safe_reuse_time: roa_cache_earliest_safe_reuse_time(
|
||||
ee.resource_cert.tbs.validity_not_before,
|
||||
verified_crl.crl.this_update.utc,
|
||||
validation_time,
|
||||
),
|
||||
};
|
||||
if !collect_vcir_local_outputs {
|
||||
return Ok((vrps, Vec::new(), Some(cache_object_meta)));
|
||||
@@ -3908,6 +3940,7 @@ mod tests {
|
||||
source_object_hash: roa_hash,
|
||||
ee_serial: vec![0x01],
|
||||
crl_uri: TEST_CRL_URI.to_string(),
|
||||
earliest_safe_reuse_time: vcir.last_successful_validation_time.clone(),
|
||||
}],
|
||||
}),
|
||||
)
|
||||
@@ -4299,7 +4332,7 @@ mod tests {
|
||||
issuer_der,
|
||||
crl_hash,
|
||||
roa_hash,
|
||||
fixed_time("2026-06-04T00:00:00Z"),
|
||||
fixed_time("2026-06-04T01:00:00Z"),
|
||||
fixed_time("2026-06-08T00:00:00Z"),
|
||||
);
|
||||
let projection = sample_roa_cache_projection(&vcir, roa_hash);
|
||||
@@ -4594,6 +4627,7 @@ mod tests {
|
||||
source_object_hash: roa_hash,
|
||||
ee_serial: Some(vec![0x01]),
|
||||
crl_uri: None,
|
||||
earliest_safe_reuse_time_unix: validation_time.unix_timestamp(),
|
||||
outputs_effective_until_unix,
|
||||
outputs: vec![output.clone()],
|
||||
},
|
||||
@@ -4610,6 +4644,7 @@ mod tests {
|
||||
source_object_hash: roa_hash,
|
||||
ee_serial: None,
|
||||
crl_uri: Some(TEST_CRL_URI.to_string()),
|
||||
earliest_safe_reuse_time_unix: validation_time.unix_timestamp(),
|
||||
outputs_effective_until_unix,
|
||||
outputs: vec![output.clone()],
|
||||
},
|
||||
@@ -4626,6 +4661,7 @@ mod tests {
|
||||
source_object_hash: roa_hash,
|
||||
ee_serial: Some(vec![0x01]),
|
||||
crl_uri: Some(TEST_CRL_URI.to_string()),
|
||||
earliest_safe_reuse_time_unix: validation_time.unix_timestamp(),
|
||||
outputs_effective_until_unix,
|
||||
outputs: vec![output.clone()],
|
||||
},
|
||||
@@ -4652,6 +4688,7 @@ mod tests {
|
||||
source_object_hash: [0xff; 32],
|
||||
ee_serial: Some(vec![0x01]),
|
||||
crl_uri: Some(TEST_CRL_URI.to_string()),
|
||||
earliest_safe_reuse_time_unix: validation_time.unix_timestamp(),
|
||||
outputs_effective_until_unix,
|
||||
outputs: vec![output.clone()],
|
||||
},
|
||||
@@ -4668,6 +4705,7 @@ mod tests {
|
||||
source_object_hash: roa_hash,
|
||||
ee_serial: Some(vec![0x01]),
|
||||
crl_uri: Some(TEST_CRL_URI.to_string()),
|
||||
earliest_safe_reuse_time_unix: validation_time.unix_timestamp(),
|
||||
outputs_effective_until_unix,
|
||||
outputs: Vec::new(),
|
||||
},
|
||||
@@ -4688,6 +4726,7 @@ mod tests {
|
||||
source_object_hash: roa_hash,
|
||||
ee_serial: Some(vec![0x01]),
|
||||
crl_uri: Some(TEST_CRL_URI.to_string()),
|
||||
earliest_safe_reuse_time_unix: validation_time.unix_timestamp(),
|
||||
outputs_effective_until_unix,
|
||||
outputs: vec![output],
|
||||
},
|
||||
|
||||
@@ -33,8 +33,9 @@ use crate::storage::{
|
||||
PublicationPointCacheProjectionWriteAction, RawByHashEntry, RoaCacheProjectionContext,
|
||||
RocksStore, ValidatedCaInstanceResult, VcirArtifactKind, VcirArtifactRole,
|
||||
VcirArtifactValidationStatus, VcirAuditSummary, VcirCcrManifestProjection, VcirChildEntry,
|
||||
VcirInstanceGate, VcirLocalOutput, VcirLocalOutputPayload, VcirOutputType, VcirRelatedArtifact,
|
||||
VcirReplaceTimingBreakdown, VcirSourceObjectType, VcirSummary,
|
||||
VcirFailedFetchReuseIdentity, VcirInstanceGate, VcirLocalOutput, VcirLocalOutputPayload,
|
||||
VcirOutputType, VcirRelatedArtifact, VcirReplaceTimingBreakdown, VcirSourceObjectType,
|
||||
VcirSummary,
|
||||
};
|
||||
use crate::sync::repo::{
|
||||
sync_publication_point, sync_publication_point_replay, sync_publication_point_replay_delta,
|
||||
@@ -1751,6 +1752,7 @@ impl<'a> PublicationPointRunner for Rpkiv1PublicationPointRunner<'a> {
|
||||
self.store,
|
||||
ca,
|
||||
&fresh_err,
|
||||
self.policy,
|
||||
self.validation_time,
|
||||
)
|
||||
.map_err(|e| format!("failed fetch VCIR projection failed: {e}"))?;
|
||||
@@ -4256,6 +4258,7 @@ fn project_current_instance_vcir_on_failed_fetch(
|
||||
store: &RocksStore,
|
||||
ca: &CaInstanceHandle,
|
||||
fresh_err: &ManifestFreshError,
|
||||
policy: &Policy,
|
||||
validation_time: time::OffsetDateTime,
|
||||
) -> Result<VcirReuseProjection, String> {
|
||||
let mut warnings = Vec::new();
|
||||
@@ -4264,80 +4267,57 @@ fn project_current_instance_vcir_on_failed_fetch(
|
||||
.get_vcir(&ca.manifest_rsync_uri)
|
||||
.map_err(|e| format!("load VCIR failed: {e}"))?
|
||||
else {
|
||||
warnings.push(
|
||||
Warning::new(format!("manifest failed fetch: {fresh_err}"))
|
||||
.with_rfc_refs(&[RfcRef("RFC 9286 §6.6")])
|
||||
.with_context(&ca.manifest_rsync_uri),
|
||||
);
|
||||
warnings.push(
|
||||
Warning::new(
|
||||
"no latest validated result for current CA instance; no cached output reused",
|
||||
)
|
||||
.with_rfc_refs(&[RfcRef("RFC 9286 §6.6")])
|
||||
.with_context(&ca.manifest_rsync_uri),
|
||||
);
|
||||
return Ok(VcirReuseProjection {
|
||||
source: PublicationPointSource::FailedFetchNoCache,
|
||||
vcir: None,
|
||||
ccr_manifest_projection: None,
|
||||
snapshot: None,
|
||||
objects: empty_objects_output(),
|
||||
child_audits: Vec::new(),
|
||||
discovered_children: Vec::new(),
|
||||
warnings,
|
||||
});
|
||||
return Ok(failed_fetch_no_cache_projection(
|
||||
ca,
|
||||
fresh_err,
|
||||
None,
|
||||
"no latest validated result for current CA instance; no cached output reused",
|
||||
));
|
||||
};
|
||||
|
||||
if !vcir.audit_summary.failed_fetch_eligible {
|
||||
warnings.push(
|
||||
Warning::new(format!("manifest failed fetch: {fresh_err}"))
|
||||
.with_rfc_refs(&[RfcRef("RFC 9286 §6.6")])
|
||||
.with_context(&ca.manifest_rsync_uri),
|
||||
);
|
||||
warnings.push(
|
||||
Warning::new(
|
||||
"latest VCIR is not marked failed-fetch eligible; no cached output reused",
|
||||
)
|
||||
.with_rfc_refs(&[RfcRef("RFC 9286 §6.6")])
|
||||
.with_context(&ca.manifest_rsync_uri),
|
||||
);
|
||||
return Ok(VcirReuseProjection {
|
||||
source: PublicationPointSource::FailedFetchNoCache,
|
||||
vcir: Some(vcir),
|
||||
ccr_manifest_projection: None,
|
||||
snapshot: None,
|
||||
objects: empty_objects_output(),
|
||||
child_audits: Vec::new(),
|
||||
discovered_children: Vec::new(),
|
||||
warnings,
|
||||
});
|
||||
return Ok(failed_fetch_no_cache_projection(
|
||||
ca,
|
||||
fresh_err,
|
||||
Some(vcir),
|
||||
"latest VCIR is not marked failed-fetch eligible; no cached output reused",
|
||||
));
|
||||
}
|
||||
|
||||
let instance_effective_until =
|
||||
parse_snapshot_time_value(&vcir.instance_gate.instance_effective_until)?;
|
||||
if validation_time > instance_effective_until {
|
||||
warnings.push(
|
||||
Warning::new(format!("manifest failed fetch: {fresh_err}"))
|
||||
.with_rfc_refs(&[RfcRef("RFC 9286 §6.6")])
|
||||
.with_context(&ca.manifest_rsync_uri),
|
||||
);
|
||||
warnings.push(
|
||||
Warning::new(
|
||||
"latest VCIR instance_gate expired; current instance contributes no cached output",
|
||||
)
|
||||
.with_rfc_refs(&[RfcRef("RFC 9286 §6.6")])
|
||||
.with_context(&ca.manifest_rsync_uri),
|
||||
);
|
||||
return Ok(VcirReuseProjection {
|
||||
source: PublicationPointSource::FailedFetchNoCache,
|
||||
vcir: Some(vcir),
|
||||
ccr_manifest_projection: None,
|
||||
snapshot: None,
|
||||
objects: empty_objects_output(),
|
||||
child_audits: Vec::new(),
|
||||
discovered_children: Vec::new(),
|
||||
warnings,
|
||||
});
|
||||
let reuse_identity = match store.get_vcir_failed_fetch_reuse_identity(&ca.manifest_rsync_uri) {
|
||||
Ok(Some(identity)) => identity,
|
||||
Ok(None) => {
|
||||
return Ok(failed_fetch_no_cache_projection(
|
||||
ca,
|
||||
fresh_err,
|
||||
Some(vcir),
|
||||
"latest VCIR reuse identity is missing; no cached output or child reused",
|
||||
));
|
||||
}
|
||||
Err(error) => {
|
||||
return Ok(failed_fetch_no_cache_projection(
|
||||
ca,
|
||||
fresh_err,
|
||||
Some(vcir),
|
||||
&format!(
|
||||
"latest VCIR reuse identity is invalid ({error}); no cached output or child reused"
|
||||
),
|
||||
));
|
||||
}
|
||||
};
|
||||
if !failed_fetch_reuse_identity_matches_current(
|
||||
&reuse_identity,
|
||||
&vcir,
|
||||
ca,
|
||||
policy,
|
||||
validation_time,
|
||||
) {
|
||||
return Ok(failed_fetch_no_cache_projection(
|
||||
ca,
|
||||
fresh_err,
|
||||
Some(vcir),
|
||||
"latest VCIR reuse identity does not match the current CA context or time window; no cached output or child reused",
|
||||
));
|
||||
}
|
||||
|
||||
let ccr_manifest_projection = reuse_ccr_manifest_projection_from_vcir(ca, &vcir)?;
|
||||
@@ -4367,6 +4347,73 @@ fn project_current_instance_vcir_on_failed_fetch(
|
||||
})
|
||||
}
|
||||
|
||||
fn failed_fetch_no_cache_projection(
|
||||
ca: &CaInstanceHandle,
|
||||
fresh_err: &ManifestFreshError,
|
||||
vcir: Option<ValidatedCaInstanceResult>,
|
||||
reason: &str,
|
||||
) -> VcirReuseProjection {
|
||||
let warnings = vec![
|
||||
Warning::new(format!("manifest failed fetch: {fresh_err}"))
|
||||
.with_rfc_refs(&[RfcRef("RFC 9286 §6.6")])
|
||||
.with_context(&ca.manifest_rsync_uri),
|
||||
Warning::new(reason)
|
||||
.with_rfc_refs(&[RfcRef("RFC 9286 §6.6")])
|
||||
.with_context(&ca.manifest_rsync_uri),
|
||||
];
|
||||
VcirReuseProjection {
|
||||
source: PublicationPointSource::FailedFetchNoCache,
|
||||
vcir,
|
||||
ccr_manifest_projection: None,
|
||||
snapshot: None,
|
||||
objects: empty_objects_output(),
|
||||
child_audits: Vec::new(),
|
||||
discovered_children: Vec::new(),
|
||||
warnings,
|
||||
}
|
||||
}
|
||||
|
||||
fn failed_fetch_reuse_identity_for_fresh_result(
|
||||
ca: &CaInstanceHandle,
|
||||
policy: &Policy,
|
||||
validation_time: time::OffsetDateTime,
|
||||
effective_until: PackTime,
|
||||
) -> Result<VcirFailedFetchReuseIdentity, String> {
|
||||
let current_ca_sha256 = ca.ca_certificate_sha256_32().ok_or_else(|| {
|
||||
"current CA certificate hash unavailable for VCIR reuse identity".to_string()
|
||||
})?;
|
||||
let identity = VcirFailedFetchReuseIdentity {
|
||||
current_ca_sha256,
|
||||
ta_context_digest: ta_context_digest_for_ca(ca),
|
||||
parent_context_digest: parent_context_digest_for_ca(ca),
|
||||
policy_fingerprint: publication_point_cache_policy_fingerprint(policy),
|
||||
effective_not_before: PackTime::from_utc_offset_datetime(validation_time),
|
||||
effective_until,
|
||||
};
|
||||
identity
|
||||
.validate_internal()
|
||||
.map_err(|error| error.to_string())?;
|
||||
Ok(identity)
|
||||
}
|
||||
|
||||
fn failed_fetch_reuse_identity_matches_current(
|
||||
cached: &VcirFailedFetchReuseIdentity,
|
||||
vcir: &ValidatedCaInstanceResult,
|
||||
ca: &CaInstanceHandle,
|
||||
policy: &Policy,
|
||||
validation_time: time::OffsetDateTime,
|
||||
) -> bool {
|
||||
let Some(current_ca_sha256) = ca.ca_certificate_sha256_32() else {
|
||||
return false;
|
||||
};
|
||||
cached.current_ca_sha256 == current_ca_sha256
|
||||
&& cached.ta_context_digest == ta_context_digest_for_ca(ca)
|
||||
&& cached.parent_context_digest == parent_context_digest_for_ca(ca)
|
||||
&& cached.policy_fingerprint == publication_point_cache_policy_fingerprint(policy)
|
||||
&& cached.effective_until == vcir.instance_gate.instance_effective_until
|
||||
&& cached.contains_validation_time(validation_time)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
fn reconstruct_snapshot_from_vcir(
|
||||
store: &RocksStore,
|
||||
@@ -5280,8 +5327,14 @@ fn persist_vcir_for_fresh_result_with_timing(
|
||||
.expect("publication point projection must exist when guard is not active"),
|
||||
)
|
||||
};
|
||||
let failed_fetch_reuse_identity = failed_fetch_reuse_identity_for_fresh_result(
|
||||
ca,
|
||||
policy,
|
||||
validation_time,
|
||||
vcir.instance_gate.instance_effective_until.clone(),
|
||||
)?;
|
||||
let replace_timing = store
|
||||
.replace_vcir_manifest_replay_meta_and_projection_action(
|
||||
.replace_vcir_manifest_replay_meta_and_projection_action_with_failed_fetch_reuse_identity(
|
||||
&vcir,
|
||||
Some(&RoaCacheProjectionContext {
|
||||
parent_context_digest: parent_context_digest_for_ca(ca),
|
||||
@@ -5289,6 +5342,7 @@ fn persist_vcir_for_fresh_result_with_timing(
|
||||
object_meta: objects.roa_cache_object_meta.clone(),
|
||||
}),
|
||||
publication_point_cache_projection_action,
|
||||
Some(&failed_fetch_reuse_identity),
|
||||
)
|
||||
.map_err(|e| format!("store VCIR and manifest replay meta failed: {e}"))?;
|
||||
timing.replace_vcir_ms = replace_vcir_started.elapsed().as_millis() as u64;
|
||||
|
||||
@@ -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();
|
||||
|
||||
Reference in New Issue
Block a user