Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions lib/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -52,8 +53,10 @@ Client.prototype.apiCall = function (method, path, params, callback) {
'host': this.host,
'method': method,
'path': path,
'headers': headers,
'ca': constants.DUO_PINNED_CERT
'headers': headers
}
if (this.enableCAPinning) {
Comment thread
cisco-annikiti marked this conversation as resolved.
options.ca = constants.DUO_PINNED_CERT
}
_request_with_backoff(options, body, callback)
}
Expand Down
46 changes: 46 additions & 0 deletions tests/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -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'
Expand Down Expand Up @@ -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, undefined)
done()
})
})
})
Loading