mirror of
https://github.com/denoland/deno
synced 2024-11-05 18:45:24 +00: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(
|
||||
target: &BooleanPermission,
|
||||
incoming: Option<PermissionState>,
|
||||
mut main: BooleanPermission,
|
||||
worker: Option<PermissionState>,
|
||||
) -> Result<BooleanPermission, AnyError> {
|
||||
let mut perm = target.clone();
|
||||
perm.state = match target.state {
|
||||
PermissionState::Granted => match incoming {
|
||||
Some(state) => state,
|
||||
None => perm.state,
|
||||
},
|
||||
_ => match incoming {
|
||||
Some(state) => match state {
|
||||
PermissionState::Denied => state,
|
||||
_ => {
|
||||
return Err(custom_error(
|
||||
"PermissionDenied",
|
||||
"Can't escalate parent thread permissions",
|
||||
))
|
||||
}
|
||||
},
|
||||
None => perm.state,
|
||||
},
|
||||
};
|
||||
Ok(perm)
|
||||
if let Some(worker) = worker {
|
||||
if worker < main.state {
|
||||
return Err(custom_error(
|
||||
"PermissionDenied",
|
||||
"Can't escalate parent thread permissions",
|
||||
));
|
||||
} else {
|
||||
main.state = worker;
|
||||
}
|
||||
}
|
||||
Ok(main)
|
||||
}
|
||||
|
||||
fn check_net_permission_contains(
|
||||
a: &HashSet<NetPermission>,
|
||||
b: &HashSet<NetPermission>,
|
||||
) -> bool {
|
||||
b.iter().all(|x| a.contains(x))
|
||||
}
|
||||
|
||||
fn merge_net_permissions(
|
||||
target: &UnaryPermission<NetPermission>,
|
||||
incoming: Option<UnaryPermission<NetPermission>>,
|
||||
fn merge_net_permission(
|
||||
mut main: UnaryPermission<NetPermission>,
|
||||
worker: Option<UnaryPermission<NetPermission>>,
|
||||
) -> Result<UnaryPermission<NetPermission>, AnyError> {
|
||||
if incoming.is_none() {
|
||||
return Ok(target.clone());
|
||||
};
|
||||
|
||||
let new_permissions = incoming.unwrap();
|
||||
match &target.global_state {
|
||||
PermissionState::Granted => 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::Prompt => match new_permissions.global_state {
|
||||
//Throw
|
||||
PermissionState::Granted => Err(custom_error(
|
||||
if let Some(worker) = worker {
|
||||
if (worker.global_state < main.global_state)
|
||||
|| !worker
|
||||
.granted_list
|
||||
.iter()
|
||||
.all(|x| main.check(&(&x.0, x.1)).is_ok())
|
||||
{
|
||||
return Err(custom_error(
|
||||
"PermissionDenied",
|
||||
"Can't escalate parent thread permissions",
|
||||
)),
|
||||
//Merge
|
||||
PermissionState::Prompt => {
|
||||
if check_net_permission_contains(
|
||||
&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",
|
||||
)),
|
||||
},
|
||||
));
|
||||
} else {
|
||||
main.global_state = worker.global_state;
|
||||
main.granted_list = worker.granted_list;
|
||||
}
|
||||
}
|
||||
Ok(main)
|
||||
}
|
||||
|
||||
fn check_read_permissions(
|
||||
allow_list: &HashSet<ReadPermission>,
|
||||
current_permissions: &Permissions,
|
||||
) -> 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,
|
||||
fn merge_read_permission(
|
||||
mut main: UnaryPermission<ReadPermission>,
|
||||
worker: Option<UnaryPermission<ReadPermission>>,
|
||||
) -> Result<UnaryPermission<ReadPermission>, AnyError> {
|
||||
if incoming.is_none() {
|
||||
return Ok(target.clone());
|
||||
};
|
||||
|
||||
let new_permissions = incoming.unwrap();
|
||||
match &target.global_state {
|
||||
PermissionState::Granted => 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::Prompt => match new_permissions.global_state {
|
||||
//Throw
|
||||
PermissionState::Granted => Err(custom_error(
|
||||
if let Some(worker) = worker {
|
||||
if (worker.global_state < main.global_state)
|
||||
|| !worker
|
||||
.granted_list
|
||||
.iter()
|
||||
.all(|x| main.check(x.0.as_path()).is_ok())
|
||||
{
|
||||
return Err(custom_error(
|
||||
"PermissionDenied",
|
||||
"Can't escalate parent thread permissions",
|
||||
)),
|
||||
//Merge
|
||||
PermissionState::Prompt => {
|
||||
if check_read_permissions(
|
||||
&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",
|
||||
)),
|
||||
},
|
||||
));
|
||||
} else {
|
||||
main.global_state = worker.global_state;
|
||||
main.granted_list = worker.granted_list;
|
||||
}
|
||||
}
|
||||
Ok(main)
|
||||
}
|
||||
|
||||
fn merge_write_permissions(
|
||||
target: &UnaryPermission<WritePermission>,
|
||||
incoming: Option<UnaryPermission<WritePermission>>,
|
||||
current_permissions: &Permissions,
|
||||
fn merge_write_permission(
|
||||
mut main: UnaryPermission<WritePermission>,
|
||||
worker: Option<UnaryPermission<WritePermission>>,
|
||||
) -> Result<UnaryPermission<WritePermission>, AnyError> {
|
||||
if incoming.is_none() {
|
||||
return Ok(target.clone());
|
||||
};
|
||||
|
||||
let new_permissions = incoming.unwrap();
|
||||
match &target.global_state {
|
||||
PermissionState::Granted => 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::Prompt => match new_permissions.global_state {
|
||||
//Throw
|
||||
PermissionState::Granted => Err(custom_error(
|
||||
if let Some(worker) = worker {
|
||||
if (worker.global_state < main.global_state)
|
||||
|| !worker
|
||||
.granted_list
|
||||
.iter()
|
||||
.all(|x| main.check(x.0.as_path()).is_ok())
|
||||
{
|
||||
return Err(custom_error(
|
||||
"PermissionDenied",
|
||||
"Can't escalate parent thread permissions",
|
||||
)),
|
||||
//Merge
|
||||
PermissionState::Prompt => {
|
||||
if check_write_permissions(
|
||||
&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",
|
||||
)),
|
||||
},
|
||||
));
|
||||
} else {
|
||||
main.global_state = worker.global_state;
|
||||
main.granted_list = worker.granted_list;
|
||||
}
|
||||
}
|
||||
Ok(main)
|
||||
}
|
||||
|
||||
fn create_worker_permissions(
|
||||
main_thread_permissions: &Permissions,
|
||||
permission_args: PermissionsArg,
|
||||
main_perms: Permissions,
|
||||
worker_perms: PermissionsArg,
|
||||
) -> Result<Permissions, AnyError> {
|
||||
Ok(Permissions {
|
||||
env: merge_boolean_permission(
|
||||
&main_thread_permissions.env,
|
||||
permission_args.env,
|
||||
)?,
|
||||
hrtime: merge_boolean_permission(
|
||||
&main_thread_permissions.hrtime,
|
||||
permission_args.hrtime,
|
||||
)?,
|
||||
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,
|
||||
)?,
|
||||
env: merge_boolean_permission(main_perms.env, worker_perms.env)?,
|
||||
hrtime: merge_boolean_permission(main_perms.hrtime, worker_perms.hrtime)?,
|
||||
net: merge_net_permission(main_perms.net, worker_perms.net)?,
|
||||
plugin: merge_boolean_permission(main_perms.plugin, worker_perms.plugin)?,
|
||||
read: merge_read_permission(main_perms.read, worker_perms.read)?,
|
||||
run: merge_boolean_permission(main_perms.run, worker_perms.run)?,
|
||||
write: merge_write_permission(main_perms.write, worker_perms.write)?,
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -559,7 +377,7 @@ fn op_create_worker(
|
|||
let parent_permissions = state.borrow::<Permissions>().clone();
|
||||
let worker_permissions = if let Some(permissions) = args.permissions {
|
||||
super::check_unstable(state, "Worker.deno.permissions");
|
||||
create_worker_permissions(&parent_permissions, permissions)?
|
||||
create_worker_permissions(parent_permissions.clone(), permissions)?
|
||||
} else {
|
||||
parent_permissions.clone()
|
||||
};
|
||||
|
|
|
@ -25,7 +25,7 @@ use std::sync::Mutex;
|
|||
const PERMISSION_EMOJI: &str = "⚠️";
|
||||
|
||||
/// Tri-state value for storing permission state
|
||||
#[derive(PartialEq, Debug, Clone, Copy, Deserialize)]
|
||||
#[derive(PartialEq, Debug, Clone, Copy, Deserialize, PartialOrd)]
|
||||
pub enum PermissionState {
|
||||
Granted = 0,
|
||||
Prompt = 1,
|
||||
|
|
Loading…
Reference in a new issue