This commit is contained in:
232
docs/VALIDATION.md
Normal file
232
docs/VALIDATION.md
Normal file
@@ -0,0 +1,232 @@
|
||||
# Input Validation & Sanitization
|
||||
|
||||
## Overview
|
||||
|
||||
AtlasOS implements comprehensive input validation and sanitization to ensure data integrity, security, and prevent injection attacks. All user inputs are validated before processing.
|
||||
|
||||
## Validation Rules
|
||||
|
||||
### ZFS Names (Pools, Datasets, ZVOLs, Snapshots)
|
||||
|
||||
**Rules:**
|
||||
- Must start with alphanumeric character
|
||||
- Can contain: `a-z`, `A-Z`, `0-9`, `_`, `-`, `.`, `:`
|
||||
- Cannot start with `-` or `.`
|
||||
- Maximum length: 256 characters
|
||||
- Cannot be empty
|
||||
|
||||
**Example:**
|
||||
```go
|
||||
if err := validation.ValidateZFSName("tank/data"); err != nil {
|
||||
// Handle error
|
||||
}
|
||||
```
|
||||
|
||||
### Usernames
|
||||
|
||||
**Rules:**
|
||||
- Minimum length: 3 characters
|
||||
- Maximum length: 32 characters
|
||||
- Can contain: `a-z`, `A-Z`, `0-9`, `_`, `-`, `.`
|
||||
- Must start with alphanumeric character
|
||||
|
||||
**Example:**
|
||||
```go
|
||||
if err := validation.ValidateUsername("admin"); err != nil {
|
||||
// Handle error
|
||||
}
|
||||
```
|
||||
|
||||
### Passwords
|
||||
|
||||
**Rules:**
|
||||
- Minimum length: 8 characters
|
||||
- Maximum length: 128 characters
|
||||
- Must contain at least one letter
|
||||
- Must contain at least one number
|
||||
|
||||
**Example:**
|
||||
```go
|
||||
if err := validation.ValidatePassword("SecurePass123"); err != nil {
|
||||
// Handle error
|
||||
}
|
||||
```
|
||||
|
||||
### Email Addresses
|
||||
|
||||
**Rules:**
|
||||
- Optional field (can be empty)
|
||||
- Maximum length: 254 characters
|
||||
- Must match email format pattern
|
||||
- Basic format validation (RFC 5322 simplified)
|
||||
|
||||
**Example:**
|
||||
```go
|
||||
if err := validation.ValidateEmail("user@example.com"); err != nil {
|
||||
// Handle error
|
||||
}
|
||||
```
|
||||
|
||||
### SMB Share Names
|
||||
|
||||
**Rules:**
|
||||
- Maximum length: 80 characters
|
||||
- Can contain: `a-z`, `A-Z`, `0-9`, `_`, `-`, `.`
|
||||
- Cannot be reserved Windows names (CON, PRN, AUX, NUL, COM1-9, LPT1-9)
|
||||
- Must start with alphanumeric character
|
||||
|
||||
**Example:**
|
||||
```go
|
||||
if err := validation.ValidateShareName("data-share"); err != nil {
|
||||
// Handle error
|
||||
}
|
||||
```
|
||||
|
||||
### iSCSI IQN (Qualified Name)
|
||||
|
||||
**Rules:**
|
||||
- Must start with `iqn.`
|
||||
- Format: `iqn.yyyy-mm.reversed.domain:identifier`
|
||||
- Maximum length: 223 characters
|
||||
- Year-month format validation
|
||||
|
||||
**Example:**
|
||||
```go
|
||||
if err := validation.ValidateIQN("iqn.2024-12.com.atlas:storage.target1"); err != nil {
|
||||
// Handle error
|
||||
}
|
||||
```
|
||||
|
||||
### Size Strings
|
||||
|
||||
**Rules:**
|
||||
- Format: number followed by optional unit (K, M, G, T, P)
|
||||
- Units: K (kilobytes), M (megabytes), G (gigabytes), T (terabytes), P (petabytes)
|
||||
- Case insensitive
|
||||
|
||||
**Examples:**
|
||||
- `"10"` - 10 bytes
|
||||
- `"10K"` - 10 kilobytes
|
||||
- `"1G"` - 1 gigabyte
|
||||
- `"2T"` - 2 terabytes
|
||||
|
||||
**Example:**
|
||||
```go
|
||||
if err := validation.ValidateSize("10G"); err != nil {
|
||||
// Handle error
|
||||
}
|
||||
```
|
||||
|
||||
### Filesystem Paths
|
||||
|
||||
**Rules:**
|
||||
- Must be absolute (start with `/`)
|
||||
- Maximum length: 4096 characters
|
||||
- Cannot contain `..` (path traversal)
|
||||
- Cannot contain `//` (double slashes)
|
||||
- Cannot contain null bytes
|
||||
|
||||
**Example:**
|
||||
```go
|
||||
if err := validation.ValidatePath("/tank/data"); err != nil {
|
||||
// Handle error
|
||||
}
|
||||
```
|
||||
|
||||
### CIDR/Hostname (NFS Clients)
|
||||
|
||||
**Rules:**
|
||||
- Can be wildcard: `*`
|
||||
- Can be CIDR notation: `192.168.1.0/24`
|
||||
- Can be hostname: `server.example.com`
|
||||
- Hostname must follow DNS rules
|
||||
|
||||
**Example:**
|
||||
```go
|
||||
if err := validation.ValidateCIDR("192.168.1.0/24"); err != nil {
|
||||
// Handle error
|
||||
}
|
||||
```
|
||||
|
||||
## Sanitization
|
||||
|
||||
### String Sanitization
|
||||
|
||||
Removes potentially dangerous characters:
|
||||
- Null bytes (`\x00`)
|
||||
- Control characters (ASCII < 32, except space)
|
||||
- Removes leading/trailing whitespace
|
||||
|
||||
**Example:**
|
||||
```go
|
||||
clean := validation.SanitizeString(userInput)
|
||||
```
|
||||
|
||||
### Path Sanitization
|
||||
|
||||
Normalizes filesystem paths:
|
||||
- Removes leading/trailing whitespace
|
||||
- Normalizes slashes (backslash to forward slash)
|
||||
- Removes multiple consecutive slashes
|
||||
|
||||
**Example:**
|
||||
```go
|
||||
cleanPath := validation.SanitizePath("/tank//data/")
|
||||
// Result: "/tank/data"
|
||||
```
|
||||
|
||||
## Integration
|
||||
|
||||
### In API Handlers
|
||||
|
||||
Validation is integrated into all create/update handlers:
|
||||
|
||||
```go
|
||||
func (a *App) handleCreatePool(w http.ResponseWriter, r *http.Request) {
|
||||
// ... decode request ...
|
||||
|
||||
// Validate pool name
|
||||
if err := validation.ValidateZFSName(req.Name); err != nil {
|
||||
writeError(w, errors.ErrValidation(err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
// ... continue with creation ...
|
||||
}
|
||||
```
|
||||
|
||||
### Error Responses
|
||||
|
||||
Validation errors return structured error responses:
|
||||
|
||||
```json
|
||||
{
|
||||
"code": "VALIDATION_ERROR",
|
||||
"message": "validation error on field 'name': name cannot be empty",
|
||||
"details": ""
|
||||
}
|
||||
```
|
||||
|
||||
## Security Benefits
|
||||
|
||||
1. **Injection Prevention**: Validates inputs prevent command injection
|
||||
2. **Path Traversal Protection**: Path validation prevents directory traversal
|
||||
3. **Data Integrity**: Ensures data conforms to expected formats
|
||||
4. **System Stability**: Prevents invalid operations that could crash services
|
||||
5. **User Experience**: Clear error messages guide users to correct input
|
||||
|
||||
## Best Practices
|
||||
|
||||
1. **Validate Early**: Validate inputs as soon as they're received
|
||||
2. **Sanitize Before Storage**: Sanitize strings before storing in database
|
||||
3. **Validate Format**: Check format before parsing (e.g., size strings)
|
||||
4. **Check Length**: Enforce maximum lengths to prevent DoS
|
||||
5. **Whitelist Characters**: Only allow known-safe characters
|
||||
|
||||
## Future Enhancements
|
||||
|
||||
1. **Custom Validators**: Domain-specific validation rules
|
||||
2. **Validation Middleware**: Automatic validation for all endpoints
|
||||
3. **Schema Validation**: JSON schema validation
|
||||
4. **Rate Limiting**: Prevent abuse through validation
|
||||
5. **Input Normalization**: Automatic normalization of valid inputs
|
||||
Reference in New Issue
Block a user