Security Guide
Comprehensive security guide for Axon OS, covering authentication, authorization, encryption, and best practices for secure deployment.
Security Overview
Axon OS implements a multi-layered security approach with defense-in-depth principles:
- Authentication: JWT tokens, OAuth 2.0, API keys
- Authorization: Role-based access control (RBAC)
- Encryption: TLS/SSL, data-at-rest encryption
- Network Security: Firewall rules, VPN access
- Audit Logging: Complete activity tracking
Authentication
JWT Token Authentication
// Token configuration
const jwtConfig = {
secret: process.env.JWT_SECRET,
expiresIn: '24h',
algorithm: 'HS256',
issuer: 'axonos',
audience: 'axonos-users'
};
// Token verification middleware
app.use(verifyToken);
function verifyToken(req: Request, res: Response, next: NextFunction) {
const token = req.headers.authorization?.split(' ')[1];
if (!token) {
return res.status(401).json({ error: 'Access token required' });
}
try {
const decoded = jwt.verify(token, jwtConfig.secret);
req.user = decoded;
next();
} catch (error) {
return res.status(403).json({ error: 'Invalid token' });
}
}
OAuth 2.0 Integration
Google OAuth Setup
auth:
oauth:
google:
client_id: "${GOOGLE_CLIENT_ID}"
client_secret: "${GOOGLE_CLIENT_SECRET}"
redirect_uri: "https://axonos.example.com/auth/google/callback"
scopes:
- "openid"
- "profile"
- "email"
GitHub OAuth Setup
auth:
oauth:
github:
client_id: "${GITHUB_CLIENT_ID}"
client_secret: "${GITHUB_CLIENT_SECRET}"
redirect_uri: "https://axonos.example.com/auth/github/callback"
scopes:
- "user:email"
- "read:org"
API Key Management
interface ApiKey {
id: string;
name: string;
key: string;
userId: string;
permissions: string[];
expiresAt?: Date;
lastUsed?: Date;
isActive: boolean;
}
// API key validation
async function validateApiKey(key: string): Promise<ApiKey | null> {
// Decrypt and validate key
const decryptedKey = decrypt(key);
const apiKey = await apiKeyRepository.findByKey(decryptedKey);
if (!apiKey || !apiKey.isActive) {
return null;
}
if (apiKey.expiresAt && apiKey.expiresAt < new Date()) {
return null;
}
// Update last used timestamp
await apiKeyRepository.updateLastUsed(apiKey.id);
return apiKey;
}
Multi-Factor Authentication (MFA)
// TOTP-based MFA
import speakeasy from 'speakeasy';
// Generate MFA secret for user
function generateMFASecret(userId: string) {
const secret = speakeasy.generateSecret({
name: `Axon OS (${userId})`,
issuer: 'Axon OS'
});
return {
secret: secret.base32,
qrCode: secret.otpauth_url
};
}
// Verify MFA token
function verifyMFAToken(secret: string, token: string): boolean {
return speakeasy.totp.verify({
secret: secret,
encoding: 'base32',
token: token,
window: 2
});
}
Authorization
Role-Based Access Control (RBAC)
Role Definitions
enum Role {
SUPER_ADMIN = 'super_admin',
ADMIN = 'admin',
DEVELOPER = 'developer',
OPERATOR = 'operator',
VIEWER = 'viewer'
}
enum Permission {
// Workflow permissions
WORKFLOW_CREATE = 'workflow:create',
WORKFLOW_READ = 'workflow:read',
WORKFLOW_UPDATE = 'workflow:update',
WORKFLOW_DELETE = 'workflow:delete',
WORKFLOW_EXECUTE = 'workflow:execute',
// Node permissions
NODE_CREATE = 'node:create',
NODE_READ = 'node:read',
NODE_UPDATE = 'node:update',
NODE_DELETE = 'node:delete',
NODE_INSTALL = 'node:install',
// System permissions
SYSTEM_CONFIG = 'system:config',
SYSTEM_MONITOR = 'system:monitor',
SYSTEM_BACKUP = 'system:backup',
// User management
USER_CREATE = 'user:create',
USER_READ = 'user:read',
USER_UPDATE = 'user:update',
USER_DELETE = 'user:delete'
}
Role Permission Matrix
const rolePermissions: Record<Role, Permission[]> = {
[Role.SUPER_ADMIN]: Object.values(Permission),
[Role.ADMIN]: [
Permission.WORKFLOW_CREATE,
Permission.WORKFLOW_READ,
Permission.WORKFLOW_UPDATE,
Permission.WORKFLOW_DELETE,
Permission.WORKFLOW_EXECUTE,
Permission.NODE_CREATE,
Permission.NODE_READ,
Permission.NODE_UPDATE,
Permission.NODE_DELETE,
Permission.NODE_INSTALL,
Permission.SYSTEM_MONITOR,
Permission.USER_READ,
Permission.USER_UPDATE
],
[Role.DEVELOPER]: [
Permission.WORKFLOW_CREATE,
Permission.WORKFLOW_READ,
Permission.WORKFLOW_UPDATE,
Permission.WORKFLOW_EXECUTE,
Permission.NODE_CREATE,
Permission.NODE_READ,
Permission.NODE_UPDATE,
Permission.NODE_INSTALL
],
[Role.OPERATOR]: [
Permission.WORKFLOW_READ,
Permission.WORKFLOW_EXECUTE,
Permission.NODE_READ,
Permission.SYSTEM_MONITOR
],
[Role.VIEWER]: [
Permission.WORKFLOW_READ,
Permission.NODE_READ
]
};
Permission Checking Middleware
function requirePermission(permission: Permission) {
return (req: Request, res: Response, next: NextFunction) => {
const user = req.user;
if (!user) {
return res.status(401).json({ error: 'Authentication required' });
}
const userPermissions = rolePermissions[user.role] || [];
if (!userPermissions.includes(permission)) {
return res.status(403).json({
error: 'Insufficient permissions',
required: permission,
userRole: user.role
});
}
next();
};
}
// Usage
app.post('/workflows',
requirePermission(Permission.WORKFLOW_CREATE),
createWorkflow
);
Resource-Level Authorization
// Ownership-based access control
interface ResourceOwnership {
userId: string;
resourceType: 'workflow' | 'node' | 'project';
resourceId: string;
permissions: Permission[];
}
async function checkResourceAccess(
userId: string,
resourceType: string,
resourceId: string,
requiredPermission: Permission
): Promise<boolean> {
// Check if user owns the resource
const ownership = await ownershipRepository.findOwnership(
userId, resourceType, resourceId
);
if (ownership && ownership.permissions.includes(requiredPermission)) {
return true;
}
// Check shared access
const sharedAccess = await shareRepository.findSharedAccess(
userId, resourceType, resourceId
);
return sharedAccess?.permissions.includes(requiredPermission) || false;
}
Encryption
Data in Transit
TLS Configuration
ssl:
enabled: true
certificate: "/etc/ssl/certs/axonos.crt"
private_key: "/etc/ssl/private/axonos.key"
# TLS settings
min_version: "1.2"
max_version: "1.3"
# Cipher suites (TLS 1.3)
cipher_suites:
- "TLS_AES_256_GCM_SHA384"
- "TLS_CHACHA20_POLY1305_SHA256"
- "TLS_AES_128_GCM_SHA256"
# TLS 1.2 cipher suites (fallback)
cipher_suites_tls12:
- "ECDHE-RSA-AES256-GCM-SHA384"
- "ECDHE-RSA-AES128-GCM-SHA256"
- "ECDHE-RSA-AES256-SHA384"
# Security headers
headers:
strict_transport_security: "max-age=31536000; includeSubDomains"
x_frame_options: "DENY"
x_content_type_options: "nosniff"
x_xss_protection: "1; mode=block"
Certificate Management
#!/bin/bash
# SSL certificate generation script
# Generate CA private key
openssl genrsa -out ca.key 4096
# Generate CA certificate
openssl req -new -x509 -days 3650 -key ca.key -out ca.crt \
-subj "/C=US/ST=CA/L=San Francisco/O=Axon OS/CN=Axon OS CA"
# Generate server private key
openssl genrsa -out server.key 4096
# Generate certificate signing request
openssl req -new -key server.key -out server.csr \
-subj "/C=US/ST=CA/L=San Francisco/O=Axon OS/CN=axonos.example.com"
# Generate server certificate
openssl x509 -req -days 365 -in server.csr -CA ca.crt -CAkey ca.key \
-CAcreateserial -out server.crt
# Set appropriate permissions
chmod 600 *.key
chmod 644 *.crt
Data at Rest
Database Encryption
database:
encryption:
enabled: true
algorithm: "AES-256-GCM"
key_rotation_days: 90
# PostgreSQL configuration
postgresql:
ssl_mode: "require"
ssl_cert: "/etc/ssl/certs/postgresql.crt"
ssl_key: "/etc/ssl/private/postgresql.key"
ssl_ca: "/etc/ssl/certs/ca.crt"
File System Encryption
# LUKS encryption for data volumes
cryptsetup luksFormat /dev/sdb
cryptsetup luksOpen /dev/sdb axonos_data
# Create filesystem
mkfs.ext4 /dev/mapper/axonos_data
# Mount with encryption
mount /dev/mapper/axonos_data /var/lib/axonos
Application-Level Encryption
import crypto from 'crypto';
class EncryptionService {
private algorithm = 'aes-256-gcm';
private keySize = 32;
private ivSize = 16;
private tagSize = 16;
constructor(private masterKey: string) {}
encrypt(plaintext: string): string {
const iv = crypto.randomBytes(this.ivSize);
const cipher = crypto.createCipher(this.algorithm, this.masterKey);
cipher.setAAD(Buffer.from('axonos'));
let encrypted = cipher.update(plaintext, 'utf8', 'hex');
encrypted += cipher.final('hex');
const tag = cipher.getAuthTag();
return iv.toString('hex') + ':' + tag.toString('hex') + ':' + encrypted;
}
decrypt(ciphertext: string): string {
const parts = ciphertext.split(':');
const iv = Buffer.from(parts[0], 'hex');
const tag = Buffer.from(parts[1], 'hex');
const encrypted = parts[2];
const decipher = crypto.createDecipher(this.algorithm, this.masterKey);
decipher.setAuthTag(tag);
decipher.setAAD(Buffer.from('axonos'));
let decrypted = decipher.update(encrypted, 'hex', 'utf8');
decrypted += decipher.final('utf8');
return decrypted;
}
}
Network Security
Firewall Configuration
iptables Rules
#!/bin/bash
# Firewall configuration script
# Clear existing rules
iptables -F
iptables -X
iptables -t nat -F
iptables -t nat -X
# Default policies
iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -P OUTPUT ACCEPT
# Allow loopback
iptables -A INPUT -i lo -j ACCEPT
iptables -A OUTPUT -o lo -j ACCEPT
# Allow established connections
iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
# Allow SSH (change port as needed)
iptables -A INPUT -p tcp --dport 22 -j ACCEPT
# Allow HTTP/HTTPS
iptables -A INPUT -p tcp --dport 80 -j ACCEPT
iptables -A INPUT -p tcp --dport 443 -j ACCEPT
# Allow Axon OS API
iptables -A INPUT -p tcp --dport 8080 -j ACCEPT
# Allow specific IPs for database access
iptables -A INPUT -p tcp -s 10.0.1.0/24 --dport 5432 -j ACCEPT
# Rate limiting for API endpoints
iptables -A INPUT -p tcp --dport 8080 -m limit --limit 25/minute --limit-burst 100 -j ACCEPT
# Save rules
iptables-save > /etc/iptables/rules.v4
VPN Access
WireGuard Configuration
[Interface]
PrivateKey = <server_private_key>
Address = 10.8.0.1/24
ListenPort = 51820
PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE
# Client configuration
[Peer]
PublicKey = <client_public_key>
AllowedIPs = 10.8.0.2/32
Audit Logging
Security Event Logging
interface SecurityEvent {
id: string;
timestamp: Date;
eventType: SecurityEventType;
userId?: string;
sessionId?: string;
ipAddress: string;
userAgent: string;
resource?: string;
action?: string;
success: boolean;
details?: Record<string, any>;
riskScore?: number;
}
enum SecurityEventType {
LOGIN_SUCCESS = 'login_success',
LOGIN_FAILURE = 'login_failure',
LOGOUT = 'logout',
PASSWORD_CHANGE = 'password_change',
MFA_ENABLE = 'mfa_enable',
MFA_DISABLE = 'mfa_disable',
API_KEY_CREATE = 'api_key_create',
API_KEY_DELETE = 'api_key_delete',
PERMISSION_DENIED = 'permission_denied',
SUSPICIOUS_ACTIVITY = 'suspicious_activity',
DATA_ACCESS = 'data_access',
CONFIGURATION_CHANGE = 'configuration_change'
}
class SecurityLogger {
async logEvent(event: SecurityEvent): Promise<void> {
// Log to database
await securityEventRepository.create(event);
// Log to external SIEM if configured
if (config.siem.enabled) {
await this.sendToSIEM(event);
}
// Check for suspicious patterns
await this.analyzeSecurity(event);
}
private async analyzeSecurity(event: SecurityEvent): Promise<void> {
// Multiple failed logins
if (event.eventType === SecurityEventType.LOGIN_FAILURE) {
const recentFailures = await this.getRecentFailures(
event.ipAddress,
event.userId
);
if (recentFailures >= 5) {
await this.triggerSecurityAlert({
type: 'multiple_failed_logins',
severity: 'high',
details: { failures: recentFailures, ...event }
});
}
}
// Unusual access patterns
if (event.eventType === SecurityEventType.DATA_ACCESS) {
const accessPattern = await this.analyzeAccessPattern(event.userId);
if (accessPattern.isUnusual) {
await this.triggerSecurityAlert({
type: 'unusual_access_pattern',
severity: 'medium',
details: { pattern: accessPattern, ...event }
});
}
}
}
}
Compliance Logging
GDPR Compliance
interface DataProcessingLog {
id: string;
timestamp: Date;
dataSubject: string; // User ID
processingPurpose: string;
dataCategories: string[];
legalBasis: 'consent' | 'contract' | 'legal_obligation' | 'vital_interests' | 'public_task' | 'legitimate_interests';
retentionPeriod: string;
thirdPartySharing?: {
recipient: string;
purpose: string;
safeguards: string[];
};
}
// Log data processing activities
async function logDataProcessing(log: DataProcessingLog): Promise<void> {
await dataProcessingRepository.create(log);
// Schedule data deletion based on retention period
await scheduleDataDeletion(log.dataSubject, log.retentionPeriod);
}
Security Monitoring
Intrusion Detection
interface SecurityRule {
id: string;
name: string;
description: string;
severity: 'low' | 'medium' | 'high' | 'critical';
conditions: SecurityCondition[];
actions: SecurityAction[];
enabled: boolean;
}
interface SecurityCondition {
field: string;
operator: 'equals' | 'contains' | 'greater_than' | 'less_than' | 'regex';
value: any;
}
interface SecurityAction {
type: 'alert' | 'block' | 'quarantine' | 'notify';
parameters: Record<string, any>;
}
// Example security rules
const securityRules: SecurityRule[] = [
{
id: 'sql_injection',
name: 'SQL Injection Attempt',
description: 'Detects potential SQL injection in request parameters',
severity: 'high',
conditions: [
{
field: 'request.parameters',
operator: 'regex',
value: /('|(\\x27)|(\\x2D\\x2D)|(%27)|(%2D%2D))/i
}
],
actions: [
{ type: 'block', parameters: {} },
{ type: 'alert', parameters: { channel: 'security' } }
],
enabled: true
},
{
id: 'brute_force',
name: 'Brute Force Attack',
description: 'Detects brute force login attempts',
severity: 'high',
conditions: [
{
field: 'failed_logins_per_ip',
operator: 'greater_than',
value: 10
}
],
actions: [
{ type: 'block', parameters: { duration: '1h' } },
{ type: 'notify', parameters: { admin: true } }
],
enabled: true
}
];
Real-time Monitoring Dashboard
interface SecurityMetrics {
activeUsers: number;
failedLogins: number;
apiRequests: number;
blockedRequests: number;
securityAlerts: SecurityAlert[];
threatLevel: 'low' | 'medium' | 'high' | 'critical';
}
class SecurityDashboard {
async getMetrics(): Promise<SecurityMetrics> {
const now = new Date();
const oneHourAgo = new Date(now.getTime() - 60 * 60 * 1000);
return {
activeUsers: await this.getActiveUsers(oneHourAgo),
failedLogins: await this.getFailedLogins(oneHourAgo),
apiRequests: await this.getApiRequests(oneHourAgo),
blockedRequests: await this.getBlockedRequests(oneHourAgo),
securityAlerts: await this.getRecentAlerts(oneHourAgo),
threatLevel: await this.calculateThreatLevel()
};
}
}
Security Best Practices
Development Security
-
Secure Coding Guidelines
- Input validation and sanitization
- Output encoding
- Parameterized queries
- Error handling without information disclosure
-
Dependency Management
- Regular security updates
- Vulnerability scanning
- License compliance
-
Code Review Process
- Security-focused code reviews
- Automated security testing
- Static code analysis
Deployment Security
-
Infrastructure Security
- Principle of least privilege
- Network segmentation
- Regular security updates
- Configuration management
-
Container Security
- Minimal base images
- Regular image updates
- Runtime security monitoring
- Resource limits
-
Cloud Security
- IAM best practices
- Encryption at rest and in transit
- Security groups and NACLs
- Audit logging
Operational Security
-
Access Management
- Regular access reviews
- Privileged account monitoring
- Session management
- Password policies
-
Incident Response
- Incident response plan
- Security playbooks
- Forensic capabilities
- Recovery procedures
-
Security Training
- Regular security awareness training
- Phishing simulation
- Security documentation
- Incident reporting
Compliance
Standards and Frameworks
- SOC 2 Type II: Security, availability, and confidentiality
- ISO 27001: Information security management
- GDPR: Data protection and privacy
- HIPAA: Healthcare data protection (if applicable)
Regular Security Assessments
- Penetration Testing: Quarterly external assessments
- Vulnerability Scanning: Weekly automated scans
- Code Security Reviews: For every major release
- Security Architecture Reviews: Annual comprehensive reviews