Skip to content

Commit 645e910

Browse files
sfc-gh-stakedaankit-bhatnagar167
authored andcommitted
SNOW-88410: fix custom OCSP URL threadsafe
1 parent 5fc5fb7 commit 645e910

File tree

2 files changed

+97
-16
lines changed

2 files changed

+97
-16
lines changed

connection.py

Lines changed: 26 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,8 @@ class SnowflakeConnection(object):
165165
connect(..) to get the object.
166166
"""
167167

168+
OCSP_ENV_LOCK = Lock()
169+
168170
def __init__(self, **kwargs):
169171
self._lock_sequence_counter = Lock()
170172
self.sequence_counter = 0
@@ -609,30 +611,39 @@ def __set_error_attributes(self):
609611

610612
@staticmethod
611613
def setup_ocsp_privatelink(app, hostname):
612-
if app == APPLICATION_SNOWSQL:
614+
SnowflakeConnection.OCSP_ENV_LOCK.acquire()
615+
if app is APPLICATION_SNOWSQL:
613616
ocsp_cache_server = u'http://ocsp{}/ocsp_response_cache.json'.format(
614617
hostname[hostname.index('.'):])
618+
'''
619+
Check if user has configured a custom OCSP Cache Server URL
620+
'''
621+
if 'SF_OCSP_RESPONSE_CACHE_SERVER_URL' not in os.environ:
622+
os.environ[
623+
'SF_OCSP_RESPONSE_CACHE_SERVER_URL'] = ocsp_cache_server
624+
else:
625+
if "ocsp_response_cache" not in os.environ['SF_OCSP_RESPONSE_CACHE_SERVER_URL']:
626+
if not os.environ['SF_OCSP_RESPONSE_CACHE_SERVER_URL']. \
627+
startswith("http://"):
628+
ocsp_cache_server = "http://{0}/{1}".format(
629+
os.environ['SF_OCSP_RESPONSE_CACHE_SERVER_URL'],
630+
"ocsp_response_cache.json")
631+
else:
632+
ocsp_cache_server = "{0}/{1}".format(
633+
os.environ['SF_OCSP_RESPONSE_CACHE_SERVER_URL'],
634+
"ocsp_response_cache.json")
635+
else:
636+
ocsp_cache_server = os.environ['SF_OCSP_RESPONSE_CACHE_SERVER_URL']
637+
638+
os.environ['SF_OCSP_RESPONSE_CACHE_SERVER_URL'] = ocsp_cache_server
615639
else:
616640
ocsp_cache_server = \
617641
u'http://ocsp.{}/ocsp_response_cache.json'.format(
618642
hostname)
619-
if 'SF_OCSP_RESPONSE_CACHE_SERVER_URL' not in os.environ:
620-
os.environ[
621-
'SF_OCSP_RESPONSE_CACHE_SERVER_URL'] = ocsp_cache_server
622-
else:
623-
if not os.environ['SF_OCSP_RESPONSE_CACHE_SERVER_URL']. \
624-
startswith("http://"):
625-
ocsp_cache_server = "http://{0}/{1}".format(
626-
os.environ['SF_OCSP_RESPONSE_CACHE_SERVER_URL'],
627-
"ocsp_response_cache.json")
628-
else:
629-
ocsp_cache_server = "{0}/{1}".format(
630-
os.environ['SF_OCSP_RESPONSE_CACHE_SERVER_URL'],
631-
"ocsp_response_cache.json")
632-
633643
os.environ[
634644
'SF_OCSP_RESPONSE_CACHE_SERVER_URL'] = ocsp_cache_server
635645
logger.debug(u"OCSP Cache Server is updated: %s", ocsp_cache_server)
646+
SnowflakeConnection.OCSP_ENV_LOCK.release()
636647

637648
def __open_connection(self):
638649
u"""

test/test_connection.py

Lines changed: 71 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
import os
88

99
import pytest
10+
import threading
11+
import queue
1012

1113
import snowflake.connector
1214
from snowflake.connector import (
@@ -467,7 +469,7 @@ def test_eu_connection(tmpdir):
467469
)
468470

469471

470-
@pytest.mark.timeout(15)
472+
#@pytest.mark.timeout(15)
471473
def test_us_west_connection(tmpdir):
472474
"""
473475
region='us-west-2' indicates no region is included in the hostname, i.e.,
@@ -565,3 +567,71 @@ def test_privatelink_ocsp_url_creation():
565567
assert ocsp_cache_server == \
566568
"http://ocsp.testaccount.us-east-1.privatelink.snowflakecomputing.com/ocsp_response_cache.json"
567569

570+
571+
def test_privatelink_ocsp_url_multithreaded():
572+
bucket = queue.Queue()
573+
574+
hostname = "testaccount.us-east-1.privatelink.snowflakecomputing.com"
575+
expectation = "http://ocsp.testaccount.us-east-1.privatelink.snowflakecomputing.com/ocsp_response_cache.json"
576+
thread_obj = []
577+
for i in range(15):
578+
thread_obj.append(ExecPrivatelinkThread(bucket, hostname, expectation, CLIENT_NAME))
579+
580+
for i in range(15):
581+
thread_obj[i].start()
582+
583+
fail_flag = False
584+
for i in range(15):
585+
thread_obj[i].join()
586+
exc = bucket.get(block=False)
587+
if exc != 'Success' and not fail_flag:
588+
fail_flag = True
589+
590+
if fail_flag:
591+
assert False, "OCSP URL was set incorrectly"
592+
593+
if os.getenv("SF_OCSP_RESPONSE_CACHE_SERVER_URL", None) is not None:
594+
del os.environ["SF_OCSP_RESPONSE_CACHE_SERVER_URL"]
595+
596+
597+
def test_privatelink_ocsp_url_multithreaded_snowsql():
598+
bucket = queue.Queue()
599+
600+
hostname = "testaccount.us-east-1.privatelink.snowflakecomputing.com"
601+
expectation = "http://ocsp.us-east-1.privatelink.snowflakecomputing.com/ocsp_response_cache.json"
602+
thread_obj = []
603+
for i in range(15):
604+
thread_obj.append(ExecPrivatelinkThread(bucket, hostname, expectation, APPLICATION_SNOWSQL))
605+
606+
for i in range(15):
607+
thread_obj[i].start()
608+
609+
fail_flag = False
610+
for i in range(15):
611+
thread_obj[i].join()
612+
exc = bucket.get(block=False)
613+
if exc != 'Success' and not fail_flag:
614+
fail_flag = True
615+
616+
if fail_flag:
617+
assert False, "OCSP URL was set incorrectly"
618+
619+
620+
class ExecPrivatelinkThread(threading.Thread):
621+
622+
def __init__(self, bucket, hostname, expectation, client_name):
623+
threading.Thread.__init__(self)
624+
self.bucket = bucket
625+
self.hostname = hostname
626+
self.expectation = expectation
627+
self.client_name = client_name
628+
629+
def run(self):
630+
SnowflakeConnection.setup_ocsp_privatelink(self.client_name, self.hostname)
631+
ocsp_cache_server = os.getenv("SF_OCSP_RESPONSE_CACHE_SERVER_URL", None)
632+
if ocsp_cache_server is not None and ocsp_cache_server !=\
633+
self.expectation:
634+
print("Got {0} Expected {1}".format(ocsp_cache_server, self.expectation))
635+
self.bucket.put("Fail")
636+
else:
637+
self.bucket.put("Success")

0 commit comments

Comments
 (0)