diff --git a/lib/auth/auth.js b/lib/auth/auth.js index ac9503d25..99011d490 100644 --- a/lib/auth/auth.js +++ b/lib/auth/auth.js @@ -10,18 +10,15 @@ const constructStringToSignV4 = require('./v4/constructStringToSign'); const convertUTCtoISO8601 = require('./v4/timeUtils').convertUTCtoISO8601; const crypto = require('crypto'); const vaultUtilities = require('./in_memory/vaultUtilities'); - +let vault = require('./vault'); const auth = {}; auth.setAuthHandler = handler => { - authV2.headerAuthCheck.setAuthHandler(handler); - authV2.queryAuthCheck.setAuthHandler(handler); - authV4.headerAuthCheck.setAuthHandler(handler); - authV4.queryAuthCheck.setAuthHandler(handler); + vault = handler; return auth; }; -auth.doAuth = (request, log, cb, awsService, data) => { +auth.check = (request, log, awsService, data) => { log.debug('running auth checks', { method: 'auth' }); const authHeader = request.headers.authorization; // Check whether signature is in header @@ -31,41 +28,64 @@ auth.doAuth = (request, log, cb, awsService, data) => { // handle temporary security credentials if (authHeader.startsWith('AWS ')) { log.trace('authenticating request with auth v2 using headers'); - authV2.headerAuthCheck.check(request, log, cb); + return authV2.headerAuthCheck.check(request, log, data); } else if (authHeader.startsWith('AWS4')) { log.debug('authenticating request with Auth V4 using headers'); - authV4.headerAuthCheck.check(request, log, cb, awsService); - } else { - log.warn('missing authorization security header'); - return cb(errors.MissingSecurityHeader); + return authV4.headerAuthCheck.check(request, log, awsService); } + log.warn('missing authorization security header'); + return { err: errors.MissingSecurityHeader }; } else if (data.Signature) { // Check whether signature is in query string log.trace('authenticating request with auth v2 using query string'); - authV2.queryAuthCheck.check(request, log, data, cb); + return authV2.queryAuthCheck.check(request, log, data); } else if (data['X-Amz-Algorithm']) { log.debug('authenticating request with Auth v4 using query string'); - authV4.queryAuthCheck.check(request, log, data, cb); - } else { - // If no auth information is provided in request, then - // user is part of 'All Users Group' so send back this - // group as the canonicalID - log.trace('No authentication provided. User identified as public'); - const authInfo = new AuthInfo({ canonicalID: constants.publicId }); - return cb(null, authInfo); + return authV4.queryAuthCheck.check(request, log, data); + } + // If no auth information is provided in request, then + // user is part of 'All Users Group' so send back this + // group as the canonicalID + log.trace('No authentication provided. User identified as public'); + const authInfo = new AuthInfo({ canonicalID: constants.publicId }); + return { err: null, data: authInfo }; +}; + +auth.doAuth = (request, log, cb, awsService, data) => { + const res = auth.check(request, log, awsService, data); + if (res.err) { + return cb(res.err); + } else if (res.version === 2) { + return vault.authenticateV2Request(res.data.accessKey, + res.data.signatureFromRequest, + res.data.stringToSign, res.data.algo, log, + (err, authInfo) => { + if (err) { + return cb(err); + } + return cb(null, authInfo); + }); + } else if (res.version === 4) { + res.data.log = log; + return vault.authenticateV4Request(res.data, cb, awsService); + } else if (res.data instanceof AuthInfo) { + return cb(null, res.data); } - return undefined; + log.error('Cannot found authentification method', { + method: 'Arsenal.auth.doAuth', + }); + return cb(errors.InternalError); }; auth.generateV4Headers = - (request, data, accessKey, secretKeyValue) => { + (request, data, accessKey, secretKeyValue, awsService) => { Object.assign(request, { headers: {} }); const amzDate = convertUTCtoISO8601(Date.now()); // get date without time const scopeDate = amzDate.slice(0, amzDate.indexOf('T')); const signedHeaders = 'host;x-amz-date;x-amz-content-sha256'; const region = 'us-east-1'; - const service = 'iam'; + const service = awsService || 'iam'; const credentialScope = `${scopeDate}/${region}/${service}/aws4_request`; const timestamp = amzDate; @@ -91,7 +111,8 @@ auth.generateV4Headers = const stringToSign = constructStringToSignV4(params); const signingKey = vaultUtilities.calculateSigningKey(secretKeyValue, region, - scopeDate); + scopeDate, + service); const signature = crypto.createHmac('sha256', signingKey) .update(stringToSign).digest('hex'); const authorizationHeader = `${algorithm} Credential=${accessKey}` + diff --git a/lib/auth/in_memory/vaultUtilities.js b/lib/auth/in_memory/vaultUtilities.js index ca5dd66c4..6a10c4dd0 100644 --- a/lib/auth/in_memory/vaultUtilities.js +++ b/lib/auth/in_memory/vaultUtilities.js @@ -17,15 +17,16 @@ function hashSignature(stringToSign, secretKey, algorithm) { * @param {string} secretKey - requester's secretKey * @param {string} region - region included in request * @param {string} scopeDate - scopeDate included in request + * @param {string} [service] - To specify another service than s3 * @return {string} signingKey - signingKey to calculate signature */ -function calculateSigningKey(secretKey, region, scopeDate) { +function calculateSigningKey(secretKey, region, scopeDate, service) { const dateKey = crypto.createHmac('sha256', `AWS4${secretKey}`) .update(scopeDate).digest('binary'); const dateRegionKey = crypto.createHmac('sha256', dateKey) .update(region).digest('binary'); const dateRegionServiceKey = crypto.createHmac('sha256', dateRegionKey) - .update('s3').digest('binary'); + .update(service || 's3').digest('binary'); const signingKey = crypto.createHmac('sha256', dateRegionServiceKey) .update('aws4_request').digest('binary'); return signingKey; diff --git a/lib/auth/v2/headerAuthCheck.js b/lib/auth/v2/headerAuthCheck.js index 90bf77c47..dec339c99 100644 --- a/lib/auth/v2/headerAuthCheck.js +++ b/lib/auth/v2/headerAuthCheck.js @@ -5,16 +5,9 @@ const constructStringToSign = require('./constructStringToSign'); const checkRequestExpiry = require('./checkRequestExpiry'); const algoCheck = require('./algoCheck'); -let vault = require('../vault'); - const headerAuthCheck = {}; -headerAuthCheck.setAuthHandler = handler => { - vault = handler; - return headerAuthCheck; -}; - -headerAuthCheck.check = (request, log, callback) => { +headerAuthCheck.check = (request, log, data) => { log.trace('running header auth check'); const headers = request.headers; @@ -24,13 +17,13 @@ headerAuthCheck.check = (request, log, callback) => { timestamp = Date.parse(timestamp); if (!timestamp) { log.warn('missing security header: invalid date/timestamp'); - return callback(errors.MissingSecurityHeader); + return { err: errors.MissingSecurityHeader }; } const timeout = checkRequestExpiry(timestamp, log); if (timeout) { log.warn('request time too skewed', { timestamp }); - return callback(errors.RequestTimeTooSkewed); + return { err: errors.RequestTimeTooSkewed }; } // Authorization Header should be // in the format of 'AWS AccessKey:Signature' @@ -38,37 +31,40 @@ headerAuthCheck.check = (request, log, callback) => { if (!authInfo) { log.warn('missing authorization security header'); - return callback(errors.MissingSecurityHeader); + return { err: errors.MissingSecurityHeader }; } const semicolonIndex = authInfo.indexOf(':'); if (semicolonIndex < 0) { log.warn('invalid authorization header', { authInfo }); - return callback(errors.MissingSecurityHeader); + return { err: errors.MissingSecurityHeader }; } const accessKey = semicolonIndex > 4 ? authInfo.substring(4, semicolonIndex).trim() : undefined; if (typeof accessKey !== 'string' || accessKey.length === 0) { log.trace('invalid authorization header', { authInfo }); - return callback(errors.MissingSecurityHeader); + return { err: errors.MissingSecurityHeader }; } log.addDefaultFields({ accessKey }); const signatureFromRequest = authInfo.substring(semicolonIndex + 1).trim(); log.trace('signature from request', { signatureFromRequest }); - const stringToSign = constructStringToSign(request, log); + const stringToSign = constructStringToSign(request, data, log); log.trace('constructed string to sign', { stringToSign }); const algo = algoCheck(signatureFromRequest.length); log.trace('algo for calculating signature', { algo }); if (algo === undefined) { - return callback(errors.InvalidArgument); + return { err: errors.InvalidArgument }; } - return vault.authenticateV2Request(accessKey, - signatureFromRequest, stringToSign, algo, log, (err, authInfo) => { - if (err) { - return callback(err); - } - return callback(null, authInfo); - }); + return { + err: null, + version: 2, + data: { + accessKey, + signatureFromRequest, + stringToSign, + algo, + }, + }; }; module.exports = headerAuthCheck; diff --git a/lib/auth/v2/queryAuthCheck.js b/lib/auth/v2/queryAuthCheck.js index acce42baf..8e47e1a02 100644 --- a/lib/auth/v2/queryAuthCheck.js +++ b/lib/auth/v2/queryAuthCheck.js @@ -1,27 +1,19 @@ 'use strict'; // eslint-disable-line strict -const errors = require('../../../index').errors; +const errors = require('../../errors'); const algoCheck = require('./algoCheck'); const constructStringToSign = require('./constructStringToSign'); const checkRequestExpiry = require('./checkRequestExpiry'); -let vault = require('../vault'); - const queryAuthCheck = {}; -queryAuthCheck.setAuthHandler = handler => { - vault = handler; - return queryAuthCheck; -}; - -queryAuthCheck.check = (request, log, data, callback) => { +queryAuthCheck.check = (request, log, data) => { log.trace('running query auth check'); if (request.method === 'POST') { log.warn('query string auth not supported for post requests'); - return callback(errors.NotImplemented); + return { err: errors.NotImplemented }; } - /* Check whether request has expired or if expires parameter is more than 15 minutes in the future. @@ -33,11 +25,11 @@ queryAuthCheck.check = (request, log, data, callback) => { if (isNaN(expirationTime)) { log.warn('invalid expires parameter', { expires: data.Expires }); - return callback(errors.MissingSecurityHeader); + return { err: errors.MissingSecurityHeader }; } const timeout = checkRequestExpiry(expirationTime, log); if (timeout) { - return callback(errors.RequestTimeTooSkewed); + return { err: errors.RequestTimeTooSkewed }; } const accessKey = data.AWSAccessKeyId; log.addDefaultFields({ accessKey }); @@ -46,23 +38,25 @@ queryAuthCheck.check = (request, log, data, callback) => { log.trace('signature from request', { signatureFromRequest }); if (!accessKey || !signatureFromRequest) { log.warn('invalid access key/signature parameters'); - return callback(errors.MissingSecurityHeader); + return { err: errors.MissingSecurityHeader }; } const stringToSign = constructStringToSign(request, data, log); log.trace('constructed string to sign', { stringToSign }); const algo = algoCheck(signatureFromRequest.length); log.trace('algo for calculating signature', { algo }); if (algo === undefined) { - return callback(errors.InvalidArgument); + return { err: errors.InvalidArgument }; } - return vault.authenticateV2Request(accessKey, - signatureFromRequest, stringToSign, algo, log, (err, authInfo) => { - if (err) { - return callback(err); - } - return callback(null, authInfo); - } - ); + return { + err: null, + version: 2, + data: { + accessKey, + signatureFromRequest, + stringToSign, + algo, + }, + }; }; module.exports = queryAuthCheck; diff --git a/lib/auth/v4/headerAuthCheck.js b/lib/auth/v4/headerAuthCheck.js index a1aafe411..98f6f8449 100644 --- a/lib/auth/v4/headerAuthCheck.js +++ b/lib/auth/v4/headerAuthCheck.js @@ -8,50 +8,40 @@ const convertUTCtoISO8601 = require('./timeUtils').convertUTCtoISO8601; const extractAuthItems = require('./validateInputs').extractAuthItems; const validateCredentials = require('./validateInputs').validateCredentials; -let vault = require('../vault'); - const headerAuthCheck = {}; -headerAuthCheck.setAuthHandler = handler => { - vault = handler; - return headerAuthCheck; -}; - /** * V4 header auth check * @param {object} request - HTTP request object * @param {object} log - logging object - * @param {function} callback - callback to auth checking function - * @param {string} awsService - the name of the aws service using this method - * This is unused for now (forward compat) + * @param {string} awsService - either 's3' or 'iam' * @return {callback} calls callback */ -// eslint-disable-next-line no-unused-vars -headerAuthCheck.check = (request, log, callback, awsService) => { +headerAuthCheck.check = (request, log, awsService) => { log.trace('running header auth check'); // authorization header const authHeader = request.headers.authorization; if (!authHeader) { log.warn('missing authorization header'); - return callback(errors.MissingSecurityHeader); + return { err: errors.MissingSecurityHeader }; } const payloadChecksum = request.headers['x-amz-content-sha256']; if (!payloadChecksum) { log.debug('missing payload checksum'); - return callback(errors.MissingSecurityHeader); + return { err: errors.MissingSecurityHeader }; } if (payloadChecksum === 'STREAMING-AWS4-HMAC-SHA256-PAYLOAD') { log.trace('requesting streaming v4 auth'); // TODO: Implement this option - return callback(errors.NotImplemented); + return { err: errors.NotImplemented }; } log.trace('authorization header from request', { authHeader }); const authHeaderItems = extractAuthItems(authHeader, log); if (Object.keys(authHeaderItems).length < 3) { - return callback(errors.MissingSecurityHeader); + return { err: errors.MissingSecurityHeader }; } const signatureFromRequest = authHeaderItems.signatureFromRequest; const credentialsArr = authHeaderItems.credentialsArr; @@ -67,12 +57,12 @@ headerAuthCheck.check = (request, log, callback, awsService) => { } if (!timestamp) { log.warn('missing date header'); - return callback(errors.MissingSecurityHeader); + return { err: errors.MissingSecurityHeader }; } if (!validateCredentials(credentialsArr, timestamp, log)) { log.warn('credentials in improper format', { credentialsArr }); - return callback(errors.InvalidArgument); + return { err: errors.InvalidArgument }; } // credentialsArr is [accessKey, date, region, aws-service, aws4_request] const scopeDate = credentialsArr[1]; @@ -97,7 +87,7 @@ headerAuthCheck.check = (request, log, callback, awsService) => { const expiry = (15 * 60); const isTimeSkewed = checkTimeSkew(timestamp, expiry, log); if (isTimeSkewed) { - return callback(errors.RequestTimeTooSkewed); + return { err: errors.RequestTimeTooSkewed }; } const stringToSign = constructStringToSign({ @@ -111,17 +101,19 @@ headerAuthCheck.check = (request, log, callback, awsService) => { }); log.trace('constructed stringToSign', { stringToSign }); if (stringToSign instanceof Error) { - return callback(stringToSign); + return { err: stringToSign }; } - const vaultParams = { - accessKey, - signatureFromRequest, - region, - scopeDate, - stringToSign, - log, + return { + err: null, + version: 4, + data: { + accessKey, + signatureFromRequest, + region, + scopeDate, + stringToSign, + }, }; - return vault.authenticateV4Request(vaultParams, callback); }; module.exports = headerAuthCheck; diff --git a/lib/auth/v4/queryAuthCheck.js b/lib/auth/v4/queryAuthCheck.js index ffd874e83..fda4c68a0 100644 --- a/lib/auth/v4/queryAuthCheck.js +++ b/lib/auth/v4/queryAuthCheck.js @@ -7,27 +7,20 @@ const checkTimeSkew = require('./timeUtils').checkTimeSkew; const validateCredentials = require('./validateInputs').validateCredentials; const extractQueryParams = require('./validateInputs').extractQueryParams; -let vault = require('../vault'); - const queryAuthCheck = {}; -queryAuthCheck.setAuthHandler = handler => { - vault = handler; - return queryAuthCheck; -}; - /** * V4 query auth check * @param {object} request - HTTP request object * @param {object} log - logging object - * @param {function} callback - callback to auth checking function + * @param {object} data - Contain authentification params (GET or POST data) * @return {callback} calls callback */ -queryAuthCheck.check = (request, log, data, callback) => { +queryAuthCheck.check = (request, log, data) => { const authParams = extractQueryParams(data, log); if (Object.keys(authParams).length !== 5) { - return callback(errors.InvalidArgument); + return { err: errors.InvalidArgument }; } const signedHeaders = authParams.signedHeaders; const signatureFromRequest = authParams.signatureFromRequest; @@ -37,7 +30,7 @@ queryAuthCheck.check = (request, log, data, callback) => { if (!validateCredentials(credential, timestamp, log)) { log.warn('credential param format incorrect', { credential }); - return callback(errors.InvalidArgument); + return { err: errors.InvalidArgument }; } const accessKey = credential[0]; const scopeDate = credential[1]; @@ -47,7 +40,7 @@ queryAuthCheck.check = (request, log, data, callback) => { const isTimeSkewed = checkTimeSkew(timestamp, expiry, log); if (isTimeSkewed) { - return callback(errors.RequestTimeTooSkewed); + return { err: errors.RequestTimeTooSkewed }; } // In query v4 auth, the canonical request needs @@ -76,18 +69,20 @@ queryAuthCheck.check = (request, log, data, callback) => { `${scopeDate}/${region}/${service}/${requestType}`, }); if (stringToSign instanceof Error) { - return callback(stringToSign); + return { err: stringToSign }; } log.trace('constructed stringToSign', { stringToSign }); - const vaultParams = { - accessKey, - signatureFromRequest, - region, - scopeDate, - stringToSign, - log, + return { + err: null, + version: 4, + data: { + accessKey, + signatureFromRequest, + region, + scopeDate, + stringToSign, + }, }; - return vault.authenticateV4Request(vaultParams, callback); }; module.exports = queryAuthCheck; diff --git a/tests/unit/auth/v2/errorHandling.js b/tests/unit/auth/v2/errorHandling.js index 460ce8927..3efa6c9dc 100644 --- a/tests/unit/auth/v2/errorHandling.js +++ b/tests/unit/auth/v2/errorHandling.js @@ -27,7 +27,7 @@ describe('Error handling in checkAuth', () => { auth(request, logger, err => { assert.deepStrictEqual(err, errors.InvalidAccessKeyId); done(); - }); + }, 's3', request.query); }); it('should return an error message if no date header ' + @@ -46,7 +46,7 @@ describe('Error handling in checkAuth', () => { auth(request, logger, err => { assert.deepStrictEqual(err, errors.MissingSecurityHeader); done(); - }); + }, 's3', request.query); }); it('should return an error message if the Expires ' + @@ -67,7 +67,7 @@ describe('Error handling in checkAuth', () => { auth(request, logger, err => { assert.deepStrictEqual(err, errors.RequestTimeTooSkewed); done(); - }); + }, 's3', request.query); }); it('should return an error message if ' + @@ -92,7 +92,7 @@ describe('Error handling in checkAuth', () => { auth(request, logger, err => { assert.deepStrictEqual(err, errors.SignatureDoesNotMatch); done(); - }); + }, 's3', request.query); }); it('should return an error message if the ' + @@ -113,7 +113,7 @@ describe('Error handling in checkAuth', () => { auth(request, logger, err => { assert.deepStrictEqual(err, errors.SignatureDoesNotMatch); done(); - }); + }, 's3', request.query); }); it('should return an error message if accessKey is empty for' + @@ -134,7 +134,7 @@ describe('Error handling in checkAuth', () => { auth(request, logger, err => { assert.deepStrictEqual(err, errors.MissingSecurityHeader); done(); - }); + }, 's3', request.query); }); }); diff --git a/tests/unit/auth/v2/publicAccess.js b/tests/unit/auth/v2/publicAccess.js index 55269637a..c57124e60 100644 --- a/tests/unit/auth/v2/publicAccess.js +++ b/tests/unit/auth/v2/publicAccess.js @@ -28,7 +28,7 @@ describe('Public Access', () => { assert.strictEqual(authInfo.getCanonicalID(), publicAuthInfo.getCanonicalID()); done(); - }); + }, 's3', request.query); }); it('should not grant access to a request that contains ' + @@ -45,6 +45,6 @@ describe('Public Access', () => { auth(request, logger, err => { assert.deepStrictEqual(err, errors.MissingSecurityHeader); done(); - }); + }, 's3', request.query); }); }); diff --git a/tests/unit/auth/v2/signature.js b/tests/unit/auth/v2/signature.js index c63b1c871..a0d95c7bd 100644 --- a/tests/unit/auth/v2/signature.js +++ b/tests/unit/auth/v2/signature.js @@ -27,7 +27,7 @@ describe('checkAuth reconstruction of signature', () => { query: {}, }; const secretKey = 'verySecretKey1'; - const stringToSign = constructStringToSign(request, log); + const stringToSign = constructStringToSign(request, request.query, log); const reconstructedSig = hashSignature(stringToSign, secretKey, 'sha1'); assert.strictEqual(reconstructedSig, 'MJNF7AqNapSu32TlBOVkcAxj58c='); }); @@ -50,7 +50,7 @@ describe('checkAuth reconstruction of signature', () => { query: { 'max-keys': '1000', 'prefix': '', 'delimiter': '/' }, }; const secretKey = 'verySecretKey1'; - const stringToSign = constructStringToSign(request, log); + const stringToSign = constructStringToSign(request, request.query, log); const reconstructedSig = hashSignature(stringToSign, secretKey, 'sha1'); assert.strictEqual(reconstructedSig, 'V8g5UJUFmMzruMqUHVT6ZwvUw+M='); }); @@ -77,7 +77,7 @@ describe('checkAuth reconstruction of signature', () => { query: {}, }; const secretKey = 'verySecretKey1'; - const stringToSign = constructStringToSign(request, log); + const stringToSign = constructStringToSign(request, request.query, log); const reconstructedSig = hashSignature(stringToSign, secretKey, 'sha1'); assert.strictEqual(reconstructedSig, 'fWPcicKn7Fhzfje/0pRTifCxL44='); }); diff --git a/tests/unit/auth/v4/headerAuthCheck.js b/tests/unit/auth/v4/headerAuthCheck.js index 6f34e23f9..64b3af026 100644 --- a/tests/unit/auth/v4/headerAuthCheck.js +++ b/tests/unit/auth/v4/headerAuthCheck.js @@ -9,7 +9,6 @@ const createAlteredRequest = require('../../helpers').createAlteredRequest; const headerAuthCheck = require('../../../../lib/auth/v4/headerAuthCheck').check; const DummyRequestLogger = require('../../helpers').DummyRequestLogger; -const makeAuthInfo = require('../../helpers').makeAuthInfo; const log = new DummyRequestLogger(); @@ -35,25 +34,22 @@ const request = { headers, query: {}, }; -const createdAuthInfo = makeAuthInfo('accessKey1'); describe('v4 headerAuthCheck', () => { it('should return error if undefined authorization header', done => { const alteredRequest = createAlteredRequest({ authorization: undefined }, 'headers', request, headers); - headerAuthCheck(alteredRequest, log, err => { - assert.deepStrictEqual(err, errors.MissingSecurityHeader); - done(); - }); + const res = headerAuthCheck(alteredRequest, log); + assert.deepStrictEqual(res.err, errors.MissingSecurityHeader); + done(); }); it('should return error if undefined sha256 header', done => { const alteredRequest = createAlteredRequest({ 'x-amz-content-sha256': undefined }, 'headers', request, headers); - headerAuthCheck(alteredRequest, log, err => { - assert.deepStrictEqual(err, errors.MissingSecurityHeader); - done(); - }); + const res = headerAuthCheck(alteredRequest, log); + assert.deepStrictEqual(res.err, errors.MissingSecurityHeader); + done(); }); it('should return error if missing credentials', done => { @@ -62,10 +58,9 @@ describe('v4 headerAuthCheck', () => { 'x-amz-content-sha256;x-amz-date, Signature=abed9' + '24c06abf8772c670064d22eacd6ccb85c06befa15f' + '4a789b0bae19307bc' }, 'headers', request, headers); - headerAuthCheck(alteredRequest, log, err => { - assert.deepStrictEqual(err, errors.MissingSecurityHeader); - done(); - }); + const res = headerAuthCheck(alteredRequest, log); + assert.deepStrictEqual(res.err, errors.MissingSecurityHeader); + done(); }); it('should return error if missing SignedHeaders', done => { @@ -77,10 +72,9 @@ describe('v4 headerAuthCheck', () => { 'x-amz-date, Signature=abed924c06abf8772c6' + '70064d22eacd6ccb85c06befa15f' + '4a789b0bae19307bc' }, 'headers', request, headers); - headerAuthCheck(alteredRequest, log, err => { - assert.deepStrictEqual(err, errors.MissingSecurityHeader); - done(); - }); + const res = headerAuthCheck(alteredRequest, log); + assert.deepStrictEqual(res.err, errors.MissingSecurityHeader); + done(); }); it('should return error if missing Signature', done => { @@ -92,19 +86,17 @@ describe('v4 headerAuthCheck', () => { 'x-amz-date, Sig=abed924c06abf8772c6' + '70064d22eacd6ccb85c06befa15f' + '4a789b0bae19307bc' }, 'headers', request, headers); - headerAuthCheck(alteredRequest, log, err => { - assert.deepStrictEqual(err, errors.MissingSecurityHeader); - done(); - }); + const res = headerAuthCheck(alteredRequest, log); + assert.deepStrictEqual(res.err, errors.MissingSecurityHeader); + done(); }); it('should return error if missing timestamp', done => { const alteredRequest = createAlteredRequest({ 'x-amz-date': undefined }, 'headers', request, headers); - headerAuthCheck(alteredRequest, log, err => { - assert.deepStrictEqual(err, errors.MissingSecurityHeader); - done(); - }); + const res = headerAuthCheck(alteredRequest, log); + assert.deepStrictEqual(res.err, errors.MissingSecurityHeader); + done(); }); it('should return error if scope date does not ' + @@ -112,10 +104,9 @@ describe('v4 headerAuthCheck', () => { // Different timestamp (2015 instead of 2016) const alteredRequest = createAlteredRequest({ 'x-amz-date': '20150208T201405Z' }, 'headers', request, headers); - headerAuthCheck(alteredRequest, log, err => { - assert.deepStrictEqual(err, errors.InvalidArgument); - done(); - }); + const res = headerAuthCheck(alteredRequest, log); + assert.deepStrictEqual(res.err, errors.InvalidArgument); + done(); }); it('should return error if timestamp from x-amz-date header' + @@ -129,10 +120,9 @@ describe('v4 headerAuthCheck', () => { 'x-amz-date, Signature=abed924c06abf8772c67' + '0064d22eacd6ccb85c06befa15f' + '4a789b0bae19307bc' }, 'headers', request, headers); - headerAuthCheck(alteredRequest, log, err => { - assert.deepStrictEqual(err, errors.RequestTimeTooSkewed); - done(); - }); + const res = headerAuthCheck(alteredRequest, log); + assert.deepStrictEqual(res.err, errors.RequestTimeTooSkewed); + done(); }); it('should return error if timestamp from date header' + @@ -147,10 +137,9 @@ describe('v4 headerAuthCheck', () => { '4a789b0bae19307bc' }, 'headers', request, headers); delete alteredRequest.headers['x-amz-date']; - headerAuthCheck(alteredRequest, log, err => { - assert.deepStrictEqual(err, errors.RequestTimeTooSkewed); - done(); - }); + const res = headerAuthCheck(alteredRequest, log); + assert.deepStrictEqual(res.err, errors.RequestTimeTooSkewed); + done(); }); it('should return error if timestamp from x-amz-date header' + @@ -165,10 +154,9 @@ describe('v4 headerAuthCheck', () => { '0064d22eacd6ccb85c06befa15f' + '4a789b0bae19307bc' }, 'headers', request, headers); - headerAuthCheck(alteredRequest, log, err => { - assert.deepStrictEqual(err, errors.RequestTimeTooSkewed); - done(); - }); + const res = headerAuthCheck(alteredRequest, log); + assert.deepStrictEqual(res.err, errors.RequestTimeTooSkewed); + done(); }); it('should return error if timestamp from date header' + @@ -184,10 +172,9 @@ describe('v4 headerAuthCheck', () => { '4a789b0bae19307bc' }, 'headers', request, headers); delete alteredRequest.headers['x-amz-date']; - headerAuthCheck(alteredRequest, log, err => { - assert.deepStrictEqual(err, errors.RequestTimeTooSkewed); - done(); - }); + const res = headerAuthCheck(alteredRequest, log); + assert.deepStrictEqual(res.err, errors.RequestTimeTooSkewed); + done(); }); it('should not return error due to unknown region', done => { @@ -200,39 +187,19 @@ describe('v4 headerAuthCheck', () => { '8e43e369f48ea6d3a5f1fe518e14', }, 'headers', request, headers); const clock = lolex.install(1454962445000); - headerAuthCheck(alteredRequest, log, err => { - clock.uninstall(); - assert.ifError(err); - done(); - }); + const res = headerAuthCheck(alteredRequest, log); + clock.uninstall(); + assert.ifError(res.err); + done(); }); - it('should successfully authenticate', done => { + it('should successfully return information', done => { // Freezes time so date created within function will be Feb 8, 2016 const clock = lolex.install(1454962445000); - headerAuthCheck(request, log, (err, authInfo) => { - clock.uninstall(); - assert.strictEqual(err, null); - assert.strictEqual(authInfo.getCanonicalID(), - createdAuthInfo.getCanonicalID()); - done(); - }); - }); - - it('should return error if accessKey does not exist', done => { - const alteredRequest = createAlteredRequest({ - authorization: 'AWS4-HMAC-SHA256 ' + - 'Credential=nonexistaentkey/20160208' + - '/us-east-1/s3/aws4_request, SignedHeaders=host;' + - 'x-amz-content-sha256;' + - 'x-amz-date, Signature=abed924c06abf8772c67006' + - '4d22eacd6ccb85c06befa15f' + - '4a789b0bae19307bc' }, 'headers', request, headers); - const clock = lolex.install(1454962445000); - headerAuthCheck(alteredRequest, log, err => { - clock.uninstall(); - assert.deepStrictEqual(err, errors.InvalidAccessKeyId); - done(); - }); + const res = headerAuthCheck(request, log); + clock.uninstall(); + assert.strictEqual(res.err, null); + assert.strictEqual(res.version, 4); + done(); }); }); diff --git a/tests/unit/auth/v4/queryAuthCheck.js b/tests/unit/auth/v4/queryAuthCheck.js index b0951073d..aa71a60d2 100644 --- a/tests/unit/auth/v4/queryAuthCheck.js +++ b/tests/unit/auth/v4/queryAuthCheck.js @@ -8,7 +8,6 @@ const errors = require('../../../../lib/errors'); const createAlteredRequest = require('../../helpers').createAlteredRequest; const queryAuthCheck = require('../../../../lib/auth/v4/queryAuthCheck').check; const DummyRequestLogger = require('../../helpers').DummyRequestLogger; -const makeAuthInfo = require('../../helpers').makeAuthInfo; const log = new DummyRequestLogger(); @@ -32,35 +31,29 @@ const request = { query, }; - -const createdAuthInfo = makeAuthInfo('accessKey1'); - describe('v4 queryAuthCheck', () => { it('should return error if algorithm param incorrect', done => { const alteredRequest = createAlteredRequest({ 'X-Amz-Algorithm': 'AWS4-HMAC-SHA1' }, 'query', request, query); - queryAuthCheck(alteredRequest, log, err => { - assert.deepStrictEqual(err, errors.InvalidArgument); - done(); - }); + const res = queryAuthCheck(alteredRequest, log, alteredRequest.query); + assert.deepStrictEqual(res.err, errors.InvalidArgument); + done(); }); it('should return error if X-Amz-Credential param is undefined', done => { const alteredRequest = createAlteredRequest({ 'X-Amz-Credential': undefined }, 'query', request, query); - queryAuthCheck(alteredRequest, log, err => { - assert.deepStrictEqual(err, errors.InvalidArgument); - done(); - }); + const res = queryAuthCheck(alteredRequest, log, alteredRequest.query); + assert.deepStrictEqual(res.err, errors.InvalidArgument); + done(); }); it('should return error if credential param format incorrect', done => { const alteredRequest = createAlteredRequest({ 'X-Amz-Credential': 'incorrectformat' }, 'query', request, query); - queryAuthCheck(alteredRequest, log, err => { - assert.deepStrictEqual(err, errors.InvalidArgument); - done(); - }); + const res = queryAuthCheck(alteredRequest, log, alteredRequest.query); + assert.deepStrictEqual(res.err, errors.InvalidArgument); + done(); }); it('should return error if service set forth in ' + @@ -68,10 +61,9 @@ describe('v4 queryAuthCheck', () => { const alteredRequest = createAlteredRequest({ 'X-Amz-Credential': 'accessKey1/20160208/us-east-1/EC2/aws4_request' }, 'query', request, query); - queryAuthCheck(alteredRequest, log, err => { - assert.deepStrictEqual(err, errors.InvalidArgument); - done(); - }); + const res = queryAuthCheck(alteredRequest, log, alteredRequest.query); + assert.deepStrictEqual(res.err, errors.InvalidArgument); + done(); }); it('should return error if requestType set forth in ' + @@ -79,56 +71,50 @@ describe('v4 queryAuthCheck', () => { const alteredRequest = createAlteredRequest({ 'X-Amz-Credential': 'accessKey1/20160208/us-east-1/s3/aws2_request' }, 'query', request, query); - queryAuthCheck(alteredRequest, log, err => { - assert.deepStrictEqual(err, errors.InvalidArgument); - done(); - }); + const res = queryAuthCheck(alteredRequest, log, alteredRequest.query); + assert.deepStrictEqual(res.err, errors.InvalidArgument); + done(); }); it('should return error if undefined X-Amz-SignedHeaders param', done => { const alteredRequest = createAlteredRequest({ 'X-Amz-SignedHeaders': undefined }, 'query', request, query); - queryAuthCheck(alteredRequest, log, err => { - assert.deepStrictEqual(err, errors.InvalidArgument); - done(); - }); + const res = queryAuthCheck(alteredRequest, log, alteredRequest.query); + assert.deepStrictEqual(res.err, errors.InvalidArgument); + done(); }); it('should return error if undefined X-Amz-Signature param', done => { const alteredRequest = createAlteredRequest({ 'X-Amz-Signature': undefined }, 'query', request, query); - queryAuthCheck(alteredRequest, log, err => { - assert.deepStrictEqual(err, errors.InvalidArgument); - done(); - }); + const res = queryAuthCheck(alteredRequest, log, alteredRequest.query); + assert.deepStrictEqual(res.err, errors.InvalidArgument); + done(); }); it('should return error if undefined X-Amz-Date param', done => { const alteredRequest = createAlteredRequest({ 'X-Amz-Date': undefined }, 'query', request, query); - queryAuthCheck(alteredRequest, log, err => { - assert.deepStrictEqual(err, errors.InvalidArgument); - done(); - }); + const res = queryAuthCheck(alteredRequest, log, alteredRequest.query); + assert.deepStrictEqual(res.err, errors.InvalidArgument); + done(); }); it('should return error if undefined X-Amz-Expires param', done => { const alteredRequest = createAlteredRequest({ 'X-Amz-Expires': undefined }, 'query', request, query); - queryAuthCheck(alteredRequest, log, err => { - assert.deepStrictEqual(err, errors.InvalidArgument); - done(); - }); + const res = queryAuthCheck(alteredRequest, log, alteredRequest.query); + assert.deepStrictEqual(res.err, errors.InvalidArgument); + done(); }); it('should return error if X-Amz-Expires param ' + 'is less than 1', done => { const alteredRequest = createAlteredRequest({ 'X-Amz-Expires': 0 }, 'query', request, query); - queryAuthCheck(alteredRequest, log, err => { - assert.deepStrictEqual(err, errors.InvalidArgument); - done(); - }); + const res = queryAuthCheck(alteredRequest, log, alteredRequest.query); + assert.deepStrictEqual(res.err, errors.InvalidArgument); + done(); }); it('should return error if X-Amz-Expires param ' + @@ -136,10 +122,9 @@ describe('v4 queryAuthCheck', () => { // Greater than 604800 seconds (7 days) const alteredRequest = createAlteredRequest({ 'X-Amz-Expires': 604801 }, 'query', request, query); - queryAuthCheck(alteredRequest, log, err => { - assert.deepStrictEqual(err, errors.InvalidArgument); - done(); - }); + const res = queryAuthCheck(alteredRequest, log, alteredRequest.query); + assert.deepStrictEqual(res.err, errors.InvalidArgument); + done(); }); it('should return error if X-Amz-Date param is in the future', done => { @@ -148,20 +133,18 @@ describe('v4 queryAuthCheck', () => { 'X-Amz-Date': '20950208T234304Z', 'X-Amz-Credential': 'accessKey1/20950208/us-east-1/s3/aws4_request', }, 'query', request, query); - queryAuthCheck(alteredRequest, log, err => { - assert.deepStrictEqual(err, errors.RequestTimeTooSkewed); - done(); - }); + const res = queryAuthCheck(alteredRequest, log, alteredRequest.query); + assert.deepStrictEqual(res.err, errors.RequestTimeTooSkewed); + done(); }); it('should return error if X-Amz-Date param is too old', done => { const alteredRequest = createAlteredRequest({ 'X-Amz-Date': '20160208T234304Z', }, 'query', request, query); - queryAuthCheck(alteredRequest, log, err => { - assert.deepStrictEqual(err, errors.RequestTimeTooSkewed); - done(); - }); + const res = queryAuthCheck(alteredRequest, log, alteredRequest.query); + assert.deepStrictEqual(res.err, errors.RequestTimeTooSkewed); + done(); }); it('should return error if scope date from X-Amz-Credential param' + @@ -171,23 +154,20 @@ describe('v4 queryAuthCheck', () => { 'X-Amz-Credential': 'accessKey1/20160209/' + 'us-east-1/s3/aws4_request', }, 'query', request, query); - queryAuthCheck(alteredRequest, log, err => { - clock.uninstall(); - assert.deepStrictEqual(err, errors.InvalidArgument); - done(); - }); + const res = queryAuthCheck(alteredRequest, log, alteredRequest.query); + clock.uninstall(); + assert.deepStrictEqual(res.err, errors.InvalidArgument); + done(); }); - it('should successfully authenticate', done => { + it('should successfully return informations', done => { // Freezes time so date created within function will be Feb 8, 2016 // (within 15 minutes of timestamp in request) const clock = lolex.install(1454974984001); - queryAuthCheck(request, log, (err, authInfo) => { - clock.uninstall(); - assert.deepStrictEqual(err, null); - assert.strictEqual(authInfo.getCanonicalID(), - createdAuthInfo.getCanonicalID()); - done(); - }); + const res = queryAuthCheck(request, log, request.query); + clock.uninstall(); + assert.deepStrictEqual(res.err, null); + assert.strictEqual(res.version, 4); + done(); }); });