From 968d578e387c84bf87bfe7d81526e74a51c8cb76 Mon Sep 17 00:00:00 2001 From: mokaddem Date: Tue, 12 Mar 2019 08:15:27 +0100 Subject: [PATCH] chg: [distributionNetwork] Integration with event index - WiP --- app/Controller/EventsController.php | 35 +- app/View/Elements/Events/eventIndexTable.ctp | 15 + app/View/Events/index.ctp | 6 + app/View/Events/view.ctp | 7 +- app/webroot/css/distribution-graph.css | 38 ++ app/webroot/js/event-distribution-graph.js | 474 +------------------ cti-python-stix2 | 2 +- 7 files changed, 102 insertions(+), 475 deletions(-) diff --git a/app/Controller/EventsController.php b/app/Controller/EventsController.php index c80a8d71c..d2e054d0c 100644 --- a/app/Controller/EventsController.php +++ b/app/Controller/EventsController.php @@ -862,6 +862,7 @@ class EventsController extends AppController $this->set('analysisLevels', $this->Event->analysisLevels); $this->set('distributionLevels', $this->Event->distributionLevels); $this->set('shortDist', $this->Event->shortDist); + $this->set('distributionData', $this->genDistributionGraph(0)); if ($this->params['ext'] === 'csv') { App::uses('CsvExport', 'Export'); $export = new CsvExport(); @@ -4661,8 +4662,7 @@ class EventsController extends AppController return new CakeResponse(array('body' => json_encode($json), 'status' => 200, 'type' => 'json')); } - public function getDistributionGraph($id, $type = 'event') - { + private function genDistributionGraph($id, $type = 'event', $extended = 0) { $validTools = array('event'); if (!in_array($type, $validTools)) { throw new MethodNotAllowedException(__('Invalid type.')); @@ -4671,9 +4671,6 @@ class EventsController extends AppController $this->loadModel('Organisation'); App::uses('DistributionGraphTool', 'Tools'); $grapher = new DistributionGraphTool(); - $data = $this->request->is('post') ? $this->request->data : array(); - - $extended = isset($this->params['named']['extended']) ? 1 : 0; $servers = $this->Server->find('list', array( 'fields' => array('name'), @@ -4686,6 +4683,34 @@ class EventsController extends AppController $item = utf8_encode($item); } }); + return $json; + } + + public function getDistributionGraph($id, $type = 'event') + { + // $validTools = array('event'); + // if (!in_array($type, $validTools)) { + // throw new MethodNotAllowedException(__('Invalid type.')); + // } + // $this->loadModel('Server'); + // $this->loadModel('Organisation'); + // App::uses('DistributionGraphTool', 'Tools'); + // $grapher = new DistributionGraphTool(); + // + $extended = isset($this->params['named']['extended']) ? 1 : 0; + // + // $servers = $this->Server->find('list', array( + // 'fields' => array('name'), + // )); + // $grapher->construct($this->Event, $servers, $this->Auth->user(), $extended); + // $json = $grapher->get_distributions_graph($id); + // + // array_walk_recursive($json, function (&$item, $key) { + // if (!mb_detect_encoding($item, 'utf-8', true)) { + // $item = utf8_encode($item); + // } + // }); + $json = $this->genDistributionGraph($id, $type, $extended); $this->response->type('json'); return new CakeResponse(array('body' => json_encode($json), 'status' => 200, 'type' => 'json')); } diff --git a/app/View/Elements/Events/eventIndexTable.ctp b/app/View/Elements/Events/eventIndexTable.ctp index b5fe45ea9..66cfae051 100644 --- a/app/View/Elements/Events/eventIndexTable.ctp +++ b/app/View/Elements/Events/eventIndexTable.ctp @@ -214,6 +214,15 @@ echo h($shortDist[$event['Event']['distribution']]); endif; ?> + ', + 'Toggle advanced sharing network viewer', + 'fa fa-share-alt useCursorPointer distributionNetworkToggle', + h($event['Event']['distribution']), + h($event['Event']['id']) + ) + ?> , + }); + }); }); diff --git a/app/View/Events/index.ctp b/app/View/Events/index.ctp index 5dc14f5bc..4815c9cef 100644 --- a/app/View/Events/index.ctp +++ b/app/View/Events/index.ctp @@ -136,6 +136,12 @@ }); +Html->script('vis'); + echo $this->Html->css('vis'); + echo $this->Html->css('distribution-graph'); + echo $this->Html->script('network-distribution-graph'); +?> Html->css('query-builder.default'); echo $this->Html->script('query-builder'); echo $this->Html->css('attack_matrix'); + echo $this->Html->script('network-distribution-graph'); ?>
element('view_event_distribution_graph') ), sprintf( - '', + '', 'Toggle advanced sharing network viewer', - 'fa fa-share-alt useCursorPointer', - 'showAdvancedSharing(this)' + 'fa fa-share-alt useCursorPointer' ) ) ); @@ -507,6 +507,7 @@ $(document).ready(function () { $.get("/threads/view//true", function(data) { $("#discussions_div").html(data); }); + }); function enable_correlation_graph() { diff --git a/app/webroot/css/distribution-graph.css b/app/webroot/css/distribution-graph.css index 3f8fa970e..85f5e5682 100644 --- a/app/webroot/css/distribution-graph.css +++ b/app/webroot/css/distribution-graph.css @@ -2,6 +2,44 @@ color: #333333; } +.eventgraph_header { + background: #f9f9f9; + box-shadow: 0px 0px 6px #B2B2B2; + margin-bottom: 2px; + width: 100%; + height: 40px; + overflow: hidden; +} + +select.center-in-network-header { + margin-bottom: 0px; + width: fit-content; +} + +input[type="text"].center-in-network-header { + top: 5px; + margin: 0px; + margin-left: 5px; +} + +input[type="checkbox"].center-in-network-header { + top: 0px; + margin: 0px; + margin-left: 5px; +} + +label.center-in-network-header { + user-select: none; + font-weight: bold; +} + +.center-in-network-header { + position: relative; + display: inline-block; + top: 5px; + margin-left: 5px; +} + .loadingPopover { position: absolute; left: 50%; diff --git a/app/webroot/js/event-distribution-graph.js b/app/webroot/js/event-distribution-graph.js index 87e4533e8..b458e99b6 100644 --- a/app/webroot/js/event-distribution-graph.js +++ b/app/webroot/js/event-distribution-graph.js @@ -7,12 +7,6 @@ var payload = {}; var distribution_chart; var distributionData; -var EDGE_LENGTH_HUB = 300; -var cacheAddedOrgName = {}; -var nodes_distri; -var edges_distri; -var advancedSharingNetwork; - function clickHandlerGraph(evt) { var firstPoint = distribution_chart.getElementAtEvent(evt)[0]; var distribution_id; @@ -226,38 +220,6 @@ function add_level_to_pb(distribution, additionalInfo, maxLevel) { } -function showAdvancedSharing(clicked) { - $clicked = $(clicked); - var network_active = $clicked.data('networkactive'); - if (network_active !== undefined && network_active === true) { - $('#advancedSharingNetworkWrapper').hide('slide', {direction: 'right'}, 300); - $clicked.data('networkactive', false); - return; - } else if (network_active !== undefined && network_active === false) { - $('#advancedSharingNetworkWrapper').show('slide', {direction: 'right'}, 300); - $clicked.data('networkactive', true); - return; - } - $clicked.data('networkactive', true); - var $popover = $('#eventdistri_graph').parent().parent(); - var boundingRect = $popover[0].getBoundingClientRect() - var $div = $(''); - - $('body').append($div); - $div.toggle('slide', {direction: 'right'}, 300); - - construct_network(); -} - function construct_piechart(data) { $('.toBeCleared').remove(); @@ -422,432 +384,6 @@ function construct_piechart(data) { distri_graph.append(div); } -function construct_network(target_distribution, scope_text, overwriteSg) { - cacheAddedOrgName = {}; - if (advancedSharingNetwork !== undefined) { - advancedSharingNetwork.destroy(); - } - if (scope_text == undefined) { - scope_text = 'Event ' + scope_id; - } - $('#sharingNetworkTargetId').val(scope_text); - - nodes_distri = new vis.DataSet([ - {id: 'root', group: 'root', label: scope_text, x: 0, y: 0, fixed: true, mass: 20}, - {id: distributionData.additionalDistributionInfo[0][0], label: distributionData.additionalDistributionInfo[0][0], group: 'org-only'}, - - ]); - edges_distri = new vis.DataSet([ - {from: 'root', to: distributionData.additionalDistributionInfo[0][0], length: 30, width: 3}, - ]); - if (target_distribution === undefined || target_distribution == 5) { - target_distribution = event_distribution; - } - - if (target_distribution !== 0) { - // Event always restrict propagation (sharing group is a special case) - var temp_target_disti = target_distribution; - if (target_distribution !== 4 && temp_target_disti >= event_distribution) { - while (temp_target_disti >= event_distribution) { - var toID = false; - switch (temp_target_disti) { - case 0: - break; - case 1: - toID = 'this-community'; - break; - case 2: - toID = 'connected-community'; - break; - case 3: - toID = 'all-community'; - break; - case 4: - toID = 'sharing-group'; - break; - default: - break; - } - var edgeData = {from: 'root', to: toID, width: 3}; - if (temp_target_disti != event_distribution) { - edgeData.label = 'X'; - edgeData.title = 'The distribution of the Event restricts the distribution level of this element'; - edgeData.font = { - size: 50, - color: '#ff0000', - strokeWidth: 6, - strokeColor: '#ff0000' - }; - } - if (toID !== false) { - edges_distri.add(edgeData); - } - temp_target_disti--; - } - } else { - switch (temp_target_disti) { - case 0: - break; - case 1: - toID = 'this-community'; - break; - case 2: - toID = 'connected-community'; - break; - case 3: - toID = 'all-community'; - break; - case 4: - toID = 'sharing-group'; - break; - default: - break; - } - var edgeData = {from: 'root', to: toID, width: 3}; - if (toID !== false) { - edges_distri.add(edgeData); - } - } - } - - var nodesToAdd = []; - var edgesToAdd = []; - cacheAddedOrgName[distributionData.additionalDistributionInfo[0][0]] = 1; - - // Community - if (target_distribution >= 1 && target_distribution != 4 - && (distributionData.event[1] > 0 || distributionData.event[2] > 0 || distributionData.event[3] > 0) - ) { - nodesToAdd.push({id: 'this-community', label: 'This community', group: 'root-this-community'}); - inject_this_community_org(nodesToAdd, edgesToAdd, distributionData.additionalDistributionInfo[1], 'this-community', 'this-community'); - } - // Connected Community - if (target_distribution >= 2 && target_distribution != 4 - && (distributionData.event[2] > 0 || distributionData.event[3] > 0) - ) { - nodesToAdd.push({id: 'connected-community', label: 'Connected community', group: 'root-connected-community'}); - distributionData.additionalDistributionInfo[2].forEach(function(orgName) { - if (orgName === 'This community') { - edgesToAdd.push({from: 'connected-community', to: 'this-community', length: EDGE_LENGTH_HUB}); - } else { - nodesToAdd.push({ - id: 'connected-community_' + orgName, - label: orgName, - group: 'connected-community' - }); - edgesToAdd.push({from: 'connected-community', to: 'connected-community_' + orgName}); - } - }); - } - - // All Community - if (target_distribution >= 3 && target_distribution != 4 && distributionData.event[3] > 0) { - nodesToAdd.push({id: 'all-community', label: 'All community', group: 'web'}); - distributionData.additionalDistributionInfo[3].forEach(function(orgName) { - if (orgName === 'This community') { - edgesToAdd.push({from: 'all-community', to: 'this-community', length: EDGE_LENGTH_HUB}); - } else if (orgName === 'All other communities') { - edgesToAdd.push({from: 'all-community', to: 'connected-community', length: EDGE_LENGTH_HUB}); - } - }); - } - // Sharing Group - if (distributionData.event[4] > 0) { - distributionData.allSharingGroup.forEach(function(sg) { - var sgName = sg.SharingGroup.name; - if (overwriteSg === undefined) { // if overwriteSg not set, use the one from the event - overwriteSg = distributionData.additionalDistributionInfo[4]; - } - if (overwriteSg.indexOf(sgName) == -1) { - return true; - } - - nodesToAdd.push({ - id: 'sharing-group_' + sgName, - label: sgName, - group: 'root-sharing-group' - }); - edgesToAdd.push({from: 'root', to: 'sharing-group_' + sgName, width: 3}); - sg.SharingGroupOrg.forEach(function(org) { - var sgOrgName = org.Organisation.name; - if (cacheAddedOrgName[sgOrgName] === undefined) { - nodesToAdd.push({ - id: sgOrgName, - label: sgOrgName, - group: 'sharing-group' - }); - cacheAddedOrgName[sgOrgName] = 1; - } - edgesToAdd.push({ - from: 'sharing-group_' + sgName, - to: sgOrgName, - arrows: { - to: { enabled: false } - }, - color: { opacity: 0.4 } - }); - }); - }); - } - - var options = ''; - $('#sharingNetworkOrgFinder').empty(); - Object.keys(cacheAddedOrgName).forEach(function(org) { - options += ''; - }); - $('#sharingNetworkOrgFinder').append(options) - .trigger('chosen:updated') - .chosen({ - inherit_select_classes: true, - no_results_text: "Focus to an organisation", - placeholder_text_single: "Focus to an organisation", - allow_single_deselect: true - }) - .off('change') - .on('change', function(evt, params) { - if (this.value !== '') { - advancedSharingNetwork.focus(this.value, {animation: true}); - advancedSharingNetwork.selectNodes([this.value]); - } else { - advancedSharingNetwork.fit({animation: true}) - } - }); - - nodes_distri.add(nodesToAdd); - edges_distri.add(edgesToAdd); - var data = { nodes: nodes_distri, edges: edges_distri }; - var network_options = { - width: '800px', - height: '759px', - layout: {randomSeed: 0}, - edges: { - arrowStrikethrough: false, - arrows: { - to: {enabled: true, scaleFactor:1, type:'arrow'}, - }, - shadow: { - enabled: true, - size: 7, - x: 3, - y: 3 - } - }, - physics:{ - barnesHut: { - gravitationalConstant: -10000, - centralGravity: 0.3, - springLength: 150, - springConstant: 0.02, - damping: 0.09, - avoidOverlap: 0 - }, - repulsion: { - centralGravity: 0.2, - springLength: 200, - springConstant: 0.02, - nodeDistance: 200, - damping: 0.15 - }, - - solver: 'barnesHut' - }, - nodes: { - shadow: { - enabled: true, - size: 7, - x: 3, - y: 3 - } - }, - groups: { - 'root': { - shape: 'icon', - icon: { - face: 'FontAwesome', - code: '\uf10c', - color: '#000000', - size: 50 - }, - font: {size: 30}, - color: '#000000', - }, - 'org-only': { - shape: 'icon', - icon: { - face: 'FontAwesome', - code: '\uf2c2', - color: '#ff0000', - size: 30 - }, - font: { - size: 14, // px - color: '#ff0000', - background: 'rgba(255, 255, 255, 0.7)' - }, - color: '#ff0000', - }, - 'root-this-community': { - shape: 'icon', - icon: { - face: 'FontAwesome', - code: '\uf1e1', - color: '#ff9725', - size: 70 - }, - font: { - size: 18, // px - color: '#ff9725', - background: 'rgba(255, 255, 255, 0.7)' - }, - color: '#ff9725', - }, - 'this-community': { - font: {color: 'white'}, - color: '#ff9725', - shape: 'box', - margin: 3 - }, - 'root-connected-community': { - shape: 'icon', - icon: { - face: 'FontAwesome', - code: '\uf0e8', - color: '#9b6e1b', - size: 70 - }, - font: { - size: 18, // px - color: '#9b6e1b', - background: 'rgba(255, 255, 255, 0.7)' - }, - color: '#9b6e1b', - }, - 'connected-community': { - shape: 'image', - image: '/img/orgs/MISP.png' - }, - 'web': { - shape: 'icon', - icon: { - face: 'FontAwesome', - code: '\uf0ac', - color: '#007d20', - size: 70 - }, - font: { - size: 18, // px - color: '#007d20', - background: 'rgba(255, 255, 255, 0.7)' - }, - color: '#007d20', - }, - 'root-sharing-group': { - shape: 'icon', - icon: { - face: 'FontAwesome', - code: '\uf0c0', - color: '#1369a0', - size: 70 - }, - font: { - size: 18, // px - color: '#1369a0', - background: 'rgba(255, 255, 255, 0.7)' - }, - color: '#1369a0', - } - } - }; - advancedSharingNetwork = new vis.Network(document.getElementById('advancedSharingNetwork'), data, network_options); - - advancedSharingNetwork.on("dragStart", function (params) { - params.nodes.forEach(function(nodeId) { - nodes_distri.update({id: nodeId, fixed: {x: false, y: false}}); - }); - }); - advancedSharingNetwork.on("dragEnd", function (params) { - params.nodes.forEach(function(nodeId) { - nodes_distri.update({id: nodeId, fixed: {x: true, y: true}}); - }); - }); - - $('#interactive_picking_mode').off('change').on('change', function(e) { - var target_id = $(this).val(); - if (this.checked) { - toggleRowListener(true); - } else { - toggleRowListener(false); - construct_network(event_distribution) - } - }); -} - -function toggleRowListener(toAdd) { - if (toAdd) { - $('#attributes_div table tr').off('click.advancedSharing').on('click.advancedSharing', function() { - var $row = $(this); - var clicked_type = $row.attr('id').split('_')[0]; - var clicked_id = $row.attr('id').split('_')[1]; - // var $dist_cell = $row.find('#'+clicked_type+'_'+clicked_id+'_distribution_solid'); - var $dist_cell = $row.find('div').filter(function() { - return $(this).attr('id') !== undefined && $(this).attr('id').includes(clicked_id+'_distribution'); - }); - - var distribution_value; - var overwriteSg; - switch ($dist_cell.text().trim()) { - case 'Organisation': - distribution_value = 0; - break; - case 'Community': - distribution_value = 1; - break; - case 'Connected': - distribution_value = 2; - break; - case 'All': - distribution_value = 3; - break; - case 'Inherit': - distribution_value = 5; - if (event_distribution == 4) { - overwriteSg = event_distribution_text.trim(); - } - break; - default: - distribution_value = 4; - overwriteSg = $dist_cell.text().trim(); - break - } - construct_network(distribution_value, clicked_type+' '+clicked_id, [overwriteSg]); - }); - } else { - $('#attributes_div table tr').off('click.advancedSharing'); - } -} - - -function inject_this_community_org(nodesToAdd, edgesToAdd, orgs, group, root) { - orgs.forEach(function(orgName) { - if (cacheAddedOrgName[orgName] === undefined) { - nodesToAdd.push({ - id: orgName, - label: orgName, - group: group - }); - cacheAddedOrgName[orgName] = 1; - } - edgesToAdd.push({ - from: root, - to: orgName, - arrows: { - to: { enabled: false } - }, - color: { opacity: 0.4 } - }); - }); -} - function fetchDistributionData(callback) { $.ajax({ url: "/events/"+"getDistributionGraph"+"/"+scope_id+"/event.json", @@ -894,10 +430,11 @@ $(document).ready(function() { if (distributionData !== undefined) { construct_piechart(distributionData); } else { - fetchDistributionData(function(data) { construct_piechart(data); }); + fetchDistributionData(function(data) { + construct_piechart(data); + }); } }).on('hide.bs.popover', function(e) { - // $('#advancedSharingNetworkWrapper').hide('slide', {direction: 'right'}, 200, function() { $('#advancedSharingNetworkWrapper').remove(); }); }); $('body').on('mouseup', function(e) { @@ -909,5 +446,10 @@ $(document).ready(function() { fetchDistributionData(function(data) { drawBarChart(data); + $('#showAdvancedSharingButton').distributionNetwork({ + event_distribution: event_distribution, + distributionData: data, + scope_id: scope_id + }); }); }); diff --git a/cti-python-stix2 b/cti-python-stix2 index 469d17bce..407f346eb 160000 --- a/cti-python-stix2 +++ b/cti-python-stix2 @@ -1 +1 @@ -Subproject commit 469d17bceeed65373da3ac3b4f96600dfea8ca68 +Subproject commit 407f346eb8118d57b43035ef0da47e2ff77ed00e