vanguard_plugin/
validator.rs

1use std::path::Path;
2use thiserror::Error;
3
4use crate::PluginMetadata;
5
6/// Errors that can occur during plugin validation
7#[derive(Error, Debug)]
8pub enum ValidationError {
9    /// Plugin signature verification failed
10    #[error("Signature verification failed: {0}")]
11    SignatureInvalid(String),
12
13    /// Plugin is not compatible with current platform
14    #[error("Platform not supported: {0}")]
15    PlatformIncompatible(String),
16
17    /// Plugin exceeds resource limits
18    #[error("Resource limit exceeded: {0}")]
19    ResourceLimitExceeded(String),
20
21    /// Plugin failed sandbox constraints
22    #[error("Sandbox constraint violation: {0}")]
23    SandboxViolation(String),
24
25    /// Plugin metadata is invalid
26    #[error("Invalid metadata: {0}")]
27    InvalidMetadata(String),
28}
29
30/// Result of plugin validation
31pub type ValidationResult = Result<(), ValidationError>;
32
33/// Plugin validator for security and compatibility checks
34#[derive(Debug)]
35pub struct PluginValidator {
36    /// Maximum memory usage in bytes
37    pub max_memory: usize,
38    /// Whether to enforce strict signature checks
39    pub strict_signatures: bool,
40    /// Whether to enforce sandboxing
41    pub enforce_sandbox: bool,
42}
43
44impl Default for PluginValidator {
45    fn default() -> Self {
46        Self::new()
47    }
48}
49
50impl PluginValidator {
51    /// Create a new plugin validator with default settings
52    pub fn new() -> Self {
53        Self {
54            max_memory: 100 * 1024 * 1024, // 100MB
55            strict_signatures: true,
56            enforce_sandbox: true,
57        }
58    }
59
60    /// Set maximum allowed memory usage
61    pub fn with_max_memory(mut self, max_bytes: usize) -> Self {
62        self.max_memory = max_bytes;
63        self
64    }
65
66    /// Set whether to enforce strict signature verification
67    pub fn with_strict_signatures(mut self, strict: bool) -> Self {
68        self.strict_signatures = strict;
69        self
70    }
71
72    /// Set whether to enforce sandbox constraints
73    pub fn with_sandbox(mut self, enforce: bool) -> Self {
74        self.enforce_sandbox = enforce;
75        self
76    }
77
78    /// Validate a plugin binary and its metadata
79    pub async fn validate_plugin(
80        &self,
81        binary_path: &Path,
82        metadata: &PluginMetadata,
83    ) -> ValidationResult {
84        // Validate metadata first
85        self.validate_metadata(metadata)?;
86
87        // Verify plugin signature if enabled
88        if self.strict_signatures {
89            self.verify_signature(binary_path)?;
90        }
91
92        // Check platform compatibility
93        self.check_platform_compatibility(metadata)?;
94
95        // Validate resource usage
96        self.validate_resources(binary_path)?;
97
98        // Check sandbox constraints
99        if self.enforce_sandbox {
100            self.check_sandbox_constraints(binary_path)?;
101        }
102
103        Ok(())
104    }
105
106    /// Validate plugin metadata
107    fn validate_metadata(&self, metadata: &PluginMetadata) -> ValidationResult {
108        // For now just check required fields are present
109        if metadata.name.is_empty() {
110            return Err(ValidationError::InvalidMetadata("name is required".into()));
111        }
112        if metadata.version.is_empty() {
113            return Err(ValidationError::InvalidMetadata(
114                "version is required".into(),
115            ));
116        }
117        Ok(())
118    }
119
120    /// Verify plugin binary signature
121    fn verify_signature(&self, _binary_path: &Path) -> ValidationResult {
122        // TODO: Implement actual signature verification
123        // For now just return Ok
124        Ok(())
125    }
126
127    /// Check if plugin is compatible with current platform
128    fn check_platform_compatibility(&self, _metadata: &PluginMetadata) -> ValidationResult {
129        // TODO: Implement actual platform checks
130        // For now just return Ok
131        Ok(())
132    }
133
134    /// Validate plugin resource usage
135    fn validate_resources(&self, _binary_path: &Path) -> ValidationResult {
136        // TODO: Implement actual resource validation
137        // For now just return Ok
138        Ok(())
139    }
140
141    /// Check plugin sandbox constraints
142    fn check_sandbox_constraints(&self, _binary_path: &Path) -> ValidationResult {
143        // TODO: Implement actual sandbox checks
144        // For now just return Ok
145        Ok(())
146    }
147}
148
149#[cfg(test)]
150mod tests {
151    use super::*;
152    use std::path::PathBuf;
153
154    fn create_test_metadata() -> PluginMetadata {
155        PluginMetadata {
156            name: "test-plugin".to_string(),
157            version: "1.0.0".to_string(),
158            description: "Test Plugin".to_string(),
159            author: "Test Author".to_string(),
160            min_vanguard_version: Some("0.1.0".to_string()),
161            max_vanguard_version: Some("2.0.0".to_string()),
162            dependencies: vec![],
163        }
164    }
165
166    #[tokio::test]
167    async fn test_validator_configuration() {
168        let validator = PluginValidator::new()
169            .with_max_memory(50 * 1024 * 1024)
170            .with_strict_signatures(false)
171            .with_sandbox(true);
172
173        assert_eq!(validator.max_memory, 50 * 1024 * 1024);
174        assert!(!validator.strict_signatures);
175        assert!(validator.enforce_sandbox);
176    }
177
178    #[tokio::test]
179    async fn test_metadata_validation() {
180        let validator = PluginValidator::new();
181        let metadata = create_test_metadata();
182
183        assert!(validator.validate_metadata(&metadata).is_ok());
184
185        // Test invalid metadata
186        let invalid_metadata = PluginMetadata {
187            name: "".to_string(),
188            ..metadata.clone()
189        };
190        assert!(matches!(
191            validator.validate_metadata(&invalid_metadata),
192            Err(ValidationError::InvalidMetadata(_))
193        ));
194    }
195
196    #[tokio::test]
197    async fn test_full_validation() {
198        let validator = PluginValidator::new();
199        let metadata = create_test_metadata();
200        let binary_path = PathBuf::from("test-binary");
201
202        let result = validator.validate_plugin(&binary_path, &metadata).await;
203        assert!(result.is_ok());
204    }
205}