TheHive4py 1.8.0 is hot off the press

TheHive4py 1.8.0 is finally released. During the last 5 months, the team was busy working on TheHive and Cortex but today, it’s time to unveil the biggest milestone of TheHive’s official python API client.

TheHive4py official documentation website

1.8.0 contains 31 Github issues including 17 contributions for which, we would like to thank all the community members who helped shaping the release.

TheHive4py is getting a bit hard to maintain because of the backward compatibility constraints introduced by TheHive 3 and 4 versions. TheHive 4 also introduces new features that are not available in TheHive 3, and this makes it challenging to serve both versions with the same code base.

TheHive 4 has also its dedicated and optimised APIs (read APIs v1), and those are not used by TheHive4py, which is still relying on APIs v0 of TheHive 4.

Anyways.

What’s new?

1.8.0 release introduced a significant number of new methods and changes:

  • attachment download support for files (by id), observables and task log attachments
  • alert merge into case
  • alert delete
  • case task delete
  • case task log search
  • task log search
  • support to alert similarity in fetch
  • case observable search method
  • case observable fetch method
  • case observable delete method
  • support to in memory files when calling APIs evolving attachments
  • MISP export
  • support to PAP in alerts
  • add Tlp, Pap, Severity, CaseStatus, TaskStatus enumerations

in addition to some TheHive 4 related features:

  • Add a version parameter to TheHiveApi class’s constructor
  • Add support to ignoreSimilarity attribute
  • Add support to alert.externalLink attribute

Please read the full release notes for more details.

Below, we will highlight the major features other than the self explanatory newly added methods.

New version parameter

This change is important and required for developers using TheHive4py to play with a TheHive 4 instance. the `version` parameter has been introduced to allow fine tune access to features available on TheHive 4 and not in TheHive 3, like for `alert.extrnalLink` field.

The version is set by default to Version.THEHIVE_3.value, which means version 3.

from thehive4py.models import Version

# Init an API client for TheHive 4
api = TheHiveApi(THEHIVE_URL, API_KEY, version=Version.THEHIVE_4.value)

Add support to ignoreSimilarity field

This capability has been introduced by TheHive 4.0.1 release. It allows setting an `ignoreSimilarity` flag at the case and alert observable level. When set to True it tells TheHive to ignore the observable from any similarity computing.

So, if you need to create an alert with an observable you would like to skip when running the similarity algorithm, then, you need to set ignoreSimilarity to True

Here is an example that creates and alert with an observable to be ignored for similarity:

import uuid
from thehive4py.api import TheHiveApi
from thehive4py.models import Tlp, Pap, Alert, AlertArtifact

sourceRef = str(uuid.uuid4())[0:6]

# Prepare the Alert object
alert = Alert(title='Sample alert - ID {}'.format(sourceRef), 
  tlp=Tlp.AMBER.value, 
  pap=Pap.AMBER.value, 
  tags=['TheHive4Py'],
  description='Sample alert for the blog post',
  source='dev',
  type='script',
  sourceRef=sourceRef,
  externaleLink='https://some-web-site/alert/{}'.format(sourceRef),
  artifacts=[
    AlertArtifact(
      dataType='domain', 
      data='dl.some-web-site.com', 
      tlp=Tlp.WHITE.value, 
      ioc=True,
      sighted=False,
      ignoreSimilarity=True
    )
  ])

# Init an API client instance
api = TheHiveApi(THEHIVE_URL, THEHIVE_API_KEY, version=4)

# Create the alert
response = api.create_alert(alert)

Note that the same option is available for Case observables during creation and update:

# Set an observable as ignorable

api.update_case_observable(
   observable_id, 
   {"ignoreSimilarity": True}, 
   fields=['ignoreSimilarity']
 )

Support in-memory files

Old versions of TheHiv4py required existing files when dealing with attachments. For example, to create a file case observable, the corresponding file has to be already stored on the file system before calling the `create_case_observable` method.

This release allows using files from memory and not relying on file paths. So you use, for example, an API to download a file and you want to store that file as observable, you can use the new feature of TheHive4py, as below:

from thehive4py.models import Tlp, Pap, Alert, CaseObservable

# Say you have a method to get a screenshot
file = get_screenshot()

# Prepare the observable
observable = CaseObservable(
    dataType='file',
    data=(file, 'screenshot-{}.png'.format(int(time.time())*1000)),
    tlp=Tlp.WHITE.value,
    pap=Pap.GREEN.value,
    tags=['category:screenshot']
)

# Create the observable
response = api.create_case_observable(case_id, observable)

# Close the file object
file.close()

Note: closing the file object is still required. We will handle closing the files during the upcoming releases.

Attachment download features

The new methods introduced by 1.8.0 release and related to attachment download, light some interesting TheHive APIs up.

Did you know TheHive has APIs to download existing file from the datastore? Do you know how does TheHive store files?

Well, when a file is uploaded to TheHive as case observable, alert observable or case log attachments, the file is stored in the DataStore and is given an ID that can be used in two APIs:

  • `/api/datastore/{attachment_id}`: downloads the file content
  • `/api/datastorezip/{attachment_id}`: downloads the file content as zip password protected file, and the password is the one defined in application.conf (defaults to `malware`)

In this release, we introduced methods to make these APIs available on TheHive4py.

Download an attachment by its ID

This method is useful if you know the attachment ID (could be an alert file observable for exemple, in TheHive 4)

# Download an attachment by a known id
response = api.download_attachment(
  attachment_id, 
  filename='screenshot.png',
  archive=False
)

# Save the attachment to disk
f = open('./{}'.format('screenshot.png'), 'wb')
f.write(response.content)
f.close()

Download an attachment of a task log

This method allows downloading the attachment of a given task log object, identified by its ID

response = api.download_task_log_attachment(log_id, archive=False)

f = open('./{}'.format('screenshot.png'), 'wb')
f.write(response.content)
f.close()

If the task log doesn’t have an attachment, this methods throws an exception.

Download a file attachment of a file observable

This methods allows downloading a file observable, and forces protecting it as password protected zip archive

response = api.download_observable_attachment(observable_id)

f = open('./{}'.format('observable.png.zip'), 'wb')
f.write(response.content)
f.close()

If the observable is not a file, this methods throws an exception.

Documentation

As you might know, with the 1.7.0 release we released a documentation website for TheHive4py where all the methods are documented. Donc hesitate to refer to it for more details: https://thehive-project.github.io/TheHive4py

Updating/Installing

To update your existing package to version 1.8.0:

$ sudo pip install thehive4py --upgrade

Got a question?

If you encounter any difficulty, please join our  user forum, contact us on Discord, or send us an email at support@thehive-project.org. As usual, we’ll be more than happy to help!

TheHive4py got a second wind, version 1.7.0 released

“TheHive4py”, this sounds like a word you didn’t hear about during the last 12 months. Well, our focus on this library was put on hold. We will tell you the reason, but much better, we will solve the problem.

A brief review

TheHive4py was quickly initiated after the first releases of TheHive to help developers interact with TheHive APIs using python. We started creating methods and functions for main functionalities and to be honest, it was a sort of a quick-and-dirty solution.

TheHive4py has some limitation:

  • The API client is a flat class with dozens of methods
  • The API clients’ methods return the native `requests.Reponse` class instead of a structured data
  • Exception handling could be improved
  • Code could be made more reusable

As developers, we are aware of these limitations and are eager to provide a better library, and that’s what we started making with TheHive4py rewrite. We wanted to provide you with a library you can use this way:

# Fetch cases
open_cases = api.cases.find_all({'status': 'Open'}, range='0-5')
log('Open cases', list(map(lambda i: i.json(), open_cases)))

# Fetch a case by `id` or `number` (caseId)
sample_case = open_cases[0]
log('case details by id', api.cases.get_by_id(sample_case.id).json())
log('case details by number', api.cases.get_by_number(sample_case.caseId).json())

# Fetch alerts
new_alerts = api.alerts.find_all({'status': 'New'}, range='0-2')
log('New alerts', list(map(lambda i: i.json(), new_alerts)))

# Fetch observables
domain_observables = api.observables.find_all({'dataType': 'domain'}, range='0-2')
log('New alerts', list(map(lambda i: i.json(), domain_observables)))

# Fetch tasks
waiting_tasks = api.tasks.find_all({'status': 'Waiting'}, range='0-2')
log('Waiting tasks', list(map(lambda i: i.json(), waiting_tasks)))

waiting_tasks = api.tasks.get_waiting(range='0-2')
log('Waiting tasks', list(map(lambda i: i.json(), waiting_tasks)))

jdoe_tasks = api.tasks.get_by_user('jdoe', {}, range='0-3')
log('Tasks of jdoe', list(map(lambda i: i.json(), jdoe_tasks)))

case_tasks = api.tasks.of_case(sample_case.id, query={'status': 'Waiting'})
log('Case tasks', list(map(lambda i: i.json(), case_tasks)))

The library’s rewrite was supposed to produce a 2.0.0 version of TheHive4py but we had a major issue: backward compatibility.

Well, in theory, backward compatibility can be handled through a clear communication to:

  • tell the users how to make sure to update their dependencies to TheHive4py < 2.0.0
  • provide a migration plan
  • maintain both versions during a certain time
  • maintain documentation for old and new versions

To be honest, this was hard to achieve, because of the famous lack of time, but things a going to change.

What’s the plan?

We didn’t want to make a plan without asking the community about how they interact with TheHive APIs. So we did two twitter polls that ended up with the following results:

Twitter poll about TheHive API usage methods

The second poll asked our users about pros and cons of TheHive4py:

Twitter poll about TheHive4py pros and cons

The poll results are clear: we need to put more efforts on TheHive4py.

Here we go, firstly, let’s release version 1.7.0

TheHive4py 1.7.0 milestone has been initiated almost one year ago, and we are happy to announce its availability today.

What’s new about it?

The most important change is allowing TheHive4py to interact with TheHive 4 in addition to introducing some missing features, and bug fixes. Here is a short listing of main changes:

Add support to multi tenancy

Allow a developer to specify the organisation against which an API call is done:

api = TheHiveApi('http://my_thehive:9000', 'my_api_key', organisation='cert')

Add custom field support for new types:

TheHive 4 introduces custom fields of type integer and float, this feature allows specifying custom fields with types supported by TheHive 4. These types are not supported by TheHive 3.

CustomFieldHelper
   .add_integer('number_hits', 10)
   .add_float('cvss', 5.6)
   .build()

The code snippet above produces the following content:

{
  "number_hits": {
    "order": 0,
    "integer": 100
  },
  "cvss": {
    "order": 1,
    "integer": 5.6
  }
}

Add support to like and wildcard query operators

TheHive query DSL supports like and wildcard operators, but TheHive4py didn’t had an option to use those operators. In this version the following query methods have been added:

  • Like (field, value): Field’s value must contain value, that must contain `*` in the beginning or at the end
  • StratsWith (field, value): Field’s value must start with value
  • EndsWith (field, value): Field’s value must end with value
  • ContainsString (field, value): Field’s value must contain value
from thehive4py.query import Eq, Like, And, StartsWith

# find cases where title contains 'Dridex'
api.find_cases(query=Like('title', 'Dridex*'))

# find alerts where status is 'New' and title starts with 'Emotet'
api.find_alert(query=And(Eq('status', 'New'), StartsWith('title', 'Emotet')))

Add ioc and sighted attributes to case and alert artifacts

This allows specifying these attributes during Alert or Case observables creation

Add update_case_observable method

Can be used to patch an existing observable, by setting a tag or marking as IOC.

Add PAP to Case and CaseTemplate models

PAP flag has been added in TheHive recently and TheHive4py was not able to set the PAP value of a Case or CaseTemplate

Add custom fields creation method

Added a `create_custom_field` method that check custom field name uniqueness before creating it.

Note: This method is for now, compatible with TheHive 3 only because it relies on the DBList API that is no longer available on TheHive 4.

Add case template creation method

Added a `create_case_template` method allowing developers to create new Case Templates.

The full change log is available at the release page

What about documentation

Once again we are glad to announce the initial version of a documentation website, dedicated to TheHive4py, including documentation of all the features the library provides, and code samples of the most useful features.

We aim to maintain and improve this documentation over time, so please, don’t hesitate to either contribute or ask for more content.

Screenshot of the documentation website

TheHive4py 2.0

We will put the rewrite of TheHive4py on hold for now and will communicate about it again when we are ready. In the meantime, we will continue maintaining TheHive4py 1.x.

Update: TheHive4py 1.7.1 Patch

During the release 1.7.0, we have noticed that the build process and deployment went wrong, so we have created a 1.7.0.post1 release.

The community also raised a regression that has been fixed in 1.7.1 release. You can read the change log for more details.

Updating/Installing

To update your existing package to version 1.7.0:

$ sudo pip install thehive4py --upgrade

Got a question?

If you encounter any difficulty, please join our  user forum, contact us on Gitter, or send us an email at support@thehive-project.org. As usual, we’ll be more than happy to help!