Skip to content

Commit

Permalink
Merge pull request #2 from SocketDev/doug/add-webhook-support
Browse files Browse the repository at this point in the history
Added support for webhooks and updated documentation
  • Loading branch information
dacoburn authored Dec 9, 2023
2 parents d435d2f + 1f3e0cc commit 4c92fbc
Show file tree
Hide file tree
Showing 6 changed files with 161 additions and 9 deletions.
63 changes: 62 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ This tool supports the following connectors:
- Google BigQuery
- Panther SIEM
- Elasticsearch
- WebHook

### Other SIEM Integrations

Expand Down Expand Up @@ -52,7 +53,14 @@ if __name__ == '__main__':

### CSV

The CSV Export function will output to a specified CSV file. Currently, it will overwrite the file if it already exists.
The CSV Export function will output to a specified CSV file. Currently, it will overwrite the file if it already exists.

Initializing Options:

| Option | Required | Default | Description |
|---------|----------|-------------|-----------------------------------------------------------------------------------------------------------------------------------------------------|
| file | True | None | The name of the file to write the CSV results out to |
| columns | False | All Columns | The names of the column headers and the order for the columns. Must match the property names for the issues. If not passed default columns are used |

```python
import os
Expand Down Expand Up @@ -87,6 +95,12 @@ The BigQuery connector will send data to the specified Table within BigQuery. Cu
2. In a terminal run `gcloud auth login`
3. In a terminal run `gcloud config set project $MY_PROJECT_ID`

Initializing Options:

| Option | Required | Default | Description |
|--------|----------|---------|----------------------------------------------------------------------------------|
| table | True | None | This is the table in the format of `dataset.table` that results will be added to |

```python
import os
from core.socket_reports import Reports
Expand Down Expand Up @@ -114,6 +128,14 @@ The Panther connector requires you to have an HTTP connector setup in the Panthe

Configuration can be found [here](panther/README.md)

Initializing Options:

| Option | Required | Default | Description |
|---------|----------|---------|-------------------------------------------------------------------------------------------------------|
| token | False | None | Token to use if you are using Bearer token. Default method if custom headers are not passed to `send` |
| url | True | None | Panther Webhook URL to POST data to |
| timeout | False | 10 | Timeout in seconds for requests |

```python
import os
from core.socket_reports import Reports
Expand Down Expand Up @@ -171,3 +193,42 @@ if __name__ == '__main__':
for issue in issue_data:
es.add_document(issue, elastic_index)
```

### WebHook
The WebHook integration is a simple wrapper for sending an HTTP(s) Request to the desired URL.

Initialize Options:

| Option | Required | Default | Description |
|--------------|----------|----------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------|
| url | True | None | URL for the WebHook |
| headers | False | `{'User-Agent': 'SocketPythonScript/0.0.1', "accept": "application/json", 'Content-Type': "application/json"}` | Default set of headers to use if not specified |
| auth_headers | False | None | Dictionary of auth headers to use to authenticate to the WebHook |
| params | False | None | Dictionary of query params to use if needed |
| timeout | False | 10 | Time in seconds to timeout out a request |

```python
import os
from core.socket_reports import Reports
from core.connectors.webhook import Webhook


if __name__ == '__main__':
socket_org = os.getenv("SOCKET_ORG") or exit(1)
api_key = os.getenv("SOCKET_API_KEY") or exit(1)
start_date = os.getenv("START_DATE") or exit(1)
reports = Reports(
org=socket_org,
api_key=api_key,
start_date=start_date
)
issue_data = reports.get_issues()
webhook_url = os.getenv("WEBHOOK_URL") or exit(1)
webhook_auth_headers = os.getenv("WEBHOOK_AUTH_HEADERS") or {
'Authorization': 'Bearer EXAMPLE'
}
webhook = Webhook(webhook_url)
for issue in issue_data:
issue_json = json.loads(str(issue))
webhook.send(issue_json)
```
Empty file added core/connectors/__init__.py
Empty file.
7 changes: 4 additions & 3 deletions core/connectors/panther.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ class Panther:
url: str
timeout: int

def __init__(self, token: str, url: str, timeout: int = 10):
def __init__(self, url: str, token: str = None, timeout: int = 10):
self.token = token
self.url = url
self.timeout = timeout
Expand All @@ -21,11 +21,12 @@ def do_request(

if headers is None:
headers = {
'Authorization': f"Bearer {self.token}",
'User-Agent': 'SocketPythonScript/0.0.1',
"accept": "application/json",
'Content-Type': "application/json"
}
if self.token is not None:
headers['Authorization'] = f"Bearer {self.token}"
response = requests.request(
method.upper(),
self.url,
Expand All @@ -41,7 +42,7 @@ def do_request(
result = response.text
return result

def send_to_webhook(self, payload: str, headers: dict = None):
def send(self, payload: str, headers: dict = None):
response = self.do_request(
method="POST",
payload=payload,
Expand Down
17 changes: 13 additions & 4 deletions core/connectors/socket_csv.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import json
import csv
from core.socket_reports.classes import IssueRecord
from core import columns as default_columns


class SocketCSV:
Expand All @@ -10,17 +11,25 @@ class SocketCSV:
def __init__(self, file: str, columns: list = None):
self.file = file
self.columns = columns
if self.columns is None:
self.columns = default_columns

def write_csv(self, data: list):
with open(self.file, 'w', newline='') as file:
writer = csv.writer(file)
writer.writerow(self.columns)
if self.columns is not None:
writer.writerow(self.columns)
for issue in data:
writer.writerow(self.create_row(issue))

def create_row(self, issue: IssueRecord) -> tuple:
row = ()
for column in self.columns:
value = getattr(issue, column)
row += (value,)
if self.columns is not None:
for column in self.columns:
value = getattr(issue, column)
row += (value,)
else:
data = json.loads(str(issue))
for value in data:
row += (value,)
return row
69 changes: 69 additions & 0 deletions core/connectors/webhook.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import json
import urllib.parse

import requests
import urllib


class Webhook:
headers: dict
method: str
params: dict
auth_headers: dict
timeout: int
url: str

def __init__(
self,
url: str,
headers: dict = None,
auth_headers: dict = None,
method: str = "POST",
params: dict = None,
timeout: int = 10
):
self.headers = headers
self.auth_headers = auth_headers
self.method = method
self.params = params
self.timeout = timeout
self.url = url

def send(self, payload: dict):
headers = self.get_headers()
url = self.create_url(self.url, self.params)
data = json.dumps(payload)
response = requests.request(
self.method.upper(),
url,
headers=headers,
data=data,
timeout=self.timeout
)
if response.status_code != 200:
print("Failed to post data")
print(response.text)
result = None
else:
result = response.text
return result

@staticmethod
def create_url(url: str, params: dict) -> str:
if params is not None:
query_params = urllib.parse.urlencode(params)
url = f"{url}?{query_params}"
return url

def get_headers(self):
headers = {
'User-Agent': 'SocketPythonScript/0.0.1',
"accept": "application/json",
'Content-Type': "application/json"
}
if self.headers is None and self.auth_headers is not None:
for name in self.auth_headers:
headers[name] = self.auth_headers[name]
elif self.headers is not None:
headers = self.headers
return headers
14 changes: 13 additions & 1 deletion socket-integration-example.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,13 @@
from core.connectors.bigquery import BigQuery
from core.connectors.panther import Panther
from core.connectors.socket_csv import SocketCSV
from core.connectors.webhook import Webhook


if __name__ == '__main__':
socket_org = os.getenv("SOCKET_ORG") or exit(1)
api_key = os.getenv("SOCKET_API_KEY") or exit(1)
start_date = os.getenv("START_DATE") or exit(1)
start_date = os.getenv("START_DATE") or None
reports = Reports(
org=socket_org,
api_key=api_key,
Expand Down Expand Up @@ -52,3 +53,14 @@
issue_json = json.loads(str(issue))
panther.send_to_webhook(str(issue))
print(f"Processed issue id: {issue.id}")

# Webhook Example
webhook_url = os.getenv("WEBHOOK_URL") or exit(1)
webhook_auth_headers = os.getenv("WEBHOOK_AUTH_HEADERS") or {
'Authorization': 'Bearer EXAMPLE'
}
webhook = Webhook(webhook_url)
for issue in issue_data:
issue_json = json.loads(str(issue))
webhook.send(issue_json)

0 comments on commit 4c92fbc

Please sign in to comment.