resilient

Python client module for the IBM SOAR REST API

API Client

class SimpleClient(org_name=None, base_url=None, proxies=None, verify=None, cache_ttl=240, certauth=None, custom_headers=None, **kwargs)

Python helper class for using the IBM SOAR REST API.

'''
An example script showing how to connect and get
incidents with IBM Security SOAR

Example Usage:
python sample_connect.py "https://<host>", "<org_name>", "<api_key_id>", "<api_key_secret>", "<path_to_ca_file>|False"
'''

import sys
import os
from resilient import SimpleClient


def main():

    args = sys.argv
    assert len(args) == 6
    SCRIPT_NAME = args[0]

    # Get required parameters
    HOST = args[1]
    ORG_NAME = args[2]
    API_KEY_ID = args[3]
    API_KEY_SECRET = args[4]

    # Check if using cafile
    ca_file = args[5]
    VERIFY = ca_file if os.path.isfile(ca_file) is True else False

    # Instansiate SimpleClient
    res_client = SimpleClient(
        org_name=ORG_NAME,
        base_url=HOST,
        verify=VERIFY
    )

    # Set the API Key
    res_client.set_api_key(
        api_key_id=API_KEY_ID,
        api_key_secret=API_KEY_SECRET
    )

    # Setup the request payload
    payload = {
        "filters": [
            {
                "conditions": [{"field_name": "plan_status", "method": "equals", "value": "A"}]
            }
        ]
    }

    # Invoke the request
    response = res_client.post("/incidents/query_paged?return_level=full", payload=payload)

    # Print results
    for incident in response.get("data", []):
        print("{0}: {1}".format(incident.get("id"), incident.get("name")))


if __name__ == "__main__":
    main()

Note

The full REST API Documentation for IBM SOAR can be viewed on the Platform itself by searching for the REST API Reference or by going to: https://<base_url>/docs/rest-api/index.html

__init__(org_name=None, base_url=None, proxies=None, verify=None, cache_ttl=240, certauth=None, custom_headers=None, **kwargs)
Parameters:
  • org_name (str) – The name of the organization to use.

  • base_url (str) – The base URL of the SOAR server, e.g. https://soar.ibm.com/

  • proxies (dict) – A dictionary of HTTP proxies to use, if any.

  • verify (str|bool) – The path to a PEM file containing the trusted CAs, or False to disable all TLS verification

  • cache_ttl (int) – Time in seconds to live for cached API responses

  • certauth (str|tuple(str, str)) – The filepath for the client side certificate and the private key either as a single file or as a tuple of both files’ paths

  • custom_headers (dict) – A dictionary of any headers you want to send in every request

  • kwargs (dict) –

    A dictionary of any other keyword arguments including;

    • max_connection_retries (int) - Number of attempts to retry when connecting to SOAR. Use -1 for unlimited retries. Defaults to -1.

    • request_max_retries (int) - Max number of times to retry a request to SOAR before exiting. Defaults to 5.

    • request_retry_delay (int) - Number of seconds to wait between retries. Defaults to 2.

    • request_retry_backoff (int) - Multiplier applied to delay between retry attempts. Defaults to 2.

cached_get(uri, co3_context_token=None, timeout=None, skip_retry=[])

Same as get(), but checks cache first

connect(email, password, timeout=None)

Connect and authenticate to the IBM SOAR REST API service.

Parameters:
  • email (str) – The email address to use for authentication.

  • password (str) – The password.

  • timeout (int) – optional timeout (seconds)

Returns:

The IBM SOAR session object.

Raises:

SimpleHTTPException – if an HTTP exception occurs.

delete(uri, co3_context_token=None, timeout=None, skip_retry=[])

Deletes the specified URI.

Note

This URI is relative to <base_url>/rest/orgs/<org_id>. So for example, if you specify a uri of /incidents, the actual URL would be something like: https://soar.ibm.com/rest/orgs/201/incidents

Parameters:
  • uri (str) – Relative URI of the resource to delete.

  • co3_context_token (str) – The Co3ContextToken from an Action Module message, if available.

  • timeout (int) – Optional timeout (seconds).

Raises:

SimpleHTTPException – if an HTTP exception occurs.

get(uri, co3_context_token=None, timeout=None, is_uri_absolute=None, get_response_object=None, skip_retry=[])

Gets the specified URI.

Note

This URI is relative to <base_url>/rest/orgs/<org_id>. So for example, if you specify a uri of /incidents, the actual URL would be something like: https://soar.ibm.com/rest/orgs/201/incidents

Parameters:
  • uri (str) – Relative URI of the resource to fetch.

  • co3_context_token (str) – The Co3ContextToken from an Action Module message, if available.

  • timeout (int) – Optional timeout (seconds).

  • is_uri_absolute (bool) – if True, does not insert /org/{org_id} into the uri.

  • get_response_object (bool) – if True, returns entire response object.

Returns:

A dictionary, list, or response object with the value returned by the server.

Return type:

dict | list | Response

Raises:

SimpleHTTPException – if an HTTP exception occurs.

get_const(co3_context_token=None, timeout=None)

Get the ConstREST endpoint.

Endpoint for retrieving various constant information for this server. This information is useful in translating names that the user sees to IDs that other REST API endpoints accept.

For example, the incidentDTO has a field called "crimestatus_id". The valid values are stored in constDTO.crime_statuses.

Parameters:
  • co3_context_token (str) – The Co3ContextToken from an Action Module message, if available.

  • timeout (int) – Optional timeout (seconds).

Returns:

ConstDTO as a dictionary

Return type:

dict

Raises:

SimpleHTTPException – if an HTTP exception occurs.

get_content(uri, co3_context_token=None, timeout=None, skip_retry=[])

Gets the specified URI.

Note

This URI is relative to <base_url>/rest/orgs/<org_id>. So for example, if you specify a uri of /incidents, the actual URL would be something like: https://soar.ibm.com/rest/orgs/201/incidents

Parameters:
  • uri (str) – Relative URI of the resource to fetch.

  • co3_context_token (str) – The Co3ContextToken from an Action Module message, if available.

  • timeout (int) – Optional timeout (seconds).

Returns:

The raw value returned by the server for this resource.

Return type:

dict

Raises:

SimpleHTTPException – if an HTTP exception occurs.

get_put(uri, apply_func, co3_context_token=None, timeout=None)

Safely performs an update operation by a GET, calls your apply_func callback, then PUT with the updated value. If the put call returns a 409 error, these steps are retried.

Note

This URI is relative to <base_url>/rest/orgs/<org_id>. So for example, if you specify a uri of /incidents, the actual URL would be something like: https://soar.ibm.com/rest/orgs/201/incidents

Parameters:
  • uri (str) – Relative URI of the resource to get and update.

  • apply_func (func) – A callback function that you implement to update the resource. The function must be of the following form: def my_apply_func(object_to_update), and update the object. If your callback raises resilient.NoChange, the update is skipped.

  • co3_context_token (str) – The Co3ContextToken from an Action Module message, if available.

  • timeout (int) – Optional timeout (seconds).

Returns:

A dictionary or list with the value returned by the PUT operation.

Return type:

dict | list

Raises:

SimpleHTTPException – if an HTTP exception occurs.

patch(uri, patch, co3_context_token=None, timeout=None, overwrite_conflict=False)

PATCH request to the specified URI.

Note

This URI is relative to <base_url>/rest/orgs/<org_id>. So for example, if you specify a uri of /incidents, the actual URL would be something like: https://soar.ibm.com/rest/orgs/201/incidents

Parameters:
  • uri (str) – Relative URI of the resource to patch.

  • patch (Patch) – The Patch object to apply

  • co3_context_token (str) – The Co3ContextToken from an Action Module message, if available.

  • timeout (int) – Optional timeout (seconds).

  • overwrite_conflict (bool) – always overwrite fields in conflict. If True, the passed-in patch object will be modified if necessary.

Returns:

the response from the endpoint.

Return type:

requests.Response

Raises:
patch_with_callback(uri, patch, callback, co3_context_token=None, timeout=None)

PATCH request to the specified URI. If the patch application fails because of field conflicts, the specified callback is invoked, allowing the caller to adjust the patch as necessary.

Parameters:
  • uri – Relative URI of the resource to patch.

  • patch (Patch) – The Patch object to apply

  • callback (func) – Function/lambda to invoke when a patch conflict is detected. The function/lambda must be of the following form: def my_callback(response, patch_status, patch). If your callback raises resilient.NoChange, the update is skipped.

  • co3_context_token (str) – The Co3ContextToken from an Action Module message, if available.

  • timeout (int) – Optional timeout (seconds).

Returns:

the response from the endpoint.

Return type:

requests.Response

post(uri, payload, co3_context_token=None, timeout=None, headers=None, skip_retry=[], **kwargs)

Posts to the specified URI.

Note

This URI is relative to <base_url>/rest/orgs/<org_id>. So for example, if you specify a uri of /incidents, the actual URL would be something like: https://soar.ibm.com/rest/orgs/201/incidents

Parameters:
  • uri (str) – Relative URI of the resource to post.

  • payload (dict) – A dictionary value to be posted.

  • co3_context_token (str) – The Co3ContextToken from an Action Module message, if available.

  • timeout (int) – Optional timeout (seconds).

  • headers (dict) – Optional headers to include.

Returns:

A dictionary or list with the value returned by the server.

Return type:

dict | list

Raises:

SimpleHTTPException – if an HTTP exception occurs.

post_attachment(uri, filepath, filename=None, mimetype=None, data=None, co3_context_token=None, timeout=None, bytes_handle=None, skip_retry=[])

Upload a file to the specified URI e.g. /incidents/<id>/attachments (for incident attachments) or /tasks/<id>/attachments (for task attachments)

Warning

Please see our updated resilient_lib.write_file_attachment as this method takes a data stream and is more reliable

Parameters:
  • uri (str) – Relative URI of the resource to post.

  • filepath (str) – the path of the file to post

  • filename (str) – optional name of the file when posted

  • mimetype (str) – optional override for the guessed MIME type

  • data (dict) – optional dict with additional MIME parts (not required for file attachments; used in artifacts)

  • co3_context_token (str) – The Co3ContextToken from an Action Module message, if available.

  • timeout (int) – Optional timeout (seconds).

  • bytes_handle (BytesIO) – BytesIO handle for content or use filepath

Returns:

the response from the endpoint.

Return type:

requests.Response

put(uri, payload, co3_context_token=None, timeout=None, headers=None, skip_retry=[])

Directly performs an update operation by PUT to the specified URI.

Note

This URI is relative to <base_url>/rest/orgs/<org_id>. So for example, if you specify a uri of /incidents, the actual URL would be something like: https://soar.ibm.com/rest/orgs/201/incidents

Parameters:
  • uri (str) – Relative URI of the resource to update.

  • payload (dict) – The object to update.

  • co3_context_token (str) – The Co3ContextToken from an Action Module message, if available.

  • timeout (int) – Optional timeout (seconds).

  • headers (dict) – Optional headers to include.

Returns:

A dictionary or list with the value returned by the server.

Return type:

dict | list

Raises:

SimpleHTTPException – if an HTTP exception occurs.

search(payload, co3_context_token=None, timeout=None)

Posts to the SearchExREST endpoint.

Endpoint for performing full text searches through incidents and incident child objects (tasks, incident comments, task comments, milestones, artifacts, incident attachments, task attachments, and data tables).

Parameters:
  • payload (dict) – The SearchExInputDTO parameters for performing a search.

  • co3_context_token (str) – The Co3ContextToken from an Action Module message, if available.

  • timeout (int) – Optional timeout (seconds).

Returns:

List of results, as an array of SearchExResultDTO

Return type:

list

Raises:

SimpleHTTPException – if an HTTP exception occurs.

exception SimpleHTTPException(response)

Exception for HTTP errors.

exception PatchConflictException(response, patch_status)

Exception for patch conflicts.

exception NoChange

Exception that can be raised within a get/put handler or a patch callback to indicate ‘no change’ (which then just bypasses the update operation).

Change Log

2024-07: version 51.0.2.2 * Update dependency version of setuptools version to 70.3.x to address CVE-2024-6345

2024-07: version 51.0.2.1

  • All IBM SOAR Python libraries now only officially support Python 3.9, 3.11, and 3.12. To continue using SOAR libraries on earlier versions of Python, use v52.0.2.0.974

  • Fix for secret substitution when value starts with “^” but is not intended to be substituted

2024-05: version 51.0.2.0

  • Added official support for Python 3.12

2024-04: version 51.0.1.1

  • Updated jwcrypto dependency requirement to ~= 1.5.6 (for Python 3.9 and 3.11) to address CVE-2024-28102 Note that Python 3.6 and Python 2.7 are no longer receiving security updates and should be moved away from immediately. See previous release below for details on our support for Python 3.11

2024-02: version 51.0.1.0

  • All SOAR Python libraries now officially support Python 3.11

  • All SOAR Python libraries are now published in a docker container format on Quay.io. This is to better support our apps build process to include the latest SOAR libraries in the base image. This also allows us to better control the OS and Python dependencies that appear in the eventual app container. To take advantage of this new image in your app see the SDK Change Log. The new base image is hosted on quay.io. The default Python version is 3.11 and the image can be pulled manually with:

    $ docker pull quay.io/ibmresilient/soarapps-base-docker-image:latest # latest libraries with Python 3.11
    $ docker pull quay.io/ibmresilient/soarapps-base-docker-image:python-39 # latest libraries with Python 3.9
    
  • Updated jwcrypto dependency requirement to ~= 1.5.2 (for Python 3.9 and 3.11) to address CVE-2023-6681

  • Pinned jwcrypto to == 1.5.1 for Python 3.6 since 1.5.2 is no longer 3.6 compatible

2023-11: version 51.0.0.0

  • Changed the version of resilient (and all other SOAR Python libraries) to match the new v.r.m.f scheme that SOAR v51.0.0.0 introduced

2023-10: version 50.1

  • Improved options for skipping retry with certain exit codes received by REST methods in SimpleClient

  • resilient.RetryHTTPException now inherits from resilient.BasicHTTPException for improved error handling

  • Bug fix for resilient.app_config.AppConfigManager when using Jinja2 to render values from app.config. This fix is only applicable to Python 3 and cannot be fixed in Python 2

  • Improved obfuscation of potential secrets in logs

2023-08: version 50.0

  • Adding a deprecation warning for use of Email and Password for authentication. This is still supported but will become unsupported in the future. Any integration servers using email and password to authenticate should consider moving to API Keys as soon as possible

2023-07: version 49.1

  • Bug fix for protected secrets which ended in $}

2023-05: version 49.0

2023-05: version 48.2

  • Update version of requests-toolbelt to v1.0 to support urllib3 v2.0

2023-04: version 48.1

  • REST client updated to use include_permissions=false by default when authenticating to /rest/session endpoint. This will give improved performance for SOAR instances with large organizations.

2023-02: version 48.0

  • Updated project to use pyproject.toml and setup.cfg metadata files. Build backend continues to use setuptools. Instead of directly invoking setup.py to get a sdist or wheel, use build as a build frontend:

    pip install build
    python -m build
    

2022-12: version 47.1

2022-11: version 47.0

  • Added more general retry logic to our get, post and delete request methods. All of which can be configured by specifying any of the following parameters in the SimpleClient class

    • max_connection_retries - Number of attempts to retry when connecting to SOAR. Use -1 for unlimited retries. Defaults to -1.

    • request_max_retries - Max number of times to retry a request to SOAR before exiting. Defaults to 5.

    • request_retry_delay - Number of seconds to wait between retries. Defaults to 2.

    • request_retry_backoff - Multiplier applied to delay between retry attempts. Defaults to 2.

  • Now support Protected Secrets. If running on the Edge Gateway (formally App Host) and there are encrypted secrets in JSON Web Key format, in the /etc/secrets directory, we will use the jwe and jwk libraries in jwcrypto to decrypt the secret and make it available in your app

2022-08: version 46.0

2022-07: version 45.1

  • No major changes. Just bumping build number to coincide with other builds

2022-05: version 45.0

  • The org config can now specify any of the organization’s cloud_account, uuid or name

  • Removed the User-Agent header for all requests

  • Added a custom header for all requests that will include the current version of the library: Resilient-Module-Version: 45.0.0

  • The optional client_auth_cert and client_auth_key app.config parameters have been added to specify the respective paths to client side certificates and client side certificate private keys

2022-04: version 44.1

  • Better logging of an Unauthorized request with API Keys and exits with a code of 21

  • Added optional get_response_object argument to resilient.SimpleClient.get() that if True, returns entire response object

2022-02: version 44.0

  • Ensure tests/ is not included in packaged code

  • Added is_uri_absolute argument to resilient.SimpleClient.get() that if True, does not insert /org/{org_id} into the uri

  • Officially support Python 3.9

2022-01: version 43.1

  • Ability to globally check if unrecognized arguments are allowed

2021-11: version 43.0

2021-11: version 42.3

  • No major changes. Just bumping build number to coincide with other builds

2021-10: version 42.2

  • Bug fix for pip >= 21.3

2021-08: version 42.1

  • Bug fix removing pinned urllib3 dependency

2021-08: version 42.0

  • Added support for HTTP_PROXY, HTTPS_PROXY and NO_PROXY environmental variables. See the App Host Deployment Guide for details.

  • Add new User-Agent: soar-app-1.0 header for API calls to SOAR platform.

  • Bug fixes.

2021-06: version 41.1

  • No major changes. Just bumping build number to coincide with other builds

2021-05: version 41.0

  • No major changes. Just bumping build number to coincide with other builds

2021-03: version 40.2

  • Bug fix for to use setuptools_scm < 6.0.0 for Python 2.7 environments

2021-03: version 40.1

  • No major changes. Just bumping build number to coincide with other builds

2021-02: version 40.0

  • Bump minimum requests version to 2.25.0

2020-07-15: version 37.2

  • Bug fix for proxy in python 3.

2020-01-16: version 35.0.195

  • Moved ImportDefinition from resilient-circuits

  • Added –resilient-mock parameter

2019-08-02: version 33.0.189

  • Minor bug fixes.

2019-07-03: version 32.0.186

  • Fix for deprecated log warnings

  • Other minor bug fixes

2019-04-12: version 32.0.140

  • No major changes. Just bumping build number to coincide with other builds

2019-03-06: version 32.0.126

  • No major changes. Just bumping build number to coincide with other builds

2019-01-15: version 32.0

  • No major changes. Just bumping build number to coincide with other builds

2018-12-05: version 31.0

  • Bug Fixes

2018-04-15: version 30.0

  • Fix an issue with keyring values outside the [resilient] config section

2018-02-22: version 29.1.0

  • Fix an issue with performance receiving STOMP messages

2017-12-12: version 29.0.1

  • Fix an issue with backward compatibility between co3 and resilient package names

2017-12-01: version 29.0.0

  • Refactoring base class to support minimal environments

2017-09-01: version 28.2.1

  • rename co3 package to resilient

    Note

    note The module co3 is retained for backward compatibility, and most applications will still work using import co3 after this change. Applications that import from submodules (import co3.co3.xxx) must be changed to import from resilient instead.

2017-08-24: version 28.1.

  • add patch method to SimpleClient for efficient field-level updates

2017-06-22: version 28.0.33

  • disable the ConfigParser % interpolation feature

2017-06-14: version 28.0.30

  • Add get_const() to get the ConstREST endpoint

  • Add search() to post to the SearchExREST endpoint (only for v28+ servers)

    (Note: there is no method to call the deprecated searchREST endpoint from earlier versions)

  • Fix proxy support, adding config options: proxy_host, proxy_port, proxy_user, proxy_password

  • Remove stomp.py dependency, resilient_circuits now uses stompest library

  • New res-keyring command-line utility to store secrets in the keyring

  • Move the keyring and env argument parser from resilient_circuits into co3,

    so all config files can make use of ^xxx (keyring) and $xxx (environment) values

  • Add a dependency on keyring package

2017-04-27: version 27.1.22

2017-04-21: version 27.1.13

  • Remember the available orgs that the user can log in to

  • Add post_artifact_file method to support posting file (binary) artifacts

  • Add cached_get method and --cache-ttl commandline option

  • Add get_client helper function to properly construct a SimpleClient from options

  • For Debian OS, specify exact version of the keyring dependency

  • Use configuration file ($APP_CONFIG_FILE or ./app.config or ~/.resilient/app.config) for utility scripts

  • Move the utility scripts gadget and finfo into the co3 module, installed as executables

  • Add support for tests

2017-02-17: version 27.0.0

  • Support UTF8 strings in co3 module

  • Support UTF8 characters in configuration files

  • Add optional timeout parameter to REST calls

  • Add NoChange to optimize get/put

  • Fix post_attachment() to guess MIME-type based on the filename