diff --git a/cli/flags.rs b/cli/flags.rs index bc08d2ec7a..95e5617aba 100644 --- a/cli/flags.rs +++ b/cli/flags.rs @@ -6,6 +6,7 @@ use clap::Arg; use clap::ArgMatches; use clap::ArgSettings; use clap::SubCommand; +use deno_runtime::permissions::PermissionsOptions; use log::Level; use std::net::SocketAddr; use std::path::PathBuf; @@ -100,11 +101,11 @@ pub struct Flags { pub allow_env: bool, pub allow_hrtime: bool, - pub allow_net: bool, + pub allow_net: Option>, pub allow_plugin: bool, - pub allow_read: bool, + pub allow_read: Option>, pub allow_run: bool, - pub allow_write: bool, + pub allow_write: Option>, pub cache_blocklist: Vec, pub ca_file: Option, pub cached_only: bool, @@ -117,11 +118,9 @@ pub struct Flags { pub lock: Option, pub lock_write: bool, pub log_level: Option, - pub net_allowlist: Vec, pub no_check: bool, pub no_prompts: bool, pub no_remote: bool, - pub read_allowlist: Vec, pub reload: bool, pub repl: bool, pub seed: Option, @@ -129,7 +128,6 @@ pub struct Flags { pub v8_flags: Vec, pub version: bool, pub watch: bool, - pub write_allowlist: Vec, } fn join_paths(allowlist: &[PathBuf], d: &str) -> String { @@ -146,32 +144,37 @@ impl Flags { pub fn to_permission_args(&self) -> Vec { let mut args = vec![]; - if !self.read_allowlist.is_empty() { - let s = format!("--allow-read={}", join_paths(&self.read_allowlist, ",")); - args.push(s); + match &self.allow_read { + Some(read_allowlist) if read_allowlist.is_empty() => { + args.push("--allow-read".to_string()); + } + Some(read_allowlist) => { + let s = format!("--allow-read={}", join_paths(read_allowlist, ",")); + args.push(s); + } + _ => {} } - if self.allow_read { - args.push("--allow-read".to_string()); + match &self.allow_write { + Some(write_allowlist) if write_allowlist.is_empty() => { + args.push("--allow-write".to_string()); + } + Some(write_allowlist) => { + let s = format!("--allow-write={}", join_paths(write_allowlist, ",")); + args.push(s); + } + _ => {} } - if !self.write_allowlist.is_empty() { - let s = - format!("--allow-write={}", join_paths(&self.write_allowlist, ",")); - args.push(s); - } - - if self.allow_write { - args.push("--allow-write".to_string()); - } - - if !self.net_allowlist.is_empty() { - let s = format!("--allow-net={}", self.net_allowlist.join(",")); - args.push(s); - } - - if self.allow_net { - args.push("--allow-net".to_string()); + match &self.allow_net { + Some(net_allowlist) if net_allowlist.is_empty() => { + args.push("--allow-net".to_string()); + } + Some(net_allowlist) => { + let s = format!("--allow-net={}", net_allowlist.join(",")); + args.push(s); + } + _ => {} } if self.allow_env { @@ -194,6 +197,20 @@ impl Flags { } } +impl From for PermissionsOptions { + fn from(flags: Flags) -> Self { + Self { + allow_env: flags.allow_env, + allow_hrtime: flags.allow_hrtime, + allow_net: flags.allow_net, + allow_plugin: flags.allow_plugin, + allow_read: flags.allow_read, + allow_run: flags.allow_run, + allow_write: flags.allow_write, + } + } +} + static ENV_VARIABLES_HELP: &str = "ENVIRONMENT VARIABLES: DENO_DIR Set the cache directory DENO_INSTALL_ROOT Set deno install's output directory @@ -437,7 +454,7 @@ fn bundle_parse(flags: &mut Flags, matches: &clap::ArgMatches) { let source_file = matches.value_of("source_file").unwrap().to_string(); let out_file = if let Some(out_file) = matches.value_of("out_file") { - flags.allow_write = true; + flags.allow_write = Some(vec![]); Some(PathBuf::from(out_file)) } else { None @@ -469,22 +486,22 @@ fn repl_parse(flags: &mut Flags, matches: &clap::ArgMatches) { runtime_args_parse(flags, matches, false); flags.repl = true; flags.subcommand = DenoSubcommand::Repl; - flags.allow_net = true; + flags.allow_net = Some(vec![]); flags.allow_env = true; flags.allow_run = true; - flags.allow_read = true; - flags.allow_write = true; + flags.allow_read = Some(vec![]); + flags.allow_write = Some(vec![]); flags.allow_plugin = true; flags.allow_hrtime = true; } fn eval_parse(flags: &mut Flags, matches: &clap::ArgMatches) { runtime_args_parse(flags, matches, false); - flags.allow_net = true; + flags.allow_net = Some(vec![]); flags.allow_env = true; flags.allow_run = true; - flags.allow_read = true; - flags.allow_write = true; + flags.allow_read = Some(vec![]); + flags.allow_write = Some(vec![]); flags.allow_plugin = true; flags.allow_hrtime = true; let as_typescript = matches.is_present("ts"); @@ -1579,34 +1596,20 @@ fn no_remote_arg_parse(flags: &mut Flags, matches: &clap::ArgMatches) { fn permission_args_parse(flags: &mut Flags, matches: &clap::ArgMatches) { if let Some(read_wl) = matches.values_of("allow-read") { let read_allowlist: Vec = read_wl.map(PathBuf::from).collect(); - - if read_allowlist.is_empty() { - flags.allow_read = true; - } else { - flags.read_allowlist = read_allowlist; - } + flags.allow_read = Some(read_allowlist); } if let Some(write_wl) = matches.values_of("allow-write") { let write_allowlist: Vec = write_wl.map(PathBuf::from).collect(); - - if write_allowlist.is_empty() { - flags.allow_write = true; - } else { - flags.write_allowlist = write_allowlist; - } + flags.allow_write = Some(write_allowlist); } if let Some(net_wl) = matches.values_of("allow-net") { - let raw_net_allowlist: Vec = - net_wl.map(ToString::to_string).collect(); - if raw_net_allowlist.is_empty() { - flags.allow_net = true; - } else { - flags.net_allowlist = - crate::flags_allow_net::parse(raw_net_allowlist).unwrap(); - debug!("net allowlist: {:#?}", &flags.net_allowlist); - } + let net_allowlist: Vec = + crate::flags_allow_net::parse(net_wl.map(ToString::to_string).collect()) + .unwrap(); + flags.allow_net = Some(net_allowlist); + debug!("net allowlist: {:#?}", &flags.allow_net); } if matches.is_present("allow-env") { @@ -1622,12 +1625,11 @@ fn permission_args_parse(flags: &mut Flags, matches: &clap::ArgMatches) { flags.allow_hrtime = true; } if matches.is_present("allow-all") { - flags.allow_read = true; + flags.allow_read = Some(vec![]); flags.allow_env = true; - flags.allow_net = true; + flags.allow_net = Some(vec![]); flags.allow_run = true; - flags.allow_read = true; - flags.allow_write = true; + flags.allow_write = Some(vec![]); flags.allow_plugin = true; flags.allow_hrtime = true; } @@ -1768,7 +1770,7 @@ mod tests { subcommand: DenoSubcommand::Run { script: "script.ts".to_string(), }, - allow_write: true, + allow_write: Some(vec![]), ..Flags::default() } ); @@ -1823,7 +1825,7 @@ mod tests { script: "gist.ts".to_string(), }, argv: svec!["--title", "X"], - allow_net: true, + allow_net: Some(vec![]), ..Flags::default() } ); @@ -1838,11 +1840,11 @@ mod tests { subcommand: DenoSubcommand::Run { script: "gist.ts".to_string(), }, - allow_net: true, + allow_net: Some(vec![]), allow_env: true, allow_run: true, - allow_read: true, - allow_write: true, + allow_read: Some(vec![]), + allow_write: Some(vec![]), allow_plugin: true, allow_hrtime: true, ..Flags::default() @@ -1860,7 +1862,7 @@ mod tests { subcommand: DenoSubcommand::Run { script: "gist.ts".to_string(), }, - allow_read: true, + allow_read: Some(vec![]), ..Flags::default() } ); @@ -1903,7 +1905,7 @@ mod tests { script: "script.ts".to_string(), }, argv: svec!["--", "-D", "--allow-net"], - allow_write: true, + allow_write: Some(vec![]), ..Flags::default() } ); @@ -2214,11 +2216,11 @@ mod tests { code: "'console.log(\"hello\")'".to_string(), as_typescript: false, }, - allow_net: true, + allow_net: Some(vec![]), allow_env: true, allow_run: true, - allow_read: true, - allow_write: true, + allow_read: Some(vec![]), + allow_write: Some(vec![]), allow_plugin: true, allow_hrtime: true, ..Flags::default() @@ -2237,11 +2239,11 @@ mod tests { code: "1+2".to_string(), as_typescript: false, }, - allow_net: true, + allow_net: Some(vec![]), allow_env: true, allow_run: true, - allow_read: true, - allow_write: true, + allow_read: Some(vec![]), + allow_write: Some(vec![]), allow_plugin: true, allow_hrtime: true, ..Flags::default() @@ -2265,11 +2267,11 @@ mod tests { code: "'console.log(\"hello\")'".to_string(), as_typescript: true, }, - allow_net: true, + allow_net: Some(vec![]), allow_env: true, allow_run: true, - allow_read: true, - allow_write: true, + allow_read: Some(vec![]), + allow_write: Some(vec![]), allow_plugin: true, allow_hrtime: true, ..Flags::default() @@ -2302,11 +2304,11 @@ mod tests { v8_flags: svec!["--help", "--random-seed=1"], seed: Some(1), inspect: Some("127.0.0.1:9229".parse().unwrap()), - allow_net: true, + allow_net: Some(vec![]), allow_env: true, allow_run: true, - allow_read: true, - allow_write: true, + allow_read: Some(vec![]), + allow_write: Some(vec![]), allow_plugin: true, allow_hrtime: true, ..Flags::default() @@ -2332,11 +2334,11 @@ mod tests { as_typescript: false, }, argv: svec!["arg1", "arg2"], - allow_net: true, + allow_net: Some(vec![]), allow_env: true, allow_run: true, - allow_read: true, - allow_write: true, + allow_read: Some(vec![]), + allow_write: Some(vec![]), allow_plugin: true, allow_hrtime: true, ..Flags::default() @@ -2352,11 +2354,11 @@ mod tests { Flags { repl: true, subcommand: DenoSubcommand::Repl, - allow_net: true, + allow_net: Some(vec![]), allow_env: true, allow_run: true, - allow_read: true, - allow_write: true, + allow_read: Some(vec![]), + allow_write: Some(vec![]), allow_plugin: true, allow_hrtime: true, ..Flags::default() @@ -2386,11 +2388,11 @@ mod tests { v8_flags: svec!["--help", "--random-seed=1"], seed: Some(1), inspect: Some("127.0.0.1:9229".parse().unwrap()), - allow_net: true, + allow_net: Some(vec![]), allow_env: true, allow_run: true, - allow_read: true, - allow_write: true, + allow_read: Some(vec![]), + allow_write: Some(vec![]), allow_plugin: true, allow_hrtime: true, ..Flags::default() @@ -2412,8 +2414,7 @@ mod tests { assert_eq!( r.unwrap(), Flags { - allow_read: false, - read_allowlist: vec![PathBuf::from("."), temp_dir], + allow_read: Some(vec![PathBuf::from("."), temp_dir]), subcommand: DenoSubcommand::Run { script: "script.ts".to_string(), }, @@ -2436,8 +2437,7 @@ mod tests { assert_eq!( r.unwrap(), Flags { - allow_write: false, - write_allowlist: vec![PathBuf::from("."), temp_dir], + allow_write: Some(vec![PathBuf::from("."), temp_dir]), subcommand: DenoSubcommand::Run { script: "script.ts".to_string(), }, @@ -2460,8 +2460,7 @@ mod tests { subcommand: DenoSubcommand::Run { script: "script.ts".to_string(), }, - allow_net: false, - net_allowlist: svec!["127.0.0.1"], + allow_net: Some(svec!["127.0.0.1"]), ..Flags::default() } ); @@ -2500,7 +2499,7 @@ mod tests { source_file: "source.ts".to_string(), out_file: Some(PathBuf::from("bundle.js")), }, - allow_write: true, + allow_write: Some(vec![]), no_remote: true, config_path: Some("tsconfig.json".to_owned()), ..Flags::default() @@ -2519,7 +2518,7 @@ mod tests { source_file: "source.ts".to_string(), out_file: Some(PathBuf::from("bundle.js")), }, - allow_write: true, + allow_write: Some(vec![]), ..Flags::default() } ); @@ -2802,8 +2801,8 @@ mod tests { v8_flags: svec!["--help", "--random-seed=1"], seed: Some(1), inspect: Some("127.0.0.1:9229".parse().unwrap()), - allow_net: true, - allow_read: true, + allow_net: Some(vec![]), + allow_read: Some(vec![]), ..Flags::default() } ); @@ -2890,7 +2889,7 @@ mod tests { subcommand: DenoSubcommand::Run { script: "script.ts".to_string(), }, - allow_read: true, + allow_read: Some(vec![]), argv: svec!["--allow-net", "-r", "--help", "--foo", "bar"], ..Flags::default() } @@ -2996,7 +2995,7 @@ mod tests { subcommand: DenoSubcommand::Run { script: "script.ts".to_string(), }, - net_allowlist: svec![ + allow_net: Some(svec![ "deno.land", "0.0.0.0:8000", "127.0.0.1:8000", @@ -3004,7 +3003,7 @@ mod tests { "0.0.0.0:4545", "127.0.0.1:4545", "localhost:4545" - ], + ]), ..Flags::default() } ); @@ -3024,7 +3023,7 @@ mod tests { subcommand: DenoSubcommand::Run { script: "script.ts".to_string(), }, - net_allowlist: svec![ + allow_net: Some(svec![ "deno.land", "deno.land:80", "::", @@ -3035,7 +3034,7 @@ mod tests { "127.0.0.1:5678", "localhost:5678", "[::1]:8080" - ], + ]), ..Flags::default() } ); @@ -3080,7 +3079,7 @@ mod tests { }, unstable: true, coverage_dir: Some("cov".to_string()), - allow_net: true, + allow_net: Some(vec![]), argv: svec!["arg1", "arg2"], ..Flags::default() } diff --git a/cli/main.rs b/cli/main.rs index 0cbf61c61c..578ea6846b 100644 --- a/cli/main.rs +++ b/cli/main.rs @@ -70,7 +70,6 @@ use deno_doc as doc; use deno_doc::parser::DocFileLoader; use deno_runtime::ops::worker_host::CreateWebWorkerCb; use deno_runtime::permissions::Permissions; -use deno_runtime::permissions::PermissionsOptions; use deno_runtime::web_worker::WebWorker; use deno_runtime::web_worker::WebWorkerOptions; use deno_runtime::worker::MainWorker; @@ -87,23 +86,6 @@ use std::pin::Pin; use std::rc::Rc; use std::sync::Arc; -impl From for PermissionsOptions { - fn from(flags: Flags) -> Self { - Self { - allow_env: flags.allow_env, - allow_hrtime: flags.allow_hrtime, - allow_net: flags.allow_net, - allow_plugin: flags.allow_plugin, - allow_read: flags.allow_read, - allow_run: flags.allow_run, - allow_write: flags.allow_write, - net_allowlist: flags.net_allowlist, - read_allowlist: flags.read_allowlist, - write_allowlist: flags.write_allowlist, - } - } -} - fn create_web_worker_callback( program_state: Arc, ) -> Arc { diff --git a/cli/tools/installer.rs b/cli/tools/installer.rs index ec527949d1..48aa524804 100644 --- a/cli/tools/installer.rs +++ b/cli/tools/installer.rs @@ -632,8 +632,8 @@ mod tests { install( Flags { - allow_net: true, - allow_read: true, + allow_net: Some(vec![]), + allow_read: Some(vec![]), no_check: true, log_level: Some(Level::Error), ..Flags::default() diff --git a/runtime/permissions.rs b/runtime/permissions.rs index df957aa013..5ccfea2790 100644 --- a/runtime/permissions.rs +++ b/runtime/permissions.rs @@ -78,56 +78,67 @@ pub struct Permissions { pub hrtime: PermissionState, } -fn resolve_fs_allowlist(allowlist: &[PathBuf]) -> HashSet { - allowlist - .iter() - .map(|raw_path| resolve_from_cwd(Path::new(&raw_path)).unwrap()) - .collect() +fn resolve_fs_allowlist(allow: &Option>) -> HashSet { + if let Some(v) = allow { + v.iter() + .map(|raw_path| resolve_from_cwd(Path::new(&raw_path)).unwrap()) + .collect() + } else { + HashSet::new() + } } #[derive(Clone, Debug, PartialEq, Default)] pub struct PermissionsOptions { pub allow_env: bool, pub allow_hrtime: bool, - pub allow_net: bool, + pub allow_net: Option>, pub allow_plugin: bool, - pub allow_read: bool, + pub allow_read: Option>, pub allow_run: bool, - pub allow_write: bool, - pub net_allowlist: Vec, - pub read_allowlist: Vec, - pub write_allowlist: Vec, + pub allow_write: Option>, } impl Permissions { pub fn from_options(opts: &PermissionsOptions) -> Self { - fn state_from_flag_bool(flag: bool) -> PermissionState { + fn global_state_from_flag_bool(flag: bool) -> PermissionState { if flag { PermissionState::Granted } else { PermissionState::Prompt } } + fn global_state_from_option(flag: &Option>) -> PermissionState { + if matches!(flag, Some(v) if v.is_empty()) { + PermissionState::Granted + } else { + PermissionState::Prompt + } + } Self { read: UnaryPermission:: { - global_state: state_from_flag_bool(opts.allow_read), - granted_list: resolve_fs_allowlist(&opts.read_allowlist), + global_state: global_state_from_option(&opts.allow_read), + granted_list: resolve_fs_allowlist(&opts.allow_read), ..Default::default() }, write: UnaryPermission:: { - global_state: state_from_flag_bool(opts.allow_write), - granted_list: resolve_fs_allowlist(&opts.write_allowlist), + global_state: global_state_from_option(&opts.allow_write), + granted_list: resolve_fs_allowlist(&opts.allow_write), ..Default::default() }, net: UnaryPermission:: { - global_state: state_from_flag_bool(opts.allow_net), - granted_list: opts.net_allowlist.iter().cloned().collect(), + global_state: global_state_from_option(&opts.allow_net), + granted_list: opts + .allow_net + .as_ref() + .map(|v| v.iter().cloned().collect()) + .unwrap_or_else(HashSet::new), ..Default::default() }, - env: state_from_flag_bool(opts.allow_env), - run: state_from_flag_bool(opts.allow_run), - plugin: state_from_flag_bool(opts.allow_plugin), - hrtime: state_from_flag_bool(opts.allow_hrtime), + env: global_state_from_flag_bool(opts.allow_env), + run: global_state_from_flag_bool(opts.allow_run), + plugin: global_state_from_flag_bool(opts.allow_plugin), + hrtime: global_state_from_flag_bool(opts.allow_hrtime), } } @@ -707,8 +718,8 @@ mod tests { ]; let perms = Permissions::from_options(&PermissionsOptions { - read_allowlist: allowlist.clone(), - write_allowlist: allowlist, + allow_read: Some(allowlist.clone()), + allow_write: Some(allowlist), ..Default::default() }); @@ -762,14 +773,14 @@ mod tests { #[test] fn test_check_net() { let perms = Permissions::from_options(&PermissionsOptions { - net_allowlist: svec![ + allow_net: Some(svec![ "localhost", "deno.land", "github.com:3000", "127.0.0.1", "172.16.0.2:8000", "www.github.com:443" - ], + ]), ..Default::default() }); @@ -853,8 +864,8 @@ mod tests { vec![PathBuf::from("/a")] }; let perms = Permissions::from_options(&PermissionsOptions { - read_allowlist, - net_allowlist: svec!["localhost"], + allow_read: Some(read_allowlist), + allow_net: Some(svec!["localhost"]), ..Default::default() }); @@ -967,12 +978,12 @@ mod tests { let perms2 = Permissions { read: UnaryPermission { global_state: PermissionState::Prompt, - granted_list: resolve_fs_allowlist(&[PathBuf::from("/foo")]), + granted_list: resolve_fs_allowlist(&Some(vec![PathBuf::from("/foo")])), ..Default::default() }, write: UnaryPermission { global_state: PermissionState::Prompt, - granted_list: resolve_fs_allowlist(&[PathBuf::from("/foo")]), + granted_list: resolve_fs_allowlist(&Some(vec![PathBuf::from("/foo")])), ..Default::default() }, net: UnaryPermission { @@ -1073,12 +1084,12 @@ mod tests { let mut perms = Permissions { read: UnaryPermission { global_state: PermissionState::Prompt, - granted_list: resolve_fs_allowlist(&[PathBuf::from("/foo")]), + granted_list: resolve_fs_allowlist(&Some(vec![PathBuf::from("/foo")])), ..Default::default() }, write: UnaryPermission { global_state: PermissionState::Prompt, - granted_list: resolve_fs_allowlist(&[PathBuf::from("/foo")]), + granted_list: resolve_fs_allowlist(&Some(vec![PathBuf::from("/foo")])), ..Default::default() }, net: UnaryPermission {