diff options
Diffstat (limited to 'runtime')
-rw-r--r-- | runtime/Cargo.toml | 1 | ||||
-rw-r--r-- | runtime/lib.rs | 2 | ||||
-rw-r--r-- | runtime/ops/permissions.rs | 6 | ||||
-rw-r--r-- | runtime/ops/worker_host.rs | 2 | ||||
-rw-r--r-- | runtime/permissions.rs | 238 | ||||
-rw-r--r-- | runtime/permissions/Cargo.toml | 28 | ||||
-rw-r--r-- | runtime/permissions/README.md | 0 | ||||
-rw-r--r-- | runtime/permissions/lib.rs (renamed from runtime/permissions/mod.rs) | 233 | ||||
-rw-r--r-- | runtime/snapshot.rs | 20 | ||||
-rw-r--r-- | runtime/web_worker.rs | 1 | ||||
-rw-r--r-- | runtime/worker.rs | 3 |
11 files changed, 341 insertions, 193 deletions
diff --git a/runtime/Cargo.toml b/runtime/Cargo.toml index 723a4b2a9..c27ae1012 100644 --- a/runtime/Cargo.toml +++ b/runtime/Cargo.toml @@ -90,6 +90,7 @@ deno_kv.workspace = true deno_napi.workspace = true deno_net.workspace = true deno_node.workspace = true +deno_permissions.workspace = true deno_terminal.workspace = true deno_tls.workspace = true deno_url.workspace = true diff --git a/runtime/lib.rs b/runtime/lib.rs index ade10a9c6..72fa1cef8 100644 --- a/runtime/lib.rs +++ b/runtime/lib.rs @@ -16,6 +16,8 @@ pub use deno_kv; pub use deno_napi; pub use deno_net; pub use deno_node; +pub use deno_permissions; +pub use deno_terminal::colors; pub use deno_tls; pub use deno_url; pub use deno_web; diff --git a/runtime/ops/permissions.rs b/runtime/ops/permissions.rs index e6c4261e3..a961fd3ea 100644 --- a/runtime/ops/permissions.rs +++ b/runtime/ops/permissions.rs @@ -1,8 +1,8 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. -use crate::permissions::parse_sys_kind; -use crate::permissions::PermissionState; -use crate::permissions::PermissionsContainer; +use ::deno_permissions::parse_sys_kind; +use ::deno_permissions::PermissionState; +use ::deno_permissions::PermissionsContainer; use deno_core::error::custom_error; use deno_core::error::uri_error; use deno_core::error::AnyError; diff --git a/runtime/ops/worker_host.rs b/runtime/ops/worker_host.rs index d1b318f0f..1d056d459 100644 --- a/runtime/ops/worker_host.rs +++ b/runtime/ops/worker_host.rs @@ -153,7 +153,7 @@ fn op_create_worker( let parent_permissions = state.borrow_mut::<PermissionsContainer>(); let worker_permissions = if let Some(child_permissions_arg) = args.permissions { - let mut parent_permissions = parent_permissions.0.lock(); + let mut parent_permissions = parent_permissions.0 .0.lock(); let perms = create_child_permissions(&mut parent_permissions, child_permissions_arg)?; PermissionsContainer::new(perms) diff --git a/runtime/permissions.rs b/runtime/permissions.rs new file mode 100644 index 000000000..ccd0d3254 --- /dev/null +++ b/runtime/permissions.rs @@ -0,0 +1,238 @@ +// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. + +use std::path::Path; + +use deno_core::error::AnyError; +use deno_core::url::Url; +pub use deno_permissions::create_child_permissions; +pub use deno_permissions::parse_sys_kind; +pub use deno_permissions::set_prompt_callbacks; +pub use deno_permissions::ChildPermissionsArg; +pub use deno_permissions::Permissions; +pub use deno_permissions::PermissionsOptions; + +// NOTE: Temporary permissions container to satisfy traits. We are migrating to the deno_permissions +// crate. +#[derive(Debug, Clone)] + +pub struct PermissionsContainer(pub deno_permissions::PermissionsContainer); + +impl PermissionsContainer { + pub fn new(permissions: deno_permissions::Permissions) -> Self { + Self(deno_permissions::PermissionsContainer::new(permissions)) + } + + pub fn allow_all() -> Self { + Self(deno_permissions::PermissionsContainer::allow_all()) + } +} + +impl std::ops::Deref for PermissionsContainer { + type Target = deno_permissions::PermissionsContainer; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl std::ops::DerefMut for PermissionsContainer { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } +} + +impl deno_node::NodePermissions for PermissionsContainer { + #[inline(always)] + fn check_net_url( + &mut self, + url: &Url, + api_name: &str, + ) -> Result<(), AnyError> { + self.0.check_net_url(url, api_name) + } + + #[inline(always)] + fn check_read_with_api_name( + &self, + path: &Path, + api_name: Option<&str>, + ) -> Result<(), AnyError> { + self.0.check_read_with_api_name(path, api_name) + } + + #[inline(always)] + fn check_write_with_api_name( + &self, + path: &Path, + api_name: Option<&str>, + ) -> Result<(), AnyError> { + self.0.check_write_with_api_name(path, api_name) + } + + fn check_sys(&self, kind: &str, api_name: &str) -> Result<(), AnyError> { + self.0.check_sys(kind, api_name) + } +} + +impl deno_fetch::FetchPermissions for PermissionsContainer { + #[inline(always)] + fn check_net_url( + &mut self, + url: &Url, + api_name: &str, + ) -> Result<(), AnyError> { + self.0.check_net_url(url, api_name) + } + + #[inline(always)] + fn check_read( + &mut self, + path: &Path, + api_name: &str, + ) -> Result<(), AnyError> { + self.0.check_read(path, api_name) + } +} + +impl deno_net::NetPermissions for PermissionsContainer { + #[inline(always)] + fn check_net<T: AsRef<str>>( + &mut self, + host: &(T, Option<u16>), + api_name: &str, + ) -> Result<(), AnyError> { + self.0.check_net(host, api_name) + } + + #[inline(always)] + fn check_read( + &mut self, + path: &Path, + api_name: &str, + ) -> Result<(), AnyError> { + self.0.check_read(path, api_name) + } + + #[inline(always)] + fn check_write( + &mut self, + path: &Path, + api_name: &str, + ) -> Result<(), AnyError> { + self.0.check_write(path, api_name) + } +} + +impl deno_web::TimersPermission for PermissionsContainer { + #[inline(always)] + fn allow_hrtime(&mut self) -> bool { + self.0.allow_hrtime() + } +} + +impl deno_websocket::WebSocketPermissions for PermissionsContainer { + #[inline(always)] + fn check_net_url( + &mut self, + url: &Url, + api_name: &str, + ) -> Result<(), AnyError> { + self.0.check_net_url(url, api_name) + } +} + +impl deno_fs::FsPermissions for PermissionsContainer { + fn check_read( + &mut self, + path: &Path, + api_name: &str, + ) -> Result<(), AnyError> { + self.0.check_read(path, api_name) + } + + fn check_read_blind( + &mut self, + path: &Path, + display: &str, + api_name: &str, + ) -> Result<(), AnyError> { + self.0.check_read_blind(path, display, api_name) + } + + fn check_write( + &mut self, + path: &Path, + api_name: &str, + ) -> Result<(), AnyError> { + self.0.check_write(path, api_name) + } + + fn check_write_partial( + &mut self, + path: &Path, + api_name: &str, + ) -> Result<(), AnyError> { + self.0.check_write_partial(path, api_name) + } + + fn check_write_blind( + &mut self, + p: &Path, + display: &str, + api_name: &str, + ) -> Result<(), AnyError> { + self.0.check_write_blind(p, display, api_name) + } + + fn check_read_all(&mut self, api_name: &str) -> Result<(), AnyError> { + self.0.check_read_all(api_name) + } + + fn check_write_all(&mut self, api_name: &str) -> Result<(), AnyError> { + self.0.check_write_all(api_name) + } +} + +// NOTE(bartlomieju): for now, NAPI uses `--allow-ffi` flag, but that might +// change in the future. +impl deno_napi::NapiPermissions for PermissionsContainer { + #[inline(always)] + fn check(&mut self, path: Option<&Path>) -> Result<(), AnyError> { + self.0.check_ffi(path) + } +} + +impl deno_ffi::FfiPermissions for PermissionsContainer { + #[inline(always)] + fn check_partial(&mut self, path: Option<&Path>) -> Result<(), AnyError> { + self.0.check_ffi_partial(path) + } +} + +impl deno_kv::sqlite::SqliteDbHandlerPermissions for PermissionsContainer { + #[inline(always)] + fn check_read(&mut self, p: &Path, api_name: &str) -> Result<(), AnyError> { + self.0.check_read(p, api_name) + } + + #[inline(always)] + fn check_write(&mut self, p: &Path, api_name: &str) -> Result<(), AnyError> { + self.0.check_write(p, api_name) + } +} + +impl deno_kv::remote::RemoteDbHandlerPermissions for PermissionsContainer { + #[inline(always)] + fn check_env(&mut self, var: &str) -> Result<(), AnyError> { + self.0.check_env(var) + } + + #[inline(always)] + fn check_net_url( + &mut self, + url: &Url, + api_name: &str, + ) -> Result<(), AnyError> { + self.0.check_net_url(url, api_name) + } +} diff --git a/runtime/permissions/Cargo.toml b/runtime/permissions/Cargo.toml new file mode 100644 index 000000000..8a0904bea --- /dev/null +++ b/runtime/permissions/Cargo.toml @@ -0,0 +1,28 @@ +# Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. + +[package] +name = "deno_permissions" +version = "0.1.0" +authors.workspace = true +edition.workspace = true +license.workspace = true +repository.workspace = true +description = "Provides the deno permissions implementation." + +[lib] +name = "deno_permissions" +path = "lib.rs" + +[dependencies] +console_static_text.workspace = true +deno_core.workspace = true +deno_terminal.workspace = true +libc.workspace = true +log.workspace = true +once_cell.workspace = true +serde.workspace = true +termcolor.workspace = true +which = "4.2.5" + +[target.'cfg(windows)'.dependencies] +winapi = { workspace = true, features = ["commapi", "knownfolders", "mswsock", "objbase", "psapi", "shlobj", "tlhelp32", "winbase", "winerror", "winuser", "winsock2"] } diff --git a/runtime/permissions/README.md b/runtime/permissions/README.md new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/runtime/permissions/README.md diff --git a/runtime/permissions/mod.rs b/runtime/permissions/lib.rs index 2cdbc6014..ca9d8084f 100644 --- a/runtime/permissions/mod.rs +++ b/runtime/permissions/lib.rs @@ -1,10 +1,11 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. -use crate::fs_util::resolve_from_cwd; +use deno_core::anyhow::Context; use deno_core::error::custom_error; use deno_core::error::type_error; use deno_core::error::uri_error; use deno_core::error::AnyError; +use deno_core::normalize_path; use deno_core::parking_lot::Mutex; use deno_core::serde::de; use deno_core::serde::Deserialize; @@ -15,7 +16,6 @@ use deno_core::url; use deno_core::url::Url; use deno_core::ModuleSpecifier; use deno_terminal::colors; -use log; use once_cell::sync::Lazy; use std::borrow::Cow; use std::collections::HashSet; @@ -28,7 +28,7 @@ use std::string::ToString; use std::sync::Arc; use which::which; -mod prompter; +pub mod prompter; use prompter::permission_prompt; use prompter::PromptResponse; use prompter::PERMISSION_EMOJI; @@ -36,6 +36,18 @@ use prompter::PERMISSION_EMOJI; pub use prompter::set_prompt_callbacks; pub use prompter::PromptCallback; +#[inline] +fn resolve_from_cwd(path: &Path) -> Result<PathBuf, AnyError> { + if path.is_absolute() { + Ok(normalize_path(path)) + } else { + #[allow(clippy::disallowed_methods)] + let cwd = std::env::current_dir() + .context("Failed to get current working directory")?; + Ok(normalize_path(cwd.join(path))) + } +} + static DEBUG_LOG_ENABLED: Lazy<bool> = Lazy::new(|| log::log_enabled!(log::Level::Debug)); @@ -1271,6 +1283,11 @@ impl PermissionsContainer { Self(Arc::new(Mutex::new(perms))) } + #[inline(always)] + pub fn allow_hrtime(&mut self) -> bool { + self.0.lock().hrtime.check().is_ok() + } + pub fn allow_all() -> Self { Self::new(Permissions::allow_all()) } @@ -1293,6 +1310,15 @@ impl PermissionsContainer { } #[inline(always)] + pub fn check_read_with_api_name( + &self, + path: &Path, + api_name: Option<&str>, + ) -> Result<(), AnyError> { + self.0.lock().read.check(path, api_name) + } + + #[inline(always)] pub fn check_read_blind( &mut self, path: &Path, @@ -1317,6 +1343,15 @@ impl PermissionsContainer { } #[inline(always)] + pub fn check_write_with_api_name( + &self, + path: &Path, + api_name: Option<&str>, + ) -> Result<(), AnyError> { + self.0.lock().write.check(path, api_name) + } + + #[inline(always)] pub fn check_write_all(&mut self, api_name: &str) -> Result<(), AnyError> { self.0.lock().write.check_all(Some(api_name)) } @@ -1332,6 +1367,15 @@ impl PermissionsContainer { } #[inline(always)] + pub fn check_write_partial( + &mut self, + path: &Path, + api_name: &str, + ) -> Result<(), AnyError> { + self.0.lock().write.check_partial(path, Some(api_name)) + } + + #[inline(always)] pub fn check_run( &mut self, cmd: &str, @@ -1346,11 +1390,7 @@ impl PermissionsContainer { } #[inline(always)] - pub fn check_sys( - &mut self, - kind: &str, - api_name: &str, - ) -> Result<(), AnyError> { + pub fn check_sys(&self, kind: &str, api_name: &str) -> Result<(), AnyError> { self.0.lock().sys.check(kind, Some(api_name)) } @@ -1363,11 +1403,9 @@ impl PermissionsContainer { pub fn check_env_all(&mut self) -> Result<(), AnyError> { self.0.lock().env.check_all() } -} -impl deno_node::NodePermissions for PermissionsContainer { #[inline(always)] - fn check_net_url( + pub fn check_net_url( &mut self, url: &Url, api_name: &str, @@ -1376,31 +1414,7 @@ impl deno_node::NodePermissions for PermissionsContainer { } #[inline(always)] - fn check_read_with_api_name( - &self, - path: &Path, - api_name: Option<&str>, - ) -> Result<(), AnyError> { - self.0.lock().read.check(path, api_name) - } - - #[inline(always)] - fn check_write_with_api_name( - &self, - path: &Path, - api_name: Option<&str>, - ) -> Result<(), AnyError> { - self.0.lock().write.check(path, api_name) - } - - fn check_sys(&self, kind: &str, api_name: &str) -> Result<(), AnyError> { - self.0.lock().sys.check(kind, Some(api_name)) - } -} - -impl deno_net::NetPermissions for PermissionsContainer { - #[inline(always)] - fn check_net<T: AsRef<str>>( + pub fn check_net<T: AsRef<str>>( &mut self, host: &(T, Option<u16>), api_name: &str, @@ -1409,155 +1423,16 @@ impl deno_net::NetPermissions for PermissionsContainer { } #[inline(always)] - fn check_read( - &mut self, - path: &Path, - api_name: &str, - ) -> Result<(), AnyError> { - self.0.lock().read.check(path, Some(api_name)) - } - - #[inline(always)] - fn check_write( - &mut self, - path: &Path, - api_name: &str, - ) -> Result<(), AnyError> { - self.0.lock().write.check(path, Some(api_name)) - } -} - -impl deno_fetch::FetchPermissions for PermissionsContainer { - #[inline(always)] - fn check_net_url( - &mut self, - url: &url::Url, - api_name: &str, - ) -> Result<(), AnyError> { - self.0.lock().net.check_url(url, Some(api_name)) - } - - #[inline(always)] - fn check_read( - &mut self, - path: &Path, - api_name: &str, - ) -> Result<(), AnyError> { - self.0.lock().read.check(path, Some(api_name)) - } -} - -impl deno_web::TimersPermission for PermissionsContainer { - #[inline(always)] - fn allow_hrtime(&mut self) -> bool { - self.0.lock().hrtime.check().is_ok() - } -} - -impl deno_websocket::WebSocketPermissions for PermissionsContainer { - #[inline(always)] - fn check_net_url( - &mut self, - url: &url::Url, - api_name: &str, - ) -> Result<(), AnyError> { - self.0.lock().net.check_url(url, Some(api_name)) - } -} - -impl deno_fs::FsPermissions for PermissionsContainer { - fn check_read( - &mut self, - path: &Path, - api_name: &str, - ) -> Result<(), AnyError> { - self.0.lock().read.check(path, Some(api_name)) - } - - fn check_read_blind( - &mut self, - path: &Path, - display: &str, - api_name: &str, - ) -> Result<(), AnyError> { - self.0.lock().read.check_blind(path, display, api_name) - } - - fn check_write( - &mut self, - path: &Path, - api_name: &str, - ) -> Result<(), AnyError> { - self.0.lock().write.check(path, Some(api_name)) - } - - fn check_write_partial( - &mut self, - path: &Path, - api_name: &str, - ) -> Result<(), AnyError> { - self.0.lock().write.check_partial(path, Some(api_name)) - } - - fn check_write_blind( - &mut self, - p: &Path, - display: &str, - api_name: &str, - ) -> Result<(), AnyError> { - self.0.lock().write.check_blind(p, display, api_name) - } - - fn check_read_all(&mut self, api_name: &str) -> Result<(), AnyError> { - self.0.lock().read.check_all(Some(api_name)) - } - - fn check_write_all(&mut self, api_name: &str) -> Result<(), AnyError> { - self.0.lock().write.check_all(Some(api_name)) - } -} - -// NOTE(bartlomieju): for now, NAPI uses `--allow-ffi` flag, but that might -// change in the future. -impl deno_napi::NapiPermissions for PermissionsContainer { - #[inline(always)] - fn check(&mut self, path: Option<&Path>) -> Result<(), AnyError> { + pub fn check_ffi(&mut self, path: Option<&Path>) -> Result<(), AnyError> { self.0.lock().ffi.check(path.unwrap(), None) } -} - -impl deno_ffi::FfiPermissions for PermissionsContainer { - #[inline(always)] - fn check_partial(&mut self, path: Option<&Path>) -> Result<(), AnyError> { - self.0.lock().ffi.check_partial(path) - } -} -impl deno_kv::sqlite::SqliteDbHandlerPermissions for PermissionsContainer { #[inline(always)] - fn check_read(&mut self, p: &Path, api_name: &str) -> Result<(), AnyError> { - self.0.lock().read.check(p, Some(api_name)) - } - - #[inline(always)] - fn check_write(&mut self, p: &Path, api_name: &str) -> Result<(), AnyError> { - self.0.lock().write.check(p, Some(api_name)) - } -} - -impl deno_kv::remote::RemoteDbHandlerPermissions for PermissionsContainer { - #[inline(always)] - fn check_env(&mut self, var: &str) -> Result<(), AnyError> { - self.0.lock().env.check(var) - } - - #[inline(always)] - fn check_net_url( + pub fn check_ffi_partial( &mut self, - url: &url::Url, - api_name: &str, + path: Option<&Path>, ) -> Result<(), AnyError> { - self.0.lock().net.check_url(url, Some(api_name)) + self.0.lock().ffi.check_partial(path) } } diff --git a/runtime/snapshot.rs b/runtime/snapshot.rs index edfef39c2..54652e1f1 100644 --- a/runtime/snapshot.rs +++ b/runtime/snapshot.rs @@ -19,7 +19,7 @@ use std::sync::Arc; #[derive(Clone)] struct Permissions; -impl deno_fetch::FetchPermissions for Permissions { +impl deno_websocket::WebSocketPermissions for Permissions { fn check_net_url( &mut self, _url: &deno_core::url::Url, @@ -27,17 +27,15 @@ impl deno_fetch::FetchPermissions for Permissions { ) -> Result<(), deno_core::error::AnyError> { unreachable!("snapshotting!") } +} - fn check_read( - &mut self, - _p: &Path, - _api_name: &str, - ) -> Result<(), deno_core::error::AnyError> { +impl deno_web::TimersPermission for Permissions { + fn allow_hrtime(&mut self) -> bool { unreachable!("snapshotting!") } } -impl deno_websocket::WebSocketPermissions for Permissions { +impl deno_fetch::FetchPermissions for Permissions { fn check_net_url( &mut self, _url: &deno_core::url::Url, @@ -45,10 +43,12 @@ impl deno_websocket::WebSocketPermissions for Permissions { ) -> Result<(), deno_core::error::AnyError> { unreachable!("snapshotting!") } -} -impl deno_web::TimersPermission for Permissions { - fn allow_hrtime(&mut self) -> bool { + fn check_read( + &mut self, + _p: &Path, + _api_name: &str, + ) -> Result<(), deno_core::error::AnyError> { unreachable!("snapshotting!") } } diff --git a/runtime/web_worker.rs b/runtime/web_worker.rs index f35d38921..eefb49023 100644 --- a/runtime/web_worker.rs +++ b/runtime/web_worker.rs @@ -390,6 +390,7 @@ impl WebWorker { enable_testing_features: bool, }, state = |state, options| { + state.put(options.permissions.0.clone()); state.put::<PermissionsContainer>(options.permissions); state.put(ops::TestingFeaturesEnabled(options.enable_testing_features)); }, diff --git a/runtime/worker.rs b/runtime/worker.rs index b9b03a957..20bd37afb 100644 --- a/runtime/worker.rs +++ b/runtime/worker.rs @@ -315,6 +315,9 @@ impl MainWorker { enable_testing_features: bool, }, state = |state, options| { + // Save the permissions container and the wrapper. + state.put(options.permissions.0.clone()); + // This is temporary until we migrate all exts/ to the deno_permissions crate. state.put::<PermissionsContainer>(options.permissions); state.put(ops::TestingFeaturesEnabled(options.enable_testing_features)); }, |