ic_backup/ops/persistence/download_journal/integrity/
mod.rs1use super::super::json::check_json_size;
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::{
14 OperationPlanPersistenceError, PersistenceError, read_json, read_operation_plan,
15 },
16 },
17 policy::download_integrity::{DownloadIntegrityPolicyError, DurableDownloadView, validate},
18};
19use thiserror::Error;
20
21impl DownloadJournalGuard<'_> {
22 pub fn verify_durable_artifacts<'a>(
37 &'a self,
38 plan: &'a OperationPlanRecord,
39 ) -> Result<DurableDownloadView<'a>, DownloadIntegrityError> {
40 self.check_usable()?;
41 read_operation_plan(self.layout, &plan.digest())?;
42 self.require_unchanged_integrity_journal()?;
43 let view = validate(plan, &self.record)?;
44 self.check_artifact_parent()?;
45 for artifact in view.artifacts() {
46 let path = self.layout.root().join(artifact.artifact().artifact_path());
47 checksum_directory(&path)?.verify(artifact.checksum().hash())?;
48 }
49 self.check_usable()?;
52 read_operation_plan(self.layout, &plan.digest())?;
53 self.require_unchanged_integrity_journal()?;
54 Ok(view)
55 }
56
57 pub(super) fn require_unchanged_integrity_journal(&self) -> Result<(), DownloadIntegrityError> {
58 let retained: DownloadJournalRecord = read_json(&self.path(), MAX_DOWNLOAD_JOURNAL_BYTES)?;
59 check_json_size(&retained, MAX_DOWNLOAD_JOURNAL_BYTES)?;
60 if retained != self.record {
61 return Err(DownloadIntegrityError::JournalChanged);
62 }
63 Ok(())
64 }
65}
66
67#[derive(Debug, Error)]
69pub enum DownloadIntegrityError {
70 #[error("retained download journal changed during integrity verification")]
72 JournalChanged,
73 #[error(transparent)]
75 Journal(#[from] DownloadJournalError),
76 #[error(transparent)]
78 Plan(#[from] OperationPlanPersistenceError),
79 #[error(transparent)]
81 Policy(#[from] DownloadIntegrityPolicyError),
82 #[error(transparent)]
84 Persistence(#[from] PersistenceError),
85 #[error(transparent)]
87 Artifact(#[from] ArtifactError),
88 #[error(transparent)]
90 Checksum(#[from] ChecksumError),
91}
92
93#[cfg(all(test, unix))]
94mod tests;