Skip to content
This repository has been archived by the owner on Apr 2, 2019. It is now read-only.

Commit

Permalink
Add headerBlacklist option
Browse files Browse the repository at this point in the history
  • Loading branch information
sktt committed Feb 3, 2017
1 parent 1d562e9 commit 4676725
Show file tree
Hide file tree
Showing 4 changed files with 62 additions and 7 deletions.
2 changes: 2 additions & 0 deletions api.md
Expand Up @@ -30,6 +30,7 @@ Handles logging, caching and checking for blocked requets.
| config | <code>object</code> | |
| config.apiKey | <code>string</code> | AccessWatch api key |
| config.cache | <code>[Cache](#AccessWatch.Cache)</code> | A cache for storing sessions. |
| [config.headerBlacklist] | <code>Array.&lt;String&gt;</code> | A list of headers that must never be sent to the AccessWatch service. By default Cookie and Authorization are omitted. The headers are case insensitive. |
| [config.fwdHeaders] | <code>AccessWatch.ForwardHeaders</code> | Specify custom proxy header names. It is necessary to set this if the server is behind a reverse proxy. Use pass a custom object or the predefined `AccessWatch.fwdHeaders` which should sufficient for most cases. |
| [config.apiBase] | <code>string</code> | A custom api base url, may be useful for testing and debugging. |

Expand Down Expand Up @@ -58,6 +59,7 @@ Look up a Session from cache or api with a node request
### accessWatch.checkBlocked(req) ⇒ <code>Promise.&lt;boolean&gt;</code>
Check if a request should be blocked by checking for the requestSignature
in the cache.

NOTE: If its a cache miss, default will be `false` since we should never
add extra latency to the response times or making it dependent on the
access watch api service.
Expand Down
12 changes: 10 additions & 2 deletions index.js
Expand Up @@ -42,7 +42,9 @@
*/

const crypto = require('crypto');
const request = require('request-promise');
const omit = require('lodash.omit');
const promisify = require('./promisify');
const request = promisify(require('request'));

const API_BASE = 'https://access.watch/api/1.0';

Expand Down Expand Up @@ -82,6 +84,9 @@ class AccessWatch {
* @param {object} config
* @param {string} config.apiKey AccessWatch api key
* @param {AccessWatch.Cache} config.cache A cache for storing sessions.
* @param {Array<String>} [config.headerBlacklist] A list of headers that must
* never be sent to the AccessWatch service. By default Cookie and
* Authorization are omitted. The headers are case insensitive.
* @param {AccessWatch.ForwardHeaders} [config.fwdHeaders] Specify custom
* proxy header names. It is necessary to set this if the server is behind a
* reverse proxy. Use pass a custom object or the predefined
Expand All @@ -101,6 +106,8 @@ class AccessWatch {
this.apiKey = config.apiKey;
this.apiBase = config.apiBase || API_BASE;
this.fwdHeaders = config.fwdHeaders || {};
this.headerBlacklist = (config.headerBlacklist || ['Cookie', 'Authorization'])
.map(header => header.toLowerCase()); // we always keep headers lowercase!

this.cache = {
get: promisify(config.cache.get, config.cache),
Expand Down Expand Up @@ -179,6 +186,7 @@ class AccessWatch {
/**
* Check if a request should be blocked by checking for the requestSignature
* in the cache.
*
* NOTE: If its a cache miss, default will be `false` since we should never
* add extra latency to the response times or making it dependent on the
* access watch api service.
Expand Down Expand Up @@ -230,7 +238,7 @@ class AccessWatch {
// 80 or 443.
port: (forwarded.host || req.headers['host']).split(':')[1],
url: req.url,
headers: req.headers
headers: omit(req.headers, this.headerBlacklist)
},
response: {
status: res.statusCode
Expand Down
3 changes: 2 additions & 1 deletion package.json
Expand Up @@ -19,7 +19,8 @@
"author": "johannes@access.watch",
"license": "MIT",
"dependencies": {
"request-promise": "^4.1.1"
"lodash.omit": "^4.5.0",
"request": "^2.79.0"
},
"devDependencies": {
"coveralls": "^2.11.12",
Expand Down
52 changes: 48 additions & 4 deletions test.js
Expand Up @@ -216,14 +216,15 @@ test('lookupSession(req, noCache) find a session. cache and api', childTest => {
});

test('log(req, res) logs a request and response', childTest => {
childTest.plan(2);
childTest.plan(3);
const fakeReq = {
httpVersion: '999',
headers: {
host: 'localhost',
'x-forwarded-for': '1.2.3.4, 2.2.2.2, 3.3.3.3',
'x-forwarded-proto': 'https',
'x-forwarded-host': 'access.watch'
'x-forwarded-host': 'access.watch',
'cookie': 'dont include me plz'
},
socket: {
remoteAddress: '127.0.0.1',
Expand All @@ -248,7 +249,11 @@ test('log(req, res) logs a request and response', childTest => {
t.assert(body.request.scheme === 'https');
t.assert(body.request.host === 'access.watch');
t.assert(body.request.url === '/some/url');
t.same(body.request.headers, fakeReq.headers);
t.assert(body.request.headers['cookie'] === undefined);
t.same(
Object.keys(body.request.headers).length,
Object.keys(fakeReq.headers).length - 1 // cookie header was omitted
);
t.assert(body.response.status === 123);
return 200;
});
Expand All @@ -258,6 +263,41 @@ test('log(req, res) logs a request and response', childTest => {
.catch(t.fail);
});

childTest.test('it uses headerBlacklist', t => {
const fakeReq = {
httpVersion: '999',
headers: {
host: 'localhost',
one: '1',
two: '1',
three: '1',
cookie: 'i can be included'
},
socket: {
remoteAddress: '127.0.0.1',
encrypted: false
},
url: '/some/url'
};

const aw = getTestInstance({
headerBlacklist: ['one', 'TWO', 'tHree']
});

nock(aw.apiBase)
.post('/log')
.reply((uri, body) => {
t.assert(body.request.headers['one'] === undefined);
t.assert(body.request.headers['three'] === undefined);
t.assert(body.request.headers['three'] === undefined);
t.assert(body.request.headers['cookie'] === 'i can be included');
});

return aw.log(fakeReq, fakeRes)
.then(_ => t.end())
.catch(t.fail);
});

childTest.test('without fwdHeaders', t => {
const aw = getTestInstance();

Expand All @@ -269,7 +309,11 @@ test('log(req, res) logs a request and response', childTest => {
t.assert(body.request.scheme === 'http');
t.assert(body.request.host === 'localhost');
t.assert(body.request.url === '/some/url');
t.same(body.request.headers, fakeReq.headers);
t.assert(body.request.headers['cookie'] === undefined);
t.same(
Object.keys(body.request.headers).length,
Object.keys(fakeReq.headers).length - 1
);
t.assert(body.response.status === 123);
return 200;
});
Expand Down

0 comments on commit 4676725

Please sign in to comment.