/** * sigma_details_service.js * * This service provides functionality for retrieving and explaining Sigma rules. */ const logger = require('../../utils/logger'); const { convertSigmaRule, extractDetectionCondition } = require('./sigma_converter_service'); const { debugRuleContent, getRuleYamlContent } = require('../../sigma_db/queries'); const { getFileName } = require('../../utils/file_utils'); const FILE_NAME = getFileName(__filename); /** * Explains a Sigma rule by providing a simplified, human-readable format * Performs diagnostics before explanation and handles error cases * * @param {string} ruleId - The ID of the rule to explain * @returns {Promise} Result object with success flag and explanation or error message */ async function getSigmaRuleDetails(ruleId) { if (!ruleId) { logger.warn(`${FILE_NAME}: Cannot explain rule: Missing rule ID`); return { success: false, message: 'Missing rule ID' }; } logger.info(`${FILE_NAME}: Running diagnostics for rule: ${ruleId}`); logger.info(`${FILE_NAME}: Explaining rule ${ruleId}`); try { // Run diagnostics on the rule content first const diagnosticResult = await debugRuleContent(ruleId); logger.debug(`${FILE_NAME}: Diagnostic result: ${JSON.stringify(diagnosticResult || {})}`); // Convert the rule ID to a structured object const conversionResult = await convertSigmaRule(ruleId); if (!conversionResult.success) { logger.warn(`${FILE_NAME}: Failed to convert rule ${ruleId}: ${conversionResult.message}`); return { success: false, message: conversionResult.message || `Failed to parse rule with ID ${ruleId}` }; } const rule = conversionResult.rule; // Extra safety check if (!rule) { logger.error(`${FILE_NAME}: Converted rule is null for ID ${ruleId}`); return { success: false, message: `Failed to process rule with ID ${ruleId}` }; } // Create a simplified explanation with safe access to properties const explanation = { id: rule.id || ruleId, title: rule.title || 'Untitled Rule', description: rule.description || 'No description provided', author: rule.author || 'Unknown author', severity: rule.level || 'Unknown', detectionExplanation: extractDetectionCondition(rule), falsePositives: Array.isArray(rule.falsepositives) ? rule.falsepositives : typeof rule.falsepositives === 'string' ? [rule.falsepositives] : ['None specified'], tags: Array.isArray(rule.tags) ? rule.tags : [], references: Array.isArray(rule.references) ? rule.references : [] }; logger.info(`${FILE_NAME}: Successfully explained rule ${ruleId}`); logger.debug(`${FILE_NAME}: Explanation properties: ${Object.keys(explanation).join(', ')}`); return { success: true, explanation }; } catch (error) { logger.error(`${FILE_NAME}: Error explaining rule: ${error.message}`); logger.debug(`${FILE_NAME}: Error stack: ${error.stack}`); return { success: false, message: `Error explaining rule: ${error.message}` }; } } /** * Gets the raw YAML content of a Sigma rule * Retrieves the content from the database * * @param {string} ruleId - The ID of the rule to get YAML for * @returns {Promise} Result object with success flag and YAML content or error message */ async function getSigmaRuleYaml(ruleId) { if (!ruleId) { logger.warn(`${FILE_NAME}: Cannot get YAML: Missing rule ID`); return { success: false, message: 'Missing rule ID' }; } logger.info(`${FILE_NAME}: Getting YAML content for rule: ${ruleId}`); try { // Get YAML content from database const yamlResult = await getRuleYamlContent(ruleId); if (!yamlResult.success) { logger.warn(`${FILE_NAME}: Failed to retrieve YAML for rule ${ruleId}: ${yamlResult.message}`); return { success: false, message: yamlResult.message || `Failed to retrieve YAML for rule with ID ${ruleId}` }; } // Add extra safety check for content if (!yamlResult.content) { logger.warn(`${FILE_NAME}: YAML content is empty for rule ${ruleId}`); return { success: true, yaml: '', warning: 'YAML content is empty for this rule' }; } logger.debug(`${FILE_NAME}: Successfully retrieved YAML content with length: ${yamlResult.content.length}`); // Return the YAML content return { success: true, yaml: yamlResult.content }; } catch (error) { logger.error(`${FILE_NAME}: Error retrieving YAML: ${error.message}`); logger.debug(`${FILE_NAME}: Error stack: ${error.stack}`); return { success: false, message: `Error retrieving YAML: ${error.message}` }; } } module.exports = { getSigmaRuleDetails, getSigmaRuleYaml };