diff options
author | Lars Wirzenius <liw@liw.fi> | 2023-09-02 09:35:15 +0300 |
---|---|---|
committer | Lars Wirzenius <liw@liw.fi> | 2023-09-02 09:35:15 +0300 |
commit | 17eb20a3ed9f11e302a7af41dcd02655f51e80ec (patch) | |
tree | 6e8a3b81c383a7cb397cd300f4192a457b10213f | |
parent | 9b0d3fe877b8f0df38fd9b0f0245148474629540 (diff) | |
download | ambient-run-17eb20a3ed9f11e302a7af41dcd02655f51e80ec.tar.gz |
feat: fail build if it produces an artifact that's too large
Sponsored-by: author
-rw-r--r-- | ambient-run.md | 31 | ||||
-rw-r--r-- | src/bin/ambient-run.rs | 3 | ||||
-rw-r--r-- | src/project.rs | 9 | ||||
-rw-r--r-- | src/qemu.rs | 14 |
4 files changed, 55 insertions, 2 deletions
diff --git a/ambient-run.md b/ambient-run.md index 7d3ab68..82eccab 100644 --- a/ambient-run.md +++ b/ambient-run.md @@ -166,6 +166,7 @@ shell: | cargo test image: /my/image.qcow2 artifact: null +artifact_max_size: null ~~~ ### Show per-build configuration @@ -285,6 +286,36 @@ shell: | image: image.qcow2 ~~~ +### Fail build that tries to produce an oversize artifact + +_Requirement:_ If a build produces an artifact that is too large, the +build should fail. + +_Justification:_ Without a limit, a malicious build could fill all +available storage space, which is a denial-of-service attack. + +_Stakeholder:_ Lars. + +~~~scenario +given an installed ambient-run +given file small-artifact-project.yaml +given file foo/README.md from foo-project.yaml +given image file image.qcow2 specified for test suite +when I run ambient-run build small-artifact-project.yaml --log foo.log +then file foo.log contains "EXIT CODE: 2" +~~~ + + +~~~{#small-artifact-project.yaml .file .yaml} +source: foo +shell: | + #!/bin/bash + tar -cf /dev/vdc . +image: image.qcow2 +artifact: foo.tar +artifact_max_size: 1 +~~~ + ### Build is given dependencies ### Cache is persistent between builds ### Build gets the resources is demands diff --git a/src/bin/ambient-run.rs b/src/bin/ambient-run.rs index 3dc778e..37054c2 100644 --- a/src/bin/ambient-run.rs +++ b/src/bin/ambient-run.rs @@ -216,7 +216,8 @@ impl BuildCommand { let mut qemu = Qemu::new(&project.image()) .with_shell(project.shell()) .with_source(&project.source()) - .with_artifact(project.artifact()); + .with_artifact(project.artifact()) + .with_artifact_max_size(project.artifact_max_size()); if let Some(log) = &self.log { qemu = qemu.with_log(log); } diff --git a/src/project.rs b/src/project.rs index b381734..76f42dc 100644 --- a/src/project.rs +++ b/src/project.rs @@ -13,6 +13,7 @@ pub struct Project { shell: String, image: PathBuf, artifact: Option<PathBuf>, + artifact_max_size: Option<u64>, } impl Project { @@ -45,6 +46,7 @@ impl Project { shell: "".into(), image, artifact: None, + artifact_max_size: None, }; project.add_from(filename)?; if project.shell.is_empty() { @@ -71,6 +73,7 @@ impl Project { self.image = x; } self.artifact = snippet.artifact; + self.artifact_max_size = snippet.artifact_max_size; Ok(()) } @@ -98,6 +101,11 @@ impl Project { pub fn artifact(&self) -> &Option<PathBuf> { &self.artifact } + + /// Artifact file max size. + pub fn artifact_max_size(&self) -> Option<u64> { + self.artifact_max_size.clone() + } } #[derive(Debug, Deserialize)] @@ -107,6 +115,7 @@ struct ProjectSnippet { shell: Option<String>, image: Option<PathBuf>, artifact: Option<PathBuf>, + artifact_max_size: Option<u64>, } /// Possible errors from configuration file handling. diff --git a/src/qemu.rs b/src/qemu.rs index 3450101..4c6efff 100644 --- a/src/qemu.rs +++ b/src/qemu.rs @@ -19,6 +19,7 @@ pub struct Qemu { source: PathBuf, shell: Option<String>, artifact: Option<PathBuf>, + artifact_max_xize: u64, } impl Qemu { @@ -27,6 +28,7 @@ impl Qemu { Self { image: image.into(), source: PathBuf::from("."), + artifact_max_xize: MAX_OUTPUT_SIZE, ..Default::default() } } @@ -55,6 +57,12 @@ impl Qemu { self } + /// Set maximum length of output artifact. + pub fn with_artifact_max_size(mut self, size: Option<u64>) -> Self { + self.artifact_max_xize = size.unwrap_or(MAX_OUTPUT_SIZE); + self + } + /// Run QEMU in the specified way. pub fn run(&self) -> Result<(), QemuError> { eprintln!("qemu run"); @@ -71,7 +79,11 @@ impl Qemu { eprintln!("output drive"); let output_drive = if let Some(filename) = &self.artifact { eprintln!("output to {}", filename.display()); - Self::create_tar_with_size(filename.to_path_buf(), empty.path(), MAX_OUTPUT_SIZE)? + Self::create_tar_with_size( + filename.to_path_buf(), + empty.path(), + self.artifact_max_xize, + )? } else { eprintln!("empty output drive"); Self::create_tar_with_size(tmp.path().join("output"), empty.path(), 0)? |