let sortOrder ; function objectToQueryString(obj) { return Object.keys(obj) .filter(key => obj[key] !== undefined && obj[key] !== null && obj[key] !== '') .map(key => encodeURIComponent(key) + '=' + encodeURIComponent(obj[key])) .join('&'); } async function fetchAlert(alertId) { const response = get_raw_request_api(`/alerts/${alertId}?cid=${get_caseid()}`); return await response; } async function fetchMultipleAlerts(alertIds) { const response = get_raw_request_api(`/alerts/filter?cid=${get_caseid()}&alert_ids=${alertIds.join(',')}`); return await response; } const selectsConfig = { alert_status_id: { url: '/manage/alert-status/list', id: 'status_id', name: 'status_name', }, alert_severity_id: { url: '/manage/severities/list', id: 'severity_id', name: 'severity_name' }, alert_classification_id: { url: '/manage/case-classifications/list', id: 'id', name: 'name_expanded', }, alert_customer_id: { url: '/manage/customers/list', id: 'customer_id', name: 'customer_name' }, alert_owner_id: { url: '/manage/users/list', id: 'user_id', name: 'user_name' }, alert_resolution_id: { url: '/manage/alert-resolutions/list', id: 'resolution_status_id', name: 'resolution_status_name' } }; let alertStatusList = {}; let alertResolutionList = {}; function getAlertStatusList() { get_request_api('/manage/alert-status/list') .then((data) => { if (!notify_auto_api(data, true)) { return; } alertStatusList = data.data; }); } function getAlertResolutionList() { get_request_api('/manage/alert-resolutions/list') .then((data) => { if (!notify_auto_api(data, true)) { return; } alertResolutionList = data.data; }); } function getAlertStatusId(statusName) { const status = alertStatusList.find((status) => status.status_name === statusName); return status ? status.status_id : undefined; } function getAlertResolutionId(resolutionName) { if (alertResolutionList.length === undefined) { getAlertResolutionList(); } const resolution = alertResolutionList.find((resolution) => resolution.resolution_status_name.toLowerCase().replaceAll(' ', '_') === resolutionName); return resolution ? resolution.resolution_status_id : undefined; } function appendLabels(list, items, itemType) { items.forEach((item) => { const label = $('').addClass('d-block'); const input = $('').attr({ type: 'checkbox', name: itemType, value: filterXSS(item[itemType + '_name'] || item[itemType + '_value']), id: item[itemType + '_uuid'], checked: true, }); label.append(input); label.append(`${filterXSS(item[itemType + '_name'] || item[itemType + '_value'])}`); list.append(label); }); } function toggleSelectDeselect(toggleButton, listSelector) { let allChecked = true; $(listSelector).each(function () { if (!$(this).prop("checked")) { allChecked = false; } $(this).prop("checked", !$(this).prop("checked")); }); if (allChecked) { toggleButton.text("Select All"); } else { toggleButton.text("Deselect All"); } } function unlinkAlertFromCase(alert_id, case_id) { do_deletion_prompt(`Unlink alert #${alert_id} from the case #${case_id}?`, true) .then( () => { unlinkAlertFromCaseRequest(alert_id, case_id) .then((data) => { if (!notify_auto_api(data)) { return; } refreshAlert(alert_id); }); }); } async function unlinkAlertFromCaseRequest(alert_id, case_id) { return await post_request_api(`/alerts/unmerge/${alert_id}`, JSON.stringify({ target_case_id: case_id, csrf_token: $('#csrf_token').val() })); } function mergeMultipleAlertsModal() { const selectedAlerts = getBatchAlerts(); const escalateButton = $("#escalateOrMergeButton"); if (selectedAlerts.length === 0) { notify_error('Please select at least one alert to perform this action on.'); return; } fetchMultipleAlerts(selectedAlerts) .then((alertDataReq) => { if (notify_auto_api(alertDataReq, true)) { const ioCsList = $("#ioCsList"); const assetsList = $("#assetsList"); // Configure the modal for both escalation and merging $('#escalateModalLabel').text('Merge multiple alerts in a new case'); $('#escalateModalExplanation').text('These alerts will be merged into a new case. Set the case title and select the IOCs and Assets to escalate into the case.'); $('#modalAlertTitleContainer').hide(); $('#modalEscalateCaseTitle').val(`[ALERT] Escalation of ${selectedAlerts.length} alerts`); $('#modalEscalateCaseTitleContainer').show(); escalateButton.attr("data-merge", false); $('#mergeAlertCaseSelectSection').hide(); const case_tags = $('#case_tags'); case_tags.val('') case_tags.amsifySuggestags({ printValues: false, suggestions: [] }); // Load case options for merging var options = { ajax: { url: '/context/search-cases' + case_param(), type: 'GET', dataType: 'json' }, locale: { emptyTitle: 'Select and Begin Typing', statusInitialized: '', }, preprocessData: function (data) { return context_data_parser(data); }, preserveSelected: false }; get_request_api('/context/get-cases/100') .done((data) => { if (notify_auto_api(data, true)) { mergeAlertCasesSelectOption(data); $('#mergeAlertCaseSelect').ajaxSelectPicker(options); get_request_api('/manage/case-templates/list') .done((dataTemplate) => { if (notify_auto_api(dataTemplate, true)) { dataTemplate = dataTemplate.data; const templateSelect = $('#mergeAlertCaseTemplateSelect'); templateSelect.html(''); templateSelect.append(''); for (let i = 0; i < dataTemplate.length; i++) { templateSelect.append(``); } templateSelect.selectpicker('refresh'); // Clear the lists ioCsList.html(""); assetsList.html(""); let alertsData = alertDataReq.data; for (let i = 0; i < alertsData.length; i++) { let alertData = alertsData[i]; if (alertData.iocs.length !== 0) { appendLabels(ioCsList, alertData.iocs, 'ioc'); } if (alertData.assets.length !== 0) { appendLabels(assetsList, alertData.assets, 'asset'); } } escalateButton.attr("data-merge", false); escalateButton.attr("data-multi-merge", true); $("#escalateOrMergeButton").attr('onclick', `mergeAlertClicked("${selectedAlerts.join(',')}");`); $('#escalateModal').modal('show'); $("input[type='radio'][name='mergeOption']:checked").trigger("change"); $("input[type='radio'][name='mergeOption']").off('change').on("change", function () { if ($(this).val() === "existing_case") { $('#escalateModalLabel').text(`Merge ${selectedAlerts.length} alerts in an existing case`); $('#escalateModalExplanation').text('These alerts will be merged into the selected case. Select the IOCs and Assets to merge into the case.'); $('#mergeAlertCaseSelectSection').show(); $('#mergeAlertCaseTemplateSection').hide(); $('#modalEscalateCaseTitleContainer').hide(); $('#mergeAlertCaseSelect').selectpicker('refresh'); $('#mergeAlertCaseSelect').selectpicker('val', get_caseid()); escalateButton.data("merge", true); } else { console.log('change') $('#escalateModalLabel').text(`Merge ${selectedAlerts.length} alerts in new case`); $('#escalateModalExplanation').text('This alert will be merged into a new case. Set the case title and select the IOCs and Assets to merge into the case.'); $('#mergeAlertCaseSelectSection').hide(); $('#mergeAlertCaseTemplateSection').show(); $('#modalEscalateCaseTitleContainer').show(); escalateButton.data("merge", false); } }); } }); } }); } }); } function showEscalationModal() { $("#escalateModal").modal("show"); } function mergeAlertModal(alert_id) { const escalateButton = $("#escalateOrMergeButton"); escalateButton.attr("data-alert-id", alert_id); let alertDataReq = null; const ioCsList = $("#ioCsList"); const assetsList = $("#assetsList"); fetchAlert(alert_id) .then((data) => { alertDataReq = data; notify_auto_api(data, true); let alert_title = filterXSS(alertDataReq.data.alert_title); $("#modalAlertId").val(alert_id); $("#modalAlertTitle").val(alert_title); // Configure the modal for both escalation and merging $('#escalateModalLabel').html(`Merge alert #${alert_id} in a new case`); $('#escalateModalLabel')[0].offsetHeight; $('#escalateModalExplanation').text('This alert will be escalated into a new case. Set a title and select the IOCs and Assets to escalate into the case.'); $('#modalEscalateCaseTitle').val(`[ALERT] ${alert_title}`); $('#modalEscalateCaseTitleContainer').show(); escalateButton.attr("data-merge", false); $('#mergeAlertCaseSelectSection').hide(); const case_tags = $('#case_tags'); case_tags.val(alertDataReq.data.alert_tags) case_tags.amsifySuggestags({ printValues: false, suggestions: [] }); // Load case options for merging var options = { ajax: { url: '/context/search-cases' + case_param(), type: 'GET', dataType: 'json' }, locale: { emptyTitle: 'Select and Begin Typing', statusInitialized: '', }, preprocessData: function (data) { return context_data_parser(data); }, preserveSelected: false }; get_request_api('/context/get-cases/100') .done((data) => { if (notify_auto_api(data, true)) { mergeAlertCasesSelectOption(data); $('#mergeAlertCaseSelect').ajaxSelectPicker(options); get_request_api('/manage/case-templates/list') .done((data) => { if (notify_auto_api(data, true)) { data = data.data; const templateSelect = $('#mergeAlertCaseTemplateSelect'); templateSelect.html(''); templateSelect.append(''); for (let i = 0; i < data.length; i++) { templateSelect.append(``); } templateSelect.selectpicker('refresh'); // Clear the lists ioCsList.html(""); assetsList.html(""); if (!notify_auto_api(alertDataReq, true)) { return; } let alertData = alertDataReq.data; if (alertData.iocs.length !== 0) { appendLabels(ioCsList, alertData.iocs, 'ioc'); $("#toggle-iocs").off("click").on("click", function () { toggleSelectDeselect($(this), "#ioCsList input[type='checkbox']"); }); $("#ioc-container").show(); } else { $("#ioc-container").show(); } if (alertData.assets.length !== 0) { appendLabels(assetsList, alertData.assets, 'asset'); $("#toggle-assets").off("click").on("click", function () { toggleSelectDeselect($(this), "#assetsList input[type='checkbox']"); }); $("#asset-container").show(); } else { $("#asset-container").hide(); } $("input[type='radio'][name='mergeOption']:checked").trigger("change"); $("input[type='radio'][name='mergeOption']").off("change").on("change", function () { if ($(this).val() === "existing_case") { $('#escalateModalLabel').text(`Merge alert #${alert_id} in existing case`); $('#escalateModalExplanation').text('This alert will be merged into the selected case. Select the IOCs and Assets to merge into the case.'); $('#mergeAlertCaseSelectSection').show(); $('#mergeAlertCaseTemplateSection').hide(); $('#modalEscalateCaseTitleContainer').hide(); $('#mergeAlertCaseSelect').selectpicker('refresh'); $('#mergeAlertCaseSelect').selectpicker('val', get_caseid()); escalateButton.data("merge", true); } else { $('#escalateModalLabel').text(`Merge alert #${alert_id} in new case`); $('#escalateModalExplanation').text('This alert will be merged into a new case. Set the case title and select the IOCs and Assets to merge into the case.'); $('#mergeAlertCaseSelectSection').hide(); $('#mergeAlertCaseTemplateSection').show(); $('#modalEscalateCaseTitleContainer').show(); escalateButton.data("merge", false); } }); $("#escalateOrMergeButton").attr('onclick', `mergeAlertClicked(${alert_id});`); $("#escalateModal").modal("show"); } }); } }); }); } function mergeAlertClicked(alertId) { const merge = $("#escalateOrMergeButton").data("merge"); const multiMerge = $("#escalateOrMergeButton").data("multi-merge"); escalateOrMergeAlert(alertId, merge, multiMerge); } function mergeAlertCasesSelectOption(data) { if(notify_auto_api(data, true)) { $('#mergeAlertCaseSelect').empty(); $('#mergeAlertCaseSelect').append(''); $('#mergeAlertCaseSelect').append(''); let ocs = data.data; let ret_data = []; for (index in ocs) { let case_name = sanitizeHTML(ocs[index].name); let cs_name = sanitizeHTML(ocs[index].customer_name); ret_data.push({ 'value': ocs[index].case_id, 'text': `${case_name} (${cs_name}) ${ocs[index].access}` }); if (ocs[index].close_date != null) { $('#switchMergeAlertCasesClose').append(``); } else { $('#switchMergeAlertCasesOpen').append(``) } } return ret_data; } } function fetchSmartRelations(alert_id) { $(`input[name="open_alerts_${alert_id}"]`).prop('checked', true); $(`input[name="closed_alerts_${alert_id}"]`).prop('checked', false); $(`input[name="open_cases_${alert_id}"]`).prop('checked', false); $(`input[name="closed_cases_${alert_id}"]`).prop('checked', false); fetchSimilarAlerts(alert_id, false, true, false, false, false); } function buildAlertLink(alert_id){ const current_path = location.protocol + '//' + location.host return current_path + '/alerts' + case_param() + '&alert_ids=' + alert_id; } function copyAlertLink(alert_id) { const link = buildAlertLink(alert_id); navigator.clipboard.writeText(link).then(function() { notify_success('Link copied'); }, function(err) { notify_error('Can\'t copy link. I printed it in console.'); console.error('Shared link', err); }); } function copyMDAlertLink(alert_id){ const link = `[ #${alert_id}](${buildAlertLink(alert_id)})`; navigator.clipboard.writeText(link).then(function() { notify_success('MD link copied'); }, function(err) { notify_error('Can\'t copy link. I printed it in console.'); console.error('Shared link', err); }); } function getAlertOffset(element) { const rect = element.getBoundingClientRect(); return { left: rect.left, top: rect.top + window.scrollY, }; } function createNetwork(alert_id, relatedAlerts, nb_nodes, containerId, containerConfigureId) { const { nodes, edges } = relatedAlerts; if (nodes.length === 0 || nodes.length === undefined) { $(`#similarAlertsNotify-${alert_id}`).text(`No relationships found for this alert`); return; } const data = { nodes: new vis.DataSet(nodes), edges: new vis.DataSet(edges), }; const options = { edges: { smooth: { enabled: true, type: 'continuous', roundness: 0.5 } }, layout: { randomSeed: 2, improvedLayout: true }, interaction: { hideEdgesOnDrag: false, tooltipDelay: 100 }, height: (window.innerHeight- 250) + "px", clickToUse: true, physics: { forceAtlas2Based: { gravitationalConstant: -167, centralGravity: 0.04, springLength: 0, springConstant: 0.02, damping: 0.9 }, minVelocity: 0.41, solver: "forceAtlas2Based", timestep: 0.45 } }; const container = document.getElementById(containerId); const network = new vis.Network(container, data, options); // Create a MutationObserver to listen for DOM changes in the container const observer = new MutationObserver((mutations) => { for (const mutation of mutations) { if (mutation.type === 'childList') { network.redraw(); // Force a redraw when the DOM is updated break; } } }); // Start observing the container for DOM changes observer.observe(container, { childList: true, subtree: true, }); network.on("stabilizationIterationsDone", function () { network.setOptions( { physics: false } ); }); let selectedNodeId = null; let node_type = null; let node_id = null; network.on('oncontext', (event) => { event.event.preventDefault(); const nodeId = network.getNodeAt(event.pointer.DOM); if (nodeId) { selectedNodeId = nodeId; node_type = selectedNodeId.split('_')[0]; node_id = selectedNodeId.split('_')[1]; if (node_type === 'alert' || node_type === 'case' || node_type === 'asset' || node_type === 'ioc') { // Get the offset of the container element. const containerOffset = getAlertOffset(container); const x = event.pointer.DOM.x + 110; const y = containerOffset.top + event.pointer.DOM.y; const contextMenu = $('#context-menu-relationships'); contextMenu.css({ position: 'absolute', left: `${x}px`, top: `${y}px` }) $('#view-alert').data('node-id', node_id); $('#view-alert').data('node-type', node_type); if (node_type === 'alert' || node_type === 'case') { $('#view-alert-text').text(`View on ${node_type} #${node_id}`); } else { $('#view-alert-text').text(`Pivot on ${node_type} ${node_id}`); } contextMenu.show(); } } }); document.addEventListener('click', () => { const contextMenu = $('#context-menu-relationships'); contextMenu.hide(); }); if (nodes.length >= nb_nodes) { $(`#similarAlertsNotify-${alert_id}`).text(`Relationships node exceeded the nodes limit. Expect truncated results.`) } else { $(`#similarAlertsNotify-${alert_id}`).text(``); } } function viewAlertGraph() { const node_id = $("#view-alert").data('node-id'); const node_type = $("#view-alert").data('node-type'); if (node_type === 'alert') { window.open(`/alerts?alert_ids=${node_id}&cid=${get_caseid()}`); } else if (node_type === 'case') { window.open(`/case?cid=${node_id}`); } else if (node_type === 'asset') { window.open(`/alerts?alert_assets=${node_id}&cid=${get_caseid()}`); } else if (node_type === 'ioc') { window.open(`/alerts?alert_iocs=${node_id}&cid=${get_caseid()}`); } } function fetchSimilarAlerts(alert_id, refresh = false, fetch_open_alerts = true, fetch_closed_alerts = false, fetch_open_cases = false, fetch_closed_cases = false ) { const similarAlertsElement = $(`#similarAlerts-${alert_id}`); if (!similarAlertsElement.html() || refresh) { // Build the query string with the new parameters const nb_nodes = $(`#nbResultsGraphFilter-${alert_id}`).val(); const queryString = new URLSearchParams({ 'open-alerts': fetch_open_alerts, 'closed-alerts': fetch_closed_alerts, 'open-cases': fetch_open_cases, 'closed-cases': fetch_closed_cases, 'days-back': $(`#daysBackGraphFilter-${alert_id}`).val(), 'number-of-nodes': nb_nodes }).toString(); $(`#similarAlertsNotify-${alert_id}`).text('Fetching relationships...'); get_raw_request_api(`/alerts/similarities/${alert_id}?${queryString}&cid=${get_caseid()}`) .done((data) => { createNetwork(alert_id, data.data, nb_nodes, `similarAlerts-${alert_id}`, `graphConfigure-${alert_id}`); }); } } function escalateOrMergeAlert(alert_id, merge = false, batch = false) { const selectedIOCs = $('#ioCsList input[type="checkbox"]:checked').map((_, checkbox) => { return $(checkbox).attr('id'); }).get(); const selectedAssets = $('#assetsList input[type="checkbox"]:checked').map((_, checkbox) => { return $(checkbox).attr('id'); }).get(); const note = $('#note').val(); const importAsEvent = $('#importAsEvent').is(':checked'); let case_template_id = null; if (!merge) { case_template_id = $('#mergeAlertCaseTemplateSelect').val(); } const requestBody = { iocs_import_list: selectedIOCs, assets_import_list: selectedAssets, note: note, import_as_event: importAsEvent, case_tags: $('#case_tags').val(), case_template_id: case_template_id, csrf_token: $("#csrf_token").val() }; let url = batch ? `/alerts/batch/`: `/alerts/`; if (merge) { requestBody.target_case_id = $('#mergeAlertCaseSelect').val(); url += batch ? 'merge' : `merge/${alert_id}`; } else { requestBody.case_title = $('#modalEscalateCaseTitle').val(); url += batch ? 'escalate' : `escalate/${alert_id}`; } if (batch) { requestBody.alert_ids = alert_id; } post_request_api(url, JSON.stringify(requestBody)) .then((data) => { if (data.status == 'success') { $("#escalateModal").modal("hide"); notify_auto_api(data); if (batch) { refreshAlerts(); } else { refreshAlert(alert_id); } } else { notify_auto_api(data); } }); } async function fetchAlerts(page, per_page, filters_string = {}, sort_order= 'desc') { const response = get_raw_request_api(`/alerts/filter?cid=${get_caseid()}&page=${page}&per_page=${per_page} &sort=${sort_order}&${filters_string}`); return await response; } function alert_severity_to_color(severity) { switch (severity) { case 'Critical': return 'critical'; case 'High': return 'danger'; case 'Medium': return 'warning'; case 'Low': return 'low'; case 'Informational': return 'info'; default: return 'muted'; } } function alertStatusToColor(status) { switch (status) { case 'Closed': return 'alert-card-done'; case 'Dismissed': return 'alert-card-done'; case 'Merged': return 'alert-card-done'; case 'Escalated': return 'alert-card-done'; case 'New': return 'alert-card-new'; default: return ''; } } function generateDefinitionList(obj) { let html = ""; for (const key in obj) { const value = obj[key]; html += `
${key}:
`; if (typeof value === "object" && value !== null) { html += `
${generateDefinitionList(value)}
`; } else { html += `
${value}
`; } } return html; } function addTagFilter(this_object) { let tag_name = $(this_object).data('tag'); let filters = getFiltersFromUrl(); if (filters['alert_tags']) { for (let tag of filters['alert_tags'].split(',')) { if (tag === tag_name) { return; } } filters['alert_tags'] += `,${tag_name}`; } else { filters['alert_tags'] = tag_name; } const queryParams = new URLSearchParams(window.location.search); let page_number = parseInt(queryParams.get('page')); let per_page = parseInt(queryParams.get('per_page')); updateAlerts(page_number, per_page, filters) .then(() => { notify_success('Refreshed'); $('#newAlertsBadge').text(0).hide(); }); } function getFiltersFromUrl() { const formData = new FormData($('#alertFilterForm')[0]); return Object.fromEntries(formData.entries()); } function alertResolutionToARC(resolution) { if (resolution === null) { return ''; } switch (resolution.resolution_status_name) { case 'True Positive With Impact': return `True Positive with impact` case 'True Positive Without Impact': return `True Positive without impact` case 'False Positive': return `False Positive` } } function renderNestedObject(obj) { let output = ''; Object.entries(obj).forEach(([key, value]) => { if (typeof value === 'object' && value !== null) { output += `
${filterXSS(key)}:

${renderNestedObject(value)}
`; } else { output += `
${filterXSS(key)}:
${filterXSS(value)}
`; } }); return output; } function renderAlert(alert, expanded=false, modulesOptionsAlertReq, modulesOptionsIocReq) { const colorSeverity = alert_severity_to_color(alert.severity.severity_name); const alert_color = alertStatusToColor(alert.status.status_name); const alert_resolution = alertResolutionToARC(alert.resolution_status); if (alert.owner !== null) { alert.owner.user_name = filterXSS(alert.owner.user_name); } alert.alert_title = alert.alert_title ? filterXSS(alert.alert_title) : 'No title provided'; alert.alert_description = alert.alert_description ? filterXSS(alert.alert_description) : 'No description provided'; alert.alert_source = alert.alert_description ? filterXSS(alert.alert_source) : 'No source provided'; alert.alert_source_link = filterXSS(alert.alert_source_link); alert.alert_source_ref = filterXSS(alert.alert_source_ref); alert.alert_note = filterXSS(alert.alert_note); let menuOptionsHtmlAlert = ''; const menuOptions = modulesOptionsAlertReq; if (menuOptions.length !== 0) { menuOptionsHtmlAlert = ''; for (let index in menuOptions) { let opt = menuOptions[index]; menuOptionsHtmlAlert += ` ${opt.manual_hook_ui_name}` } } return `
${alert.owner ? get_avatar_initials(alert.owner.user_name, true, `changeAlertOwner(${alert.alert_id})`) : `
`}
${alert.alert_title}
#${alert.alert_id} - ${alert.alert_uuid}
${alert.status.status_name === 'Closed' ? ` `: ` `}
${alert.alert_description.replaceAll('\n', '
').replaceAll('\t', ' ')}

General info

${alert.alert_source ? `
Source:
${alert.alert_source}
` : ''} ${alert.alert_source_link ? `
Source Link:
${ alert.alert_source_link && alert.alert_source_link.startsWith('http') ? `${alert.alert_source_link}` : 'No valid link provided' }
` : ''} ${alert.alert_source_ref ? `
Source Reference:
${alert.alert_source_ref}
` : ''} ${alert.alert_source_event_time ? `
Source Event Time:
${alert.alert_source_event_time}
` : ''} ${alert.alert_creation_time ? `
IRIS Creation Time:
${alert.alert_creation_time}
` : ''}

Alert note

${alert.alert_note}
${ alert.alert_context && Object.keys(alert.alert_context).length > 0 ? `

Context

${renderNestedObject(alert.alert_context)}
` : '' }

Relationships

The following relationships are automatically generated by IRIS based on the alert's IOCs and assets in the system. They are an indication only and may not be accurate.
Nodes limit
Lookback (days)
${ alert.iocs && alert.iocs.length > 0 ? `

IOCs

${alert.iocs .map( (ioc) => ` ` ) .join('')}
Value Description Type TLP Tags Enrichment
${filterXSS(ioc.ioc_value)} ${filterXSS(ioc.ioc_description)} ${ioc.ioc_type ? filterXSS(ioc.ioc_type.type_name) : '-'} ${filterXSS(ioc.ioc_tlp) ? ioc.ioc_tlp : '-'} ${ioc.ioc_tags ? ioc.ioc_tags.split(',').map((tag) => `${filterXSS(tag)}`).join('') : ''} ${ioc.ioc_enrichment ? `` : ''}
` : '' } ${ alert.assets && alert.assets.length > 0 ? `

Assets

${alert.assets .map( (asset) => ` ` ) .join('')}
Name Description Type Domain IP Tags Enrichment
${asset.asset_name ? filterXSS(asset.asset_name) : '-'} ${asset.asset_description ? filterXSS(asset.asset_description) : '-'} ${asset.asset_type ? filterXSS(asset.asset_type.asset_name) : '-'} ${asset.asset_domain ? filterXSS(asset.asset_domain) : '-'} ${asset.asset_ip ? filterXSS(asset.asset_ip) : '-'} ${asset.asset_tags ? asset.asset_tags.split(',').map((tag) => `${filterXSS(tag)}`).join('') : ''} ${asset.asset_enrichment ? `` : ''}
` : '' } ${ alert.alert_source_content ? `

Raw Alert

${filterXSS(JSON.stringify(alert.alert_source_content, null, 2))}
` : "" }
${alert.cases ? `
` + alert.cases.map((case_) => ` `).join('') + '
' : '
'}
${alert_resolution === undefined ? "": alert_resolution} ${alert.status ? `${alert.status.status_name}` : ''} ${alert.alert_source_event_time} ${alert.severity.severity_name} ${filterXSS(alert.alert_source) || 'Unspecified'} ${filterXSS(alert.customer.customer_name) || 'Unspecified'} ${alert.classification && alert.classification.name_expanded ? `${filterXSS(alert.classification.name_expanded)}`: ''} ${alert.alert_tags ? alert.alert_tags.split(',').map((tag) => `${filterXSS(tag)}`).join('') + `` : ''}
`; } function init_module_processing_alert(alert_id, hook_name, hook_ui_name, module_name, data_type) { let data = Object(); data['hook_name'] = hook_name; data['module_name'] = module_name; data['hook_ui_name'] = hook_ui_name; data['csrf_token'] = $('#csrf_token').val(); data['type'] = 'alert'; data['targets'] = [alert_id]; post_request_api("/dim/hooks/call", JSON.stringify(data), true) .done(function (data){ notify_auto_api(data) }); } let modulesOptionsAlertReq = null; let modulesOptionsIocReq = null; async function showAlertHistory(alertId) { const alertDataReq = await fetchAlert(alertId); if (!notify_auto_api(alertDataReq, true)) { return; } let alertData = alertDataReq.data; let entryDiv = $('#modal_alert_history_content'); for (let entry in alertData.modification_history) { let date = new Date(Math.floor(entry) * 1000); let dateStr = date.toLocaleString(); let entryStr = alertData.modification_history[entry]; entryDiv.append('
' + dateStr + '
' + entryStr.user + '
'+ entryStr.action +'
'); } $('#modal_alert_history').modal('show'); } async function refreshAlert(alertId, alertData, expanded=false) { if (alertData === undefined) { const alertDataReq = await fetchAlert(alertId); if (!notify_auto_api(alertDataReq, true)) { return; } alertData = alertDataReq.data; } if (modulesOptionsAlertReq === null) { modulesOptionsAlertReq = await fetchModulesOptionsAlert(); if (!notify_auto_api(modulesOptionsAlertReq, true)) { return; } } if (modulesOptionsIocReq === null) { modulesOptionsIocReq = await fetchModulesOptionsIoc(); if (!notify_auto_api(modulesOptionsIocReq, true)) { return; } } const alertElement = $(`#alertCard-${alertId}`); const alertHtml = renderAlert(alertData, expanded, modulesOptionsAlertReq.data, modulesOptionsIocReq.data); alertElement.replaceWith(alertHtml); } async function fetchModulesOptionsAlert() { const response = get_request_api('/dim/hooks/options/alert/list'); return await response; } async function fetchModulesOptionsIoc() { const response = get_request_api('/dim/hooks/options/ioc/list'); return await response; } async function fetchModulesOptionsAsset() { const response = get_request_api('/dim/hooks/options/asset/list'); return await response; } async function updateAlerts(page, per_page, filters = {}, paging=false){ if (sortOrder === undefined) { sortOrder = 'desc'; } if (paging) { filters = getFiltersFromUrl(); } const alertsContainer = $('.alerts-container'); alertsContainer.html('

Retrieving alerts...

'); const filterString = objectToQueryString(filters); const data = await fetchAlerts(page, per_page, filterString, sortOrder); if (!notify_auto_api(data, true)) { return; } const alerts = data.data.alerts; if (modulesOptionsAlertReq === null) { modulesOptionsAlertReq = await fetchModulesOptionsAlert(); if (!notify_auto_api(modulesOptionsAlertReq, true)) { return; } } if (modulesOptionsIocReq === null) { modulesOptionsIocReq = await fetchModulesOptionsIoc(); if (!notify_auto_api(modulesOptionsIocReq, true)) { return; } } // Check if the selection mode is active const selectionModeActive = $('body').hasClass('selection-mode'); selectionModeActive ? $('body').removeClass('selection-mode') : ''; $('#toggle-selection-mode').text('Select'); $('body').removeClass('selection-mode'); $('#select-deselect-all').hide(); $('#alerts-batch-actions').hide(); // Clear the current alerts list const queryParams = new URLSearchParams(window.location.search); const isExpanded = queryParams.get('is-expanded') === 'true'; alertsContainer.html(''); if (alerts.length === 0) { // Display "No results" message when there are no alerts alertsContainer.append('
No results
'); } else { // Add the fetched alerts to the alerts container alerts.forEach((alert) => { const alertElement = $('
'); const alertHtml = renderAlert(alert, isExpanded, modulesOptionsAlertReq.data, modulesOptionsIocReq.data); alertElement.html(alertHtml); alertsContainer.append(alertElement); }); } // Update the pagination links const currentPage = page; const totalPages = Math.ceil(data.data.total / per_page); createPagination(currentPage, totalPages, per_page, 'updateAlerts', '.pagination-container'); // Update the URL with the filter parameters queryParams.set('page', page); queryParams.set('per_page', per_page); let filter_tags_info = []; for (const key in filters) { if (filters.hasOwnProperty(key)) { if (filters[key] === '') { queryParams.delete(key); } else { queryParams.set(key, filters[key]); filter_tags_info.push(` ${key}: ${filterXSS(filters[key])} `) } } } queryParams.set('sort', sortOrder); history.replaceState(null, null, `?${queryParams.toString()}`); $('#alertsInfoFilter').text(`${data.data.total} Alert${ data.data.total > 1 ? 's' : ''} ${ filterString ? `(filtered)` : '' }`); if (filter_tags_info) { $('#alertsInfoFilterTags').html(filter_tags_info.join(' + ')); $('#alertsInfoFilterTags .tag-delete-alert-filter').on('click', function () { const filterKey = $(this).data('filter-key'); delete filters[filterKey]; queryParams.delete(filterKey); $(`#${filterKey}`).val(''); resetSavedFilters(queryParams, false); history.replaceState(null, null, `?${queryParams.toString()}`); updateAlerts(page, per_page, filters); }); } else { $('#alertsInfoFilterTags').html(''); } filterString || queryParams.get('filter_id') ? $('#resetFilters').show() : $('#resetFilters').hide(); alertsContainer.show(); } $('#alertsPerPage').on('change', (e) => { const per_page = parseInt(e.target.value, 10); updateAlerts(1, per_page, undefined, sortOrder); // Update the alerts list with the new 'per_page' value and reset to the first page }); $('#orderAlertsBtn').on('click', function () { sortOrder = sortOrder === 'desc' ? 'asc' : 'desc'; const iconClass = sortOrder === 'desc' ? 'fas fa-arrow-up-short-wide' : 'fas fa-arrow-up-wide-short'; $('#orderAlertsBtn i').attr('class', iconClass); const queryParams = new URLSearchParams(window.location.search); let page_number = parseInt(queryParams.get('page')); let per_page = parseInt(queryParams.get('per_page')); const formData = new FormData($('#alertFilterForm')[0]); const filters = Object.fromEntries(formData.entries()); updateAlerts(page_number, per_page, filters); }); function refreshAlerts(){ const queryParams = new URLSearchParams(window.location.search); let page_number = parseInt(queryParams.get('page')); let per_page = parseInt(queryParams.get('per_page')); const formData = new FormData($('#alertFilterForm')[0]); const filters = Object.fromEntries(formData.entries()); updateAlerts(page_number, per_page, filters) .then(() => { notify_success('Refreshed'); $('#newAlertsBadge').text(0).hide(); }); } function toggleCollapseAllAlerts() { const toggleAllBtn = $('#toggleAllAlertsBtn'); const isExpanded = toggleAllBtn.data('is-expanded') || false; collapseAlerts(!isExpanded); const queryParams = new URLSearchParams(window.location.search); queryParams.set('is-expanded', !isExpanded); window.history.replaceState(null, '', '?' + queryParams.toString()); } function collapseAlerts(isExpanded) { const alertsContainer = $('.alert-collapsible'); const toggleAllBtn = $('#toggleAllAlertsBtn'); if (isExpanded) { alertsContainer.collapse('show'); toggleAllBtn.text('Collapse All'); toggleAllBtn.data('is-expanded', true); } else { alertsContainer.collapse('hide'); toggleAllBtn.text('Expand All'); toggleAllBtn.data('is-expanded', false); } } $('#alertFilterForm').on('submit', (e) => { e.preventDefault(); // Get the filter values from the form const formData = new FormData(e.target); const filters = Object.fromEntries(formData.entries()); const queryParams = new URLSearchParams(window.location.search); let per_page = parseInt(queryParams.get('per_page')); if (!per_page) { per_page = 10; } // Update the alerts list with the new filters and reset to the first page updateAlerts(1, per_page, filters); }); $('#resetFilters').on('click', function () { const form = $('#alertFilterForm'); // Reset all input fields form.find('input, select').each((_, element) => { if (element.type === 'checkbox') { $(element).prop('checked', false); } else { $(element).val(''); } }); // Reset the saved filters dropdown resetSavedFilters(null); // Trigger the form submit event to fetch alerts with the updated filters form.trigger('submit'); }); function resetSavedFilters(queryParams = null, replaceState = true) { if (queryParams === null || queryParams === undefined) { queryParams = new URLSearchParams(window.location.search); } queryParams.delete('filter_id'); if (replaceState) { window.history.replaceState(null, null, `?${queryParams.toString()}`); } $('#savedFilters').selectpicker('val', ''); return queryParams; } function showEnrichment(enrichment) { const ace = get_new_ace_editor('enrichmentData', null, null, null, null, true, false); ace.session.setMode("ace/mode/json"); ace.setValue(JSON.stringify(enrichment, null, 4), -1); } function delete_alert(alert_id) { do_deletion_prompt(`Are you sure you want to delete alert #${alert_id}?`, true) .then((doDelete) => { if (doDelete) { post_request_api(`/alerts/delete/${alert_id}`) .then((data) => { if (notify_auto_api(data)) { setFormValuesFromUrl(); } }); } }); } async function editAlert(alert_id, close=false) { const alertTag = $('#editAlertTags'); const confirmAlertEdition = $('#confirmAlertEdition'); alertTag.val($(`#alertTags-${alert_id}`).text()) alertTag.amsifySuggestags({ printValues: false, suggestions: [] }); $('#editAlertNote').val($(`#alertNote-${alert_id}`).text()); if (close) { confirmAlertEdition.text('Close alert'); $('.alert-edition-part').hide(); $('#closeAlertModalLabel').text(`Close alert #${alert_id}`); } else { $('.alert-edition-part').show(); $('#closeAlertModalLabel').text(`Edit alert #${alert_id}`); confirmAlertEdition.text('Save') } fetchSelectOptions('editAlertClassification', selectsConfig['alert_classification_id']).then(() => { $('#editAlertClassification').val($(`#alertClassification-${alert_id}`).data('classification-id')); }).catch(error => { console.error(error); }); fetchSelectOptions('editAlertSeverity', selectsConfig['alert_severity_id']).then(() => { $('#editAlertSeverity').val($(`#alertSeverity-${alert_id}`).data('severity-id')); }).catch(error => { console.error(error); }); $('#editAlertModal').modal('show'); confirmAlertEdition.off('click').on('click', function () { let alert_note = $('#editAlertNote').val(); let alert_tags = alertTag.val(); console.log(getAlertResolutionId($("input[type='radio'][name='resolutionStatus']:checked").val())); let data = { alert_note: alert_note, alert_tags: alert_tags, alert_resolution_status_id: getAlertResolutionId($("input[type='radio'][name='resolutionStatus']:checked").val()), alert_classification_id: $('#editAlertClassification').val(), alert_severity_id: $('#editAlertSeverity').val() }; if (close) { data['alert_status_id'] = getAlertStatusId('Closed'); } updateAlert(alert_id, data, true, true) .then(() => { $('#editAlertModal').modal('hide'); }); }); } async function fetchSavedFilters() { const url = '/filters/alerts/list'; return get_request_api(url) .then((data) => { if (notify_auto_api(data, true)) { const savedFiltersDropdown = $('#savedFiltersDropdown'); savedFiltersDropdown.empty(); let dropdownHtml = ` '; savedFiltersDropdown.append(dropdownHtml); // Initialize the bootstrap-select component $('#savedFilters').selectpicker(); // Add the event listener after the selectpicker is loaded $('#savedFilters').on('shown.bs.select', function () { $('.trash-wrapper').removeClass('hidden-trash'); $('.delete-filter').off().on('click', function (event) { event.preventDefault(); event.stopPropagation(); const filterId = $(this).attr('id').split('-')[2]; if (!filterId) return; do_deletion_prompt(`Are you sure you want to delete filter #${filterId}?`, true) .then((do_delete) => { if (!do_delete) return; const url = `/filters/delete/${filterId}`; const data = { csrf_token: $('#csrf_token').val() }; post_request_api(url, JSON.stringify(data)) .then((data) => { if (notify_auto_api(data)) { fetchSavedFilters(); } }); }); }); }).on('hide.bs.select', function () { $('.trash-wrapper').addClass('hidden-trash'); }); $('#savedFilters').on('change', function() { const selectedFilterId = $('#savedFilters').val(); if (!selectedFilterId) return; const url = `/filters/${selectedFilterId}`; get_request_api(url) .then((data) => { if(!notify_auto_api(data, true)) return; const queryParams = new URLSearchParams(); Object.entries(data.data.filter_data).forEach(([key, value]) => { if (value !== '') { queryParams.set(key, value); } }); queryParams.set('filter_id', selectedFilterId); // Update the URL and reload the page with the new filter settings window.location.href = window.location.pathname + case_param() + '&' + queryParams.toString(); }) }); } }); } $('#saveFilters').on('click', function () { $('#saveFilterModal').modal('show'); }); $('#saveFilterButton').on('click', function () { const filterData = $('#alertFilterForm').serializeArray().reduce((obj, item) => { obj[item.name] = item.value; return obj; }, {}); const filterName = $('#filterName').val(); const filterDescription = $('#filterDescription').val(); const filterIsPrivate = $('#filterIsPrivate').prop('checked'); if (!filterName) return; const url = '/filters/add'; post_request_api(url, JSON.stringify({ filter_name: filterName, filter_description: filterDescription, filter_data: filterData, filter_is_private: filterIsPrivate, filter_type: 'alerts', csrf_token: $('#csrf_token').val() })) .then(function (data) { if (notify_auto_api(data)) { fetchSavedFilters(); } }); $('#saveFilterModal').modal('hide'); }); function changeStatusAlert(alert_id, status_name) { let status_id = getAlertStatusId(status_name); let data = { 'alert_status_id': status_id } updateAlert(alert_id, data, true); } async function changeAlertOwner(alertId) { // Fetch the user list from the endpoint const usersReq = await get_request_api('/manage/users/list'); if (!notify_auto_api(usersReq, true)) { return; }; users = usersReq.data; // Populate the select element with the fetched user list const userSelect = $('#changeOwnerAlertSelect'); userSelect.empty(); users.forEach((user) => { userSelect.append(``); }); $('#alertIDAssignModal').text(alertId); // Show the modal $('#changeAlertOwnerModal').modal('show'); // Set up the form submission document.getElementById('assign-owner-button').onclick = async () => { // Get the selected user ID const newOwnerId = userSelect.val(); // Send a POST request to the update endpoint updateAlert(alertId, {alert_owner_id: newOwnerId}, true) .then(() => { // Close the modal $('#changeAlertOwnerModal').modal('hide'); }); }; } async function changeBatchAlertOwner(alertId) { const selectedAlerts = getBatchAlerts(); if (selectedAlerts.length === 0) { notify_error('Please select at least one alert to perform this action on.'); return; } // Fetch the user list from the endpoint const usersReq = await get_request_api('/manage/users/list'); if (!notify_auto_api(usersReq, true)) { return; }; users = usersReq.data; // Populate the select element with the fetched user list const userSelect = $('#changeOwnerAlertSelect'); userSelect.empty(); users.forEach((user) => { userSelect.append(``); }); $('#alertIDAssignModal').text(alertId); // Show the modal $('#changeAlertOwnerModal').modal('show'); // Set up the form submission document.getElementById('assign-owner-button').onclick = async () => { // Get the selected user ID const newOwnerId = userSelect.val(); // Send a POST request to the update endpoint updateBatchAlerts({alert_owner_id: newOwnerId}) .then(() => { // Close the modal $('#changeAlertOwnerModal').modal('hide'); }); }; } async function updateAlert(alert_id, data = {}, do_refresh = false, collapse_toggle = false) { data['csrf_token'] = $('#csrf_token').val(); return post_request_api('/alerts/update/' + alert_id, JSON.stringify(data)).then(function (data) { if (notify_auto_api(data)) { if (do_refresh) { const expanded = $(`#additionalDetails-${alert_id}`).hasClass('show'); return refreshAlert(alert_id, data.data, expanded) .then(() => { const updatedAlertElement = $(`#alertCard-${alert_id}`); if (updatedAlertElement.length) { updatedAlertElement.addClass('fade-it'); } }); } } }); } function setFormValuesFromUrl() { const queryParams = new URLSearchParams(window.location.search); const form = $('#alertFilterForm'); const ajaxCalls = []; queryParams.forEach((value, key) => { const input = form.find(`[name="${key}"]`); if (input.length > 0) { if (input.prop('type') === 'checkbox') { input.prop('checked', value in ['true', 'y', 'yes', '1', 'on']); } else if (input.is('select') && selectsConfig[input.attr('id')]) { const ajaxCall = new Promise((resolve, reject) => { input.one('click', function () { fetchSelectOptions(input.attr('id'), selectsConfig[input.attr('id')]).then(() => { input.val(value); resolve(); }).catch(error => { console.error(error); reject(error); }); }).trigger('click'); }); ajaxCalls.push(ajaxCall); } else { input.val(value); } } if (key === 'filter_id') { $('#savedFilters').selectpicker('val', value); $('.preset-dropdown-container').show(); } }); Promise.all(ajaxCalls) .then(() => { form.trigger('submit'); }) .catch(error => { console.error('Error setting form values:', error); }); } function fetchSelectOptions(selectElementId, configItem) { return new Promise((resolve, reject) => { get_request_api(configItem.url) .then(function (data) { if (!notify_auto_api(data, true)) { reject('Failed to fetch options'); return; } const selectElement = $(`#${selectElementId}`); selectElement.empty(); selectElement.append($('