ic_backup/ops/persistence/download_journal/integrity/
mod.rs1use super::super::json::read_record;
4use super::{DownloadJournalError, DownloadJournalGuard};
5use crate::{
6 model::{
7 artifacts::ChecksumError,
8 download_journal::{DownloadJournalRecord, MAX_DOWNLOAD_JOURNAL_BYTES},
9 operation_plan::OperationPlanRecord,
10 },
11 ops::{
12 artifacts::{ArtifactError, checksum_directory},
13 persistence::{OperationPlanPersistenceError, PersistenceError, read_operation_plan},
14 },
15 policy::download_integrity::{DownloadIntegrityPolicyError, DurableDownloadView, validate},
16};
17use thiserror::Error;
18
19impl DownloadJournalGuard<'_> {
20 pub fn verify_durable_artifacts<'a>(
35 &'a self,
36 plan: &'a OperationPlanRecord,
37 ) -> Result<DurableDownloadView<'a>, DownloadIntegrityError> {
38 self.admit_integrity_original(plan)?;
39 let view = validate(plan, &self.record)?;
40 self.check_artifact_parent()?;
41 for artifact in view.artifacts() {
42 let path = self.layout.root().join(artifact.artifact().artifact_path());
43 checksum_directory(&path)?.verify(artifact.checksum().hash())?;
44 }
45 self.admit_integrity_original(plan)?;
48 Ok(view)
49 }
50
51 pub(super) fn admit_integrity_original(
54 &self,
55 plan: &OperationPlanRecord,
56 ) -> Result<(), DownloadIntegrityError> {
57 self.check_usable()?;
58 read_operation_plan(self.layout, &plan.digest())?;
59 self.require_unchanged_integrity_journal()
60 }
61
62 pub(super) fn require_unchanged_integrity_journal(&self) -> Result<(), DownloadIntegrityError> {
63 let retained: DownloadJournalRecord =
64 read_record(&self.path(), MAX_DOWNLOAD_JOURNAL_BYTES)?;
65 if retained != self.record {
66 return Err(DownloadIntegrityError::JournalChanged);
67 }
68 Ok(())
69 }
70}
71
72#[derive(Debug, Error)]
74pub enum DownloadIntegrityError {
75 #[error("retained download journal changed during integrity verification")]
77 JournalChanged,
78 #[error(transparent)]
80 Journal(#[from] DownloadJournalError),
81 #[error(transparent)]
83 Plan(#[from] OperationPlanPersistenceError),
84 #[error(transparent)]
86 Policy(#[from] DownloadIntegrityPolicyError),
87 #[error(transparent)]
89 Persistence(#[from] PersistenceError),
90 #[error(transparent)]
92 Artifact(#[from] ArtifactError),
93 #[error(transparent)]
95 Checksum(#[from] ChecksumError),
96}
97
98#[cfg(all(test, unix))]
99mod tests;