Hi Everyone,
The issue with the code below appears to be with the values of the {report_id} variable not being passed correctly to the download_report function, in particular this line:
url = f"https://example_url/{report_id}/download"
If I hardcode the url with a valid token, instead of the {report_id} variable, the report gets downloaded, as expected.
Any help would be much appreciated !
Full code below:
import requests
def collect_events(helper, ew):
"""
Main function to authenticate, generate report ID, and download the report.
"""
username = helper.get_arg('username')
password = helper.get_arg('password')
auth_url = "https://example_url/auth"
headers = {
'Content-Type': 'application/x-www-form-urlencoded',
}
data = {
'username': username,
'password': password,
'token': 'true',
'permissions': 'true',
}
try:
# Step 1: Authenticate to get the JWT token
auth_response = requests.post(auth_url, headers=headers, data=data)
if auth_response.status_code == 201:
jwt_token = auth_response.text.strip() # Extract and clean the token
if jwt_token:
# Log and create an event for the JWT token
event = helper.new_event(
data=f"JWT Token: {jwt_token}"
)
ew.write_event(event)
# Step 2: Generate the report ID
report_id = generate_report_id(jwt_token, helper)
if report_id:
# Log and create an event for the report ID
event = helper.new_event(
data=f"Report ID: {report_id}"
)
ew.write_event(event)
# Step 3: Download the report
file_path = download_report(jwt_token, report_id, helper)
if file_path:
helper.log_info(f"Report successfully downloaded to: {file_path}")
else:
raise ValueError("Failed to download the report.")
else:
raise ValueError("Failed to generate report ID.")
else:
raise ValueError("JWT token not found in response.")
else:
raise ValueError(f"Failed to get JWT: {auth_response.status_code}, {auth_response.text}")
except Exception as e:
helper.log_error(f"Error in collect_events: {e}")
def generate_report_id(jwt_token, helper):
url = "https://example_url"
headers = {
"accept": "application/json",
"Authorization": f"Bearer {jwt_token}"
}
params = {
"havingQuery": "isSecurity: true",
"platform": "Windows"
}
try:
response = requests.get(url, headers=headers, params=params)
if response.status_code in (200, 201):
report_data = response.json()
report_id = report_data.get('reportId')
if report_id:
return report_id
else:
raise ValueError("Report ID not found in response.")
else:
raise ValueError(f"Failed to generate report ID: {response.status_code}, {response.text}")
except Exception as e:
helper.log_error(f"Error while generating report ID: {e}")
raise ValueError(f"Error while generating report ID: {e}")
def download_report(jwt_token, report_id, helper):
"""
Downloads the report using the JWT token and report ID.
"""
url = f"https://example_url/{report_id}/download"
headers = {
"accept": "application/json",
"Authorization": f"Bearer {jwt_token}",
}
try:
# Make the request to download the report
response = helper.send_http_request(url, method="GET", headers=headers, verify=True)
if response.status_code in (200, 201):
# Save the report content to a file
sanitized_report_id = "".join(c if c.isalnum() else "_" for c in report_id)
file_path = f"C:\\Program Files\\Splunk\\etc\\apps\\splunk_app_addon-builder\\local\\temp\\{sanitized_report_id}.csv.gz"
with open(file_path, "wb") as file:
file.write(response.content)
helper.log_info(f"Report downloaded successfully to: {file_path}")
return file_path
else:
raise ValueError(f"Failed to download report: {response.status_code}, {response.text}")
except Exception as e:
helper.log_error(f"Error while downloading report: {e}")
raise ValueError(f"Error while downloading report: {e}")
I can't see any obvious issue with your code. What happens if you include debug log statements that output the report_id value, and then the resulting URL?
Assuming logging mode is set to debug:
helper.log_debug(f"Report ID is: {report_id}")
url = f"https://example_url/{report_id}/download"
helper.log_debug(f"URL is: {url}")
headers = {
"accept": "application/json",
"Authorization": f"Bearer {jwt_token}",
}