Skip to content

Commit

Permalink
Merge pull request #9 from splunk-soar-connectors/sodle/CloudDocs
Browse files Browse the repository at this point in the history
Add documentation indicating that this app is only supported for SOAR Cloud
  • Loading branch information
phantom-jacob authored Jan 11, 2025
2 parents 0cbd0b8 + a80b45e commit e5e1827
Show file tree
Hide file tree
Showing 8 changed files with 64 additions and 24 deletions.
4 changes: 2 additions & 2 deletions 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 All @@ -198,4 +198,4 @@
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
limitations under the License.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@ 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) 5 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
4 changes: 2 additions & 2 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,7 +13,7 @@
],
"product_version_regex": ".*",
"publisher": "Splunk",
"license": "Copyright (c) 2024 Splunk Inc.",
"license": "Copyright (c) 2025 Splunk Inc.",
"app_version": "1.0.1",
"utctime_updated": "2024-06-21T18:40:03.685771Z",
"package_name": "phantom_ciscotalosintelligence",
Expand Down
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
2 changes: 2 additions & 0 deletions release_notes/unreleased.md
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
**Unreleased**

* Add documentation indicating that this app is only supported for SOAR Cloud.

0 comments on commit e5e1827

Please sign in to comment.