Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Normalize URLs in HMAC interceptor #114

Merged
merged 2 commits into from
Jan 10, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
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
25 changes: 18 additions & 7 deletions lib/gp-hmac.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,10 @@
* limitations under the License.
*/

var crypto = require('crypto');
/* eslint no-console: "off" */

const crypto = require('crypto');
const url = require('url');
/**
* @author Steven R. Loomis
* @ignore
Expand All @@ -36,13 +38,14 @@ GaasHmac.prototype.user = undefined;
GaasHmac.prototype.secret = undefined;

GaasHmac.prototype.AUTH_SCHEME = "GaaS-HMAC";
// GaasHmac.prototype.AUTH_SCHEME = "GP-HMAC";
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we should switch the scheme in the future?

GaasHmac.prototype.SEP = "\n";
GaasHmac.prototype.ENC = "ascii"; // ISO-8859-1 not supported!
GaasHmac.prototype.HMAC_SHA1_ALGORITHM = 'sha1'; // "HmacSHA1";
GaasHmac.prototype.forceDate = null;
GaasHmac.prototype.forceDateString = null;

// GaasHmac.prototype.VERBOSE = process.env.GP_VERBOSE || false;
GaasHmac.prototype.VERBOSE = process.env.GP_VERBOSE || false;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was mostly disabled because of the lint rule, but I fixed the lint rule.


function rfc1123date(d) {
return d.toUTCString();
Expand Down Expand Up @@ -82,8 +85,17 @@ function rfc1123date(d) {
* The Date: header is required for HMAC.
*/
GaasHmac.prototype.apply = function(obj) {
//if(this.VERBOSE) console.dir(obj, {color: true, depth: null});
if(this.VERBOSE) console.dir(obj, {color: true, depth: null});
if(obj.url.indexOf("/swagger.json") !== -1) return obj; // skip for swagger.json

const href = url.parse(obj.url).href;
if(href !== obj.url) {
if(this.VERBOSE) console.log('hmac: Warn: normalized', obj.url, '->', href);
// For example, if there is a quote (') in the URL, it will turn into %27
// AFTER this interceptor is called (by Fetch).
obj.url = href;
}

var dateString = (this.forceDateString ||
rfc1123date(this.forceDate || new Date()));
var bodyString = "";
Expand All @@ -98,15 +110,14 @@ GaasHmac.prototype.apply = function(obj) {
obj.url + this.SEP +
dateString + this.SEP +
bodyString;
//if(this.VERBOSE) console.log('hmacText = <<' + hmacText + '>>');
//var hmacBuffer = new Buffer(hmacText, this.ENC);
if(this.VERBOSE) console.log('hmacText = <<' + hmacText + '>>');

var hmacHash = crypto.createHmac(this.HMAC_SHA1_ALGORITHM, this.secretBuffer )
.update(hmacText, 'utf8')
.digest('base64');
//if(this.VERBOSE) console.log('hmacHash = ' + hmacHash );
if(this.VERBOSE) console.log('hmacHash = ' + hmacHash );
var hmacHeader = this.AUTH_SCHEME + ' ' + this.user + ':' + hmacHash;
//if(this.VERBOSE) console.log('hmacHeader = ' + hmacHeader);
if(this.VERBOSE) console.log('hmacHeader = ' + hmacHeader);
obj.headers.Authorization = hmacHeader;
obj.headers.Date = dateString;
return obj;
Expand Down
17 changes: 16 additions & 1 deletion test/client-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ var NO_DELETE = process.env.NO_DELETE || false;
if(VERBOSE) console.dir(module.filename);

var projectId = process.env.GP_PROJECT || 'MyHLProject'+Math.random();
const projectId_space = projectId+'_space';
// var projectId2 = process.env.GP_PROJECT2 || 'MyOtherHLProject'+Math.random();
var projectId3 = process.env.GP_PROJECT3 || 'MyUserProject'+Math.random();
var projectId4 = process.env.GP_PROJECT3 || 'MyUpdatedProject'+Math.random();
Expand Down Expand Up @@ -371,6 +372,11 @@ describe('gaasClient.bundle()', function() {
targetLanguages: [gaasTest.TARGETS[0],gaasTest.CYRILLIC],
notes: ['Note to self'] });
});
it('Should let us create ' + projectId_space, () =>
gaasClient
.bundle({id: projectId_space, serviceInstance: instanceName})
.create({sourceLanguage: 'en', targetLanguages: []}));

// Create some strings for later
it('Should let us create ' + projectId4, function() {
var proj = gaasClient.bundle({id:projectId4, serviceInstance: instanceName});
Expand Down Expand Up @@ -467,7 +473,10 @@ describe('gaasClient.bundle()', function() {
return done();
});
});

it('Should let us upload to ' + projectId_space, () =>
gaasClient
.bundle({id: projectId_space, serviceInstance: instanceName})
.uploadStrings({ languageId: 'en', strings: { "I' d_2dd7f01d": 'I’m sorry, Dave.' }}));

if(DELAY_AVAIL) it('should let us verify the target entry(qru).key1 is in progress', function(done) {
var proj = gaasClient.bundle({id:projectId, serviceInstance: instanceName});
Expand Down Expand Up @@ -530,6 +539,12 @@ describe('gaasClient.bundle()', function() {
done();
});
});
it('Should let us verfy ' + projectId_space, () =>
gaasClient
.bundle({id: projectId_space, serviceInstance: instanceName})
.getResourceEntryInfo({languageId: 'en', resourceKey: "I' d_2dd7f01d"})
.then(((data) => expect(data.resourceEntry.value).to.contain('Dave'))));

it('should let us verify some source entries', function(done) {
var bund = gaasClient.bundle({id:projectId, serviceInstance: instanceName});
var entry = bund.entry({languageId:gaasTest.SOURCES[0],resourceKey:'key1'});
Expand Down
26 changes: 26 additions & 0 deletions test/hmac-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,32 @@ describe('lib/gaas-hmac', function() {
expect(obj.headers.Date).to.be.ok;
expect(obj.headers.Date).to.equal(myHmac.forceDateString);
});
it('Should verify that we can apply with a spacious key body (golden test)', function() {
var myHmac = new GaasHmac('MyAuth', 'MyUser', 'MySecret');

expect(myHmac).to.be.ok;
expect(myHmac.name).to.be.ok;
expect(myHmac.name).to.equal('MyAuth');

var obj = {
method: 'GET',
url: "https://example.com/translate/rest/19e7b569069447b6b1f7bbdf8106decc/v2/bundles/mybundle/fr/I'%20d_2dd7f01d", // This gets escaped to I%27%20 …
headers: {
Authorization: undefined
},
body: '{"param":"value"}'
};

// we must force the Date so that we have a consistent test.
myHmac.forceDateString = "Mon, 30 Jun 2014 00:00:00 GMT"; // Bluemix launch date
expect(myHmac.apply(obj)).to.be.ok;

expect(obj.headers.Authorization).to.be.ok;
expect(obj.headers.Authorization).to.equal(
'GaaS-HMAC MyUser:6iqc3pISoVrgGLMzxhZ9jujUm64=');
expect(obj.headers.Date).to.be.ok;
expect(obj.headers.Date).to.equal(myHmac.forceDateString);
});
it('Should verify that we can apply with undefined body', function() {
var myHmac = new GaasHmac('MyAuth', 'MyUser', 'MySecret');

Expand Down