Compare commits
4 Commits
developmen
...
task/poc-b
Author | SHA1 | Date |
---|---|---|
williamlardier | f6ab312c46 | |
williamlardier | 89805212c9 | |
williamlardier | 503dc74f4b | |
williamlardier | 65b409fff2 |
|
@ -139,9 +139,10 @@ const api = {
|
||||||
|
|
||||||
function checkAuthResults(authResults) {
|
function checkAuthResults(authResults) {
|
||||||
let returnTagCount = true;
|
let returnTagCount = true;
|
||||||
|
let isImplicitDeny = true;
|
||||||
if (apiMethod === 'objectGet') {
|
if (apiMethod === 'objectGet') {
|
||||||
// first item checks s3:GetObject(Version) action
|
// first item checks s3:GetObject(Version) action
|
||||||
if (!authResults[0].isAllowed) {
|
if (!authResults[0].isAllowed && !authResults[0].isImplicit) {
|
||||||
log.trace('get object authorization denial from Vault');
|
log.trace('get object authorization denial from Vault');
|
||||||
return errors.AccessDenied;
|
return errors.AccessDenied;
|
||||||
}
|
}
|
||||||
|
@ -153,13 +154,18 @@ const api = {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (let i = 0; i < authResults.length; i++) {
|
for (let i = 0; i < authResults.length; i++) {
|
||||||
if (!authResults[i].isAllowed) {
|
if (!authResults[i].isAllowed && !authResults[i].isImplicit) {
|
||||||
|
// Any explicit deny rejects the current APÏ call
|
||||||
log.trace('authorization denial from Vault');
|
log.trace('authorization denial from Vault');
|
||||||
return errors.AccessDenied;
|
return errors.AccessDenied;
|
||||||
|
} else if (authResults[i].isAllowed) {
|
||||||
|
// If the action is allowed, the result is not implicit
|
||||||
|
// Deny.
|
||||||
|
isImplicitDeny = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return returnTagCount;
|
return { returnTagCount, isImplicitDeny };
|
||||||
}
|
}
|
||||||
|
|
||||||
return async.waterfall([
|
return async.waterfall([
|
||||||
|
@ -237,7 +243,8 @@ const api = {
|
||||||
if (checkedResults instanceof Error) {
|
if (checkedResults instanceof Error) {
|
||||||
return callback(checkedResults);
|
return callback(checkedResults);
|
||||||
}
|
}
|
||||||
returnTagCount = checkedResults;
|
returnTagCount = checkedResults.returnTagCount;
|
||||||
|
request.isImplicitIdentityDeny = checkedResults.isImplicitDeny;
|
||||||
}
|
}
|
||||||
if (apiMethod === 'objectPut' || apiMethod === 'objectPutPart') {
|
if (apiMethod === 'objectPut' || apiMethod === 'objectPutPart') {
|
||||||
request._response = response;
|
request._response = response;
|
||||||
|
|
|
@ -8,7 +8,7 @@ const { allAuthedUsersId, bucketOwnerActions, logId, publicId,
|
||||||
const publicReadBuckets = process.env.ALLOW_PUBLIC_READ_BUCKETS ?
|
const publicReadBuckets = process.env.ALLOW_PUBLIC_READ_BUCKETS ?
|
||||||
process.env.ALLOW_PUBLIC_READ_BUCKETS.split(',') : [];
|
process.env.ALLOW_PUBLIC_READ_BUCKETS.split(',') : [];
|
||||||
|
|
||||||
function checkBucketAcls(bucket, requestType, canonicalID) {
|
function checkBucketAcls(bucket, requestType, canonicalID, requesterIsNotUser) {
|
||||||
if (bucket.getOwner() === canonicalID) {
|
if (bucket.getOwner() === canonicalID) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -268,7 +268,18 @@ function checkBucketPolicy(policy, requestType, canonicalID, arn, bucketOwner, l
|
||||||
return permission;
|
return permission;
|
||||||
}
|
}
|
||||||
|
|
||||||
function isBucketAuthorized(bucket, requestType, canonicalID, authInfo, log, request) {
|
function isIdentityAndResourceAuthorized(isImplicitIdentityDeny, resourceAuthzResult) {
|
||||||
|
// If resourceAuthzResult is true, the the IAM result is either Allow or
|
||||||
|
// implicit Deny (nothing applicable): in this case, we allow the request.
|
||||||
|
if (resourceAuthzResult === true) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// If resourceAuthzResult is false, we only return true if IAM result is
|
||||||
|
// Allow. Otherwise we default to an implicit Deny.
|
||||||
|
return isImplicitIdentityDeny === false;
|
||||||
|
}
|
||||||
|
|
||||||
|
function isBucketAuthorized(bucket, requestType, canonicalID, authInfo, isImplicitIdentityDeny, log, request) {
|
||||||
// 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
|
||||||
|
@ -280,32 +291,34 @@ function isBucketAuthorized(bucket, requestType, canonicalID, authInfo, log, req
|
||||||
}
|
}
|
||||||
// if the bucket owner is an account, users should not have default access
|
// if the bucket owner is an account, users should not have default access
|
||||||
if ((bucket.getOwner() === canonicalID) && requesterIsNotUser) {
|
if ((bucket.getOwner() === canonicalID) && requesterIsNotUser) {
|
||||||
return true;
|
return isIdentityAndResourceAuthorized(isImplicitIdentityDeny, true);
|
||||||
}
|
}
|
||||||
const aclPermission = checkBucketAcls(bucket, requestType, canonicalID);
|
const aclPermission = checkBucketAcls(bucket, requestType, canonicalID, requesterIsNotUser);
|
||||||
const bucketPolicy = bucket.getBucketPolicy();
|
const bucketPolicy = bucket.getBucketPolicy();
|
||||||
if (!bucketPolicy) {
|
if (!bucketPolicy) {
|
||||||
return aclPermission;
|
return isIdentityAndResourceAuthorized(isImplicitIdentityDeny, aclPermission);
|
||||||
}
|
}
|
||||||
const bucketPolicyPermission = checkBucketPolicy(bucketPolicy, requestType,
|
const bucketPolicyPermission = checkBucketPolicy(bucketPolicy, requestType,
|
||||||
canonicalID, arn, bucket.getOwner(), log, request);
|
canonicalID, arn, bucket.getOwner(), log, request);
|
||||||
if (bucketPolicyPermission === 'explicitDeny') {
|
if (bucketPolicyPermission === 'explicitDeny') {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return (aclPermission || (bucketPolicyPermission === 'allow'));
|
return isIdentityAndResourceAuthorized(isImplicitIdentityDeny,
|
||||||
|
(aclPermission || (bucketPolicyPermission === 'allow')));
|
||||||
}
|
}
|
||||||
|
|
||||||
function isObjAuthorized(bucket, objectMD, requestType, canonicalID, authInfo, log, request) {
|
function isObjAuthorized(bucket, objectMD, requestType, canonicalID, authInfo, isImplicitIdentityDeny, log, request) {
|
||||||
const bucketOwner = bucket.getOwner();
|
const bucketOwner = bucket.getOwner();
|
||||||
if (!objectMD) {
|
if (!objectMD) {
|
||||||
// User is already authorized on the bucket for FULL_CONTROL or WRITE or
|
// User is already authorized on the bucket for FULL_CONTROL or WRITE or
|
||||||
// bucket has canned ACL public-read-write
|
// bucket has canned ACL public-read-write
|
||||||
if (requestType === 'objectPut' || requestType === 'objectDelete') {
|
if (requestType === 'objectPut' || requestType === 'objectDelete') {
|
||||||
return true;
|
return isIdentityAndResourceAuthorized(isImplicitIdentityDeny, true);
|
||||||
}
|
}
|
||||||
// check bucket has read access
|
// check bucket has read access
|
||||||
// 'bucketGet' covers listObjects and listMultipartUploads, bucket read actions
|
// 'bucketGet' covers listObjects and listMultipartUploads, bucket read actions
|
||||||
return isBucketAuthorized(bucket, 'bucketGet', canonicalID, authInfo, log, request);
|
return isIdentityAndResourceAuthorized(isImplicitIdentityDeny,
|
||||||
|
isBucketAuthorized(bucket, 'bucketGet', canonicalID, authInfo, log, isImplicitIdentityDeny, request));
|
||||||
}
|
}
|
||||||
let requesterIsNotUser = true;
|
let requesterIsNotUser = true;
|
||||||
let arn = null;
|
let arn = null;
|
||||||
|
@ -314,7 +327,7 @@ function isObjAuthorized(bucket, objectMD, requestType, canonicalID, authInfo, l
|
||||||
arn = authInfo.getArn();
|
arn = authInfo.getArn();
|
||||||
}
|
}
|
||||||
if (objectMD['owner-id'] === canonicalID && requesterIsNotUser) {
|
if (objectMD['owner-id'] === canonicalID && requesterIsNotUser) {
|
||||||
return true;
|
return isIdentityAndResourceAuthorized(isImplicitIdentityDeny, true);
|
||||||
}
|
}
|
||||||
// account is authorized if:
|
// account is authorized if:
|
||||||
// - requesttype is included in bucketOwnerActions and
|
// - requesttype is included in bucketOwnerActions and
|
||||||
|
@ -323,20 +336,21 @@ function isObjAuthorized(bucket, objectMD, requestType, canonicalID, authInfo, l
|
||||||
if (bucketOwnerActions.includes(requestType)
|
if (bucketOwnerActions.includes(requestType)
|
||||||
&& (bucketOwner === canonicalID)
|
&& (bucketOwner === canonicalID)
|
||||||
&& requesterIsNotUser) {
|
&& requesterIsNotUser) {
|
||||||
return true;
|
return isIdentityAndResourceAuthorized(isImplicitIdentityDeny, true);
|
||||||
}
|
}
|
||||||
const aclPermission = checkObjectAcls(bucket, objectMD, requestType,
|
const aclPermission = checkObjectAcls(bucket, objectMD, requestType,
|
||||||
canonicalID);
|
canonicalID);
|
||||||
const bucketPolicy = bucket.getBucketPolicy();
|
const bucketPolicy = bucket.getBucketPolicy();
|
||||||
if (!bucketPolicy) {
|
if (!bucketPolicy) {
|
||||||
return aclPermission;
|
return isIdentityAndResourceAuthorized(isImplicitIdentityDeny, aclPermission);
|
||||||
}
|
}
|
||||||
const bucketPolicyPermission = checkBucketPolicy(bucketPolicy, requestType,
|
const bucketPolicyPermission = checkBucketPolicy(bucketPolicy, requestType,
|
||||||
canonicalID, arn, bucket.getOwner(), log, request);
|
canonicalID, arn, bucket.getOwner(), log, request);
|
||||||
if (bucketPolicyPermission === 'explicitDeny') {
|
if (bucketPolicyPermission === 'explicitDeny') {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return (aclPermission || (bucketPolicyPermission === 'allow'));
|
return isIdentityAndResourceAuthorized(isImplicitIdentityDeny,
|
||||||
|
(aclPermission || (bucketPolicyPermission === 'allow')));
|
||||||
}
|
}
|
||||||
|
|
||||||
function _checkResource(resource, bucketArn) {
|
function _checkResource(resource, bucketArn) {
|
||||||
|
|
|
@ -22,10 +22,11 @@ function abortMultipartUpload(authInfo, bucketName, objectKey, uploadId, log,
|
||||||
// but the requestType is the more general 'objectDelete'
|
// but the requestType is the more general 'objectDelete'
|
||||||
const metadataValParams = Object.assign({}, metadataValMPUparams);
|
const metadataValParams = Object.assign({}, metadataValMPUparams);
|
||||||
metadataValParams.requestType = 'objectPut';
|
metadataValParams.requestType = 'objectPut';
|
||||||
|
const authzIdentityResult = request ? request.isImplicitIdentityDeny : true;
|
||||||
|
|
||||||
async.waterfall([
|
async.waterfall([
|
||||||
function checkDestBucketVal(next) {
|
function checkDestBucketVal(next) {
|
||||||
metadataValidateBucketAndObj(metadataValParams, log,
|
metadataValidateBucketAndObj(metadataValParams, authzIdentityResult, log,
|
||||||
(err, destinationBucket) => {
|
(err, destinationBucket) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
return next(err, destinationBucket);
|
return next(err, destinationBucket);
|
||||||
|
|
|
@ -34,7 +34,7 @@ function bucketDelete(authInfo, request, log, cb) {
|
||||||
request,
|
request,
|
||||||
};
|
};
|
||||||
|
|
||||||
return metadataValidateBucket(metadataValParams, log,
|
return metadataValidateBucket(metadataValParams, request.isImplicitIdentityDeny, log,
|
||||||
(err, bucketMD) => {
|
(err, bucketMD) => {
|
||||||
const corsHeaders = collectCorsHeaders(request.headers.origin,
|
const corsHeaders = collectCorsHeaders(request.headers.origin,
|
||||||
request.method, bucketMD);
|
request.method, bucketMD);
|
||||||
|
|
|
@ -26,7 +26,7 @@ function bucketDeleteEncryption(authInfo, request, log, callback) {
|
||||||
};
|
};
|
||||||
|
|
||||||
return async.waterfall([
|
return async.waterfall([
|
||||||
next => metadataValidateBucket(metadataValParams, log, next),
|
next => metadataValidateBucket(metadataValParams, request.isImplicitIdentityDeny, log, next),
|
||||||
(bucket, next) => checkExpectedBucketOwner(request.headers, bucket, log, err => next(err, bucket)),
|
(bucket, next) => checkExpectedBucketOwner(request.headers, bucket, log, err => next(err, bucket)),
|
||||||
(bucket, next) => {
|
(bucket, next) => {
|
||||||
const sseConfig = bucket.getServerSideEncryption();
|
const sseConfig = bucket.getServerSideEncryption();
|
||||||
|
|
|
@ -21,7 +21,7 @@ function bucketDeleteLifecycle(authInfo, request, log, callback) {
|
||||||
requestType: 'bucketDeleteLifecycle',
|
requestType: 'bucketDeleteLifecycle',
|
||||||
request,
|
request,
|
||||||
};
|
};
|
||||||
return metadataValidateBucket(metadataValParams, log, (err, bucket) => {
|
return metadataValidateBucket(metadataValParams, request.isImplicitIdentityDeny, log, (err, bucket) => {
|
||||||
const corsHeaders = collectCorsHeaders(headers.origin, method, bucket);
|
const corsHeaders = collectCorsHeaders(headers.origin, method, bucket);
|
||||||
if (err) {
|
if (err) {
|
||||||
log.debug('error processing request', {
|
log.debug('error processing request', {
|
||||||
|
|
|
@ -19,7 +19,7 @@ function bucketDeletePolicy(authInfo, request, log, callback) {
|
||||||
requestType: 'bucketDeletePolicy',
|
requestType: 'bucketDeletePolicy',
|
||||||
request,
|
request,
|
||||||
};
|
};
|
||||||
return metadataValidateBucket(metadataValParams, log, (err, bucket) => {
|
return metadataValidateBucket(metadataValParams, request.isImplicitIdentityDeny, log, (err, bucket) => {
|
||||||
const corsHeaders = collectCorsHeaders(headers.origin, method, bucket);
|
const corsHeaders = collectCorsHeaders(headers.origin, method, bucket);
|
||||||
if (err) {
|
if (err) {
|
||||||
log.debug('error processing request', {
|
log.debug('error processing request', {
|
||||||
|
|
|
@ -21,7 +21,7 @@ function bucketDeleteReplication(authInfo, request, log, callback) {
|
||||||
requestType: 'bucketDeleteReplication',
|
requestType: 'bucketDeleteReplication',
|
||||||
request,
|
request,
|
||||||
};
|
};
|
||||||
return metadataValidateBucket(metadataValParams, log, (err, bucket) => {
|
return metadataValidateBucket(metadataValParams, request.isImplicitIdentityDeny, log, (err, bucket) => {
|
||||||
const corsHeaders = collectCorsHeaders(headers.origin, method, bucket);
|
const corsHeaders = collectCorsHeaders(headers.origin, method, bucket);
|
||||||
if (err) {
|
if (err) {
|
||||||
log.debug('error processing request', {
|
log.debug('error processing request', {
|
||||||
|
|
|
@ -351,7 +351,7 @@ function bucketGet(authInfo, request, log, callback) {
|
||||||
listParams.marker = params.marker;
|
listParams.marker = params.marker;
|
||||||
}
|
}
|
||||||
|
|
||||||
metadataValidateBucket(metadataValParams, log, (err, bucket) => {
|
metadataValidateBucket(metadataValParams, request.isImplicitIdentityDeny, log, (err, bucket) => {
|
||||||
const corsHeaders = collectCorsHeaders(request.headers.origin,
|
const corsHeaders = collectCorsHeaders(request.headers.origin,
|
||||||
request.method, bucket);
|
request.method, bucket);
|
||||||
if (err) {
|
if (err) {
|
||||||
|
|
|
@ -55,7 +55,7 @@ function bucketGetACL(authInfo, request, log, callback) {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
metadataValidateBucket(metadataValParams, log, (err, bucket) => {
|
metadataValidateBucket(metadataValParams, request.isImplicitIdentityDeny, log, (err, bucket) => {
|
||||||
const corsHeaders = collectCorsHeaders(request.headers.origin,
|
const corsHeaders = collectCorsHeaders(request.headers.origin,
|
||||||
request.method, bucket);
|
request.method, bucket);
|
||||||
if (err) {
|
if (err) {
|
||||||
|
|
|
@ -27,7 +27,7 @@ function bucketGetEncryption(authInfo, request, log, callback) {
|
||||||
};
|
};
|
||||||
|
|
||||||
return async.waterfall([
|
return async.waterfall([
|
||||||
next => metadataValidateBucket(metadataValParams, log, next),
|
next => metadataValidateBucket(metadataValParams, request.isImplicitIdentityDeny, log, next),
|
||||||
(bucket, next) => checkExpectedBucketOwner(request.headers, bucket, log, err => next(err, bucket)),
|
(bucket, next) => checkExpectedBucketOwner(request.headers, bucket, log, err => next(err, bucket)),
|
||||||
(bucket, next) => {
|
(bucket, next) => {
|
||||||
// If sseInfo is present but the `mandatory` flag is not set
|
// If sseInfo is present but the `mandatory` flag is not set
|
||||||
|
|
|
@ -24,7 +24,7 @@ function bucketGetLifecycle(authInfo, request, log, callback) {
|
||||||
requestType: 'bucketGetLifecycle',
|
requestType: 'bucketGetLifecycle',
|
||||||
request,
|
request,
|
||||||
};
|
};
|
||||||
return metadataValidateBucket(metadataValParams, log, (err, bucket) => {
|
return metadataValidateBucket(metadataValParams, request.isImplicitIdentityDeny, log, (err, bucket) => {
|
||||||
const corsHeaders = collectCorsHeaders(headers.origin, method, bucket);
|
const corsHeaders = collectCorsHeaders(headers.origin, method, bucket);
|
||||||
if (err) {
|
if (err) {
|
||||||
log.debug('error processing request', {
|
log.debug('error processing request', {
|
||||||
|
|
|
@ -41,7 +41,7 @@ function bucketGetNotification(authInfo, request, log, callback) {
|
||||||
request,
|
request,
|
||||||
};
|
};
|
||||||
|
|
||||||
return metadataValidateBucket(metadataValParams, log, (err, bucket) => {
|
return metadataValidateBucket(metadataValParams, request.isImplicitIdentityDeny, log, (err, bucket) => {
|
||||||
const corsHeaders = collectCorsHeaders(headers.origin, method, bucket);
|
const corsHeaders = collectCorsHeaders(headers.origin, method, bucket);
|
||||||
if (err) {
|
if (err) {
|
||||||
log.debug('error processing request', {
|
log.debug('error processing request', {
|
||||||
|
|
|
@ -36,7 +36,7 @@ function bucketGetObjectLock(authInfo, request, log, callback) {
|
||||||
requestType: 'bucketGetObjectLock',
|
requestType: 'bucketGetObjectLock',
|
||||||
request,
|
request,
|
||||||
};
|
};
|
||||||
return metadataValidateBucket(metadataValParams, log, (err, bucket) => {
|
return metadataValidateBucket(metadataValParams, request.isImplicitIdentityDeny, log, (err, bucket) => {
|
||||||
const corsHeaders = collectCorsHeaders(headers.origin, method, bucket);
|
const corsHeaders = collectCorsHeaders(headers.origin, method, bucket);
|
||||||
if (err) {
|
if (err) {
|
||||||
log.debug('error processing request', {
|
log.debug('error processing request', {
|
||||||
|
|
|
@ -21,7 +21,7 @@ function bucketGetPolicy(authInfo, request, log, callback) {
|
||||||
request,
|
request,
|
||||||
};
|
};
|
||||||
|
|
||||||
return metadataValidateBucket(metadataValParams, log, (err, bucket) => {
|
return metadataValidateBucket(metadataValParams, request.isImplicitIdentityDeny, log, (err, bucket) => {
|
||||||
const corsHeaders = collectCorsHeaders(headers.origin, method, bucket);
|
const corsHeaders = collectCorsHeaders(headers.origin, method, bucket);
|
||||||
if (err) {
|
if (err) {
|
||||||
log.debug('error processing request', {
|
log.debug('error processing request', {
|
||||||
|
|
|
@ -24,7 +24,7 @@ function bucketGetReplication(authInfo, request, log, callback) {
|
||||||
requestType: 'bucketGetReplication',
|
requestType: 'bucketGetReplication',
|
||||||
request,
|
request,
|
||||||
};
|
};
|
||||||
return metadataValidateBucket(metadataValParams, log, (err, bucket) => {
|
return metadataValidateBucket(metadataValParams, request.isImplicitIdentityDeny, log, (err, bucket) => {
|
||||||
const corsHeaders = collectCorsHeaders(headers.origin, method, bucket);
|
const corsHeaders = collectCorsHeaders(headers.origin, method, bucket);
|
||||||
if (err) {
|
if (err) {
|
||||||
log.debug('error processing request', {
|
log.debug('error processing request', {
|
||||||
|
|
|
@ -58,7 +58,7 @@ function bucketGetVersioning(authInfo, request, log, callback) {
|
||||||
request,
|
request,
|
||||||
};
|
};
|
||||||
|
|
||||||
metadataValidateBucket(metadataValParams, log, (err, bucket) => {
|
metadataValidateBucket(metadataValParams, log, request.isImplicitIdentityDeny, (err, bucket) => {
|
||||||
const corsHeaders = collectCorsHeaders(request.headers.origin,
|
const corsHeaders = collectCorsHeaders(request.headers.origin,
|
||||||
request.method, bucket);
|
request.method, bucket);
|
||||||
if (err) {
|
if (err) {
|
||||||
|
|
|
@ -22,7 +22,7 @@ function bucketHead(authInfo, request, log, callback) {
|
||||||
requestType: 'bucketHead',
|
requestType: 'bucketHead',
|
||||||
request,
|
request,
|
||||||
};
|
};
|
||||||
metadataValidateBucket(metadataValParams, log, (err, bucket) => {
|
metadataValidateBucket(metadataValParams, request.isImplicitIdentityDeny, log, (err, bucket) => {
|
||||||
const corsHeaders = collectCorsHeaders(request.headers.origin,
|
const corsHeaders = collectCorsHeaders(request.headers.origin,
|
||||||
request.method, bucket);
|
request.method, bucket);
|
||||||
if (err) {
|
if (err) {
|
||||||
|
|
|
@ -105,7 +105,7 @@ function bucketPutACL(authInfo, request, log, callback) {
|
||||||
|
|
||||||
return async.waterfall([
|
return async.waterfall([
|
||||||
function waterfall1(next) {
|
function waterfall1(next) {
|
||||||
metadataValidateBucket(metadataValParams, log,
|
metadataValidateBucket(metadataValParams, request.isImplicitIdentityDeny, log,
|
||||||
(err, bucket) => {
|
(err, bucket) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
log.trace('request authorization failed', {
|
log.trace('request authorization failed', {
|
||||||
|
|
|
@ -28,7 +28,7 @@ function bucketPutEncryption(authInfo, request, log, callback) {
|
||||||
};
|
};
|
||||||
|
|
||||||
return async.waterfall([
|
return async.waterfall([
|
||||||
next => metadataValidateBucket(metadataValParams, log, next),
|
next => metadataValidateBucket(metadataValParams, request.isImplicitIdentityDeny, log, next),
|
||||||
(bucket, next) => checkExpectedBucketOwner(request.headers, bucket, log, err => next(err, bucket)),
|
(bucket, next) => checkExpectedBucketOwner(request.headers, bucket, log, err => next(err, bucket)),
|
||||||
(bucket, next) => {
|
(bucket, next) => {
|
||||||
log.trace('parsing encryption config', { method: 'bucketPutEncryption' });
|
log.trace('parsing encryption config', { method: 'bucketPutEncryption' });
|
||||||
|
|
|
@ -43,7 +43,7 @@ function bucketPutLifecycle(authInfo, request, log, callback) {
|
||||||
return next(null, configObj);
|
return next(null, configObj);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
(lcConfig, next) => metadataValidateBucket(metadataValParams, log,
|
(lcConfig, next) => metadataValidateBucket(metadataValParams, request.isImplicitIdentityDeny, log,
|
||||||
(err, bucket) => {
|
(err, bucket) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
return next(err, bucket);
|
return next(err, bucket);
|
||||||
|
|
|
@ -34,7 +34,7 @@ function bucketPutNotification(authInfo, request, log, callback) {
|
||||||
const notifConfig = notificationConfig.error ? undefined : notificationConfig;
|
const notifConfig = notificationConfig.error ? undefined : notificationConfig;
|
||||||
process.nextTick(() => next(notificationConfig.error, notifConfig));
|
process.nextTick(() => next(notificationConfig.error, notifConfig));
|
||||||
},
|
},
|
||||||
(notifConfig, next) => metadataValidateBucket(metadataValParams, log,
|
(notifConfig, next) => metadataValidateBucket(metadataValParams, request.isImplicitIdentityDeny, log,
|
||||||
(err, bucket) => next(err, bucket, notifConfig)),
|
(err, bucket) => next(err, bucket, notifConfig)),
|
||||||
(bucket, notifConfig, next) => {
|
(bucket, notifConfig, next) => {
|
||||||
bucket.setNotificationConfiguration(notifConfig);
|
bucket.setNotificationConfiguration(notifConfig);
|
||||||
|
|
|
@ -41,7 +41,7 @@ function bucketPutObjectLock(authInfo, request, log, callback) {
|
||||||
return next(configObj.error || null, configObj);
|
return next(configObj.error || null, configObj);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
(objectLockConfig, next) => metadataValidateBucket(metadataValParams,
|
(objectLockConfig, next) => metadataValidateBucket(metadataValParams, request.isImplicitIdentityDeny,
|
||||||
log, (err, bucket) => {
|
log, (err, bucket) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
return next(err, bucket);
|
return next(err, bucket);
|
||||||
|
|
|
@ -70,7 +70,7 @@ function bucketPutPolicy(authInfo, request, log, callback) {
|
||||||
return next(null, bucketPolicy);
|
return next(null, bucketPolicy);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
(bucketPolicy, next) => metadataValidateBucket(metadataValParams, log,
|
(bucketPolicy, next) => metadataValidateBucket(metadataValParams, request.isImplicitIdentityDeny, log,
|
||||||
(err, bucket) => {
|
(err, bucket) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
return next(err, bucket);
|
return next(err, bucket);
|
||||||
|
|
|
@ -37,7 +37,7 @@ function bucketPutReplication(authInfo, request, log, callback) {
|
||||||
// Check bucket user privileges and ensure versioning is 'Enabled'.
|
// Check bucket user privileges and ensure versioning is 'Enabled'.
|
||||||
(config, next) =>
|
(config, next) =>
|
||||||
// TODO: Validate that destination bucket exists and has versioning.
|
// TODO: Validate that destination bucket exists and has versioning.
|
||||||
metadataValidateBucket(metadataValParams, log, (err, bucket) => {
|
metadataValidateBucket(metadataValParams, request.isImplicitIdentityDeny, log, (err, bucket) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
return next(err);
|
return next(err);
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,7 +42,7 @@ function bucketPutTagging(authInfo, request, log, callback) {
|
||||||
};
|
};
|
||||||
let bucket = null;
|
let bucket = null;
|
||||||
return waterfall([
|
return waterfall([
|
||||||
next => metadataValidateBucket(metadataValParams, log,
|
next => metadataValidateBucket(metadataValParams, request.isImplicitIdentityDeny, log,
|
||||||
(err, b) => {
|
(err, b) => {
|
||||||
bucket = b;
|
bucket = b;
|
||||||
return next(err);
|
return next(err);
|
||||||
|
|
|
@ -94,7 +94,7 @@ function bucketPutVersioning(authInfo, request, log, callback) {
|
||||||
|
|
||||||
return waterfall([
|
return waterfall([
|
||||||
next => _parseXML(request, log, next),
|
next => _parseXML(request, log, next),
|
||||||
next => metadataValidateBucket(metadataValParams, log,
|
next => metadataValidateBucket(metadataValParams, request.isImplicitIdentityDeny, log,
|
||||||
(err, bucket) => next(err, bucket)), // ignore extra null object,
|
(err, bucket) => next(err, bucket)), // ignore extra null object,
|
||||||
(bucket, next) => parseString(request.post, (err, result) => {
|
(bucket, next) => parseString(request.post, (err, result) => {
|
||||||
// just for linting; there should not be any parsing error here
|
// just for linting; there should not be any parsing error here
|
||||||
|
|
|
@ -120,7 +120,7 @@ function completeMultipartUpload(authInfo, request, log, callback) {
|
||||||
// at the destinationBucket level are same as objectPut
|
// at the destinationBucket level are same as objectPut
|
||||||
requestType: 'objectPut',
|
requestType: 'objectPut',
|
||||||
};
|
};
|
||||||
metadataValidateBucketAndObj(metadataValParams, log, next);
|
metadataValidateBucketAndObj(metadataValParams, request.isImplicitIdentityDeny, log, next);
|
||||||
},
|
},
|
||||||
function validateMultipart(destBucket, objMD, next) {
|
function validateMultipart(destBucket, objMD, next) {
|
||||||
if (objMD) {
|
if (objMD) {
|
||||||
|
|
|
@ -262,7 +262,7 @@ function initiateMultipartUpload(authInfo, request, log, callback) {
|
||||||
}
|
}
|
||||||
|
|
||||||
async.waterfall([
|
async.waterfall([
|
||||||
next => metadataValidateBucketAndObj(metadataValParams, log,
|
next => metadataValidateBucketAndObj(metadataValParams, request.isImplicitIdentityDeny, log,
|
||||||
(error, destinationBucket) => {
|
(error, destinationBucket) => {
|
||||||
const corsHeaders = collectCorsHeaders(request.headers.origin,
|
const corsHeaders = collectCorsHeaders(request.headers.origin,
|
||||||
request.method, destinationBucket);
|
request.method, destinationBucket);
|
||||||
|
|
|
@ -105,7 +105,7 @@ function listMultipartUploads(authInfo, request, log, callback) {
|
||||||
function waterfall1(next) {
|
function waterfall1(next) {
|
||||||
// Check final destination bucket for authorization rather
|
// Check final destination bucket for authorization rather
|
||||||
// than multipart upload bucket
|
// than multipart upload bucket
|
||||||
metadataValidateBucket(metadataValParams, log,
|
metadataValidateBucket(metadataValParams, request.isImplicitIdentityDeny, log,
|
||||||
(err, bucket) => next(err, bucket));
|
(err, bucket) => next(err, bucket));
|
||||||
},
|
},
|
||||||
function getMPUBucket(bucket, next) {
|
function getMPUBucket(bucket, next) {
|
||||||
|
|
|
@ -115,7 +115,7 @@ function listParts(authInfo, request, log, callback) {
|
||||||
|
|
||||||
async.waterfall([
|
async.waterfall([
|
||||||
function checkDestBucketVal(next) {
|
function checkDestBucketVal(next) {
|
||||||
metadataValidateBucketAndObj(metadataValParams, log,
|
metadataValidateBucketAndObj(metadataValParams, request.isImplicitIdentityDeny, log,
|
||||||
(err, destinationBucket) => {
|
(err, destinationBucket) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
return next(err, destinationBucket, null);
|
return next(err, destinationBucket, null);
|
||||||
|
|
|
@ -249,7 +249,7 @@ function objectCopy(authInfo, request, sourceBucket,
|
||||||
}
|
}
|
||||||
return async.waterfall([
|
return async.waterfall([
|
||||||
function checkDestAuth(next) {
|
function checkDestAuth(next) {
|
||||||
return metadataValidateBucketAndObj(valPutParams, log,
|
return metadataValidateBucketAndObj(valPutParams, request.isImplicitIdentityDeny, log,
|
||||||
(err, destBucketMD, destObjMD) => {
|
(err, destBucketMD, destObjMD) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
log.debug('error validating put part of request',
|
log.debug('error validating put part of request',
|
||||||
|
@ -267,7 +267,7 @@ function objectCopy(authInfo, request, sourceBucket,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
function checkSourceAuthorization(destBucketMD, destObjMD, next) {
|
function checkSourceAuthorization(destBucketMD, destObjMD, next) {
|
||||||
return metadataValidateBucketAndObj(valGetParams, log,
|
return metadataValidateBucketAndObj(valGetParams, request.isImplicitIdentityDeny, log,
|
||||||
(err, sourceBucketMD, sourceObjMD) => {
|
(err, sourceBucketMD, sourceObjMD) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
log.debug('error validating get part of request',
|
log.debug('error validating get part of request',
|
||||||
|
|
|
@ -59,7 +59,7 @@ function objectDelete(authInfo, request, log, cb) {
|
||||||
const canonicalID = authInfo.getCanonicalID();
|
const canonicalID = authInfo.getCanonicalID();
|
||||||
return async.waterfall([
|
return async.waterfall([
|
||||||
function validateBucketAndObj(next) {
|
function validateBucketAndObj(next) {
|
||||||
return metadataValidateBucketAndObj(valParams, log,
|
return metadataValidateBucketAndObj(valParams, request.isImplicitIdentityDeny, log,
|
||||||
(err, bucketMD, objMD) => {
|
(err, bucketMD, objMD) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
return next(err, bucketMD);
|
return next(err, bucketMD);
|
||||||
|
|
|
@ -49,7 +49,7 @@ function objectDeleteTagging(authInfo, request, log, callback) {
|
||||||
};
|
};
|
||||||
|
|
||||||
return async.waterfall([
|
return async.waterfall([
|
||||||
next => metadataValidateBucketAndObj(metadataValParams, log,
|
next => metadataValidateBucketAndObj(metadataValParams, request.isImplicitIdentityDeny, log,
|
||||||
(err, bucket, objectMD) => {
|
(err, bucket, objectMD) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
log.trace('request authorization failed',
|
log.trace('request authorization failed',
|
||||||
|
|
|
@ -50,7 +50,7 @@ function objectGet(authInfo, request, returnTagCount, log, callback) {
|
||||||
request,
|
request,
|
||||||
};
|
};
|
||||||
|
|
||||||
return metadataValidateBucketAndObj(mdValParams, log,
|
return metadataValidateBucketAndObj(mdValParams, request.isImplicitIdentityDeny, log,
|
||||||
(err, bucket, objMD) => {
|
(err, bucket, objMD) => {
|
||||||
const corsHeaders = collectCorsHeaders(request.headers.origin,
|
const corsHeaders = collectCorsHeaders(request.headers.origin,
|
||||||
request.method, bucket);
|
request.method, bucket);
|
||||||
|
|
|
@ -74,7 +74,7 @@ function objectGetACL(authInfo, request, log, callback) {
|
||||||
|
|
||||||
return async.waterfall([
|
return async.waterfall([
|
||||||
function validateBucketAndObj(next) {
|
function validateBucketAndObj(next) {
|
||||||
return metadataValidateBucketAndObj(metadataValParams, log,
|
return metadataValidateBucketAndObj(metadataValParams, request.isImplicitIdentityDeny, log,
|
||||||
(err, bucket, objectMD) => {
|
(err, bucket, objectMD) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
log.trace('request authorization failed',
|
log.trace('request authorization failed',
|
||||||
|
|
|
@ -45,7 +45,7 @@ function objectGetLegalHold(authInfo, request, log, callback) {
|
||||||
};
|
};
|
||||||
|
|
||||||
return async.waterfall([
|
return async.waterfall([
|
||||||
next => metadataValidateBucketAndObj(metadataValParams, log,
|
next => metadataValidateBucketAndObj(metadataValParams, request.isImplicitIdentityDeny, log,
|
||||||
(err, bucket, objectMD) => {
|
(err, bucket, objectMD) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
log.trace('request authorization failed',
|
log.trace('request authorization failed',
|
||||||
|
|
|
@ -45,7 +45,7 @@ function objectGetRetention(authInfo, request, log, callback) {
|
||||||
};
|
};
|
||||||
|
|
||||||
return async.waterfall([
|
return async.waterfall([
|
||||||
next => metadataValidateBucketAndObj(metadataValParams, log,
|
next => metadataValidateBucketAndObj(metadataValParams, request.isImplicitIdentityDeny, log,
|
||||||
(err, bucket, objectMD) => {
|
(err, bucket, objectMD) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
log.trace('request authorization failed',
|
log.trace('request authorization failed',
|
||||||
|
|
|
@ -46,7 +46,7 @@ function objectGetTagging(authInfo, request, log, callback) {
|
||||||
};
|
};
|
||||||
|
|
||||||
return async.waterfall([
|
return async.waterfall([
|
||||||
next => metadataValidateBucketAndObj(metadataValParams, log,
|
next => metadataValidateBucketAndObj(metadataValParams, request.isImplicitIdentityDeny, log,
|
||||||
(err, bucket, objectMD) => {
|
(err, bucket, objectMD) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
log.trace('request authorization failed',
|
log.trace('request authorization failed',
|
||||||
|
|
|
@ -50,7 +50,7 @@ function objectHead(authInfo, request, log, callback) {
|
||||||
request,
|
request,
|
||||||
};
|
};
|
||||||
|
|
||||||
return metadataValidateBucketAndObj(mdValParams, log,
|
return metadataValidateBucketAndObj(mdValParams, request.isImplicitIdentityDeny, log,
|
||||||
(err, bucket, objMD) => {
|
(err, bucket, objMD) => {
|
||||||
const corsHeaders = collectCorsHeaders(request.headers.origin,
|
const corsHeaders = collectCorsHeaders(request.headers.origin,
|
||||||
request.method, bucket);
|
request.method, bucket);
|
||||||
|
|
|
@ -71,7 +71,7 @@ function objectPut(authInfo, request, streamingV4Params, log, callback) {
|
||||||
|
|
||||||
log.trace('owner canonicalID to send to data', { canonicalID });
|
log.trace('owner canonicalID to send to data', { canonicalID });
|
||||||
|
|
||||||
return metadataValidateBucketAndObj(valParams, log,
|
return metadataValidateBucketAndObj(valParams, request.isImplicitIdentityDeny, log,
|
||||||
(err, bucket, objMD) => {
|
(err, bucket, objMD) => {
|
||||||
const responseHeaders = collectCorsHeaders(headers.origin,
|
const responseHeaders = collectCorsHeaders(headers.origin,
|
||||||
method, bucket);
|
method, bucket);
|
||||||
|
|
|
@ -112,7 +112,7 @@ function objectPutACL(authInfo, request, log, cb) {
|
||||||
|
|
||||||
return async.waterfall([
|
return async.waterfall([
|
||||||
function validateBucketAndObj(next) {
|
function validateBucketAndObj(next) {
|
||||||
return metadataValidateBucketAndObj(metadataValParams, log,
|
return metadataValidateBucketAndObj(metadataValParams, request.isImplicitIdentityDeny, log,
|
||||||
(err, bucket, objectMD) => {
|
(err, bucket, objectMD) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
return next(err);
|
return next(err);
|
||||||
|
|
|
@ -93,7 +93,7 @@ function objectPutCopyPart(authInfo, request, sourceBucket,
|
||||||
|
|
||||||
return async.waterfall([
|
return async.waterfall([
|
||||||
function checkDestAuth(next) {
|
function checkDestAuth(next) {
|
||||||
return metadataValidateBucketAndObj(valPutParams, log,
|
return metadataValidateBucketAndObj(valPutParams, request.isImplicitIdentityDeny, log,
|
||||||
(err, destBucketMD) => {
|
(err, destBucketMD) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
log.debug('error validating authorization for ' +
|
log.debug('error validating authorization for ' +
|
||||||
|
@ -112,7 +112,7 @@ function objectPutCopyPart(authInfo, request, sourceBucket,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
function checkSourceAuthorization(destBucketMD, next) {
|
function checkSourceAuthorization(destBucketMD, next) {
|
||||||
return metadataValidateBucketAndObj(valGetParams, log,
|
return metadataValidateBucketAndObj(valGetParams, request.isImplicitIdentityDeny, log,
|
||||||
(err, sourceBucketMD, sourceObjMD) => {
|
(err, sourceBucketMD, sourceObjMD) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
log.debug('error validating get part of request',
|
log.debug('error validating get part of request',
|
||||||
|
|
|
@ -48,7 +48,7 @@ function objectPutLegalHold(authInfo, request, log, callback) {
|
||||||
};
|
};
|
||||||
|
|
||||||
return async.waterfall([
|
return async.waterfall([
|
||||||
next => metadataValidateBucketAndObj(metadataValParams, log,
|
next => metadataValidateBucketAndObj(metadataValParams, request.isImplicitIdentityDeny, log,
|
||||||
(err, bucket, objectMD) => {
|
(err, bucket, objectMD) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
log.trace('request authorization failed',
|
log.trace('request authorization failed',
|
||||||
|
|
|
@ -49,7 +49,7 @@ function objectPutRetention(authInfo, request, log, callback) {
|
||||||
};
|
};
|
||||||
|
|
||||||
return async.waterfall([
|
return async.waterfall([
|
||||||
next => metadataValidateBucketAndObj(metadataValParams, log,
|
next => metadataValidateBucketAndObj(metadataValParams, request.isImplicitIdentityDeny, log,
|
||||||
(err, bucket, objectMD) => {
|
(err, bucket, objectMD) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
log.trace('request authorization failed',
|
log.trace('request authorization failed',
|
||||||
|
|
|
@ -50,7 +50,7 @@ function objectPutTagging(authInfo, request, log, callback) {
|
||||||
};
|
};
|
||||||
|
|
||||||
return async.waterfall([
|
return async.waterfall([
|
||||||
next => metadataValidateBucketAndObj(metadataValParams, log,
|
next => metadataValidateBucketAndObj(metadataValParams, request.isImplicitIdentityDeny, log,
|
||||||
(err, bucket, objectMD) => {
|
(err, bucket, objectMD) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
log.trace('request authorization failed',
|
log.trace('request authorization failed',
|
||||||
|
|
|
@ -94,6 +94,7 @@ function metadataGetObject(bucketName, objectKey, versionId, log, cb) {
|
||||||
* @param {string} params.requestType - type of request
|
* @param {string} params.requestType - type of request
|
||||||
* @param {string} [params.preciseRequestType] - precise type of request
|
* @param {string} [params.preciseRequestType] - precise type of request
|
||||||
* @param {object} params.request - http request object
|
* @param {object} params.request - http request object
|
||||||
|
* @param {object} isImplicitIdentityDeny - identity authorization results
|
||||||
* @param {RequestLogger} log - request logger
|
* @param {RequestLogger} log - request logger
|
||||||
* @return {ArsenalError|null} returns a validation error, or null if validation OK
|
* @return {ArsenalError|null} returns a validation error, or null if validation OK
|
||||||
* The following errors may be returned:
|
* The following errors may be returned:
|
||||||
|
@ -102,7 +103,7 @@ function metadataGetObject(bucketName, objectKey, versionId, log, cb) {
|
||||||
* bucket policy operation
|
* bucket policy operation
|
||||||
* - AccessDenied: bucket is not authorized
|
* - AccessDenied: bucket is not authorized
|
||||||
*/
|
*/
|
||||||
function validateBucket(bucket, params, log) {
|
function validateBucket(bucket, params, isImplicitIdentityDeny, log) {
|
||||||
const { authInfo, requestType, preciseRequestType, request } = params;
|
const { authInfo, requestType, preciseRequestType, request } = params;
|
||||||
if (bucketShield(bucket, requestType)) {
|
if (bucketShield(bucket, requestType)) {
|
||||||
log.debug('bucket is shielded from request', {
|
log.debug('bucket is shielded from request', {
|
||||||
|
@ -119,7 +120,7 @@ function validateBucket(bucket, params, log) {
|
||||||
return errors.MethodNotAllowed;
|
return errors.MethodNotAllowed;
|
||||||
}
|
}
|
||||||
if (!isBucketAuthorized(bucket, (preciseRequestType || requestType), canonicalID,
|
if (!isBucketAuthorized(bucket, (preciseRequestType || requestType), canonicalID,
|
||||||
authInfo, log, request)) {
|
authInfo, isImplicitIdentityDeny, log, request)) {
|
||||||
log.debug('access denied for user on bucket', { requestType });
|
log.debug('access denied for user on bucket', { requestType });
|
||||||
return errors.AccessDenied;
|
return errors.AccessDenied;
|
||||||
}
|
}
|
||||||
|
@ -135,11 +136,12 @@ function validateBucket(bucket, params, log) {
|
||||||
* @param {string} [params.versionId] - version id if getting specific version
|
* @param {string} [params.versionId] - version id if getting specific version
|
||||||
* @param {string} params.requestType - type of request
|
* @param {string} params.requestType - type of request
|
||||||
* @param {object} params.request - http request object
|
* @param {object} params.request - http request object
|
||||||
|
* @param {boolean} isImplicitIdentityDeny - identity authorization results
|
||||||
* @param {RequestLogger} log - request logger
|
* @param {RequestLogger} log - request logger
|
||||||
* @param {function} callback - callback
|
* @param {function} callback - callback
|
||||||
* @return {undefined} - and call callback with params err, bucket md
|
* @return {undefined} - and call callback with params err, bucket md
|
||||||
*/
|
*/
|
||||||
function metadataValidateBucketAndObj(params, log, callback) {
|
function metadataValidateBucketAndObj(params, isImplicitIdentityDeny, log, callback) {
|
||||||
const { authInfo, bucketName, objectKey, versionId, getDeleteMarker,
|
const { authInfo, bucketName, objectKey, versionId, getDeleteMarker,
|
||||||
requestType, request } = params;
|
requestType, request } = params;
|
||||||
async.waterfall([
|
async.waterfall([
|
||||||
|
@ -161,7 +163,7 @@ function metadataValidateBucketAndObj(params, log, callback) {
|
||||||
});
|
});
|
||||||
return next(errors.NoSuchBucket);
|
return next(errors.NoSuchBucket);
|
||||||
}
|
}
|
||||||
const validationError = validateBucket(bucket, params, log);
|
const validationError = validateBucket(bucket, params, isImplicitIdentityDeny, log);
|
||||||
if (validationError) {
|
if (validationError) {
|
||||||
return next(validationError, bucket);
|
return next(validationError, bucket);
|
||||||
}
|
}
|
||||||
|
@ -174,7 +176,8 @@ function metadataValidateBucketAndObj(params, log, callback) {
|
||||||
},
|
},
|
||||||
(bucket, objMD, next) => {
|
(bucket, objMD, next) => {
|
||||||
const canonicalID = authInfo.getCanonicalID();
|
const canonicalID = authInfo.getCanonicalID();
|
||||||
if (!isObjAuthorized(bucket, objMD, requestType, canonicalID, authInfo, log, request)) {
|
if (!isObjAuthorized(bucket, objMD, requestType, canonicalID, authInfo, isImplicitIdentityDeny,
|
||||||
|
log, request)) {
|
||||||
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);
|
||||||
}
|
}
|
||||||
|
@ -196,18 +199,19 @@ function metadataValidateBucketAndObj(params, log, callback) {
|
||||||
* @param {string} params.bucketName - name of bucket
|
* @param {string} params.bucketName - name of bucket
|
||||||
* @param {string} params.requestType - type of request
|
* @param {string} params.requestType - type of request
|
||||||
* @param {string} params.request - http request object
|
* @param {string} params.request - http request object
|
||||||
|
* @param {boolean} isImplicitIdentityDeny - identity authorization results
|
||||||
* @param {RequestLogger} log - request logger
|
* @param {RequestLogger} log - request logger
|
||||||
* @param {function} callback - callback
|
* @param {function} callback - callback
|
||||||
* @return {undefined} - and call callback with params err, bucket md
|
* @return {undefined} - and call callback with params err, bucket md
|
||||||
*/
|
*/
|
||||||
function metadataValidateBucket(params, log, callback) {
|
function metadataValidateBucket(params, isImplicitIdentityDeny, log, callback) {
|
||||||
const { bucketName } = params;
|
const { bucketName } = params;
|
||||||
return metadata.getBucket(bucketName, log, (err, bucket) => {
|
return metadata.getBucket(bucketName, log, (err, bucket) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
log.debug('metadata getbucket failed', { error: err });
|
log.debug('metadata getbucket failed', { error: err });
|
||||||
return callback(err);
|
return callback(err);
|
||||||
}
|
}
|
||||||
const validationError = validateBucket(bucket, params, log);
|
const validationError = validateBucket(bucket, params, isImplicitIdentityDeny, log);
|
||||||
return callback(validationError, bucket);
|
return callback(validationError, bucket);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -1271,7 +1271,7 @@ function routeBackbeat(clientIP, request, response, log) {
|
||||||
requestType: 'ReplicateObject',
|
requestType: 'ReplicateObject',
|
||||||
request,
|
request,
|
||||||
};
|
};
|
||||||
return metadataValidateBucketAndObj(mdValParams, log, next);
|
return metadataValidateBucketAndObj(mdValParams, false, log, next);
|
||||||
},
|
},
|
||||||
(bucketInfo, objMd, next) => {
|
(bucketInfo, objMd, next) => {
|
||||||
if (useMultipleBackend) {
|
if (useMultipleBackend) {
|
||||||
|
|
|
@ -244,7 +244,7 @@ describe('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',
|
||||||
bucketOwnerCanonicalId, null, log);
|
bucketOwnerCanonicalId, null, true, log);
|
||||||
assert.equal(allowed, true);
|
assert.equal(allowed, true);
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
|
@ -252,7 +252,7 @@ describe('bucket policy authorization', () => {
|
||||||
it('should deny access to non-bucket owner',
|
it('should deny access to non-bucket owner',
|
||||||
done => {
|
done => {
|
||||||
const allowed = isBucketAuthorized(bucket, 'bucketPut',
|
const allowed = isBucketAuthorized(bucket, 'bucketPut',
|
||||||
altAcctCanonicalId, null, log);
|
altAcctCanonicalId, null, true, log);
|
||||||
assert.equal(allowed, false);
|
assert.equal(allowed, false);
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
|
@ -268,7 +268,7 @@ describe('bucket policy authorization', () => {
|
||||||
it('should allow access to non-bucket owner if principal is set to "*"',
|
it('should allow access to non-bucket owner if principal is set to "*"',
|
||||||
done => {
|
done => {
|
||||||
const allowed = isBucketAuthorized(bucket, bucAction,
|
const allowed = isBucketAuthorized(bucket, bucAction,
|
||||||
altAcctCanonicalId, null, log);
|
altAcctCanonicalId, null, true, log);
|
||||||
assert.equal(allowed, true);
|
assert.equal(allowed, true);
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
|
@ -276,7 +276,7 @@ describe('bucket policy authorization', () => {
|
||||||
it('should allow access to public user if principal is set to "*"',
|
it('should allow access to public user if principal is set to "*"',
|
||||||
done => {
|
done => {
|
||||||
const allowed = isBucketAuthorized(bucket, bucAction,
|
const allowed = isBucketAuthorized(bucket, bucAction,
|
||||||
constants.publicId, null, log);
|
constants.publicId, null, true, log);
|
||||||
assert.equal(allowed, true);
|
assert.equal(allowed, true);
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
|
@ -287,7 +287,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.bucketAuthInfo, log);
|
t.bucketId, t.bucketAuthInfo, true, log);
|
||||||
assert.equal(allowed, t.expected);
|
assert.equal(allowed, t.expected);
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
|
@ -304,7 +304,7 @@ describe('bucket policy authorization', () => {
|
||||||
};
|
};
|
||||||
bucket.setBucketPolicy(newPolicy);
|
bucket.setBucketPolicy(newPolicy);
|
||||||
const allowed = isBucketAuthorized(bucket, bucAction,
|
const allowed = isBucketAuthorized(bucket, bucAction,
|
||||||
altAcctCanonicalId, null, log);
|
altAcctCanonicalId, null, true, log);
|
||||||
assert.equal(allowed, false);
|
assert.equal(allowed, false);
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
|
@ -312,7 +312,7 @@ describe('bucket policy authorization', () => {
|
||||||
it('should deny access to non-bucket owner with an unsupported action type',
|
it('should deny access to non-bucket owner with an unsupported action type',
|
||||||
done => {
|
done => {
|
||||||
const allowed = isBucketAuthorized(bucket, 'unsupportedAction',
|
const allowed = isBucketAuthorized(bucket, 'unsupportedAction',
|
||||||
altAcctCanonicalId, null, log);
|
altAcctCanonicalId, null, true, log);
|
||||||
assert.equal(allowed, false);
|
assert.equal(allowed, false);
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
|
@ -325,7 +325,7 @@ describe('bucket policy authorization', () => {
|
||||||
|
|
||||||
it('should allow access to object owner', done => {
|
it('should allow access to object owner', done => {
|
||||||
const allowed = isObjAuthorized(bucket, object, objAction,
|
const allowed = isObjAuthorized(bucket, object, objAction,
|
||||||
objectOwnerCanonicalId, null, log);
|
objectOwnerCanonicalId, null, true, log);
|
||||||
assert.equal(allowed, true);
|
assert.equal(allowed, true);
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
|
@ -333,7 +333,7 @@ describe('bucket policy authorization', () => {
|
||||||
it('should deny access to non-object owner',
|
it('should deny access to non-object owner',
|
||||||
done => {
|
done => {
|
||||||
const allowed = isObjAuthorized(bucket, object, objAction,
|
const allowed = isObjAuthorized(bucket, object, objAction,
|
||||||
altAcctCanonicalId, null, log);
|
altAcctCanonicalId, null, true, log);
|
||||||
assert.equal(allowed, false);
|
assert.equal(allowed, false);
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
|
@ -352,7 +352,7 @@ describe('bucket policy authorization', () => {
|
||||||
it('should allow access to non-object owner if principal is set to "*"',
|
it('should allow access to non-object owner if principal is set to "*"',
|
||||||
done => {
|
done => {
|
||||||
const allowed = isObjAuthorized(bucket, object, objAction,
|
const allowed = isObjAuthorized(bucket, object, objAction,
|
||||||
altAcctCanonicalId, null, log);
|
altAcctCanonicalId, null, true, log);
|
||||||
assert.equal(allowed, true);
|
assert.equal(allowed, true);
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
|
@ -360,7 +360,7 @@ describe('bucket policy authorization', () => {
|
||||||
it('should allow access to public user if principal is set to "*"',
|
it('should allow access to public user if principal is set to "*"',
|
||||||
done => {
|
done => {
|
||||||
const allowed = isObjAuthorized(bucket, object, objAction,
|
const allowed = isObjAuthorized(bucket, object, objAction,
|
||||||
constants.publicId, null, log);
|
constants.publicId, null, true, log);
|
||||||
assert.equal(allowed, true);
|
assert.equal(allowed, true);
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
|
@ -371,7 +371,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.objectAuthInfo, log);
|
t.objectId, t.objectAuthInfo, true, log);
|
||||||
assert.equal(allowed, t.expected);
|
assert.equal(allowed, t.expected);
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
|
@ -383,7 +383,7 @@ describe('bucket policy authorization', () => {
|
||||||
newPolicy.Statement[0].Action = ['s3:GetObject'];
|
newPolicy.Statement[0].Action = ['s3:GetObject'];
|
||||||
bucket.setBucketPolicy(newPolicy);
|
bucket.setBucketPolicy(newPolicy);
|
||||||
const allowed = isObjAuthorized(bucket, object, 'objectHead',
|
const allowed = isObjAuthorized(bucket, object, 'objectHead',
|
||||||
altAcctCanonicalId, altAcctAuthInfo, log);
|
altAcctCanonicalId, altAcctAuthInfo, true, log);
|
||||||
assert.equal(allowed, true);
|
assert.equal(allowed, true);
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
|
@ -393,7 +393,7 @@ describe('bucket policy authorization', () => {
|
||||||
newPolicy.Statement[0].Action = ['s3:PutObject'];
|
newPolicy.Statement[0].Action = ['s3:PutObject'];
|
||||||
bucket.setBucketPolicy(newPolicy);
|
bucket.setBucketPolicy(newPolicy);
|
||||||
const allowed = isObjAuthorized(bucket, object, 'objectHead',
|
const allowed = isObjAuthorized(bucket, object, 'objectHead',
|
||||||
altAcctCanonicalId, altAcctAuthInfo, log);
|
altAcctCanonicalId, altAcctAuthInfo, true, log);
|
||||||
assert.equal(allowed, false);
|
assert.equal(allowed, false);
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
|
@ -408,7 +408,7 @@ describe('bucket policy authorization', () => {
|
||||||
};
|
};
|
||||||
bucket.setBucketPolicy(newPolicy);
|
bucket.setBucketPolicy(newPolicy);
|
||||||
const allowed = isObjAuthorized(bucket, object, objAction,
|
const allowed = isObjAuthorized(bucket, object, objAction,
|
||||||
altAcctCanonicalId, null, log);
|
altAcctCanonicalId, null, true, log);
|
||||||
assert.equal(allowed, false);
|
assert.equal(allowed, false);
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
|
@ -416,7 +416,7 @@ describe('bucket policy authorization', () => {
|
||||||
it('should deny access to non-object owner with an unsupported action type',
|
it('should deny access to non-object owner with an unsupported action type',
|
||||||
done => {
|
done => {
|
||||||
const allowed = isObjAuthorized(bucket, object, 'unsupportedAction',
|
const allowed = isObjAuthorized(bucket, object, 'unsupportedAction',
|
||||||
altAcctCanonicalId, null, log);
|
altAcctCanonicalId, null, true, log);
|
||||||
assert.equal(allowed, false);
|
assert.equal(allowed, false);
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
|
|
|
@ -48,7 +48,7 @@ describe('validateBucket', () => {
|
||||||
authInfo: otherAuthInfo,
|
authInfo: otherAuthInfo,
|
||||||
requestType: 'bucketGet',
|
requestType: 'bucketGet',
|
||||||
request: null,
|
request: null,
|
||||||
}, log);
|
}, true, log);
|
||||||
assert(validationResult);
|
assert(validationResult);
|
||||||
assert(validationResult.is.AccessDenied);
|
assert(validationResult.is.AccessDenied);
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue