diff options
Diffstat (limited to 'cli')
-rw-r--r-- | cli/args/flags.rs | 130 | ||||
-rw-r--r-- | cli/dts/lib.deno.ns.d.ts | 24 | ||||
-rw-r--r-- | cli/dts/lib.deno.unstable.d.ts | 28 | ||||
-rw-r--r-- | cli/tests/unit/network_interfaces_test.ts | 5 | ||||
-rw-r--r-- | cli/tests/unit/os_test.ts | 62 | ||||
-rw-r--r-- | cli/tests/unit/permissions_test.ts | 17 | ||||
-rw-r--r-- | cli/tools/standalone.rs | 1 |
7 files changed, 227 insertions, 40 deletions
diff --git a/cli/args/flags.rs b/cli/args/flags.rs index 513307e92..46fa8c552 100644 --- a/cli/args/flags.rs +++ b/cli/args/flags.rs @@ -291,6 +291,7 @@ pub struct Flags { pub allow_ffi: Option<Vec<PathBuf>>, pub allow_read: Option<Vec<PathBuf>>, pub allow_run: Option<Vec<String>>, + pub allow_sys: Option<Vec<String>>, pub allow_write: Option<Vec<PathBuf>>, pub ca_stores: Option<Vec<String>>, pub ca_file: Option<String>, @@ -413,6 +414,17 @@ impl Flags { _ => {} } + match &self.allow_sys { + Some(sys_allowlist) if sys_allowlist.is_empty() => { + args.push("--allow-sys".to_string()); + } + Some(sys_allowlist) => { + let s = format!("--allow-sys={}", sys_allowlist.join(",")); + args.push(s) + } + _ => {} + } + match &self.allow_ffi { Some(ffi_allowlist) if ffi_allowlist.is_empty() => { args.push("--allow-ffi".to_string()); @@ -470,6 +482,7 @@ impl Flags { allow_ffi: self.allow_ffi.clone(), allow_read: self.allow_read.clone(), allow_run: self.allow_run.clone(), + allow_sys: self.allow_sys.clone(), allow_write: self.allow_write.clone(), prompt: !self.no_prompt, } @@ -590,6 +603,7 @@ fn handle_repl_flags(flags: &mut Flags, repl_flags: ReplFlags) { flags.allow_env = Some(vec![]); flags.allow_run = Some(vec![]); flags.allow_read = Some(vec![]); + flags.allow_sys = Some(vec![]); flags.allow_write = Some(vec![]); flags.allow_ffi = Some(vec![]); flags.allow_hrtime = true; @@ -1811,6 +1825,27 @@ fn permission_args(app: Command) -> Command { }), ) .arg( + Arg::new("allow-sys") + .long("allow-sys") + .min_values(0) + .takes_value(true) + .use_value_delimiter(true) + .require_equals(true) + .help("Allow access to system info") + .validator(|keys| { + for key in keys.split(',') { + match key { + "hostname" | "osRelease" | "loadavg" | "networkInterfaces" + | "systemMemoryInfo" | "getUid" | "getGid" => {} + _ => { + return Err(format!("unknown system info kind \"{}\"", key)); + } + } + } + Ok(()) + }), + ) + .arg( Arg::new("allow-run") .long("allow-run") .min_values(0) @@ -2367,6 +2402,7 @@ fn eval_parse(flags: &mut Flags, matches: &clap::ArgMatches) { flags.allow_env = Some(vec![]); flags.allow_run = Some(vec![]); flags.allow_read = Some(vec![]); + flags.allow_sys = Some(vec![]); flags.allow_write = Some(vec![]); flags.allow_ffi = Some(vec![]); flags.allow_hrtime = true; @@ -2870,6 +2906,12 @@ fn permission_args_parse(flags: &mut Flags, matches: &clap::ArgMatches) { debug!("run allowlist: {:#?}", &flags.allow_run); } + if let Some(sys_wl) = matches.values_of("allow-sys") { + let sys_allowlist: Vec<String> = sys_wl.map(ToString::to_string).collect(); + flags.allow_sys = Some(sys_allowlist); + debug!("sys info allowlist: {:#?}", &flags.allow_sys); + } + if let Some(ffi_wl) = matches.values_of("allow-ffi") { let ffi_allowlist: Vec<PathBuf> = ffi_wl.map(PathBuf::from).collect(); flags.allow_ffi = Some(ffi_allowlist); @@ -2886,6 +2928,7 @@ fn permission_args_parse(flags: &mut Flags, matches: &clap::ArgMatches) { flags.allow_net = Some(vec![]); flags.allow_run = Some(vec![]); flags.allow_write = Some(vec![]); + flags.allow_sys = Some(vec![]); flags.allow_ffi = Some(vec![]); flags.allow_hrtime = true; } @@ -3351,6 +3394,7 @@ mod tests { allow_env: Some(vec![]), allow_run: Some(vec![]), allow_read: Some(vec![]), + allow_sys: Some(vec![]), allow_write: Some(vec![]), allow_ffi: Some(vec![]), allow_hrtime: true, @@ -3978,6 +4022,7 @@ mod tests { allow_env: Some(vec![]), allow_run: Some(vec![]), allow_read: Some(vec![]), + allow_sys: Some(vec![]), allow_write: Some(vec![]), allow_ffi: Some(vec![]), allow_hrtime: true, @@ -4001,6 +4046,7 @@ mod tests { allow_env: Some(vec![]), allow_run: Some(vec![]), allow_read: Some(vec![]), + allow_sys: Some(vec![]), allow_write: Some(vec![]), allow_ffi: Some(vec![]), allow_hrtime: true, @@ -4025,6 +4071,7 @@ mod tests { allow_env: Some(vec![]), allow_run: Some(vec![]), allow_read: Some(vec![]), + allow_sys: Some(vec![]), allow_write: Some(vec![]), allow_ffi: Some(vec![]), allow_hrtime: true, @@ -4062,6 +4109,7 @@ mod tests { allow_env: Some(vec![]), allow_run: Some(vec![]), allow_read: Some(vec![]), + allow_sys: Some(vec![]), allow_write: Some(vec![]), allow_ffi: Some(vec![]), allow_hrtime: true, @@ -4092,6 +4140,7 @@ mod tests { allow_env: Some(vec![]), allow_run: Some(vec![]), allow_read: Some(vec![]), + allow_sys: Some(vec![]), allow_write: Some(vec![]), allow_ffi: Some(vec![]), allow_hrtime: true, @@ -4115,6 +4164,7 @@ mod tests { allow_env: Some(vec![]), allow_run: Some(vec![]), allow_read: Some(vec![]), + allow_sys: Some(vec![]), allow_write: Some(vec![]), allow_ffi: Some(vec![]), allow_hrtime: true, @@ -4151,6 +4201,7 @@ mod tests { allow_env: Some(vec![]), allow_run: Some(vec![]), allow_read: Some(vec![]), + allow_sys: Some(vec![]), allow_write: Some(vec![]), allow_ffi: Some(vec![]), allow_hrtime: true, @@ -4175,6 +4226,7 @@ mod tests { allow_env: Some(vec![]), allow_run: Some(vec![]), allow_read: Some(vec![]), + allow_sys: Some(vec![]), allow_write: Some(vec![]), allow_ffi: Some(vec![]), allow_hrtime: true, @@ -4203,6 +4255,7 @@ mod tests { allow_env: Some(vec![]), allow_run: Some(vec![]), allow_read: Some(vec![]), + allow_sys: Some(vec![]), allow_write: Some(vec![]), allow_ffi: Some(vec![]), allow_hrtime: true, @@ -4330,6 +4383,81 @@ mod tests { } #[test] + fn allow_sys() { + let r = flags_from_vec(svec!["deno", "run", "--allow-sys", "script.ts"]); + assert_eq!( + r.unwrap(), + Flags { + subcommand: DenoSubcommand::Run(RunFlags { + script: "script.ts".to_string(), + }), + allow_sys: Some(vec![]), + ..Flags::default() + } + ); + } + + #[test] + fn allow_sys_allowlist() { + let r = + flags_from_vec(svec!["deno", "run", "--allow-sys=hostname", "script.ts"]); + assert_eq!( + r.unwrap(), + Flags { + subcommand: DenoSubcommand::Run(RunFlags { + script: "script.ts".to_string(), + }), + allow_sys: Some(svec!["hostname"]), + ..Flags::default() + } + ); + } + + #[test] + fn allow_sys_allowlist_multiple() { + let r = flags_from_vec(svec![ + "deno", + "run", + "--allow-sys=hostname,osRelease", + "script.ts" + ]); + assert_eq!( + r.unwrap(), + Flags { + subcommand: DenoSubcommand::Run(RunFlags { + script: "script.ts".to_string(), + }), + allow_sys: Some(svec!["hostname", "osRelease"]), + ..Flags::default() + } + ); + } + + #[test] + fn allow_sys_allowlist_validator() { + let r = + flags_from_vec(svec!["deno", "run", "--allow-sys=hostname", "script.ts"]); + assert!(r.is_ok()); + let r = flags_from_vec(svec![ + "deno", + "run", + "--allow-sys=hostname,osRelease", + "script.ts" + ]); + assert!(r.is_ok()); + let r = + flags_from_vec(svec!["deno", "run", "--allow-sys=foo", "script.ts"]); + assert!(r.is_err()); + let r = flags_from_vec(svec![ + "deno", + "run", + "--allow-sys=hostname,foo", + "script.ts" + ]); + assert!(r.is_err()); + } + + #[test] fn reload_validator() { let r = flags_from_vec(svec![ "deno", @@ -4931,6 +5059,7 @@ mod tests { allow_env: Some(vec![]), allow_run: Some(vec![]), allow_read: Some(vec![]), + allow_sys: Some(vec![]), allow_write: Some(vec![]), allow_ffi: Some(vec![]), allow_hrtime: true, @@ -5012,6 +5141,7 @@ mod tests { allow_env: Some(vec![]), allow_run: Some(vec![]), allow_read: Some(vec![]), + allow_sys: Some(vec![]), allow_write: Some(vec![]), allow_ffi: Some(vec![]), allow_hrtime: true, diff --git a/cli/dts/lib.deno.ns.d.ts b/cli/dts/lib.deno.ns.d.ts index 97d3fed04..095ae139a 100644 --- a/cli/dts/lib.deno.ns.d.ts +++ b/cli/dts/lib.deno.ns.d.ts @@ -183,6 +183,15 @@ declare namespace Deno { */ env?: "inherit" | boolean | string[]; + /** Specifies if the `sys` permission should be requested or revoked. + * If set to `"inherit"`, the current `sys` permission will be inherited. + * If set to `true`, the global `sys` permission will be requested. + * If set to `false`, the global `sys` permission will be revoked. + * + * Defaults to `false`. + */ + sys?: "inherit" | boolean | string[]; + /** Specifies if the `hrtime` permission should be requested or revoked. * If set to `"inherit"`, the current `hrtime` permission will be inherited. * If set to `true`, the global `hrtime` permission will be requested. @@ -2913,6 +2922,7 @@ declare namespace Deno { | "write" | "net" | "env" + | "sys" | "ffi" | "hrtime"; @@ -2958,6 +2968,19 @@ declare namespace Deno { } /** @category Permissions */ + export interface SysPermissionDescriptor { + name: "sys"; + kind?: + | "loadavg" + | "hostname" + | "systemMemoryInfo" + | "networkInterfaces" + | "osRelease" + | "getUid" + | "getGid"; + } + + /** @category Permissions */ export interface FfiPermissionDescriptor { name: "ffi"; path?: string | URL; @@ -2979,6 +3002,7 @@ declare namespace Deno { | WritePermissionDescriptor | NetPermissionDescriptor | EnvPermissionDescriptor + | SysPermissionDescriptor | FfiPermissionDescriptor | HrtimePermissionDescriptor; diff --git a/cli/dts/lib.deno.unstable.d.ts b/cli/dts/lib.deno.unstable.d.ts index ec87fa9ca..6cb062396 100644 --- a/cli/dts/lib.deno.unstable.d.ts +++ b/cli/dts/lib.deno.unstable.d.ts @@ -255,11 +255,11 @@ declare namespace Deno { * console.log(Deno.loadavg()); // e.g. [ 0.71, 0.44, 0.44 ] * ``` * - * Requires `allow-env` permission. + * Requires `allow-sys` permission. * There are questions around which permission this needs. And maybe should be * renamed (loadAverage?). * - * @tags allow-env + * @tags allow-sys * @category Observability */ export function loadavg(): number[]; @@ -272,11 +272,11 @@ declare namespace Deno { * console.log(Deno.osRelease()); * ``` * - * Requires `allow-env` permission. + * Requires `allow-sys` permission. * Under consideration to possibly move to Deno.build or Deno.versions and if * it should depend sys-info, which may not be desirable. * - * @tags allow-env + * @tags allow-sys * @category Runtime Environment */ export function osRelease(): string; @@ -292,9 +292,9 @@ declare namespace Deno { * console.log(Deno.systemMemoryInfo()); * ``` * - * Requires `allow-env` permission. + * Requires `allow-sys` permission. * - * @tags allow-env + * @tags allow-sys * @category Runtime Environment */ export function systemMemoryInfo(): SystemMemoryInfo; @@ -355,9 +355,9 @@ declare namespace Deno { * console.log(Deno.networkInterfaces()); * ``` * - * Requires `allow-env` permission. + * Requires `allow-sys` permission. * - * @tags allow-env + * @tags allow-sys * @category Network */ export function networkInterfaces(): NetworkInterfaceInfo[]; @@ -370,9 +370,9 @@ declare namespace Deno { * console.log(Deno.getUid()); * ``` * - * Requires `allow-env` permission. + * Requires `allow-sys` permission. * - * @tags allow-env + * @tags allow-sys * @category Runtime Environment */ export function getUid(): number | null; @@ -385,9 +385,9 @@ declare namespace Deno { * console.log(Deno.getGid()); * ``` * - * Requires `allow-env` permission. + * Requires `allow-sys` permission. * - * @tags allow-env + * @tags allow-sys * @category Runtime Environment */ export function getGid(): number | null; @@ -980,11 +980,11 @@ declare namespace Deno { * console.log(Deno.hostname()); * ``` * - * Requires `allow-env` permission. + * Requires `allow-sys` permission. * Additional consideration is still necessary around the permissions * required. * - * @tags allow-env + * @tags allow-sys * @category Runtime Environment */ export function hostname(): string; diff --git a/cli/tests/unit/network_interfaces_test.ts b/cli/tests/unit/network_interfaces_test.ts index 120f58763..a0e6e691a 100644 --- a/cli/tests/unit/network_interfaces_test.ts +++ b/cli/tests/unit/network_interfaces_test.ts @@ -1,7 +1,10 @@ import { assert } from "./test_util.ts"; Deno.test( - { name: "Deno.networkInterfaces", permissions: { env: true } }, + { + name: "Deno.networkInterfaces", + permissions: { sys: ["networkInterfaces"] }, + }, () => { const networkInterfaces = Deno.networkInterfaces(); assert(Array.isArray(networkInterfaces)); diff --git a/cli/tests/unit/os_test.ts b/cli/tests/unit/os_test.ts index bdbf7f0ca..d620ae4e3 100644 --- a/cli/tests/unit/os_test.ts +++ b/cli/tests/unit/os_test.ts @@ -187,49 +187,61 @@ Deno.test({ permissions: { read: false } }, function execPathPerm() { ); }); -Deno.test({ permissions: { env: true } }, function loadavgSuccess() { - const load = Deno.loadavg(); - assertEquals(load.length, 3); -}); +Deno.test( + { permissions: { sys: ["loadavg"] } }, + function loadavgSuccess() { + const load = Deno.loadavg(); + assertEquals(load.length, 3); + }, +); -Deno.test({ permissions: { env: false } }, function loadavgPerm() { +Deno.test({ permissions: { sys: false } }, function loadavgPerm() { assertThrows(() => { Deno.loadavg(); }, Deno.errors.PermissionDenied); }); -Deno.test({ permissions: { env: true } }, function hostnameDir() { - assertNotEquals(Deno.hostname(), ""); -}); +Deno.test( + { permissions: { sys: ["hostname"] } }, + function hostnameDir() { + assertNotEquals(Deno.hostname(), ""); + }, +); -Deno.test({ permissions: { env: false } }, function hostnamePerm() { +Deno.test({ permissions: { sys: false } }, function hostnamePerm() { assertThrows(() => { Deno.hostname(); }, Deno.errors.PermissionDenied); }); -Deno.test({ permissions: { env: true } }, function releaseDir() { - assertNotEquals(Deno.osRelease(), ""); -}); +Deno.test( + { permissions: { sys: ["osRelease"] } }, + function releaseDir() { + assertNotEquals(Deno.osRelease(), ""); + }, +); -Deno.test({ permissions: { env: false } }, function releasePerm() { +Deno.test({ permissions: { sys: false } }, function releasePerm() { assertThrows(() => { Deno.osRelease(); }, Deno.errors.PermissionDenied); }); -Deno.test({ permissions: { env: true } }, function systemMemoryInfo() { - const info = Deno.systemMemoryInfo(); - assert(info.total >= 0); - assert(info.free >= 0); - assert(info.available >= 0); - assert(info.buffers >= 0); - assert(info.cached >= 0); - assert(info.swapTotal >= 0); - assert(info.swapFree >= 0); -}); +Deno.test( + { permissions: { sys: ["systemMemoryInfo"] } }, + function systemMemoryInfo() { + const info = Deno.systemMemoryInfo(); + assert(info.total >= 0); + assert(info.free >= 0); + assert(info.available >= 0); + assert(info.buffers >= 0); + assert(info.cached >= 0); + assert(info.swapTotal >= 0); + assert(info.swapFree >= 0); + }, +); -Deno.test({ permissions: { env: true } }, function getUid() { +Deno.test({ permissions: { sys: ["getUid"] } }, function getUid() { if (Deno.build.os === "windows") { assertEquals(Deno.getUid(), null); } else { @@ -239,7 +251,7 @@ Deno.test({ permissions: { env: true } }, function getUid() { } }); -Deno.test({ permissions: { env: true } }, function getGid() { +Deno.test({ permissions: { sys: ["getGid"] } }, function getGid() { if (Deno.build.os === "windows") { assertEquals(Deno.getGid(), null); } else { diff --git a/cli/tests/unit/permissions_test.ts b/cli/tests/unit/permissions_test.ts index 551e9bdcd..c0945bb59 100644 --- a/cli/tests/unit/permissions_test.ts +++ b/cli/tests/unit/permissions_test.ts @@ -19,6 +19,23 @@ Deno.test(async function permissionNetInvalidHost() { }, URIError); }); +Deno.test(async function permissionSysValidKind() { + await Deno.permissions.query({ name: "sys", kind: "loadavg" }); + await Deno.permissions.query({ name: "sys", kind: "osRelease" }); + await Deno.permissions.query({ name: "sys", kind: "networkInterfaces" }); + await Deno.permissions.query({ name: "sys", kind: "systemMemoryInfo" }); + await Deno.permissions.query({ name: "sys", kind: "hostname" }); + await Deno.permissions.query({ name: "sys", kind: "getUid" }); + await Deno.permissions.query({ name: "sys", kind: "getGid" }); +}); + +Deno.test(async function permissionSysInvalidKind() { + await assertRejects(async () => { + // deno-lint-ignore no-explicit-any + await Deno.permissions.query({ name: "sys", kind: "abc" as any }); + }, TypeError); +}); + Deno.test(async function permissionQueryReturnsEventTarget() { const status = await Deno.permissions.query({ name: "hrtime" }); assert(["granted", "denied", "prompt"].includes(status.state)); diff --git a/cli/tools/standalone.rs b/cli/tools/standalone.rs index 03118f4b6..eeedf8bd5 100644 --- a/cli/tools/standalone.rs +++ b/cli/tools/standalone.rs @@ -257,6 +257,7 @@ pub fn compile_to_runtime_flags( allow_ffi: flags.allow_ffi.clone(), allow_read: flags.allow_read.clone(), allow_run: flags.allow_run.clone(), + allow_sys: flags.allow_sys.clone(), allow_write: flags.allow_write.clone(), ca_stores: flags.ca_stores.clone(), ca_file: flags.ca_file.clone(), |