Security Considerations #
Comprehensive security guide for Server Monitor plugin deployment, covering authentication, data protection, and best practices.
Security Architecture #
Multi-Layered Security #
The Server Monitor plugin implements security at multiple levels:
- Application Layer - Authentication, authorization, input validation
- Database Layer - Organization isolation, encrypted data
- Network Layer - API key protection, HTTPS enforcement
- Infrastructure Layer - Server hardening, access controls
Threat Model #
Protected Assets:
- Server endpoint URLs (may reveal infrastructure)
- User contact information (email, phone)
- Organization data and relationships
- Monitoring status and uptime data
- Communication logs and costs
Threat Vectors:
- Unauthorized access to monitoring data
- Cross-organization data leakage
- API key compromise
- Injection attacks via server endpoints
- Social engineering for notification access
Authentication and Authorization #
User Authentication #
SaasBase Integration:
// Authentication handled by SaasBase
$user = BackendAuth::getUser();
if (!$user) {
return Redirect::to('backend/auth/signin');
}
Multi-Factor Authentication:
- Inherits MFA settings from SaasBase
- Organization admins should enable MFA
- Consider mandatory MFA for organizations with sensitive infrastructure
Authorization Controls #
Organization-Based Access:
// Users can only access their organization's data
public $implement = ['@'.\Albrightlabs\SaasBase\Behaviors\OwnableBehavior::class];
// Automatic scoping applied to all queries
$servers = Server::all(); // Only returns current user's organization servers
Role-Based Permissions:
// Organization admin check
if (!$user->is_organization_admin && !str_contains($user->email, '@albrightlabs.com')) {
Flash::error('Access denied. You must be an organization administrator.');
return Redirect::to('backend');
}
API Access Control:
// API key validation
$validApiKey = Config::get('albrightlabs.servermonitor::config.api_key');
if (!$validApiKey || $api_key !== $validApiKey) {
return response()->json(['success' => false, 'message' => 'Invalid API key'], 403);
}
Data Protection #
Data Encryption #
In Transit:
- All API communications over HTTPS
- Email notifications via encrypted SMTP
- Database connections with SSL/TLS
At Rest:
- Database encryption for sensitive fields
- API keys stored in environment variables
- Log files with restricted permissions
Implementation:
# Force HTTPS in production
APP_ENV=production
APP_DEBUG=false
FORCE_HTTPS=true
# Database encryption
DB_SSL_MODE=require
DB_SSL_CERT=/path/to/client-cert.pem
DB_SSL_KEY=/path/to/client-key.pem
DB_SSL_CA=/path/to/ca-cert.pem
Data Minimization #
Principle of Least Data:
// Only collect necessary information
$server = new Server();
$server->title = $input['title']; // Required for identification
$server->endpoint = $input['endpoint']; // Required for monitoring
// No collection of additional metadata unless necessary
Automatic Data Purging:
// Plan-based log retention
'plans' => [
'free' => ['log_retention_days' => 7],
'basic' => ['log_retention_days' => 30],
'pro' => ['log_retention_days' => 90],
'enterprise' => ['log_retention_days' => 90],
]
Personal Data Handling #
PII Protection:
- Email addresses encrypted in notifications settings
- Phone numbers hashed when not in use
- Communication logs anonymized after retention period
GDPR Compliance Considerations:
// Right to erasure implementation
public function deleteUserData($userId)
{
// Remove user from notification settings
$settings = NotificationSetting::all();
foreach ($settings as $setting) {
$admins = $setting->administrators;
$admins = array_filter($admins, function($admin) use ($userId) {
return $admin['user_id'] !== $userId;
});
$setting->administrators = $admins;
$setting->save();
}
// Anonymize communication logs
AlertLog::where('recipient', 'LIKE', "%{$userEmail}%")
->update(['recipient' => 'ANONYMIZED']);
}
API Security #
API Key Management #
Strong Key Generation:
# Generate cryptographically secure API key
openssl rand -base64 32
# Or using PHP
php -r "echo base64_encode(random_bytes(32));"
Key Rotation:
#!/bin/bash
# rotate-api-key.sh - Run monthly
OLD_KEY=$(grep SERVER_MONITOR_API_KEY .env | cut -d'=' -f2)
NEW_KEY=$(openssl rand -base64 32)
# Update environment
sed -i "s/SERVER_MONITOR_API_KEY=$OLD_KEY/SERVER_MONITOR_API_KEY=$NEW_KEY/" .env
# Update cron jobs
crontab -l | sed "s/$OLD_KEY/$NEW_KEY/g" | crontab -
# Restart application
php artisan config:clear
supervisorctl restart servermonitor-*:*
echo "API key rotated from $OLD_KEY to $NEW_KEY"
Key Storage Security:
# Secure .env file permissions
chmod 600 .env
chown www-data:www-data .env
# Prevent web access to .env
# Add to .htaccess or nginx config:
# location ~ /\.env {
# deny all;
# }
Rate Limiting #
API Rate Limiting:
// Implement rate limiting for API endpoints
Route::middleware(['throttle:60,1'])->group(function () {
Route::get('/api/servermonitor/check/{type}/{api_key}', function ($type, $api_key) {
// API endpoint logic
});
});
Nginx Rate Limiting:
# Limit API requests
location /api/servermonitor/ {
limit_req zone=api burst=10 nodelay;
limit_req_status 429;
# Continue to PHP processing
try_files $uri $uri/ /index.php?$query_string;
}
# Define rate limit zone
http {
limit_req_zone $binary_remote_addr zone=api:10m rate=30r/m;
}
IP Whitelisting #
Restrict API Access:
# Allow only specific IPs for API access
location /api/servermonitor/ {
allow 192.168.1.0/24; # Internal network
allow 10.0.0.0/8; # Private networks
allow 203.0.113.0/24; # Your office network
deny all;
try_files $uri $uri/ /index.php?$query_string;
}
Environment-Based Restrictions:
// IP whitelist in environment
$allowedIps = explode(',', env('API_ALLOWED_IPS', ''));
$clientIp = request()->ip();
if (!empty($allowedIps) && !in_array($clientIp, $allowedIps)) {
return response()->json(['error' => 'IP not allowed'], 403);
}
Input Validation and Sanitization #
Server Endpoint Validation #
URL Validation:
// Strict URL validation for server endpoints
public $rules = [
'title' => 'required|string|max:255',
'endpoint' => 'required|url|regex:/^https?:\/\//'
];
// Additional security validation
public function beforeSave()
{
// Prevent monitoring internal/private networks
$url = parse_url($this->endpoint);
$host = $url['host'];
// Block private networks
if (filter_var($host, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE) === false) {
throw new ValidationException(['endpoint' => 'Cannot monitor private or reserved IP addresses']);
}
// Block common internal hostnames
$blockedHosts = ['localhost', '127.0.0.1', '0.0.0.0', 'metadata.google.internal'];
if (in_array(strtolower($host), $blockedHosts)) {
throw new ValidationException(['endpoint' => 'Cannot monitor internal hostnames']);
}
}
Communication Data Sanitization #
Email Content Sanitization:
// Sanitize notification content
$content = strip_tags($server->title . ': ' . $log->note);
$content = substr($content, 0, 160); // SMS length limit
// Validate email addresses
if (!filter_var($admin->email, FILTER_VALIDATE_EMAIL)) {
Log::warning("Invalid email address for user {$admin->id}: {$admin->email}");
continue;
}
Phone Number Validation:
// Validate and normalize phone numbers
$phoneNumber = preg_replace('/[^0-9]/', '', $admin->phone_number);
if (!preg_match('/^1?[0-9]{10}$/', $phoneNumber)) {
Log::warning("Invalid phone number for user {$admin->id}");
continue;
}
Infrastructure Security #
Server Hardening #
Operating System Security:
# Update system packages
sudo apt update && sudo apt upgrade -y
# Configure firewall
sudo ufw enable
sudo ufw allow 22/tcp # SSH
sudo ufw allow 80/tcp # HTTP
sudo ufw allow 443/tcp # HTTPS
sudo ufw deny 3306/tcp # Block direct database access
# Disable unnecessary services
sudo systemctl disable apache2 # If using nginx
sudo systemctl disable sendmail # If using different mailer
Web Server Security:
# Nginx security headers
server {
# Security headers
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "no-referrer-when-downgrade" always;
add_header Content-Security-Policy "default-src 'self' https: data: 'unsafe-inline' 'unsafe-eval'" always;
# Hide server version
server_tokens off;
# Prevent access to sensitive files
location ~ /\.(env|git|svn) {
deny all;
return 404;
}
location ~ /(config|storage|bootstrap|vendor) {
deny all;
return 404;
}
}
Database Security #
Database Hardening:
-- Create dedicated database user
CREATE USER 'servermonitor'@'localhost' IDENTIFIED BY 'strong_random_password';
GRANT SELECT, INSERT, UPDATE, DELETE ON servermonitor.* TO 'servermonitor'@'localhost';
FLUSH PRIVILEGES;
-- Remove default users
DROP USER ''@'localhost';
DROP USER ''@'hostname';
DROP USER 'root'@'hostname';
-- Secure root account
UPDATE mysql.user SET Password=PASSWORD('very_strong_root_password') WHERE User='root';
FLUSH PRIVILEGES;
Connection Security:
# Use SSL for database connections
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=servermonitor
DB_USERNAME=servermonitor
DB_PASSWORD=strong_random_password
DB_SSL_MODE=required
Monitoring and Logging #
Security Event Logging #
Authentication Events:
// Log authentication attempts
Event::listen('auth.login', function ($user) {
Log::info("User login: {$user->email} from " . request()->ip());
});
Event::listen('auth.failed', function ($credentials) {
Log::warning("Failed login attempt: {$credentials['email']} from " . request()->ip());
});
API Access Logging:
// Log all API access attempts
Route::middleware('log.api')->group(function () {
// API routes
});
// Middleware implementation
class LogApiAccess
{
public function handle($request, Closure $next)
{
$response = $next($request);
Log::info('API Access', [
'endpoint' => $request->path(),
'ip' => $request->ip(),
'user_agent' => $request->userAgent(),
'status' => $response->status(),
]);
return $response;
}
}
Intrusion Detection #
Suspicious Activity Detection:
#!/bin/bash
# security-monitor.sh - Run every 5 minutes
# Check for repeated failed logins
FAILED_LOGINS=$(grep "Failed login attempt" storage/logs/laravel.log | grep "$(date '+%Y-%m-%d %H:%M')" | wc -l)
if [ $FAILED_LOGINS -gt 10 ]; then
echo "ALERT: $FAILED_LOGINS failed login attempts in last minute" | mail -s "Security Alert" security@yourcompany.com
fi
# Check for API abuse
API_ERRORS=$(grep "Invalid API key" storage/logs/laravel.log | grep "$(date '+%Y-%m-%d %H:%M')" | wc -l)
if [ $API_ERRORS -gt 5 ]; then
echo "ALERT: $API_ERRORS invalid API key attempts in last minute" | mail -s "API Security Alert" security@yourcompany.com
fi
Log Analysis:
# Daily security log analysis
#!/bin/bash
# analyze-security-logs.sh
echo "Security Log Analysis for $(date)"
echo "================================="
# Failed authentication attempts
echo "Failed Login Attempts:"
grep "Failed login attempt" storage/logs/laravel.log | tail -10
# API key violations
echo -e "\nAPI Key Violations:"
grep "Invalid API key" storage/logs/laravel.log | tail -10
# Suspicious endpoints
echo -e "\nSuspicious Endpoint Access:"
grep -E "(\.env|config|admin|phpmyadmin)" /var/log/nginx/access.log | tail -10
Incident Response #
Security Incident Procedures #
Immediate Response:
- Isolate - Block suspicious IP addresses
- Assess - Determine scope of potential breach
- Contain - Disable compromised accounts/API keys
- Investigate - Review logs and system integrity
- Notify - Alert relevant stakeholders
- Recover - Restore services with enhanced security
API Key Compromise Response:
#!/bin/bash
# emergency-api-rotation.sh
echo "EMERGENCY: Rotating all API keys"
# Generate new API key
NEW_KEY=$(openssl rand -base64 32)
# Update environment
cp .env .env.backup.$(date +%Y%m%d_%H%M%S)
sed -i "s/SERVER_MONITOR_API_KEY=.*/SERVER_MONITOR_API_KEY=$NEW_KEY/" .env
# Clear application cache
php artisan config:clear
# Restart services
supervisorctl restart servermonitor-*:*
# Update monitoring systems with new key
echo "NEW API KEY: $NEW_KEY"
echo "UPDATE ALL MONITORING SYSTEMS IMMEDIATELY"
# Log incident
echo "$(date): Emergency API key rotation - Key compromised" >> security-incidents.log
Data Breach Response #
Assessment Checklist:
- [ ] Identify compromised data types
- [ ] Determine number of affected organizations
- [ ] Check for cross-organization data exposure
- [ ] Verify integrity of monitoring data
- [ ] Assess notification system compromise
Communication Template:
Subject: Security Incident Notification
We are writing to inform you of a security incident that may have affected your monitoring data.
INCIDENT DETAILS:
- Date/Time: [TIMESTAMP]
- Nature: [BRIEF DESCRIPTION]
- Data Affected: [SPECIFIC DATA TYPES]
- Organizations Affected: [NUMBER]
IMMEDIATE ACTIONS TAKEN:
- [LIST CONTAINMENT MEASURES]
- [LIST SECURITY ENHANCEMENTS]
RECOMMENDED USER ACTIONS:
- Review monitoring configurations
- Update passwords if applicable
- Monitor for suspicious activity
We take security seriously and are committed to protecting your data.
Contact: security@yourcompany.com
Compliance and Auditing #
Audit Trail #
Database Auditing:
-- Create audit trail for sensitive operations
CREATE TABLE audit_log (
id INT AUTO_INCREMENT PRIMARY KEY,
user_id INT,
action VARCHAR(100),
table_name VARCHAR(100),
record_id INT,
old_values JSON,
new_values JSON,
ip_address VARCHAR(45),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
Application Auditing:
// Audit critical operations
class AuditLogger
{
public static function log($action, $model, $oldValues = null, $newValues = null)
{
DB::table('audit_log')->insert([
'user_id' => BackendAuth::getUser()->id ?? null,
'action' => $action,
'table_name' => $model->getTable(),
'record_id' => $model->id,
'old_values' => json_encode($oldValues),
'new_values' => json_encode($newValues),
'ip_address' => request()->ip(),
'created_at' => now(),
]);
}
}
// Usage in models
public function afterUpdate()
{
AuditLogger::log('update', $this, $this->original, $this->attributes);
}
Compliance Frameworks #
SOC 2 Considerations:
- Implement access controls and authentication
- Maintain audit logs for all data access
- Encrypt data in transit and at rest
- Regular vulnerability assessments
- Incident response procedures
GDPR Compliance:
- Data minimization practices
- Right to erasure implementation
- Consent management for communications
- Data processing agreements with subprocessors
- Privacy by design principles
HIPAA Considerations (if monitoring healthcare systems):
- Enhanced access controls
- Additional encryption requirements
- Business associate agreements
- Audit log retention requirements
Security Testing #
Penetration Testing #
Regular Security Assessments:
# Automated security scanning
#!/bin/bash
# security-scan.sh
# SQL injection testing
sqlmap -u "https://yoursite.com/api/servermonitor/check/premium/test" --batch --level=1
# XSS testing
xsshunter --url "https://yoursite.com"
# SSL/TLS testing
sslscan yoursite.com
# Port scanning
nmap -sS -O yoursite.com
Code Security Review:
# PHP security analysis
./vendor/bin/psalm --security-analysis
# Dependency vulnerability scanning
composer audit
# OWASP dependency checking
dependency-check.sh --project servermonitor --scan ./
Regular Security Maintenance #
Monthly Security Tasks:
- [ ] Rotate API keys
- [ ] Review user access permissions
- [ ] Update system packages
- [ ] Scan for vulnerabilities
- [ ] Review security logs
- [ ] Test backup/restore procedures
Quarterly Security Tasks:
- [ ] Penetration testing
- [ ] Security policy review
- [ ] Incident response plan testing
- [ ] Security awareness training
- [ ] Third-party security assessment
Previous: ← SaasBase Integration | Next: Legal Pages →