You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
113 lines
3.6 KiB
113 lines
3.6 KiB
import os
|
|
import sys
|
|
import logging
|
|
from sys import platform
|
|
from urllib.parse import quote, unquote
|
|
|
|
APP = "splunk_app_soar"
|
|
|
|
CERT_FILE_LOCATION_DEFAULT = os.path.join(
|
|
os.environ["SPLUNK_HOME"], "etc", "apps", APP, "default", "cert_bundle.pem"
|
|
)
|
|
CERT_FILE_LOCATION_LOCAL = os.path.join(
|
|
os.environ["SPLUNK_HOME"], "etc", "apps", APP, "local", "cert_bundle.pem"
|
|
)
|
|
|
|
splunkhome = os.environ["SPLUNK_HOME"]
|
|
sys.path.append(os.path.join(splunkhome, "etc", "apps", APP, "bin"))
|
|
sys.path.append(os.path.join(splunkhome, "etc", "apps", APP, "lib"))
|
|
|
|
# needs to happen after
|
|
# required
|
|
# from soar_utils import setup_logging
|
|
|
|
if platform == "linux" or platform == "linux2":
|
|
sys.path.append(os.path.join(splunkhome, "etc", "apps", APP, "lib", "linux"))
|
|
elif platform == "darwin":
|
|
sys.path.append(os.path.join(splunkhome, "etc", "apps", APP, "lib", "mac"))
|
|
|
|
import splunk.entity as entity
|
|
import json
|
|
import requests
|
|
import aiohttp
|
|
import asyncio
|
|
|
|
from splunk.clilib import cli_common as cli
|
|
|
|
# logging:
|
|
# To avoid overriding logging destination of callers, the libs will not set on purpose any logging definition
|
|
# and rely on callers themselves
|
|
|
|
|
|
class SOARClient:
|
|
server_url = None
|
|
auth_token = None
|
|
verify = True
|
|
|
|
def __init__(self, server_url, auth_token):
|
|
self.server_url = server_url
|
|
self.auth_token = auth_token
|
|
self.fetch_verify_certs()
|
|
|
|
def fetch_verify_certs(self):
|
|
cfg = cli.getConfStanza("soar", "verify_certs")
|
|
value = cfg.get("value")
|
|
if value == "true" and os.path.isfile(CERT_FILE_LOCATION_LOCAL):
|
|
self.verify = CERT_FILE_LOCATION_LOCAL
|
|
elif value == "true" and os.path.isfile(CERT_FILE_LOCATION_DEFAULT):
|
|
self.verify = CERT_FILE_LOCATION_DEFAULT
|
|
else:
|
|
self.verify = False
|
|
|
|
def make_request(
|
|
self, endpoint, method, data, page=0, page_size=100, extra_params=None, **kwargs
|
|
):
|
|
if extra_params is None:
|
|
extra_params = {}
|
|
|
|
url = self.server_url + "/rest/" + endpoint
|
|
headers = {"Accept": "application/json", "ph-auth-token": self.auth_token}
|
|
params = {"page": page, "page_size": page_size}
|
|
|
|
# Merge extra_params into params, with extra_params taking precedence
|
|
params.update(extra_params)
|
|
|
|
if data and method == "POST":
|
|
return requests.request(
|
|
method=method,
|
|
url=url,
|
|
headers=headers,
|
|
verify=self.verify,
|
|
data=json.dumps(data),
|
|
params=params,
|
|
**kwargs,
|
|
)
|
|
else:
|
|
return requests.request(
|
|
method=method,
|
|
url=url,
|
|
headers=headers,
|
|
verify=self.verify,
|
|
params=params,
|
|
**kwargs,
|
|
)
|
|
|
|
async def read_url(self, session, url, record):
|
|
async with session.get(url) as resp:
|
|
res_json = await resp.json()
|
|
record["soar_response"] = res_json
|
|
return record
|
|
|
|
async def make_request_async(self, records, endpoint, method="GET", **kwargs):
|
|
tasks = []
|
|
|
|
headers = {"Accept": "application/json", "ph-auth-token": self.auth_token}
|
|
|
|
async with aiohttp.ClientSession(
|
|
headers=headers, connector=aiohttp.TCPConnector(ssl=False)
|
|
) as session:
|
|
for record in records:
|
|
url = self.server_url + "/rest/" + record["endpoint"]
|
|
tasks.append(asyncio.create_task(self.read_url(session, url, record)))
|
|
return await asyncio.gather(*tasks)
|