🦀 Database Security in TuskLang for Rust
Database Security in TuskLang for Rust
TuskLang's Rust database security system provides type-safe, comprehensive security features with compile-time guarantees, async/await support, and robust protection against common database vulnerabilities.
🚀 Why Rust Database Security?
Rust's type system and ownership model make it the perfect language for database security:
- Memory Safety: No buffer overflows or memory corruption vulnerabilities - Type Safety: Compile-time validation of security policies - Zero-Cost Abstractions: No performance penalty for security features - Async/Await: Non-blocking security operations - Security Guarantees: Guaranteed protection against common attacks
Basic Security Features
use tusk_db::{SecurityManager, SecurityPolicy, Result};
use serde::{Deserialize, Serialize};
use chrono::{DateTime, Utc};#[derive(Debug, Serialize, Deserialize, Clone)]
struct User {
pub id: Option<i32>,
pub name: String,
pub email: String,
pub password_hash: String,
pub is_active: bool,
pub role: String,
pub created_at: Option<DateTime<Utc>>,
pub updated_at: Option<DateTime<Utc>>,
}
#[derive(Debug, Serialize, Deserialize, Clone)]
struct Post {
pub id: Option<i32>,
pub title: String,
pub content: String,
pub user_id: i32,
pub published: bool,
pub created_at: Option<DateTime<Utc>>,
pub updated_at: Option<DateTime<Utc>>,
}
// Basic security manager
async fn secure_database_operations() -> Result<()> {
let security_manager = @SecurityManager::new().await?;
// Configure security policies
security_manager.set_policy(SecurityPolicy {
sql_injection_protection: true,
parameterized_queries: true,
input_validation: true,
output_encoding: true,
access_control: true,
audit_logging: true,
}).await?;
// Secure query execution
let users = @db.table::<User>("users")
.where_eq("is_active", true)
.secure() // Enable security features
.get()
.await?;
Ok(())
}
// Input validation and sanitization
async fn secure_user_creation(user_data: User) -> Result<User> {
let validator = @InputValidator::new().await?;
// Validate input data
let validation_result = validator.validate(&user_data).await?;
if !validation_result.is_valid() {
return Err(ValidationError::new("Invalid user data", validation_result.errors).into());
}
// Sanitize input
let sanitized_user = validator.sanitize(user_data).await?;
// Create user with security checks
let user = @User::create(sanitized_user)
.secure()
.await?;
Ok(user)
}
SQL Injection Protection
use tusk_db::{SqlInjectionProtection, ParameterizedQuery};// SQL injection protection
async fn sql_injection_protection() -> Result<Vec<User>> {
let protection = @SqlInjectionProtection::new().await?;
// Enable protection
protection.enable(true).await?;
// Safe parameterized query
let email = "user@example.com";
let users = @db.table::<User>("users")
.where_eq("email", email) // Automatically parameterized
.secure()
.get()
.await?;
// Dynamic query with protection
let search_term = "john";
let users = @db.table::<User>("users")
.where_like("name", &format!("%{}%", search_term))
.secure()
.get()
.await?;
// Raw query with parameterization
let user_id = 123;
let users = @db.raw::<User>(
"SELECT * FROM users WHERE id = ? AND is_active = ?",
&[&user_id, &true]
).secure().await?;
Ok(users)
}
// Protection against malicious input
async fn malicious_input_protection() -> Result<()> {
let protection = @SqlInjectionProtection::new().await?;
// Test malicious input
let malicious_inputs = vec![
"'; DROP TABLE users; --",
"' OR '1'='1",
"'; INSERT INTO users VALUES (1, 'hacker', 'hack@evil.com'); --",
"admin'--",
];
for malicious_input in malicious_inputs {
// This should be safely handled
let users = @db.table::<User>("users")
.where_eq("email", malicious_input)
.secure()
.get()
.await?;
// Verify no unauthorized access
assert!(users.is_empty());
}
Ok(())
}
Access Control and Authorization
use tusk_db::{AccessControl, Authorization, Permission};// Access control system
async fn access_control_example() -> Result<Vec<Post>> {
let access_control = @AccessControl::new().await?;
// Define permissions
let user_permissions = vec![
Permission::Read("posts"),
Permission::Create("posts"),
Permission::Update("posts", "own"),
Permission::Delete("posts", "own"),
];
// Set user context
let current_user_id = 123;
access_control.set_user_context(current_user_id, &user_permissions).await?;
// Query with access control
let posts = @db.table::<Post>("posts")
.where_eq("user_id", current_user_id) // Only own posts
.secure()
.authorize(&access_control)
.get()
.await?;
Ok(posts)
}
// Role-based access control
async fn role_based_access_control() -> Result<()> {
let rbac = @RoleBasedAccessControl::new().await?;
// Define roles and permissions
rbac.define_role("admin", &[
Permission::All("users"),
Permission::All("posts"),
Permission::All("comments"),
]).await?;
rbac.define_role("moderator", &[
Permission::Read("users"),
Permission::All("posts"),
Permission::All("comments"),
]).await?;
rbac.define_role("user", &[
Permission::Read("users", "public"),
Permission::Create("posts"),
Permission::Update("posts", "own"),
Permission::Delete("posts", "own"),
Permission::Create("comments"),
Permission::Update("comments", "own"),
Permission::Delete("comments", "own"),
]).await?;
// Assign role to user
let user_id = 123;
rbac.assign_role(user_id, "user").await?;
// Check permissions
let can_create_post = rbac.has_permission(user_id, &Permission::Create("posts")).await?;
let can_delete_any_post = rbac.has_permission(user_id, &Permission::Delete("posts", "any")).await?;
assert!(can_create_post);
assert!(!can_delete_any_post);
Ok(())
}
// Row-level security
async fn row_level_security() -> Result<Vec<Post>> {
let rls = @RowLevelSecurity::new().await?;
// Enable RLS on posts table
rls.enable("posts", |user_id| {
// Users can only see their own posts or published posts
format!("user_id = {} OR published = true", user_id)
}).await?;
let current_user_id = 123;
// Query with RLS automatically applied
let posts = @db.table::<Post>("posts")
.secure()
.with_rls(current_user_id)
.get()
.await?;
// Verify RLS is working
for post in &posts {
assert!(post.user_id == current_user_id || post.published);
}
Ok(posts)
}
Data Encryption and Protection
use tusk_db::{DataEncryption, EncryptionKey, EncryptedField};// Data encryption
async fn data_encryption_example() -> Result<()> {
let encryption = @DataEncryption::new().await?;
// Generate encryption key
let key = @EncryptionKey::generate().await?;
encryption.set_key(&key).await?;
// Encrypt sensitive data
let sensitive_user = User {
id: None,
name: "John Doe".to_string(),
email: "john@example.com".to_string(),
password_hash: hash_password("secret123"),
is_active: true,
role: "user".to_string(),
created_at: None,
updated_at: None,
};
// Encrypt specific fields
let encrypted_user = encryption.encrypt_fields(&sensitive_user, &["email", "password_hash"]).await?;
// Save encrypted user
let saved_user = @User::create(encrypted_user)
.secure()
.await?;
// Decrypt when needed
let decrypted_user = encryption.decrypt_fields(&saved_user, &["email", "password_hash"]).await?;
assert_eq!(decrypted_user.email, "john@example.com");
Ok(())
}
// Field-level encryption
#[derive(Debug, Serialize, Deserialize, Clone)]
struct SecureUser {
pub id: Option<i32>,
pub name: String,
#[encrypted]
pub email: String,
#[encrypted]
pub password_hash: String,
pub is_active: bool,
pub role: String,
pub created_at: Option<DateTime<Utc>>,
pub updated_at: Option<DateTime<Utc>>,
}
// Automatic encryption/decryption
async fn automatic_encryption() -> Result<()> {
let encryption = @DataEncryption::new().await?;
// Enable automatic encryption
encryption.enable_automatic_encryption(true).await?;
// Create user with automatic encryption
let user = SecureUser {
id: None,
name: "Jane Doe".to_string(),
email: "jane@example.com".to_string(),
password_hash: hash_password("secret456"),
is_active: true,
role: "user".to_string(),
created_at: None,
updated_at: None,
};
// Save with automatic encryption
let saved_user = @SecureUser::create(user)
.secure()
.await?;
// Retrieve with automatic decryption
let retrieved_user = @SecureUser::find(saved_user.id.unwrap())
.secure()
.await?;
assert_eq!(retrieved_user.email, "jane@example.com");
Ok(())
}
Audit Logging and Monitoring
use tusk_db::{AuditLogger, AuditEvent, SecurityMonitor};// Audit logging
async fn audit_logging_example() -> Result<()> {
let audit_logger = @AuditLogger::new().await?;
// Enable audit logging
audit_logger.enable(true).await?;
// Configure audit events
audit_logger.log_events(&[
AuditEvent::DataAccess,
AuditEvent::DataModification,
AuditEvent::Authentication,
AuditEvent::Authorization,
AuditEvent::SecurityViolation,
]).await?;
// Perform operations with audit logging
let user_id = 123;
// This will be logged
let users = @db.table::<User>("users")
.where_eq("id", user_id)
.secure()
.audit(&audit_logger)
.get()
.await?;
// This will also be logged
let updated_user = @db.table::<User>("users")
.where_eq("id", user_id)
.update(&[("is_active", &false)])
.secure()
.audit(&audit_logger)
.await?;
// Retrieve audit logs
let audit_logs = audit_logger.get_logs(
Utc::now() - chrono::Duration::hours(1),
Utc::now()
).await?;
for log in &audit_logs {
@log::info!("Audit log", {
timestamp: log.timestamp,
user_id: log.user_id,
action: &log.action,
table: &log.table,
details: &log.details,
});
}
Ok(())
}
// Security monitoring
async fn security_monitoring() -> Result<()> {
let security_monitor = @SecurityMonitor::new().await?;
// Enable security monitoring
security_monitor.enable(true).await?;
// Set up alerts
security_monitor.set_alerts(&[
SecurityAlert::SqlInjectionAttempt,
SecurityAlert::UnauthorizedAccess,
SecurityAlert::DataExfiltration,
SecurityAlert::PrivilegeEscalation,
]).await?;
// Monitor in real-time
let mut alert_stream = security_monitor.subscribe_to_alerts().await?;
tokio::spawn(async move {
while let Some(alert) = alert_stream.recv().await {
match alert {
SecurityAlert::SqlInjectionAttempt(details) => {
@log::error!("SQL Injection attempt detected", {
ip: &details.ip_address,
query: &details.query,
timestamp: details.timestamp,
});
// Take action (block IP, notify admin, etc.)
@block_ip_address(&details.ip_address).await?;
}
SecurityAlert::UnauthorizedAccess(details) => {
@log::warn!("Unauthorized access attempt", {
user_id: details.user_id,
resource: &details.resource,
action: &details.action,
});
}
_ => {}
}
}
});
Ok(())
}
Input Validation and Sanitization
use tusk_db::{InputValidator, ValidationRule, Sanitizer};// Comprehensive input validation
async fn input_validation_example() -> Result<User> {
let validator = @InputValidator::new().await?;
// Define validation rules
let validation_rules = vec![
ValidationRule::new("name", |value| {
if value.len() < 2 || value.len() > 100 {
return Err("Name must be between 2 and 100 characters".into());
}
if !value.chars().all(|c| c.is_alphanumeric() || c.is_whitespace()) {
return Err("Name contains invalid characters".into());
}
Ok(())
}),
ValidationRule::new("email", |value| {
if !value.contains('@') || !value.contains('.') {
return Err("Invalid email format".into());
}
if value.len() > 255 {
return Err("Email too long".into());
}
Ok(())
}),
ValidationRule::new("role", |value| {
let allowed_roles = vec!["user", "moderator", "admin"];
if !allowed_roles.contains(&value.as_str()) {
return Err("Invalid role".into());
}
Ok(())
}),
];
// Validate user data
let user_data = User {
id: None,
name: "John Doe".to_string(),
email: "john@example.com".to_string(),
password_hash: hash_password("secret123"),
is_active: true,
role: "user".to_string(),
created_at: None,
updated_at: None,
};
let validation_result = validator.validate_with_rules(&user_data, &validation_rules).await?;
if !validation_result.is_valid() {
return Err(ValidationError::new("Validation failed", validation_result.errors).into());
}
// Sanitize input
let sanitizer = @Sanitizer::new().await?;
let sanitized_user = sanitizer.sanitize(&user_data).await?;
// Create user
let user = @User::create(sanitized_user)
.secure()
.await?;
Ok(user)
}
// XSS protection
async fn xss_protection() -> Result<()> {
let sanitizer = @Sanitizer::new().await?;
// Test XSS attempts
let xss_attempts = vec![
"<script>alert('xss')</script>",
"javascript:alert('xss')",
"<img src=x onerror=alert('xss')>",
"'; DROP TABLE users; --",
];
for xss_attempt in xss_attempts {
let sanitized = sanitizer.sanitize_html(xss_attempt).await?;
// Verify XSS was removed
assert!(!sanitized.contains("<script>"));
assert!(!sanitized.contains("javascript:"));
assert!(!sanitized.contains("onerror="));
}
Ok(())
}
Connection Security
use tusk_db::{ConnectionSecurity, SslConfig, ConnectionPool};// Secure database connections
async fn secure_connection_setup() -> Result<()> {
let connection_security = @ConnectionSecurity::new().await?;
// Configure SSL/TLS
let ssl_config = SslConfig {
enabled: true,
verify_cert: true,
ca_cert_path: "certs/ca.crt".to_string(),
client_cert_path: "certs/client.crt".to_string(),
client_key_path: "certs/client.key".to_string(),
};
connection_security.set_ssl_config(ssl_config).await?;
// Configure connection encryption
connection_security.enable_encryption(true).await?;
connection_security.set_encryption_algorithm("AES-256-GCM").await?;
// Secure connection pool
let pool = @ConnectionPool::new()
.with_security(&connection_security)
.max_connections(10)
.min_connections(2)
.connection_timeout(30)
.idle_timeout(300)
.build()
.await?;
// Use secure connection
let db = @Database::with_pool(pool).await?;
Ok(())
}
// Connection monitoring
async fn connection_monitoring() -> Result<()> {
let connection_monitor = @ConnectionMonitor::new().await?;
// Monitor connection security
connection_monitor.enable(true).await?;
// Set up connection alerts
connection_monitor.set_alerts(&[
ConnectionAlert::UnauthorizedConnection,
ConnectionAlert::FailedAuthentication,
ConnectionAlert::SslError,
ConnectionAlert::ConnectionLimitExceeded,
]).await?;
// Monitor connection metrics
let metrics = connection_monitor.get_metrics().await?;
@log::info!("Connection metrics", {
active_connections: metrics.active_connections,
total_connections: metrics.total_connections,
failed_connections: metrics.failed_connections,
ssl_connections: metrics.ssl_connections,
});
Ok(())
}
Security Testing and Validation
use tusk_db::test_utils::{SecurityTest, VulnerabilityScanner};// Security testing
#[tokio::test]
async fn test_sql_injection_protection() -> Result<()> {
let security_test = @SecurityTest::new().await?;
// Test SQL injection attempts
let injection_attempts = vec![
"'; DROP TABLE users; --",
"' OR '1'='1",
"'; INSERT INTO users VALUES (1, 'hacker', 'hack@evil.com'); --",
"admin'--",
"1' UNION SELECT * FROM users--",
];
for attempt in injection_attempts {
let result = @db.table::<User>("users")
.where_eq("email", attempt)
.secure()
.get()
.await;
// Should not panic or return unauthorized data
assert!(result.is_ok());
let users = result?;
// Should return empty result for malicious input
assert!(users.is_empty());
}
Ok(())
}
// Vulnerability scanning
#[tokio::test]
async fn test_vulnerability_scanning() -> Result<()> {
let scanner = @VulnerabilityScanner::new().await?;
// Scan for common vulnerabilities
let vulnerabilities = scanner.scan_database().await?;
for vulnerability in &vulnerabilities {
@log::warn!("Vulnerability found", {
type_: &vulnerability.vuln_type,
severity: vulnerability.severity,
description: &vulnerability.description,
recommendation: &vulnerability.recommendation,
});
}
// Assert no critical vulnerabilities
let critical_vulns = vulnerabilities.iter()
.filter(|v| v.severity == Severity::Critical)
.count();
assert_eq!(critical_vulns, 0, "Critical vulnerabilities found");
Ok(())
}
// Penetration testing
async fn penetration_testing() -> Result<()> {
let pen_tester = @PenetrationTester::new().await?;
// Run penetration tests
let test_results = pen_tester.run_tests(&[
PenTest::SqlInjection,
PenTest::AuthenticationBypass,
PenTest::PrivilegeEscalation,
PenTest::DataExfiltration,
PenTest::DenialOfService,
]).await?;
for result in &test_results {
if result.vulnerable {
@log::error!("Security vulnerability detected", {
test: &result.test_name,
description: &result.description,
severity: result.severity,
});
} else {
@log::info!("Security test passed", {
test: &result.test_name,
});
}
}
// Assert all tests passed
let failed_tests = test_results.iter()
.filter(|r| r.vulnerable)
.count();
assert_eq!(failed_tests, 0, "Security tests failed");
Ok(())
}
Security Best Practices
use tusk_db::{SecurityBestPractices, SecurityGuidelines};// Security best practices implementation
async fn security_best_practices() -> Result<()> {
let security_manager = @SecurityManager::new().await?;
// 1. Always use parameterized queries
let email = "user@example.com";
let users = @db.table::<User>("users")
.where_eq("email", email) // Parameterized
.secure()
.get()
.await?;
// 2. Validate and sanitize all input
let validator = @InputValidator::new().await?;
let sanitizer = @Sanitizer::new().await?;
let user_input = "user@example.com<script>alert('xss')</script>";
let validated = validator.validate_email(user_input).await?;
let sanitized = sanitizer.sanitize_html(&validated).await?;
// 3. Implement proper access control
let access_control = @AccessControl::new().await?;
access_control.require_permission("users", "read").await?;
// 4. Use encryption for sensitive data
let encryption = @DataEncryption::new().await?;
encryption.encrypt_field("password_hash").await?;
// 5. Enable audit logging
let audit_logger = @AuditLogger::new().await?;
audit_logger.enable(true).await?;
// 6. Use secure connections
let connection_security = @ConnectionSecurity::new().await?;
connection_security.enable_ssl(true).await?;
// 7. Implement rate limiting
let rate_limiter = @RateLimiter::new().await?;
rate_limiter.limit_requests("login", 5, 300).await?; // 5 attempts per 5 minutes
// 8. Use strong authentication
let auth = @Authentication::new().await?;
auth.require_strong_password().await?;
auth.enable_mfa(true).await?;
// 9. Regular security updates
let updater = @SecurityUpdater::new().await?;
updater.check_for_updates().await?;
// 10. Monitor for security events
let monitor = @SecurityMonitor::new().await?;
monitor.enable(true).await?;
Ok(())
}
Best Practices for Rust Database Security
1. Use Strong Types: Leverage Rust's type system for security validation 2. Parameterized Queries: Always use parameterized queries to prevent SQL injection 3. Input Validation: Validate and sanitize all user input 4. Access Control: Implement proper role-based access control 5. Encryption: Encrypt sensitive data at rest and in transit 6. Audit Logging: Log all security-relevant events 7. Connection Security: Use SSL/TLS for database connections 8. Rate Limiting: Implement rate limiting for authentication attempts 9. Security Testing: Regularly test for vulnerabilities 10. Security Monitoring: Continuously monitor for security threats
Related Topics
- database-overview-rust
- Database integration overview
- query-builder-rust
- Fluent query interface
- orm-models-rust
- Model definition and usage
- migrations-rust
- Database schema versioning
- relationships-rust
- Model relationships
---
Ready to build type-safe, secure database applications with Rust and TuskLang?