Skip to content

Commit

Permalink
Added the ability for users to specify a CA bundle for HTTPS requests (
Browse files Browse the repository at this point in the history
  • Loading branch information
barrybarrette authored and childish-sambino committed Sep 26, 2019
1 parent 2c3f9e7 commit 45440e8
Show file tree
Hide file tree
Showing 7 changed files with 87 additions and 0 deletions.
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,12 @@ TypeScript is supported for TypeScript version 2.9 and above.

Check out these [code examples](examples) in JavaScript and TypeScript to get up and running quickly.

### Environment Variables

`twilio-node` supports credential storage in environment variables. If no credentials are provided when instantiating the Twilio client (e.g., `const client = require('twilio')();`), the values in following env vars will be used: `TWILIO_ACCOUNT_SID` and `TWILIO_AUTH_TOKEN`.

If your environment requires SSL decryption, you can set the path to CA bundle in the env var `TWILIO_CA_BUNDLE`.

## Docker Image

The `Dockerfile` present in this repository and its respective `twilio/twilio-node` Docker image are currently used by Twilio for testing purposes only.
Expand Down
4 changes: 4 additions & 0 deletions examples/example.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ var Twilio = require('../lib');
var accountSid = process.env.TWILIO_ACCOUNT_SID;
var token = process.env.TWILIO_AUTH_TOKEN;

// Uncomment the following line to specify a custom CA bundle for HTTPS requests:
// process.env.TWILIO_CA_BUNDLE = '/path/to/cert.pem';
// You can also set this as a regular environment variable outside of the code

var twilio = new Twilio(accountSid, token);

var i = 0;
Expand Down
9 changes: 9 additions & 0 deletions lib/base/RequestClient.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

var _ = require('lodash');
var http = require('request');
var fs = require('fs');
var Q = require('q');
var Response = require('../http/response');
var Request = require('../http/request');
Expand Down Expand Up @@ -53,6 +54,13 @@ RequestClient.prototype.request = function(opts) {
forever: opts.forever === false ? false : true,
};

if (process.env.TWILIO_CA_BUNDLE !== undefined) {
if (this.ca === undefined) {
this.ca = fs.readFileSync(process.env.TWILIO_CA_BUNDLE);
}
options.ca = this.ca;
}

if (!_.isNull(opts.data)) {
options.formData = opts.data;
}
Expand All @@ -69,6 +77,7 @@ RequestClient.prototype.request = function(opts) {
params: options.qs,
data: options.formData,
headers: options.headers,
ca: options.ca
};

var _this = this;
Expand Down
1 change: 1 addition & 0 deletions lib/http/request.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ var Request = function(opts) {
this.params = opts.params || this.ANY;
this.data = opts.data || this.ANY;
this.headers = opts.headers || this.ANY;
this.ca = opts.ca;
};

Request.prototype.ANY = '*';
Expand Down
6 changes: 6 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
"jasmine": "^3.4.0",
"jsdoc": "^3.6.3",
"jshint": "^2.10.2",
"mock-fs": "^4.10.1",
"node-mocks-http": "^1.8.0",
"proxyquire": "1.8.0",
"typescript": "^2.8.3"
Expand Down
60 changes: 60 additions & 0 deletions spec/unit/base/RequestClient.spec.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
var mockfs = require('mock-fs');
var proxyquire = require('proxyquire');

describe('lastResponse and lastRequest defined', function() {
Expand Down Expand Up @@ -85,3 +86,62 @@ describe('lastRequest defined, lastResponse undefined', function() {
});

});

describe('User specified CA bundle', function() {
var client;
beforeEach(function() {
RequestClientMock = proxyquire('../../../lib/base/RequestClient', {
request: function (options, callback) {
callback('failed', null);
},
});

client = new RequestClientMock();

options = {
method: 'GET',
uri: 'test-uri',
username: 'test-username',
password: 'test-password',
headers: {'test-header-key': 'test-header-value'},
params: {'test-param-key': 'test-param-value'},
data: {'test-data-key': 'test-data-value'}
};

mockfs({
'/path/to/ca': {
'test-ca.pem': 'test ca data'
}
});
});

afterEach(function () {
mockfs.restore();
});

it('should not modify CA if not specified', function() {
client.request(options);
expect(client.lastRequest.ca).toBeUndefined();
});

it('should use CA if it is specified', function() {
process.env.TWILIO_CA_BUNDLE = '/path/to/ca/test-ca.pem';
client.request(options);
expect(client.lastRequest.ca.toString()).toEqual('test ca data');
delete process.env.TWILIO_CA_BUNDLE;
});

it('should cache the CA after loading it for the first time', function () {
process.env.TWILIO_CA_BUNDLE = '/path/to/ca/test-ca.pem';
client.request(options);
mockfs({
'/path/to/ca': {
'test-ca.pem': null
}
});
client.request(options);
expect(client.lastRequest.ca.toString()).toEqual('test ca data');
delete process.env.TWILIO_CA_BUNDLE;
})

});

0 comments on commit 45440e8

Please sign in to comment.