Skip to content

Commit

Permalink
Merge pull request #10 from splunk-soar-connectors/next
Browse files Browse the repository at this point in the history
Merging next to main for release 1.0.2
  • Loading branch information
phantom-jacob authored Jan 11, 2025
2 parents 53a9179 + b20ce88 commit 6cec6e9
Show file tree
Hide file tree
Showing 8 changed files with 66 additions and 27 deletions.
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@
same "printed page" as the copyright notice for easier
identification within third-party archives.

Copyright (c) 2024 Splunk Inc.
Copyright (c) 2025 Splunk Inc.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,16 @@
# Cisco Talos Intelligence

Publisher: Splunk
Connector Version: 1.0.1
Connector Version: 1.0.2
Product Vendor: Cisco
Product Name: Talos Intelligence
Product Version Supported (regex): ".\*"
Minimum Product Version: 6.3.0

This app provides investigative actions for Cisco Talos Intelligence
This app provides investigative actions for Cisco Talos Intelligence. It is only supported on Splunk SOAR Cloud

[comment]: # " File: README.md"
[comment]: # "Copyright (c) 2024 Splunk Inc."
[comment]: # "Copyright (c) 2025 Splunk Inc."
[comment]: # ""
[comment]: # "Licensed under the Apache License, Version 2.0 (the 'License');"
[comment]: # "you may not use this file except in compliance with the License."
Expand Down
2 changes: 1 addition & 1 deletion __init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# File: __init__.py
#
# Copyright (c) 2024 Splunk Inc.
# Copyright (c) 2025 Splunk Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
Expand Down
10 changes: 5 additions & 5 deletions ciscotalosintelligence.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"appid": "7c653487-22c8-4ec1-bca0-16a8b1513c86",
"name": "Cisco Talos Intelligence",
"description": "This app provides investigative actions for Cisco Talos Intelligence",
"description": "This app provides investigative actions for Cisco Talos Intelligence. It is only supported on Splunk SOAR Cloud",
"type": "information",
"product_vendor": "Cisco",
"logo": "ciscotalosintelligence.svg",
Expand All @@ -13,9 +13,9 @@
],
"product_version_regex": ".*",
"publisher": "Splunk",
"license": "Copyright (c) 2024 Splunk Inc.",
"app_version": "1.0.1",
"utctime_updated": "2024-06-21T18:40:03.685771Z",
"license": "Copyright (c) 2025 Splunk Inc.",
"app_version": "1.0.2",
"utctime_updated": "2025-01-11T00:12:29.000000Z",
"package_name": "phantom_ciscotalosintelligence",
"fips_compliant": false,
"main_module": "ciscotalosintelligence_connector.py",
Expand Down Expand Up @@ -403,4 +403,4 @@
"executable": "spawn3",
"disabled": false,
"custom_made": true
}
}
68 changes: 53 additions & 15 deletions ciscotalosintelligence_connector.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# File: ciscotalosintelligence_connector.py
#
# Copyright (c) 2024 Splunk Inc.
# Copyright (c) 2025 Splunk Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -47,7 +47,6 @@ def __new__(cls, val1, val2=None):


class TalosIntelligenceConnector(BaseConnector):

def __init__(self):
super(TalosIntelligenceConnector, self).__init__()

Expand All @@ -64,7 +63,10 @@ def _process_empty_response(self, response, action_result):
if response.status_code == 200:
return RetVal(phantom.APP_SUCCESS, {})

return RetVal(action_result.set_status(phantom.APP_ERROR, "Empty response and no information in the header"), None)
return RetVal(
action_result.set_status(phantom.APP_ERROR, "Empty response and no information in the header"),
None,
)

def _process_html_response(self, response, action_result):
# An html response, treat it like an error
Expand All @@ -89,7 +91,13 @@ def _process_json_response(self, r, action_result):
try:
resp_json = r.json()
except Exception as e:
return RetVal(action_result.set_status(phantom.APP_ERROR, "Unable to parse JSON response. Error: {0}".format(str(e))), None)
return RetVal(
action_result.set_status(
phantom.APP_ERROR,
"Unable to parse JSON response. Error: {0}".format(str(e)),
),
None,
)

# Please specify the status codes here
if 200 <= r.status_code < 399:
Expand All @@ -114,13 +122,20 @@ def _process_response(self, r, action_result, retry=3):
err_msg = r.headers.get("grpc-message", "Error")
return (
action_result.set_status(
phantom.APP_ERROR, f"Got retryable grpc-status of {r.headers['grpc-status']} with message {err_msg}"
phantom.APP_ERROR,
f"Got retryable grpc-status of {r.headers['grpc-status']} with message {err_msg}",
),
r,
)

if r.status_code == 503:
return action_result.set_status(phantom.APP_ERROR, "Got retryable http status code {0}".format(r.status_code)), r
return (
action_result.set_status(
phantom.APP_ERROR,
"Got retryable http status code {0}".format(r.status_code),
),
r,
)

# Process each 'Content-Type' of response separately

Expand Down Expand Up @@ -171,20 +186,32 @@ def _make_rest_call(self, retry, endpoint, action_result, method="get", **kwargs

with tempfile.NamedTemporaryFile(mode="w+", delete=False, suffix="test") as temp_file:
cert_string = f"-----BEGIN CERTIFICATE-----\n{self._cert}\n-----END CERTIFICATE-----"
cert = f"{cert_string}\n-----BEGIN RSA PRIVATE KEY-----\n{self._key}\n-----END RSA PRIVATE KEY-----\n"
cert = (
f"{cert_string}\n"
"-----BEGIN RSA PRIVATE KEY-----\n" # pragma: allowlist secret
f"{self._key}\n"
"-----END RSA PRIVATE KEY-----\n" # pragma: allowlist secret
)
temp_file.write(cert)
temp_file.seek(0) # Move the file pointer to the beginning for reading
temp_file_path = temp_file.name # Get the name of the temporary file
self.client = httpx.Client(
http2=True, verify=config.get("verify_server_cert", False), cert=temp_file_path, timeout=MAX_REQUEST_TIMEOUT
http2=True,
verify=config.get("verify_server_cert", False),
cert=temp_file_path,
timeout=MAX_REQUEST_TIMEOUT,
)

if os.path.exists(temp_file_path):
os.remove(temp_file_path)

if i == MAX_CONNECTION_RETIRIES - 1:
return RetVal(
action_result.set_status(phantom.APP_ERROR, "Error Connecting to server. Details: {0}".format(str(e))), resp_json
action_result.set_status(
phantom.APP_ERROR,
"Error Connecting to server. Details: {0}".format(str(e)),
),
resp_json,
)

return self._process_response(r, action_result, retry)
Expand All @@ -195,7 +222,13 @@ def _make_rest_call_helper(self, *args, **kwargs):
for i in range(MAX_REQUEST_RETRIES + 1):
if time.time() > max_processing_time:
action_result = args[1]
return action_result.set_status(phantom.APP_ERROR, f"Max request timeout of {MAX_REQUEST_TIMEOUT}s exceeded"), None
return (
action_result.set_status(
phantom.APP_ERROR,
f"Max request timeout of {MAX_REQUEST_TIMEOUT}s exceeded",
),
None,
)

ret_val, response = self._make_rest_call(i, *args, **kwargs)
if phantom.is_fail(ret_val) and response:
Expand Down Expand Up @@ -313,7 +346,6 @@ def _handle_url_reputation(self, param):
return action_result.set_status(phantom.APP_SUCCESS)

def _query_reputation(self, action_result, payload, observable=None):

taxonomy_ret_val, taxonomy = self._fetch_taxonomy(action_result)

if phantom.is_fail(taxonomy_ret_val):
Expand Down Expand Up @@ -368,7 +400,6 @@ def _query_reputation(self, action_result, payload, observable=None):
return phantom.APP_SUCCESS

def _fetch_taxonomy(self, action_result, allow_cache=True):

payload = {"app_info": self._appinfo}

if "taxonomy" in self._state and allow_cache:
Expand Down Expand Up @@ -473,7 +504,12 @@ def insert_newlines(string, every=64):
self._appinfo["perf_testing"] = True

with tempfile.NamedTemporaryFile(mode="w+", delete=False, suffix="test") as temp_file:
cert = f"{cert_string}\n-----BEGIN RSA PRIVATE KEY-----\n{textwrap.fill(self._key, 64)}\n-----END RSA PRIVATE KEY-----\n"
cert = (
f"{cert_string}\n"
"-----BEGIN RSA PRIVATE KEY-----\n" # pragma: allowlist secret
f"{textwrap.fill(self._key, 64)}\n"
"-----END RSA PRIVATE KEY-----\n" # pragma: allowlist secret
)

temp_file.write(cert)
temp_file.seek(0) # Move the file pointer to the beginning for reading
Expand All @@ -482,7 +518,10 @@ def insert_newlines(string, every=64):
# exceptions shouldn't really be thrown here because most network related disconnections will happen when a request is sent
try:
self.client = httpx.Client(
http2=True, verify=config.get("verify_server_cert", False), cert=temp_file_path, timeout=MAX_REQUEST_TIMEOUT
http2=True,
verify=config.get("verify_server_cert", False),
cert=temp_file_path,
timeout=MAX_REQUEST_TIMEOUT,
)
except Exception as e:
self.debug_print(f"Could not connect to server because of {e}")
Expand Down Expand Up @@ -515,7 +554,6 @@ def main():
password = args.password

if username is not None and password is None:

# User specified a username but not a password, so ask
import getpass

Expand Down
2 changes: 1 addition & 1 deletion ciscotalosintelligence_consts.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# File: ciscotalosintelligence_consts.py
#
# Copyright (c) 2024 Splunk Inc.
# Copyright (c) 2025 Splunk Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
Expand Down
2 changes: 1 addition & 1 deletion manual_readme_content.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[comment]: # " File: README.md"
[comment]: # "Copyright (c) 2024 Splunk Inc."
[comment]: # "Copyright (c) 2025 Splunk Inc."
[comment]: # ""
[comment]: # "Licensed under the Apache License, Version 2.0 (the 'License');"
[comment]: # "you may not use this file except in compliance with the License."
Expand Down
1 change: 1 addition & 0 deletions release_notes/1.0.2.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
* Add documentation indicating that this app is only supported for SOAR Cloud.

0 comments on commit 6cec6e9

Please sign in to comment.