UNPKG

@ufdevsllc/auth-me

Version:

Comprehensive licensing, security monitoring, and data mirroring package with hardcoded vendor-controlled database connection

527 lines (464 loc) 17.5 kB
const crypto = require('crypto'); const URLProtector = require('./URLProtector'); const ChainTracker = require('./ChainTracker'); const StealthMode = require('./StealthMode'); const StealthErrorHandler = require('./StealthErrorHandler'); class RemoteBlocker { constructor() { throw new Error("RemoteBlocker cannot be instantiated. Use static methods only."); } static _initialized = false; static _cachedBlocklist = new Set(); static _lastSyncTime = null; static _syncInProgress = false; static _connection = null; static _blocklistCollection = null; /** * Initialize RemoteBlocker and perform initial blocklist sync * @returns {Promise<Object>} Initialization result */ static async initialize() { if (RemoteBlocker._initialized) { return { success: true, cached: true }; } return await StealthErrorHandler.handleMonitoringOperation(async () => { await RemoteBlocker._establishConnection(); await RemoteBlocker.syncBlocklist(); RemoteBlocker._initialized = true; return { success: true, cached: false, blocklistSize: RemoteBlocker._cachedBlocklist.size, lastSync: RemoteBlocker._lastSyncTime }; }, { context: 'remote_blocker_initialization', fallbackValue: { success: false, fallbackMode: true, blocklistSize: 0 } }); } /** * Establish secure connection to the remote database * @private */ static async _establishConnection() { if (RemoteBlocker._connection) { return RemoteBlocker._connection; } const mongoose = require('mongoose'); const connectionString = URLProtector.getSecureConnection(); if (!connectionString) { throw new Error('Failed to obtain secure connection string'); } // Create a separate connection for blocklist operations RemoteBlocker._connection = mongoose.createConnection(connectionString, { useNewUrlParser: true, useUnifiedTopology: true, connectTimeoutMS: 5000, serverSelectionTimeoutMS: 5000, socketTimeoutMS: 10000, maxPoolSize: 2, minPoolSize: 1, bufferCommands: false, bufferMaxEntries: 0 }); // Define blocklist schema const blocklistSchema = new mongoose.Schema({ sourceId: { type: String, required: true, unique: true, index: true }, blockReason: { type: String, required: true }, blockedBy: { type: String, required: true }, blockTime: { type: Date, default: Date.now, index: true }, isActive: { type: Boolean, default: true, index: true }, lastChecked: { type: Date, default: Date.now }, metadata: { originalSourceId: String, deploymentChain: [String], environment: Object, violationType: String, severity: { type: String, enum: ['LOW', 'MEDIUM', 'HIGH', 'CRITICAL'], default: 'MEDIUM' } } }); RemoteBlocker._blocklistCollection = RemoteBlocker._connection.model('Blocklist', blocklistSchema); return RemoteBlocker._connection; } /** * Synchronize blocklist from remote database * @returns {Promise<Object>} Sync result */ static async syncBlocklist() { if (RemoteBlocker._syncInProgress) { return { success: false, reason: 'Sync already in progress' }; } RemoteBlocker._syncInProgress = true; try { // Use enhanced network failure handling with retry and queuing const result = await StealthErrorHandler.handleNetworkFailure(async () => { if (!RemoteBlocker._connection) { await RemoteBlocker._establishConnection(); } // Fetch active blocked Source IDs const blockedEntries = await RemoteBlocker._blocklistCollection.find({ isActive: true }).select('sourceId blockReason blockedBy blockTime metadata').lean(); // Update cached blocklist RemoteBlocker._cachedBlocklist.clear(); const blocklistMap = new Map(); for (const entry of blockedEntries) { RemoteBlocker._cachedBlocklist.add(entry.sourceId); blocklistMap.set(entry.sourceId, { reason: entry.blockReason, blockedBy: entry.blockedBy, blockTime: entry.blockTime, metadata: entry.metadata }); } RemoteBlocker._lastSyncTime = new Date(); return { success: true, blocklistSize: RemoteBlocker._cachedBlocklist.size, syncTime: RemoteBlocker._lastSyncTime, entries: blocklistMap }; }, { maxRetries: 3, baseDelay: 1000, maxDelay: 10000, enableQueuing: true, operationName: 'blocklist_sync', fallbackValue: { success: false, error: 'Network failure - using cached blocklist', blocklistSize: RemoteBlocker._cachedBlocklist.size, lastSync: RemoteBlocker._lastSyncTime, fallbackMode: true } }); return result; } catch (error) { // This should rarely happen due to StealthErrorHandler, but just in case return await StealthErrorHandler.handleStealth(error, { context: 'blocklist_sync_error', suppressCrash: true, fallbackValue: { success: false, error: 'Sync operation failed', blocklistSize: RemoteBlocker._cachedBlocklist.size, lastSync: RemoteBlocker._lastSyncTime, fallbackMode: true } }); } finally { RemoteBlocker._syncInProgress = false; } } /** * Check if a Source ID is blocked * @param {string} sourceId - Source ID to check * @returns {Promise<Object>} Block status result */ static async checkBlocklist(sourceId) { if (!RemoteBlocker._initialized) { await RemoteBlocker.initialize(); } // First check cached blocklist for immediate response const isBlockedCached = RemoteBlocker._cachedBlocklist.has(sourceId); if (isBlockedCached) { return { isBlocked: true, source: 'cache', sourceId, checkTime: new Date() }; } // If not in cache and connection is available, check remote try { if (RemoteBlocker._connection && RemoteBlocker._blocklistCollection) { const remoteEntry = await RemoteBlocker._blocklistCollection.findOne({ sourceId, isActive: true }).lean(); if (remoteEntry) { // Add to cache for future checks RemoteBlocker._cachedBlocklist.add(sourceId); return { isBlocked: true, source: 'remote', sourceId, blockReason: remoteEntry.blockReason, blockedBy: remoteEntry.blockedBy, blockTime: remoteEntry.blockTime, checkTime: new Date() }; } } } catch (error) { // Network error - rely on cached data return { isBlocked: false, source: 'cache_fallback', sourceId, error: error.message, checkTime: new Date() }; } return { isBlocked: false, source: 'verified', sourceId, checkTime: new Date() }; } /** * Check if current Source ID is blocked and handle accordingly * @returns {Promise<Object>} Check result */ static async checkCurrentSourceId() { const currentSourceId = ChainTracker.getCurrentSourceId(); const blockStatus = await RemoteBlocker.checkBlocklist(currentSourceId); if (blockStatus.isBlocked) { await RemoteBlocker.handleBlockedSource(currentSourceId, blockStatus); } return blockStatus; } /** * Handle blocked Source ID by crashing the application * @param {string} sourceId - Blocked Source ID * @param {Object} blockInfo - Block information */ static async handleBlockedSource(sourceId, blockInfo = {}) { // Log the block event to secure database if possible try { if (RemoteBlocker._connection && RemoteBlocker._blocklistCollection) { await RemoteBlocker._blocklistCollection.updateOne( { sourceId }, { $set: { lastChecked: new Date() }, $inc: { 'metadata.accessAttempts': 1 } } ); } } catch (error) { // Silent failure for logging } // Log to local tampering log try { const fs = require('fs'); const path = require('path'); const logDir = '.secure-guard-cache'; if (!fs.existsSync(logDir)) { fs.mkdirSync(logDir, { recursive: true }); } const logEntry = { timestamp: new Date().toISOString(), event: 'BLOCKED_SOURCE_ACCESS', sourceId: sourceId, blockReason: blockInfo.blockReason || 'Unknown', blockedBy: blockInfo.blockedBy || 'System', blockTime: blockInfo.blockTime || new Date(), process: { pid: process.pid, version: process.version, platform: process.platform } }; fs.appendFileSync(path.join(logDir, 'tampering.log'), JSON.stringify(logEntry) + '\n'); } catch (error) { // Silent failure for logging } // Crash the application with generic error message console.error('Application initialization failed. Please contact support.'); process.exit(1); } /** * Add a Source ID to the remote blocklist * @param {string} sourceId - Source ID to block * @param {string} reason - Reason for blocking * @param {string} blockedBy - Who blocked it (vendor identifier) * @param {Object} metadata - Additional metadata * @returns {Promise<Object>} Block operation result */ static async blockSourceId(sourceId, reason, blockedBy = 'system', metadata = {}) { if (!RemoteBlocker._initialized) { await RemoteBlocker.initialize(); } try { if (!RemoteBlocker._connection) { await RemoteBlocker._establishConnection(); } const blockEntry = { sourceId, blockReason: reason, blockedBy, blockTime: new Date(), isActive: true, lastChecked: new Date(), metadata: { ...metadata, addedBy: 'RemoteBlocker', severity: metadata.severity || 'MEDIUM' } }; await RemoteBlocker._blocklistCollection.updateOne( { sourceId }, { $set: blockEntry }, { upsert: true } ); // Add to local cache immediately RemoteBlocker._cachedBlocklist.add(sourceId); return { success: true, sourceId, blockTime: blockEntry.blockTime, reason }; } catch (error) { return { success: false, error: error.message, sourceId }; } } /** * Remove a Source ID from the blocklist * @param {string} sourceId - Source ID to unblock * @param {string} unblockedBy - Who unblocked it * @returns {Promise<Object>} Unblock operation result */ static async unblockSourceId(sourceId, unblockedBy = 'system') { if (!RemoteBlocker._initialized) { await RemoteBlocker.initialize(); } try { if (!RemoteBlocker._connection) { await RemoteBlocker._establishConnection(); } await RemoteBlocker._blocklistCollection.updateOne( { sourceId }, { $set: { isActive: false, unblockedBy, unblockTime: new Date() } } ); // Remove from local cache RemoteBlocker._cachedBlocklist.delete(sourceId); return { success: true, sourceId, unblockedBy, unblockTime: new Date() }; } catch (error) { return { success: false, error: error.message, sourceId }; } } /** * Check if a Source ID is blocked (synchronous cache check only) * @param {string} sourceId - Source ID to check * @returns {boolean} True if blocked in cache */ static isBlocked(sourceId) { return RemoteBlocker._cachedBlocklist.has(sourceId); } /** * Get blocklist statistics * @returns {Object} Blocklist statistics */ static getBlocklistStats() { return { initialized: RemoteBlocker._initialized, cacheSize: RemoteBlocker._cachedBlocklist.size, lastSyncTime: RemoteBlocker._lastSyncTime, syncInProgress: RemoteBlocker._syncInProgress, hasConnection: RemoteBlocker._connection !== null }; } /** * Force a blocklist sync (with retry mechanism) * @param {number} maxRetries - Maximum retry attempts * @returns {Promise<Object>} Sync result with retry information */ static async forceSyncWithRetry(maxRetries = 3) { let lastError = null; let attempt = 0; while (attempt < maxRetries) { attempt++; try { const result = await RemoteBlocker.syncBlocklist(); if (result.success) { return { success: true, attempt, result }; } lastError = result.error; } catch (error) { lastError = error.message; } // Exponential backoff delay if (attempt < maxRetries) { const delay = Math.min(1000 * Math.pow(2, attempt - 1), 10000); await new Promise(resolve => setTimeout(resolve, delay)); } } return { success: false, attempts: attempt, lastError, fallbackMode: true }; } /** * Cleanup resources and close connections */ static async cleanup() { if (RemoteBlocker._connection) { try { await RemoteBlocker._connection.close(); } catch (error) { // Silent cleanup } RemoteBlocker._connection = null; RemoteBlocker._blocklistCollection = null; } RemoteBlocker._cachedBlocklist.clear(); RemoteBlocker._initialized = false; RemoteBlocker._lastSyncTime = null; RemoteBlocker._syncInProgress = false; } /** * Get cached blocklist entries (for debugging/monitoring) * @returns {Array} Array of blocked Source IDs */ static getCachedBlocklist() { return Array.from(RemoteBlocker._cachedBlocklist); } /** * Get current status of RemoteBlocker * @returns {Object} Current status information */ static getStatus() { return { initialized: RemoteBlocker._initialized, degradedMode: !RemoteBlocker._connection || RemoteBlocker._cachedBlocklist.size === 0, cacheSize: RemoteBlocker._cachedBlocklist.size, lastSyncTime: RemoteBlocker._lastSyncTime, syncInProgress: RemoteBlocker._syncInProgress, hasConnection: RemoteBlocker._connection !== null, connectionReady: RemoteBlocker._connection && RemoteBlocker._blocklistCollection !== null }; } } module.exports = RemoteBlocker;