Compare commits

...

6 Commits

Author SHA1 Message Date
Dora Korpar 29b0791a16 [squash] fix tests 3 2020-02-19 15:06:42 -08:00
Dora Korpar 8a01af66b8 [squash] fix tests 2 2020-02-19 14:14:18 -08:00
Dora Korpar da7b6799c3 [squash] fix tests 1 2020-02-19 13:56:11 -08:00
Dora Korpar 1b19798ddf [squash] fix negation 2020-02-18 15:44:24 -08:00
Dora Korpar be09313051 [squash] fix isObjAuthorized func 2020-02-18 14:16:01 -08:00
Dora Korpar 29912f79d8 bf: S3C 2597 user bucket policy 2020-02-18 10:34:37 -08:00
13 changed files with 111 additions and 72 deletions

View File

@ -229,11 +229,17 @@ function checkBucketPolicy(policy, requestType, canonicalID, arn, log) {
return permission; return permission;
} }
function isBucketAuthorized(bucket, requestType, canonicalID, arn, log) { function isBucketAuthorized(bucket, requestType, canonicalID, authInfo, log) {
// Check to see if user is authorized to perform a // Check to see if user is authorized to perform a
// particular action on bucket based on ACLs. // particular action on bucket based on ACLs.
// TODO: Add IAM checks // TODO: Add IAM checks
if (bucket.getOwner() === canonicalID) { let requesterIsNotUser = true;
let arn = null;
if (authInfo) {
requesterIsNotUser = !authInfo.isRequesterAnIAMUser();
arn = authInfo.getArn();
}
if ((bucket.getOwner() === canonicalID) && requesterIsNotUser) {
return true; return true;
} }
const aclPermission = checkBucketAcls(bucket, requestType, canonicalID); const aclPermission = checkBucketAcls(bucket, requestType, canonicalID);
@ -252,19 +258,28 @@ function isBucketAuthorized(bucket, requestType, canonicalID, arn, log) {
return (aclPermission || (bucketPolicyPermission === 'allow')); return (aclPermission || (bucketPolicyPermission === 'allow'));
} }
function isObjAuthorized(bucket, objectMD, requestType, canonicalID, arn, log) { function isObjAuthorized(bucket, objectMD, requestType, canonicalID, authInfo,
log) {
const bucketOwner = bucket.getOwner(); const bucketOwner = bucket.getOwner();
if (!objectMD) { if (!objectMD) {
return false; return false;
} }
if (objectMD['owner-id'] === canonicalID) { let requesterIsNotUser = true;
let arn = null;
if (authInfo) {
requesterIsNotUser = !authInfo.isRequesterAnIAMUser();
arn = authInfo.getArn();
}
if (objectMD['owner-id'] === canonicalID && requesterIsNotUser) {
return true; return true;
} }
// account is authorized if: // account is authorized if:
// - requesttype is included in bucketOwnerActions and // - requesttype is included in bucketOwnerActions and
// - account is the bucket owner // - account is the bucket owner
// - requester is account, not user
if (constants.bucketOwnerActions.includes(requestType) if (constants.bucketOwnerActions.includes(requestType)
&& bucketOwner === canonicalID) { && bucketOwner === canonicalID
&& requesterIsNotUser) {
return true; return true;
} }
const aclPermission = checkObjectAcls(bucket, objectMD, requestType, const aclPermission = checkObjectAcls(bucket, objectMD, requestType,

View File

@ -20,7 +20,6 @@ const requestType = 'bucketDeleteCors';
function bucketDeleteCors(authInfo, request, log, callback) { function bucketDeleteCors(authInfo, request, log, callback) {
const bucketName = request.bucketName; const bucketName = request.bucketName;
const canonicalID = authInfo.getCanonicalID(); const canonicalID = authInfo.getCanonicalID();
const requestArn = authInfo.getArn();
return metadata.getBucket(bucketName, log, (err, bucket) => { return metadata.getBucket(bucketName, log, (err, bucket) => {
const corsHeaders = collectCorsHeaders(request.headers.origin, const corsHeaders = collectCorsHeaders(request.headers.origin,
@ -34,7 +33,7 @@ function bucketDeleteCors(authInfo, request, log, callback) {
} }
log.trace('found bucket in metadata'); log.trace('found bucket in metadata');
if (!isBucketAuthorized(bucket, requestType, canonicalID, requestArn, if (!isBucketAuthorized(bucket, requestType, canonicalID, authInfo,
log)) { log)) {
log.debug('access denied for user on bucket', { log.debug('access denied for user on bucket', {
requestType, requestType,

View File

@ -12,7 +12,6 @@ const requestType = 'bucketDeleteWebsite';
function bucketDeleteWebsite(authInfo, request, log, callback) { function bucketDeleteWebsite(authInfo, request, log, callback) {
const bucketName = request.bucketName; const bucketName = request.bucketName;
const canonicalID = authInfo.getCanonicalID(); const canonicalID = authInfo.getCanonicalID();
const requestArn = authInfo.getArn();
return metadata.getBucket(bucketName, log, (err, bucket) => { return metadata.getBucket(bucketName, log, (err, bucket) => {
const corsHeaders = collectCorsHeaders(request.headers.origin, const corsHeaders = collectCorsHeaders(request.headers.origin,
@ -26,7 +25,7 @@ function bucketDeleteWebsite(authInfo, request, log, callback) {
} }
log.trace('found bucket in metadata'); log.trace('found bucket in metadata');
if (!isBucketAuthorized(bucket, requestType, canonicalID, requestArn, if (!isBucketAuthorized(bucket, requestType, canonicalID, authInfo,
log)) { log)) {
log.debug('access denied for user on bucket', { log.debug('access denied for user on bucket', {
requestType, requestType,

View File

@ -21,7 +21,6 @@ const requestType = 'bucketGetCors';
function bucketGetCors(authInfo, request, log, callback) { function bucketGetCors(authInfo, request, log, callback) {
const bucketName = request.bucketName; const bucketName = request.bucketName;
const canonicalID = authInfo.getCanonicalID(); const canonicalID = authInfo.getCanonicalID();
const requestArn = authInfo.getArn();
metadata.getBucket(bucketName, log, (err, bucket) => { metadata.getBucket(bucketName, log, (err, bucket) => {
if (err) { if (err) {
@ -35,7 +34,7 @@ function bucketGetCors(authInfo, request, log, callback) {
const corsHeaders = collectCorsHeaders(request.headers.origin, const corsHeaders = collectCorsHeaders(request.headers.origin,
request.method, bucket); request.method, bucket);
if (!isBucketAuthorized(bucket, requestType, canonicalID, requestArn, if (!isBucketAuthorized(bucket, requestType, canonicalID, authInfo,
log)) { log)) {
log.debug('access denied for user on bucket', { log.debug('access denied for user on bucket', {
requestType, requestType,

View File

@ -22,7 +22,6 @@ const requestType = 'bucketGetLocation';
function bucketGetLocation(authInfo, request, log, callback) { function bucketGetLocation(authInfo, request, log, callback) {
const bucketName = request.bucketName; const bucketName = request.bucketName;
const canonicalID = authInfo.getCanonicalID(); const canonicalID = authInfo.getCanonicalID();
const requestArn = authInfo.getArn();
return metadata.getBucket(bucketName, log, (err, bucket) => { return metadata.getBucket(bucketName, log, (err, bucket) => {
if (err) { if (err) {
@ -37,7 +36,7 @@ function bucketGetLocation(authInfo, request, log, callback) {
const corsHeaders = collectCorsHeaders(request.headers.origin, const corsHeaders = collectCorsHeaders(request.headers.origin,
request.method, bucket); request.method, bucket);
if (!isBucketAuthorized(bucket, requestType, canonicalID, requestArn, if (!isBucketAuthorized(bucket, requestType, canonicalID, authInfo,
log)) { log)) {
log.debug('access denied for account on bucket', { log.debug('access denied for account on bucket', {
requestType, requestType,

View File

@ -21,7 +21,6 @@ const requestType = 'bucketGetWebsite';
function bucketGetWebsite(authInfo, request, log, callback) { function bucketGetWebsite(authInfo, request, log, callback) {
const bucketName = request.bucketName; const bucketName = request.bucketName;
const canonicalID = authInfo.getCanonicalID(); const canonicalID = authInfo.getCanonicalID();
const requestArn = authInfo.getArn();
metadata.getBucket(bucketName, log, (err, bucket) => { metadata.getBucket(bucketName, log, (err, bucket) => {
if (err) { if (err) {
@ -35,7 +34,7 @@ function bucketGetWebsite(authInfo, request, log, callback) {
const corsHeaders = collectCorsHeaders(request.headers.origin, const corsHeaders = collectCorsHeaders(request.headers.origin,
request.method, bucket); request.method, bucket);
if (!isBucketAuthorized(bucket, requestType, canonicalID, requestArn, if (!isBucketAuthorized(bucket, requestType, canonicalID, authInfo,
log)) { log)) {
log.debug('access denied for user on bucket', { log.debug('access denied for user on bucket', {
requestType, requestType,

View File

@ -24,7 +24,6 @@ function bucketPutCors(authInfo, request, log, callback) {
log.debug('processing request', { method: 'bucketPutCors' }); log.debug('processing request', { method: 'bucketPutCors' });
const bucketName = request.bucketName; const bucketName = request.bucketName;
const canonicalID = authInfo.getCanonicalID(); const canonicalID = authInfo.getCanonicalID();
const requestArn = authInfo.getArn();
if (!request.post) { if (!request.post) {
log.debug('CORS xml body is missing', log.debug('CORS xml body is missing',
@ -67,8 +66,8 @@ function bucketPutCors(authInfo, request, log, callback) {
}); });
}, },
function validateBucketAuthorization(bucket, rules, corsHeaders, next) { function validateBucketAuthorization(bucket, rules, corsHeaders, next) {
if (!isBucketAuthorized(bucket, requestType, canonicalID, if (!isBucketAuthorized(bucket, requestType, canonicalID, authInfo,
requestArn, log)) { log)) {
log.debug('access denied for account on bucket', { log.debug('access denied for account on bucket', {
requestType, requestType,
}); });

View File

@ -23,7 +23,6 @@ function bucketPutWebsite(authInfo, request, log, callback) {
log.debug('processing request', { method: 'bucketPutWebsite' }); log.debug('processing request', { method: 'bucketPutWebsite' });
const bucketName = request.bucketName; const bucketName = request.bucketName;
const canonicalID = authInfo.getCanonicalID(); const canonicalID = authInfo.getCanonicalID();
const requestArn = authInfo.getArn();
if (!request.post) { if (!request.post) {
return callback(errors.MissingRequestBodyError); return callback(errors.MissingRequestBodyError);
@ -47,8 +46,8 @@ function bucketPutWebsite(authInfo, request, log, callback) {
}); });
}, },
function validateBucketAuthorization(bucket, config, next) { function validateBucketAuthorization(bucket, config, next) {
if (!isBucketAuthorized(bucket, requestType, canonicalID, if (!isBucketAuthorized(bucket, requestType, canonicalID, authInfo,
requestArn, log)) { log)) {
log.debug('access denied for user on bucket', { log.debug('access denied for user on bucket', {
requestType, requestType,
method: 'bucketPutWebsite', method: 'bucketPutWebsite',

View File

@ -317,7 +317,6 @@ function multiObjectDelete(authInfo, request, log, callback) {
const bucketName = request.bucketName; const bucketName = request.bucketName;
const canonicalID = authInfo.getCanonicalID(); const canonicalID = authInfo.getCanonicalID();
const requestArn = authInfo.getArn();
return async.waterfall([ return async.waterfall([
function parseXML(next) { function parseXML(next) {
@ -449,8 +448,8 @@ function multiObjectDelete(authInfo, request, log, callback) {
return next(null, quietSetting, errorResults, inPlay, return next(null, quietSetting, errorResults, inPlay,
bucketMD); bucketMD);
} }
if (!isBucketAuthorized(bucketMD, 'objectDelete', if (!isBucketAuthorized(bucketMD, 'objectDelete', canonicalID,
canonicalID, requestArn, log)) { authInfo, log)) {
log.trace("access denied due to bucket acl's"); log.trace("access denied due to bucket acl's");
// if access denied at the bucket level, no access for // if access denied at the bucket level, no access for
// any of the objects so all results will be error results // any of the objects so all results will be error results

View File

@ -83,7 +83,6 @@ function objectPutPart(authInfo, request, streamingV4Params, log,
log.trace('owner canonicalid to send to data', { log.trace('owner canonicalid to send to data', {
canonicalID: authInfo.getCanonicalID, canonicalID: authInfo.getCanonicalID,
}); });
const requestArn = authInfo.getArn();
// Note that keys in the query object retain their case, so // Note that keys in the query object retain their case, so
// `request.query.uploadId` must be called with that exact capitalization. // `request.query.uploadId` must be called with that exact capitalization.
const uploadId = request.query.uploadId; const uploadId = request.query.uploadId;
@ -111,8 +110,8 @@ function objectPutPart(authInfo, request, streamingV4Params, log,
// For validating the request at the destinationBucket level the // For validating the request at the destinationBucket level the
// `requestType` is the general 'objectPut'. // `requestType` is the general 'objectPut'.
const requestType = 'objectPut'; const requestType = 'objectPut';
if (!isBucketAuthorized(destinationBucket, requestType, if (!isBucketAuthorized(destinationBucket, requestType, canonicalID,
canonicalID, requestArn, log)) { authInfo, log)) {
log.debug('access denied for user on bucket', { requestType }); log.debug('access denied for user on bucket', { requestType });
return next(errors.AccessDenied, destinationBucket); return next(errors.AccessDenied, destinationBucket);
} }

View File

@ -176,7 +176,6 @@ function metadataGetObject(bucketName, objectKey, versionId, log, cb) {
function metadataValidateBucketAndObj(params, log, callback) { function metadataValidateBucketAndObj(params, log, callback) {
const { authInfo, bucketName, objectKey, versionId, requestType } = params; const { authInfo, bucketName, objectKey, versionId, requestType } = params;
const canonicalID = authInfo.getCanonicalID(); const canonicalID = authInfo.getCanonicalID();
const requestArn = authInfo.getArn();
async.waterfall([ async.waterfall([
function getBucketAndObjectMD(next) { function getBucketAndObjectMD(next) {
return metadataGetBucketAndObject(requestType, bucketName, return metadataGetBucketAndObject(requestType, bucketName,
@ -184,7 +183,7 @@ function metadataValidateBucketAndObj(params, log, callback) {
}, },
function checkBucketAuth(bucket, objMD, next) { function checkBucketAuth(bucket, objMD, next) {
if (!isBucketAuthorized(bucket, requestType, canonicalID, if (!isBucketAuthorized(bucket, requestType, canonicalID,
requestArn, log)) { authInfo, log)) {
log.debug('access denied for user on bucket', { requestType }); log.debug('access denied for user on bucket', { requestType });
return next(errors.AccessDenied, bucket); return next(errors.AccessDenied, bucket);
} }
@ -202,7 +201,7 @@ function metadataValidateBucketAndObj(params, log, callback) {
return next(null, bucket); return next(null, bucket);
} }
if (!isObjAuthorized(bucket, objMD, requestType, canonicalID, if (!isObjAuthorized(bucket, objMD, requestType, canonicalID,
requestArn, log)) { authInfo, log)) {
log.debug('access denied for user on object', { requestType }); log.debug('access denied for user on object', { requestType });
return next(errors.AccessDenied, bucket); return next(errors.AccessDenied, bucket);
} }
@ -256,13 +255,12 @@ function metadataGetBucket(requestType, bucketName, log, cb) {
function metadataValidateBucket(params, log, callback) { function metadataValidateBucket(params, log, callback) {
const { authInfo, bucketName, requestType } = params; const { authInfo, bucketName, requestType } = params;
const canonicalID = authInfo.getCanonicalID(); const canonicalID = authInfo.getCanonicalID();
const requestArn = authInfo.getArn();
return metadataGetBucket(requestType, bucketName, log, (err, bucket) => { return metadataGetBucket(requestType, bucketName, log, (err, bucket) => {
if (err) { if (err) {
return callback(err); return callback(err);
} }
// still return bucket for cors headers // still return bucket for cors headers
if (!isBucketAuthorized(bucket, requestType, canonicalID, requestArn, if (!isBucketAuthorized(bucket, requestType, canonicalID, authInfo,
log)) { log)) {
log.debug('access denied for user on bucket', { requestType }); log.debug('access denied for user on bucket', { requestType });
return callback(errors.AccessDenied, bucket); return callback(errors.AccessDenied, bucket);

View File

@ -3,20 +3,23 @@ const { BucketInfo, BucketPolicy } = require('arsenal').models;
const constants = require('../../../constants'); const constants = require('../../../constants');
const { isBucketAuthorized, isObjAuthorized, validatePolicyResource } const { isBucketAuthorized, isObjAuthorized, validatePolicyResource }
= require('../../../lib/api/apiUtils/authorization/permissionChecks'); = require('../../../lib/api/apiUtils/authorization/permissionChecks');
const { DummyRequestLogger } = require('../helpers'); const { DummyRequestLogger, makeAuthInfo } = require('../helpers');
const bucketOwnerCanonicalId = 'bucketOwnerCanonicalId'; const accessKey = 'accessKey1';
const altAccessKey = 'accessKey2';
const authInfo = makeAuthInfo(accessKey);
const userAuthInfo = makeAuthInfo(accessKey, 'user');
const altUserAuthInfo = makeAuthInfo(accessKey, 'other');
const altAcctAuthInfo = makeAuthInfo(altAccessKey);
const altAcctUserAuthInfo = makeAuthInfo(altAccessKey, 'altUser');
const bucketOwnerCanonicalId = authInfo.getCanonicalID();
const objectOwnerCanonicalId = userAuthInfo.getCanonicalID();
const canonicalIdToVet = altAcctAuthInfo.getCanonicalID();
const creationDate = new Date().toJSON(); const creationDate = new Date().toJSON();
const bucket = new BucketInfo('policyBucketAuthTester', bucketOwnerCanonicalId, const bucket = new BucketInfo('policyBucketAuthTester', bucketOwnerCanonicalId,
'iAmTheOwnerDisplayName', creationDate); authInfo.getAccountDisplayName(), creationDate);
const objectOwnerCanonicalId = 'objectOwnerCanonicalId';
const object = { 'owner-id': objectOwnerCanonicalId }; const object = { 'owner-id': objectOwnerCanonicalId };
const canonicalIdToVet = 'canonicalIdToVet'; const accountId = authInfo.getShortid();
const userArn = 'arn:aws:iam::123456789012:user/user';
const otherUserArn = 'arn:aws:iam::123456789012:user/other';
const otherAccountUserArn = 'arn:aws:iam:987654321098:user/other';
const accountArn = 'arn:aws:iam::123456789012:root';
const accountId = '123456789012';
const bucAction = 'bucketPut'; const bucAction = 'bucketPut';
const objAction = 'objectPut'; const objAction = 'objectPut';
const basePolicyObj = { const basePolicyObj = {
@ -35,7 +38,9 @@ const authTests = [
{ {
name: 'should allow access if canonical user principal matches non-', name: 'should allow access if canonical user principal matches non-',
bucketId: canonicalIdToVet, bucketId: canonicalIdToVet,
bucketAuthInfo: altAcctAuthInfo,
objectId: canonicalIdToVet, objectId: canonicalIdToVet,
objectAuthInfo: altAcctAuthInfo,
keyToChange: 'Principal', keyToChange: 'Principal',
bucketValue: { CanonicalUser: [canonicalIdToVet] }, bucketValue: { CanonicalUser: [canonicalIdToVet] },
objectValue: { CanonicalUser: [canonicalIdToVet] }, objectValue: { CanonicalUser: [canonicalIdToVet] },
@ -43,26 +48,32 @@ const authTests = [
}, },
{ {
name: 'should allow access if user arn principal matches non-', name: 'should allow access if user arn principal matches non-',
bucketId: userArn, bucketId: objectOwnerCanonicalId,
objectId: userArn, bucketAuthInfo: userAuthInfo,
objectId: objectOwnerCanonicalId,
objectAuthInfo: userAuthInfo,
keyToChange: 'Principal', keyToChange: 'Principal',
bucketValue: { AWS: userArn }, bucketValue: { AWS: userAuthInfo.getArn() },
objectValue: { AWS: userArn }, objectValue: { AWS: userAuthInfo.getArn() },
expected: true, expected: true,
}, },
{ {
name: 'should allow access if account arn principal matches non-', name: 'should allow access if account arn principal matches non-',
bucketId: accountArn, bucketId: bucketOwnerCanonicalId,
objectId: accountArn, bucketAuthInfo: authInfo,
objectId: bucketOwnerCanonicalId,
objectAuthInfo: authInfo,
keyToChange: 'Principal', keyToChange: 'Principal',
bucketValue: { AWS: accountArn }, bucketValue: { AWS: authInfo.getArn() },
objectValue: { AWS: accountArn }, objectValue: { AWS: authInfo.getArn() },
expected: true, expected: true,
}, },
{ {
name: 'should allow access if account id principal matches non-', name: 'should allow access if account id principal matches non-',
bucketId: accountId, bucketId: accountId,
bucketAuthInfo: authInfo,
objectId: accountId, objectId: accountId,
objectAuthInfo: authInfo,
keyToChange: 'Principal', keyToChange: 'Principal',
bucketValue: { AWS: accountId }, bucketValue: { AWS: accountId },
objectValue: { AWS: accountId }, objectValue: { AWS: accountId },
@ -71,8 +82,10 @@ const authTests = [
{ {
name: 'should allow access if account id principal is contained in ' + name: 'should allow access if account id principal is contained in ' +
'user arn of non-', 'user arn of non-',
bucketId: userArn, bucketId: objectOwnerCanonicalId,
objectId: userArn, bucketAuthInfo: userAuthInfo.getArn(),
objectId: objectOwnerCanonicalId,
objectAuthInfo: userAuthInfo.getArn(),
keyToChange: 'Principal', keyToChange: 'Principal',
bucketValue: { AWS: accountId }, bucketValue: { AWS: accountId },
objectValue: { AWS: accountId }, objectValue: { AWS: accountId },
@ -81,8 +94,10 @@ const authTests = [
{ {
name: 'should allow access if account id principal is contained in ' + name: 'should allow access if account id principal is contained in ' +
'account arn of non-', 'account arn of non-',
bucketId: accountArn, bucketId: bucketOwnerCanonicalId,
objectId: accountArn, bucketAuthInfo: authInfo,
objectId: bucketOwnerCanonicalId,
objectAuthInfo: authInfo,
keyToChange: 'Principal', keyToChange: 'Principal',
bucketValue: { AWS: accountId }, bucketValue: { AWS: accountId },
objectValue: { AWS: accountId }, objectValue: { AWS: accountId },
@ -91,37 +106,45 @@ const authTests = [
{ {
name: 'should allow access if account arn principal is contained in ' + name: 'should allow access if account arn principal is contained in ' +
'user arn of non-', 'user arn of non-',
bucketId: userArn, bucketId: objectOwnerCanonicalId,
objectId: userArn, bucketAuthInfo: userAuthInfo,
objectId: objectOwnerCanonicalId,
objectAuthInfo: userAuthInfo,
keyToChange: 'Principal', keyToChange: 'Principal',
bucketValue: { AWS: accountArn }, bucketValue: { AWS: authInfo.getArn() },
objectValue: { AWS: accountArn }, objectValue: { AWS: authInfo.getArn() },
expected: true, expected: true,
}, },
{ {
name: 'should deny access if account arn principal doesn\'t match ' + name: 'should deny access if account arn principal doesn\'t match ' +
'user arn of non-', 'user arn of non-',
bucketId: otherAccountUserArn, bucketId: altAcctUserAuthInfo.getCanonicalID(),
objectId: otherAccountUserArn, bucketAuthInfo: altAcctUserAuthInfo,
objectId: altAcctUserAuthInfo.getCanonicalID(),
objectAuthInfo: altAcctUserAuthInfo,
keyToChange: 'Principal', keyToChange: 'Principal',
bucketValue: { AWS: accountArn }, bucketValue: { AWS: authInfo.getArn() },
objectValue: { AWS: accountArn }, objectValue: { AWS: authInfo.getArn() },
expected: false, expected: false,
}, },
{ {
name: 'should deny access if user arn principal doesn\'t match ' + name: 'should deny access if user arn principal doesn\'t match ' +
'user arn of non-', 'user arn of non-',
bucketId: userArn, bucketId: objectOwnerCanonicalId,
objectId: userArn, bucketAuthInfo: userAuthInfo,
objectId: objectOwnerCanonicalId,
objectAuthInfo: userAuthInfo,
keyToChange: 'Principal', keyToChange: 'Principal',
bucketValue: { AWS: otherUserArn }, bucketValue: { AWS: altUserAuthInfo.getArn() },
objectValue: { AWS: otherUserArn }, objectValue: { AWS: altUserAuthInfo.getArn() },
expected: false, expected: false,
}, },
{ {
name: 'should deny access if principal doesn\'t match non-', name: 'should deny access if principal doesn\'t match non-',
bucketId: canonicalIdToVet, bucketId: canonicalIdToVet,
bucketAuthInfo: altAcctAuthInfo,
objectId: canonicalIdToVet, objectId: canonicalIdToVet,
objectAuthInfo: altAcctAuthInfo,
keyToChange: 'Principal', keyToChange: 'Principal',
bucketValue: { CanonicalUser: [bucketOwnerCanonicalId] }, bucketValue: { CanonicalUser: [bucketOwnerCanonicalId] },
objectValue: { CanonicalUser: [objectOwnerCanonicalId] }, objectValue: { CanonicalUser: [objectOwnerCanonicalId] },
@ -131,7 +154,9 @@ const authTests = [
name: 'should allow access if principal and action match policy for ' + name: 'should allow access if principal and action match policy for ' +
'non-', 'non-',
bucketId: canonicalIdToVet, bucketId: canonicalIdToVet,
bucketAuthInfo: altAcctAuthInfo,
objectId: canonicalIdToVet, objectId: canonicalIdToVet,
objectAuthInfo: altAcctAuthInfo,
keyToChange: 'Action', keyToChange: 'Action',
bucketValue: ['s3:CreateBucket'], bucketValue: ['s3:CreateBucket'],
objectValue: ['s3:PutObject'], objectValue: ['s3:PutObject'],
@ -141,7 +166,9 @@ const authTests = [
name: 'should deny access if principal matches but action does not ' + name: 'should deny access if principal matches but action does not ' +
'match policy for non-', 'match policy for non-',
bucketId: canonicalIdToVet, bucketId: canonicalIdToVet,
bucketAuthInfo: altAcctAuthInfo,
objectId: canonicalIdToVet, objectId: canonicalIdToVet,
objectAuthInfo: altAcctAuthInfo,
keyToChange: 'Action', keyToChange: 'Action',
bucketValue: ['s3:GetBucketLocation'], bucketValue: ['s3:GetBucketLocation'],
objectValue: ['s3:GetObject'], objectValue: ['s3:GetObject'],
@ -150,7 +177,9 @@ const authTests = [
{ {
name: 'should allow access even if bucket policy denies for ', name: 'should allow access even if bucket policy denies for ',
bucketId: bucketOwnerCanonicalId, bucketId: bucketOwnerCanonicalId,
bucketAuthInfo: authInfo,
objectId: objectOwnerCanonicalId, objectId: objectOwnerCanonicalId,
objectAuthInfo: userAuthInfo,
keyToChange: 'Effect', keyToChange: 'Effect',
bucketValue: 'Deny', bucketValue: 'Deny',
objectValue: 'Deny', objectValue: 'Deny',
@ -187,7 +216,7 @@ const resourceTests = [
}, },
]; ];
describe('bucket policy authorization', () => { describe.only('bucket policy authorization', () => {
describe('isBucketAuthorized with no policy set', () => { describe('isBucketAuthorized with no policy set', () => {
it('should allow access to bucket owner', done => { it('should allow access to bucket owner', done => {
const allowed = isBucketAuthorized(bucket, 'bucketPut', const allowed = isBucketAuthorized(bucket, 'bucketPut',
@ -234,7 +263,7 @@ describe('bucket policy authorization', () => {
newPolicy.Statement[0][t.keyToChange] = t.bucketValue; newPolicy.Statement[0][t.keyToChange] = t.bucketValue;
bucket.setBucketPolicy(newPolicy); bucket.setBucketPolicy(newPolicy);
const allowed = isBucketAuthorized(bucket, bucAction, const allowed = isBucketAuthorized(bucket, bucAction,
t.bucketId, t.bucketId, log); t.bucketId, t.bucketAuthInfo, log);
assert.equal(allowed, t.expected); assert.equal(allowed, t.expected);
done(); done();
}); });
@ -310,7 +339,7 @@ describe('bucket policy authorization', () => {
newPolicy.Statement[0][t.keyToChange] = t.objectValue; newPolicy.Statement[0][t.keyToChange] = t.objectValue;
bucket.setBucketPolicy(newPolicy); bucket.setBucketPolicy(newPolicy);
const allowed = isObjAuthorized(bucket, object, objAction, const allowed = isObjAuthorized(bucket, object, objAction,
t.objectId, t.objectId, log); t.objectId, t.objectAuthInfo, log);
assert.equal(allowed, t.expected); assert.equal(allowed, t.expected);
done(); done();
}); });

View File

@ -63,7 +63,7 @@ function timeDiff(startTime) {
return milliseconds; return milliseconds;
} }
function makeAuthInfo(accessKey) { function makeAuthInfo(accessKey, userName) {
const canIdMap = { const canIdMap = {
accessKey1: '79a59df900b949e55d96a1e698fbacedfd6e09d98eacf8f8d5218e7' accessKey1: '79a59df900b949e55d96a1e698fbacedfd6e09d98eacf8f8d5218e7'
+ 'cd47ef2be', + 'cd47ef2be',
@ -73,12 +73,18 @@ function makeAuthInfo(accessKey) {
}; };
canIdMap[constants.publicId] = constants.publicId; canIdMap[constants.publicId] = constants.publicId;
return new AuthInfo({ const params = {
canonicalID: canIdMap[accessKey] || canIdMap.default, canonicalID: canIdMap[accessKey] || canIdMap.default,
shortid: 'shortid', shortid: 'shortid',
email: `${accessKey}@l.com`, email: `${accessKey}@l.com`,
accountDisplayName: `${accessKey}displayName`, accountDisplayName: `${accessKey}displayName`,
}); arn: 'arn:aws:iam::shortid:root',
};
if (userName) {
params.IAMdisplayName = `${accessKey}-${userName}-UserDisplayName`;
params.arn = `arn:aws:iam::shortid:user/${userName}`;
}
return new AuthInfo(params);
} }
class WebsiteConfig { class WebsiteConfig {