|
7 | 7 |
|
8 | 8 | import logging |
9 | 9 | import os |
| 10 | +import platform |
10 | 11 | import time |
11 | 12 | from concurrent.futures.thread import ThreadPoolExecutor |
12 | 13 | from os import environ, path |
13 | 14 | from unittest import mock |
14 | 15 |
|
| 16 | +try: |
| 17 | + from snowflake.connector.util_text import random_string |
| 18 | +except ImportError: |
| 19 | + from ..randomize import random_string |
| 20 | + |
15 | 21 | import pytest |
16 | 22 |
|
17 | 23 | import snowflake.connector.ocsp_snowflake |
@@ -62,6 +68,41 @@ def overwrite_ocsp_cache(tmpdir): |
62 | 68 | THIS_DIR = path.dirname(path.realpath(__file__)) |
63 | 69 |
|
64 | 70 |
|
| 71 | +@pytest.fixture(autouse=True) |
| 72 | +def random_ocsp_response_validation_cache(): |
| 73 | + file_path = { |
| 74 | + "linux": os.path.join( |
| 75 | + "~", |
| 76 | + ".cache", |
| 77 | + "snowflake", |
| 78 | + f"ocsp_response_validation_cache{random_string()}", |
| 79 | + ), |
| 80 | + "darwin": os.path.join( |
| 81 | + "~", |
| 82 | + "Library", |
| 83 | + "Caches", |
| 84 | + "Snowflake", |
| 85 | + f"ocsp_response_validation_cache{random_string()}", |
| 86 | + ), |
| 87 | + "windows": os.path.join( |
| 88 | + "~", |
| 89 | + "AppData", |
| 90 | + "Local", |
| 91 | + "Snowflake", |
| 92 | + "Caches", |
| 93 | + f"ocsp_response_validation_cache{random_string()}", |
| 94 | + ), |
| 95 | + } |
| 96 | + yield SFDictFileCache( |
| 97 | + entry_lifetime=3600, |
| 98 | + file_path=file_path, |
| 99 | + ) |
| 100 | + try: |
| 101 | + os.unlink(file_path[platform.system().lower()]) |
| 102 | + except BaseException: |
| 103 | + pass |
| 104 | + |
| 105 | + |
65 | 106 | def test_ocsp(): |
66 | 107 | """OCSP tests.""" |
67 | 108 | # reset the memory cache |
@@ -209,73 +250,81 @@ def test_ocsp_with_file_cache(tmpdir): |
209 | 250 |
|
210 | 251 |
|
211 | 252 | @pytest.mark.skipolddriver |
212 | | -def test_ocsp_with_bogus_cache_files(tmpdir): |
213 | | - from snowflake.connector.ocsp_snowflake import OCSPResponseValidationResult |
214 | | - |
215 | | - """Attempts to use bogus OCSP response data.""" |
216 | | - cache_file_name, target_hosts = _store_cache_in_file(tmpdir) |
| 253 | +def test_ocsp_with_bogus_cache_files(tmpdir, random_ocsp_response_validation_cache): |
| 254 | + with mock.patch( |
| 255 | + "snowflake.connector.ocsp_snowflake.OCSP_RESPONSE_VALIDATION_CACHE", |
| 256 | + random_ocsp_response_validation_cache, |
| 257 | + ): |
| 258 | + from snowflake.connector.ocsp_snowflake import OCSPResponseValidationResult |
217 | 259 |
|
218 | | - ocsp = SFOCSP() |
219 | | - OCSPCache.read_ocsp_response_cache_file(ocsp, cache_file_name) |
220 | | - cache_data = snowflake.connector.ocsp_snowflake.OCSP_RESPONSE_VALIDATION_CACHE |
221 | | - assert cache_data, "more than one cache entries should be stored." |
222 | | - |
223 | | - # setting bogus data |
224 | | - current_time = int(time.time()) |
225 | | - for k, _ in cache_data.items(): |
226 | | - cache_data[k] = OCSPResponseValidationResult( |
227 | | - ocsp_response=b"bogus", |
228 | | - ts=current_time, |
229 | | - validated=True, |
230 | | - ) |
| 260 | + """Attempts to use bogus OCSP response data.""" |
| 261 | + cache_file_name, target_hosts = _store_cache_in_file(tmpdir) |
231 | 262 |
|
232 | | - # write back the cache file |
233 | | - OCSPCache.CACHE = cache_data |
234 | | - OCSPCache.write_ocsp_response_cache_file(ocsp, cache_file_name) |
235 | | - |
236 | | - # forces to use the bogus cache file but it should raise errors |
237 | | - SnowflakeOCSP.clear_cache() |
238 | | - ocsp = SFOCSP() |
239 | | - for hostname in target_hosts: |
240 | | - connection = _openssl_connect(hostname) |
241 | | - assert ocsp.validate(hostname, connection), "Failed to validate: {}".format( |
242 | | - hostname |
243 | | - ) |
| 263 | + ocsp = SFOCSP() |
| 264 | + OCSPCache.read_ocsp_response_cache_file(ocsp, cache_file_name) |
| 265 | + cache_data = snowflake.connector.ocsp_snowflake.OCSP_RESPONSE_VALIDATION_CACHE |
| 266 | + assert cache_data, "more than one cache entries should be stored." |
| 267 | + |
| 268 | + # setting bogus data |
| 269 | + current_time = int(time.time()) |
| 270 | + for k, _ in cache_data.items(): |
| 271 | + cache_data[k] = OCSPResponseValidationResult( |
| 272 | + ocsp_response=b"bogus", |
| 273 | + ts=current_time, |
| 274 | + validated=True, |
| 275 | + ) |
| 276 | + |
| 277 | + # write back the cache file |
| 278 | + OCSPCache.CACHE = cache_data |
| 279 | + OCSPCache.write_ocsp_response_cache_file(ocsp, cache_file_name) |
| 280 | + |
| 281 | + # forces to use the bogus cache file but it should raise errors |
| 282 | + SnowflakeOCSP.clear_cache() |
| 283 | + ocsp = SFOCSP() |
| 284 | + for hostname in target_hosts: |
| 285 | + connection = _openssl_connect(hostname) |
| 286 | + assert ocsp.validate(hostname, connection), "Failed to validate: {}".format( |
| 287 | + hostname |
| 288 | + ) |
244 | 289 |
|
245 | 290 |
|
246 | 291 | @pytest.mark.skipolddriver |
247 | | -def test_ocsp_with_outdated_cache(tmpdir): |
248 | | - from snowflake.connector.ocsp_snowflake import OCSPResponseValidationResult |
249 | | - |
250 | | - """Attempts to use outdated OCSP response cache file.""" |
251 | | - cache_file_name, target_hosts = _store_cache_in_file(tmpdir) |
| 292 | +def test_ocsp_with_outdated_cache(tmpdir, random_ocsp_response_validation_cache): |
| 293 | + with mock.patch( |
| 294 | + "snowflake.connector.ocsp_snowflake.OCSP_RESPONSE_VALIDATION_CACHE", |
| 295 | + random_ocsp_response_validation_cache, |
| 296 | + ): |
| 297 | + from snowflake.connector.ocsp_snowflake import OCSPResponseValidationResult |
252 | 298 |
|
253 | | - ocsp = SFOCSP() |
| 299 | + """Attempts to use outdated OCSP response cache file.""" |
| 300 | + cache_file_name, target_hosts = _store_cache_in_file(tmpdir) |
254 | 301 |
|
255 | | - # reading cache file |
256 | | - OCSPCache.read_ocsp_response_cache_file(ocsp, cache_file_name) |
257 | | - cache_data = snowflake.connector.ocsp_snowflake.OCSP_RESPONSE_VALIDATION_CACHE |
258 | | - assert cache_data, "more than one cache entries should be stored." |
259 | | - |
260 | | - # setting outdated data |
261 | | - current_time = int(time.time()) |
262 | | - for k, v in cache_data.items(): |
263 | | - cache_data[k] = OCSPResponseValidationResult( |
264 | | - ocsp_response=v.ocsp_response, |
265 | | - ts=current_time - 144 * 60 * 60, |
266 | | - validated=True, |
267 | | - ) |
268 | | - |
269 | | - # write back the cache file |
270 | | - OCSPCache.CACHE = cache_data |
271 | | - OCSPCache.write_ocsp_response_cache_file(ocsp, cache_file_name) |
| 302 | + ocsp = SFOCSP() |
272 | 303 |
|
273 | | - # forces to use the bogus cache file but it should raise errors |
274 | | - SnowflakeOCSP.clear_cache() # reset the memory cache |
275 | | - SFOCSP() |
276 | | - assert ( |
277 | | - SnowflakeOCSP.cache_size() == 0 |
278 | | - ), "must be empty. outdated cache should not be loaded" |
| 304 | + # reading cache file |
| 305 | + OCSPCache.read_ocsp_response_cache_file(ocsp, cache_file_name) |
| 306 | + cache_data = snowflake.connector.ocsp_snowflake.OCSP_RESPONSE_VALIDATION_CACHE |
| 307 | + assert cache_data, "more than one cache entries should be stored." |
| 308 | + |
| 309 | + # setting outdated data |
| 310 | + current_time = int(time.time()) |
| 311 | + for k, v in cache_data.items(): |
| 312 | + cache_data[k] = OCSPResponseValidationResult( |
| 313 | + ocsp_response=v.ocsp_response, |
| 314 | + ts=current_time - 144 * 60 * 60, |
| 315 | + validated=True, |
| 316 | + ) |
| 317 | + |
| 318 | + # write back the cache file |
| 319 | + OCSPCache.CACHE = cache_data |
| 320 | + OCSPCache.write_ocsp_response_cache_file(ocsp, cache_file_name) |
| 321 | + |
| 322 | + # forces to use the bogus cache file but it should raise errors |
| 323 | + SnowflakeOCSP.clear_cache() # reset the memory cache |
| 324 | + SFOCSP() |
| 325 | + assert ( |
| 326 | + SnowflakeOCSP.cache_size() == 0 |
| 327 | + ), "must be empty. outdated cache should not be loaded" |
279 | 328 |
|
280 | 329 |
|
281 | 330 | def _store_cache_in_file(tmpdir, target_hosts=None): |
@@ -312,16 +361,22 @@ def test_ocsp_with_invalid_cache_file(): |
312 | 361 | "snowflake.connector.ocsp_snowflake.SnowflakeOCSP._fetch_ocsp_response", |
313 | 362 | side_effect=BrokenPipeError("fake error"), |
314 | 363 | ) |
315 | | -def test_ocsp_cache_when_server_is_down(mock_fetch_ocsp_response, tmpdir): |
316 | | - ocsp = SFOCSP() |
| 364 | +def test_ocsp_cache_when_server_is_down( |
| 365 | + mock_fetch_ocsp_response, tmpdir, random_ocsp_response_validation_cache |
| 366 | +): |
| 367 | + with mock.patch( |
| 368 | + "snowflake.connector.ocsp_snowflake.OCSP_RESPONSE_VALIDATION_CACHE", |
| 369 | + random_ocsp_response_validation_cache, |
| 370 | + ): |
| 371 | + ocsp = SFOCSP() |
317 | 372 |
|
318 | | - """Attempts to use outdated OCSP response cache file.""" |
319 | | - cache_file_name, target_hosts = _store_cache_in_file(tmpdir) |
| 373 | + """Attempts to use outdated OCSP response cache file.""" |
| 374 | + cache_file_name, target_hosts = _store_cache_in_file(tmpdir) |
320 | 375 |
|
321 | | - # reading cache file |
322 | | - OCSPCache.read_ocsp_response_cache_file(ocsp, cache_file_name) |
323 | | - cache_data = snowflake.connector.ocsp_snowflake.OCSP_RESPONSE_VALIDATION_CACHE |
324 | | - assert not cache_data, "no cache should present because of broken pipe" |
| 376 | + # reading cache file |
| 377 | + OCSPCache.read_ocsp_response_cache_file(ocsp, cache_file_name) |
| 378 | + cache_data = snowflake.connector.ocsp_snowflake.OCSP_RESPONSE_VALIDATION_CACHE |
| 379 | + assert not cache_data, "no cache should present because of broken pipe" |
325 | 380 |
|
326 | 381 |
|
327 | 382 | def test_concurrent_ocsp_requests(tmpdir): |
|
0 commit comments