Files

81 lines
2.9 KiB
Rust

// SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
// SPDX-License-Identifier: Apache-2.0
use openshell_core::proto::SandboxPolicy;
use openshell_supervisor_middleware::MiddlewareRegistry;
use tonic::Status;
/// Validate implementation-owned middleware config before accepting a policy.
pub async fn validate_policy(
registry: &MiddlewareRegistry,
policy: &SandboxPolicy,
) -> Result<(), Status> {
registry
.validate_policy_configs(policy)
.await
.map_err(|error| {
Status::invalid_argument(format!("policy middleware validation failed: {error}"))
})
}
#[cfg(test)]
mod tests {
use super::*;
use openshell_core::proto::NetworkMiddlewareConfig;
#[tokio::test]
async fn unregistered_external_middleware_is_rejected_before_admission() {
let policy = SandboxPolicy {
network_middlewares: std::collections::HashMap::from([(
"guard".into(),
NetworkMiddlewareConfig {
middleware: "example/content-guard".into(),
..Default::default()
},
)]),
..Default::default()
};
let error = validate_policy(&MiddlewareRegistry::default(), &policy)
.await
.expect_err("unregistered middleware must fail");
assert_eq!(error.code(), tonic::Code::InvalidArgument);
assert!(error.message().contains("not registered"));
}
#[tokio::test]
async fn invalid_builtin_config_is_rejected_by_implementation() {
let registry = MiddlewareRegistry::connect_services(
openshell_supervisor_middleware_builtins::services(),
Vec::new(),
)
.await
.expect("built-in registry");
let policy = SandboxPolicy {
network_middlewares: std::collections::HashMap::from([(
"redactor".into(),
NetworkMiddlewareConfig {
middleware: openshell_supervisor_middleware_builtins::BUILTIN_REGEX.into(),
config: Some(prost_types::Struct {
fields: std::iter::once((
"mode".into(),
prost_types::Value {
kind: Some(prost_types::value::Kind::StringValue("allow".into())),
},
))
.collect(),
}),
..Default::default()
},
)]),
..Default::default()
};
let error = validate_policy(&registry, &policy)
.await
.expect_err("invalid built-in config must fail admission");
assert_eq!(error.code(), tonic::Code::InvalidArgument);
assert!(error.message().contains("supports only mode: redact"));
}
}