Participants
This scenario involves a software developer (Developer A) and an end user (User A). Developer A wants to implement a new connector for the STIX-shifter project that can support a particular security product (Product A). User A is another developer that uses the STIX-shifter library.
Problem to solve
User A performs security monitoring with Product A and several other security products. The other products already have existing STIX-shifter connectors.
User A would like to:
- Submit one STIX pattern to query all the user’s security products at once. The use of a STIX pattern simplifies the search process because User A does not need to know the query language or API calls for each security product.
- See the query results from all the security products in one unified format (STIX bundle). With the assumption that the submitted pattern represents a potential security incident, the STIX bundle presents the query results in the context of the security event.
By implementing a new connector, Developer A allows Product A to fit into the workflow.
- Your development environment must use Python 3.8 or greater.
- You must have access to the target data source. In the sample scenario, you must have access to Product A data source.
- You must be familiar with Product A's query language and APIs.
- You must be familiar or understand the following concepts:
- Observable objects. See STIX™ Version 2.0. Part 4: Cyber Observable Objects
- Stix patterning. See STIX™ Version 2.0. Part 5: STIX Patterning
Familiarize yourself with some best practices before beginning a new connector.
To develop a STIX-shifter connector for a data source:
- Fork the
opencybersecurityalliance/stix-shifter
repository from https://github.com/opencybersecurityalliance/stix-shifter to work on your own copy of the library. - Create a module folder.
- Create a Translation module.
- Create a Transmission module.
- Create Configuration JSONs.
- Create the module entry points.
- Create a pull request to merge your changes in the
opencybersecurityalliance/stix-shifter
repository.
Connector modules are stored under the stix_shifter_modules
directory. To help you get started with creating a new connector, two module templates are available. If your data source executes queries synchronously (there is no API call to check the status of the query), make a copy of the synchronous_template
folder in the stix_shifter_modules
directory. If your data source executes queries asynchronously, make a copy of the async_template
folder. The instructions that follow use the async template as an example.
Rename the copied folder to match the data source your new connector is being developed for. For example, abc_security_monitor
.
The module name is used as an argument when either translation or transmission is called. This argument is used throughout the project so that STIX-shifter knows which modules to use.
Each module contains the following directories and files:
stix_translation: Directory containing files needed for STIX translation.
stix_transmission: Directory containing files for executing API calls to run data source queries.
configuration: Directory containing configuration files.
entry_point.py: Initializes classes and paths used by the connector.
The EntryPoint
class acts as a gateway to the various methods used by the translation and transmission classes. In most instances, it's fine to use the setup_transmission_simple
and setup_translation_simple(dialect_default='default')
methods. In cases where multiple dialects are used by the connector, the dialect_default
argument is the dialect you wish to use as the default when the entire collection isn't passed in. See Create a Translation module to learn about dialects.
If the data source is synchronous, you must include set_async(False)
in the connector's entry point initialization, otherwise the data source will be treated as asynchronous by default. Even though a synchronous connector omits the query_connector.py
and status_connector.py
files from its transmission directory, those connectors are still called in every module's entry point. For synchronous data sources, those connectors call the BaseSyncConnector()
methods which return {"success": True, "status": "COMPLETED", "progress": 100}
.
class EntryPoint(EntryPointBase):
def __init__(self, connection={}, configuration={}, options={}):
super().__init__(connection, configuration, options)
self.set_async(False)
if connection:
api_client = APIClient(connection, configuration)
base_sync_connector = BaseSyncConnector()
ping_connector = PingConnector(api_client)
query_connector = base_sync_connector
status_connector = base_sync_connector
...
self.set_query_connector(query_connector)
self.set_ping_connector(ping_connector)
self.set_status_connector(status_connector)
self.set_delete_connector(delete_connector)
self.set_results_connector(results_connector)
else:
...
Work on a new stix-shifter connector occurs after the project has been forked and cloned into a local development environment. Stix-shifter contains a proxy connector that facilitates a remote instance of the project calling out to a local instance. While in development, a new connector's working branch can be tested in any project using the stix-shifter library without first merging into the master branch on Github. A host is run on the local instance from the CLI. When a proxy
data source is passed to the remote instance of stix-shifter, the real connection attributes (data source type, host, and port contained in the options) are passed onto the local instance of stix-shifter running the proxy host. The host will then use the new connector and return results back to the remote stix-shifter instance.
Open a terminal and navigate to your local stix-shifter directory. Run the host with the following command:
python main.py host "<STIX Identity Object>" "<Host IP address>:<Host Port>"
As an example:
python main.py host '{"type": "identity","id": "identity--f431f809-377b-45e0-aa1c-6a4751cae5ff","name": "Bundle","identity_class": "events"}' "192.168.122.83:5000"
Each of the translate and transmit CLI commands outlined in the stix-shifter overview can be used to call the proxy host.
As an example:
python main.py transmit proxy '{"options": {"proxy_host": "127.0.0.1", "proxy_port": 5000, "destination": {"connection": {"options": {"result_limit": 10000, "time_range": 5, "timeout": 30}, "host": "<HOST>", "port": <PORT>, "type": "qradar"}, "configuration": {"auth": { "SEC": "<SEC TOKEN>"} } } }}' '{}' ping
Stix-shifter can be broken into several python whl packages by using the setup.py
script found in the root of the project. This packaging script can be called from the CLI:
MODE='<module name>' VERSION='<connector version>' python3 setup.py bdist_wheel
MODE
is a required argument that is used to determine how the project is packaged. Mode options include:
'1'
= Include everything in one whl package
'3'
- 3 whl packages respectively for stix-shifter, stix-shifter-utils and stix-shifter-modules
'N'
- stix-shifter
, stix-shifter-utils
, and each connector is packaged separately
<module name>
- package only the specified connector
The VERSION
argument is optional. If missing, version 1.0.0 is attached to the package name.
When the script is executed, a new dist
directory is created at the root of the stix-shifter project; this contains the generated whl packages.
A packaged connector follows the naming convention of:
stix_shifter_modules_<module name>-<version>-py2.py3-none-any.whl
The contents of the package has the same directory structure as the module in the project:
stix_shifter_modules =>
<module name> =>
configuration
stix_translation
stix_transmission
entry_point
You can build the docker image your developed connector locally and publish it to your desired repository. In order to do that, follow the below steps-
- Make sure you have built the wheel distribution of the connector module by following the steps in Packaging individual connectors section.
image_builder
directory in your stix-shifter project contains the required scripts that will automatically build the connector image. You can copy the directory in a separate location or keep it inside stix-shifter project.- Create a folder named
bundle
insideimage_builder/
directory. - Move your desired connector wheel file (
stix_shifter_modules_<module name>-<version>-py2.py3-none-any.whl
) to the bundle folder created in step 3. - Run
build_local.sh
script. - Image should be automatically built in your running docker client.