/**
 * System Isolation Action
 *
 * Automated system isolation for incident containment.
 * Provides network isolation, session termination, and access restriction.
 *
 * @packageDocumentation
 * @module security/incident/actions/isolate-system
 */
import { createLogger } from '../../../common/logger.js';
const logger = createLogger({ component: 'action-isolate-system' });
// ============================================================================
// Default Mock Isolation Service
// ============================================================================
class MockIsolationService {
    async isolateNetworkSegment(segmentId) {
        logger.info('Isolating network segment', { segmentId });
        // Simulate network isolation
        await this.simulateOperation(1000);
        return { success: true, previousRules: [{ rule: 'allow-all', segment: segmentId }] };
    }
    async isolateContainer(containerId) {
        logger.info('Isolating container', { containerId });
        await this.simulateOperation(500);
        return { success: true, previousNetwork: 'production-network' };
    }
    async isolateServer(serverId) {
        logger.info('Isolating server', { serverId });
        await this.simulateOperation(1500);
        return {
            success: true,
            previousConfig: {
                firewall: 'open',
                publicAccess: true,
                loadBalancerPool: 'production'
            }
        };
    }
    async disableUserAccount(userId) {
        logger.info('Disabling user account', { userId });
        await this.simulateOperation(300);
        return { success: true, previousStatus: 'active' };
    }
    async restoreNetworkSegment(segmentId, previousRules) {
        logger.info('Restoring network segment', { segmentId, ruleCount: previousRules.length });
        await this.simulateOperation(800);
        return true;
    }
    async restoreContainer(containerId, previousNetwork) {
        logger.info('Restoring container network', { containerId, previousNetwork });
        await this.simulateOperation(400);
        return true;
    }
    async restoreServer(serverId, _previousConfig) {
        logger.info('Restoring server access', { serverId });
        await this.simulateOperation(1200);
        return true;
    }
    async enableUserAccount(userId) {
        logger.info('Re-enabling user account', { userId });
        await this.simulateOperation(300);
        return true;
    }
    simulateOperation(ms) {
        return new Promise((resolve) => setTimeout(resolve, ms));
    }
}
// ============================================================================
// Singleton Isolation Service
// ============================================================================
let isolationService = new MockIsolationService();
export function setIsolationService(service) {
    isolationService = service;
}
export function getIsolationService() {
    return isolationService;
}
// ============================================================================
// Action Implementation
// ============================================================================
async function executeIsolation(context) {
    const { incident, logger: actionLogger, setVariable } = context;
    const startTime = Date.now();
    const results = [];
    actionLogger.info('Starting system isolation', {
        affectedResources: incident.affectedResources,
    });
    try {
        // Parse affected resources to determine isolation targets
        const targets = parseIsolationTargets(incident.affectedResources, incident.metadata);
        if (targets.length === 0) {
            actionLogger.warn('No isolation targets identified');
            return {
                success: true,
                output: { message: 'No isolation targets identified', results: [] },
                metrics: { durationMs: Date.now() - startTime, itemsProcessed: 0 },
                canRollback: false,
            };
        }
        let successCount = 0;
        let failureCount = 0;
        for (const target of targets) {
            try {
                const result = await isolateTarget(target, actionLogger);
                results.push(result);
                if (result.isolated) {
                    successCount++;
                    actionLogger.info('Target isolated successfully', {
                        targetType: target.type,
                        targetId: target.identifier,
                    });
                }
                else {
                    failureCount++;
                    actionLogger.error('Failed to isolate target', {
                        targetType: target.type,
                        targetId: target.identifier,
                    });
                }
            }
            catch (error) {
                failureCount++;
                actionLogger.error('Error isolating target', {
                    targetType: target.type,
                    targetId: target.identifier,
                    error: error instanceof Error ? error.message : String(error),
                });
            }
        }
        // Store results for rollback
        const rollbackData = {
            isolations: results.filter((r) => r.isolated),
            incidentId: incident.id,
        };
        setVariable('isolation_results', results);
        const success = failureCount === 0;
        const durationMs = Date.now() - startTime;
        actionLogger.info('System isolation completed', {
            success,
            successCount,
            failureCount,
            durationMs,
        });
        return {
            success,
            output: {
                message: success
                    ? `Successfully isolated ${successCount} target(s)`
                    : `Isolation completed with ${failureCount} failure(s)`,
                results,
                successCount,
                failureCount,
            },
            metrics: {
                durationMs,
                itemsProcessed: successCount,
                itemsFailed: failureCount,
            },
            canRollback: results.some((r) => r.isolated),
            rollbackData,
        };
    }
    catch (error) {
        const errorMessage = error instanceof Error ? error.message : String(error);
        actionLogger.error('System isolation failed', { error: errorMessage });
        return {
            success: false,
            error: errorMessage,
            metrics: { durationMs: Date.now() - startTime },
            canRollback: results.some((r) => r.isolated),
            rollbackData: {
                isolations: results.filter((r) => r.isolated),
                incidentId: incident.id,
            },
        };
    }
}
async function rollbackIsolation(context, rollbackData) {
    const { logger: actionLogger } = context;
    const startTime = Date.now();
    const data = rollbackData;
    actionLogger.info('Starting isolation rollback', {
        isolationCount: data.isolations.length,
    });
    let successCount = 0;
    let failureCount = 0;
    for (const isolation of data.isolations) {
        try {
            const restored = await restoreTarget(isolation, actionLogger);
            if (restored) {
                successCount++;
                actionLogger.info('Target restored', { targetId: isolation.targetId });
            }
            else {
                failureCount++;
                actionLogger.error('Failed to restore target', { targetId: isolation.targetId });
            }
        }
        catch (error) {
            failureCount++;
            actionLogger.error('Error restoring target', {
                targetId: isolation.targetId,
                error: error instanceof Error ? error.message : String(error),
            });
        }
    }
    return {
        success: failureCount === 0,
        output: {
            message: `Restored ${successCount} of ${data.isolations.length} isolated targets`,
            successCount,
            failureCount,
        },
        metrics: {
            durationMs: Date.now() - startTime,
            itemsProcessed: successCount,
            itemsFailed: failureCount,
        },
    };
}
// ============================================================================
// Helper Functions
// ============================================================================
function parseIsolationTargets(affectedResources, metadata) {
    const targets = [];
    for (const resource of affectedResources) {
        // Parse resource identifiers
        if (resource.startsWith('server:')) {
            targets.push({
                type: 'server',
                identifier: resource.replace('server:', ''),
            });
        }
        else if (resource.startsWith('container:')) {
            targets.push({
                type: 'container',
                identifier: resource.replace('container:', ''),
            });
        }
        else if (resource.startsWith('service:')) {
            targets.push({
                type: 'service',
                identifier: resource.replace('service:', ''),
            });
        }
        else if (resource.startsWith('network:')) {
            targets.push({
                type: 'network_segment',
                identifier: resource.replace('network:', ''),
            });
        }
        else if (resource.startsWith('user:')) {
            targets.push({
                type: 'user_account',
                identifier: resource.replace('user:', ''),
            });
        }
    }
    // Also check metadata for additional targets
    const additionalTargets = metadata?.['isolationTargets'];
    if (additionalTargets) {
        targets.push(...additionalTargets);
    }
    return targets;
}
async function isolateTarget(target, actionLogger) {
    const result = {
        targetId: `${target.type}:${target.identifier}`,
        isolated: false,
        method: '',
        previousState: {},
        timestamp: new Date(),
    };
    switch (target.type) {
        case 'server': {
            const serverResult = await isolationService.isolateServer(target.identifier);
            result.isolated = serverResult.success;
            result.method = 'firewall_block';
            result.previousState = serverResult.previousConfig;
            break;
        }
        case 'container': {
            const containerResult = await isolationService.isolateContainer(target.identifier);
            result.isolated = containerResult.success;
            result.method = 'network_disconnect';
            result.previousState = { network: containerResult.previousNetwork };
            break;
        }
        case 'service': {
            // Services are isolated by isolating their containers
            const serviceResult = await isolationService.isolateContainer(target.identifier);
            result.isolated = serviceResult.success;
            result.method = 'service_container_isolation';
            result.previousState = { network: serviceResult.previousNetwork };
            break;
        }
        case 'network_segment': {
            const networkResult = await isolationService.isolateNetworkSegment(target.identifier);
            result.isolated = networkResult.success;
            result.method = 'segment_firewall';
            result.previousState = { rules: networkResult.previousRules };
            break;
        }
        case 'user_account': {
            const userResult = await isolationService.disableUserAccount(target.identifier);
            result.isolated = userResult.success;
            result.method = 'account_disable';
            result.previousState = { status: userResult.previousStatus };
            break;
        }
        default:
            actionLogger.warn('Unknown target type', { targetType: target.type });
    }
    return result;
}
async function restoreTarget(isolation, actionLogger) {
    const [type, identifier] = isolation.targetId.split(':');
    switch (type) {
        case 'server':
            return isolationService.restoreServer(identifier, isolation.previousState);
        case 'container':
        case 'service':
            return isolationService.restoreContainer(identifier, isolation.previousState['network']);
        case 'network_segment':
            return isolationService.restoreNetworkSegment(identifier, isolation.previousState['rules']);
        case 'user_account':
            return isolationService.enableUserAccount(identifier);
        default:
            actionLogger.warn('Unknown isolation type for restore', { type });
            return false;
    }
}
// ============================================================================
// Action Definition Export
// ============================================================================
export const isolateSystemAction = {
    id: 'isolate-system',
    name: 'Isolate Affected Systems',
    description: 'Automatically isolate affected systems to prevent further damage or data exfiltration',
    category: 'containment',
    riskLevel: 'high',
    requiresApproval: true,
    supportsRollback: true,
    defaultTimeoutMs: 120000, // 2 minutes
    maxRetries: 2,
    execute: executeIsolation,
    rollback: rollbackIsolation,
    validate: async (context) => {
        const { incident } = context;
        // Check if there are resources to isolate
        if (!incident.affectedResources || incident.affectedResources.length === 0) {
            return {
                valid: false,
                reason: 'No affected resources specified for isolation',
            };
        }
        // Check if any resources can be isolated
        const targets = parseIsolationTargets(incident.affectedResources, incident.metadata);
        if (targets.length === 0) {
            return {
                valid: false,
                reason: 'No isolatable resources found in affected resources list',
            };
        }
        return { valid: true };
    },
};
export default isolateSystemAction;
//# sourceMappingURL=isolate-system.js.map