Skip to content

Commit 4cddd94

Browse files
committed
Adds more utility methods in BaseScanner class
to be used by consumer classes
1 parent 5ed413f commit 4cddd94

File tree

1 file changed

+147
-0
lines changed

1 file changed

+147
-0
lines changed

ccp/scanning/base_scanner.py

Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,14 @@
66

77
from datetime import datetime
88

9+
import json
910
import logging
1011
import os
1112
import platform
1213
import subprocess
14+
import sys
15+
16+
import requests
1317

1418

1519
class BinaryDoesNotExist(Exception):
@@ -147,3 +151,146 @@ def run_cmd_out_err(self, cmd):
147151
"""
148152
return subprocess.Popen(cmd, stdout=subprocess.PIPE,
149153
stderr=subprocess.PIPE).communicate()
154+
155+
def post_request(self, endpoint, api, data, headers=None):
156+
"""
157+
Make a post call to analytics server with given data
158+
:param endpoint: API server end point
159+
:param api: API to make POST call against
160+
:param data: JSON data needed for POST call to api endpoint
161+
:return: Tuple (status, error_if_any, status_code)
162+
where status = True/False
163+
error_if_any = string message on error, "" on success
164+
status_code = status_code returned by server
165+
"""
166+
url = requests.compat.urljoin(endpoint, api)
167+
# TODO: check if we need API key in data
168+
try:
169+
r = requests.post(
170+
url,
171+
json.dumps(data),
172+
headers=headers)
173+
except requests.exceptions.RequestException as e:
174+
error = ("Could not send POST request to URL {0}, "
175+
"with data: {1}.").format(url, str(data))
176+
return False, error + " Error: " + str(e), 0
177+
else:
178+
# requests.codes.ok == 200
179+
if r.status_code == requests.codes.ok:
180+
return True, json.loads(r.text), r.status_code
181+
else:
182+
return False, "Returned {} status code for {}".format(
183+
r.status_code, url), r.status_code
184+
185+
def get_request(self, endpoint, api, data, headers=None):
186+
"""
187+
Make a get call to analytics server
188+
:param endpoint: API server end point
189+
:param api: API to make GET call against
190+
:param data: JSON data needed for GET call
191+
:return: Tuple (status, error_if_any, status_code)
192+
where status = True/False
193+
error_if_any = string message on error, "" on success
194+
status_code = status_code returned by server
195+
"""
196+
url = requests.compat.urljoin(endpoint, api)
197+
# TODO: check if we need API key in data
198+
try:
199+
r = requests.get(
200+
url,
201+
params=data,
202+
headers=headers)
203+
204+
except requests.exceptions.RequestException as e:
205+
error = "Failed to process URL: {} with params {}".format(
206+
url, data)
207+
return False, error + " Error: " + str(e), 0
208+
else:
209+
# requests.codes.ok == 200 or
210+
# check for 400 code - as this is a valid response
211+
# as per the workflow
212+
if r.status_code in [requests.codes.ok, 400]:
213+
return True, json.loads(r.text), r.status_code
214+
else:
215+
msg = "Returned {} status code for {}. {}".format(
216+
r.status_code, url, r.json().get(
217+
"summary", "no summary returned from server."))
218+
return False, msg, r.status_code
219+
220+
def export_json_results(self, results, output_dir, output_file):
221+
"""
222+
Export given results JSON data in output_dir/output_file
223+
224+
:param results: JSON results to be exported
225+
:type results: dict
226+
:param output_dir: Output directory
227+
:type output_dir: str
228+
:param output_file: Output file name
229+
:type output_file: str
230+
"""
231+
os.makedirs(output_dir)
232+
233+
result_filename = os.path.join(output_dir, output_file)
234+
235+
with open(result_filename, "w") as f:
236+
json.dump(results, f, indent=4, separators=(",", ": "))
237+
238+
def template_json_data(self, scanner, scan_type='', uuid=''):
239+
"""
240+
Populate and return a template standard json data out for scanner.
241+
"""
242+
current_time = datetime.now().strftime("%Y-%m-%d-%H-%M-%S-%f")
243+
json_out = {
244+
"Start Time": current_time,
245+
"Successful": False,
246+
"Scan Type": scan_type,
247+
"UUID": uuid,
248+
"Scanner": scanner,
249+
"Scan Results": {},
250+
"Summary": ""
251+
}
252+
return json_out
253+
254+
def configure_stdout_logging(
255+
self, logger_name, logging_level=logging.DEBUG):
256+
"""
257+
Configures stdout logging and returns logger object
258+
259+
:param logger_name: Logger name
260+
:type logger_name: str
261+
:param logging_level: Logging level
262+
:type logging_level: str or int
263+
264+
:return: Logger object
265+
"""
266+
logger = logging.getLogger(logger_name)
267+
logger.setLevel(logging_level)
268+
# add sys.stdout stream
269+
ch = logging.StreamHandler(sys.stdout)
270+
ch.setLevel(logging.DEBUG)
271+
# add logging formatter
272+
formatter = logging.Formatter(
273+
"%(asctime)s %(levelname)s p%(process)s %(name)s %(lineno)d "
274+
"%(levelname)s - %(message)s"
275+
)
276+
# set formatter to stream handler
277+
ch.setFormatter(formatter)
278+
# set handler to logger
279+
logger.addHandler(ch)
280+
return logger
281+
282+
def get_env_var(self, env_var):
283+
"""
284+
Gets the given configured env_var
285+
:param env_var: Environment variable to be accessed
286+
:type env_var: str
287+
288+
:return: Value of given env_var
289+
:rtype: str
290+
"""
291+
if not os.environ.get(env_var, False):
292+
raise ValueError(
293+
"No value for {0} env var. Please re-run with: "
294+
"{0}=<VALUE> [..] atomic scan [..] ".format(env_var)
295+
)
296+
return os.environ.get(env_var)

0 commit comments

Comments
 (0)