Skip to content

Commit 90920a1

Browse files
authored
[DSEC-963] add retry loop
* add retry loop * increase zap connect timeout. * decrease requests per second in zap. * change zap shutdown * add retries * fix float issue * fix resolution error * add logging * use zap session for shutdown request * clean up * small formatting updates * make retry loop more robust
1 parent 5590e47 commit 90920a1

File tree

3 files changed

+51
-21
lines changed

3 files changed

+51
-21
lines changed

zap/src/drive_upload.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ def find_subfolder(folder_structure, target_name, target_folder=None):
120120
Finds a specific subfolder by name, returns the dict for that folder.
121121
"""
122122
for child in folder_structure['children']:
123-
if child['name'] == target_name:
123+
if target_name in child['name']:
124124
target_folder = child
125125
return target_folder
126126
target_folder = find_subfolder(child, target_name)

zap/src/scan.py

Lines changed: 22 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
from google.cloud import storage
2323
from slack_sdk.web import WebClient as SlackClient
2424

25-
from zap import ScanType, zap_compliance_scan, zap_connect
25+
from zap import ScanType, zap_compliance_scan, zap_shutdown
2626

2727

2828
def fetch_dojo_product_name(defect_dojo, defect_dojo_user, defect_dojo_key, product_id):
@@ -34,7 +34,7 @@ def fetch_dojo_product_name(defect_dojo, defect_dojo_user, defect_dojo_key, prod
3434
defect_dojo, defect_dojo_key, defect_dojo_user, debug=False, timeout=120)
3535
max_retries = int(getenv("MAX_RETRIES", '6'))
3636
retry_delay = 30
37-
for attempt in range(max_retries):
37+
for _ in range(max_retries):
3838
try:
3939
product = dojo.get_product(product_id=product_id)
4040
return product.data["name"]
@@ -106,11 +106,21 @@ def defectdojo_upload(product_id: int, zap_filename: str, defect_dojo_key: str,
106106
date = datetime.today().strftime("%Y%m%d%H:%M")
107107
lead_id = fetch_dojo_lead_id(dojo, defect_dojo_user)
108108

109-
engagement=dojo.create_engagement( name=date, product_id=product_id, lead_id=lead_id,
110-
target_start=datetime.today().strftime("%Y-%m-%d"),
111-
target_end=datetime.today().strftime("%Y-%m-%d"), status="In Progress",
112-
active='True',deduplication_on_engagement='False')
113-
engagement_id=engagement.data["id"]
109+
# The call to create_engagement sometimes fails.
110+
retry_delay = 20
111+
max_retries = int(getenv("MAX_RETRIES", '5'))
112+
for attempt in range(max_retries):
113+
try:
114+
engagement=dojo.create_engagement( name=date, product_id=product_id, lead_id=lead_id,
115+
target_start=datetime.today().strftime("%Y-%m-%d"),
116+
target_end=datetime.today().strftime("%Y-%m-%d"), status="In Progress",
117+
active='True',deduplication_on_engagement='False')
118+
engagement_id=engagement.data["id"]
119+
break
120+
except Exception: # pylint: disable=broad-except
121+
sleep(retry_delay)
122+
if attempt == max_retries-1:
123+
raise RuntimeError("Maximum retry attempts reached for closing engagement")
114124

115125
dojo_upload = dojo.upload_scan(engagement_id=engagement_id,
116126
scan_type="ZAP Scan",
@@ -242,7 +252,6 @@ def get_codedx_initial_report(
242252
file_name=report_file,
243253
filters=filters,
244254
)
245-
246255
return report_file
247256

248257

@@ -372,7 +381,7 @@ def upload_googledrive(scan_type, zap_filename, codedx_project, report_file, sla
372381
"""
373382
root_id = os.getenv('DRIVE_ROOT_ID', None)
374383
drive_id = os.getenv('DRIVE_ID', None)
375-
if scan_type in (ScanType.BASELINE):
384+
if scan_type in (ScanType.BASELINE):
376385
return
377386
try:
378387
logging.info('Setting up the google drive API service for uploading reports.')
@@ -389,7 +398,6 @@ def upload_googledrive(scan_type, zap_filename, codedx_project, report_file, sla
389398
date = datetime.today()
390399
date = drivehelper.adjust_date(date)
391400
_, xml_folder_dict, zap_raw_folder = drivehelper.get_upload_folders(folder_structure, date)
392-
393401
file = drivehelper.upload_file_to_drive(zap_filename,
394402
xml_folder_dict.get('id'),
395403
drive_id,
@@ -508,10 +516,9 @@ def main(): # pylint: disable=too-many-locals
508516
dd,
509517
target_url
510518
)
511-
zap = zap_connect()
512-
zap.core.shutdown()
519+
zap_shutdown()
513520
return
514-
521+
515522
# upload its results to Code Dx
516523
cdx = CodeDx(codedx_url, codedx_api_key)
517524

@@ -533,8 +540,7 @@ def main(): # pylint: disable=too-many-locals
533540
logging.info("ready to upload to google drive")
534541
upload_googledrive(scan_type, zap_filename, codedx_project, cdx_filename, slack_token, slack_channel)
535542

536-
zap = zap_connect()
537-
zap.core.shutdown()
543+
zap_shutdown()
538544
return
539545
except Exception as error: # pylint: disable=broad-except
540546
error_message = f"[RETRY-{ attempt }] Exception running Zap Scans: { error }"
@@ -546,8 +552,7 @@ def main(): # pylint: disable=too-many-locals
546552
except:
547553
logging.error(f"Slack could not post to {slack_channel}")
548554
try:
549-
zap = zap_connect()
550-
zap.core.shutdown()
555+
zap_shutdown()
551556
except Exception as zap_e: # pylint: disable=broad-except
552557
error_message = f"Error shutting down zap: { zap_e }"
553558
error_slack_alert(

zap/src/zap.py

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
from zap_scan_type import ScanType
2222
from zapv2 import ZAPv2
2323

24-
TIMEOUT_MINS = 5
24+
TIMEOUT_MINS = 6
2525
zap_port = int(os.getenv("ZAP_PORT", ""))
2626
PROXY = f"http://localhost:{zap_port}"
2727

@@ -47,7 +47,7 @@ def zap_init(target_url: str):
4747
enabled = True
4848
matchregex = True
4949
matchstring = ".*"
50-
requestspersecond = 5
50+
requestspersecond = 4
5151
groupby = "host"
5252
zap.network.add_rate_limit_rule(description,
5353
enabled,
@@ -60,6 +60,31 @@ def zap_init(target_url: str):
6060

6161
return zap
6262

63+
def zap_shutdown():
64+
"""
65+
Connect to the Zap instance and shut it down.
66+
"""
67+
proxies = {
68+
'http': PROXY,
69+
'https': PROXY,
70+
}
71+
logging.info("Attempting to shutdown ZAP")
72+
apikey = os.getenv("ZAP_API_KEY", "")
73+
zap = ZAPv2(proxies={"http": PROXY, "https": PROXY}, apikey=apikey)
74+
sleep_time = 20
75+
attempts = int((TIMEOUT_MINS*60)/20)
76+
for attempt in range(attempts):
77+
try:
78+
shutdown_endpoint = zap.base + "core/action/shutdown/"
79+
headers = { "X-ZAP-API-Key" : apikey }
80+
resp = requests.get(shutdown_endpoint, proxies=proxies, headers=headers,
81+
timeout=int(TIMEOUT_MINS*60)/2)
82+
logging.info(f"Response code from requesting ZAP shutdown: {resp.status_code}")
83+
if int(resp.status_code) == 200:
84+
return
85+
except Exception as e:
86+
logging.error(f"An error occured while shutting down zap. Attempt {attempt+1}")
87+
time.sleep(sleep_time)
6388

6489
def parse_url(url):
6590
"""
@@ -320,7 +345,7 @@ def get_hail_token():
320345
"aud": "https://www.googleapis.com/oauth2/v4/token",
321346
"iat": now,
322347
"scope": scope,
323-
"exp": now + 300, # 5m
348+
"exp": now + 3000, # 50m
324349
"iss": creds['client_email'],
325350
}
326351
encoded_assertion = jwt.encode(assertion, creds['private_key'], algorithm='RS256')

0 commit comments

Comments
 (0)