Skip to content

Commit

Permalink
Add AwsSigV4 signing functionality (opensearch-project#279)
Browse files Browse the repository at this point in the history
* Add AwsSigV4 signing functionality

Signed-off-by: Harsha Vamsi Kalluri <[email protected]>

* Adlicense text to signer types

Signed-off-by: Harsha Vamsi Kalluri <[email protected]>

* Pulling aws signer into separate namespace

Signed-off-by: Harsha Vamsi Kalluri <[email protected]>

* Adding separate injection point for v4Signer

Signed-off-by: Harsha Vamsi Kalluri <[email protected]>

* Fix name spacing and bump version

Signed-off-by: Harsha Vamsi Kalluri <[email protected]>

* Typo in readme

Signed-off-by: Harsha Vamsi Kalluri <[email protected]>

* Adding 0BSD to allow license

Signed-off-by: Harsha Vamsi Kalluri <[email protected]>

* Split code snippets into USER GUIDE

Signed-off-by: Harsha Vamsi Kalluri <[email protected]>

* Remove un-used package and update license

Signed-off-by: Harsha Vamsi Kalluri <[email protected]>

* Fix language in user guide

Signed-off-by: Harsha Vamsi Kalluri <[email protected]>

* Add types to dev dependencies

Signed-off-by: Harsha Vamsi Kalluri <[email protected]>

* Update USER_GUIDE.md

Co-authored-by: Graeme <[email protected]>
Signed-off-by: Harsha Vamsi Kalluri <[email protected]>

* add credentials refresh options

Signed-off-by: rawpixel-vincent <[email protected]>

* fix AwsSigv4Signer type with Promise

Signed-off-by: rawpixel-vincent <[email protected]>

* remove JSDoc

Signed-off-by: rawpixel-vincent <[email protected]>

* update example usage

Signed-off-by: rawpixel-vincent <[email protected]>

* update credentials refresh strategy

Signed-off-by: rawpixel-vincent <[email protected]>

* update credentials refresh and expiration

Signed-off-by: rawpixel-vincent <[email protected]>

* fix types

Signed-off-by: rawpixel-vincent <[email protected]>

* add failure to refresh credentials test case

Signed-off-by: rawpixel-vincent <[email protected]>

* cleanup and comments

Signed-off-by: rawpixel-vincent <[email protected]>

* clarify code example in the docs

Signed-off-by: rawpixel-vincent <[email protected]>

* remove explicit async from code example

Signed-off-by: rawpixel-vincent <[email protected]>

* remove unused credentialsState.acquiredAt

Signed-off-by: rawpixel-vincent <[email protected]>

* Minor doc and misc fixes

Signed-off-by: Harsha Vamsi Kalluri <[email protected]>

Signed-off-by: Harsha Vamsi Kalluri <[email protected]>
Signed-off-by: rawpixel-vincent <[email protected]>
Co-authored-by: Graeme <[email protected]>
Co-authored-by: rawpixel-vincent <[email protected]>
(cherry picked from commit 70a26d3)
  • Loading branch information
harshavamsi committed Feb 21, 2023
1 parent 4457548 commit ddd4356
Show file tree
Hide file tree
Showing 4 changed files with 257 additions and 253 deletions.
112 changes: 58 additions & 54 deletions lib/aws/AwsSigv4Signer.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,112 +9,116 @@
* GitHub history for details.
*/

'use strict'
const Connection = require('../Connection')
const Transport = require('../Transport')
const aws4 = require('aws4')
const AwsSigv4SignerError = require('./errors')
'use strict';
const Connection = require('../Connection');
const Transport = require('../Transport');
const aws4 = require('aws4');
const AwsSigv4SignerError = require('./errors');

function AwsSigv4Signer (opts) {
function AwsSigv4Signer(opts) {
const credentialsState = {
credentials: null
}
credentials: null,
};
if (opts && (!opts.region || opts.region === null || opts.region === '')) {
throw new AwsSigv4SignerError('Region cannot be empty')
throw new AwsSigv4SignerError('Region cannot be empty');
}
if (opts && typeof opts.getCredentials !== 'function') {
throw new AwsSigv4SignerError('getCredentials function is required')
throw new AwsSigv4SignerError('getCredentials function is required');
}

function buildSignedRequestObject (request = {}) {
request.service = 'es'
request.region = opts.region
request.headers = request.headers || {}
request.headers.host = request.hostname
return aws4.sign(request, credentialsState.credentials)
function buildSignedRequestObject(request = {}) {
request.service = 'es';
request.region = opts.region;
request.headers = request.headers || {};
request.headers['host'] = request.hostname;
return aws4.sign(request, credentialsState.credentials);
}

class AwsSigv4SignerConnection extends Connection {
buildRequestObject (params) {
const request = super.buildRequestObject(params)
return buildSignedRequestObject(request)
buildRequestObject(params) {
const request = super.buildRequestObject(params);
return buildSignedRequestObject(request);
}
}

class AwsSigv4SignerTransport extends Transport {
request (params, options = {}, callback = undefined) {
request(params, options = {}, callback = undefined) {
// options is optional so if options is a function, it's the callback.
if (typeof options === 'function') {
callback = options
options = {}
callback = options;
options = {};
}

const currentCredentials = credentialsState.credentials
let expired = false
const currentCredentials = credentialsState.credentials;
let expired = false;
if (!currentCredentials) {
// Credentials haven't been acquired yet.
expired = true
} else if (typeof currentCredentials.needsRefresh === 'function') {
// AWS SDK V2, needsRefresh should be available.
expired = currentCredentials.needsRefresh()
} else if (currentCredentials.expired === true) {
// AWS SDK V2, alternative to needsRefresh.
expired = true
} else if (currentCredentials.expireTime && currentCredentials.expireTime < new Date()) {
// AWS SDK V2, alternative to needsRefresh and expired.
expired = true
} else if (currentCredentials.expiration && currentCredentials.expiration < new Date()) {
// AWS SDK V3, Credentials.expiration is a Date object
expired = true
expired = true;
}
// AWS SDK V2, needsRefresh should be available.
else if (typeof currentCredentials.needsRefresh === 'function') {
expired = currentCredentials.needsRefresh();
}
// AWS SDK V2, alternative to needsRefresh.
else if (currentCredentials.expired === true) {
expired = true;
}
// AWS SDK V2, alternative to needsRefresh and expired.
else if (currentCredentials.expireTime && currentCredentials.expireTime < new Date()) {
expired = true;
}
// AWS SDK V3, Credentials.expiration is a Date object
else if (currentCredentials.expiration && currentCredentials.expiration < new Date()) {
expired = true;
}

if (!expired) {
if (typeof callback === 'undefined') {
return super.request(params, options)
return super.request(params, options);
}
super.request(params, options, callback)
return
super.request(params, options, callback);
return;
}

// In AWS SDK V2 Credentials.refreshPromise should be available.
if (currentCredentials && typeof currentCredentials.refreshPromise === 'function') {
if (typeof callback === 'undefined') {
return currentCredentials.refreshPromise().then(() => {
return super.request(params, options)
})
return super.request(params, options);
});
} else {
currentCredentials
.refreshPromise()
.then(() => {
super.request(params, options, callback)
super.request(params, options, callback);
})
.catch(callback)
return
.catch(callback);
return;
}
}

// For AWS SDK V3 or when the client has not acquired credentials yet.
if (typeof callback === 'undefined') {
return opts.getCredentials().then((credentials) => {
credentialsState.credentials = credentials
return super.request(params, options)
})
credentialsState.credentials = credentials;
return super.request(params, options);
});
} else {
opts
.getCredentials()
.then((credentials) => {
credentialsState.credentials = credentials
super.request(params, options, callback)
credentialsState.credentials = credentials;
super.request(params, options, callback);
})
.catch(callback)
.catch(callback);
}
}
}

return {
Transport: AwsSigv4SignerTransport,
Connection: AwsSigv4SignerConnection,
buildSignedRequestObject
}
buildSignedRequestObject,
};
}
module.exports = AwsSigv4Signer
module.exports = AwsSigv4Signer;
18 changes: 9 additions & 9 deletions lib/aws/errors.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,17 @@
* GitHub history for details.
*/

'use strict'
const { OpenSearchClientError } = require('../errors')
'use strict';
const { OpenSearchClientError } = require('../errors');

class AwsSigv4SignerError extends OpenSearchClientError {
constructor (message, data) {
super(message, data)
Error.captureStackTrace(this, AwsSigv4SignerError)
this.name = 'AwsSigv4SignerError'
this.message = message || 'AwsSigv4Signer Error'
this.data = data
constructor(message, data) {
super(message, data);
Error.captureStackTrace(this, AwsSigv4SignerError);
this.name = 'AwsSigv4SignerError';
this.message = message || 'AwsSigv4Signer Error';
this.data = data;
}
}

module.exports = AwsSigv4SignerError
module.exports = AwsSigv4SignerError;
10 changes: 5 additions & 5 deletions lib/aws/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,12 @@
* GitHub history for details.
*/

'use strict'
'use strict';

const AwsSigv4Signer = require('./AwsSigv4Signer')
const AwsSigv4SignerError = require('./errors')
const AwsSigv4Signer = require('./AwsSigv4Signer');
const AwsSigv4SignerError = require('./errors');

module.exports = {
AwsSigv4Signer,
AwsSigv4SignerError
}
AwsSigv4SignerError,
};
Loading

0 comments on commit ddd4356

Please sign in to comment.