mirror of https://github.com/MISP/MISP
new: [sighting/api] trying to follow the new API architecture. JSON
export is broken but CSV is working. WIP...pull/3789/head
parent
41d2de90db
commit
99e5f560a8
|
@ -181,13 +181,14 @@ class RestResponseComponent extends Component
|
|||
'mandatory' => array('OR' => array('values', 'id')),
|
||||
'optional' => array('type', 'source', 'timestamp', 'date', 'time')
|
||||
),
|
||||
'get' => array(
|
||||
'restSearch' => array(
|
||||
'description' => "Search MISP using a list of filter parameters and return the data in the JSON format.
|
||||
The search is available on an event, attribute or instace level,
|
||||
just select the scope via the URL (/sighting/get/event vs /sighting/get/).",
|
||||
'mandatory' => array('context'),
|
||||
just select the scope via the URL (/sighting/get/event vs /sighting/get/).
|
||||
id MUST be provided is context is set.",
|
||||
'mandatory' => array('returnFormat'),
|
||||
'optional' => array('id', 'type', 'from', 'to', 'last', 'org_id', 'includeAttribute', 'includeEvent'),
|
||||
'params' => array()
|
||||
'params' => array('context')
|
||||
),
|
||||
),
|
||||
'SharingGroup' => array(
|
||||
|
@ -454,14 +455,15 @@ class RestResponseComponent extends Component
|
|||
|
||||
private function __setup() {
|
||||
if (!$this->__setup) {
|
||||
$scopes = array('Event', 'Attribute');
|
||||
$scopes = array('Event', 'Attribute', 'Sighting');
|
||||
foreach ($scopes as $scope) {
|
||||
$this->{$scope} = ClassRegistry::init($scope);
|
||||
$this->__descriptions[$scope]['restSearch'] = array(
|
||||
'description' => $this->__descriptions[$scope]['restSearch']['description'],
|
||||
'returnFormat' => array_keys($this->{$scope}->validFormats),
|
||||
'mandatory' => $this->__descriptions[$scope]['restSearch']['mandatory'],
|
||||
'optional' => $this->__descriptions[$scope]['restSearch']['optional']
|
||||
'optional' => $this->__descriptions[$scope]['restSearch']['optional'],
|
||||
'params' => $this->__descriptions[$scope]['restSearch']['params']
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -220,9 +220,9 @@ class SightingsController extends AppController
|
|||
return $this->RestResponse->viewData($sightings);
|
||||
}
|
||||
|
||||
public function get($context = false)
|
||||
public function restSearch($context = false)
|
||||
{
|
||||
$paramArray = array('id', 'type', 'from', 'to', 'last', 'org_id');
|
||||
$paramArray = array('returnFormat', 'id', 'type', 'from', 'to', 'last', 'org_id', 'includeAttribute', 'includeEvent');
|
||||
$filterData = array(
|
||||
'request' => $this->request,
|
||||
'named_params' => $this->params['named'],
|
||||
|
@ -232,13 +232,24 @@ class SightingsController extends AppController
|
|||
$filters = $this->_harvestParameters($filterData, $exception);
|
||||
$filters['context'] = $context;
|
||||
|
||||
if (isset($filters['returnFormat'])) {
|
||||
$returnFormat = $filters['returnFormat'];
|
||||
}
|
||||
if ($returnFormat === 'download') {
|
||||
$returnFormat = 'json';
|
||||
}
|
||||
|
||||
// ensure that an id is provided if context is set
|
||||
if ($context !== false && !isset($filters['id'])) {
|
||||
throw new MethodNotAllowedException(_('An id must be provided if the context is set.'));
|
||||
}
|
||||
|
||||
$sightings = $this->Sighting->getSightingsForTime($this->Auth->user(), $filters);
|
||||
return $this->RestResponse->viewData($sightings);
|
||||
$sightings = $this->Sighting->getSightingsForTime($this->Auth->user(), $returnFormat, $filters);
|
||||
|
||||
$validFormats = $this->Sighting->validFormats;
|
||||
$responseType = $validFormats[$returnFormat][0];
|
||||
return $this->RestResponse->viewData($sightings, $responseType, false, true);
|
||||
//return $this->RestResponse->viewData($sightings);
|
||||
}
|
||||
|
||||
public function listSightings($id, $context = 'attribute', $org_id = false)
|
||||
|
|
|
@ -14,6 +14,8 @@ class CsvExport
|
|||
$lines = $this->__attributesHandler($data, $options);
|
||||
} else if($options['scope'] === 'Event') {
|
||||
$lines = $this->__eventsHandler($data, $options);
|
||||
} else if($options['scope'] === 'Sighting') {
|
||||
$lines = $this->__sightingsHandler($data, $options);
|
||||
}
|
||||
return $lines;
|
||||
}
|
||||
|
@ -46,6 +48,32 @@ class CsvExport
|
|||
return $this->__addLine($attribute, $options);
|
||||
}
|
||||
|
||||
private function __sightingsHandler($sighting, $options)
|
||||
{
|
||||
$lines = '';
|
||||
if (isset($sighting['Sighting']['Event'])) {
|
||||
foreach($sighting['Sighting']['Event'] as $k => $event_val) {
|
||||
$new_key = 'event_' . $k;
|
||||
// in case we have an array, e.g. orc => name
|
||||
if (is_array($event_val)) {
|
||||
$v2 = reset($event_val);
|
||||
$k2 = key($event_val);
|
||||
$new_key .= '_' . $k2;
|
||||
$event_val = $v2;
|
||||
}
|
||||
$sighting['Sighting'][$new_key] = $event_val;
|
||||
}
|
||||
}
|
||||
if (isset($sighting['Sighting']['Attribute'])) {
|
||||
foreach($sighting['Sighting']['Attribute'] as $k => $attribute_val) {
|
||||
$new_key = 'attribute_' . $k;
|
||||
$sighting['Sighting'][$new_key] = $attribute_val;
|
||||
}
|
||||
}
|
||||
$lines .= $this->__addLine($sighting['Sighting'], $options);
|
||||
return $lines;
|
||||
}
|
||||
|
||||
private function __eventsHandler($event, $options)
|
||||
{
|
||||
$lines = '';
|
||||
|
|
|
@ -38,6 +38,20 @@ class Sighting extends AppModel
|
|||
2 => 'expiration'
|
||||
);
|
||||
|
||||
public $validFormats = array(
|
||||
'json' => array('json', 'JsonExport', 'json'),
|
||||
//'openioc' => array('xml', 'OpeniocExport', 'ioc'),
|
||||
//'xml' => array('xml', 'XmlExport', 'xml'),
|
||||
//'suricata' => array('txt', 'NidsSuricataExport', 'rules'),
|
||||
//'snort' => array('txt', 'NidsSnortExport', 'rules'),
|
||||
//'rpz' => array('rpz', 'RPZExport', 'rpz'),
|
||||
//'text' => array('text', 'TextExport', 'txt'),
|
||||
'csv' => array('csv', 'CsvExport', 'csv'),
|
||||
//'stix' => array('xml', 'Stix1Export', 'xml'),
|
||||
//'stix2' => array('json', 'Stix2Export', 'json'),
|
||||
//'cache' => array('txt', 'CacheExport', 'cache')
|
||||
);
|
||||
|
||||
public function beforeValidate($options = array())
|
||||
{
|
||||
parent::beforeValidate();
|
||||
|
@ -449,8 +463,13 @@ class Sighting extends AppModel
|
|||
return $sightingsRearranged;
|
||||
}
|
||||
|
||||
public function getSightingsForTime($user, $filters)
|
||||
public function getSightingsForTime($user, $returnFormat, $filters)
|
||||
{
|
||||
if (!isset($this->validFormats[$returnFormat][1])) {
|
||||
throw new NotFoundException('Invalid output format.');
|
||||
}
|
||||
App::uses($this->validFormats[$returnFormat][1], 'Export');
|
||||
$exportTool = new $this->validFormats[$returnFormat][1]();
|
||||
|
||||
// fetch sightings matching the query
|
||||
if (isset($filters['from']) && isset($filters['to'])) {
|
||||
|
@ -490,21 +509,79 @@ class Sighting extends AppModel
|
|||
));
|
||||
$sightings = array_values($sightings);
|
||||
|
||||
$filters['requested_attributes'] = array('id', 'attribute_id', 'event_id', 'org_id', 'date_sighting', 'uuid', 'source', 'type');
|
||||
|
||||
// apply ACL and sightings policies
|
||||
$allowedSightings = array();
|
||||
$additional_attribute_added = false;
|
||||
$additional_event_added = false;
|
||||
foreach($sightings as $sid) {
|
||||
$sight = $this->getSighting($sid, $user);
|
||||
// by default, do not include event and attribute
|
||||
if (!isset($filters['includeAttribute']) || !$filters['includeAttribute']) {
|
||||
unset($sight["Sighting"]["Attribute"]);
|
||||
} else if (!$additional_attribute_added) {
|
||||
$filters['requested_attributes'] = array_merge($filters['requested_attributes'], array('attribute_uuid', 'attribute_type', 'attribute_category', 'attribute_to_ids', 'attribute_value'));
|
||||
$additional_attribute_added = true;
|
||||
}
|
||||
|
||||
if (!isset($filters['includeEvent']) || !$filters['includeEvent']) {
|
||||
unset($sight["Sighting"]["Event"]);
|
||||
} else if (!$additional_event_added) {
|
||||
$filters['requested_attributes'] = array_merge($filters['requested_attributes'], array('event_uuid', 'event_orgc_id', 'event_org_id', 'event_info', 'event_Orgc_name'));
|
||||
$additional_event_added = true;
|
||||
}
|
||||
|
||||
if (!empty($sight)) {
|
||||
array_push($allowedSightings, $sight);
|
||||
}
|
||||
}
|
||||
return $allowedSightings;
|
||||
|
||||
$params = array(
|
||||
'conditions' => array(), //result already filtered
|
||||
);
|
||||
|
||||
if (!isset($this->validFormats[$returnFormat])) {
|
||||
// this is where the new code path for the export modules will go
|
||||
throw new MethodNotFoundException('Invalid export format.');
|
||||
}
|
||||
if (method_exists($exportTool, 'modify_params')) {
|
||||
//$params = $exportTool->modify_params($user, $params);
|
||||
}
|
||||
|
||||
$exportToolParams = array(
|
||||
'user' => $user,
|
||||
'params' => $params,
|
||||
'returnFormat' => $returnFormat,
|
||||
'scope' => 'Sighting',
|
||||
'filters' => $filters
|
||||
);
|
||||
if (!empty($exportTool->additional_params)) {
|
||||
//$params = array_merge($params, $exportTool->additional_params);
|
||||
}
|
||||
|
||||
$tmpfile = tmpfile();
|
||||
fwrite($tmpfile, $exportTool->header($exportToolParams));
|
||||
|
||||
$temp = '';
|
||||
$i = 0;
|
||||
foreach ($allowedSightings as $sighting) {
|
||||
$temp .= $exportTool->handler($sighting, $exportToolParams);
|
||||
if ($temp !== '') {
|
||||
if ($i != count($allowedSightings) -1) {
|
||||
$temp .= $exportTool->separator($exportToolParams);
|
||||
}
|
||||
}
|
||||
$i++;
|
||||
}
|
||||
fwrite($tmpfile, $temp);
|
||||
|
||||
fwrite($tmpfile, $exportTool->footer($exportToolParams));
|
||||
fseek($tmpfile, 0);
|
||||
$final = fread($tmpfile, fstat($tmpfile)['size']);
|
||||
fclose($tmpfile);
|
||||
return $final;
|
||||
|
||||
//return $allowedSightings;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue