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.check_usable()?;
39 read_operation_plan(self.layout, &plan.digest())?;
40 self.require_unchanged_integrity_journal()?;
41 let view = validate(plan, &self.record)?;
42 self.check_artifact_parent()?;
43 for artifact in view.artifacts() {
44 let path = self.layout.root().join(artifact.artifact().artifact_path());
45 checksum_directory(&path)?.verify(artifact.checksum().hash())?;
46 }
47 self.check_usable()?;
50 read_operation_plan(self.layout, &plan.digest())?;
51 self.require_unchanged_integrity_journal()?;
52 Ok(view)
53 }
54
55 pub(super) fn require_unchanged_integrity_journal(&self) -> Result<(), DownloadIntegrityError> {
56 let retained: DownloadJournalRecord =
57 read_record(&self.path(), MAX_DOWNLOAD_JOURNAL_BYTES)?;
58 if retained != self.record {
59 return Err(DownloadIntegrityError::JournalChanged);
60 }
61 Ok(())
62 }
63}
64
65#[derive(Debug, Error)]
67pub enum DownloadIntegrityError {
68 #[error("retained download journal changed during integrity verification")]
70 JournalChanged,
71 #[error(transparent)]
73 Journal(#[from] DownloadJournalError),
74 #[error(transparent)]
76 Plan(#[from] OperationPlanPersistenceError),
77 #[error(transparent)]
79 Policy(#[from] DownloadIntegrityPolicyError),
80 #[error(transparent)]
82 Persistence(#[from] PersistenceError),
83 #[error(transparent)]
85 Artifact(#[from] ArtifactError),
86 #[error(transparent)]
88 Checksum(#[from] ChecksumError),
89}
90
91#[cfg(all(test, unix))]
92mod tests;