@iota-big3/sdk-security
Version:
Advanced security features including zero trust, quantum-safe crypto, and ML threat detection
254 lines • 9.43 kB
JavaScript
"use strict";
/**
* @iota-big3/sdk-security - Blockchain Audit Trail
* Immutable audit logging with blockchain technology
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.BlockchainAuditTrail = void 0;
const tslib_1 = require("tslib");
const crypto = tslib_1.__importStar(require("crypto"));
const events_1 = require("events");
class BlockchainAuditTrail extends events_1.EventEmitter {
constructor(config, logger) {
super();
this.isEnabled = true;
this.events = new Map();
this.eventBuffer = [];
this.blockHeight = 0;
this.lastHash = '0';
this.isInitialized = false;
this.config = config;
this.logger = logger;
if (config.encryptionEnabled) {
this.encryptionKey = crypto.randomBytes(32);
}
}
async initialize() {
if (this.isInitialized) {
return;
}
try {
this.logger.info('Initializing blockchain audit trail');
// Validate blockchain config
if (this.config.blockchain?.type === 'invalid') {
throw new Error('Invalid blockchain configuration');
}
// Initialize blockchain connection (mock)
await this.connectToBlockchain();
// Setup auto-flush interval
this.flushInterval = setInterval(() => {
this.flushBuffer().catch(err => this.logger.error('Buffer flush failed', err));
}, 5000);
this.isInitialized = true;
this.emit('audit:initialized');
}
catch (error) {
this.logger.error('Failed to initialize blockchain audit trail', error);
this.emit('audit:error', error);
throw error;
}
}
async connectToBlockchain() {
// Mock blockchain connection
this.logger.debug(`Connecting to ${this.config.blockchain?.type || 'mock'} blockchain`);
}
async logEvent(event) {
const eventId = this.generateEventId();
const timestamp = Date.now();
let eventData = {
...event,
id: eventId,
timestamp
};
// Encrypt sensitive data if enabled
if (this.config.encryptionEnabled && event.details?.sensitive) {
eventData = this.encryptEventData(eventData);
eventData.encrypted = true;
}
// Calculate hash
const hash = this.calculateHash(eventData, this.lastHash);
const storedEvent = {
...eventData,
hash,
previousHash: this.lastHash,
blockHeight: this.blockHeight + 1
};
// Add to buffer
this.eventBuffer.push(storedEvent);
this.events.set(eventId, storedEvent);
// Update state
this.lastHash = hash;
// Emit events
this.emit('audit:event:logged', storedEvent);
if (this.config.realTimeStreaming) {
this.emit('audit:event:streamed', storedEvent);
}
return eventId;
}
async queryEvents(options = {}) {
let events = Array.from(this.events.values());
// Filter by date range
if (options.startDate) {
const startTime = options.startDate.getTime();
events = events.filter(e => e.timestamp >= startTime);
}
if (options.endDate) {
const endTime = options.endDate.getTime();
events = events.filter(e => e.timestamp <= endTime);
}
// Filter by event type
if (options.eventTypes && options.eventTypes.length > 0) {
events = events.filter(e => options.eventTypes.includes(e.eventType));
}
// Filter by actor
if (options.actors && options.actors.length > 0) {
events = events.filter(e => options.actors.includes(e.actor.id));
}
// Filter by event IDs
if (options.eventIds && options.eventIds.length > 0) {
events = events.filter(e => options.eventIds.includes(e.id));
}
// Sort
const sortOrder = options.sortOrder || 'desc';
events.sort((a, b) => {
const diff = a.timestamp - b.timestamp;
return sortOrder === 'asc' ? diff : -diff;
});
// Pagination
const offset = options.offset || 0;
const limit = options.limit || events.length;
return events.slice(offset, offset + limit);
}
async verifyEventIntegrity(eventId) {
const event = this.events.get(eventId);
if (!event) {
return false;
}
// Verify hash chain
const calculatedHash = this.calculateHash({ ...event, hash: undefined, previousHash: undefined }, event.previousHash || '0');
return calculatedHash === event.hash;
}
async exportAuditTrail(options, format) {
const events = await this.queryEvents(options);
switch (format) {
case 'json':
return JSON.stringify({
events,
metadata: {
exportDate: new Date(),
totalEvents: events.length,
blockHeight: this.blockHeight
}
}, null, 2);
case 'csv': {
const headers = 'eventId,timestamp,eventType,actor,resource,action,outcome\n';
const rows = events.map(e => `"${e.id}","${new Date(e.timestamp).toISOString()}","${e.eventType}","${e.actor.name}","${e.resource?.name || ''}","${e.action}","${e.outcome}"`).join('\n');
return headers + rows;
}
case 'pdf':
// Mock PDF generation
return Buffer.from(`Audit Trail Export\n${JSON.stringify(events, null, 2)}`);
default:
throw new Error(`Unsupported format: ${format}`);
}
}
async getStatistics() {
const events = Array.from(this.events.values());
const stats = {
totalEvents: events.length,
eventsByType: {},
eventsByOutcome: {},
eventsByActor: {}
};
for (const event of events) {
// By type
stats.eventsByType[event.eventType] = (stats.eventsByType[event.eventType] || 0) + 1;
// By outcome
stats.eventsByOutcome[event.outcome] = (stats.eventsByOutcome[event.outcome] || 0) + 1;
// By actor
stats.eventsByActor[event.actor.id] = (stats.eventsByActor[event.actor.id] || 0) + 1;
}
return stats;
}
getMetrics() {
return {
blockchainConnected: this.isInitialized,
eventsLogged: this.events.size,
bufferSize: this.eventBuffer.length,
lastBlockHeight: this.blockHeight,
averageLatency: 5 // Mock latency in ms
};
}
async flushBuffer() {
if (this.eventBuffer.length === 0) {
return;
}
try {
// Simulate writing to blockchain
const eventsToFlush = [...this.eventBuffer];
this.eventBuffer = [];
// Update block height
this.blockHeight++;
this.logger.debug(`Flushed ${eventsToFlush.length} events to blockchain`);
this.emit('audit:buffer:flushed', eventsToFlush.length);
}
catch (error) {
// Re-add events to buffer on failure
this.eventBuffer.unshift(...this.eventBuffer);
throw error;
}
}
async shutdown() {
if (!this.isInitialized) {
return;
}
try {
// Flush remaining events
await this.flushBuffer();
// Clear interval
if (this.flushInterval) {
clearInterval(this.flushInterval);
}
// Clear data
this.events.clear();
this.eventBuffer = [];
this.isInitialized = false;
this.emit('audit:shutdown');
}
catch (error) {
this.logger.error('Error during audit trail shutdown', error);
throw error;
}
}
generateEventId() {
return `evt-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
}
calculateHash(data, previousHash) {
const content = JSON.stringify(data) + previousHash;
return crypto.createHash('sha256').update(content).digest('hex');
}
encryptEventData(data) {
if (!this.encryptionKey) {
return data;
}
// Simple encryption for sensitive fields
const encrypted = { ...data };
if (encrypted.details?.sensitive) {
const iv = crypto.randomBytes(16);
const cipher = crypto.createCipheriv('aes-256-cbc', this.encryptionKey, iv);
let encryptedData = cipher.update(JSON.stringify(encrypted.details.sensitive), 'utf8', 'hex');
encryptedData += cipher.final('hex');
encrypted.details = {
...encrypted.details,
sensitive: undefined,
encrypted: {
data: encryptedData,
iv: iv.toString('hex')
}
};
}
return encrypted;
}
}
exports.BlockchainAuditTrail = BlockchainAuditTrail;
//# sourceMappingURL=blockchain-audit.js.map