def test_ocsp_with_outdated_cache(tmpdir): """ Attempt to use outdated OCSP response cache file """ cache_file_name, target_hosts = _store_cache_in_file(tmpdir) ocsp = SFOCSP(ocsp_response_cache_uri='file://' + cache_file_name) # reading cache file OCSPCache.read_ocsp_response_cache_file(ocsp, cache_file_name) cache_data = OCSPCache.CACHE assert cache_data, "more than one cache entries should be stored." # setting outdated data current_time = int(time.time()) for k, v in cache_data.items(): cache_data[k] = (current_time - 48 * 60 * 60, v[1]) # write back the cache file OCSPCache.CACHE = cache_data OCSPCache.write_ocsp_response_cache_file(ocsp, cache_file_name) # forces to use the bogus cache file but it should raise errors SnowflakeOCSP.clear_cache() # reset the memory cache SFOCSP(ocsp_response_cache_uri='file://' + cache_file_name) assert SnowflakeOCSP.cache_size() == 0, \ 'must be empty. outdated cache should not be loaded'
def test_ocsp_cache_merge(tmpdir): """ Merge two OCSP response cache files """ previous_cache_filename = path.join(str(tmpdir), 'cache_file1.txt') _store_cache_in_file(tmpdir, target_hosts=TARGET_HOSTS[0:3], filename=previous_cache_filename) current_cache_filename = path.join(str(tmpdir), 'cache_file2.txt') _store_cache_in_file(tmpdir, target_hosts=TARGET_HOSTS[4:], filename=current_cache_filename) latest_cache_filename = path.join(str(tmpdir), 'cache_file.txt') SnowflakeOCSP.clear_cache() # reset the memory cache ocsp = SFOCSP() OCSPCache.merge_cache(ocsp, previous_cache_filename, current_cache_filename, latest_cache_filename) with codecs.open(previous_cache_filename) as f: prev = json.load(f) with codecs.open(current_cache_filename) as f: curr = json.load(f) with codecs.open(latest_cache_filename) as f: latest = json.load(f) assert len(latest) > len(prev) assert len(latest) > len(curr)
def test_ocsp_cache_merge(tmpdir): """Merges two OCSP response cache files.""" previous_folder = tmpdir.mkdir('previous') previous_cache_filename, _ = _store_cache_in_file( previous_folder, target_hosts=TARGET_HOSTS[0:3]) current_folder = tmpdir.mkdir('current') current_cache_filename, _ = _store_cache_in_file( current_folder, target_hosts=TARGET_HOSTS[4:]) latest_folder = tmpdir.mkdir('latest') latest_cache_filename = path.join(str(latest_folder), 'cache_file.txt') SnowflakeOCSP.clear_cache() # reset the memory cache ocsp = SFOCSP() OCSPCache.merge_cache(ocsp, previous_cache_filename, current_cache_filename, latest_cache_filename) with codecs.open(previous_cache_filename) as f: prev = json.load(f) with codecs.open(current_cache_filename) as f: curr = json.load(f) with codecs.open(latest_cache_filename) as f: latest = json.load(f) assert len(latest) > len(prev) assert len(latest) > len(curr)
def test_ocsp_with_bogus_cache_files(tmpdir): """ Attempt to use bogus OCSP response data """ cache_file_name, target_hosts = _store_cache_in_file(tmpdir) ocsp = SFOCSP(ocsp_response_cache_uri='file://' + cache_file_name) OCSPCache.read_ocsp_response_cache_file(ocsp, cache_file_name) cache_data = OCSPCache.CACHE assert cache_data, "more than one cache entries should be stored." # setting bogus data current_time = int(time.time()) for k, v in cache_data.items(): cache_data[k] = (current_time, b'bogus') # write back the cache file OCSPCache.CACHE = cache_data OCSPCache.write_ocsp_response_cache_file(ocsp, cache_file_name) # forces to use the bogus cache file but it should raise errors SnowflakeOCSP.clear_cache() ocsp = SFOCSP(ocsp_response_cache_uri='file://' + cache_file_name) for hostname in target_hosts: connection = _openssl_connect(hostname) assert ocsp.validate(hostname, connection), \ 'Failed to validate: {0}'.format(hostname)
def ocsp_reset(tmpdir): # Reset OCSP cache location before each test if "SF_OCSP_RESPONSE_CACHE_DIR" in os.environ: del os.environ["SF_OCSP_RESPONSE_CACHE_DIR"] os.environ["SF_OCSP_RESPONSE_CACHE_DIR"] = str( tmpdir.join(random_string(5))) OCSPCache.reset_cache_dir()
def test_ocsp_cache_merge(tmpdir): """ Merges two OCSP response cache files. First create the entire cache for all hosts. Split the created cache into two caches Merge the two caches. This is to prevent us from doing multiple cache creations as the results are not predictable due to OCSP responder shenanigans """ cache_folder = tmpdir.mkdir("caches") cache_filename, _ = _store_cache_in_file( cache_folder, target_hosts=TARGET_HOSTS) previous_folder = tmpdir.mkdir('previous') previous_cache_filename = path.join(str(previous_folder), 'ocsp_response_cache.json') current_folder = tmpdir.mkdir('current') current_cache_filename = path.join(str(current_folder), 'ocsp_response_cache.json') prev_cache = {} current_cache = {} with codecs.open(cache_filename) as cf: orig_cache = json.load(cf) counter = 0 for certid, arr in orig_cache.items(): if counter < 1: prev_cache.update({certid: arr}) else: current_cache.update({certid: arr}) counter += 1 with open(previous_cache_filename, 'w') as prev_cache_fp: json.dump(prev_cache, prev_cache_fp) with open(current_cache_filename, 'w') as curr_cache_fp: json.dump(current_cache, curr_cache_fp) latest_folder = tmpdir.mkdir('latest') latest_cache_filename = path.join(str(latest_folder), 'cache_file.txt') SnowflakeOCSP.clear_cache() # reset the memory cache ocsp = SFOCSP() OCSPCache.merge_cache( ocsp, previous_cache_filename, current_cache_filename, latest_cache_filename) with codecs.open(previous_cache_filename) as f: prev = json.load(f) with codecs.open(current_cache_filename) as f: curr = json.load(f) with codecs.open(latest_cache_filename) as f: latest = json.load(f) assert len(latest) > len(prev) assert len(latest) > len(curr)
def test_ocsp_bad_validity(): SnowflakeOCSP.clear_cache() environ["SF_OCSP_TEST_MODE"] = "true" environ["SF_TEST_OCSP_FORCE_BAD_RESPONSE_VALIDITY"] = "true" OCSPCache.del_cache_file() ocsp = SFOCSP(use_ocsp_cache_server=False) connection = _openssl_connect("snowflake.okta.com") assert ocsp.validate("snowflake.okta.com", connection), "Connection should have passed with fail open" del environ['SF_OCSP_TEST_MODE'] del environ['SF_TEST_OCSP_FORCE_BAD_RESPONSE_VALIDITY']
def _store_cache_in_file(tmpdir, target_hosts=None): if target_hosts is None: target_hosts = TARGET_HOSTS os.environ['SF_OCSP_RESPONSE_CACHE_DIR'] = str(tmpdir) OCSPCache.reset_cache_dir() filename = path.join(str(tmpdir), 'ocsp_response_cache.json') # cache OCSP response SnowflakeOCSP.clear_cache() ocsp = SFOCSP(ocsp_response_cache_uri='file://' + filename, use_ocsp_cache_server=False) for hostname in target_hosts: connection = _openssl_connect(hostname) assert ocsp.validate(hostname, connection), \ 'Failed to validate: {}'.format(hostname) assert path.exists(filename), "OCSP response cache file" return filename, target_hosts
def test_ocsp_fail_open_w_single_endpoint(): SnowflakeOCSP.clear_cache() OCSPCache.del_cache_file() environ["SF_OCSP_TEST_MODE"] = "true" environ["SF_TEST_OCSP_URL"] = "http://httpbin.org/delay/10" environ["SF_TEST_CA_OCSP_RESPONDER_CONNECTION_TIMEOUT"] = "5" ocsp = SFOCSP(use_ocsp_cache_server=False) connection = _openssl_connect("snowflake.okta.com") try: assert ocsp.validate("snowflake.okta.com", connection), \ 'Failed to validate: {0}'.format("snowflake.okta.com") finally: del environ['SF_OCSP_TEST_MODE'] del environ['SF_TEST_OCSP_URL'] del environ['SF_TEST_CA_OCSP_RESPONDER_CONNECTION_TIMEOUT']
def test_ocsp_fail_close_w_single_endpoint(): SnowflakeOCSP.clear_cache() environ["SF_OCSP_TEST_MODE"] = "true" environ["SF_TEST_OCSP_URL"] = "http://httpbin.org/delay/10" environ["SF_TEST_CA_OCSP_RESPONDER_CONNECTION_TIMEOUT"] = "5" OCSPCache.del_cache_file() ocsp = SFOCSP(use_ocsp_cache_server=False, use_fail_open=False) connection = _openssl_connect("snowflake.okta.com") with pytest.raises(RevocationCheckError) as ex: ocsp.validate("snowflake.okta.com", connection) try: assert ex.value.errno == ER_INVALID_OCSP_RESPONSE_CODE, "Connection should have failed" finally: del environ['SF_OCSP_TEST_MODE'] del environ['SF_TEST_OCSP_URL'] del environ['SF_TEST_CA_OCSP_RESPONDER_CONNECTION_TIMEOUT']
def test_ocsp_wo_cache_file(): """ OCSP tests without File cache. NOTE: Use /etc as a readonly directory such that no cache file is used. """ # reset the memory cache SnowflakeOCSP.clear_cache() OCSPCache.del_cache_file() environ['SF_OCSP_RESPONSE_CACHE_DIR'] = '/etc' OCSPCache.reset_cache_dir() try: ocsp = SFOCSP() for url in TARGET_HOSTS: connection = _openssl_connect(url) assert ocsp.validate(url, connection), \ 'Failed to validate: {0}'.format(url) finally: del environ['SF_OCSP_RESPONSE_CACHE_DIR'] OCSPCache.reset_cache_dir()
def cleanup(): # Reset OCSP cache location before each test if 'SF_OCSP_RESPONSE_CACHE_DIR' in os.environ: del os.environ['SF_OCSP_RESPONSE_CACHE_DIR'] OCSPCache.reset_cache_dir()
def test_building_retry_url(): # privatelink retry url OCSPCache.ACTIVATE_SSD = False OCSPCache.RETRY_URL_PATTERN = None OCSPCache.CACHE_SERVER_URL = \ 'http://ocsp.us-east-1.snowflakecomputing.com/ocsp_response_cache.json' OCSPCache._reset_ocsp_dynamic_cache_server_url() assert OCSPCache.RETRY_URL_PATTERN == \ 'http://ocsp.us-east-1.snowflakecomputing.com/retry/{0}/{1}' # privatelink retry url with port OCSPCache.ACTIVATE_SSD = False OCSPCache.RETRY_URL_PATTERN = None OCSPCache.CACHE_SERVER_URL = \ 'http://ocsp.us-east-1.snowflakecomputing.com:80/ocsp_response_cache' \ '.json' OCSPCache._reset_ocsp_dynamic_cache_server_url() assert OCSPCache.RETRY_URL_PATTERN == \ 'http://ocsp.us-east-1.snowflakecomputing.com:80/retry/{0}/{1}' # non-privatelink retry url OCSPCache.ACTIVATE_SSD = False OCSPCache.RETRY_URL_PATTERN = None OCSPCache.CACHE_SERVER_URL = \ 'http://ocsp.snowflakecomputing.com/ocsp_response_cache.json' OCSPCache._reset_ocsp_dynamic_cache_server_url() assert OCSPCache.RETRY_URL_PATTERN is None # non-privatelink retry url with port OCSPCache.ACTIVATE_SSD = False OCSPCache.RETRY_URL_PATTERN = None OCSPCache.CACHE_SERVER_URL = \ 'http://ocsp.snowflakecomputing.com:80/ocsp_response_cache.json' OCSPCache._reset_ocsp_dynamic_cache_server_url() assert OCSPCache.RETRY_URL_PATTERN is None # ssd enabled for privatelink retry url OCSPCache.ACTIVATE_SSD = True OCSPCache.RETRY_URL_PATTERN = None OCSPCache.CACHE_SERVER_URL = \ 'http://ocsp.us-east-1.snowflakecomputing.com/ocsp_response_cache.json' OCSPCache._reset_ocsp_dynamic_cache_server_url() assert OCSPCache.RETRY_URL_PATTERN == \ 'http://ocsp.us-east-1.snowflakecomputing.com/retry' # ssd enabled for privatelink retry url with port OCSPCache.ACTIVATE_SSD = True OCSPCache.RETRY_URL_PATTERN = None OCSPCache.CACHE_SERVER_URL = \ 'http://ocsp.us-east-1.snowflakecomputing.com:80/ocsp_response_cache' \ '.json' OCSPCache._reset_ocsp_dynamic_cache_server_url() assert OCSPCache.RETRY_URL_PATTERN == \ 'http://ocsp.us-east-1.snowflakecomputing.com:80/retry' # ssd enabled for non-privatelink OCSPCache.ACTIVATE_SSD = True OCSPCache.RETRY_URL_PATTERN = None OCSPCache.CACHE_SERVER_URL = \ 'http://ocsp.snowflakecomputing.com/ocsp_response_cache.json' OCSPCache._reset_ocsp_dynamic_cache_server_url() assert OCSPCache.RETRY_URL_PATTERN == \ 'http://ocsp.snowflakecomputing.com/retry' # ssd enabled for non-privatelink with port OCSPCache.ACTIVATE_SSD = True OCSPCache.RETRY_URL_PATTERN = None OCSPCache.CACHE_SERVER_URL = \ 'http://ocsp.snowflakecomputing.com:80/ocsp_response_cache.json' OCSPCache._reset_ocsp_dynamic_cache_server_url() assert OCSPCache.RETRY_URL_PATTERN == \ 'http://ocsp.snowflakecomputing.com/retry'