Skip to content

Commit ff20301

Browse files
smtakedaankit-bhatnagar167
authored andcommitted
SNOW-75337: Improved OCSP Monitoring script
1 parent 8230e9b commit ff20301

File tree

3 files changed

+99
-56
lines changed

3 files changed

+99
-56
lines changed

ocsp_asn1crypto.py

Lines changed: 31 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -194,16 +194,17 @@ def process_ocsp_response(self, issuer, cert_id, ocsp_response):
194194

195195
if cur_time > ocsp_cert['tbs_certificate']['validity']['not_after'].native or \
196196
cur_time < ocsp_cert['tbs_certificate']['validity']['not_before'].native:
197+
debug_msg = "Certificate attached to OCSP response is invalid. OCSP response " \
198+
"current time - {0} certificate not before time - {1} certificate " \
199+
"not after time - {2}. Consider running curl -o ocsp.der {3}".\
200+
format(cur_time,
201+
ocsp_cert['tbs_certificate']['validity']['not_before'].native,
202+
ocsp_cert['tbs_certificate']['validity']['not_after'].native,
203+
super(SnowflakeOCSPAsn1Crypto, self).debug_ocsp_failure_url)
204+
197205
raise OperationalError(
198-
msg="Certificate attached to OCSP response is invalid. OCSP response "
199-
"current time - {0} "
200-
"certificate not before time - {1} "
201-
"certificate not after time - {2}".
202-
format(cur_time,
203-
ocsp_cert['tbs_certificate']['validity']['not_before'].native,
204-
ocsp_cert['tbs_certificate']['validity']['not_after'].native),
205-
errno=ER_INVALID_OCSP_RESPONSE_CODE
206-
)
206+
msg=debug_msg,
207+
errno=ER_INVALID_OCSP_RESPONSE_CODE)
207208

208209
self.verify_signature(
209210
ocsp_cert.hash_algo,
@@ -227,19 +228,27 @@ def process_ocsp_response(self, issuer, cert_id, ocsp_response):
227228

228229
single_response = tbs_response_data['responses'][0]
229230
cert_status = single_response['cert_status'].name
230-
if cert_status == 'good':
231-
self._process_good_status(single_response, cert_id, ocsp_response)
232-
SnowflakeOCSP.OCSP_CACHE.update_cache(self, cert_id, ocsp_response)
233-
elif cert_status == 'revoked':
234-
self._process_revoked_status(single_response, cert_id)
235-
elif cert_status == 'unknown':
236-
self._process_unknown_status(cert_id)
237-
else:
238-
raise OperationalError(
239-
msg="Unknown revocation status was returned. OCSP response "
240-
"may be malformed: {0}".format(cert_status),
241-
errno=ER_INVALID_OCSP_RESPONSE_CODE
242-
)
231+
try:
232+
if cert_status == 'good':
233+
self._process_good_status(single_response, cert_id, ocsp_response)
234+
SnowflakeOCSP.OCSP_CACHE.update_cache(self, cert_id, ocsp_response)
235+
elif cert_status == 'revoked':
236+
self._process_revoked_status(single_response, cert_id)
237+
elif cert_status == 'unknown':
238+
self._process_unknown_status(cert_id)
239+
else:
240+
debug_msg = "Unknown revocation status was returned." \
241+
"OCSP response may be malformed: {0}.".\
242+
format(cert_status)
243+
raise OperationalError(
244+
msg=debug_msg,
245+
errno=ER_INVALID_OCSP_RESPONSE_CODE
246+
)
247+
except OperationalError as op_er:
248+
debug_msg = "{0} Consider running curl -o ocsp.der {1}".\
249+
format(op_er.msg,
250+
self.debug_ocsp_failure_url)
251+
raise OperationalError(msg=debug_msg, errno=op_er.errno)
243252

244253
def verify_signature(self, signature_algorithm, signature, cert, data):
245254
pubkey = cert.public_key.unwrap().dump()

ocsp_pyasn1.py

Lines changed: 29 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -422,11 +422,12 @@ def process_ocsp_response(self, issuer, cert_id, ocsp_response):
422422
cert_not_before_utc = cert_not_before.getComponentByName('utcTime').asDateTime
423423

424424
if cur_time > cert_not_after_utc or cur_time < cert_not_before_utc:
425+
debug_msg = "Certificate attached to OCSP Response is invalid. " \
426+
"OCSP response current time - {0} certificate not " \
427+
"before time - {1} certificate not after time - {2}. ".\
428+
format(cur_time, cert_not_before_utc, cert_not_after_utc)
425429
raise OperationalError(
426-
msg="Certificate attached to OCSP Response is invalid. OCSP response "
427-
"current time - {0} "
428-
"certificate not before time - {1} "
429-
"certificate not after time - {2}".format(cur_time, cert_not_before_utc, cert_not_after_utc),
430+
msg=debug_msg,
430431
errno=ER_INVALID_OCSP_RESPONSE_CODE
431432
)
432433

@@ -453,19 +454,31 @@ def process_ocsp_response(self, issuer, cert_id, ocsp_response):
453454

454455
single_response = tbs_response_data.getComponentByName('responses')[0]
455456
cert_status = single_response.getComponentByName('certStatus')
456-
if cert_status.getName() == 'good':
457-
self._process_good_status(single_response, cert_id, ocsp_response)
458-
SnowflakeOCSP.OCSP_CACHE.update_cache(self, cert_id, ocsp_response)
459-
elif cert_status.getName() == 'revoked':
460-
self._process_revoked_status(single_response, cert_id)
461-
elif cert_status.getName() == 'unknown':
462-
self._process_unknown_status(cert_id)
463-
else:
457+
try:
458+
if cert_status.getName() == 'good':
459+
self._process_good_status(single_response, cert_id, ocsp_response)
460+
SnowflakeOCSP.OCSP_CACHE.update_cache(self, cert_id, ocsp_response)
461+
elif cert_status.getName() == 'revoked':
462+
self._process_revoked_status(single_response, cert_id)
463+
elif cert_status.getName() == 'unknown':
464+
self._process_unknown_status(cert_id)
465+
else:
466+
debug_msg = "Unknown revocation status was returned. " \
467+
"OCSP response may be malformed: {0}. ".format(cert_status)
468+
raise OperationalError(
469+
msg=debug_msg,
470+
errno=ER_INVALID_OCSP_RESPONSE_CODE
471+
)
472+
except OperationalError as op_er:
473+
if not self.debug_ocsp_failure_url:
474+
debug_msg = op_er.msg
475+
else:
476+
debug_msg = "{0} Consider running curl -o ocsp.der {1}".\
477+
format(op_er.msg,
478+
self.debug_ocsp_failure_url)
464479
raise OperationalError(
465-
msg="Unknown revocation status was returned. OCSP response "
466-
"may be malformed: {0}".format(cert_status),
467-
errno=ER_INVALID_OCSP_RESPONSE_CODE
468-
)
480+
msg=debug_msg,
481+
errno=op_er.errno)
469482

470483
def verify_signature(self, signature_algorithm, signature, cert, data):
471484
"""

ocsp_snowflake.py

Lines changed: 39 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -765,6 +765,8 @@ def __init__(
765765
SnowflakeOCSP.SSD.check_ssd_support()
766766
self.OCSP_CACHE_SERVER = OCSPServer()
767767

768+
self.debug_ocsp_failure_url = None
769+
768770
if SnowflakeOCSP.SSD.ACTIVATE_SSD:
769771
SnowflakeOCSP.OCSP_CACHE.set_ssd_status(SnowflakeOCSP.SSD.ACTIVATE_SSD)
770772
SnowflakeOCSP.SSD.clear_ssd_cache()
@@ -900,6 +902,8 @@ def validate_by_direct_connection(self, issuer, subject, hostname=None, do_retry
900902
logger.debug("getting OCSP response from CA's OCSP server")
901903
ocsp_response = self._fetch_ocsp_response(req, subject, cert_id, hostname)
902904
else:
905+
ocsp_url = self.extract_ocsp_url(subject)
906+
self.debug_ocsp_failure_url = SnowflakeOCSP.create_ocsp_debug_info(self, req, ocsp_url)
903907
logger.debug("using OCSP response cache")
904908

905909
if not ocsp_response:
@@ -1056,6 +1060,12 @@ def cache_size():
10561060
def delete_cache_file():
10571061
SnowflakeOCSP.OCSP_CACHE.delete_cache_file()
10581062

1063+
@staticmethod
1064+
def create_ocsp_debug_info(ocsp, ocsp_request, ocsp_url):
1065+
b64data = ocsp.decode_ocsp_request_b64(ocsp_request)
1066+
target_url = "{0}/{1}".format(ocsp_url, b64data)
1067+
return target_url
1068+
10591069
def _fetch_ocsp_response(self, ocsp_request, subject, cert_id, hostname=None, do_retry=True):
10601070
"""
10611071
Fetch OCSP response using OCSPRequest
@@ -1092,31 +1102,42 @@ def _fetch_ocsp_response(self, ocsp_request, subject, cert_id, hostname=None, do
10921102
'ocsp_responder_url': ocsp_url})
10931103
headers = {'Content-Type': 'application/json'}
10941104

1105+
self.debug_ocsp_failure_url = SnowflakeOCSP.create_ocsp_debug_info(self, ocsp_request, ocsp_url)
1106+
10951107
ret = None
10961108
logger.debug('url: %s', target_url)
10971109
with generic_requests.Session() as session:
10981110
max_retry = 30 if do_retry else 1
10991111
sleep_time = 1
11001112
backoff = DecorrelateJitterBackoff(sleep_time, 16)
11011113
for attempt in range(max_retry):
1102-
response = session.request(
1103-
headers=headers,
1104-
method=actual_method,
1105-
url=target_url,
1106-
timeout=30,
1107-
data=payload,
1108-
)
1109-
if response.status_code == OK:
1110-
logger.debug(
1111-
"OCSP response was successfully returned from OCSP "
1112-
"server.")
1113-
ret = response.content
1114-
break
1115-
elif max_retry > 1:
1116-
sleep_time = backoff.next_sleep(1, sleep_time)
1117-
logger.debug("OCSP server returned %s. Retrying in %s(s)",
1118-
response.status_code, sleep_time)
1119-
time.sleep(sleep_time)
1114+
try:
1115+
response = session.request(
1116+
headers=headers,
1117+
method=actual_method,
1118+
url=target_url,
1119+
timeout=30,
1120+
data=payload,
1121+
)
1122+
if response.status_code == OK:
1123+
logger.debug(
1124+
"OCSP response was successfully returned from OCSP "
1125+
"server.")
1126+
ret = response.content
1127+
break
1128+
elif max_retry > 1:
1129+
sleep_time = backoff.next_sleep(1, sleep_time)
1130+
logger.debug("OCSP server returned %s. Retrying in %s(s)",
1131+
response.status_code, sleep_time)
1132+
time.sleep(sleep_time)
1133+
except Exception as ex:
1134+
if max_retry > 1:
1135+
sleep_time = backoff.next_sleep(1, sleep_time)
1136+
logger.debug("Could not fetch OCSP Response from server"
1137+
"Retrying in %s(s)", sleep_time)
1138+
time.sleep(sleep_time)
1139+
else:
1140+
raise ex
11201141
else:
11211142
logger.error(
11221143
"Failed to get OCSP response after %s attempt.", max_retry)

0 commit comments

Comments
 (0)