Skip to content

Commit

Permalink
Merge pull request #61 from demisto/add-feed-json
Browse files Browse the repository at this point in the history
Add feed json support
  • Loading branch information
glicht authored Feb 6, 2021
2 parents aa97c7a + 867c4c3 commit 2a9feb3
Show file tree
Hide file tree
Showing 13 changed files with 524 additions and 5 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -92,3 +92,5 @@ git_push.sh
.swagger-codegen
.vscode
.pytest_cache
py27
py37
5 changes: 4 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,11 @@
[PyPI History][1]

[1]: https://pypi.org/project/demisto-py/#history
## 2.0.23
* Support for adding feed indicators via the route: `/indicators/feed/json`.

## 2.0.22
* don't cache last response in case `DONT_CACHE_LAST_RESPONSE` environment variable is set to true, this to avoid memory leaks.
* Don't cache last response in case `DONT_CACHE_LAST_RESPONSE` environment variable is set to true, this to avoid memory leaks.

## 2.0.20
* Log only headers in exceptions when `DEMISTO_EXCEPTION_HEADER_LOGGING` environment variable is set to true. This protects against possible sensitive data being logged in exceptions.
Expand Down
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -129,16 +129,16 @@ tox -l
```
Then setup dev virtual envs for both python 2 and 3 (will also install all necessary requirements):
```
tox --devenv venv2 --devenv py27
tox --devenv venv3 --devenv py37
tox --devenv py27
tox --devenv py37
```
Activate python 2 env by running:
```
. venv2/bin/activate
. py27/bin/activate
```
Switch to python 3 env by running:
```
. venv3/bin/activate
. py37/bin/activate
```

## Running Unit Tests
Expand Down
2 changes: 2 additions & 0 deletions demisto_client/demisto_api/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@
from demisto_client.demisto_api.models.expiration_source import ExpirationSource
from demisto_client.demisto_api.models.feed_indicator import FeedIndicator
from demisto_client.demisto_api.models.feed_indicators import FeedIndicators
from demisto_client.demisto_api.models.feed_indicators_request import FeedIndicatorsRequest
from demisto_client.demisto_api.models.field_group import FieldGroup
from demisto_client.demisto_api.models.field_mapping import FieldMapping
from demisto_client.demisto_api.models.field_term_location_map import FieldTermLocationMap
Expand Down Expand Up @@ -147,6 +148,7 @@
from demisto_client.demisto_api.models.playbook_view import PlaybookView
from demisto_client.demisto_api.models.question import Question
from demisto_client.demisto_api.models.quiet_mode import QuietMode
from demisto_client.demisto_api.models.raw_feed_indicator import RawFeedIndicator
from demisto_client.demisto_api.models.raw_message import RawMessage
from demisto_client.demisto_api.models.reliability import Reliability
from demisto_client.demisto_api.models.remote_repos import RemoteRepos
Expand Down
99 changes: 99 additions & 0 deletions demisto_client/demisto_api/api/default_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -709,6 +709,105 @@ def create_docker_image_with_http_info(self, **kwargs): # noqa: E501
_request_timeout=params.get('_request_timeout'),
collection_formats=collection_formats)

def create_feed_indicators_json(self, feed_indicators_request, **kwargs): # noqa: E501
"""Create feed indicators from JSON # noqa: E501
Create indicators from raw JSON (similar to ingesting from a feed). Builds indicators according to the specified feed classifier, or uses the default one if not specified. Indicator properties (all optional except for value): **value** (string, required) | **type** (string) | **score** (number, 0-3, default `0`, where `0` means None, `1` Good, `2` Suspicious, and `3` Bad) | **sourceBrand** (string, default `\"External\"`) | **sourceInstance** (string, default `\"External\"`) | **reliability** (string, one of `\"A - Completely reliable\"`, `\"B - Usually reliable\"`, `\"C - Fairly reliable\"`, `\"D - Not usually reliable\"`, `\"E - Unreliable\"`, `\"F - Reliability cannot be judged\"`) | **expirationPolicy** (string, one of `\"never\"`, `\"interval\"`, `\"indicatorType\"`) | **expirationInterval** (number, in minutes) # noqa: E501
This method makes a synchronous HTTP request by default. To make an
asynchronous HTTP request, please pass async_req=True
>>> thread = api.create_feed_indicators_json(feed_indicators_request, async_req=True)
>>> result = thread.get()
:param async_req bool
:param FeedIndicatorsRequest feed_indicators_request: (required)
:return: None
If the method is called asynchronously,
returns the request thread.
"""
kwargs['_return_http_data_only'] = True
if kwargs.get('async_req'):
return self.create_feed_indicators_json_with_http_info(feed_indicators_request, **kwargs) # noqa: E501
else:
(data) = self.create_feed_indicators_json_with_http_info(feed_indicators_request, **kwargs) # noqa: E501
return data

def create_feed_indicators_json_with_http_info(self, feed_indicators_request, **kwargs): # noqa: E501
"""Create feed indicators from JSON # noqa: E501
Create indicators from raw JSON (similar to ingesting from a feed). Builds indicators according to the specified feed classifier, or uses the default one if not specified. Indicator properties (all optional except for value): **value** (string, required) | **type** (string) | **score** (number, 0-3, default `0`, where `0` means None, `1` Good, `2` Suspicious, and `3` Bad) | **sourceBrand** (string, default `\"External\"`) | **sourceInstance** (string, default `\"External\"`) | **reliability** (string, one of `\"A - Completely reliable\"`, `\"B - Usually reliable\"`, `\"C - Fairly reliable\"`, `\"D - Not usually reliable\"`, `\"E - Unreliable\"`, `\"F - Reliability cannot be judged\"`) | **expirationPolicy** (string, one of `\"never\"`, `\"interval\"`, `\"indicatorType\"`) | **expirationInterval** (number, in minutes) # noqa: E501
This method makes a synchronous HTTP request by default. To make an
asynchronous HTTP request, please pass async_req=True
>>> thread = api.create_feed_indicators_json_with_http_info(feed_indicators_request, async_req=True)
>>> result = thread.get()
:param async_req bool
:param FeedIndicatorsRequest feed_indicators_request: (required)
:return: None
If the method is called asynchronously,
returns the request thread.
"""

all_params = ['feed_indicators_request'] # noqa: E501
all_params.append('async_req')
all_params.append('_return_http_data_only')
all_params.append('_preload_content')
all_params.append('_request_timeout')

params = locals()
for key, val in six.iteritems(params['kwargs']):
if key not in all_params:
raise TypeError(
"Got an unexpected keyword argument '%s'"
" to method create_feed_indicators_json" % key
)
params[key] = val
del params['kwargs']
# verify the required parameter 'feed_indicators_request' is set
if ('feed_indicators_request' not in params or
params['feed_indicators_request'] is None):
raise ValueError("Missing the required parameter `feed_indicators_request` when calling `create_feed_indicators_json`") # noqa: E501

collection_formats = {}

path_params = {}

query_params = []

header_params = {}

form_params = []
local_var_files = {}

body_params = None
if 'feed_indicators_request' in params:
body_params = params['feed_indicators_request']
# HTTP header `Accept`
header_params['Accept'] = self.api_client.select_header_accept(
['application/json']) # noqa: E501

# HTTP header `Content-Type`
header_params['Content-Type'] = self.api_client.select_header_content_type( # noqa: E501
['application/json', 'application/xml']) # noqa: E501

# Authentication setting
auth_settings = ['api_key', 'csrf_token'] # noqa: E501

return self.api_client.call_api(
'/indicators/feed/json', 'POST',
path_params,
query_params,
header_params,
body=body_params,
post_params=form_params,
files=local_var_files,
response_type=None, # noqa: E501
auth_settings=auth_settings,
async_req=params.get('async_req'),
_return_http_data_only=params.get('_return_http_data_only'),
_preload_content=params.get('_preload_content', True),
_request_timeout=params.get('_request_timeout'),
collection_formats=collection_formats)

def create_incident(self, **kwargs): # noqa: E501
"""Create single incident # noqa: E501
Expand Down
2 changes: 2 additions & 0 deletions demisto_client/demisto_api/models/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@
from demisto_client.demisto_api.models.expiration_source import ExpirationSource
from demisto_client.demisto_api.models.feed_indicator import FeedIndicator
from demisto_client.demisto_api.models.feed_indicators import FeedIndicators
from demisto_client.demisto_api.models.feed_indicators_request import FeedIndicatorsRequest
from demisto_client.demisto_api.models.field_group import FieldGroup
from demisto_client.demisto_api.models.field_mapping import FieldMapping
from demisto_client.demisto_api.models.field_term_location_map import FieldTermLocationMap
Expand Down Expand Up @@ -140,6 +141,7 @@
from demisto_client.demisto_api.models.playbook_view import PlaybookView
from demisto_client.demisto_api.models.question import Question
from demisto_client.demisto_api.models.quiet_mode import QuietMode
from demisto_client.demisto_api.models.raw_feed_indicator import RawFeedIndicator
from demisto_client.demisto_api.models.raw_message import RawMessage
from demisto_client.demisto_api.models.reliability import Reliability
from demisto_client.demisto_api.models.remote_repos import RemoteRepos
Expand Down
195 changes: 195 additions & 0 deletions demisto_client/demisto_api/models/feed_indicators_request.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,195 @@
# coding: utf-8

"""
Demisto API
This is the public REST API to integrate with the demisto server. HTTP request can be sent using any HTTP-client. For an example dedicated client take a look at: https://github.com/demisto/demisto-py. Requests must include API-key that can be generated in the Demisto web client under 'Settings' -> 'Integrations' -> 'API keys' Optimistic Locking and Versioning\\: When using Demisto REST API, you will need to make sure to work on the latest version of the item (incident, entry, etc.), otherwise, you will get a DB version error (which not allow you to override a newer item). In addition, you can pass 'version\\: -1' to force data override (make sure that other users data might be lost). Assume that Alice and Bob both read the same data from Demisto server, then they both changed the data, and then both tried to write the new versions back to the server. Whose changes should be saved? Alice’s? Bob’s? To solve this, each data item in Demisto has a numeric incremental version. If Alice saved an item with version 4 and Bob trying to save the same item with version 3, Demisto will rollback Bob request and returns a DB version conflict error. Bob will need to get the latest item and work on it so Alice work will not get lost. Example request using 'curl'\\: ``` curl 'https://hostname:443/incidents/search' -H 'content-type: application/json' -H 'accept: application/json' -H 'Authorization: <API Key goes here>' --data-binary '{\"filter\":{\"query\":\"-status:closed -category:job\",\"period\":{\"by\":\"day\",\"fromValue\":7}}}' --compressed ``` # noqa: E501
OpenAPI spec version: 2.0.0
Generated by: https://github.com/swagger-api/swagger-codegen.git
"""


import pprint
import re # noqa: F401

import six

from demisto_client.demisto_api.models.raw_feed_indicator import RawFeedIndicator # noqa: F401,E501


class FeedIndicatorsRequest(object):
"""NOTE: This class is auto generated by the swagger code generator program.
Do not edit the class manually.
"""

"""
Attributes:
swagger_types (dict): The key is attribute name
and the value is attribute type.
attribute_map (dict): The key is attribute name
and the value is json key in definition.
"""
swagger_types = {
'bypass_exclusion_list': 'bool',
'classifier_id': 'str',
'indicators': 'list[RawFeedIndicator]',
'mapper_id': 'str'
}

attribute_map = {
'bypass_exclusion_list': 'bypassExclusionList',
'classifier_id': 'classifierId',
'indicators': 'indicators',
'mapper_id': 'mapperId'
}

def __init__(self, bypass_exclusion_list=None, classifier_id=None, indicators=None, mapper_id=None): # noqa: E501
"""FeedIndicatorsRequest - a model defined in Swagger""" # noqa: E501

self._bypass_exclusion_list = None
self._classifier_id = None
self._indicators = None
self._mapper_id = None
self.discriminator = None

if bypass_exclusion_list is not None:
self.bypass_exclusion_list = bypass_exclusion_list
if classifier_id is not None:
self.classifier_id = classifier_id
if indicators is not None:
self.indicators = indicators
if mapper_id is not None:
self.mapper_id = mapper_id

@property
def bypass_exclusion_list(self):
"""Gets the bypass_exclusion_list of this FeedIndicatorsRequest. # noqa: E501
:return: The bypass_exclusion_list of this FeedIndicatorsRequest. # noqa: E501
:rtype: bool
"""
return self._bypass_exclusion_list

@bypass_exclusion_list.setter
def bypass_exclusion_list(self, bypass_exclusion_list):
"""Sets the bypass_exclusion_list of this FeedIndicatorsRequest.
:param bypass_exclusion_list: The bypass_exclusion_list of this FeedIndicatorsRequest. # noqa: E501
:type: bool
"""

self._bypass_exclusion_list = bypass_exclusion_list

@property
def classifier_id(self):
"""Gets the classifier_id of this FeedIndicatorsRequest. # noqa: E501
:return: The classifier_id of this FeedIndicatorsRequest. # noqa: E501
:rtype: str
"""
return self._classifier_id

@classifier_id.setter
def classifier_id(self, classifier_id):
"""Sets the classifier_id of this FeedIndicatorsRequest.
:param classifier_id: The classifier_id of this FeedIndicatorsRequest. # noqa: E501
:type: str
"""

self._classifier_id = classifier_id

@property
def indicators(self):
"""Gets the indicators of this FeedIndicatorsRequest. # noqa: E501
:return: The indicators of this FeedIndicatorsRequest. # noqa: E501
:rtype: list[RawFeedIndicator]
"""
return self._indicators

@indicators.setter
def indicators(self, indicators):
"""Sets the indicators of this FeedIndicatorsRequest.
:param indicators: The indicators of this FeedIndicatorsRequest. # noqa: E501
:type: list[RawFeedIndicator]
"""

self._indicators = indicators

@property
def mapper_id(self):
"""Gets the mapper_id of this FeedIndicatorsRequest. # noqa: E501
:return: The mapper_id of this FeedIndicatorsRequest. # noqa: E501
:rtype: str
"""
return self._mapper_id

@mapper_id.setter
def mapper_id(self, mapper_id):
"""Sets the mapper_id of this FeedIndicatorsRequest.
:param mapper_id: The mapper_id of this FeedIndicatorsRequest. # noqa: E501
:type: str
"""

self._mapper_id = mapper_id

def to_dict(self):
"""Returns the model properties as a dict"""
result = {}

for attr, _ in six.iteritems(self.swagger_types):
value = getattr(self, attr)
if isinstance(value, list):
result[attr] = list(map(
lambda x: x.to_dict() if hasattr(x, "to_dict") else x,
value
))
elif hasattr(value, "to_dict"):
result[attr] = value.to_dict()
elif isinstance(value, dict):
result[attr] = dict(map(
lambda item: (item[0], item[1].to_dict())
if hasattr(item[1], "to_dict") else item,
value.items()
))
else:
result[attr] = value
if issubclass(FeedIndicatorsRequest, dict):
for key, value in self.items():
result[key] = value

return result

def to_str(self):
"""Returns the string representation of the model"""
return pprint.pformat(self.to_dict())

def __repr__(self):
"""For `print` and `pprint`"""
return self.to_str()

def __eq__(self, other):
"""Returns true if both objects are equal"""
if not isinstance(other, FeedIndicatorsRequest):
return False

return self.__dict__ == other.__dict__

def __ne__(self, other):
"""Returns true if both objects are not equal"""
return not self == other
Loading

0 comments on commit 2a9feb3

Please sign in to comment.