diff --git a/lib/agent/check.js b/lib/agent/check.js index 44f715cfd..3d8df616c 100644 --- a/lib/agent/check.js +++ b/lib/agent/check.js @@ -29,8 +29,7 @@ const rfc2560 = require('asn1.js-rfc2560'); const Util = require('../util'); const CertUtil = require('./cert_util'); -const Errors = require('../errors'); -const ErrorCodes = Errors.codes; +const GlobalConfig = require('../global_config'); const Logger = require('../logger'); @@ -48,7 +47,7 @@ module.exports = function check(options, cb) { var sync = true; var req; - const maxNumRetries = 10; + const maxNumRetries = GlobalConfig.getOcspMode() === GlobalConfig.ocspModes.FAIL_CLOSED ? 10 : 3; function done(err, data) { diff --git a/lib/agent/ocsp_response_cache.js b/lib/agent/ocsp_response_cache.js index 453164d9f..141cfef60 100644 --- a/lib/agent/ocsp_response_cache.js +++ b/lib/agent/ocsp_response_cache.js @@ -67,7 +67,7 @@ function OcspResponseCache() } catch (e) { - Logger.getInstance().debug("Failed to read a OCSP cache file. %s", e); + Logger.getInstance().debug("Failed to read OCSP cache file: %s, err: %s", cacheFileName, e); } /** @@ -107,7 +107,14 @@ function OcspResponseCache() }); const writeContent = JSON.stringify(cacheOutput); Logger.getInstance().debug("Writing OCSP cache file. %s", cacheFileName); - fs.writeFileSync(cacheFileName, writeContent, 'utf-8'); + try + { + fs.writeFileSync(cacheFileName, writeContent, 'utf-8'); + } + catch (e) + { + Logger.getInstance().debug("Failed to update OCSP cache file: %s, err: %s", cacheFileName, e); + } cacheUpdated = false; } }; @@ -162,7 +169,7 @@ function OcspResponseCache() if (err) { Logger.getInstance() - .debug("Failed to download a OCSP cache file. %s. Ignored", err); + .debug("Failed to download OCSP cache file. %s. Ignored", err); return cb(err, false); } try @@ -229,7 +236,7 @@ function OcspResponseCache() catch (e) { Logger.getInstance() - .debug("failed to delete cache file. %s, %s", cacheFileName, e); + .debug("Failed to delete OCSP cache file: %s, err: %s", cacheFileName, e); } }; diff --git a/lib/agent/socket_util.js b/lib/agent/socket_util.js index 4f82bb4b2..9e5635221 100644 --- a/lib/agent/socket_util.js +++ b/lib/agent/socket_util.js @@ -21,8 +21,6 @@ const ocspFailOpenWarning = const rawOcspFlag = process.env.SF_OCSP_RESPONSE_CACHE_SERVER_ENABLED; -let ocspResponseCache; - const variables = { SF_OCSP_RESPONSE_CACHE_SERVER_ENABLED: !rawOcspFlag || rawOcspFlag && rawOcspFlag.toLowerCase() !== "false", diff --git a/lib/global_config.js b/lib/global_config.js index 4ed700158..9dffd9ffd 100644 --- a/lib/global_config.js +++ b/lib/global_config.js @@ -103,31 +103,38 @@ exports.getOcspResponseCacheMaxAge = function () */ exports.mkdirCacheDir = function () { - var homeDir = Os.homedir(); - if (!Util.exists(homeDir)) + let cacheRootDir = process.env.SF_OCSP_RESPONSE_CACHE_DIR; + if (!Util.exists(cacheRootDir)) { - homeDir = Os.tmpdir(); // fallback to TMP if user home doesn't exist. + cacherootDir = Os.homedir(); + } + if (!Util.exists(cacheRootDir)) + { + cacheRootDir = Os.tmpdir(); // fallback to TMP if user home doesn't exist. } var cacheDir; const platform = Os.platform(); if (platform === 'darwin') { - cacheDir = Path.join(homeDir, "Library", "Caches", "Snowflake"); + cacheDir = Path.join(cacheRootDir, "Library", "Caches", "Snowflake"); } else if (platform === 'win32') { - cacheDir = Path.join(homeDir, "AppData", "Local", "Snowflake", "Caches"); + cacheDir = Path.join(cacheRootDir, "AppData", "Local", "Snowflake", "Caches"); } else { // linux - cacheDir = Path.join(homeDir, ".cache", "snowflake"); + cacheDir = Path.join(cacheRootDir, ".cache", "snowflake"); + } + try + { + Mkdirp.sync(cacheDir); } - let err = Mkdirp.sync(cacheDir); - if (err) + catch (e) { - Logger.getInstance().debug("Failed to create a cache directory: %s", err); + Logger.getInstance().debug("Failed to create a cache directory %s, err: %s", cacheDir, e); } return cacheDir; }; diff --git a/package.json b/package.json index d22ef140b..e9e589319 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "snowflake-sdk", - "version": "1.2.1", + "version": "1.2.2", "description": "Node.js driver for Snowflake", "dependencies": { "agent-base": "^2.1.1", @@ -19,6 +19,7 @@ "request": "^2.88.0", "simple-lru-cache": "^0.0.2", "uuid": "^3.3.2", + "lodash": "^4.17.15", "winston": "^3.1.0" }, "devDependencies": { diff --git a/test/integration/testOcsp.js b/test/integration/testOcsp.js index f1a62e7a9..2546ac027 100644 --- a/test/integration/testOcsp.js +++ b/test/integration/testOcsp.js @@ -1,6 +1,7 @@ /* * Copyright (c) 2015-2019 Snowflake Computing Inc. All rights reserved. */ +const Os = require('os'); const async = require('async'); const assert = require('assert'); const snowflake = require('./../../lib/snowflake'); @@ -112,6 +113,14 @@ describe('OCSP validation', function () } + function deleteCache() + { + if (SocketUtil.variables.OCSP_RESPONSE_CACHE) + { + SocketUtil.variables.OCSP_RESPONSE_CACHE.deleteCache(); + } + } + it('Test Ocsp with different endpoints', function (done) { const testOptions = function (i) @@ -124,61 +133,113 @@ describe('OCSP validation', function () it('Test Ocsp with different endpoints - force to download cache', function (done) { - if (SocketUtil.variables.OCSP_RESPONSE_CACHE) + deleteCache(); + SocketUtil.variables.OCSP_RESPONSE_CACHE = undefined; + + function cleanup() { - SocketUtil.variables.OCSP_RESPONSE_CACHE.deleteCache(); + deleteCache(); + done(); } - SocketUtil.variables.OCSP_RESPONSE_CACHE = undefined; const testOptions = function (i) { const connection = snowflake.createConnection(httpsEndpoints[i]); - connectToHttpsEndpoint(testOptions, i, connection, done) + connectToHttpsEndpoint(testOptions, i, connection, cleanup) }; testOptions(0); }); it('Test Ocsp with different endpoints - download cache in FAIL_CLOSED', function (done) { - if (SocketUtil.variables.OCSP_RESPONSE_CACHE) + deleteCache(); + SocketUtil.variables.OCSP_RESPONSE_CACHE = undefined; + + function cleanup() { - SocketUtil.variables.OCSP_RESPONSE_CACHE.deleteCache(); + deleteCache(); + snowflake.configure({ocspFailOpen: true}); + done(); } - SocketUtil.variables.OCSP_RESPONSE_CACHE = undefined; const testOptions = function (i) { snowflake.configure({ocspFailOpen: false}); const connection = snowflake.createConnection(httpsEndpoints[i]); - connectToHttpsEndpoint(testOptions, i, connection, done) - snowflake.configure({ocspFailOpen: true}); + connectToHttpsEndpoint(testOptions, i, connection, cleanup); }; testOptions(0); }); - it('Test Ocsp with different endpoints - no cache server or file', function (done) + it('Test Ocsp with different endpoints - no cache server in FAIL_CLOSED', function (done) { - if (SocketUtil.variables.OCSP_RESPONSE_CACHE) + deleteCache(); + SocketUtil.variables.OCSP_RESPONSE_CACHE = undefined; + SocketUtil.variables.SF_OCSP_RESPONSE_CACHE_SERVER_ENABLED = false; + + function cleanup() { - SocketUtil.variables.OCSP_RESPONSE_CACHE.deleteCache(); + deleteCache(); + SocketUtil.variables.SF_OCSP_RESPONSE_CACHE_SERVER_ENABLED = true; + snowflake.configure({ocspFailOpen: true}); + done(); } + + const testOptions = function (i) + { + snowflake.configure({ocspFailOpen: false}); + const connection = snowflake.createConnection(httpsEndpoints[i]); + connectToHttpsEndpoint(testOptions, i, connection, cleanup); + }; + testOptions(0); + }); + + it('Test Ocsp with different endpoints - no cache server or file', function (done) + { + deleteCache(); SocketUtil.variables.OCSP_RESPONSE_CACHE = undefined; SocketUtil.variables.SF_OCSP_RESPONSE_CACHE_SERVER_ENABLED = false; - function resetCacheServer() + function cleanup() { SocketUtil.variables.SF_OCSP_RESPONSE_CACHE_SERVER_ENABLED = true; + deleteCache(); done(); } const testOptions = function (i) { const connection = snowflake.createConnection(httpsEndpoints[i]); - connectToHttpsEndpoint(testOptions, i, connection, resetCacheServer) + connectToHttpsEndpoint(testOptions, i, connection, cleanup); }; testOptions(0); }); + it('Test Ocsp with different endpoints - no cache directory access', function (done) + { + const platform = Os.platform(); + if (platform === "linux") + { + deleteCache(); + SocketUtil.variables.OCSP_RESPONSE_CACHE = undefined; + process.env['SF_OCSP_RESPONSE_CACHE_DIR'] = '/usr'; + + function cleanup() + { + delete process.env['SF_OCSP_RESPONSE_CACHE_DIR']; + deleteCache(); + done(); + } + + const testOptions = function (i) + { + const connection = snowflake.createConnection(httpsEndpoints[i]); + connectToHttpsEndpoint(testOptions, i, connection, cleanup); + }; + testOptions(0); + } + }); + it('Test OCSP with different OCSP modes enabled', function (done) { const globalOptions = [