From 97d075f22f0a01377f420313b6ffd7994f80f7b3 Mon Sep 17 00:00:00 2001 From: iglocska Date: Fri, 24 Aug 2018 14:21:50 +0200 Subject: [PATCH] new: [API] reworked the attribute level restsearch - use the new filter parameters - use the new condition building mechanism - no more pre-filtering --- app/Controller/AttributesController.php | 74 ++++++++++++++++++++++++- app/Model/Attribute.php | 49 ++++++++++++++++ app/Model/Event.php | 20 ++++++- 3 files changed, 138 insertions(+), 5 deletions(-) diff --git a/app/Controller/AttributesController.php b/app/Controller/AttributesController.php index 60fbb1096..176e57dc2 100644 --- a/app/Controller/AttributesController.php +++ b/app/Controller/AttributesController.php @@ -2082,7 +2082,77 @@ class AttributesController extends AppController $this->set('fails', $this->Attribute->checkComposites()); } - + public function restSearch($returnFormat = 'json', $value = false, $type = false, $category = false, $org = false, $tags = false, $from = false, $to = false, $last = false, $eventid = false, $withAttachments = false, $uuid = false, $publish_timestamp = false, $published = false, $timestamp = false, $enforceWarninglist = false, $to_ids = false, $deleted = false, $includeEventUuid = false, $event_timestamp = false, $threat_level_id = false) { + $paramArray = array('value' , 'type', 'category', 'org', 'tags', 'from', 'to', 'last', 'eventid', 'withAttachments', 'uuid', 'publish_timestamp', 'timestamp', 'enforceWarninglist', 'to_ids', 'deleted', 'includeEventUuid', 'event_timestamp', 'threat_level_id'); + $filterData = array( + 'request' => $this->request, + 'named_params' => $this->params['named'], + 'paramArray' => $paramArray, + 'ordered_url_params' => compact($paramArray) + ); + $exception = false; + $filters = $this->_harvestParameters($filterData, $exception); + unset($filterData); + if ($filters === false) { + return $exception; + } + $list = array(); + $user = $this->_getApiAuthUser($returnFormat, $exception); + if ($user === false) { + return $exception; + } + if (isset($filters['returnFormat'])) { + $returnFormat = $filters['returnFormat']; + } + $conditions = $this->Attribute->buildFilterConditions($this->Auth->user(), $filters); + $params = array( + 'conditions' => $conditions, + 'fields' => array('Attribute.*', 'Event.org_id', 'Event.distribution'), + 'withAttachments' => !empty($filters['withAttachments']) ? $filters['withAttachments'] : 0, + 'enforceWarninglist' => !empty($filters['enforceWarninglist']) ? $filters['enforceWarninglist'] : 0, + 'includeAllTags' => true, + 'flatten' => 1, + 'includeEventUuid' => !empty($filters['includeEventUuid']) ? $filters['includeEventUuid'] : 0, + ); + if (!empty($filtes['deleted'])) { + $params['deleted'] = 1; + if ($params['deleted'] === 'only') { + $params['conditions']['AND'][] = array('Attribute.deleted' => 1); + $params['conditions']['AND'][] = array('Object.deleted' => 1); + } + } + $results = $this->Attribute->fetchAttributes($this->Auth->user(), $params); + $this->loadModel('Whitelist'); + $results = $this->Whitelist->removeWhitelistedFromArray($results, true); + if ($returnFormat == 'openioc') { + App::uses('IOCExportTool', 'Tools'); + $this->IOCExport = new IOCExportTool(); + $results = $this->IOCExport->buildAll($this->Auth->user(), $results, 'attribute'); + } else { + if (!empty($results)) { + $results = array('response' => array('Attribute' => $results)); + foreach ($results['response']['Attribute'] as $k => $v) { + if (isset($results['response']['Attribute'][$k]['AttributeTag'])) { + foreach ($results['response']['Attribute'][$k]['AttributeTag'] as $tk => $tag) { + $results['response']['Attribute'][$k]['Attribute']['Tag'][$tk] = $tag['Tag']; + } + } + $results['response']['Attribute'][$k] = $results['response']['Attribute'][$k]['Attribute']; + unset( + $results['response']['Attribute'][$k]['value1'], + $results['response']['Attribute'][$k]['value2'] + ); + } + } else { + $results = array('response' => array('Attribute' => array())); + } + } + $responseType = $this->response->type(); + if ($returnFormat == 'openioc') { + $responseType = 'openioc'; + } + return $this->RestResponse->viewData($results, $responseType); + } // Use the rest interface to search for attributes. Usage: // MISP-base-url/attributes/restSearch/[api-key]/[value]/[type]/[category]/[orgc] @@ -2090,7 +2160,7 @@ class AttributesController extends AppController // the last 4 fields accept the following operators: // && - you can use && between two search values to put a logical OR between them. for value, 1.1.1.1&&2.2.2.2 would find attributes with the value being either of the two. // ! - you can negate a search term. For example: google.com&&!mail would search for all attributes with value google.com but not ones that include mail. www.google.com would get returned, mail.google.com wouldn't. - public function restSearch($key = 'download', $value = false, $type = false, $category = false, $org = false, $tags = false, $from = false, $to = false, $last = false, $eventid = false, $withAttachments = false, $uuid = false, $publish_timestamp = false, $published = false, $timestamp = false, $enforceWarninglist = false, $to_ids = false, $deleted = false, $includeEventUuid = false, $event_timestamp = false, $threat_level_id = false) + public function restSearch2($key = 'download', $value = false, $type = false, $category = false, $org = false, $tags = false, $from = false, $to = false, $last = false, $eventid = false, $withAttachments = false, $uuid = false, $publish_timestamp = false, $published = false, $timestamp = false, $enforceWarninglist = false, $to_ids = false, $deleted = false, $includeEventUuid = false, $event_timestamp = false, $threat_level_id = false) { if ($tags) { $tags = str_replace(';', ':', $tags); diff --git a/app/Model/Attribute.php b/app/Model/Attribute.php index 5f4cc2488..6a4c85303 100644 --- a/app/Model/Attribute.php +++ b/app/Model/Attribute.php @@ -3581,6 +3581,7 @@ class Attribute extends AppModel } return true; } + public function attachValidationWarnings($adata) { if (!$this->__fTool) { @@ -3591,4 +3592,52 @@ class Attribute extends AppModel } return $adata; } + + public function buildFilterConditions($user, &$params) + { + $conditions = $this->buildConditions($user); + $attribute_conditions = array(); + $object_conditions = array(); + $simple_params = array( + 'Attribute' => array( + 'value' => array('function' => 'set_filter_value'), + 'category' => array('function' => 'set_filter_simple_attribute'), + 'type' => array('function' => 'set_filter_simple_attribute'), + 'tags' => array('function' => 'set_filter_tags'), + 'uuid' => array('function' => 'set_filter_uuid'), + 'deleted' => array('function' => 'set_filter_deleted') + ), + 'Event' => array( + 'eventid' => array('function' => 'set_filter_eventid'), + 'ignore' => array('function' => 'set_filter_ignore'), + 'tags' => array('function' => 'set_filter_tags'), + 'tag' => array('function' => 'set_filter_tags'), + 'from' => array('function' => 'set_filter_timestamp'), + 'to' => array('function' => 'set_filter_timestamp'), + 'last' => array('function' => 'set_filter_timestamp'), + 'timestamp' => array('function' => 'set_filter_timestamp'), + 'publish_timestamp' => array('function' => 'set_filter_timestamp'), + 'org' => array('function' => 'set_filter_org'), + 'uuid' => array('function' => 'set_filter_uuid'), + 'published' => array('function' => 'set_filter_published') + ), + 'Object' => array( + 'object_name' => array('function' => 'set_filter_object_name'), + 'deleted' => array('function' => 'set_filter_deleted') + ) + ); + foreach ($params as $param => $paramData) { + foreach ($simple_params as $scope => $simple_param_scoped) { + if (isset($simple_param_scoped[$param]) && $params[$param] !== false) { + $options = array( + 'filter' => $param, + 'scope' => $scope, + 'pop' => !empty($simple_param_scoped[$param]['pop']) + ); + $conditions = $this->Event->{$simple_param_scoped[$param]['function']}($params, $conditions, $options); + } + } + } + return $conditions; + } } diff --git a/app/Model/Event.php b/app/Model/Event.php index 1186ac601..a160949cc 100755 --- a/app/Model/Event.php +++ b/app/Model/Event.php @@ -1297,9 +1297,6 @@ class Event extends AppModel public function filterEventIds($user, &$params = array()) { $conditions = $this->createEventConditions($user); - $paramArray = array('searchall', 'withAttachments', 'metadata', 'published', 'publish_timestamp', 'timestamp', 'enforceWarninglist', 'sgReferenceOnly'); - $attribute_conditions = array(); - $object_conditions = array(); $simple_params = array( 'Event' => array( 'eventid' => array('function' => 'set_filter_eventid', 'pop' => true), @@ -1995,6 +1992,23 @@ class Event extends AppModel return $conditions; } + public function set_filter_deleted(&$params, $conditions, $options) + { + if (!empty($params['deleted'])) { + if (empty($options['scope'])) { + $scope = 'Attribute'; + } else { + $scope = $options['scope']; + } + if ($params['deleted']) + $conditions = $this-> + $conditions = $this->generic_add_filter($conditions, $params['deleted'], $scope . '.deleted'); + } + return $conditions; + } + + + public function set_filter_ignore(&$params, $conditions, $options) { if (empty($params['ignore'])) {