Initial commit: StreamFlow IPTV platform

This commit is contained in:
aiulian25 2025-12-17 00:42:43 +00:00
commit 73a8ae9ffd
1240 changed files with 278451 additions and 0 deletions

View file

@ -0,0 +1,531 @@
/**
* Security Audit Logger
* Tracks security-related events for compliance and forensics
* Integrated with SIEM for centralized log aggregation
*/
const logger = require('./logger');
const { db } = require('../database/db');
const logAggregator = require('./logAggregator');
class SecurityAuditLogger {
/**
* Log authentication events
*/
static async logAuthEvent(eventType, userId, details = {}) {
const event = {
event_type: eventType,
user_id: userId,
ip_address: details.ip || 'unknown',
user_agent: details.userAgent || 'unknown',
success: details.success !== false,
failure_reason: details.failureReason || null,
metadata: JSON.stringify(details.metadata || {}),
timestamp: new Date().toISOString()
};
try {
await new Promise((resolve, reject) => {
db.run(
`INSERT INTO security_audit_log (event_type, user_id, ip_address, user_agent, success, failure_reason, metadata, timestamp)
VALUES (?, ?, ?, ?, ?, ?, ?, ?)`,
[event.event_type, event.user_id, event.ip_address, event.user_agent, event.success ? 1 : 0, event.failure_reason, event.metadata, event.timestamp],
(err) => err ? reject(err) : resolve()
);
});
logger.info(`[SECURITY] ${eventType}: user=${userId}, ip=${event.ip_address}, success=${event.success}`);
// Aggregate to SIEM
const level = event.success ? 'info' : 'warn';
const source = eventType.startsWith('LOGIN') || eventType.includes('PASSWORD') ? 'authentication' : 'security_audit';
logAggregator.aggregate(source, level, 'authentication', `${eventType}: ${event.success ? 'success' : 'failure'}`, {
userId: event.user_id,
ip: event.ip_address,
userAgent: event.user_agent,
failureReason: event.failure_reason,
metadata: details.metadata || {}
});
} catch (error) {
logger.error('Failed to log security event:', error);
}
}
/**
* Log login attempt
*/
static async logLoginAttempt(username, success, details = {}) {
return this.logAuthEvent('LOGIN_ATTEMPT', null, {
success,
failureReason: success ? null : (details.reason || 'Invalid credentials'),
ip: details.ip,
userAgent: details.userAgent,
metadata: { username }
});
}
/**
* Log successful login
*/
static async logLoginSuccess(userId, details = {}) {
return this.logAuthEvent('LOGIN_SUCCESS', userId, {
success: true,
ip: details.ip,
userAgent: details.userAgent,
metadata: { twoFactorUsed: details.twoFactorUsed || false }
});
}
/**
* Log failed login
*/
static async logLoginFailure(username, reason, details = {}) {
return this.logAuthEvent('LOGIN_FAILURE', null, {
success: false,
failureReason: reason,
ip: details.ip,
userAgent: details.userAgent,
metadata: { username }
});
}
/**
* Log account lockout
*/
static async logAccountLockout(userId, details = {}) {
return this.logAuthEvent('ACCOUNT_LOCKOUT', userId, {
success: false,
failureReason: 'Too many failed login attempts',
ip: details.ip,
userAgent: details.userAgent,
metadata: { failedAttempts: details.failedAttempts }
});
}
/**
* Log password change
*/
static async logPasswordChange(userId, details = {}) {
return this.logAuthEvent('PASSWORD_CHANGE', userId, {
success: true,
ip: details.ip,
userAgent: details.userAgent,
metadata: { forced: details.forced || false, expired: details.expired || false }
});
}
/**
* Log 2FA events
*/
static async log2FAEvent(eventType, userId, success, details = {}) {
return this.logAuthEvent(eventType, userId, {
success,
failureReason: success ? null : (details.reason || 'Invalid code'),
ip: details.ip,
userAgent: details.userAgent,
metadata: details.metadata || {}
});
}
/**
* Log session events
*/
static async logSessionEvent(eventType, userId, details = {}) {
return this.logAuthEvent(eventType, userId, {
success: true,
ip: details.ip,
userAgent: details.userAgent,
metadata: { sessionId: details.sessionId }
});
}
/**
* Log privilege escalation
*/
static async logPrivilegeEscalation(userId, details = {}) {
return this.logAuthEvent('PRIVILEGE_ESCALATION', userId, {
success: true,
ip: details.ip,
userAgent: details.userAgent,
metadata: {
fromRole: details.fromRole,
toRole: details.toRole,
grantedBy: details.grantedBy
}
});
}
/**
* Get recent security events for a user
*/
static async getUserSecurityEvents(userId, limit = 50) {
return new Promise((resolve, reject) => {
db.all(
`SELECT * FROM security_audit_log
WHERE user_id = ?
ORDER BY timestamp DESC
LIMIT ?`,
[userId, limit],
(err, rows) => err ? reject(err) : resolve(rows)
);
});
}
/**
* Get failed login attempts for an IP
*/
static async getFailedAttemptsForIP(ipAddress, timeWindowMinutes = 30) {
const cutoffTime = new Date(Date.now() - timeWindowMinutes * 60 * 1000).toISOString();
return new Promise((resolve, reject) => {
db.get(
`SELECT COUNT(*) as count
FROM security_audit_log
WHERE event_type IN ('LOGIN_FAILURE', 'LOGIN_ATTEMPT')
AND success = 0
AND ip_address = ?
AND timestamp > ?`,
[ipAddress, cutoffTime],
(err, row) => err ? reject(err) : resolve(row.count || 0)
);
});
}
/**
* Get failed login attempts for a user
*/
static async getFailedAttemptsForUser(username, timeWindowMinutes = 30) {
const cutoffTime = new Date(Date.now() - timeWindowMinutes * 60 * 1000).toISOString();
return new Promise((resolve, reject) => {
db.get(
`SELECT COUNT(*) as count
FROM security_audit_log
WHERE event_type IN ('LOGIN_FAILURE', 'LOGIN_ATTEMPT')
AND success = 0
AND metadata LIKE ?
AND timestamp > ?`,
[`%"username":"${username}"%`, cutoffTime],
(err, row) => err ? reject(err) : resolve(row.count || 0)
);
});
}
/**
* Clear old audit logs (data retention)
*/
static async cleanupOldLogs(retentionDays = 90) {
const cutoffDate = new Date(Date.now() - retentionDays * 24 * 60 * 60 * 1000).toISOString();
return new Promise((resolve, reject) => {
db.run(
'DELETE FROM security_audit_log WHERE timestamp < ?',
[cutoffDate],
function(err) {
if (err) reject(err);
else {
logger.info(`Cleaned up ${this.changes} old security audit logs`);
resolve(this.changes);
}
}
);
});
}
/**
* CWE-778: Log token issuance (JWT, OAuth, etc.)
* Includes relevant metadata such as client ID, IP address, device info
*/
static async logTokenIssuance(userId, tokenType, details = {}) {
return this.logAuthEvent('TOKEN_ISSUED', userId, {
success: true,
ip: details.ip,
userAgent: details.userAgent,
metadata: {
tokenType: tokenType, // 'JWT', 'REFRESH', 'TEMP_2FA', 'OAUTH'
clientId: details.clientId,
deviceInfo: details.deviceInfo || this.extractDeviceInfo(details.userAgent),
expiresIn: details.expiresIn,
purpose: details.purpose, // 'login', '2fa', 'registration', 'password_reset'
scope: details.scope,
grantType: details.grantType
}
});
}
/**
* CWE-778: Log token refresh
*/
static async logTokenRefresh(userId, details = {}) {
return this.logAuthEvent('TOKEN_REFRESHED', userId, {
success: true,
ip: details.ip,
userAgent: details.userAgent,
metadata: {
tokenType: details.tokenType || 'JWT',
clientId: details.clientId,
deviceInfo: details.deviceInfo || this.extractDeviceInfo(details.userAgent),
oldTokenExpiry: details.oldTokenExpiry,
newTokenExpiry: details.newTokenExpiry
}
});
}
/**
* CWE-778: Log token revocation
*/
static async logTokenRevocation(userId, reason, details = {}) {
return this.logAuthEvent('TOKEN_REVOKED', userId, {
success: true,
ip: details.ip,
userAgent: details.userAgent,
metadata: {
reason: reason, // 'logout', 'password_change', 'security_breach', 'admin_action'
tokenType: details.tokenType || 'JWT',
sessionId: details.sessionId,
revokedBy: details.revokedBy // user_id of admin who revoked it
}
});
}
/**
* CWE-778: Log privilege changes
* Any activities where user's privilege level changes
*/
static async logPrivilegeChange(userId, action, details = {}) {
return this.logAuthEvent('PRIVILEGE_CHANGE', userId, {
success: true,
ip: details.ip,
userAgent: details.userAgent,
metadata: {
action: action, // 'role_assigned', 'role_removed', 'permission_granted', 'permission_revoked'
previousRole: details.previousRole,
newRole: details.newRole,
previousPermissions: details.previousPermissions,
newPermissions: details.newPermissions,
changedBy: details.changedBy, // user_id of admin who made the change
changedByUsername: details.changedByUsername,
reason: details.reason,
affectedUser: details.affectedUser // username of the user being changed
}
});
}
/**
* CWE-778: Log permission grant
*/
static async logPermissionGrant(userId, permission, details = {}) {
return this.logAuthEvent('PERMISSION_GRANTED', userId, {
success: true,
ip: details.ip,
userAgent: details.userAgent,
metadata: {
permission: permission,
grantedBy: details.grantedBy,
grantedByUsername: details.grantedByUsername,
scope: details.scope,
expiresAt: details.expiresAt
}
});
}
/**
* CWE-778: Log permission revocation
*/
static async logPermissionRevocation(userId, permission, details = {}) {
return this.logAuthEvent('PERMISSION_REVOKED', userId, {
success: true,
ip: details.ip,
userAgent: details.userAgent,
metadata: {
permission: permission,
revokedBy: details.revokedBy,
revokedByUsername: details.revokedByUsername,
reason: details.reason
}
});
}
/**
* CWE-778: Log user activation/deactivation
*/
static async logAccountStatusChange(userId, newStatus, details = {}) {
return this.logAuthEvent('ACCOUNT_STATUS_CHANGED', userId, {
success: true,
ip: details.ip,
userAgent: details.userAgent,
metadata: {
previousStatus: details.previousStatus,
newStatus: newStatus, // 'active', 'inactive', 'suspended', 'locked'
changedBy: details.changedBy,
changedByUsername: details.changedByUsername,
reason: details.reason
}
});
}
/**
* CWE-778: Log administrative activities
* For admin actions like user creation, deletion, unlock, force logout
*/
static async logAdminActivity(adminId, action, details = {}) {
return this.logAuthEvent('ADMIN_ACTIVITY', adminId, {
success: true,
ip: details.ip,
userAgent: details.userAgent,
metadata: {
action: action, // 'user_created', 'user_deleted', 'account_unlocked', 'password_reset', 'force_logout'
targetUserId: details.targetUserId,
targetUsername: details.targetUsername,
adminUsername: details.adminUsername,
changes: details.changes,
reason: details.reason,
deviceInfo: details.deviceInfo || this.extractDeviceInfo(details.userAgent)
}
});
}
/**
* CWE-778: Log sensitive data access
* For accessing user lists, settings, VPN configs, backups, etc.
*/
static async logSensitiveDataAccess(userId, dataType, details = {}) {
return this.logAuthEvent('SENSITIVE_DATA_ACCESS', userId, {
success: true,
ip: details.ip,
userAgent: details.userAgent,
metadata: {
dataType: dataType, // 'user_list', 'user_details', 'settings', 'vpn_configs', 'backups', 'audit_logs'
accessMethod: details.accessMethod || 'view', // 'view', 'export', 'download'
recordCount: details.recordCount,
filters: details.filters,
scope: details.scope, // 'own', 'all', 'specific'
deviceInfo: details.deviceInfo || this.extractDeviceInfo(details.userAgent)
}
});
}
/**
* Extract device info from user agent
*/
static extractDeviceInfo(userAgent = '') {
if (!userAgent) return { deviceType: 'unknown', os: 'unknown', browser: 'unknown' };
const ua = userAgent.toLowerCase();
// Device type
let deviceType = 'desktop';
if (/bot|crawler|spider/.test(ua)) deviceType = 'bot';
else if (/mobile|android|iphone|ipod/.test(ua)) deviceType = 'mobile';
else if (/tablet|ipad/.test(ua)) deviceType = 'tablet';
// Operating System
let os = 'unknown';
if (/windows/.test(ua)) os = 'Windows';
else if (/mac os|macos/.test(ua)) os = 'macOS';
else if (/linux/.test(ua)) os = 'Linux';
else if (/android/.test(ua)) os = 'Android';
else if (/ios|iphone|ipad/.test(ua)) os = 'iOS';
// Browser
let browser = 'unknown';
if (/firefox/.test(ua)) browser = 'Firefox';
else if (/chrome/.test(ua) && !/edge|edg/.test(ua)) browser = 'Chrome';
else if (/safari/.test(ua) && !/chrome/.test(ua)) browser = 'Safari';
else if (/edge|edg/.test(ua)) browser = 'Edge';
else if (/opera|opr/.test(ua)) browser = 'Opera';
return { deviceType, os, browser };
}
/**
* Get comprehensive audit statistics
*/
static async getAuditStatistics(timeRangeDays = 30) {
const cutoffDate = new Date(Date.now() - timeRangeDays * 24 * 60 * 60 * 1000).toISOString();
return new Promise((resolve, reject) => {
db.all(
`SELECT
event_type,
success,
COUNT(*) as count,
COUNT(DISTINCT user_id) as unique_users,
COUNT(DISTINCT ip_address) as unique_ips
FROM security_audit_log
WHERE timestamp > ?
GROUP BY event_type, success
ORDER BY count DESC`,
[cutoffDate],
(err, rows) => err ? reject(err) : resolve(rows)
);
});
}
/**
* Log system events (startup, shutdown, cleanup, etc.)
*/
static async logSystemEvent(eventType, success, details = {}) {
return this.logAuthEvent(`SYSTEM_${eventType.toUpperCase()}`, null, {
success,
failureReason: success ? null : (details.error || 'System event failed'),
metadata: details
});
}
/**
* Log security incidents (tampering, breaches, etc.)
*/
static async logSecurityIncident(incidentType, details = {}) {
const event = {
event_type: `SECURITY_INCIDENT_${incidentType.toUpperCase()}`,
user_id: details.userId || null,
ip_address: details.ip || 'system',
user_agent: details.userAgent || 'system',
success: false,
failure_reason: `Security incident: ${incidentType}`,
metadata: JSON.stringify(details),
timestamp: new Date().toISOString()
};
try {
await new Promise((resolve, reject) => {
db.run(
`INSERT INTO security_audit_log (event_type, user_id, ip_address, user_agent, success, failure_reason, metadata, timestamp)
VALUES (?, ?, ?, ?, ?, ?, ?, ?)`,
[event.event_type, event.user_id, event.ip_address, event.user_agent, 0, event.failure_reason, event.metadata, event.timestamp],
(err) => err ? reject(err) : resolve()
);
});
logger.error(`[SECURITY INCIDENT] ${incidentType}: ${JSON.stringify(details)}`);
// Aggregate to SIEM with CRITICAL level
logAggregator.aggregate('security_audit', 'critical', 'security_incident', `Security incident: ${incidentType}`, {
incidentType,
...details
});
} catch (error) {
logger.error('Failed to log security incident:', error);
}
}
/**
* Log admin activities (user management, config changes, etc.)
*/
static async logAdminActivity(adminId, action, details = {}) {
return this.logAuthEvent(`ADMIN_${action.toUpperCase()}`, adminId, {
success: true,
ip: details.ip,
userAgent: details.userAgent,
metadata: {
action,
target: details.target || details.targetUserId,
changes: details.changes,
...details
}
});
}
}
module.exports = SecurityAuditLogger;