Compare commits

...

4 Commits

Author SHA1 Message Date
Alexandre Merle d0a7d6701d S3C-820: Create Policy signature does not match
Add an exception for aws-java-sdk, which not encode the '*' character for
signatures
2018-04-05 22:46:22 +02:00
Alexandre Merle 7ef6c17c6b fix circle 2018-04-05 22:45:46 +02:00
Rahul Padigela 8ab0e071a9
Merge pull request #381 from scality/S3C-885/sign-url
S3C-885: Change v2 query auth window to 7 days
2017-12-01 14:31:57 -08:00
Nicolas Humbert 0423cd52c8 S3C-885: Change v2 query auth window to 7 days
(cherry picked from commit 64edb99a3e)
2017-12-01 11:50:32 -08:00
8 changed files with 96 additions and 10 deletions

View File

@ -5,11 +5,15 @@ general:
- /^ultron\/.*/ # Ignore ultron/* branches
machine:
environment:
CXX: g++-4.9
node:
version: 4.5.0
dependencies:
pre:
override:
- rm -rf node_modules
- npm install
- sudo pip install yamllint
test:

View File

@ -13,8 +13,8 @@ function check(request, log, data) {
}
/*
Check whether request has expired or if
expires parameter is more than 100000000 milliseconds
(1 day and 4 hours) in the future.
expires parameter is more than 604800000 milliseconds
(7 days) in the future.
Expires time is provided in seconds so need to
multiply by 1000 to obtain
milliseconds to compare to Date.now()
@ -27,8 +27,8 @@ function check(request, log, data) {
}
const currentTime = Date.now();
// 100000000 ms (one day and 4 hours).
if (expirationTime > currentTime + 100000000) {
// 604800000 ms (seven days).
if (expirationTime > currentTime + 604800000) {
log.debug('expires parameter too far in future',
{ expires: request.query.Expires });
return { err: errors.AccessDenied };

View File

@ -32,7 +32,7 @@ function _toHexUTF8(char) {
return res;
}
function awsURIencode(input, encodeSlash) {
function awsURIencode(input, encodeSlash, noEncodeStar) {
const encSlash = encodeSlash === undefined ? true : encodeSlash;
let encoded = '';
for (let i = 0; i < input.length; i++) {
@ -47,6 +47,8 @@ function awsURIencode(input, encodeSlash) {
encoded = encoded.concat('%20');
} else if (ch === '/') {
encoded = encoded.concat(encSlash ? '%2F' : ch);
} else if (ch === '*') {
encoded = encoded.concat(noEncodeStar ? '*' : '%2A');
} else {
encoded = encoded.concat(_toHexUTF8(ch));
}

View File

@ -27,8 +27,16 @@ function createCanonicalRequest(params) {
payloadChecksum = 'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b' +
'934ca495991b7852b855';
} else if (pHttpVerb === 'POST') {
let notEncodeStar = false;
// The java sdk does not encode the '*' parameter to compute the
// signature, if the user-agent is recognized, we need to keep
// the plain '*' as well.
if (/aws-sdk-java\/[0-9.]+/.test(pHeaders['user-agent'])) {
notEncodeStar = true;
}
let payload = queryString.stringify(pQuery, null, null, {
encodeURIComponent: awsURIencode,
encodeURIComponent: input => awsURIencode(input, false,
notEncodeStar),
});
payload = payload.replace(/%20/g, '+');
payloadChecksum = crypto.createHash('sha256')

View File

@ -99,7 +99,8 @@ function extractQueryParams(queryObj, log) {
}
const expiry = Number.parseInt(queryObj['X-Amz-Expires'], 10);
if (expiry && (expiry > 0 && expiry < 604801)) {
const sevenDays = 604800;
if (expiry && (expiry > 0 && expiry <= sevenDays)) {
authParams.expiry = expiry;
} else {
log.warn('invalid expiry', { expiry });

View File

@ -1,6 +1,6 @@
{
"name": "arsenal",
"version": "1.1.0",
"version": "6.4.7",
"description": "Common utilities for the S3 project components",
"main": "index.js",
"repository": {

View File

@ -1,7 +1,8 @@
'use strict'; // eslint-disable-line strict
const assert = require('assert');
const awsURIencode =
require('../../../../lib/auth/v4/awsURIencode');
const createCanonicalRequest =
require('../../../../lib/auth/v4/createCanonicalRequest');
@ -45,6 +46,50 @@ describe('createCanonicalRequest function', () => {
assert.strictEqual(actualOutput, expectedOutput);
});
const msg = 'S3C-820: aws java sdk should not encode * ' +
'character for signature';
it(msg, () => {
const doc = JSON.stringify({
Statement: [{
Action: 's3:*',
}],
});
const params = {
pHttpVerb: 'POST',
pResource: '/',
pQuery: {
PolicyDocument: doc,
},
pHeaders: {
'host': 'examplebucket.s3.amazonaws.com',
'x-amz-date': '20130524T000000Z',
'user-agent': 'aws-sdk-java/1.11',
'authorization': 'AWS4-HMAC-SHA256 Credential' +
'=AKIAIOSFODNN7EXAMPLE/20130524/us-east-1/' +
's3/aws4_request,SignedHeaders=host;user-agent' +
'x-amz-content-sha256;x-amz-date,Signature=' +
'f0e8bdb87c964420e857bd35b5d6ed310bd44f' +
'0170aba48dd91039c6036bdb41',
'x-amz-content-sha256': 'e3b0c44298fc1c149afbf4c' +
'8996fb92427ae41e4649b934ca495991b7852b855',
},
pSignedHeaders: 'host;user-agent;x-amz-content-sha256;x-amz-date',
};
const expectedOutput = 'POST\n' +
'/\n' +
`PolicyDocument=${awsURIencode(doc)}\n` +
'host:examplebucket.s3.amazonaws.com\n' +
'user-agent:aws-sdk-java/1.11\n' +
'x-amz-content-sha256:e3b0c44298fc1c149afbf4c' +
'8996fb92427ae41e4649b934ca495991b7852b855\n' +
'x-amz-date:20130524T000000Z\n\n' +
'host;user-agent;x-amz-content-sha256;x-amz-date\n' +
'25775fcf6b536b361aadce0c5f1afb46eb945dbdd6c3a7723b18300234a89588';
const actualOutput = createCanonicalRequest(params);
assert.strictEqual(actualOutput, expectedOutput);
});
// Example taken from: http://docs.aws.amazon.com/AmazonS3/
// latest/API/sig-v4-header-based-auth.html
it('should construct a canonical request in accordance ' +

View File

@ -199,4 +199,30 @@ describe('v4 queryAuthCheck', () => {
assert.strictEqual(res.params.version, 4);
done();
});
it('should successfully return v4 and no error if X-Amz-Expires param ' +
'is 604800 (7 days)', done => {
// Freezes time so date created within function will be Feb 8, 2016
const clock = lolex.install(1454974984001);
const alteredRequest = createAlteredRequest({ 'X-Amz-Expires':
604800 }, 'query', request, query);
const res = queryAuthCheck(alteredRequest, log, alteredRequest.query);
clock.uninstall();
assert.deepStrictEqual(res.err, null);
assert.strictEqual(res.params.version, 4);
done();
});
it('should successfully return v4 and no error if X-Amz-Expires param ' +
'is less thant 604800 (7 days)', done => {
// Freezes time so date created within function will be Feb 8, 2016
const clock = lolex.install(1454974984001);
const alteredRequest = createAlteredRequest({ 'X-Amz-Expires':
604799 }, 'query', request, query);
const res = queryAuthCheck(alteredRequest, log, alteredRequest.query);
clock.uninstall();
assert.deepStrictEqual(res.err, null);
assert.strictEqual(res.params.version, 4);
done();
});
});