diff options
| author | David Sherret <dsherret@users.noreply.github.com> | 2024-09-16 21:39:37 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-09-16 21:39:37 +0100 |
| commit | 62e952559f600e72d7498c9b12f906cb0b1ba150 (patch) | |
| tree | 6dbcce6592973358ef4bf6341888b0bbbdb98cc5 /cli | |
| parent | e0b9c745c15720914f14996bf357d5b375e2dbd8 (diff) | |
refactor(permissions): split up Descriptor into Allow, Deny, and Query (#25508)
This makes the permission system more versatile.
Diffstat (limited to 'cli')
| -rw-r--r-- | cli/args/flags.rs | 103 | ||||
| -rw-r--r-- | cli/args/import_map.rs | 3 | ||||
| -rw-r--r-- | cli/args/mod.rs | 7 | ||||
| -rw-r--r-- | cli/cache/mod.rs | 8 | ||||
| -rw-r--r-- | cli/factory.rs | 53 | ||||
| -rw-r--r-- | cli/file_fetcher.rs | 166 | ||||
| -rw-r--r-- | cli/graph_container.rs | 4 | ||||
| -rw-r--r-- | cli/graph_util.rs | 6 | ||||
| -rw-r--r-- | cli/jsr.rs | 11 | ||||
| -rw-r--r-- | cli/lsp/config.rs | 24 | ||||
| -rw-r--r-- | cli/lsp/jsr.rs | 3 | ||||
| -rw-r--r-- | cli/lsp/npm.rs | 3 | ||||
| -rw-r--r-- | cli/lsp/registries.rs | 12 | ||||
| -rw-r--r-- | cli/lsp/testing/execution.rs | 15 | ||||
| -rw-r--r-- | cli/module_loader.rs | 4 | ||||
| -rw-r--r-- | cli/npm/byonm.rs | 2 | ||||
| -rw-r--r-- | cli/npm/managed/resolvers/common.rs | 3 | ||||
| -rw-r--r-- | cli/npm/mod.rs | 6 | ||||
| -rw-r--r-- | cli/ops/bench.rs | 19 | ||||
| -rw-r--r-- | cli/ops/testing.rs | 19 | ||||
| -rw-r--r-- | cli/standalone/mod.rs | 40 | ||||
| -rw-r--r-- | cli/tools/bench/mod.rs | 33 | ||||
| -rw-r--r-- | cli/tools/jupyter/mod.rs | 4 | ||||
| -rw-r--r-- | cli/tools/registry/pm/cache_deps.rs | 2 | ||||
| -rw-r--r-- | cli/tools/repl/mod.rs | 10 | ||||
| -rw-r--r-- | cli/tools/run/mod.rs | 18 | ||||
| -rw-r--r-- | cli/tools/serve.rs | 9 | ||||
| -rw-r--r-- | cli/tools/test/mod.rs | 40 | ||||
| -rw-r--r-- | cli/worker.rs | 79 |
29 files changed, 345 insertions, 361 deletions
diff --git a/cli/args/flags.rs b/cli/args/flags.rs index f7502b706..f832c2a62 100644 --- a/cli/args/flags.rs +++ b/cli/args/flags.rs @@ -32,7 +32,6 @@ use deno_core::normalize_path; use deno_core::resolve_url_or_path; use deno_core::url::Url; use deno_graph::GraphKind; -use deno_runtime::colors; use deno_runtime::deno_permissions::parse_sys_kind; use deno_runtime::deno_permissions::PermissionsOptions; use log::debug; @@ -661,107 +660,25 @@ impl PermissionFlags { || self.deny_write.is_some() } - pub fn to_options( - &self, - // will be None when `deno compile` can't resolve the cwd - initial_cwd: Option<&Path>, - ) -> Result<PermissionsOptions, AnyError> { - fn convert_option_str_to_path_buf( - flag: &Option<Vec<String>>, - initial_cwd: Option<&Path>, - ) -> Result<Option<Vec<PathBuf>>, AnyError> { - let Some(paths) = &flag else { - return Ok(None); - }; - - let mut new_paths = Vec::with_capacity(paths.len()); - for path in paths { - if let Some(initial_cwd) = initial_cwd { - new_paths.push(initial_cwd.join(path)) - } else { - let path = PathBuf::from(path); - if path.is_absolute() { - new_paths.push(path); - } else { - bail!("Could not resolve relative permission path '{}' when current working directory could not be resolved.", path.display()) - } - } - } - Ok(Some(new_paths)) - } - - fn resolve_allow_run( - allow_run: &[String], - ) -> Result<Vec<PathBuf>, AnyError> { - let mut new_allow_run = Vec::with_capacity(allow_run.len()); - for command_name in allow_run { - if command_name.is_empty() { - bail!("Empty command name not allowed in --allow-run=...") - } - let command_path_result = which::which(command_name); - match command_path_result { - Ok(command_path) => new_allow_run.push(command_path), - Err(err) => { - log::info!( - "{} Failed to resolve '{}' for allow-run: {}", - colors::gray("Info"), - command_name, - err - ); - } - } - } - Ok(new_allow_run) - } - - let mut deny_write = - convert_option_str_to_path_buf(&self.deny_write, initial_cwd)?; - let allow_run = self - .allow_run - .as_ref() - .and_then(|raw_allow_run| match resolve_allow_run(raw_allow_run) { - Ok(resolved_allow_run) => { - if resolved_allow_run.is_empty() && !raw_allow_run.is_empty() { - None // convert to no permissions if now empty - } else { - Some(Ok(resolved_allow_run)) - } - } - Err(err) => Some(Err(err)), - }) - .transpose()?; - // add the allow_run list to deno_write - if let Some(allow_run_vec) = &allow_run { - if !allow_run_vec.is_empty() { - let deno_write = deny_write.get_or_insert_with(Vec::new); - deno_write.extend(allow_run_vec.iter().cloned()); - } - } - - Ok(PermissionsOptions { + pub fn to_options(&self) -> PermissionsOptions { + PermissionsOptions { allow_all: self.allow_all, allow_env: self.allow_env.clone(), deny_env: self.deny_env.clone(), allow_net: self.allow_net.clone(), deny_net: self.deny_net.clone(), - allow_ffi: convert_option_str_to_path_buf(&self.allow_ffi, initial_cwd)?, - deny_ffi: convert_option_str_to_path_buf(&self.deny_ffi, initial_cwd)?, - allow_read: convert_option_str_to_path_buf( - &self.allow_read, - initial_cwd, - )?, - deny_read: convert_option_str_to_path_buf(&self.deny_read, initial_cwd)?, - allow_run, + allow_ffi: self.allow_ffi.clone(), + deny_ffi: self.deny_ffi.clone(), + allow_read: self.allow_read.clone(), + deny_read: self.deny_read.clone(), + allow_run: self.allow_run.clone(), deny_run: self.deny_run.clone(), allow_sys: self.allow_sys.clone(), deny_sys: self.deny_sys.clone(), - allow_write: convert_option_str_to_path_buf( - &self.allow_write, - initial_cwd, - )?, - deny_write, + allow_write: self.allow_write.clone(), + deny_write: self.deny_write.clone(), prompt: !resolve_no_prompt(self), - }) + } } } diff --git a/cli/args/import_map.rs b/cli/args/import_map.rs index 7a16ab215..ff2f15871 100644 --- a/cli/args/import_map.rs +++ b/cli/args/import_map.rs @@ -3,7 +3,6 @@ use deno_core::error::AnyError; use deno_core::serde_json; use deno_core::url::Url; -use deno_runtime::deno_permissions::PermissionsContainer; use crate::file_fetcher::FileFetcher; @@ -17,7 +16,7 @@ pub async fn resolve_import_map_value_from_specifier( Ok(serde_json::from_str(&data_url_text)?) } else { let file = file_fetcher - .fetch(specifier, &PermissionsContainer::allow_all()) + .fetch_bypass_permissions(specifier) .await? .into_text_decoded()?; Ok(serde_json::from_str(&file.source)?) diff --git a/cli/args/mod.rs b/cli/args/mod.rs index 7d885295e..0e4004a53 100644 --- a/cli/args/mod.rs +++ b/cli/args/mod.rs @@ -27,7 +27,6 @@ use deno_npm::npm_rc::NpmRc; use deno_npm::npm_rc::ResolvedNpmRc; use deno_npm::resolution::ValidSerializedNpmResolutionSnapshot; use deno_npm::NpmSystemInfo; -use deno_runtime::deno_permissions::PermissionsContainer; use deno_semver::npm::NpmPackageReqReference; use import_map::resolve_import_map_value_from_specifier; @@ -1082,7 +1081,7 @@ impl CliOptions { let specifier = specifier.clone(); async move { let file = file_fetcher - .fetch(&specifier, &PermissionsContainer::allow_all()) + .fetch_bypass_permissions(&specifier) .await? .into_text_decoded()?; Ok(file.source.to_string()) @@ -1501,8 +1500,8 @@ impl CliOptions { &self.flags.permissions } - pub fn permissions_options(&self) -> Result<PermissionsOptions, AnyError> { - self.flags.permissions.to_options(Some(&self.initial_cwd)) + pub fn permissions_options(&self) -> PermissionsOptions { + self.flags.permissions.to_options() } pub fn reload_flag(&self) -> bool { diff --git a/cli/cache/mod.rs b/cli/cache/mod.rs index 3b4e27760..86b65bc53 100644 --- a/cli/cache/mod.rs +++ b/cli/cache/mod.rs @@ -4,6 +4,7 @@ use crate::args::CacheSetting; use crate::errors::get_error_class_name; use crate::file_fetcher::FetchNoFollowOptions; use crate::file_fetcher::FetchOptions; +use crate::file_fetcher::FetchPermissionsOption; use crate::file_fetcher::FileFetcher; use crate::file_fetcher::FileOrRedirect; use crate::npm::CliNpmResolver; @@ -18,7 +19,6 @@ use deno_graph::source::CacheInfo; use deno_graph::source::LoadFuture; use deno_graph::source::LoadResponse; use deno_graph::source::Loader; -use deno_runtime::deno_permissions::PermissionsContainer; use std::collections::HashMap; use std::path::Path; use std::path::PathBuf; @@ -112,7 +112,7 @@ pub struct FetchCacher { global_http_cache: Arc<GlobalHttpCache>, npm_resolver: Arc<dyn CliNpmResolver>, module_info_cache: Arc<ModuleInfoCache>, - permissions: PermissionsContainer, + permissions: FetchPermissionsOption, cache_info_enabled: bool, } @@ -123,7 +123,7 @@ impl FetchCacher { global_http_cache: Arc<GlobalHttpCache>, npm_resolver: Arc<dyn CliNpmResolver>, module_info_cache: Arc<ModuleInfoCache>, - permissions: PermissionsContainer, + permissions: FetchPermissionsOption, ) -> Self { Self { file_fetcher, @@ -230,7 +230,7 @@ impl Loader for FetchCacher { .fetch_no_follow_with_options(FetchNoFollowOptions { fetch_options: FetchOptions { specifier: &specifier, - permissions: &permissions, + permissions: permissions.as_ref(), maybe_accept: None, maybe_cache_setting: maybe_cache_setting.as_ref(), }, diff --git a/cli/factory.rs b/cli/factory.rs index 1ec2104ed..fe6d5b92a 100644 --- a/cli/factory.rs +++ b/cli/factory.rs @@ -65,10 +65,13 @@ use deno_core::FeatureChecker; use deno_runtime::deno_fs; use deno_runtime::deno_node::DenoFsNodeResolverEnv; use deno_runtime::deno_node::NodeResolver; +use deno_runtime::deno_permissions::Permissions; +use deno_runtime::deno_permissions::PermissionsContainer; use deno_runtime::deno_tls::rustls::RootCertStore; use deno_runtime::deno_tls::RootCertStoreProvider; use deno_runtime::deno_web::BlobStore; use deno_runtime::inspector_server::InspectorServer; +use deno_runtime::permissions::RuntimePermissionDescriptorParser; use log::warn; use node_resolver::analyze::NodeCodeTranslator; use once_cell::sync::OnceCell; @@ -181,6 +184,7 @@ struct CliFactoryServices { node_code_translator: Deferred<Arc<CliNodeCodeTranslator>>, node_resolver: Deferred<Arc<NodeResolver>>, npm_resolver: Deferred<Arc<dyn CliNpmResolver>>, + permission_desc_parser: Deferred<Arc<RuntimePermissionDescriptorParser>>, sloppy_imports_resolver: Deferred<Option<Arc<SloppyImportsResolver>>>, text_only_progress_bar: Deferred<ProgressBar>, type_checker: Deferred<Arc<TypeChecker>>, @@ -708,6 +712,15 @@ impl CliFactory { .await } + pub fn permission_desc_parser( + &self, + ) -> Result<&Arc<RuntimePermissionDescriptorParser>, AnyError> { + self.services.permission_desc_parser.get_or_try_init(|| { + let fs = self.fs().clone(); + Ok(Arc::new(RuntimePermissionDescriptorParser::new(fs))) + }) + } + pub fn feature_checker(&self) -> Result<&Arc<FeatureChecker>, AnyError> { self.services.feature_checker.get_or_try_init(|| { let cli_options = self.cli_options()?; @@ -739,6 +752,17 @@ impl CliFactory { )) } + pub fn create_permissions_container( + &self, + ) -> Result<PermissionsContainer, AnyError> { + let desc_parser = self.permission_desc_parser()?.clone(); + let permissions = Permissions::from_options( + desc_parser.as_ref(), + &self.cli_options()?.permissions_options(), + )?; + Ok(PermissionsContainer::new(desc_parser, permissions)) + } + pub async fn create_cli_main_worker_factory( &self, ) -> Result<CliMainWorkerFactory, AnyError> { @@ -754,11 +778,17 @@ impl CliFactory { }; Ok(CliMainWorkerFactory::new( - StorageKeyResolver::from_options(cli_options), - cli_options.sub_command().clone(), - npm_resolver.clone(), - node_resolver.clone(), self.blob_store().clone(), + if cli_options.code_cache_enabled() { + Some(self.code_cache()?.clone()) + } else { + None + }, + self.feature_checker()?.clone(), + self.fs().clone(), + maybe_file_watcher_communicator, + self.maybe_inspector_server()?.clone(), + cli_options.maybe_lockfile().cloned(), Box::new(CliModuleLoaderFactory::new( cli_options, if cli_options.code_cache_enabled() { @@ -779,17 +809,12 @@ impl CliFactory { self.parsed_source_cache().clone(), self.resolver().await?.clone(), )), + node_resolver.clone(), + npm_resolver.clone(), + self.permission_desc_parser()?.clone(), self.root_cert_store_provider().clone(), - self.fs().clone(), - maybe_file_watcher_communicator, - self.maybe_inspector_server()?.clone(), - cli_options.maybe_lockfile().cloned(), - self.feature_checker()?.clone(), - if cli_options.code_cache_enabled() { - Some(self.code_cache()?.clone()) - } else { - None - }, + StorageKeyResolver::from_options(cli_options), + cli_options.sub_command().clone(), self.create_cli_main_worker_options()?, )) } diff --git a/cli/file_fetcher.rs b/cli/file_fetcher.rs index ace4d3c7e..ca8fcbee4 100644 --- a/cli/file_fetcher.rs +++ b/cli/file_fetcher.rs @@ -161,9 +161,38 @@ fn get_validated_scheme( } } +#[derive(Debug, Copy, Clone)] +pub enum FetchPermissionsOptionRef<'a> { + AllowAll, + Container(&'a PermissionsContainer), +} + +#[derive(Debug, Clone)] +pub enum FetchPermissionsOption { + AllowAll, + Container(PermissionsContainer), +} + +impl FetchPermissionsOption { + pub fn as_ref(&self) -> FetchPermissionsOptionRef { + match self { + FetchPermissionsOption::AllowAll => FetchPermissionsOptionRef::AllowAll, + FetchPermissionsOption::Container(container) => { + FetchPermissionsOptionRef::Container(container) + } + } + } +} + +impl From<PermissionsContainer> for FetchPermissionsOption { + fn from(value: PermissionsContainer) -> Self { + Self::Container(value) + } +} + pub struct FetchOptions<'a> { pub specifier: &'a ModuleSpecifier, - pub permissions: &'a PermissionsContainer, + pub permissions: FetchPermissionsOptionRef<'a>, pub maybe_accept: Option<&'a str>, pub maybe_cache_setting: Option<&'a CacheSetting>, } @@ -515,13 +544,35 @@ impl FileFetcher { } } + #[inline(always)] + pub async fn fetch_bypass_permissions( + &self, + specifier: &ModuleSpecifier, + ) -> Result<File, AnyError> { + self + .fetch_inner(specifier, FetchPermissionsOptionRef::AllowAll) + .await + } + /// Fetch a source file and asynchronously return it. + #[allow(dead_code)] // todo(25469): undo when merging + #[inline(always)] pub async fn fetch( &self, specifier: &ModuleSpecifier, permissions: &PermissionsContainer, ) -> Result<File, AnyError> { self + .fetch_inner(specifier, FetchPermissionsOptionRef::Container(permissions)) + .await + } + + async fn fetch_inner( + &self, + specifier: &ModuleSpecifier, + permissions: FetchPermissionsOptionRef<'_>, + ) -> Result<File, AnyError> { + self .fetch_with_options(FetchOptions { specifier, permissions, @@ -583,7 +634,14 @@ impl FileFetcher { specifier ); let scheme = get_validated_scheme(specifier)?; - options.permissions.check_specifier(specifier)?; + match options.permissions { + FetchPermissionsOptionRef::AllowAll => { + // allow + } + FetchPermissionsOptionRef::Container(permissions) => { + permissions.check_specifier(specifier)?; + } + } if let Some(file) = self.memory_files.get(specifier) { Ok(FileOrRedirect::File(file)) } else if scheme == "file" { @@ -684,9 +742,7 @@ mod tests { async fn test_fetch(specifier: &ModuleSpecifier) -> (File, FileFetcher) { let (file_fetcher, _) = setup(CacheSetting::ReloadAll, None); - let result = file_fetcher - .fetch(specifier, &PermissionsContainer::allow_all()) - .await; + let result = file_fetcher.fetch_bypass_permissions(specifier).await; assert!(result.is_ok()); (result.unwrap(), file_fetcher) } @@ -700,7 +756,7 @@ mod tests { .fetch_with_options_and_max_redirect( FetchOptions { specifier, - permissions: &PermissionsContainer::allow_all(), + permissions: FetchPermissionsOptionRef::AllowAll, maybe_accept: None, maybe_cache_setting: Some(&file_fetcher.cache_setting), }, @@ -796,9 +852,7 @@ mod tests { }; file_fetcher.insert_memory_files(file.clone()); - let result = file_fetcher - .fetch(&specifier, &PermissionsContainer::allow_all()) - .await; + let result = file_fetcher.fetch_bypass_permissions(&specifier).await; assert!(result.is_ok()); let result_file = result.unwrap(); assert_eq!(result_file, file); @@ -809,9 +863,7 @@ mod tests { let (file_fetcher, _) = setup(CacheSetting::Use, None); let specifier = resolve_url("data:application/typescript;base64,ZXhwb3J0IGNvbnN0IGEgPSAiYSI7CgpleHBvcnQgZW51bSBBIHsKICBBLAogIEIsCiAgQywKfQo=").unwrap(); - let result = file_fetcher - .fetch(&specifier, &PermissionsContainer::allow_all()) - .await; + let result = file_fetcher.fetch_bypass_permissions(&specifier).await; assert!(result.is_ok()); let file = result.unwrap().into_text_decoded().unwrap(); assert_eq!( @@ -840,9 +892,7 @@ mod tests { None, ); - let result = file_fetcher - .fetch(&specifier, &PermissionsContainer::allow_all()) - .await; + let result = file_fetcher.fetch_bypass_permissions(&specifier).await; assert!(result.is_ok()); let file = result.unwrap().into_text_decoded().unwrap(); assert_eq!( @@ -862,9 +912,7 @@ mod tests { let specifier = ModuleSpecifier::parse("http://localhost:4545/subdir/mod2.ts").unwrap(); - let result = file_fetcher - .fetch(&specifier, &PermissionsContainer::allow_all()) - .await; + let result = file_fetcher.fetch_bypass_permissions(&specifier).await; assert!(result.is_ok()); let file = result.unwrap().into_text_decoded().unwrap(); assert_eq!( @@ -882,9 +930,7 @@ mod tests { .set(&specifier, headers.clone(), file.source.as_bytes()) .unwrap(); - let result = file_fetcher_01 - .fetch(&specifier, &PermissionsContainer::allow_all()) - .await; + let result = file_fetcher_01.fetch_bypass_permissions(&specifier).await; assert!(result.is_ok()); let file = result.unwrap().into_text_decoded().unwrap(); assert_eq!( @@ -908,9 +954,7 @@ mod tests { .set(&specifier, headers.clone(), file.source.as_bytes()) .unwrap(); - let result = file_fetcher_02 - .fetch(&specifier, &PermissionsContainer::allow_all()) - .await; + let result = file_fetcher_02.fetch_bypass_permissions(&specifier).await; assert!(result.is_ok()); let file = result.unwrap().into_text_decoded().unwrap(); assert_eq!( @@ -933,9 +977,7 @@ mod tests { Default::default(), None, ); - let result = file_fetcher - .fetch(&specifier, &PermissionsContainer::allow_all()) - .await; + let result = file_fetcher.fetch_bypass_permissions(&specifier).await; assert!(result.is_ok()); let file = result.unwrap().into_text_decoded().unwrap(); assert_eq!( @@ -966,9 +1008,7 @@ mod tests { None, ); - let result = file_fetcher - .fetch(&specifier, &PermissionsContainer::allow_all()) - .await; + let result = file_fetcher.fetch_bypass_permissions(&specifier).await; assert!(result.is_ok()); let cache_key = file_fetcher.http_cache.cache_item_key(&specifier).unwrap(); @@ -1002,9 +1042,7 @@ mod tests { Default::default(), None, ); - let result = file_fetcher - .fetch(&specifier, &PermissionsContainer::allow_all()) - .await; + let result = file_fetcher.fetch_bypass_permissions(&specifier).await; assert!(result.is_ok()); let cache_key = @@ -1041,9 +1079,7 @@ mod tests { resolve_url("http://localhost:4545/subdir/redirects/redirect1.js") .unwrap(); - let result = file_fetcher - .fetch(&specifier, &PermissionsContainer::allow_all()) - .await; + let result = file_fetcher.fetch_bypass_permissions(&specifier).await; assert!(result.is_ok()); let file = result.unwrap(); assert_eq!(file.specifier, redirected_specifier); @@ -1082,9 +1118,7 @@ mod tests { resolve_url("http://localhost:4545/subdir/redirects/redirect1.js") .unwrap(); - let result = file_fetcher - .fetch(&specifier, &PermissionsContainer::allow_all()) - .await; + let result = file_fetcher.fetch_bypass_permissions(&specifier).await; assert!(result.is_ok()); let file = result.unwrap(); assert_eq!(file.specifier, redirected_02_specifier); @@ -1142,9 +1176,7 @@ mod tests { None, ); - let result = file_fetcher - .fetch(&specifier, &PermissionsContainer::allow_all()) - .await; + let result = file_fetcher.fetch_bypass_permissions(&specifier).await; assert!(result.is_ok()); let cache_key = file_fetcher @@ -1182,7 +1214,7 @@ mod tests { None, ); let result = file_fetcher - .fetch(&redirected_specifier, &PermissionsContainer::allow_all()) + .fetch_bypass_permissions(&redirected_specifier) .await; assert!(result.is_ok()); @@ -1223,7 +1255,7 @@ mod tests { .fetch_with_options_and_max_redirect( FetchOptions { specifier: &specifier, - permissions: &PermissionsContainer::allow_all(), + permissions: FetchPermissionsOptionRef::AllowAll, maybe_accept: None, maybe_cache_setting: Some(&file_fetcher.cache_setting), }, @@ -1236,7 +1268,7 @@ mod tests { .fetch_with_options_and_max_redirect( FetchOptions { specifier: &specifier, - permissions: &PermissionsContainer::allow_all(), + permissions: FetchPermissionsOptionRef::AllowAll, maybe_accept: None, maybe_cache_setting: Some(&file_fetcher.cache_setting), }, @@ -1264,9 +1296,7 @@ mod tests { resolve_url("http://localhost:4550/subdir/redirects/redirect1.js") .unwrap(); - let result = file_fetcher - .fetch(&specifier, &PermissionsContainer::allow_all()) - .await; + let result = file_fetcher.fetch_bypass_permissions(&specifier).await; assert!(result.is_ok()); let file = result.unwrap(); assert_eq!(file.specifier, redirected_specifier); @@ -1310,9 +1340,7 @@ mod tests { let specifier = resolve_url("http://localhost:4545/run/002_hello.ts").unwrap(); - let result = file_fetcher - .fetch(&specifier, &PermissionsContainer::allow_all()) - .await; + let result = file_fetcher.fetch_bypass_permissions(&specifier).await; assert!(result.is_err()); let err = result.unwrap_err(); assert_eq!(get_custom_error_class(&err), Some("NoRemote")); @@ -1343,22 +1371,16 @@ mod tests { let specifier = resolve_url("http://localhost:4545/run/002_hello.ts").unwrap(); - let result = file_fetcher_01 - .fetch(&specifier, &PermissionsContainer::allow_all()) - .await; + let result = file_fetcher_01.fetch_bypass_permissions(&specifier).await; assert!(result.is_err()); let err = result.unwrap_err(); assert_eq!(err.to_string(), "Specifier not found in cache: \"http://localhost:4545/run/002_hello.ts\", --cached-only is specified."); assert_eq!(get_custom_error_class(&err), Some("NotCached")); - let result = file_fetcher_02 - .fetch(&specifier, &PermissionsContainer::allow_all()) - .await; + let result = file_fetcher_02.fetch_bypass_permissions(&specifier).await; assert!(result.is_ok()); - let result = file_fetcher_01 - .fetch(&specifier, &PermissionsContainer::allow_all()) - .await; + let result = file_fetcher_01.fetch_bypass_permissions(&specifier).await; assert!(result.is_ok()); } @@ -1368,17 +1390,13 @@ mod tests { let fixture_path = temp_dir.path().join("mod.ts"); let specifier = ModuleSpecifier::from_file_path(&fixture_path).unwrap(); fs::write(fixture_path.clone(), r#"console.log("hello deno");"#).unwrap(); - let result = file_fetcher - .fetch(&specifier, &PermissionsContainer::allow_all()) - .await; + let result = file_fetcher.fetch_bypass_permissions(&specifier).await; assert!(result.is_ok()); let file = result.unwrap().into_text_decoded().unwrap(); assert_eq!(&*file.source, r#"console.log("hello deno");"#); fs::write(fixture_path, r#"console.log("goodbye deno");"#).unwrap(); - let result = file_fetcher - .fetch(&specifier, &PermissionsContainer::allow_all()) - .await; + let result = file_fetcher.fetch_bypass_permissions(&specifier).await; assert!(result.is_ok()); let file = result.unwrap().into_text_decoded().unwrap(); assert_eq!(&*file.source, r#"console.log("goodbye deno");"#); @@ -1392,18 +1410,14 @@ mod tests { setup(CacheSetting::RespectHeaders, Some(temp_dir.clone())); let specifier = ModuleSpecifier::parse("http://localhost:4545/dynamic").unwrap(); - let result = file_fetcher - .fetch(&specifier, &PermissionsContainer::allow_all()) - .await; + let result = file_fetcher.fetch_bypass_permissions(&specifier).await; assert!(result.is_ok()); let file = result.unwrap(); let first = file.source; let (file_fetcher, _) = setup(CacheSetting::RespectHeaders, Some(temp_dir.clone())); - let result = file_fetcher - .fetch(&specifier, &PermissionsContainer::allow_all()) - .await; + let result = file_fetcher.fetch_bypass_permissions(&specifier).await; assert!(result.is_ok()); let file = result.unwrap(); let second = file.source; @@ -1419,18 +1433,14 @@ mod tests { setup(CacheSetting::RespectHeaders, Some(temp_dir.clone())); let specifier = ModuleSpecifier::parse("http://localhost:4545/dynamic_cache").unwrap(); - let result = file_fetcher - .fetch(&specifier, &PermissionsContainer::allow_all()) - .await; + let result = file_fetcher.fetch_bypass_permissions(&specifier).await; assert!(result.is_ok()); let file = result.unwrap(); let first = file.source; let (file_fetcher, _) = setup(CacheSetting::RespectHeaders, Some(temp_dir.clone())); - let result = file_fetcher - .fetch(&specifier, &PermissionsContainer::allow_all()) - .await; + let result = file_fetcher.fetch_bypass_permissions(&specifier).await; assert!(result.is_ok()); let file = result.unwrap(); let second = file.source; diff --git a/cli/graph_container.rs b/cli/graph_container.rs index 9f71045c6..9f049946f 100644 --- a/cli/graph_container.rs +++ b/cli/graph_container.rs @@ -9,9 +9,9 @@ use deno_core::error::AnyError; use deno_core::parking_lot::RwLock; use deno_graph::ModuleGraph; use deno_runtime::colors; -use deno_runtime::deno_permissions::PermissionsContainer; use crate::args::CliOptions; +use crate::file_fetcher::FetchPermissionsOption; use crate::module_loader::ModuleLoadPreparer; use crate::util::fs::collect_specifiers; use crate::util::path::is_script_ext; @@ -75,7 +75,7 @@ impl MainModuleGraphContainer { specifiers, false, self.cli_options.ts_type_lib_window(), - PermissionsContainer::allow_all(), + FetchPermissionsOption::AllowAll, ) .await?; graph_permit.commit(); diff --git a/cli/graph_util.rs b/cli/graph_util.rs index d73733123..cb2e1bde8 100644 --- a/cli/graph_util.rs +++ b/cli/graph_util.rs @@ -11,6 +11,7 @@ use crate::cache::ModuleInfoCache; use crate::cache::ParsedSourceCache; use crate::colors; use crate::errors::get_error_class_name; +use crate::file_fetcher::FetchPermissionsOption; use crate::file_fetcher::FileFetcher; use crate::npm::CliNpmResolver; use crate::resolver::CliGraphResolver; @@ -41,7 +42,6 @@ use deno_graph::ResolutionError; use deno_graph::SpecifierError; use deno_runtime::deno_fs::FileSystem; use deno_runtime::deno_node; -use deno_runtime::deno_permissions::PermissionsContainer; use deno_semver::jsr::JsrDepPackageReq; use deno_semver::package::PackageNv; use deno_semver::Version; @@ -670,12 +670,12 @@ impl ModuleGraphBuilder { /// Creates the default loader used for creating a graph. pub fn create_graph_loader(&self) -> cache::FetchCacher { - self.create_fetch_cacher(PermissionsContainer::allow_all()) + self.create_fetch_cacher(FetchPermissionsOption::AllowAll) } pub fn create_fetch_cacher( &self, - permissions: PermissionsContainer, + permissions: FetchPermissionsOption, ) -> cache::FetchCacher { cache::FetchCacher::new( self.file_fetcher.clone(), diff --git a/cli/jsr.rs b/cli/jsr.rs index 87a54af22..767d304d6 100644 --- a/cli/jsr.rs +++ b/cli/jsr.rs @@ -6,7 +6,6 @@ use dashmap::DashMap; use deno_core::serde_json; use deno_graph::packages::JsrPackageInfo; use deno_graph::packages::JsrPackageVersionInfo; -use deno_runtime::deno_permissions::PermissionsContainer; use deno_semver::package::PackageNv; use deno_semver::package::PackageReq; use std::sync::Arc; @@ -68,10 +67,7 @@ impl JsrFetchResolver { let file_fetcher = self.file_fetcher.clone(); // spawn due to the lsp's `Send` requirement let file = deno_core::unsync::spawn(async move { - file_fetcher - .fetch(&meta_url, &PermissionsContainer::allow_all()) - .await - .ok() + file_fetcher.fetch_bypass_permissions(&meta_url).await.ok() }) .await .ok()??; @@ -96,10 +92,7 @@ impl JsrFetchResolver { let file_fetcher = self.file_fetcher.clone(); // spawn due to the lsp's `Send` requirement let file = deno_core::unsync::spawn(async move { - file_fetcher - .fetch(&meta_url, &PermissionsContainer::allow_all()) - .await - .ok() + file_fetcher.fetch_bypass_permissions(&meta_url).await.ok() }) .await .ok()??; diff --git a/cli/lsp/config.rs b/cli/lsp/config.rs index c5d064285..f69cae435 100644 --- a/cli/lsp/config.rs +++ b/cli/lsp/config.rs @@ -37,7 +37,6 @@ use deno_lint::linter::LintConfig as DenoLintConfig; use deno_npm::npm_rc::ResolvedNpmRc; use deno_package_json::PackageJsonCache; use deno_runtime::deno_node::PackageJson; -use deno_runtime::deno_permissions::PermissionsContainer; use deno_runtime::fs_util::specifier_to_file_path; use indexmap::IndexSet; use lsp_types::ClientCapabilities; @@ -1509,17 +1508,16 @@ impl ConfigData { ConfigWatchedFileType::ImportMap, ); // spawn due to the lsp's `Send` requirement - let fetch_result = deno_core::unsync::spawn({ - let file_fetcher = file_fetcher.cloned().unwrap(); - let import_map_url = import_map_url.clone(); - async move { - file_fetcher - .fetch(&import_map_url, &PermissionsContainer::allow_all()) - .await - } - }) - .await - .unwrap(); + let fetch_result = + deno_core::unsync::spawn({ + let file_fetcher = file_fetcher.cloned().unwrap(); + let import_map_url = import_map_url.clone(); + async move { + file_fetcher.fetch_bypass_permissions(&import_map_url).await + } + }) + .await + .unwrap(); let value_result = fetch_result.and_then(|f| { serde_json::from_slice::<Value>(&f.source).map_err(|e| e.into()) @@ -1558,7 +1556,7 @@ impl ConfigData { let file_fetcher = file_fetcher.clone().unwrap(); async move { let file = file_fetcher - .fetch(&specifier, &PermissionsContainer::allow_all()) + .fetch_bypass_permissions(&specifier) .await? .into_text_decoded()?; Ok(file.source.to_string()) diff --git a/cli/lsp/jsr.rs b/cli/lsp/jsr.rs index 6c591637c..9a738ec28 100644 --- a/cli/lsp/jsr.rs +++ b/cli/lsp/jsr.rs @@ -14,7 +14,6 @@ use deno_graph::packages::JsrPackageInfo; use deno_graph::packages::JsrPackageInfoVersion; use deno_graph::packages::JsrPackageVersionInfo; use deno_graph::ModuleSpecifier; -use deno_runtime::deno_permissions::PermissionsContainer; use deno_semver::jsr::JsrPackageReqReference; use deno_semver::package::PackageNv; use deno_semver::package::PackageReq; @@ -311,7 +310,7 @@ impl PackageSearchApi for CliJsrSearchApi { // spawn due to the lsp's `Send` requirement let file = deno_core::unsync::spawn(async move { file_fetcher - .fetch(&search_url, &PermissionsContainer::allow_all()) + .fetch_bypass_permissions(&search_url) .await? .into_text_decoded() }) diff --git a/cli/lsp/npm.rs b/cli/lsp/npm.rs index e5aa33744..8bdeb7e7d 100644 --- a/cli/lsp/npm.rs +++ b/cli/lsp/npm.rs @@ -4,7 +4,6 @@ use dashmap::DashMap; use deno_core::anyhow::anyhow; use deno_core::error::AnyError; use deno_core::serde_json; -use deno_runtime::deno_permissions::PermissionsContainer; use deno_semver::package::PackageNv; use deno_semver::Version; use serde::Deserialize; @@ -55,7 +54,7 @@ impl PackageSearchApi for CliNpmSearchApi { let file_fetcher = self.file_fetcher.clone(); let file = deno_core::unsync::spawn(async move { file_fetcher - .fetch(&search_url, &PermissionsContainer::allow_all()) + .fetch_bypass_permissions(&search_url) .await? .into_text_decoded() }) diff --git a/cli/lsp/registries.rs b/cli/lsp/registries.rs index c709831d4..5f7ce0082 100644 --- a/cli/lsp/registries.rs +++ b/cli/lsp/registries.rs @@ -16,6 +16,7 @@ use crate::args::CacheSetting; use crate::cache::GlobalHttpCache; use crate::cache::HttpCache; use crate::file_fetcher::FetchOptions; +use crate::file_fetcher::FetchPermissionsOptionRef; use crate::file_fetcher::FileFetcher; use crate::http_util::HttpClientProvider; @@ -30,7 +31,6 @@ use deno_core::url::Position; use deno_core::url::Url; use deno_core::ModuleSpecifier; use deno_graph::Dependency; -use deno_runtime::deno_permissions::PermissionsContainer; use log::error; use once_cell::sync::Lazy; use std::borrow::Cow; @@ -481,7 +481,7 @@ impl ModuleRegistry { file_fetcher .fetch_with_options(FetchOptions { specifier: &specifier, - permissions: &PermissionsContainer::allow_all(), + permissions: FetchPermissionsOptionRef::AllowAll, maybe_accept: Some("application/vnd.deno.reg.v2+json, application/vnd.deno.reg.v1+json;q=0.9, application/json;q=0.8"), maybe_cache_setting: None, }) @@ -584,7 +584,7 @@ impl ModuleRegistry { let file = deno_core::unsync::spawn({ async move { file_fetcher - .fetch(&endpoint, &PermissionsContainer::allow_all()) + .fetch_bypass_permissions(&endpoint) .await .ok()? .into_text_decoded() @@ -983,7 +983,7 @@ impl ModuleRegistry { // spawn due to the lsp's `Send` requirement let file = deno_core::unsync::spawn(async move { file_fetcher - .fetch(&specifier, &PermissionsContainer::allow_all()) + .fetch_bypass_permissions(&specifier) .await .ok()? .into_text_decoded() @@ -1049,7 +1049,7 @@ impl ModuleRegistry { let specifier = specifier.clone(); async move { file_fetcher - .fetch(&specifier, &PermissionsContainer::allow_all()) + .fetch_bypass_permissions(&specifier) .await .map_err(|err| { error!( @@ -1095,7 +1095,7 @@ impl ModuleRegistry { let specifier = specifier.clone(); async move { file_fetcher - .fetch(&specifier, &PermissionsContainer::allow_all()) + .fetch_bypass_permissions(&specifier) .await .map_err(|err| { error!( diff --git a/cli/lsp/testing/execution.rs b/cli/lsp/testing/execution.rs index c2398d4ff..a8cea8dd4 100644 --- a/cli/lsp/testing/execution.rs +++ b/cli/lsp/testing/execution.rs @@ -31,6 +31,7 @@ use deno_core::unsync::spawn; use deno_core::unsync::spawn_blocking; use deno_core::ModuleSpecifier; use deno_runtime::deno_permissions::Permissions; +use deno_runtime::deno_permissions::PermissionsContainer; use deno_runtime::tokio_util::create_and_run_current_thread; use indexmap::IndexMap; use std::borrow::Cow; @@ -227,8 +228,11 @@ impl TestRun { // Various test files should not share the same permissions in terms of // `PermissionsContainer` - otherwise granting/revoking permissions in one // file would have impact on other files, which is undesirable. - let permissions = - Permissions::from_options(&cli_options.permissions_options()?)?; + let permission_desc_parser = factory.permission_desc_parser()?.clone(); + let permissions = Permissions::from_options( + permission_desc_parser.as_ref(), + &cli_options.permissions_options(), + )?; let main_graph_container = factory.main_module_graph_container().await?; test::check_specifiers( factory.file_fetcher()?, @@ -276,7 +280,10 @@ impl TestRun { let join_handles = queue.into_iter().map(move |specifier| { let specifier = specifier.clone(); let worker_factory = worker_factory.clone(); - let permissions = permissions.clone(); + let permissions_container = PermissionsContainer::new( + permission_desc_parser.clone(), + permissions.clone(), + ); let worker_sender = test_event_sender_factory.worker(); let fail_fast_tracker = fail_fast_tracker.clone(); let lsp_filter = self.filters.get(&specifier); @@ -305,7 +312,7 @@ impl TestRun { // channel. create_and_run_current_thread(test::test_specifier( worker_factory, - permissions, + permissions_container, specifier, worker_sender, fail_fast_tracker, diff --git a/cli/module_loader.rs b/cli/module_loader.rs index a35e60090..86824cd70 100644 --- a/cli/module_loader.rs +++ b/cli/module_loader.rs @@ -104,7 +104,7 @@ impl ModuleLoadPreparer { roots: &[ModuleSpecifier], is_dynamic: bool, lib: TsTypeLib, - permissions: PermissionsContainer, + permissions: crate::file_fetcher::FetchPermissionsOption, ) -> Result<(), AnyError> { log::debug!("Preparing module load."); let _pb_clear_guard = self.progress_bar.clear_guard(); @@ -762,7 +762,7 @@ impl<TGraphContainer: ModuleGraphContainer> ModuleLoader &[specifier], is_dynamic, lib, - root_permissions, + root_permissions.into(), ) .await?; update_permit.commit(); diff --git a/cli/npm/byonm.rs b/cli/npm/byonm.rs index 3249b2ed1..24645e416 100644 --- a/cli/npm/byonm.rs +++ b/cli/npm/byonm.rs @@ -280,7 +280,7 @@ impl NodeRequireResolver for ByonmCliNpmResolver { .components() .any(|c| c.as_os_str().to_ascii_lowercase() == "node_modules") { - permissions.check_read(path)?; + _ = permissions.check_read_path(path)?; } Ok(()) } diff --git a/cli/npm/managed/resolvers/common.rs b/cli/npm/managed/resolvers/common.rs index 170dc2ae6..1893aa56a 100644 --- a/cli/npm/managed/resolvers/common.rs +++ b/cli/npm/managed/resolvers/common.rs @@ -127,7 +127,8 @@ impl RegistryReadPermissionChecker { } } - permissions.check_read(path) + _ = permissions.check_read_path(path)?; + Ok(()) } } diff --git a/cli/npm/mod.rs b/cli/npm/mod.rs index c8f87e6af..bedde6455 100644 --- a/cli/npm/mod.rs +++ b/cli/npm/mod.rs @@ -15,7 +15,6 @@ use deno_core::serde_json; use deno_npm::registry::NpmPackageInfo; use deno_runtime::deno_node::NodeRequireResolver; use deno_runtime::deno_node::NpmProcessStateProvider; -use deno_runtime::deno_permissions::PermissionsContainer; use deno_semver::package::PackageNv; use deno_semver::package::PackageReq; use node_resolver::NpmResolver; @@ -152,10 +151,7 @@ impl NpmFetchResolver { let file_fetcher = self.file_fetcher.clone(); // spawn due to the lsp's `Send` requirement let file = deno_core::unsync::spawn(async move { - file_fetcher - .fetch(&info_url, &PermissionsContainer::allow_all()) - .await - .ok() + file_fetcher.fetch_bypass_permissions(&info_url).await.ok() }) .await .ok()??; diff --git a/cli/ops/bench.rs b/cli/ops/bench.rs index 5521253ff..edd8c118c 100644 --- a/cli/ops/bench.rs +++ b/cli/ops/bench.rs @@ -2,6 +2,7 @@ use std::sync::atomic::AtomicUsize; use std::sync::atomic::Ordering; +use std::sync::Arc; use std::time; use deno_core::error::generic_error; @@ -13,6 +14,7 @@ use deno_core::ModuleSpecifier; use deno_core::OpState; use deno_runtime::deno_permissions::create_child_permissions; use deno_runtime::deno_permissions::ChildPermissionsArg; +use deno_runtime::deno_permissions::PermissionDescriptorParser; use deno_runtime::deno_permissions::PermissionsContainer; use tokio::sync::mpsc::UnboundedSender; use uuid::Uuid; @@ -59,11 +61,18 @@ pub fn op_pledge_test_permissions( #[serde] args: ChildPermissionsArg, ) -> Result<Uuid, AnyError> { let token = Uuid::new_v4(); + let permission_desc_parser = state + .borrow::<Arc<dyn PermissionDescriptorParser>>() + .clone(); let parent_permissions = state.borrow_mut::<PermissionsContainer>(); let worker_permissions = { - let mut parent_permissions = parent_permissions.0.lock(); - let perms = create_child_permissions(&mut parent_permissions, args)?; - PermissionsContainer::new(perms) + let mut parent_permissions = parent_permissions.inner.lock(); + let perms = create_child_permissions( + permission_desc_parser.as_ref(), + &mut parent_permissions, + args, + )?; + PermissionsContainer::new(permission_desc_parser, perms) }; let parent_permissions = parent_permissions.clone(); @@ -74,7 +83,7 @@ pub fn op_pledge_test_permissions( state.put::<PermissionsHolder>(PermissionsHolder(token, parent_permissions)); // NOTE: This call overrides current permission set for the worker - state.put(worker_permissions.0.clone()); + state.put(worker_permissions.inner.clone()); state.put::<PermissionsContainer>(worker_permissions); Ok(token) @@ -91,7 +100,7 @@ pub fn op_restore_test_permissions( } let permissions = permissions_holder.1; - state.put(permissions.0.clone()); + state.put(permissions.inner.clone()); state.put::<PermissionsContainer>(permissions); Ok(()) } else { diff --git a/cli/ops/testing.rs b/cli/ops/testing.rs index b8839a6f8..6a8d31006 100644 --- a/cli/ops/testing.rs +++ b/cli/ops/testing.rs @@ -18,9 +18,11 @@ use deno_core::ModuleSpecifier; use deno_core::OpState; use deno_runtime::deno_permissions::create_child_permissions; use deno_runtime::deno_permissions::ChildPermissionsArg; +use deno_runtime::deno_permissions::PermissionDescriptorParser; use deno_runtime::deno_permissions::PermissionsContainer; use std::sync::atomic::AtomicUsize; use std::sync::atomic::Ordering; +use std::sync::Arc; use uuid::Uuid; deno_core::extension!(deno_test, @@ -54,11 +56,18 @@ pub fn op_pledge_test_permissions( #[serde] args: ChildPermissionsArg, ) -> Result<Uuid, AnyError> { let token = Uuid::new_v4(); + let permission_desc_parser = state + .borrow::<Arc<dyn PermissionDescriptorParser>>() + .clone(); let parent_permissions = state.borrow_mut::<PermissionsContainer>(); let worker_permissions = { - let mut parent_permissions = parent_permissions.0.lock(); - let perms = create_child_permissions(&mut parent_permissions, args)?; - PermissionsContainer::new(perms) + let mut parent_permissions = parent_permissions.inner.lock(); + let perms = create_child_permissions( + permission_desc_parser.as_ref(), + &mut parent_permissions, + args, + )?; + PermissionsContainer::new(permission_desc_parser, perms) }; let parent_permissions = parent_permissions.clone(); @@ -68,7 +77,7 @@ pub fn op_pledge_test_permissions( state.put::<PermissionsHolder>(PermissionsHolder(token, parent_permissions)); // NOTE: This call overrides current permission set for the worker - state.put(worker_permissions.0.clone()); + state.put(worker_permissions.inner.clone()); state.put::<PermissionsContainer>(worker_permissions); Ok(token) @@ -85,7 +94,7 @@ pub fn op_restore_test_permissions( } let permissions = permissions_holder.1; - state.put(permissions.0.clone()); + state.put(permissions.inner.clone()); state.put::<PermissionsContainer>(permissions); Ok(()) } else { diff --git a/cli/standalone/mod.rs b/cli/standalone/mod.rs index 0a08296d9..40968a8c4 100644 --- a/cli/standalone/mod.rs +++ b/cli/standalone/mod.rs @@ -32,6 +32,8 @@ use deno_runtime::deno_permissions::Permissions; use deno_runtime::deno_permissions::PermissionsContainer; use deno_runtime::deno_tls::rustls::RootCertStore; use deno_runtime::deno_tls::RootCertStoreProvider; +use deno_runtime::deno_web::BlobStore; +use deno_runtime::permissions::RuntimePermissionDescriptorParser; use deno_runtime::WorkerExecutionMode; use deno_runtime::WorkerLogLevel; use deno_semver::npm::NpmPackageReqReference; @@ -449,7 +451,6 @@ pub async fn run( let current_exe_path = std::env::current_exe().unwrap(); let current_exe_name = current_exe_path.file_name().unwrap().to_string_lossy(); - let maybe_cwd = std::env::current_dir().ok(); let deno_dir_provider = Arc::new(DenoDirProvider::new(None)); let root_cert_store_provider = Arc::new(StandaloneRootCertStoreProvider { ca_stores: metadata.ca_stores, @@ -660,8 +661,7 @@ pub async fn run( }; let permissions = { - let mut permissions = - metadata.permissions.to_options(maybe_cwd.as_deref())?; + let mut permissions = metadata.permissions.to_options(); // if running with an npm vfs, grant read access to it if let Some(vfs_root) = maybe_vfs_root { match &mut permissions.allow_read { @@ -669,15 +669,20 @@ pub async fn run( // do nothing, already granted } Some(vec) => { - vec.push(vfs_root); + vec.push(vfs_root.to_string_lossy().to_string()); } None => { - permissions.allow_read = Some(vec![vfs_root]); + permissions.allow_read = + Some(vec![vfs_root.to_string_lossy().to_string()]); } } } - PermissionsContainer::new(Permissions::from_options(&permissions)?) + let desc_parser = + Arc::new(RuntimePermissionDescriptorParser::new(fs.clone())); + let permissions = + Permissions::from_options(desc_parser.as_ref(), &permissions)?; + PermissionsContainer::new(desc_parser, permissions) }; let feature_checker = Arc::new({ let mut checker = FeatureChecker::default(); @@ -689,21 +694,24 @@ pub async fn run( } checker }); + let permission_desc_parser = + Arc::new(RuntimePermissionDescriptorParser::new(fs.clone())); let worker_factory = CliMainWorkerFactory::new( - StorageKeyResolver::empty(), - crate::args::DenoSubcommand::Run(Default::default()), - npm_resolver, - node_resolver, - Default::default(), - Box::new(module_loader_factory), - root_cert_store_provider, - fs, + Arc::new(BlobStore::default()), + // Code cache is not supported for standalone binary yet. None, + feature_checker, + fs, None, None, - feature_checker, - // Code cache is not supported for standalone binary yet. None, + Box::new(module_loader_factory), + node_resolver, + npm_resolver, + permission_desc_parser, + root_cert_store_provider, + StorageKeyResolver::empty(), + crate::args::DenoSubcommand::Run(Default::default()), CliMainWorkerOptions { argv: metadata.argv, log_level: WorkerLogLevel::Info, diff --git a/cli/tools/bench/mod.rs b/cli/tools/bench/mod.rs index 44ae8321d..f133759c9 100644 --- a/cli/tools/bench/mod.rs +++ b/cli/tools/bench/mod.rs @@ -30,6 +30,7 @@ use deno_core::ModuleSpecifier; use deno_core::PollEventLoopOptions; use deno_runtime::deno_permissions::Permissions; use deno_runtime::deno_permissions::PermissionsContainer; +use deno_runtime::permissions::RuntimePermissionDescriptorParser; use deno_runtime::tokio_util::create_and_run_current_thread; use deno_runtime::WorkerExecutionMode; use indexmap::IndexMap; @@ -144,14 +145,14 @@ fn create_reporter( /// Run a single specifier as an executable bench module. async fn bench_specifier( worker_factory: Arc<CliMainWorkerFactory>, - permissions: Permissions, + permissions_container: PermissionsContainer, specifier: ModuleSpecifier, sender: UnboundedSender<BenchEvent>, filter: TestFilter, ) -> Result<(), AnyError> { match bench_specifier_inner( worker_factory, - permissions, + permissions_container, specifier.clone(), &sender, filter, @@ -176,7 +177,7 @@ async fn bench_specifier( /// Run a single specifier as an executable bench module. async fn bench_specifier_inner( worker_factory: Arc<CliMainWorkerFactory>, - permissions: Permissions, + permissions_container: PermissionsContainer, specifier: ModuleSpecifier, sender: &UnboundedSender<BenchEvent>, filter: TestFilter, @@ -185,7 +186,7 @@ async fn bench_specifier_inner( .create_custom_worker( WorkerExecutionMode::Bench, specifier.clone(), - PermissionsContainer::new(permissions), + permissions_container, vec![ops::bench::deno_bench::init_ops(sender.clone())], Default::default(), ) @@ -264,6 +265,7 @@ async fn bench_specifier_inner( async fn bench_specifiers( worker_factory: Arc<CliMainWorkerFactory>, permissions: &Permissions, + permissions_desc_parser: &Arc<RuntimePermissionDescriptorParser>, specifiers: Vec<ModuleSpecifier>, options: BenchSpecifierOptions, ) -> Result<(), AnyError> { @@ -273,13 +275,16 @@ async fn bench_specifiers( let join_handles = specifiers.into_iter().map(move |specifier| { let worker_factory = worker_factory.clone(); - let permissions = permissions.clone(); + let permissions_container = PermissionsContainer::new( + permissions_desc_parser.clone(), + permissions.clone(), + ); let sender = sender.clone(); let options = option_for_handles.clone(); spawn_blocking(move || { let future = bench_specifier( worker_factory, - permissions, + permissions_container, specifier, sender, options.filter, @@ -410,8 +415,11 @@ pub async fn run_benchmarks( // Various bench files should not share the same permissions in terms of // `PermissionsContainer` - otherwise granting/revoking permissions in one // file would have impact on other files, which is undesirable. - let permissions = - Permissions::from_options(&cli_options.permissions_options()?)?; + let permission_desc_parser = factory.permission_desc_parser()?.clone(); + let permissions = Permissions::from_options( + permission_desc_parser.as_ref(), + &cli_options.permissions_options(), + )?; let members_with_bench_options = cli_options.resolve_bench_options_for_members(&bench_flags)?; @@ -446,6 +454,7 @@ pub async fn run_benchmarks( bench_specifiers( worker_factory, &permissions, + &permission_desc_parser, specifiers, BenchSpecifierOptions { filter: TestFilter::from_flag(&workspace_bench_options.filter), @@ -519,8 +528,11 @@ pub async fn run_benchmarks_with_watch( // Various bench files should not share the same permissions in terms of // `PermissionsContainer` - otherwise granting/revoking permissions in one // file would have impact on other files, which is undesirable. - let permissions = - Permissions::from_options(&cli_options.permissions_options()?)?; + let permission_desc_parser = factory.permission_desc_parser()?.clone(); + let permissions = Permissions::from_options( + permission_desc_parser.as_ref(), + &cli_options.permissions_options(), + )?; let graph = module_graph_creator .create_graph(graph_kind, collected_bench_modules.clone()) @@ -568,6 +580,7 @@ pub async fn run_benchmarks_with_watch( bench_specifiers( worker_factory, &permissions, + &permission_desc_parser, specifiers, BenchSpecifierOptions { filter: TestFilter::from_flag(&workspace_bench_options.filter), diff --git a/cli/tools/jupyter/mod.rs b/cli/tools/jupyter/mod.rs index 14fcbd72c..71e947ddd 100644 --- a/cli/tools/jupyter/mod.rs +++ b/cli/tools/jupyter/mod.rs @@ -25,7 +25,6 @@ use deno_core::serde_json::json; use deno_core::url::Url; use deno_runtime::deno_io::Stdio; use deno_runtime::deno_io::StdioPipe; -use deno_runtime::deno_permissions::Permissions; use deno_runtime::deno_permissions::PermissionsContainer; use deno_runtime::WorkerExecutionMode; use deno_terminal::colors; @@ -65,7 +64,8 @@ pub async fn kernel( resolve_url_or_path("./$deno$jupyter.ts", cli_options.initial_cwd()) .unwrap(); // TODO(bartlomieju): should we run with all permissions? - let permissions = PermissionsContainer::new(Permissions::allow_all()); + let permissions = + PermissionsContainer::allow_all(factory.permission_desc_parser()?.clone()); let npm_resolver = factory.npm_resolver().await?.clone(); let resolver = factory.resolver().await?.clone(); let worker_factory = factory.create_cli_main_worker_factory().await?; diff --git a/cli/tools/registry/pm/cache_deps.rs b/cli/tools/registry/pm/cache_deps.rs index d292c32f5..a03c30df8 100644 --- a/cli/tools/registry/pm/cache_deps.rs +++ b/cli/tools/registry/pm/cache_deps.rs @@ -106,7 +106,7 @@ pub async fn cache_top_level_deps( &roots, false, deno_config::deno_json::TsTypeLib::DenoWorker, - deno_runtime::deno_permissions::PermissionsContainer::allow_all(), + crate::file_fetcher::FetchPermissionsOption::AllowAll, ) .await?; } diff --git a/cli/tools/repl/mod.rs b/cli/tools/repl/mod.rs index ed3d94c84..24bc8e30a 100644 --- a/cli/tools/repl/mod.rs +++ b/cli/tools/repl/mod.rs @@ -16,8 +16,6 @@ use deno_core::error::AnyError; use deno_core::futures::StreamExt; use deno_core::serde_json; use deno_core::unsync::spawn_blocking; -use deno_runtime::deno_permissions::Permissions; -use deno_runtime::deno_permissions::PermissionsContainer; use deno_runtime::WorkerExecutionMode; use rustyline::error::ReadlineError; @@ -151,9 +149,7 @@ async fn read_eval_file( let specifier = deno_core::resolve_url_or_path(eval_file, cli_options.initial_cwd())?; - let file = file_fetcher - .fetch(&specifier, &PermissionsContainer::allow_all()) - .await?; + let file = file_fetcher.fetch_bypass_permissions(&specifier).await?; Ok(file.into_text_decoded()?.source) } @@ -166,9 +162,7 @@ pub async fn run( let factory = CliFactory::from_flags(flags); let cli_options = factory.cli_options()?; let main_module = cli_options.resolve_main_module()?; - let permissions = PermissionsContainer::new(Permissions::from_options( - &cli_options.permissions_options()?, - )?); + let permissions = factory.create_permissions_container()?; let npm_resolver = factory.npm_resolver().await?.clone(); let resolver = factory.resolver().await?.clone(); let file_fetcher = factory.file_fetcher()?; diff --git a/cli/tools/run/mod.rs b/cli/tools/run/mod.rs index bdafdae88..200644490 100644 --- a/cli/tools/run/mod.rs +++ b/cli/tools/run/mod.rs @@ -5,8 +5,6 @@ use std::sync::Arc; use deno_config::deno_json::NodeModulesDirMode; use deno_core::error::AnyError; -use deno_runtime::deno_permissions::Permissions; -use deno_runtime::deno_permissions::PermissionsContainer; use deno_runtime::WorkerExecutionMode; use crate::args::EvalFlags; @@ -62,9 +60,7 @@ pub async fn run_script( maybe_npm_install(&factory).await?; - let permissions = PermissionsContainer::new(Permissions::from_options( - &cli_options.permissions_options()?, - )?); + let permissions = factory.create_permissions_container()?; let worker_factory = factory.create_cli_main_worker_factory().await?; let mut worker = worker_factory .create_main_worker(mode, main_module, permissions) @@ -83,9 +79,7 @@ pub async fn run_from_stdin(flags: Arc<Flags>) -> Result<i32, AnyError> { let file_fetcher = factory.file_fetcher()?; let worker_factory = factory.create_cli_main_worker_factory().await?; - let permissions = PermissionsContainer::new(Permissions::from_options( - &cli_options.permissions_options()?, - )?); + let permissions = factory.create_permissions_container()?; let mut source = Vec::new(); std::io::stdin().read_to_end(&mut source)?; // Save a fake file into file fetcher cache @@ -131,9 +125,7 @@ async fn run_with_watch( let _ = watcher_communicator.watch_paths(cli_options.watch_paths()); - let permissions = PermissionsContainer::new(Permissions::from_options( - &cli_options.permissions_options()?, - )?); + let permissions = factory.create_permissions_container()?; let mut worker = factory .create_cli_main_worker_factory() .await? @@ -181,9 +173,7 @@ pub async fn eval_command( source: source_code.into_bytes().into(), }); - let permissions = PermissionsContainer::new(Permissions::from_options( - &cli_options.permissions_options()?, - )?); + let permissions = factory.create_permissions_container()?; let worker_factory = factory.create_cli_main_worker_factory().await?; let mut worker = worker_factory .create_main_worker(WorkerExecutionMode::Eval, main_module, permissions) diff --git a/cli/tools/serve.rs b/cli/tools/serve.rs index 24666b8f6..2f553cf1e 100644 --- a/cli/tools/serve.rs +++ b/cli/tools/serve.rs @@ -5,7 +5,6 @@ use std::sync::Arc; use deno_core::error::AnyError; use deno_core::futures::TryFutureExt; use deno_core::ModuleSpecifier; -use deno_runtime::deno_permissions::Permissions; use deno_runtime::deno_permissions::PermissionsContainer; use super::run::check_permission_before_script; @@ -45,9 +44,7 @@ pub async fn serve( maybe_npm_install(&factory).await?; - let permissions = PermissionsContainer::new(Permissions::from_options( - &cli_options.permissions_options()?, - )?); + let permissions = factory.create_permissions_container()?; let worker_factory = factory.create_cli_main_worker_factory().await?; do_serve( @@ -175,9 +172,7 @@ async fn serve_with_watch( let _ = watcher_communicator.watch_paths(cli_options.watch_paths()); - let permissions = PermissionsContainer::new(Permissions::from_options( - &cli_options.permissions_options()?, - )?); + let permissions = factory.create_permissions_container()?; let worker_factory = factory.create_cli_main_worker_factory().await?; do_serve(worker_factory, main_module, permissions, worker_count, hmr) diff --git a/cli/tools/test/mod.rs b/cli/tools/test/mod.rs index 7b172cf87..63382ffc6 100644 --- a/cli/tools/test/mod.rs +++ b/cli/tools/test/mod.rs @@ -56,6 +56,7 @@ use deno_runtime::deno_io::StdioPipe; use deno_runtime::deno_permissions::Permissions; use deno_runtime::deno_permissions::PermissionsContainer; use deno_runtime::fmt_errors::format_js_error; +use deno_runtime::permissions::RuntimePermissionDescriptorParser; use deno_runtime::tokio_util::create_and_run_current_thread; use deno_runtime::worker::MainWorker; use deno_runtime::WorkerExecutionMode; @@ -595,7 +596,7 @@ fn get_test_reporter(options: &TestSpecifiersOptions) -> Box<dyn TestReporter> { async fn configure_main_worker( worker_factory: Arc<CliMainWorkerFactory>, specifier: &Url, - permissions: Permissions, + permissions_container: PermissionsContainer, worker_sender: TestEventWorkerSender, options: &TestSpecifierOptions, ) -> Result<(Option<Box<dyn CoverageCollector>>, MainWorker), anyhow::Error> { @@ -603,7 +604,7 @@ async fn configure_main_worker( .create_custom_worker( WorkerExecutionMode::Test, specifier.clone(), - PermissionsContainer::new(permissions), + permissions_container, vec![ops::testing::deno_test::init_ops(worker_sender.sender)], Stdio { stdin: StdioPipe::inherit(), @@ -646,7 +647,7 @@ async fn configure_main_worker( /// both. pub async fn test_specifier( worker_factory: Arc<CliMainWorkerFactory>, - permissions: Permissions, + permissions_container: PermissionsContainer, specifier: ModuleSpecifier, worker_sender: TestEventWorkerSender, fail_fast_tracker: FailFastTracker, @@ -658,7 +659,7 @@ pub async fn test_specifier( let (coverage_collector, mut worker) = configure_main_worker( worker_factory, &specifier, - permissions, + permissions_container, worker_sender, &options, ) @@ -1327,9 +1328,8 @@ async fn fetch_inline_files( ) -> Result<Vec<File>, AnyError> { let mut files = Vec::new(); for specifier in specifiers { - let fetch_permissions = PermissionsContainer::allow_all(); let file = file_fetcher - .fetch(&specifier, &fetch_permissions) + .fetch_bypass_permissions(&specifier) .await? .into_text_decoded()?; @@ -1407,6 +1407,7 @@ static HAS_TEST_RUN_SIGINT_HANDLER: AtomicBool = AtomicBool::new(false); async fn test_specifiers( worker_factory: Arc<CliMainWorkerFactory>, permissions: &Permissions, + permission_desc_parser: &Arc<RuntimePermissionDescriptorParser>, specifiers: Vec<ModuleSpecifier>, options: TestSpecifiersOptions, ) -> Result<(), AnyError> { @@ -1434,14 +1435,17 @@ async fn test_specifiers( let join_handles = specifiers.into_iter().map(move |specifier| { let worker_factory = worker_factory.clone(); - let permissions = permissions.clone(); + let permissions_container = PermissionsContainer::new( + permission_desc_parser.clone(), + permissions.clone(), + ); let worker_sender = test_event_sender_factory.worker(); let fail_fast_tracker = fail_fast_tracker.clone(); let specifier_options = options.specifier.clone(); spawn_blocking(move || { create_and_run_current_thread(test_specifier( worker_factory, - permissions, + permissions_container, specifier, worker_sender, fail_fast_tracker, @@ -1739,9 +1743,7 @@ async fn fetch_specifiers_with_test_mode( .collect::<Vec<_>>(); for (specifier, mode) in &mut specifiers_with_mode { - let file = file_fetcher - .fetch(specifier, &PermissionsContainer::allow_all()) - .await?; + let file = file_fetcher.fetch_bypass_permissions(specifier).await?; let (media_type, _) = file.resolve_media_type_and_charset(); if matches!(media_type, MediaType::Unknown | MediaType::Dts) { @@ -1764,8 +1766,11 @@ pub async fn run_tests( // Various test files should not share the same permissions in terms of // `PermissionsContainer` - otherwise granting/revoking permissions in one // file would have impact on other files, which is undesirable. - let permissions = - Permissions::from_options(&cli_options.permissions_options()?)?; + let permission_desc_parser = factory.permission_desc_parser()?; + let permissions = Permissions::from_options( + permission_desc_parser.as_ref(), + &cli_options.permissions_options(), + )?; let log_level = cli_options.log_level(); let members_with_test_options = @@ -1802,6 +1807,7 @@ pub async fn run_tests( test_specifiers( worker_factory, &permissions, + permission_desc_parser, specifiers_with_mode .into_iter() .filter_map(|(s, m)| match m { @@ -1914,8 +1920,11 @@ pub async fn run_tests_with_watch( .flatten() .collect::<Vec<_>>(); - let permissions = - Permissions::from_options(&cli_options.permissions_options()?)?; + let permission_desc_parser = factory.permission_desc_parser()?; + let permissions = Permissions::from_options( + permission_desc_parser.as_ref(), + &cli_options.permissions_options(), + )?; let graph = module_graph_creator .create_graph(graph_kind, test_modules) .await?; @@ -1969,6 +1978,7 @@ pub async fn run_tests_with_watch( test_specifiers( worker_factory, &permissions, + permission_desc_parser, specifiers_with_mode .into_iter() .filter_map(|(s, m)| match m { diff --git a/cli/worker.rs b/cli/worker.rs index 94884ff82..78753bf22 100644 --- a/cli/worker.rs +++ b/cli/worker.rs @@ -30,6 +30,7 @@ use deno_runtime::deno_web::BlobStore; use deno_runtime::fmt_errors::format_js_error; use deno_runtime::inspector_server::InspectorServer; use deno_runtime::ops::worker_host::CreateWebWorkerCb; +use deno_runtime::permissions::RuntimePermissionDescriptorParser; use deno_runtime::web_worker::WebWorker; use deno_runtime::web_worker::WebWorkerOptions; use deno_runtime::worker::MainWorker; @@ -121,23 +122,24 @@ pub struct CliMainWorkerOptions { } struct SharedWorkerState { - options: CliMainWorkerOptions, - subcommand: DenoSubcommand, - storage_key_resolver: StorageKeyResolver, - npm_resolver: Arc<dyn CliNpmResolver>, - node_resolver: Arc<NodeResolver>, blob_store: Arc<BlobStore>, broadcast_channel: InMemoryBroadcastChannel, - shared_array_buffer_store: SharedArrayBufferStore, + code_cache: Option<Arc<dyn code_cache::CodeCache>>, compiled_wasm_module_store: CompiledWasmModuleStore, - module_loader_factory: Box<dyn ModuleLoaderFactory>, - root_cert_store_provider: Arc<dyn RootCertStoreProvider>, + feature_checker: Arc<FeatureChecker>, fs: Arc<dyn deno_fs::FileSystem>, maybe_file_watcher_communicator: Option<Arc<WatcherCommunicator>>, maybe_inspector_server: Option<Arc<InspectorServer>>, maybe_lockfile: Option<Arc<CliLockfile>>, - feature_checker: Arc<FeatureChecker>, - code_cache: Option<Arc<dyn code_cache::CodeCache>>, + module_loader_factory: Box<dyn ModuleLoaderFactory>, + node_resolver: Arc<NodeResolver>, + npm_resolver: Arc<dyn CliNpmResolver>, + permission_desc_parser: Arc<RuntimePermissionDescriptorParser>, + root_cert_store_provider: Arc<dyn RootCertStoreProvider>, + shared_array_buffer_store: SharedArrayBufferStore, + storage_key_resolver: StorageKeyResolver, + options: CliMainWorkerOptions, + subcommand: DenoSubcommand, } impl SharedWorkerState { @@ -418,40 +420,42 @@ pub struct CliMainWorkerFactory { impl CliMainWorkerFactory { #[allow(clippy::too_many_arguments)] pub fn new( - storage_key_resolver: StorageKeyResolver, - subcommand: DenoSubcommand, - npm_resolver: Arc<dyn CliNpmResolver>, - node_resolver: Arc<NodeResolver>, blob_store: Arc<BlobStore>, - module_loader_factory: Box<dyn ModuleLoaderFactory>, - root_cert_store_provider: Arc<dyn RootCertStoreProvider>, + code_cache: Option<Arc<dyn code_cache::CodeCache>>, + feature_checker: Arc<FeatureChecker>, fs: Arc<dyn deno_fs::FileSystem>, maybe_file_watcher_communicator: Option<Arc<WatcherCommunicator>>, maybe_inspector_server: Option<Arc<InspectorServer>>, maybe_lockfile: Option<Arc<CliLockfile>>, - feature_checker: Arc<FeatureChecker>, - code_cache: Option<Arc<dyn code_cache::CodeCache>>, + module_loader_factory: Box<dyn ModuleLoaderFactory>, + node_resolver: Arc<NodeResolver>, + npm_resolver: Arc<dyn CliNpmResolver>, + permission_parser: Arc<RuntimePermissionDescriptorParser>, + root_cert_store_provider: Arc<dyn RootCertStoreProvider>, + storage_key_resolver: StorageKeyResolver, + subcommand: DenoSubcommand, options: CliMainWorkerOptions, ) -> Self { Self { shared: Arc::new(SharedWorkerState { - options, - subcommand, - storage_key_resolver, - npm_resolver, - node_resolver, blob_store, broadcast_channel: Default::default(), - shared_array_buffer_store: Default::default(), + code_cache, compiled_wasm_module_store: Default::default(), - module_loader_factory, - root_cert_store_provider, + feature_checker, fs, maybe_file_watcher_communicator, maybe_inspector_server, maybe_lockfile, - feature_checker, - code_cache, + module_loader_factory, + node_resolver, + npm_resolver, + permission_desc_parser: permission_parser, + root_cert_store_provider, + shared_array_buffer_store: Default::default(), + storage_key_resolver, + options, + subcommand, }), } } @@ -525,9 +529,13 @@ impl CliMainWorkerFactory { (main_module, false) }; - let ModuleLoaderAndSourceMapGetter { module_loader } = shared - .module_loader_factory - .create_for_main(PermissionsContainer::allow_all(), permissions.clone()); + let ModuleLoaderAndSourceMapGetter { module_loader } = + shared.module_loader_factory.create_for_main( + PermissionsContainer::allow_all( + self.shared.permission_desc_parser.clone(), + ), + permissions.clone(), + ); let maybe_inspector_server = shared.maybe_inspector_server.clone(); let create_web_worker_cb = @@ -619,6 +627,7 @@ impl CliMainWorkerFactory { ), stdio, feature_checker, + permission_desc_parser: shared.permission_desc_parser.clone(), skip_op_registration: shared.options.skip_op_registration, v8_code_cache: shared.code_cache.clone(), }; @@ -809,6 +818,7 @@ fn create_web_worker_callback( stdio: stdio.clone(), cache_storage_dir, feature_checker, + permission_desc_parser: shared.permission_desc_parser.clone(), strace_ops: shared.options.strace_ops.clone(), close_on_idle: args.close_on_idle, maybe_worker_metadata: args.maybe_worker_metadata, @@ -830,13 +840,16 @@ fn create_web_worker_callback( mod tests { use super::*; use deno_core::resolve_path; + use deno_fs::RealFs; use deno_runtime::deno_permissions::Permissions; fn create_test_worker() -> MainWorker { let main_module = resolve_path("./hello.js", &std::env::current_dir().unwrap()).unwrap(); - let permissions = - PermissionsContainer::new(Permissions::none_without_prompt()); + let permissions = PermissionsContainer::new( + Arc::new(RuntimePermissionDescriptorParser::new(Arc::new(RealFs))), + Permissions::none_without_prompt(), + ); let options = WorkerOptions { startup_snapshot: crate::js::deno_isolate_init(), |
