From bb2697193af17b11fe6113744185af5762ddc750 Mon Sep 17 00:00:00 2001 From: zach Date: Mon, 5 Dec 2022 18:01:25 -0800 Subject: [PATCH] feat: add `allowed_paths` to specify preopened directories in WASI (#137) Adds ability to make local files available to plugins. Using the Rust SDK: ```rust let wasm = include_bytes!("code.wasm"); let mut context = Context::new(); let manifest = Manifest::new(vec![Wasm::data(wasm)]).with_allowed_path("/path/on/disk", "/plugin/path"); let plugin = Plugin::new_with_manifest(&mut context, &manifest, false)?; ... ``` --- manifest/schema.json | 10 +++++++ manifest/src/lib.rs | 66 +++++++++++++++++++++++++++++++++++++++++-- runtime/src/plugin.rs | 7 +++++ 3 files changed, 81 insertions(+), 2 deletions(-) diff --git a/manifest/schema.json b/manifest/schema.json index 4cc802c..0cb1331 100644 --- a/manifest/schema.json +++ b/manifest/schema.json @@ -13,6 +13,16 @@ "type": "string" } }, + "allowed_paths": { + "default": null, + "type": [ + "object", + "null" + ], + "additionalProperties": { + "type": "string" + } + }, "config": { "default": {}, "type": "object", diff --git a/manifest/src/lib.rs b/manifest/src/lib.rs index 6b9ef72..b70be0f 100644 --- a/manifest/src/lib.rs +++ b/manifest/src/lib.rs @@ -1,4 +1,5 @@ use std::collections::BTreeMap; +use std::path::{Path, PathBuf}; #[deprecated] pub type ManifestMemory = MemoryOptions; @@ -82,8 +83,7 @@ pub type ManifestWasm = Wasm; #[serde(untagged)] pub enum Wasm { File { - path: std::path::PathBuf, - + path: PathBuf, #[serde(flatten)] meta: WasmMetadata, }, @@ -160,6 +160,8 @@ pub struct Manifest { pub config: BTreeMap, #[serde(default)] pub allowed_hosts: Option>, + #[serde(default)] + pub allowed_paths: Option>, } impl Manifest { @@ -170,6 +172,66 @@ impl Manifest { ..Default::default() } } + + /// Disallow HTTP requests to all hosts + pub fn disallow_all_hosts(mut self) -> Self { + self.allowed_hosts = Some(vec![]); + self + } + + /// Set memory options + pub fn with_memory_options(mut self, memory: MemoryOptions) -> Self { + self.memory = memory; + self + } + + /// Add a hostname to `allowed_hosts` + pub fn with_allowed_host(mut self, host: impl Into) -> Self { + match &mut self.allowed_hosts { + Some(h) => { + h.push(host.into()); + } + None => self.allowed_hosts = Some(vec![host.into()]), + } + + self + } + + /// Set `allowed_hosts` + pub fn with_allowed_hosts(mut self, hosts: impl Iterator) -> Self { + self.allowed_hosts = Some(hosts.collect()); + self + } + + /// Add a path to `allowed_paths` + pub fn with_allowed_path(mut self, src: impl AsRef, dest: impl AsRef) -> Self { + let src = src.as_ref().to_path_buf(); + let dest = dest.as_ref().to_path_buf(); + match &mut self.allowed_paths { + Some(p) => { + p.insert(src, dest); + } + None => { + let mut p = BTreeMap::new(); + p.insert(src, dest); + self.allowed_paths = Some(p); + } + } + + self + } + + /// Set `allowed_paths` + pub fn with_allowed_paths(mut self, paths: impl Iterator) -> Self { + self.allowed_paths = Some(paths.collect()); + self + } + + /// Set `config` + pub fn with_config(mut self, c: impl Iterator) -> Self { + self.config = c.collect(); + self + } } mod base64 { diff --git a/runtime/src/plugin.rs b/runtime/src/plugin.rs index c5cfb88..5a7bbd4 100644 --- a/runtime/src/plugin.rs +++ b/runtime/src/plugin.rs @@ -40,6 +40,13 @@ impl Internal { ctx = ctx.env(k, v)?; } + if let Some(a) = &manifest.as_ref().allowed_paths { + for (k, v) in a.iter() { + let d = wasmtime_wasi::Dir::from_std_file(std::fs::File::open(k)?); + ctx = ctx.preopened_dir(d, v)?; + } + } + #[cfg(feature = "nn")] let nn = wasmtime_wasi_nn::WasiNnCtx::new()?;