Skip to content

Commit

Permalink
[IPSum ] Add connector (#3002)
Browse files Browse the repository at this point in the history
  • Loading branch information
baptiste-fourmont authored Jan 13, 2025
1 parent e4aed8a commit 6ca3414
Show file tree
Hide file tree
Showing 14 changed files with 779 additions and 0 deletions.
12 changes: 12 additions & 0 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -550,6 +550,8 @@ jobs:
docker push opencti/connector-attribution-tools:${CIRCLE_TAG}
docker push opencti/connector-tenable-security-center:latest
docker push opencti/connector-tenable-security-center:${CIRCLE_TAG}
docker push opencti/connector-ipsum:latest
docker push opencti/connector-ipsum:${CIRCLE_TAG}
- slack/notify:
event: fail
template: basic_fail_1
Expand Down Expand Up @@ -1456,6 +1458,10 @@ jobs:
working_directory: ~/opencti/external-import/tenable-security-center
name: Build Docker image opencti/connector-tenable-security-center
command: docker build -t opencti/connector-tenable-security-center:rolling .
- run:
working_directory: ~/opencti/external-import/ipsum
name: Build Docker image opencti/connector-ipsum
command: docker build -t opencti/connector-ipsum:rolling .
- run:
name: Publish Docker Image to Docker Hub
command: |
Expand Down Expand Up @@ -1535,6 +1541,7 @@ jobs:
docker push opencti/connector-tenable-vuln-management:rolling
docker push opencti/connector-attribution-tools:rolling
docker push opencti/connector-tenable-security-center:rolling
docker push opencti/connector-ipsum:rolling
- slack/notify:
event: fail
template: basic_fail_1
Expand Down Expand Up @@ -1673,6 +1680,10 @@ jobs:
working_directory: ~/opencti/external-import/intel471
name: Build Docker image opencti/connector-intel471
command: docker build -t opencti/connector-intel471:rolling .
- run:
working_directory: ~/opencti/external-import/ipsum
name: Build Docker image opencti/connector-ipsum
command: docker build -t opencti/connector-ipsum:rolling .
- run:
working_directory: ~/opencti/external-import/orange-cyberdefense
name: Build Docker image opencti/connector-orange-cyberdefense
Expand Down Expand Up @@ -1897,6 +1908,7 @@ jobs:
docker push opencti/connector-qradar:rolling
docker push opencti/connector-stream-exporter:rolling
docker push opencti/connector-stream-importer:rolling
docker push opencti/connector-ipsum:rolling
- slack/notify:
event: fail
template: basic_fail_1
Expand Down
5 changes: 5 additions & 0 deletions external-import/ipsum/.dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
src/config.yml
src/__pycache__
src/logs
src/*.gql
src/.venv
19 changes: 19 additions & 0 deletions external-import/ipsum/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
FROM python:3.12-alpine
ENV CONNECTOR_TYPE=EXTERNAL_IMPORT

# Copy the connector
COPY src /opt/opencti-connector-ipsum

# Install Python modules
# hadolint ignore=DL3003
RUN apk update && apk upgrade && \
apk --no-cache add git build-base libmagic libffi-dev libxml2-dev libxslt-dev

RUN cd /opt/opencti-connector-ipsum && \
pip3 install --no-cache-dir -r requirements.txt && \
apk del git build-base

# Expose and entrypoint
COPY entrypoint.sh /
RUN chmod +x /entrypoint.sh
ENTRYPOINT ["/entrypoint.sh"]
153 changes: 153 additions & 0 deletions external-import/ipsum/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
# OpenCTI External Ingestion Connector IPSUM

<!--
General description of the connector
* What it does
* How it works
* Special requirements
* Use case description
* ...
-->

Table of Contents

- [OpenCTI External Ingestion Connector IPSUM](#opencti-external-ingestion-connector-ipsum)
- [Introduction](#introduction)
- [Installation](#installation)
- [Requirements](#requirements)
- [Configuration variables](#configuration-variables)
- [OpenCTI environment variables](#opencti-environment-variables)
- [Base connector environment variables](#base-connector-environment-variables)
- [Connector extra parameters environment variables](#connector-extra-parameters-environment-variables)
- [Deployment](#deployment)
- [Docker Deployment](#docker-deployment)
- [Manual Deployment](#manual-deployment)
- [Usage](#usage)
- [Behavior](#behavior)
- [Debugging](#debugging)
- [Additional information](#additional-information)

## Introduction

## Installation

### Requirements

- OpenCTI Platform >= 6...

## Configuration variables

There are a number of configuration options, which are set either in `docker-compose.yml` (for Docker) or
in `config.yml` (for manual deployment).

### OpenCTI environment variables

Below are the parameters you'll need to set for OpenCTI:

| Parameter | config.yml | Docker environment variable | Mandatory | Description |
|---------------|------------|-----------------------------|-----------|------------------------------------------------------|
| OpenCTI URL | url | `OPENCTI_URL` | Yes | The URL of the OpenCTI platform. |
| OpenCTI Token | token | `OPENCTI_TOKEN` | Yes | The default admin token set in the OpenCTI platform. |

### Base connector environment variables

Below are the parameters you'll need to set for running the connector properly:

| Parameter | config.yml | Docker environment variable | Default | Mandatory | Description |
|-----------------|------------|-----------------------------|-----------------|-----------|------------------------------------------------------------------------------------------|
| Connector ID | id | `CONNECTOR_ID` | / | Yes | A unique `UUIDv4` identifier for this connector instance. |
| Connector Type | type | `CONNECTOR_TYPE` | EXTERNAL_IMPORT | Yes | Should always be set to `EXTERNAL_IMPORT` for this connector. |
| Connector Name | name | `CONNECTOR_NAME` | | Yes | Name of the connector. |
| Connector Scope | scope | `CONNECTOR_SCOPE` | ipsum | Yes | The scope or type of data the connector is importing, either a MIME type or Stix Object. |
| Log Level | log_level | `CONNECTOR_LOG_LEVEL` | error | Yes | Determines the verbosity of the logs. Options are `debug`, `info`, `warn`, or `error`. |

### Connector extra parameters environment variables

Below are the parameters you'll need to set for the connector:

| Parameter | config.yml | Docker environment variable | Default | Mandatory | Description |
|--------------|--------------|-----------------------------|---------|-----------|-------------|
| API base URL | api_base_url | `CONNECTOR_IPSUM_API_BASE_URL` | `https://raw.githubusercontent.com/stamparm/ipsum/refs/heads/master/levels/5.txt` | Yes | You can choose between level 1 to level 8. 1 can have a lot of false positives, 8 has no false positive (Example: https://raw.githubusercontent.com/stamparm/ipsum/refs/heads/master/levels/8.txt - No false positive ) |
| API key | api_key | `CONNECTOR_IPSUM_API_KEY` | | No | Github API Key |
| Score | default_x_opencti_score | `CONNECTOR_IPSUM_DEFAULT_X_OPENCTI_SCORE` | 60 | No | |

## Deployment

### Docker Deployment

Before building the Docker container, you need to set the version of pycti in `requirements.txt` equal to whatever
version of OpenCTI you're running. Example, `pycti==5.12.20`. If you don't, it will take the latest version, but
sometimes the OpenCTI SDK fails to initialize.

Build a Docker Image using the provided `Dockerfile`.

Example:

```shell
# Replace the IMAGE NAME with the appropriate value
docker build . -t [IMAGE NAME]:latest
```

Make sure to replace the environment variables in `docker-compose.yml` with the appropriate configurations for your
environment. Then, start the docker container with the provided docker-compose.yml

```shell
docker compose up -d
# -d for detached
```

### Manual Deployment

Create a file `config.yml` based on the provided `config.yml.sample`.

Replace the configuration variables (especially the "**ChangeMe**" variables) with the appropriate configurations for
you environment.

Install the required python dependencies (preferably in a virtual environment):

```shell
pip3 install -r requirements.txt
```

Then, start the connector from recorded-future/src:

```shell
python3 main.py
```

## Usage

After Installation, the connector should require minimal interaction to use, and should update automatically at a regular interval specified in your `docker-compose.yml` or `config.yml` in `duration_period`.

However, if you would like to force an immediate download of a new batch of entities, navigate to:

`Data management` -> `Ingestion` -> `Connectors` in the OpenCTI platform.

Find the connector, and click on the refresh button to reset the connector's state and force a new
download of data by re-running the connector.

## Behavior

<!--
Describe how the connector functions:
* What data is ingested, updated, or modified
* Important considerations for users when utilizing this connector
* Additional relevant details
-->

## Debugging

The connector can be debugged by setting the appropiate log level.
Note that logging messages can be added using `self.helper.connector_logger,{LOG_LEVEL}("Sample message")`, i.
e., `self.helper.connector_logger.error("An error message")`.

<!-- Any additional information to help future users debug and report detailed issues concerning this connector -->

## Additional information

<!--
Any additional information about this connector
* What information is ingested/updated/changed
* What should the user take into account when using this connector
* ...
-->
37 changes: 37 additions & 0 deletions external-import/ipsum/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
version: '3'
services:
connector-ipsum:
image: opencti/connector-ipsum:6.2.4
environment:
# Connector's generic execution parameters
- OPENCTI_URL=http://localhost
- OPENCTI_TOKEN=CHANGEME
# Connector's definition parameters REQUIRED
- CONNECTOR_ID=CHANGEME
- CONNECTOR_NAME=IPsum
- CONNECTOR_SCOPE=ipsum
- CONNECTOR_LOG_LEVEL=error
- CONNECTOR_DURATION_PERIOD=PT6H # ISO8601 format in String, start with 'P...' for Period

# Connector's definition parameters OPTIONAL
# - CONNECTOR_QUEUE_THRESHOLD=500 # Default 500Mo, Float accepted
# - CONNECTOR_RUN_AND_TERMINATE=False # Default False, True run connector once
# - CONNECTOR_SEND_TO_QUEUE=True # Default True
# - CONNECTOR_SEND_TO_DIRECTORY=False # Default False
# - CONNECTOR_SEND_TO_DIRECTORY_PATH=CHANGEME # if CONNECTOR_SEND_TO_DIRECTORY is True, you must specify a path
# - CONNECTOR_SEND_TO_DIRECTORY_RETENTION=7 # Default 7, in days

# Connector's custom execution parameters
- CONNECTOR_IPSUM_API_BASE_URL=https://raw.githubusercontent.com/stamparm/ipsum/refs/heads/master/levels/5.txt
- CONNECTOR_IPSUM_API_KEY=""
- CONNECTOR_IPSUM_DEFAULT_X_OPENCTI_SCORE=60

# Add proxy parameters below if needed
# - HTTP_PROXY=CHANGEME
# - HTTPS_PROXY=CHANGEME
# - NO_PROXY=CHANGEME
restart: always
networks:
default:
external: true
name: docker_default
7 changes: 7 additions & 0 deletions external-import/ipsum/entrypoint.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#!/bin/sh

# Go to the right directory
cd /opt/opencti-connector-ipsum

# Launch the worker
python3 main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from .connector import ConnectorIPSUM

__all__ = ["ConnectorIPSUM"]
72 changes: 72 additions & 0 deletions external-import/ipsum/src/external_import_connector/client_api.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import requests

from .utils import (
is_cidr,
is_full_network,
is_private_cidr,
is_private_ip,
networkcidr_to_list,
)


class ConnectorClient:
def __init__(self, helper, config):
"""
Initialize the client with necessary configurations
"""
self.helper = helper
self.config = config

headers = {"Bearer": self.config.api_key}
self.session = requests.Session()
if self.config.api_key and self.config.api_key != "":
self.session.headers.update(headers)

def _request_data(self, api_url: str, params=None):
"""
Internal method to handle API requests
:return: Response in JSON format
"""
try:
response = self.session.get(api_url, params=params)

self.helper.connector_logger.info(
"[API] HTTP Get Request to endpoint", {"url_path": api_url}
)

response.raise_for_status()
if response.ok:
return response
return None

except requests.RequestException as err:
error_msg = "[API] Error while fetching data: "
self.helper.connector_logger.error(
error_msg, {"url_path": {api_url}, "error": {str(err)}}
)
return None

def get_entities(self, params=None) -> list:
"""
If params is None, retrieve all IPs in the Github Repository
:param params: Optional Params to filter what list to return
:return: A list of IPs
"""
ips = []
try:
response = self._request_data(self.config.api_base_url, params=params)
if response is not None:
for line in response.text.splitlines():
if not line.startswith("#"):
ip = line.strip()
if is_cidr(ip):
if is_full_network(ip) or is_private_cidr(ip):
continue
network_ips = networkcidr_to_list(ip)
ips.extend(network_ips)
else:
if not is_private_ip(ip):
ips.append(ip)
return ips
except Exception as err:
self.helper.connector_logger.error(err)
Loading

0 comments on commit 6ca3414

Please sign in to comment.