Skip to content

Commit 1e314f3

Browse files
committed
Create J1QLdeferredResponse.py
1 parent 61f36be commit 1e314f3

File tree

1 file changed

+297
-0
lines changed

1 file changed

+297
-0
lines changed

examples/J1QLdeferredResponse.py

Lines changed: 297 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,297 @@
1+
import os
2+
import time
3+
import json
4+
import requests
5+
from requests.adapters import HTTPAdapter, Retry
6+
7+
8+
def const():
9+
10+
# JupiterOne GraphQL API:
11+
url = "https://graphql.us.jupiterone.io"
12+
13+
# JupiterOne API creds
14+
acct = os.environ.get("JUPITERONE_ACCOUNT")
15+
token = os.environ.get("JUPITERONE_TOKEN")
16+
17+
# J1QL query to be executed
18+
query = "FIND *"
19+
20+
return [acct, token, url, query]
21+
22+
23+
def get_data(url, query, variables):
24+
25+
headers = {
26+
'Content-Type': 'application/json',
27+
'Authorization': 'Bearer ' + const()[1],
28+
'Jupiterone-Account': const()[0]
29+
}
30+
31+
payload = {
32+
"query": query,
33+
"variables": variables
34+
}
35+
36+
try:
37+
s = requests.Session()
38+
retries = Retry(total=10, backoff_factor=1, status_forcelist=[502, 503, 504])
39+
s.mount('https://', HTTPAdapter(max_retries=retries))
40+
response = s.post(url, headers=headers, json=payload)
41+
42+
if response.status_code == 200:
43+
data = response.json()
44+
return data
45+
else:
46+
raise Exception("Failed to fetch data. HTTP status code: " + str(response.status_code))
47+
except Exception as e:
48+
raise Exception("POST request to JupiterOne GraphQL API failed. Exception: " + str(e))
49+
50+
51+
def fetch_first_result(url, query, variables):
52+
53+
deferred_response = get_data(url, query, variables)
54+
results_url = deferred_response['data']['queryV1'].get('url')
55+
results_data = requests.get(results_url).json()
56+
return results_data
57+
58+
59+
def build_payload(q):
60+
query = '''
61+
query J1QL($query: String!, $variables: JSON, $cursor: String, $deferredResponse: DeferredResponseOption
62+
$flags: QueryV1Flags) {
63+
queryV1(query: $query, variables: $variables, cursor: $cursor, deferredResponse: $deferredResponse,
64+
flags: $flags) {
65+
type
66+
url
67+
cursor
68+
}
69+
}
70+
'''
71+
72+
variables = {
73+
"query": q,
74+
"deferredResponse": "FORCE",
75+
"cursor": ""
76+
}
77+
78+
return query, variables
79+
80+
81+
# def poll_deferred_response_url(url):
82+
#
83+
# r = requests.get(url, verify=True).json()
84+
# max_retry = 10
85+
# retry_count = 0
86+
# retry_delay = 2
87+
#
88+
# while r['status'] == "IN_PROGRESS" and retry_count < max_retry:
89+
# r = requests.get(url, verify=True).json()
90+
# retry_count += 1
91+
# time.sleep(retry_delay)
92+
# retry_delay *= 2
93+
#
94+
# if r['status'] == "COMPLETED":
95+
# response_url = r['url']
96+
# return response_url
97+
#
98+
# else:
99+
# formatted_json = json.dumps(r, indent=4)
100+
# # print(formatted_json)
101+
#
102+
#
103+
# def fetch_cursor_results(results):
104+
#
105+
# full_results = []
106+
# full_results.extend(results["data"])
107+
#
108+
# try:
109+
#
110+
# while results["cursor"]:
111+
#
112+
# variables = build_payload(const()[3])[1]
113+
#
114+
# variables["cursor"] = results["cursor"]
115+
# print(results["cursor"])
116+
#
117+
# url = fetch_results_url(const()[2],
118+
# build_payload(const()[3])[0],
119+
# variables)
120+
#
121+
# print(url)
122+
#
123+
# # results_download_url = poll_deferred_response_url(url)
124+
#
125+
# r = requests.get(results_download_url, verify=True).json()
126+
# print(r)
127+
# #
128+
# # full_results.extend(r["data"])
129+
# #
130+
# # return full_results
131+
#
132+
# except Exception as e:
133+
# err = e
134+
#
135+
# return err
136+
137+
138+
def fetch_all_results(api_endpoint, query, variables=None, headers=None):
139+
"""
140+
Fetch all URLs from a paginated GraphQL API endpoint.
141+
142+
Args:
143+
api_endpoint (str): The GraphQL API URL to request data from.
144+
query (str): The GraphQL query string.
145+
variables (dict, optional): Variables for the GraphQL query.
146+
headers (dict, optional): Headers for the request.
147+
148+
Returns:
149+
list: A list of URLs retrieved from the API.
150+
"""
151+
152+
all_results_data = []
153+
cursor = None # Initial cursor
154+
first_request = True
155+
156+
while True:
157+
158+
# Update variables with the current cursor if available
159+
if variables is None:
160+
variables = {}
161+
if cursor:
162+
variables['cursor'] = cursor
163+
164+
payload = {
165+
"query": query,
166+
"variables": variables
167+
}
168+
169+
try:
170+
s = requests.Session()
171+
retries = Retry(total=10, backoff_factor=1, status_forcelist=[502, 503, 504])
172+
s.mount('https://', HTTPAdapter(max_retries=retries))
173+
response = s.post(api_endpoint, headers=headers, json=payload)
174+
175+
if response.status_code == 200:
176+
data = response.json()
177+
# return data
178+
# print(data)
179+
180+
# Extract URLs from the response (modify according to API response structure)
181+
url = data.get('data', {}).get('queryV1', []).get('url', "")
182+
183+
# print(url)
184+
# print(first_request)
185+
186+
if first_request and url:
187+
# Execute a GET request to the first URL and return the contents
188+
first_url_response = requests.get(url)
189+
first_url_response_data = first_url_response.json()['data']
190+
first_url_response_url = first_url_response.json()['url']
191+
first_url_response_cursor = first_url_response.json()['cursor']
192+
# print(first_url_response_data)
193+
# print(first_url_response_cursor)
194+
# print(first_url_response_url)
195+
196+
all_results_data.append(first_url_response_data)
197+
198+
while first_url_response_cursor:
199+
url_response = requests.get(first_url_response_url).json()
200+
print(url_response)
201+
cursor = url_response.get('cursor')
202+
203+
all_results_data.append(url_response)
204+
205+
if not cursor:
206+
break
207+
208+
209+
return all_results_data
210+
211+
first_request = False # Mark first request as done
212+
213+
# Check for next cursor
214+
cursor = data.get('data', {}).get('cursor')
215+
if not cursor:
216+
break # Stop if there is no next cursor
217+
218+
else:
219+
raise Exception("Failed to fetch data. HTTP status code: " + str(response.status_code))
220+
except Exception as e:
221+
raise Exception("POST request to JupiterOne GraphQL API failed. Exception: " + str(e))
222+
223+
return all_results_data
224+
225+
226+
if __name__ == "__main__":
227+
228+
deferred_response_first_result = fetch_first_result(const()[2],
229+
build_payload(const()[3])[0],
230+
build_payload(const()[3])[1])
231+
# print(deferred_response_first_result)
232+
233+
all_results_data = []
234+
235+
response_status = deferred_response_first_result['status']
236+
response_url = deferred_response_first_result['url']
237+
response_data = deferred_response_first_result['data']
238+
response_cursor = deferred_response_first_result['cursor']
239+
240+
all_results_data.extend(response_data)
241+
242+
cursor = response_cursor
243+
244+
while cursor:
245+
variables = build_payload(const()[3])[1]['cursor'] = cursor
246+
# print(variables)
247+
r = get_data(url=response_url, query=build_payload(const()[3])[0], variables=const()[3])
248+
print(r)
249+
r_data = r['data']
250+
r_cursor = r['cursor']
251+
252+
all_results_data.extend(r_data)
253+
254+
cursor = r_cursor
255+
256+
if not cursor:
257+
break
258+
259+
260+
261+
# endpoint = const()[2]
262+
# query = build_payload("find *")[0]
263+
# variables = build_payload(const()[3])[1]
264+
# # print(variables)
265+
# headers = {
266+
# 'Content-Type': 'application/json',
267+
# 'Authorization': 'Bearer ' + const()[1],
268+
# 'Jupiterone-Account': const()[0]
269+
# }
270+
#
271+
# r = fetch_all_urls(endpoint, query, variables, headers)
272+
273+
# print(fetch_all_urls(endpoint, query, variables, headers))
274+
275+
276+
277+
# deferredResponseURL = fetch_results_url(const()[2],
278+
# build_payload(const()[3])[0],
279+
# build_payload(const()[3])[1])
280+
# # print(deferredResponseURL)
281+
#
282+
# results_download_url = poll_deferred_response_url(deferredResponseURL)
283+
#
284+
# r = requests.get(results_download_url, verify=True).json()
285+
# print(len(r["data"]))
286+
#
287+
# out = fetch_cursor_results(r)
288+
# print(len(out))
289+
290+
291+
292+
293+
294+
#
295+
# # # write full results data to local .json file
296+
# # with open("J1VulnExtr.json", "w", encoding="utf-8") as outfile:
297+
# # json.dump(full_results, outfile)

0 commit comments

Comments
 (0)