[security] Allow all functions by default (#2608)
This commit is contained in:
parent
4c61e3a556
commit
7265136c0a
3 changed files with 35 additions and 23 deletions
|
@ -164,7 +164,7 @@ impl<T: Target + Hash + Eq + PartialEq + std::fmt::Display> std::fmt::Display fo
|
|||
/// Capabilities are configured globally. By default, capabilities are configured as:
|
||||
/// - Scripting: false
|
||||
/// - Guest access: false
|
||||
/// - Functions: No function is allowed nor denied, hence all functions are denied unless explicitly allowed
|
||||
/// - Functions: All functions are allowed
|
||||
/// - Network: No network address is allowed nor denied, hence all network addresses are denied unless explicitly allowed
|
||||
///
|
||||
/// The capabilities are defined using allow/deny lists for fine-grained control.
|
||||
|
@ -235,23 +235,19 @@ impl std::fmt::Display for Capabilities {
|
|||
|
||||
impl Default for Capabilities {
|
||||
fn default() -> Self {
|
||||
Self::none()
|
||||
}
|
||||
}
|
||||
|
||||
impl Capabilities {
|
||||
fn none() -> Self {
|
||||
Self {
|
||||
scripting: false,
|
||||
guest_access: false,
|
||||
|
||||
allow_funcs: Arc::new(Targets::None),
|
||||
allow_funcs: Arc::new(Targets::All),
|
||||
deny_funcs: Arc::new(Targets::None),
|
||||
allow_net: Arc::new(Targets::None),
|
||||
deny_net: Arc::new(Targets::None),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Capabilities {
|
||||
pub fn all() -> Self {
|
||||
Self {
|
||||
scripting: true,
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use crate::cli::CF;
|
||||
use crate::err::Error;
|
||||
use clap::{ArgAction, Args};
|
||||
use clap::Args;
|
||||
use std::sync::OnceLock;
|
||||
use std::time::Duration;
|
||||
use surrealdb::dbs::capabilities::{Capabilities, FuncTarget, NetTarget, Targets};
|
||||
|
@ -39,21 +39,15 @@ struct DbsCapabilities {
|
|||
//
|
||||
#[arg(help = "Allow all capabilities")]
|
||||
#[arg(env = "SURREAL_CAPS_ALLOW_ALL", short = 'A', long, conflicts_with = "deny_all")]
|
||||
#[arg(default_missing_value_os = "true", action = ArgAction::Set, num_args = 0..)]
|
||||
#[arg(default_value_t = false, hide_default_value = true)]
|
||||
allow_all: bool,
|
||||
|
||||
#[cfg(feature = "scripting")]
|
||||
#[arg(help = "Allow execution of embedded scripting functions")]
|
||||
#[arg(env = "SURREAL_CAPS_ALLOW_SCRIPT", long, conflicts_with = "allow_all")]
|
||||
#[arg(default_missing_value_os = "true", action = ArgAction::Set, num_args = 0..)]
|
||||
#[arg(default_value_t = false, hide_default_value = true)]
|
||||
allow_scripting: bool,
|
||||
|
||||
#[arg(help = "Allow guest users to execute queries")]
|
||||
#[arg(env = "SURREAL_CAPS_ALLOW_GUESTS", long, conflicts_with = "allow_all")]
|
||||
#[arg(default_missing_value_os = "true", action = ArgAction::Set, num_args = 0..)]
|
||||
#[arg(default_value_t = false, hide_default_value = true)]
|
||||
allow_guests: bool,
|
||||
|
||||
#[arg(
|
||||
|
@ -67,6 +61,7 @@ Function names must be in the form <family>[::<name>]. For example:
|
|||
#[arg(env = "SURREAL_CAPS_ALLOW_FUNC", long, conflicts_with = "allow_all")]
|
||||
// If the arg is provided without value, then assume it's "", which gets parsed into Targets::All
|
||||
#[arg(default_missing_value_os = "", num_args = 0..)]
|
||||
#[arg(default_value_os = "")] // Allow all functions by default
|
||||
#[arg(value_parser = super::cli::validator::func_targets)]
|
||||
allow_funcs: Option<Targets<FuncTarget>>,
|
||||
|
||||
|
@ -90,21 +85,15 @@ Targets must be in the form of <host>[:<port>], <ipv4|ipv6>[/<mask>]. For exampl
|
|||
//
|
||||
#[arg(help = "Deny all capabilities")]
|
||||
#[arg(env = "SURREAL_CAPS_DENY_ALL", short = 'D', long, conflicts_with = "allow_all")]
|
||||
#[arg(default_missing_value_os = "true", action = ArgAction::Set, num_args = 0..)]
|
||||
#[arg(default_value_t = false, hide_default_value = true)]
|
||||
deny_all: bool,
|
||||
|
||||
#[cfg(feature = "scripting")]
|
||||
#[arg(help = "Deny execution of embedded scripting functions")]
|
||||
#[arg(env = "SURREAL_CAPS_DENY_SCRIPT", long, conflicts_with = "deny_all")]
|
||||
#[arg(default_missing_value_os = "true", action = ArgAction::Set, num_args = 0..)]
|
||||
#[arg(default_value_t = false, hide_default_value = true)]
|
||||
deny_scripting: bool,
|
||||
|
||||
#[arg(help = "Deny guest users to execute queries")]
|
||||
#[arg(env = "SURREAL_CAPS_DENY_GUESTS", long, conflicts_with = "deny_all")]
|
||||
#[arg(default_missing_value_os = "true", action = ArgAction::Set, num_args = 0..)]
|
||||
#[arg(default_value_t = false, hide_default_value = true)]
|
||||
deny_guests: bool,
|
||||
|
||||
#[arg(
|
||||
|
|
|
@ -504,8 +504,8 @@ mod cli_integration {
|
|||
|
||||
#[test(tokio::test)]
|
||||
async fn test_capabilities() {
|
||||
// Deny all, denies all users to execute functions and access any network address
|
||||
info!("* When all capabilities are denied by default");
|
||||
// Default capabilities only allow functions
|
||||
info!("* When default capabilities");
|
||||
{
|
||||
let (addr, _server) = common::start_server(StartServerArguments {
|
||||
args: "".to_owned(),
|
||||
|
@ -516,6 +516,33 @@ mod cli_integration {
|
|||
|
||||
let cmd = format!("sql --conn ws://{addr} -u root -p root --ns N --db D --multi");
|
||||
|
||||
let query = "RETURN http::get('http://127.0.0.1/');\n\n";
|
||||
let output = common::run(&cmd).input(query).output().unwrap();
|
||||
assert!(
|
||||
output.contains("Access to network target 'http://127.0.0.1/' is not allowed"),
|
||||
"unexpected output: {output:?}"
|
||||
);
|
||||
|
||||
let query = "RETURN function() { return '1' };";
|
||||
let output = common::run(&cmd).input(query).output().unwrap();
|
||||
assert!(
|
||||
output.contains("Scripting functions are not allowed"),
|
||||
"unexpected output: {output:?}"
|
||||
);
|
||||
}
|
||||
|
||||
// Deny all, denies all users to execute functions and access any network address
|
||||
info!("* When all capabilities are denied");
|
||||
{
|
||||
let (addr, _server) = common::start_server(StartServerArguments {
|
||||
args: "--deny-all".to_owned(),
|
||||
..Default::default()
|
||||
})
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let cmd = format!("sql --conn ws://{addr} -u root -p root --ns N --db D --multi");
|
||||
|
||||
let query = format!("RETURN http::get('http://{}/version');\n\n", addr);
|
||||
let output = common::run(&cmd).input(&query).output().unwrap();
|
||||
assert!(
|
||||
|
|
Loading…
Reference in a new issue