pinakes-core: update remaining modules and tests
Signed-off-by: NotAShelf <raf@notashelf.dev> Change-Id: I9e0ff5ea33a5cf697473423e88f167ce6a6a6964
This commit is contained in:
parent
c8425a4c34
commit
3d9f8933d2
44 changed files with 1207 additions and 578 deletions
|
|
@ -25,7 +25,8 @@ pub struct CapabilityEnforcer {
|
|||
|
||||
impl CapabilityEnforcer {
|
||||
/// Create a new capability enforcer with default limits
|
||||
pub fn new() -> Self {
|
||||
#[must_use]
|
||||
pub const fn new() -> Self {
|
||||
Self {
|
||||
max_memory_limit: 512 * 1024 * 1024, // 512 MB
|
||||
max_cpu_time_limit: 60 * 1000, // 60 seconds
|
||||
|
|
@ -36,36 +37,47 @@ impl CapabilityEnforcer {
|
|||
}
|
||||
|
||||
/// Set maximum memory limit
|
||||
pub fn with_max_memory(mut self, bytes: usize) -> Self {
|
||||
#[must_use]
|
||||
pub const fn with_max_memory(mut self, bytes: usize) -> Self {
|
||||
self.max_memory_limit = bytes;
|
||||
self
|
||||
}
|
||||
|
||||
/// Set maximum CPU time limit
|
||||
pub fn with_max_cpu_time(mut self, milliseconds: u64) -> Self {
|
||||
#[must_use]
|
||||
pub const fn with_max_cpu_time(mut self, milliseconds: u64) -> Self {
|
||||
self.max_cpu_time_limit = milliseconds;
|
||||
self
|
||||
}
|
||||
|
||||
/// Add allowed read path
|
||||
#[must_use]
|
||||
pub fn allow_read_path(mut self, path: PathBuf) -> Self {
|
||||
self.allowed_read_paths.push(path);
|
||||
self
|
||||
}
|
||||
|
||||
/// Add allowed write path
|
||||
#[must_use]
|
||||
pub fn allow_write_path(mut self, path: PathBuf) -> Self {
|
||||
self.allowed_write_paths.push(path);
|
||||
self
|
||||
}
|
||||
|
||||
/// Set default network access policy
|
||||
pub fn with_network_default(mut self, allow: bool) -> Self {
|
||||
#[must_use]
|
||||
pub const fn with_network_default(mut self, allow: bool) -> Self {
|
||||
self.allow_network_default = allow;
|
||||
self
|
||||
}
|
||||
|
||||
/// Validate capabilities requested by a plugin
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// Returns an error if the plugin requests capabilities that exceed the
|
||||
/// configured system limits, such as memory, CPU time, filesystem paths, or
|
||||
/// network access.
|
||||
pub fn validate_capabilities(
|
||||
&self,
|
||||
capabilities: &Capabilities,
|
||||
|
|
@ -115,8 +127,8 @@ impl CapabilityEnforcer {
|
|||
for path in &capabilities.filesystem.read {
|
||||
if !self.is_read_allowed(path) {
|
||||
return Err(anyhow!(
|
||||
"Plugin requests read access to {:?} which is not in allowed paths",
|
||||
path
|
||||
"Plugin requests read access to {} which is not in allowed paths",
|
||||
path.display()
|
||||
));
|
||||
}
|
||||
}
|
||||
|
|
@ -125,8 +137,8 @@ impl CapabilityEnforcer {
|
|||
for path in &capabilities.filesystem.write {
|
||||
if !self.is_write_allowed(path) {
|
||||
return Err(anyhow!(
|
||||
"Plugin requests write access to {:?} which is not in allowed paths",
|
||||
path
|
||||
"Plugin requests write access to {} which is not in allowed paths",
|
||||
path.display()
|
||||
));
|
||||
}
|
||||
}
|
||||
|
|
@ -135,6 +147,7 @@ impl CapabilityEnforcer {
|
|||
}
|
||||
|
||||
/// Check if a path is allowed for reading
|
||||
#[must_use]
|
||||
pub fn is_read_allowed(&self, path: &Path) -> bool {
|
||||
if self.allowed_read_paths.is_empty() {
|
||||
return false; // deny-all when unconfigured
|
||||
|
|
@ -150,6 +163,7 @@ impl CapabilityEnforcer {
|
|||
}
|
||||
|
||||
/// Check if a path is allowed for writing
|
||||
#[must_use]
|
||||
pub fn is_write_allowed(&self, path: &Path) -> bool {
|
||||
if self.allowed_write_paths.is_empty() {
|
||||
return false; // deny-all when unconfigured
|
||||
|
|
@ -173,11 +187,13 @@ impl CapabilityEnforcer {
|
|||
}
|
||||
|
||||
/// Check if network access is allowed for a plugin
|
||||
pub fn is_network_allowed(&self, capabilities: &Capabilities) -> bool {
|
||||
#[must_use]
|
||||
pub const fn is_network_allowed(&self, capabilities: &Capabilities) -> bool {
|
||||
capabilities.network.enabled && self.allow_network_default
|
||||
}
|
||||
|
||||
/// Check if a specific domain is allowed
|
||||
#[must_use]
|
||||
pub fn is_domain_allowed(
|
||||
&self,
|
||||
capabilities: &Capabilities,
|
||||
|
|
@ -197,11 +213,13 @@ impl CapabilityEnforcer {
|
|||
.network
|
||||
.allowed_domains
|
||||
.as_ref()
|
||||
.map(|domains| domains.iter().any(|d| d.eq_ignore_ascii_case(domain)))
|
||||
.unwrap_or(false)
|
||||
.is_some_and(|domains| {
|
||||
domains.iter().any(|d| d.eq_ignore_ascii_case(domain))
|
||||
})
|
||||
}
|
||||
|
||||
/// Get effective memory limit for a plugin
|
||||
#[must_use]
|
||||
pub fn get_memory_limit(&self, capabilities: &Capabilities) -> usize {
|
||||
capabilities
|
||||
.max_memory_bytes
|
||||
|
|
@ -210,6 +228,7 @@ impl CapabilityEnforcer {
|
|||
}
|
||||
|
||||
/// Get effective CPU time limit for a plugin
|
||||
#[must_use]
|
||||
pub fn get_cpu_time_limit(&self, capabilities: &Capabilities) -> u64 {
|
||||
capabilities
|
||||
.max_cpu_time_ms
|
||||
|
|
@ -264,8 +283,7 @@ mod tests {
|
|||
let test_file = allowed_dir.join("test.txt");
|
||||
std::fs::write(&test_file, "test").unwrap();
|
||||
|
||||
let enforcer =
|
||||
CapabilityEnforcer::new().allow_read_path(allowed_dir.clone());
|
||||
let enforcer = CapabilityEnforcer::new().allow_read_path(allowed_dir);
|
||||
|
||||
assert!(enforcer.is_read_allowed(&test_file));
|
||||
assert!(!enforcer.is_read_allowed(Path::new("/etc/passwd")));
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue