File size: 3,674 Bytes
7226ab4 486e814 7226ab4 486e814 7226ab4 486e814 1fdbae7 486e814 7226ab4 1fdbae7 7226ab4 486e814 7226ab4 486e814 7226ab4 486e814 7226ab4 486e814 7226ab4 486e814 7226ab4 486e814 7226ab4 486e814 7226ab4 486e814 7226ab4 486e814 7226ab4 486e814 7226ab4 486e814 7226ab4 486e814 7226ab4 486e814 7226ab4 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 |
const fs = require('fs');
const path = require('path');
class SecurityLogger {
constructor(config = {}) {
this.config = config;
/**
* Detecta ambiente
* HF Spaces → filesystem root read-only
* Railway / Docker → usar volume persistente
*/
const isHF = !!process.env.SPACE_ID;
const basePath = isHF
? '/tmp/akira_data'
: process.env.DATA_PATH || path.resolve('data');
this.logsPath = path.join(basePath, 'security_logs');
this.alertsPath = path.join(this.logsPath, 'alerts.json');
this.opsPath = path.join(this.logsPath, 'operations.json');
try {
fs.mkdirSync(this.logsPath, { recursive: true });
console.log(`✅ SecurityLogger: Diretório ativo: ${this.logsPath}`);
} catch (err) {
console.error('❌ SecurityLogger: Falha ao criar diretório:', err.message);
this.logsPath = null;
}
this.operations = this.logsPath ? this._loadJSON(this.opsPath, []) : [];
this.alerts = this.logsPath ? this._loadJSON(this.alertsPath, []) : [];
console.log('✅ SecurityLogger inicializado');
}
logOperation(operacao) {
if (!this.logsPath) return;
try {
const entry = {
id: `${Date.now()}_${Math.random().toString(36).slice(2, 9)}`,
timestamp: new Date().toISOString(),
usuario: operacao.usuario || 'UNKNOWN',
tipoOperacao: operacao.tipo,
alvo: operacao.alvo,
resultado: operacao.resultado,
risco: operacao.risco || 'BAIXO',
detalhes: operacao.detalhes || {},
ipOrigem: operacao.ipOrigem || 'N/A',
duracao: operacao.duracao || 0
};
this.operations.push(entry);
this._saveJSON(this.opsPath, this.operations);
if (this._isSuspicious(entry)) {
this._createAlert(entry);
}
console.log(`📋 [SECURITY] ${entry.tipoOperacao} → ${entry.alvo}`);
return entry;
} catch (e) {
console.error('Erro ao logar operação:', e);
}
}
_createAlert(operacao) {
const alert = {
id: `alert_${Date.now()}`,
timestamp: new Date().toISOString(),
severidade: 'ALTO',
operacaoId: operacao.id,
usuario: operacao.usuario,
descricao: `Operação suspeita: ${operacao.tipoOperacao}`,
motivo: this._getSuspiciousReason(operacao),
status: 'NOVO'
};
this.alerts.push(alert);
this._saveJSON(this.alertsPath, this.alerts);
console.log(`🚨 [SECURITY ALERT] ${alert.descricao}`);
return alert;
}
_isSuspicious(operacao) {
const recentOps = this.operations.filter(o =>
new Date(operacao.timestamp) - new Date(o.timestamp) < 60000
);
if (recentOps.length > 5) return true;
if (operacao.tipoOperacao === 'NMAP_SCAN' && operacao.risco === 'ALTO') return true;
if (operacao.tipoOperacao === 'SQLMAP_TEST' && operacao.resultado === 'VULNERÁVEL') return true;
return false;
}
_getSuspiciousReason(operacao) {
const reasons = [];
if (operacao.tipoOperacao === 'NMAP_SCAN') reasons.push('Port scan');
if (operacao.tipoOperacao === 'SQLMAP_TEST') reasons.push('SQL Injection');
if (operacao.risco === 'CRÍTICO') reasons.push('Risco crítico');
return reasons.join(', ') || 'Atividade incomum';
}
_loadJSON(file, fallback) {
try {
if (fs.existsSync(file)) {
return JSON.parse(fs.readFileSync(file, 'utf8'));
}
} catch {}
return fallback;
}
_saveJSON(file, data) {
try {
fs.writeFileSync(file, JSON.stringify(data, null, 2));
} catch (e) {
console.error(`Erro ao salvar ${file}:`, e.message);
}
}
}
module.exports = SecurityLogger;
|