PyIntel471/pyintel471/api.py

116 lines
5.8 KiB
Python

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import requests
import logging
import base64
from datetime import datetime
logger = logging.getLogger('pyintel471')
logger.setLevel(logging.DEBUG)
class PyIntel471:
def __init__(self, email: str, authkey: str):
self.auth = base64.b64encode(f'{email}:{authkey}'.encode()).decode()
def _prepare_request(self, request_type: str, url: str, data=None):
if logger.isEnabledFor(logging.DEBUG):
logger.debug('{} - {}'.format(request_type, url))
if data is not None:
logger.debug(data)
if data is None:
req = requests.Request(request_type, url)
else:
req = requests.Request(request_type, url, data=data)
with requests.Session() as s:
prepped = s.prepare_request(req)
prepped.headers.update({'Authorization': f'Basic {self.auth}'})
if logger.isEnabledFor(logging.DEBUG):
logger.debug(prepped.headers)
# TODO? handle the status codes
return s.send(prepped)
def url_parameters(self, createdFrom: datetime=None, createdUntil: datetime=None, lastUpdatedFrom: datetime=None, lastUpdatedUntil: datetime=None,
sort: str='relevance', offset: int=0, count: int=10, prettyPrint: bool=True, responseFormat: str=None):
'''Create a string with the parameters to append to the URL.
:param createdFrom:Search reports starting from given creation time (including). Object field: created. Empty indicates unbounded.
:param createdUntil:Search reports starting from given creation time (including). Object field: created. Empty indicates unbounded.
:param lastUpdatedFrom: Search results starting from given last updated time (including). Empty indicates unbounded.
:param lastUpdatedUntil: Search results ending before given last updated time (excluding). Empty indicates unbounded.
:param sort: Sort results by relevance or an object native time. Allowed values: "relevance" (default), "earliest" or "latest"
:param offset: Skip leading number of records. Default: 0
:param count: Returns given number of records starting from offset position. Default value: 10. Size range: 0-100
:param prettyPrint: Formats output json in human-readable form if present. Empty indicates Json. Allowed values: "csv".
'''
f = locals()
f.pop('self')
# Some parameters have to be renamed due to reserved words in Python.
if createdFrom:
f['from'] = f.pop('createdFrom')
if createdUntil:
f['until'] = f.pop('createdUntil')
f['format'] = f.pop('responseFormat')
return self.__prepare_url_path(f)
def search_filters(self, text: str=None, ipAddress: str=None, url: str=None, contactInfoEmail: str=None,
post: str=None, privateMessage: str=None, actor: str=None, entity: str=None, forum: str=None,
ioc: str=None, report: str=None, reportTag: str=None, reportLocation: str=None, reportAdmiraltyCode: str=None,
event: str=None, indicator: str=None, yara: str=None, nids: str=None, malwareReport: str=None, eventType: str=None,
indicatorType: str=None, nidsType: str=None, threatType: str=None, threatUid: str=None, malwareFamily: str=None,
malwareFamilyProfileUid: str=None, confidence: str=None, intelRequirement: str=None):
'''Returns selection of results matching filter criteria.
:param text: Search text everywhere
:param ipAddress: IP address search
:param url: URL search
:param contactInfoEmail: E-mail address search
:param post: Forum post search
:param privateMessage: Forum private message search
:param actor: Actor search
:param entity: Entity search
:param forum: Search posts in specific forum
:param ioc: Indicators of compromise search
:param report: Report search
:param reportTag: Search reports by tag
:param reportLocation: Search reports by location
:param reportAdmiraltyCode: Search reports by admiralty code
:param event: Free text event search
:param indicator: Free text indicator search
:param yara: Free text YARAs search
:param nids: Free text NIDS search
:param malwareReport: Free text malware reports search
:param eventType: Search events by type
:param indicatorType: Search indicators by type
:param nidsType: Search NIDS by type
:param threatType: Search events, indicators, YARAs, NIDS and malware reports by threat type.
:param threatUid: Search events, indicators, YARAs, NIDS and malware reports by threat uid.
:param malwareFamily: Search events, indicators, YARAs, NIDS and malware reports by malware family
:param malwareFamilyProfileUid: Search events, indicators, YARAs, NIDS and malware reports by malware family profile UID
'''
f = locals()
f.pop('self')
return self.__prepare_url_path(f)
def __prepare_url_path(self, params: dict):
to_return = []
for key, value in params.items():
if value is None:
continue
if isinstance(value, datetime):
# Date and time entries are UNIX timestamp multiplied by 1000
value = int(value.timestamp() * 1000)
to_return.append(f'{key}={value}')
return '&'.join(to_return)
def search(self, filters: str, parameters: str=None):
if parameters is None:
full_url = f'https://api.intel471.com/v1/search?{filters}'
else:
full_url = f'https://api.intel471.com/v1/search?{filters}&{parameters}'
return self._prepare_request('GET', full_url)