diff --git a/lib/main.js b/lib/main.js index 3394b9f..d899f0b 100644 --- a/lib/main.js +++ b/lib/main.js @@ -7,11 +7,12 @@ const _PACKAGE_VERSION = require('../package.json').version const SIGNATURE_VERSION_2 = 2 const SIGNATURE_VERSION_5 = 5 -function Client (ikey, skey, host, sigVersion = SIGNATURE_VERSION_2) { +function Client (ikey, skey, host, sigVersion = SIGNATURE_VERSION_2, enableCAPinning = true) { this.ikey = ikey this.skey = skey this.host = host this.sigVersion = sigVersion + this.enableCAPinning = enableCAPinning } Client.prototype.apiCall = function (method, path, params, callback) { @@ -53,7 +54,10 @@ Client.prototype.apiCall = function (method, path, params, callback) { 'method': method, 'path': path, 'headers': headers, - 'ca': constants.DUO_PINNED_CERT + 'rejectUnauthorized': true + } + if (this.enableCAPinning) { + options.ca = constants.DUO_PINNED_CERT } _request_with_backoff(options, body, callback) } diff --git a/tests/main.js b/tests/main.js index 407bb4f..a5daad3 100644 --- a/tests/main.js +++ b/tests/main.js @@ -2,8 +2,10 @@ var assert = require('assert') var nock = require('nock') var sinon = require('sinon') +var https = require('https') var duo_api = require('../lib/main.js') var duo_sig = require('../lib/duo_sig') +var constants = require('../lib/constants') var IKEY = 'DIXXXXXXXXXXXXXXXXXX' var SKEY = 'deadbeefdeadbeefdeadbeefdeadbeefdeadbeef' @@ -189,3 +191,47 @@ describe('Signature Checks', function () { }) }) }) + +describe('CA Pinning Configuration', function () { + var requestSpy + + beforeEach(function () { + requestSpy = sinon.spy(https, 'request') + nock('https://' + API_HOSTNAME) + .get('/foo/bar') + .reply(200, {'response': {foo: 'bar'}, stat: 'OK'}) + }) + + afterEach(function () { + requestSpy.restore() + }) + + it('CA pinning is enabled by default', function (done) { + var client = new duo_api.Client(IKEY, SKEY, API_HOSTNAME) + assert.strictEqual(client.enableCAPinning, true) + client.jsonApiCall('GET', '/foo/bar', {}, function (resp) { + var options = requestSpy.firstCall.args[0] + assert.strictEqual(options.ca, constants.DUO_PINNED_CERT) + done() + }) + }) + + it('CA pinning can be disabled via constructor parameter', function (done) { + var client = new duo_api.Client(IKEY, SKEY, API_HOSTNAME, duo_api.SIGNATURE_VERSION_2, false) + assert.strictEqual(client.enableCAPinning, false) + client.jsonApiCall('GET', '/foo/bar', {}, function (resp) { + var options = requestSpy.firstCall.args[0] + assert.strictEqual(options.ca, undefined) + done() + }) + }) + + it('TLS verification is still enforced when CA pinning is disabled', function (done) { + var client = new duo_api.Client(IKEY, SKEY, API_HOSTNAME, duo_api.SIGNATURE_VERSION_2, false) + client.jsonApiCall('GET', '/foo/bar', {}, function (resp) { + var options = requestSpy.firstCall.args[0] + assert.strictEqual(options.rejectUnauthorized, true) + done() + }) + }) +})