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