/**
 * Microsoft Sentinel Client
 *
 * Log Analytics Data Collector API client for Microsoft Sentinel integration.
 *
 * @module integrations/siem/sentinel
 */
import { createHmac } from "crypto";
import { logger } from "../../logger.js";
import { formatForSentinel } from "./format.js";
/**
 * Microsoft Sentinel (Log Analytics) client
 */
export class SentinelClient {
    provider = "sentinel";
    config;
    workspaceId;
    sharedKey;
    logType;
    constructor(config) {
        this.config = config;
        this.workspaceId = config.options?.workspaceId || "";
        this.sharedKey = config.token;
        this.logType = config.options?.logType || "VasperaHardening";
    }
    /**
     * Build authorization signature for Log Analytics API
     */
    buildSignature(date, contentLength, method, contentType, resource) {
        const xHeaders = `x-ms-date:${date}`;
        const stringToHash = `${method}\n${contentLength}\n${contentType}\n${xHeaders}\n${resource}`;
        const decodedKey = Buffer.from(this.sharedKey, "base64");
        const hmac = createHmac("sha256", decodedKey);
        hmac.update(stringToHash, "utf8");
        const encodedHash = hmac.digest("base64");
        return `SharedKey ${this.workspaceId}:${encodedHash}`;
    }
    /**
     * Get RFC1123 formatted date
     */
    getRfc1123Date() {
        return new Date().toUTCString();
    }
    /**
     * Test connection to Sentinel
     */
    async testConnection() {
        const startTime = Date.now();
        // Sentinel doesn't have a health endpoint, so we send a test event
        try {
            const testEvent = {
                timestamp: new Date().toISOString(),
                eventType: "scan.started",
                severity: "informational",
                project: "test",
                message: "Vaspera connection test",
                source: "vaspera",
                data: { test: true },
            };
            const result = await this.sendEvent(testEvent);
            return {
                success: result.success,
                provider: "sentinel",
                endpoint: this.config.endpoint,
                latencyMs: Date.now() - startTime,
                error: result.error,
                details: { workspaceId: this.workspaceId, logType: this.logType },
            };
        }
        catch (error) {
            return {
                success: false,
                provider: "sentinel",
                endpoint: this.config.endpoint,
                latencyMs: Date.now() - startTime,
                error: error instanceof Error ? error.message : String(error),
            };
        }
    }
    /**
     * Send a single event to Sentinel
     */
    async sendEvent(event) {
        const timestamp = new Date().toISOString();
        try {
            const payload = formatForSentinel(event);
            const body = JSON.stringify([payload]);
            const contentLength = Buffer.byteLength(body, "utf8");
            const date = this.getRfc1123Date();
            const resource = `/api/logs`;
            const contentType = "application/json";
            const signature = this.buildSignature(date, contentLength, "POST", contentType, resource);
            const url = `https://${this.workspaceId}.ods.opinsights.azure.com${resource}?api-version=2016-04-01`;
            const response = await fetch(url, {
                method: "POST",
                headers: {
                    "Content-Type": contentType,
                    Authorization: signature,
                    "Log-Type": this.logType,
                    "x-ms-date": date,
                    "time-generated-field": this.config.options?.timeGeneratedField || "TimeGenerated",
                },
                body,
                signal: AbortSignal.timeout(30000),
            });
            if (response.ok || response.status === 200) {
                logger.debug("siem.sentinel.event_sent", {
                    eventType: event.eventType,
                    logType: this.logType,
                });
                return {
                    success: true,
                    timestamp,
                };
            }
            const errorText = await response.text();
            logger.warn("siem.sentinel.send_failed", {
                status: response.status,
                error: errorText,
            });
            return {
                success: false,
                timestamp,
                error: `HTTP ${response.status}: ${errorText}`,
            };
        }
        catch (error) {
            const errorMessage = error instanceof Error ? error.message : String(error);
            logger.error("siem.sentinel.send_error", { error: errorMessage });
            return {
                success: false,
                timestamp,
                error: errorMessage,
            };
        }
    }
    /**
     * Send multiple events in batch
     */
    async sendEvents(events) {
        if (events.length === 0) {
            return {
                success: true,
                totalEvents: 0,
                successCount: 0,
                failureCount: 0,
            };
        }
        try {
            const payloads = events.map((event) => formatForSentinel(event));
            const body = JSON.stringify(payloads);
            const contentLength = Buffer.byteLength(body, "utf8");
            const date = this.getRfc1123Date();
            const resource = `/api/logs`;
            const contentType = "application/json";
            const signature = this.buildSignature(date, contentLength, "POST", contentType, resource);
            const url = `https://${this.workspaceId}.ods.opinsights.azure.com${resource}?api-version=2016-04-01`;
            const response = await fetch(url, {
                method: "POST",
                headers: {
                    "Content-Type": contentType,
                    Authorization: signature,
                    "Log-Type": this.logType,
                    "x-ms-date": date,
                    "time-generated-field": this.config.options?.timeGeneratedField || "TimeGenerated",
                },
                body,
                signal: AbortSignal.timeout(60000),
            });
            if (response.ok || response.status === 200) {
                logger.info("siem.sentinel.batch_sent", {
                    eventCount: events.length,
                    logType: this.logType,
                });
                return {
                    success: true,
                    totalEvents: events.length,
                    successCount: events.length,
                    failureCount: 0,
                };
            }
            const errorText = await response.text();
            logger.warn("siem.sentinel.batch_failed", {
                status: response.status,
                error: errorText,
                eventCount: events.length,
            });
            return {
                success: false,
                totalEvents: events.length,
                successCount: 0,
                failureCount: events.length,
                errors: [{ index: 0, error: `HTTP ${response.status}: ${errorText}` }],
            };
        }
        catch (error) {
            const errorMessage = error instanceof Error ? error.message : String(error);
            logger.error("siem.sentinel.batch_error", { error: errorMessage });
            return {
                success: false,
                totalEvents: events.length,
                successCount: 0,
                failureCount: events.length,
                errors: [{ index: 0, error: errorMessage }],
            };
        }
    }
    /**
     * Close connection
     */
    async close() {
        // No persistent connection to close for Log Analytics API
    }
}
/**
 * Create a Sentinel client from configuration
 */
export function createSentinelClient(config) {
    return new SentinelClient({
        provider: "sentinel",
        enabled: true,
        endpoint: `https://${config.workspaceId}.ods.opinsights.azure.com`,
        token: config.sharedKey,
        options: {
            workspaceId: config.workspaceId,
            logType: config.logType || "VasperaHardening",
            timeGeneratedField: config.timeGeneratedField,
        },
    });
}
//# sourceMappingURL=sentinel.js.map