diff --git a/lib/api/bucketPut.js b/lib/api/bucketPut.js index 5f3409da04..5bc7019bcc 100644 --- a/lib/api/bucketPut.js +++ b/lib/api/bucketPut.js @@ -126,8 +126,8 @@ function _buildConstantParams({ sslEnabled: isSecure, awsService: 's3', requesterInfo: authInfo, - signatureVersion: authParams.params.data.authType, - authType: authParams.params.data.signatureVersion, + signatureVersion: authParams.params.data.signatureVersion, + authType: authParams.params.data.authType, signatureAge: authParams.params.data.signatureAge, apiMethod, locationConstraint, diff --git a/lib/api/multiObjectDelete.js b/lib/api/multiObjectDelete.js index a512a591e9..ca743c0f9e 100644 --- a/lib/api/multiObjectDelete.js +++ b/lib/api/multiObjectDelete.js @@ -565,8 +565,8 @@ function multiObjectDelete(authInfo, request, log, callback) { awsService: 's3', locationConstraint: null, requesterInfo: authInfo, - signatureVersion: authParams.params.data.authType, - authType: authParams.params.data.signatureVersion, + signatureVersion: authParams.params.data.signatureVersion, + authType: authParams.params.data.authType, signatureAge: authParams.params.data.signatureAge, }, parameterize: { diff --git a/package.json b/package.json index 87dc93dd59..3e700f5dd6 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@zenko/cloudserver", - "version": "9.2.41", + "version": "9.2.42", "description": "Zenko CloudServer, an open-source Node.js implementation of a server handling the Amazon S3 protocol", "main": "index.js", "engines": { diff --git a/tests/unit/api/bucketPut.js b/tests/unit/api/bucketPut.js index 529f2947cb..d9e3344905 100644 --- a/tests/unit/api/bucketPut.js +++ b/tests/unit/api/bucketPut.js @@ -1,5 +1,5 @@ const assert = require('assert'); -const { errors } = require('arsenal'); +const { auth, errors } = require('arsenal'); const sinon = require('sinon'); const inMemory = require('../../../lib/kms/in_memory/backend').backend; const vault = require('../../../lib/auth/vault'); @@ -934,3 +934,43 @@ describe('bucketPut API with SSE Configurations', () => { }); }); }); + +describe('bucketPut checkPolicies request context', () => { + afterEach(() => { + sinon.restore(); + cleanup(); + }); + + it('should forward auth params unswapped to vault, including a zero signatureAge', done => { + // IAM user so that the request goes through the checkPolicies path + const userAuthInfo = makeAuthInfo(accessKey, 'testuser'); + sinon.stub(auth.server, 'extractParams').returns({ + params: { + version: 4, + data: { + signatureVersion: 'AWS4-HMAC-SHA256', + authType: 'REST-HEADER', + signatureAge: 0, + }, + }, + }); + const checkPoliciesStub = sinon.stub(vault, 'checkPolicies') + .callsFake((requestContextParams, arn, log, cb) => cb(errors.AccessDenied)); + const request = { + ...testRequest, + socket: { + remoteAddress: '127.0.0.1', + }, + }; + + bucketPut(userAuthInfo, request, log, err => { + assert.strictEqual(err.is.AccessDenied, true, `expected AccessDenied, got ${err && err.message}`); + sinon.assert.calledOnce(checkPoliciesStub); + const { constantParams } = checkPoliciesStub.getCall(0).args[0][0]; + assert.strictEqual(constantParams.signatureVersion, 'AWS4-HMAC-SHA256'); + assert.strictEqual(constantParams.authType, 'REST-HEADER'); + assert.strictEqual(constantParams.signatureAge, 0); + done(); + }); + }); +}); diff --git a/tests/unit/api/multiObjectDelete.js b/tests/unit/api/multiObjectDelete.js index b3d71d03ec..d1fcd3ba7f 100644 --- a/tests/unit/api/multiObjectDelete.js +++ b/tests/unit/api/multiObjectDelete.js @@ -1,6 +1,6 @@ const crypto = require('crypto'); const assert = require('assert'); -const { errors, storage } = require('arsenal'); +const { auth, errors, storage } = require('arsenal'); const { decodeObjectVersion, getObjMetadataAndDelete, initializeMultiObjectDeleteWithBatchingSupport } = require('../../../lib/api/multiObjectDelete'); @@ -28,6 +28,7 @@ const objectKey1 = 'objectName1'; const objectKey2 = 'objectName2'; const metadataUtils = require('../../../lib/metadata/metadataUtils'); const services = require('../../../lib/services'); +const vault = require('../../../lib/auth/vault'); const { BucketInfo } = require('arsenal/build/lib/models'); const testBucketPutRequest = new DummyRequest({ bucketName, @@ -456,3 +457,59 @@ describe('multiObjectDelete function', () => { }); }); }); + +describe('multiObjectDelete checkPolicies request context', () => { + afterEach(() => { + sinon.restore(); + }); + + it('should forward auth params unswapped to vault, including a zero signatureAge', done => { + const post = 'objectname'; + const request = new DummyRequest({ + bucketName: 'bucketname', + objectKey: 'objectname', + parsedHost: 'localhost', + headers: { + 'content-md5': crypto.createHash('md5').update(post, 'utf8').digest('base64'), + }, + post, + socket: { + remoteAddress: '127.0.0.1', + }, + url: '/bucketname', + }); + // IAM user so that the request goes through the checkPolicies path + const userAuthInfo = makeAuthInfo('accessKey1', 'testuser'); + + sinon.stub(metadataWrapper, 'getBucket').callsFake((bucketName, log, cb) => + cb(null, new BucketInfo( + 'bucketname', + userAuthInfo.getCanonicalID(), + 'accountA', + new Date().toISOString(), + 15, + ), undefined)); + sinon.stub(auth.server, 'extractParams').returns({ + params: { + version: 4, + data: { + signatureVersion: 'AWS4-HMAC-SHA256', + authType: 'REST-HEADER', + signatureAge: 0, + }, + }, + }); + const checkPoliciesStub = sinon.stub(vault, 'checkPolicies') + .callsFake((requestContextParams, arn, log, cb) => cb(errors.AccessDenied)); + + multiObjectDelete.multiObjectDelete(userAuthInfo, request, log, err => { + assert.strictEqual(err, null); + sinon.assert.calledOnce(checkPoliciesStub); + const { constantParams } = checkPoliciesStub.getCall(0).args[0]; + assert.strictEqual(constantParams.signatureVersion, 'AWS4-HMAC-SHA256'); + assert.strictEqual(constantParams.authType, 'REST-HEADER'); + assert.strictEqual(constantParams.signatureAge, 0); + done(); + }); + }); +});