mirror of https://github.com/MISP/MISP
Event ID translation feature (#6212)
* new: [sync] Event ID translation between sync serverspull/6262/head
parent
c5e200634c
commit
8844fd7ada
|
@ -423,6 +423,7 @@ class ACLComponent extends Component
|
|||
'getSubmoduleQuickUpdateForm' => array(),
|
||||
'getWorkers' => array(),
|
||||
'getVersion' => array('*'),
|
||||
'idTranslator' => array('*'),
|
||||
'import' => array(),
|
||||
'index' => array(),
|
||||
'ondemandAction' => array(),
|
||||
|
|
|
@ -1266,6 +1266,90 @@ class ServersController extends AppController
|
|||
}
|
||||
}
|
||||
|
||||
public function idTranslator() {
|
||||
|
||||
// The id translation feature is limited to people from the host org
|
||||
if (!$this->_isSiteAdmin() && $this->Auth->user('org_id') != Configure::read('MISP.host_org_id')) {
|
||||
throw new MethodNotAllowedException(__('You don\'t have the required privileges to do that.'));
|
||||
}
|
||||
|
||||
//We retrieve the list of remote servers that we can query
|
||||
$options = array();
|
||||
$options['conditions'] = array("pull" => true);
|
||||
$servers = $this->Server->find('all', $options);
|
||||
|
||||
// We generate the list of servers for the dropdown
|
||||
$displayServers = array();
|
||||
foreach($servers as $s) {
|
||||
$displayServers[] = array('name' => $s['Server']['name'],
|
||||
'value' => $s['Server']['id']);
|
||||
}
|
||||
$this->set('servers', $displayServers);
|
||||
|
||||
if ($this->request->is('post')) {
|
||||
$remote_events = array();
|
||||
if(!empty($this->request->data['Event']['uuid']) && $this->request->data['Event']['local'] == "local") {
|
||||
$local_event = $this->Event->fetchSimpleEvent($this->Auth->user(), $this->request->data['Event']['uuid']);
|
||||
} else if (!empty($this->request->data['Event']['uuid']) && $this->request->data['Event']['local'] == "remote" && !empty($this->request->data['Server']['id'])) {
|
||||
//We check on the remote server for any event with this id and try to find a match locally
|
||||
$conditions = array('AND' => array('Server.id' => $this->request->data['Server']['id'], 'Server.pull' => true));
|
||||
$remote_server = $this->Server->find('first', array('conditions' => $conditions));
|
||||
if(!empty($remote_server)) {
|
||||
try {
|
||||
$remote_event = $this->Event->downloadEventFromServer($this->request->data['Event']['uuid'], $remote_server, null, true);
|
||||
} catch (Exception $e) {
|
||||
$error_msg = __("Issue while contacting the remote server to retrieve event information");
|
||||
$this->logException($error_msg, $e);
|
||||
$this->Flash->error($error_msg);
|
||||
return;
|
||||
}
|
||||
|
||||
$local_event = $this->Event->fetchSimpleEvent($this->Auth->user(), $remote_event[0]['uuid']);
|
||||
//we record it to avoid re-querying the same server in the 2nd phase
|
||||
if(!empty($local_event)) {
|
||||
$remote_events[] = array(
|
||||
"server_id" => $remote_server['Server']['id'],
|
||||
"server_name" => $remote_server['Server']['name'],
|
||||
"url" => $remote_server['Server']['url']."/events/view/".$remote_event[0]['id'],
|
||||
"remote_id" => $remote_event[0]['id']
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
if(empty($local_event)) {
|
||||
$this->Flash->error( __("This event could not be found or you don't have permissions to see it."));
|
||||
return;
|
||||
} else {
|
||||
$this->Flash->success(__('The event has been found.'));
|
||||
}
|
||||
|
||||
// In the second phase, we query all configured sync servers to get their info on the event
|
||||
foreach($servers as $s) {
|
||||
// We check if the server was not already contacted in phase 1
|
||||
if(count($remote_events) > 0 && $remote_events[0]['server_id'] == $s['Server']['id']) {
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
$remote_event = $this->Event->downloadEventFromServer($local_event['Event']['uuid'], $s, null, true);
|
||||
$remote_event_id = $remote_event[0]['id'];
|
||||
} catch (Exception $e) {
|
||||
$this->logException("Couldn't download event from server", $e);
|
||||
$remote_event_id = null;
|
||||
}
|
||||
$remote_events[] = array(
|
||||
"server_id" => $s['Server']['id'],
|
||||
"server_name" => $s['Server']['name'],
|
||||
"url" => isset($remote_event_id) ? $s['Server']['url']."/events/view/".$remote_event_id : $s['Server']['url'],
|
||||
"remote_id" => isset($remote_event_id) ? $remote_event_id : false
|
||||
);
|
||||
}
|
||||
|
||||
$this->set('local_event', $local_event);
|
||||
$this->set('remote_events', $remote_events);
|
||||
}
|
||||
}
|
||||
|
||||
public function getSubmodulesStatus() {
|
||||
if (!$this->_isSiteAdmin()) {
|
||||
throw new MethodNotAllowedException();
|
||||
|
|
|
@ -1382,19 +1382,28 @@ class Event extends AppModel
|
|||
* @param int $eventId
|
||||
* @param array $server
|
||||
* @param null|HttpSocket $HttpSocket
|
||||
* @param boolean $metadataOnly, if True, we only retrieve the metadata
|
||||
* without attributes and attachments which is much faster
|
||||
* @return array
|
||||
* @throws Exception
|
||||
*/
|
||||
public function downloadEventFromServer($eventId, $server, $HttpSocket=null)
|
||||
public function downloadEventFromServer($eventId, $server, $HttpSocket=null, $metadataOnly=false)
|
||||
{
|
||||
$url = $server['Server']['url'];
|
||||
$HttpSocket = $this->setupHttpSocket($server, $HttpSocket);
|
||||
$request = $this->setupSyncRequest($server);
|
||||
$uri = $url . '/events/view/' . $eventId . '/deleted[]:0/deleted[]:1/excludeGalaxy:1';
|
||||
if (!empty($server['Server']['internal'])) {
|
||||
$uri = $uri . '/excludeLocalTags:1';
|
||||
if ($metadataOnly) {
|
||||
$uri = $url . '/events/index';
|
||||
$data = ['eventid' => $eventId];
|
||||
$data = json_encode($data);
|
||||
$response = $HttpSocket->post($uri, $data, $request);
|
||||
} else {
|
||||
$uri = $url . '/events/view/' . $eventId . '/deleted[]:0/deleted[]:1/excludeGalaxy:1';
|
||||
if (!empty($server['Server']['internal'])) {
|
||||
$uri = $uri . '/excludeLocalTags:1';
|
||||
}
|
||||
$response = $HttpSocket->get($uri, $data = '', $request);
|
||||
}
|
||||
$response = $HttpSocket->get($uri, $data = '', $request);
|
||||
|
||||
if ($response === false) {
|
||||
throw new Exception("Could not reach '$uri'.");
|
||||
|
|
|
@ -701,6 +701,13 @@ $divider = $this->element('/genericElements/SideMenu/side_menu_divider');
|
|||
));
|
||||
}
|
||||
}
|
||||
if ($menuItem === 'id_translator') {
|
||||
echo $this->element('/genericElements/SideMenu/side_menu_link', array(
|
||||
'text' => __('Event ID translator'),
|
||||
'url' => '/servers/id_translator',
|
||||
'element_id' => 'id_translator'
|
||||
));
|
||||
}
|
||||
break;
|
||||
|
||||
case 'admin':
|
||||
|
|
|
@ -298,6 +298,11 @@
|
|||
'text' => __('List Communities'),
|
||||
'url' => $baseurl . '/communities/index',
|
||||
'requirement' => ($isSiteAdmin)
|
||||
),
|
||||
array(
|
||||
'text' => __('Event ID translator'),
|
||||
'url' => '/servers/idTranslator',
|
||||
'requirement' => ($isSiteAdmin || $hostOrgUser)
|
||||
)
|
||||
)
|
||||
),
|
||||
|
|
|
@ -0,0 +1,75 @@
|
|||
<?php
|
||||
|
||||
echo $this->element('/genericElements/SideMenu/side_menu', array('menuList' => 'sync', 'menuItem' => 'id_translator'));
|
||||
|
||||
echo $this->element('/genericElements/Form/genericForm', array(
|
||||
'form' => $this->Form,
|
||||
'data' => array(
|
||||
'title' => __('Event ID translator'),
|
||||
'description' => __('Allows to translate a local ID into the corresponding event ID on sync servers configured.'),
|
||||
'model' => 'Event',
|
||||
'fields' => array(
|
||||
array(
|
||||
"field" => "uuid",
|
||||
"label" => __("Event ID or UUID"),
|
||||
"type" => "text",
|
||||
"placeholder" => __("1234"),
|
||||
"stayInLine" => true,
|
||||
),
|
||||
array(
|
||||
"field" => "local",
|
||||
"label" => __("referencing an event which is"),
|
||||
"default" => "local",
|
||||
"options" => array("local" => __("local"), "remote" => __("remote")),
|
||||
"type" => "select",
|
||||
"stayInLine" => true,
|
||||
),
|
||||
array(
|
||||
"field" => "Server.id",
|
||||
"div" => "input select optional-server-select hide",
|
||||
"options" => $servers,
|
||||
"label" => __("ID referenced on server:"),
|
||||
"type" => "select",
|
||||
)
|
||||
),
|
||||
"submit" => array (
|
||||
"action" => "idTranslator",
|
||||
),
|
||||
)
|
||||
));
|
||||
echo '<div class="view">';
|
||||
echo $this->Flash->render();
|
||||
if (isset($remote_events) && isset($local_event)) {
|
||||
$table_data = array();
|
||||
$table_data[] = array('key' => __('UUID'), 'value' => $local_event['Event']['uuid']);
|
||||
$link = '<a href="'.$base_url.'/events/view/'.$local_event['Event']['id'].'" target="_blank">'.$local_event['Event']['id'].'</a>';
|
||||
$table_data[] = array('key' => __('Local ID'), 'html' => $link);
|
||||
foreach($remote_events as $remote_event) {
|
||||
if($remote_event['remote_id']) {
|
||||
$value = __('Remote ID: ').'<a href="'.h($remote_event['url']).'" target="_blank">'.$remote_event['remote_id'].'</a>';
|
||||
$table_data[] = array('key' => h($remote_event['server_name']), 'html' => $value);
|
||||
} else {
|
||||
$table_data[] = array('key' => h($remote_event['server_name']), 'value' => __('Not found or server unreachable'));
|
||||
}
|
||||
}
|
||||
echo $this->element('genericElements/viewMetaTable', array('table_data' => $table_data));
|
||||
}
|
||||
|
||||
echo "</div>";
|
||||
|
||||
?>
|
||||
<script type="text/javascript">
|
||||
function IDTranslatorUISetup() {
|
||||
if($('#EventLocal').val() == "remote") {
|
||||
$(".optional-server-select").show();
|
||||
} else {
|
||||
$(".optional-server-select").hide();
|
||||
}
|
||||
}
|
||||
$(function() {
|
||||
IDTranslatorUISetup();
|
||||
});
|
||||
$("#EventLocal").change(function(){
|
||||
IDTranslatorUISetup();
|
||||
});
|
||||
</script>
|
Loading…
Reference in New Issue