mirror of
https://github.com/denoland/deno.git
synced 2025-01-11 16:42:21 -05:00
refactor(runtime/ops/worker_host): simplify worker perms handling (#9835)
This commit is contained in:
parent
91ca58fb26
commit
2d55090d8c
2 changed files with 75 additions and 257 deletions
|
@ -109,285 +109,103 @@ pub fn init(
|
||||||
}
|
}
|
||||||
|
|
||||||
fn merge_boolean_permission(
|
fn merge_boolean_permission(
|
||||||
target: &BooleanPermission,
|
mut main: BooleanPermission,
|
||||||
incoming: Option<PermissionState>,
|
worker: Option<PermissionState>,
|
||||||
) -> Result<BooleanPermission, AnyError> {
|
) -> Result<BooleanPermission, AnyError> {
|
||||||
let mut perm = target.clone();
|
if let Some(worker) = worker {
|
||||||
perm.state = match target.state {
|
if worker < main.state {
|
||||||
PermissionState::Granted => match incoming {
|
return Err(custom_error(
|
||||||
Some(state) => state,
|
"PermissionDenied",
|
||||||
None => perm.state,
|
"Can't escalate parent thread permissions",
|
||||||
},
|
));
|
||||||
_ => match incoming {
|
} else {
|
||||||
Some(state) => match state {
|
main.state = worker;
|
||||||
PermissionState::Denied => state,
|
}
|
||||||
_ => {
|
}
|
||||||
return Err(custom_error(
|
Ok(main)
|
||||||
"PermissionDenied",
|
|
||||||
"Can't escalate parent thread permissions",
|
|
||||||
))
|
|
||||||
}
|
|
||||||
},
|
|
||||||
None => perm.state,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
Ok(perm)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_net_permission_contains(
|
fn merge_net_permission(
|
||||||
a: &HashSet<NetPermission>,
|
mut main: UnaryPermission<NetPermission>,
|
||||||
b: &HashSet<NetPermission>,
|
worker: Option<UnaryPermission<NetPermission>>,
|
||||||
) -> bool {
|
|
||||||
b.iter().all(|x| a.contains(x))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn merge_net_permissions(
|
|
||||||
target: &UnaryPermission<NetPermission>,
|
|
||||||
incoming: Option<UnaryPermission<NetPermission>>,
|
|
||||||
) -> Result<UnaryPermission<NetPermission>, AnyError> {
|
) -> Result<UnaryPermission<NetPermission>, AnyError> {
|
||||||
if incoming.is_none() {
|
if let Some(worker) = worker {
|
||||||
return Ok(target.clone());
|
if (worker.global_state < main.global_state)
|
||||||
};
|
|| !worker
|
||||||
|
.granted_list
|
||||||
let new_permissions = incoming.unwrap();
|
.iter()
|
||||||
match &target.global_state {
|
.all(|x| main.check(&(&x.0, x.1)).is_ok())
|
||||||
PermissionState::Granted => Ok(UnaryPermission::<NetPermission> {
|
{
|
||||||
global_state: new_permissions.global_state,
|
return Err(custom_error(
|
||||||
granted_list: new_permissions.granted_list,
|
|
||||||
denied_list: new_permissions.denied_list,
|
|
||||||
..Permissions::new_net(&None)
|
|
||||||
}),
|
|
||||||
PermissionState::Prompt => match new_permissions.global_state {
|
|
||||||
//Throw
|
|
||||||
PermissionState::Granted => Err(custom_error(
|
|
||||||
"PermissionDenied",
|
"PermissionDenied",
|
||||||
"Can't escalate parent thread permissions",
|
"Can't escalate parent thread permissions",
|
||||||
)),
|
));
|
||||||
//Merge
|
} else {
|
||||||
PermissionState::Prompt => {
|
main.global_state = worker.global_state;
|
||||||
if check_net_permission_contains(
|
main.granted_list = worker.granted_list;
|
||||||
&target.granted_list,
|
}
|
||||||
&new_permissions.granted_list,
|
|
||||||
) {
|
|
||||||
Ok(UnaryPermission::<NetPermission> {
|
|
||||||
global_state: new_permissions.global_state,
|
|
||||||
granted_list: new_permissions.granted_list,
|
|
||||||
denied_list: target.denied_list.clone(),
|
|
||||||
..Permissions::new_net(&None)
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
Err(custom_error(
|
|
||||||
"PermissionDenied",
|
|
||||||
"Can't escalate parent thread permissions",
|
|
||||||
))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//Copy
|
|
||||||
PermissionState::Denied => Ok(UnaryPermission::<NetPermission> {
|
|
||||||
global_state: new_permissions.global_state,
|
|
||||||
granted_list: new_permissions.granted_list,
|
|
||||||
denied_list: new_permissions.denied_list,
|
|
||||||
..Permissions::new_net(&None)
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
PermissionState::Denied => match new_permissions.global_state {
|
|
||||||
PermissionState::Denied => Ok(UnaryPermission::<NetPermission> {
|
|
||||||
global_state: new_permissions.global_state,
|
|
||||||
granted_list: new_permissions.granted_list,
|
|
||||||
denied_list: new_permissions.denied_list,
|
|
||||||
..Permissions::new_net(&None)
|
|
||||||
}),
|
|
||||||
_ => Err(custom_error(
|
|
||||||
"PermissionDenied",
|
|
||||||
"Can't escalate parent thread permissions",
|
|
||||||
)),
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
Ok(main)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_read_permissions(
|
fn merge_read_permission(
|
||||||
allow_list: &HashSet<ReadPermission>,
|
mut main: UnaryPermission<ReadPermission>,
|
||||||
current_permissions: &Permissions,
|
worker: Option<UnaryPermission<ReadPermission>>,
|
||||||
) -> bool {
|
|
||||||
allow_list
|
|
||||||
.iter()
|
|
||||||
.all(|x| current_permissions.read.check(&x.0).is_ok())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn check_write_permissions(
|
|
||||||
allow_list: &HashSet<WritePermission>,
|
|
||||||
current_permissions: &Permissions,
|
|
||||||
) -> bool {
|
|
||||||
allow_list
|
|
||||||
.iter()
|
|
||||||
.all(|x| current_permissions.write.check(&x.0).is_ok())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn merge_read_permissions(
|
|
||||||
target: &UnaryPermission<ReadPermission>,
|
|
||||||
incoming: Option<UnaryPermission<ReadPermission>>,
|
|
||||||
current_permissions: &Permissions,
|
|
||||||
) -> Result<UnaryPermission<ReadPermission>, AnyError> {
|
) -> Result<UnaryPermission<ReadPermission>, AnyError> {
|
||||||
if incoming.is_none() {
|
if let Some(worker) = worker {
|
||||||
return Ok(target.clone());
|
if (worker.global_state < main.global_state)
|
||||||
};
|
|| !worker
|
||||||
|
.granted_list
|
||||||
let new_permissions = incoming.unwrap();
|
.iter()
|
||||||
match &target.global_state {
|
.all(|x| main.check(x.0.as_path()).is_ok())
|
||||||
PermissionState::Granted => Ok(UnaryPermission::<ReadPermission> {
|
{
|
||||||
global_state: new_permissions.global_state,
|
return Err(custom_error(
|
||||||
granted_list: new_permissions.granted_list,
|
|
||||||
denied_list: new_permissions.denied_list,
|
|
||||||
..Permissions::new_read(&None)
|
|
||||||
}),
|
|
||||||
PermissionState::Prompt => match new_permissions.global_state {
|
|
||||||
//Throw
|
|
||||||
PermissionState::Granted => Err(custom_error(
|
|
||||||
"PermissionDenied",
|
"PermissionDenied",
|
||||||
"Can't escalate parent thread permissions",
|
"Can't escalate parent thread permissions",
|
||||||
)),
|
));
|
||||||
//Merge
|
} else {
|
||||||
PermissionState::Prompt => {
|
main.global_state = worker.global_state;
|
||||||
if check_read_permissions(
|
main.granted_list = worker.granted_list;
|
||||||
&new_permissions.granted_list,
|
}
|
||||||
current_permissions,
|
|
||||||
) {
|
|
||||||
Ok(UnaryPermission::<ReadPermission> {
|
|
||||||
global_state: new_permissions.global_state,
|
|
||||||
granted_list: new_permissions.granted_list,
|
|
||||||
denied_list: target.denied_list.clone(),
|
|
||||||
..Permissions::new_read(&None)
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
Err(custom_error(
|
|
||||||
"PermissionDenied",
|
|
||||||
"Can't escalate parent thread permissions",
|
|
||||||
))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//Copy
|
|
||||||
PermissionState::Denied => Ok(UnaryPermission::<ReadPermission> {
|
|
||||||
global_state: new_permissions.global_state,
|
|
||||||
granted_list: new_permissions.granted_list,
|
|
||||||
denied_list: new_permissions.denied_list,
|
|
||||||
..Permissions::new_read(&None)
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
PermissionState::Denied => match new_permissions.global_state {
|
|
||||||
PermissionState::Denied => Ok(UnaryPermission::<ReadPermission> {
|
|
||||||
global_state: new_permissions.global_state,
|
|
||||||
granted_list: new_permissions.granted_list,
|
|
||||||
denied_list: new_permissions.denied_list,
|
|
||||||
..Permissions::new_read(&None)
|
|
||||||
}),
|
|
||||||
_ => Err(custom_error(
|
|
||||||
"PermissionDenied",
|
|
||||||
"Can't escalate parent thread permissions",
|
|
||||||
)),
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
Ok(main)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn merge_write_permissions(
|
fn merge_write_permission(
|
||||||
target: &UnaryPermission<WritePermission>,
|
mut main: UnaryPermission<WritePermission>,
|
||||||
incoming: Option<UnaryPermission<WritePermission>>,
|
worker: Option<UnaryPermission<WritePermission>>,
|
||||||
current_permissions: &Permissions,
|
|
||||||
) -> Result<UnaryPermission<WritePermission>, AnyError> {
|
) -> Result<UnaryPermission<WritePermission>, AnyError> {
|
||||||
if incoming.is_none() {
|
if let Some(worker) = worker {
|
||||||
return Ok(target.clone());
|
if (worker.global_state < main.global_state)
|
||||||
};
|
|| !worker
|
||||||
|
.granted_list
|
||||||
let new_permissions = incoming.unwrap();
|
.iter()
|
||||||
match &target.global_state {
|
.all(|x| main.check(x.0.as_path()).is_ok())
|
||||||
PermissionState::Granted => Ok(UnaryPermission::<WritePermission> {
|
{
|
||||||
global_state: new_permissions.global_state,
|
return Err(custom_error(
|
||||||
granted_list: new_permissions.granted_list,
|
|
||||||
denied_list: new_permissions.denied_list,
|
|
||||||
..Permissions::new_write(&None)
|
|
||||||
}),
|
|
||||||
PermissionState::Prompt => match new_permissions.global_state {
|
|
||||||
//Throw
|
|
||||||
PermissionState::Granted => Err(custom_error(
|
|
||||||
"PermissionDenied",
|
"PermissionDenied",
|
||||||
"Can't escalate parent thread permissions",
|
"Can't escalate parent thread permissions",
|
||||||
)),
|
));
|
||||||
//Merge
|
} else {
|
||||||
PermissionState::Prompt => {
|
main.global_state = worker.global_state;
|
||||||
if check_write_permissions(
|
main.granted_list = worker.granted_list;
|
||||||
&new_permissions.granted_list,
|
}
|
||||||
current_permissions,
|
|
||||||
) {
|
|
||||||
Ok(UnaryPermission::<WritePermission> {
|
|
||||||
global_state: new_permissions.global_state,
|
|
||||||
granted_list: new_permissions.granted_list,
|
|
||||||
denied_list: target.denied_list.clone(),
|
|
||||||
..Permissions::new_write(&None)
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
Err(custom_error(
|
|
||||||
"PermissionDenied",
|
|
||||||
"Can't escalate parent thread permissions",
|
|
||||||
))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//Copy
|
|
||||||
PermissionState::Denied => Ok(UnaryPermission::<WritePermission> {
|
|
||||||
global_state: new_permissions.global_state,
|
|
||||||
granted_list: new_permissions.granted_list,
|
|
||||||
denied_list: new_permissions.denied_list,
|
|
||||||
..Permissions::new_write(&None)
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
PermissionState::Denied => match new_permissions.global_state {
|
|
||||||
PermissionState::Denied => Ok(UnaryPermission::<WritePermission> {
|
|
||||||
global_state: new_permissions.global_state,
|
|
||||||
granted_list: new_permissions.granted_list,
|
|
||||||
denied_list: new_permissions.denied_list,
|
|
||||||
..Permissions::new_write(&None)
|
|
||||||
}),
|
|
||||||
_ => Err(custom_error(
|
|
||||||
"PermissionDenied",
|
|
||||||
"Can't escalate parent thread permissions",
|
|
||||||
)),
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
Ok(main)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_worker_permissions(
|
fn create_worker_permissions(
|
||||||
main_thread_permissions: &Permissions,
|
main_perms: Permissions,
|
||||||
permission_args: PermissionsArg,
|
worker_perms: PermissionsArg,
|
||||||
) -> Result<Permissions, AnyError> {
|
) -> Result<Permissions, AnyError> {
|
||||||
Ok(Permissions {
|
Ok(Permissions {
|
||||||
env: merge_boolean_permission(
|
env: merge_boolean_permission(main_perms.env, worker_perms.env)?,
|
||||||
&main_thread_permissions.env,
|
hrtime: merge_boolean_permission(main_perms.hrtime, worker_perms.hrtime)?,
|
||||||
permission_args.env,
|
net: merge_net_permission(main_perms.net, worker_perms.net)?,
|
||||||
)?,
|
plugin: merge_boolean_permission(main_perms.plugin, worker_perms.plugin)?,
|
||||||
hrtime: merge_boolean_permission(
|
read: merge_read_permission(main_perms.read, worker_perms.read)?,
|
||||||
&main_thread_permissions.hrtime,
|
run: merge_boolean_permission(main_perms.run, worker_perms.run)?,
|
||||||
permission_args.hrtime,
|
write: merge_write_permission(main_perms.write, worker_perms.write)?,
|
||||||
)?,
|
|
||||||
net: merge_net_permissions(
|
|
||||||
&main_thread_permissions.net,
|
|
||||||
permission_args.net,
|
|
||||||
)?,
|
|
||||||
plugin: merge_boolean_permission(
|
|
||||||
&main_thread_permissions.plugin,
|
|
||||||
permission_args.plugin,
|
|
||||||
)?,
|
|
||||||
read: merge_read_permissions(
|
|
||||||
&main_thread_permissions.read,
|
|
||||||
permission_args.read,
|
|
||||||
&main_thread_permissions,
|
|
||||||
)?,
|
|
||||||
run: merge_boolean_permission(
|
|
||||||
&main_thread_permissions.run,
|
|
||||||
permission_args.run,
|
|
||||||
)?,
|
|
||||||
write: merge_write_permissions(
|
|
||||||
&main_thread_permissions.write,
|
|
||||||
permission_args.write,
|
|
||||||
&main_thread_permissions,
|
|
||||||
)?,
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -559,7 +377,7 @@ fn op_create_worker(
|
||||||
let parent_permissions = state.borrow::<Permissions>().clone();
|
let parent_permissions = state.borrow::<Permissions>().clone();
|
||||||
let worker_permissions = if let Some(permissions) = args.permissions {
|
let worker_permissions = if let Some(permissions) = args.permissions {
|
||||||
super::check_unstable(state, "Worker.deno.permissions");
|
super::check_unstable(state, "Worker.deno.permissions");
|
||||||
create_worker_permissions(&parent_permissions, permissions)?
|
create_worker_permissions(parent_permissions.clone(), permissions)?
|
||||||
} else {
|
} else {
|
||||||
parent_permissions.clone()
|
parent_permissions.clone()
|
||||||
};
|
};
|
||||||
|
|
|
@ -25,7 +25,7 @@ use std::sync::Mutex;
|
||||||
const PERMISSION_EMOJI: &str = "⚠️";
|
const PERMISSION_EMOJI: &str = "⚠️";
|
||||||
|
|
||||||
/// Tri-state value for storing permission state
|
/// Tri-state value for storing permission state
|
||||||
#[derive(PartialEq, Debug, Clone, Copy, Deserialize)]
|
#[derive(PartialEq, Debug, Clone, Copy, Deserialize, PartialOrd)]
|
||||||
pub enum PermissionState {
|
pub enum PermissionState {
|
||||||
Granted = 0,
|
Granted = 0,
|
||||||
Prompt = 1,
|
Prompt = 1,
|
||||||
|
|
Loading…
Reference in a new issue