diff options
Diffstat (limited to 'cli')
-rw-r--r-- | cli/dts/lib.deno.ns.d.ts | 1 | ||||
-rw-r--r-- | cli/dts/lib.deno.unstable.d.ts | 6 | ||||
-rw-r--r-- | cli/flags.rs | 12 | ||||
-rw-r--r-- | cli/ops/testing.rs | 12 | ||||
-rw-r--r-- | cli/tests/integration/worker_tests.rs | 2 | ||||
-rw-r--r-- | cli/tests/testdata/test/allow_all.ts | 2 | ||||
-rw-r--r-- | cli/tests/testdata/workers/no_permissions_worker.js | 12 | ||||
-rw-r--r-- | cli/tests/testdata/workers/parent_read_check_granular_worker.js | 41 | ||||
-rw-r--r-- | cli/tests/testdata/workers/parent_read_check_worker.js | 39 | ||||
-rw-r--r-- | cli/tests/testdata/workers/read_check_granular_worker.js | 40 | ||||
-rw-r--r-- | cli/tests/testdata/workers/test.ts | 235 |
11 files changed, 172 insertions, 230 deletions
diff --git a/cli/dts/lib.deno.ns.d.ts b/cli/dts/lib.deno.ns.d.ts index eb91d6fa4..3fff1c61e 100644 --- a/cli/dts/lib.deno.ns.d.ts +++ b/cli/dts/lib.deno.ns.d.ts @@ -2178,6 +2178,7 @@ declare namespace Deno { export interface FfiPermissionDescriptor { name: "ffi"; + path?: string | URL; } export interface HrtimePermissionDescriptor { diff --git a/cli/dts/lib.deno.unstable.d.ts b/cli/dts/lib.deno.unstable.d.ts index 3bea165e5..fd33e1a74 100644 --- a/cli/dts/lib.deno.unstable.d.ts +++ b/cli/dts/lib.deno.unstable.d.ts @@ -910,10 +910,12 @@ declare namespace Deno { * If set to `"inherit"`, the current `ffi` permission will be inherited. * If set to `true`, the global `ffi` permission will be requested. * If set to `false`, the global `ffi` permission will be revoked. + * If set to `Array<string | URL>`, the `ffi` permission will be requested with the + * specified file paths. * * Defaults to "inherit". */ - ffi?: "inherit" | boolean; + ffi?: "inherit" | boolean | Array<string | URL>; /** Specifies if the `read` permission should be requested or revoked. * If set to `"inherit"`, the current `read` permission will be inherited. @@ -1237,7 +1239,7 @@ declare interface WorkerOptions { * For example: `["https://deno.land", "localhost:8080"]`. */ net?: "inherit" | boolean | string[]; - ffi?: "inherit" | boolean; + ffi?: "inherit" | boolean | Array<string | URL>; read?: "inherit" | boolean | Array<string | URL>; run?: "inherit" | boolean | Array<string | URL>; write?: "inherit" | boolean | Array<string | URL>; diff --git a/cli/flags.rs b/cli/flags.rs index df17c08da..67c76244d 100644 --- a/cli/flags.rs +++ b/cli/flags.rs @@ -198,7 +198,7 @@ pub struct Flags { pub allow_env: Option<Vec<String>>, pub allow_hrtime: bool, pub allow_net: Option<Vec<String>>, - pub allow_ffi: Option<Vec<String>>, + pub allow_ffi: Option<Vec<PathBuf>>, pub allow_read: Option<Vec<PathBuf>>, pub allow_run: Option<Vec<String>>, pub allow_write: Option<Vec<PathBuf>>, @@ -324,7 +324,7 @@ impl Flags { args.push("--allow-ffi".to_string()); } Some(ffi_allowlist) => { - let s = format!("--allow-ffi={}", ffi_allowlist.join(",")); + let s = format!("--allow-ffi={}", join_paths(ffi_allowlist, ",")); args.push(s); } _ => {} @@ -1685,10 +1685,10 @@ fn config_arg<'a, 'b>() -> Arg<'a, 'b> { .long_help( "Load configuration file. Before 1.14 Deno only supported loading tsconfig.json that allowed -to customise TypeScript compiler settings. +to customise TypeScript compiler settings. -Starting with 1.14 configuration file can be used to configure different -subcommands like `deno lint` or `deno fmt`. +Starting with 1.14 configuration file can be used to configure different +subcommands like `deno lint` or `deno fmt`. It's recommended to use `deno.json` or `deno.jsonc` as a filename.", ) @@ -2202,7 +2202,7 @@ fn permission_args_parse(flags: &mut Flags, matches: &clap::ArgMatches) { } if let Some(ffi_wl) = matches.values_of("allow-ffi") { - let ffi_allowlist: Vec<String> = ffi_wl.map(ToString::to_string).collect(); + let ffi_allowlist: Vec<PathBuf> = ffi_wl.map(PathBuf::from).collect(); flags.allow_ffi = Some(ffi_allowlist); debug!("ffi allowlist: {:#?}", &flags.allow_ffi); } diff --git a/cli/ops/testing.rs b/cli/ops/testing.rs index 99cfc670e..31b60b480 100644 --- a/cli/ops/testing.rs +++ b/cli/ops/testing.rs @@ -4,8 +4,8 @@ use deno_core::error::AnyError; use deno_core::JsRuntime; use deno_core::ModuleSpecifier; use deno_core::OpState; -use deno_runtime::ops::worker_host::create_worker_permissions; -use deno_runtime::ops::worker_host::PermissionsArg; +use deno_runtime::permissions::create_child_permissions; +use deno_runtime::permissions::ChildPermissionsArg; use deno_runtime::permissions::Permissions; use std::sync::mpsc::Sender; use uuid::Uuid; @@ -26,15 +26,15 @@ struct PermissionsHolder(Uuid, Permissions); pub fn op_pledge_test_permissions( state: &mut OpState, - args: PermissionsArg, + args: ChildPermissionsArg, _: (), ) -> Result<Uuid, AnyError> { deno_runtime::ops::check_unstable(state, "Deno.test.permissions"); let token = Uuid::new_v4(); - let parent_permissions = state.borrow::<Permissions>().clone(); - let worker_permissions = - create_worker_permissions(parent_permissions.clone(), args)?; + let parent_permissions = state.borrow_mut::<Permissions>(); + let worker_permissions = create_child_permissions(parent_permissions, args)?; + let parent_permissions = parent_permissions.clone(); state.put::<PermissionsHolder>(PermissionsHolder(token, parent_permissions)); diff --git a/cli/tests/integration/worker_tests.rs b/cli/tests/integration/worker_tests.rs index bf1057821..c17b63af9 100644 --- a/cli/tests/integration/worker_tests.rs +++ b/cli/tests/integration/worker_tests.rs @@ -3,7 +3,7 @@ use crate::itest; itest!(workers { - args: "test --reload --location http://127.0.0.1:4545/ --allow-net --allow-read --unstable workers/test.ts", + args: "test --reload --location http://127.0.0.1:4545/ -A --unstable workers/test.ts", output: "workers/test.ts.out", http_server: true, }); diff --git a/cli/tests/testdata/test/allow_all.ts b/cli/tests/testdata/test/allow_all.ts index abe55a8d5..e70ac46b0 100644 --- a/cli/tests/testdata/test/allow_all.ts +++ b/cli/tests/testdata/test/allow_all.ts @@ -18,7 +18,7 @@ for (const name of permissions) { }, async fn() { const status = await Deno.permissions.query({ name }); - assertEquals(status.state, "denied"); + assertEquals(status.state, "prompt"); }, }); diff --git a/cli/tests/testdata/workers/no_permissions_worker.js b/cli/tests/testdata/workers/no_permissions_worker.js index db0d911ac..f49f690ab 100644 --- a/cli/tests/testdata/workers/no_permissions_worker.js +++ b/cli/tests/testdata/workers/no_permissions_worker.js @@ -6,12 +6,12 @@ self.onmessage = async () => { const run = await Deno.permissions.query({ name: "run" }); const write = await Deno.permissions.query({ name: "write" }); self.postMessage( - hrtime.state === "denied" && - net.state === "denied" && - ffi.state === "denied" && - read.state === "denied" && - run.state === "denied" && - write.state === "denied", + hrtime.state === "prompt" && + net.state === "prompt" && + ffi.state === "prompt" && + read.state === "prompt" && + run.state === "prompt" && + write.state === "prompt", ); self.close(); }; diff --git a/cli/tests/testdata/workers/parent_read_check_granular_worker.js b/cli/tests/testdata/workers/parent_read_check_granular_worker.js deleted file mode 100644 index 1391190cd..000000000 --- a/cli/tests/testdata/workers/parent_read_check_granular_worker.js +++ /dev/null @@ -1,41 +0,0 @@ -const worker = new Worker( - new URL("./read_check_granular_worker.js", import.meta.url).href, - { - type: "module", - deno: { - namespace: true, - permissions: { - read: [], - }, - }, - }, -); - -let received = 0; -const messages = []; - -worker.onmessage = ({ data: childResponse }) => { - received++; - postMessage({ - childHasPermission: childResponse.hasPermission, - index: childResponse.index, - parentHasPermission: messages[childResponse.index], - }); - if (received === messages.length) { - worker.terminate(); - } -}; - -onmessage = async ({ data }) => { - const { state } = await Deno.permissions.query({ - name: "read", - path: data.path, - }); - - messages[data.index] = state === "granted"; - - worker.postMessage({ - index: data.index, - route: data.route, - }); -}; diff --git a/cli/tests/testdata/workers/parent_read_check_worker.js b/cli/tests/testdata/workers/parent_read_check_worker.js index ec92cca3f..87ea6bded 100644 --- a/cli/tests/testdata/workers/parent_read_check_worker.js +++ b/cli/tests/testdata/workers/parent_read_check_worker.js @@ -1,27 +1,18 @@ -onmessage = async () => { - const { state } = await Deno.permissions.query({ - name: "read", - }); - - const worker = new Worker( - new URL("./read_check_worker.js", import.meta.url).href, - { - type: "module", - deno: { - namespace: true, - permissions: { - read: false, - }, - }, +const worker = new Worker( + new URL("./read_check_granular_worker.js", import.meta.url).href, + { + type: "module", + deno: { + namespace: true, + permissions: "none", }, - ); + }, +); + +onmessage = ({ data }) => { + worker.postMessage(data); +}; - worker.onmessage = ({ data: childHasPermission }) => { - postMessage({ - parentHasPermission: state === "granted", - childHasPermission, - }); - close(); - }; - worker.postMessage(null); +worker.onmessage = ({ data }) => { + postMessage(data); }; diff --git a/cli/tests/testdata/workers/read_check_granular_worker.js b/cli/tests/testdata/workers/read_check_granular_worker.js index 25f2058b3..d40fac876 100644 --- a/cli/tests/testdata/workers/read_check_granular_worker.js +++ b/cli/tests/testdata/workers/read_check_granular_worker.js @@ -1,11 +1,29 @@ -onmessage = async ({ data }) => { - const { state } = await Deno.permissions.query({ - name: "read", - path: data.path, - }); - - postMessage({ - hasPermission: state === "granted", - index: data.index, - }); -}; +// deno-fmt-ignore-file +postMessage({ + envGlobal: (await Deno.permissions.query({ name: "env" })).state, + envFoo: (await Deno.permissions.query({ name: "env", variable: "foo" })).state, + envAbsent: (await Deno.permissions.query({ name: "env", variable: "absent" })).state, + hrtime: (await Deno.permissions.query({ name: "hrtime" })).state, + netGlobal: (await Deno.permissions.query({ name: "net" })).state, + netFoo: (await Deno.permissions.query({ name: "net", host: "foo" })).state, + netFoo8000: (await Deno.permissions.query({ name: "net", host: "foo:8000" })).state, + netBar: (await Deno.permissions.query({ name: "net", host: "bar" })).state, + netBar8000: (await Deno.permissions.query({ name: "net", host: "bar:8000" })).state, + ffiGlobal: (await Deno.permissions.query({ name: "ffi" })).state, + ffiFoo: (await Deno.permissions.query({ name: "ffi", path: new URL("foo", import.meta.url) })).state, + ffiBar: (await Deno.permissions.query({ name: "ffi", path: "bar" })).state, + ffiAbsent: (await Deno.permissions.query({ name: "ffi", path: "absent" })).state, + readGlobal: (await Deno.permissions.query({ name: "read" })).state, + readFoo: (await Deno.permissions.query({ name: "read", path: new URL("foo", import.meta.url) })).state, + readBar: (await Deno.permissions.query({ name: "read", path: "bar" })).state, + readAbsent: (await Deno.permissions.query({ name: "read", path: "absent" })).state, + runGlobal: (await Deno.permissions.query({ name: "run" })).state, + runFoo: (await Deno.permissions.query({ name: "run", command: new URL("foo", import.meta.url) })).state, + runBar: (await Deno.permissions.query({ name: "run", command: "bar" })).state, + runBaz: (await Deno.permissions.query({ name: "run", command: "./baz" })).state, + runAbsent: (await Deno.permissions.query({ name: "run", command: "absent" })).state, + writeGlobal: (await Deno.permissions.query({ name: "write" })).state, + writeFoo: (await Deno.permissions.query({ name: "write", path: new URL("foo", import.meta.url) })).state, + writeBar: (await Deno.permissions.query({ name: "write", path: "bar" })).state, + writeAbsent: (await Deno.permissions.query({ name: "write", path: "absent" })).state, +}); diff --git a/cli/tests/testdata/workers/test.ts b/cli/tests/testdata/workers/test.ts index effd104f5..4a6575863 100644 --- a/cli/tests/testdata/workers/test.ts +++ b/cli/tests/testdata/workers/test.ts @@ -8,7 +8,6 @@ import { assertThrows, } from "../../../../test_util/std/testing/asserts.ts"; import { deferred } from "../../../../test_util/std/async/deferred.ts"; -import { fromFileUrl } from "../../../../test_util/std/path/mod.ts"; Deno.test({ name: "worker terminate", @@ -454,7 +453,6 @@ Deno.test("Worker limit children permissions", async function () { }); Deno.test("Worker limit children permissions granularly", async function () { - const promise = deferred(); const worker = new Worker( new URL("./read_check_granular_worker.js", import.meta.url).href, { @@ -462,53 +460,52 @@ Deno.test("Worker limit children permissions granularly", async function () { deno: { namespace: true, permissions: { - read: [ - new URL("./read_check_worker.js", import.meta.url), - ], + env: ["foo"], + hrtime: true, + net: ["foo", "bar:8000"], + ffi: [new URL("foo", import.meta.url), "bar"], + read: [new URL("foo", import.meta.url), "bar"], + run: [new URL("foo", import.meta.url), "bar", "./baz"], + write: [new URL("foo", import.meta.url), "bar"], }, }, }, ); - - //Routes are relative to the spawned worker location - const routes = [ - { - permission: false, - path: fromFileUrl( - new URL("read_check_granular_worker.js", import.meta.url), - ), - }, - { - permission: true, - path: fromFileUrl(new URL("read_check_worker.js", import.meta.url)), - }, - ]; - - let checked = 0; - worker.onmessage = ({ data }) => { - checked++; - assertEquals(data.hasPermission, routes[data.index].permission); - routes.shift(); - if (checked === routes.length) { - promise.resolve(); - } - }; - - routes.forEach(({ path }, index) => - worker.postMessage({ - index, - path, - }) - ); - - await promise; + const promise = deferred(); + worker.onmessage = ({ data }) => promise.resolve(data); + assertEquals(await promise, { + envGlobal: "prompt", + envFoo: "granted", + envAbsent: "prompt", + hrtime: "granted", + netGlobal: "prompt", + netFoo: "granted", + netFoo8000: "granted", + netBar: "prompt", + netBar8000: "granted", + ffiGlobal: "prompt", + ffiFoo: "granted", + ffiBar: "granted", + ffiAbsent: "prompt", + readGlobal: "prompt", + readFoo: "granted", + readBar: "granted", + readAbsent: "prompt", + runGlobal: "prompt", + runFoo: "granted", + runBar: "granted", + runBaz: "granted", + runAbsent: "prompt", + writeGlobal: "prompt", + writeFoo: "granted", + writeBar: "granted", + writeAbsent: "prompt", + }); worker.terminate(); }); Deno.test("Nested worker limit children permissions", async function () { - const promise = deferred(); - - /** This worker has read permissions but doesn't grant them to its children */ + /** This worker has permissions but doesn't grant them to its children */ const worker = new Worker( new URL("./parent_read_check_worker.js", import.meta.url).href, { @@ -519,104 +516,65 @@ Deno.test("Nested worker limit children permissions", async function () { }, }, ); - - worker.onmessage = ({ data }) => { - assert(data.parentHasPermission); - assert(!data.childHasPermission); - promise.resolve(); - }; - - worker.postMessage(null); - - await promise; - worker.terminate(); -}); - -Deno.test("Nested worker limit children permissions granularly", async function () { const promise = deferred(); - - /** This worker has read permissions but doesn't grant them to its children */ - const worker = new Worker( - new URL("./parent_read_check_granular_worker.js", import.meta.url) - .href, - { - type: "module", - deno: { - namespace: true, - permissions: { - read: [ - new URL("./read_check_granular_worker.js", import.meta.url), - ], - }, - }, - }, - ); - - //Routes are relative to the spawned worker location - const routes = [ - { - childHasPermission: false, - parentHasPermission: true, - path: fromFileUrl( - new URL("read_check_granular_worker.js", import.meta.url), - ), - }, - { - childHasPermission: false, - parentHasPermission: false, - path: fromFileUrl(new URL("read_check_worker.js", import.meta.url)), - }, - ]; - - let checked = 0; - worker.onmessage = ({ data }) => { - checked++; - assertEquals( - data.childHasPermission, - routes[data.index].childHasPermission, - ); - assertEquals( - data.parentHasPermission, - routes[data.index].parentHasPermission, - ); - if (checked === routes.length) { - promise.resolve(); - } - }; - - // Index needed cause requests will be handled asynchronously - routes.forEach(({ path }, index) => - worker.postMessage({ - index, - path, - }) - ); - - await promise; + worker.onmessage = ({ data }) => promise.resolve(data); + assertEquals(await promise, { + envGlobal: "prompt", + envFoo: "prompt", + envAbsent: "prompt", + hrtime: "prompt", + netGlobal: "prompt", + netFoo: "prompt", + netFoo8000: "prompt", + netBar: "prompt", + netBar8000: "prompt", + ffiGlobal: "prompt", + ffiFoo: "prompt", + ffiBar: "prompt", + ffiAbsent: "prompt", + readGlobal: "prompt", + readFoo: "prompt", + readBar: "prompt", + readAbsent: "prompt", + runGlobal: "prompt", + runFoo: "prompt", + runBar: "prompt", + runBaz: "prompt", + runAbsent: "prompt", + writeGlobal: "prompt", + writeFoo: "prompt", + writeBar: "prompt", + writeAbsent: "prompt", + }); worker.terminate(); }); // This test relies on env permissions not being granted on main thread -Deno.test("Worker initialization throws on worker permissions greater than parent thread permissions", function () { - assertThrows( - () => { - const worker = new Worker( - new URL("./deno_worker.ts", import.meta.url).href, - { - type: "module", - deno: { - namespace: true, - permissions: { - env: true, +Deno.test({ + name: + "Worker initialization throws on worker permissions greater than parent thread permissions", + permissions: { env: false }, + fn: function () { + assertThrows( + () => { + const worker = new Worker( + new URL("./deno_worker.ts", import.meta.url).href, + { + type: "module", + deno: { + namespace: true, + permissions: { + env: true, + }, }, }, - }, - ); - worker.terminate(); - }, - Deno.errors.PermissionDenied, - "Can't escalate parent thread permissions", - ); + ); + worker.terminate(); + }, + Deno.errors.PermissionDenied, + "Can't escalate parent thread permissions", + ); + }, }); Deno.test("Worker with disabled permissions", async function () { @@ -643,6 +601,19 @@ Deno.test("Worker with disabled permissions", async function () { worker.terminate(); }); +Deno.test("Worker with invalid permission arg", function () { + assertThrows( + () => + new Worker(`data:,close();`, { + type: "module", + // @ts-expect-error invalid env value + deno: { permissions: { env: "foo" } }, + }), + TypeError, + 'Error parsing args: (deno.permissions.env) invalid value: string "foo", expected "inherit" or boolean or string[]', + ); +}); + Deno.test({ name: "worker location", fn: async function () { |