Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
williamlardier committed Jul 11, 2023
1 parent 9a29d19 commit c65067d
Show file tree
Hide file tree
Showing 53 changed files with 234 additions and 90 deletions.
4 changes: 4 additions & 0 deletions lib/api/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,10 @@ const api = {
}
}
}
// Specific APIs are not checking any ACLs or Bucket Policies.
if (apiMethod === 'bucketPut' || apiMethod === 'serviceGet' && isImplicitDeny) {
return errors.AccessDenied;
}
return { returnTagCount, isImplicitDeny };
}

Expand Down
28 changes: 22 additions & 6 deletions lib/api/apiUtils/authorization/permissionChecks.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
const { evaluators, actionMaps, RequestContext } = require('arsenal').policies;
const { evaluators, actionMaps, RequestContext, requestUtils } = require('arsenal').policies;
const constants = require('../../../../constants');
const { config } = require('../../../Config');

const { allAuthedUsersId, bucketOwnerActions, logId, publicId,
assumedRoleArnResourceType, backbeatLifecycleSessionName } = constants;
Expand All @@ -8,8 +9,8 @@ const { allAuthedUsersId, bucketOwnerActions, logId, publicId,
const publicReadBuckets = process.env.ALLOW_PUBLIC_READ_BUCKETS ?
process.env.ALLOW_PUBLIC_READ_BUCKETS.split(',') : [];

function checkBucketAcls(bucket, requestType, canonicalID, requesterIsNotUser) {
if (bucket.getOwner() === canonicalID && requesterIsNotUser) {
function checkBucketAcls(bucket, requestType, canonicalID) {
if (bucket.getOwner() === canonicalID) {
return true;
}

Expand Down Expand Up @@ -198,6 +199,20 @@ function _checkBucketPolicyResources(request, resource, log) {
return evaluators.isResourceApplicable(requestContext, resource, log);
}

function _checkBucketPolicyConditions(request, conditions, log) {
const ip = request ? requestUtils.getClientIp(request, config) : undefined;
if (!conditions) {
return true;
}
// build request context from the request!
const requestContext = new RequestContext(request.headers, request.query,
request.bucketName, request.objectKey, ip,
request.connection.encrypted, request.resourceType, 's3', null, null,
null, null, null, null, null, null, null, null, null,
request.objectLockRetentionDays);
return evaluators.meetConditions(requestContext, conditions, log);
}

function _getAccountId(arn) {
// account or user arn is of format 'arn:aws:iam::<12-digit-acct-id>:etc...
return arn.substr(13, 12);
Expand Down Expand Up @@ -255,12 +270,13 @@ function checkBucketPolicy(policy, requestType, canonicalID, arn, bucketOwner, l
const principalMatch = _checkPrincipals(canonicalID, arn, s.Principal);
const actionMatch = _checkBucketPolicyActions(requestType, s.Action, log);
const resourceMatch = _checkBucketPolicyResources(request, s.Resource, log);
const conditionsMatch = _checkBucketPolicyConditions(request, s.Condition, log);

if (principalMatch && actionMatch && resourceMatch && s.Effect === 'Deny') {
if (principalMatch && actionMatch && resourceMatch && conditionsMatch && s.Effect === 'Deny') {
// explicit deny trumps any allows, so return immediately
return 'explicitDeny';
}
if (principalMatch && actionMatch && resourceMatch && s.Effect === 'Allow') {
if (principalMatch && actionMatch && resourceMatch && conditionsMatch && s.Effect === 'Allow') {
permission = 'allow';
}
copiedStatement = copiedStatement.splice(1);
Expand Down Expand Up @@ -318,7 +334,7 @@ function isObjAuthorized(bucket, objectMD, requestType, canonicalID, authInfo, i
// check bucket has read access
// 'bucketGet' covers listObjects and listMultipartUploads, bucket read actions
return isIdentityAndResourceAuthorized(isImplicitIdentityDeny,
isBucketAuthorized(bucket, 'bucketGet', canonicalID, authInfo, log, request));
isBucketAuthorized(bucket, 'bucketGet', canonicalID, authInfo, isImplicitIdentityDeny, log, request));
}
let requesterIsNotUser = true;
let arn = null;
Expand Down
3 changes: 2 additions & 1 deletion lib/api/apiUtils/object/abortMultipartUpload.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,11 @@ function abortMultipartUpload(authInfo, bucketName, objectKey, uploadId, log,
// but the requestType is the more general 'objectDelete'
const metadataValParams = Object.assign({}, metadataValMPUparams);
metadataValParams.requestType = 'objectPut';
const authzIdentityResult = request ? request.isImplicitIdentityDeny : true;

async.waterfall([
function checkDestBucketVal(next) {
metadataValidateBucketAndObj(metadataValParams, log,
metadataValidateBucketAndObj(metadataValParams, authzIdentityResult, log,
(err, destinationBucket) => {
if (err) {
return next(err, destinationBucket);
Expand Down
2 changes: 1 addition & 1 deletion lib/api/bucketDelete.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ function bucketDelete(authInfo, request, log, cb) {
request,
};

return metadataValidateBucket(metadataValParams, log,
return metadataValidateBucket(metadataValParams, request.isImplicitIdentityDeny, log,
(err, bucketMD) => {
const corsHeaders = collectCorsHeaders(request.headers.origin,
request.method, bucketMD);
Expand Down
2 changes: 1 addition & 1 deletion lib/api/bucketDeleteEncryption.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ function bucketDeleteEncryption(authInfo, request, log, callback) {
};

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) => {
const sseConfig = bucket.getServerSideEncryption();
Expand Down
2 changes: 1 addition & 1 deletion lib/api/bucketDeleteLifecycle.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ function bucketDeleteLifecycle(authInfo, request, log, callback) {
requestType: 'bucketDeleteLifecycle',
request,
};
return metadataValidateBucket(metadataValParams, log, (err, bucket) => {
return metadataValidateBucket(metadataValParams, request.isImplicitIdentityDeny, log, (err, bucket) => {
const corsHeaders = collectCorsHeaders(headers.origin, method, bucket);
if (err) {
log.debug('error processing request', {
Expand Down
2 changes: 1 addition & 1 deletion lib/api/bucketDeletePolicy.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ function bucketDeletePolicy(authInfo, request, log, callback) {
requestType: 'bucketDeletePolicy',
request,
};
return metadataValidateBucket(metadataValParams, log, (err, bucket) => {
return metadataValidateBucket(metadataValParams, request.isImplicitIdentityDeny, log, (err, bucket) => {
const corsHeaders = collectCorsHeaders(headers.origin, method, bucket);
if (err) {
log.debug('error processing request', {
Expand Down
2 changes: 1 addition & 1 deletion lib/api/bucketDeleteReplication.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ function bucketDeleteReplication(authInfo, request, log, callback) {
requestType: 'bucketDeleteReplication',
request,
};
return metadataValidateBucket(metadataValParams, log, (err, bucket) => {
return metadataValidateBucket(metadataValParams, request.isImplicitIdentityDeny, log, (err, bucket) => {
const corsHeaders = collectCorsHeaders(headers.origin, method, bucket);
if (err) {
log.debug('error processing request', {
Expand Down
2 changes: 1 addition & 1 deletion lib/api/bucketGet.js
Original file line number Diff line number Diff line change
Expand Up @@ -351,7 +351,7 @@ function bucketGet(authInfo, request, log, callback) {
listParams.marker = params.marker;
}

metadataValidateBucket(metadataValParams, log, (err, bucket) => {
metadataValidateBucket(metadataValParams, request.isImplicitIdentityDeny, log, (err, bucket) => {
const corsHeaders = collectCorsHeaders(request.headers.origin,
request.method, bucket);
if (err) {
Expand Down
2 changes: 1 addition & 1 deletion lib/api/bucketGetACL.js
Original file line number Diff line number Diff line change
Expand Up @@ -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,
request.method, bucket);
if (err) {
Expand Down
2 changes: 1 addition & 1 deletion lib/api/bucketGetEncryption.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ function bucketGetEncryption(authInfo, request, log, callback) {
};

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) => {
// If sseInfo is present but the `mandatory` flag is not set
Expand Down
2 changes: 1 addition & 1 deletion lib/api/bucketGetLifecycle.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ function bucketGetLifecycle(authInfo, request, log, callback) {
requestType: 'bucketGetLifecycle',
request,
};
return metadataValidateBucket(metadataValParams, log, (err, bucket) => {
return metadataValidateBucket(metadataValParams, request.isImplicitIdentityDeny, log, (err, bucket) => {
const corsHeaders = collectCorsHeaders(headers.origin, method, bucket);
if (err) {
log.debug('error processing request', {
Expand Down
2 changes: 1 addition & 1 deletion lib/api/bucketGetNotification.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ function bucketGetNotification(authInfo, request, log, callback) {
request,
};

return metadataValidateBucket(metadataValParams, log, (err, bucket) => {
return metadataValidateBucket(metadataValParams, request.isImplicitIdentityDeny, log, (err, bucket) => {
const corsHeaders = collectCorsHeaders(headers.origin, method, bucket);
if (err) {
log.debug('error processing request', {
Expand Down
2 changes: 1 addition & 1 deletion lib/api/bucketGetObjectLock.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ function bucketGetObjectLock(authInfo, request, log, callback) {
requestType: 'bucketGetObjectLock',
request,
};
return metadataValidateBucket(metadataValParams, log, (err, bucket) => {
return metadataValidateBucket(metadataValParams, request.isImplicitIdentityDeny, log, (err, bucket) => {
const corsHeaders = collectCorsHeaders(headers.origin, method, bucket);
if (err) {
log.debug('error processing request', {
Expand Down
2 changes: 1 addition & 1 deletion lib/api/bucketGetPolicy.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ function bucketGetPolicy(authInfo, request, log, callback) {
request,
};

return metadataValidateBucket(metadataValParams, log, (err, bucket) => {
return metadataValidateBucket(metadataValParams, request.isImplicitIdentityDeny, log, (err, bucket) => {
const corsHeaders = collectCorsHeaders(headers.origin, method, bucket);
if (err) {
log.debug('error processing request', {
Expand Down
2 changes: 1 addition & 1 deletion lib/api/bucketGetReplication.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ function bucketGetReplication(authInfo, request, log, callback) {
requestType: 'bucketGetReplication',
request,
};
return metadataValidateBucket(metadataValParams, log, (err, bucket) => {
return metadataValidateBucket(metadataValParams, request.isImplicitIdentityDeny, log, (err, bucket) => {
const corsHeaders = collectCorsHeaders(headers.origin, method, bucket);
if (err) {
log.debug('error processing request', {
Expand Down
2 changes: 1 addition & 1 deletion lib/api/bucketGetVersioning.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ function bucketGetVersioning(authInfo, request, log, callback) {
request,
};

metadataValidateBucket(metadataValParams, log, (err, bucket) => {
metadataValidateBucket(metadataValParams, request.isImplicitIdentityDeny, log, (err, bucket) => {
const corsHeaders = collectCorsHeaders(request.headers.origin,
request.method, bucket);
if (err) {
Expand Down
2 changes: 1 addition & 1 deletion lib/api/bucketHead.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ function bucketHead(authInfo, request, log, callback) {
requestType: 'bucketHead',
request,
};
metadataValidateBucket(metadataValParams, log, (err, bucket) => {
metadataValidateBucket(metadataValParams, request.isImplicitIdentityDeny, log, (err, bucket) => {
const corsHeaders = collectCorsHeaders(request.headers.origin,
request.method, bucket);
if (err) {
Expand Down
2 changes: 1 addition & 1 deletion lib/api/bucketPutACL.js
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ function bucketPutACL(authInfo, request, log, callback) {

return async.waterfall([
function waterfall1(next) {
metadataValidateBucket(metadataValParams, log,
metadataValidateBucket(metadataValParams, request.isImplicitIdentityDeny, log,
(err, bucket) => {
if (err) {
log.trace('request authorization failed', {
Expand Down
2 changes: 1 addition & 1 deletion lib/api/bucketPutEncryption.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ function bucketPutEncryption(authInfo, request, log, callback) {
};

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) => {
log.trace('parsing encryption config', { method: 'bucketPutEncryption' });
Expand Down
2 changes: 1 addition & 1 deletion lib/api/bucketPutLifecycle.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ function bucketPutLifecycle(authInfo, request, log, callback) {
return next(null, configObj);
});
},
(lcConfig, next) => metadataValidateBucket(metadataValParams, log,
(lcConfig, next) => metadataValidateBucket(metadataValParams, request.isImplicitIdentityDeny, log,
(err, bucket) => {
if (err) {
return next(err, bucket);
Expand Down
2 changes: 1 addition & 1 deletion lib/api/bucketPutNotification.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ function bucketPutNotification(authInfo, request, log, callback) {
const notifConfig = notificationConfig.error ? undefined : notificationConfig;
process.nextTick(() => next(notificationConfig.error, notifConfig));
},
(notifConfig, next) => metadataValidateBucket(metadataValParams, log,
(notifConfig, next) => metadataValidateBucket(metadataValParams, request.isImplicitIdentityDeny, log,
(err, bucket) => next(err, bucket, notifConfig)),
(bucket, notifConfig, next) => {
bucket.setNotificationConfiguration(notifConfig);
Expand Down
2 changes: 1 addition & 1 deletion lib/api/bucketPutObjectLock.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ function bucketPutObjectLock(authInfo, request, log, callback) {
return next(configObj.error || null, configObj);
});
},
(objectLockConfig, next) => metadataValidateBucket(metadataValParams,
(objectLockConfig, next) => metadataValidateBucket(metadataValParams, request.isImplicitIdentityDeny,
log, (err, bucket) => {
if (err) {
return next(err, bucket);
Expand Down
5 changes: 2 additions & 3 deletions lib/api/bucketPutPolicy.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,7 @@ const { BucketPolicy } = models;
function _checkNotImplementedPolicy(policyString) {
// bucket names and key names cannot include "", so including those
// isolates not implemented keys
return policyString.includes('"Condition"')
|| policyString.includes('"Service"')
return policyString.includes('"Service"')
|| policyString.includes('"Federated"');
}

Expand Down Expand Up @@ -70,7 +69,7 @@ function bucketPutPolicy(authInfo, request, log, callback) {
return next(null, bucketPolicy);
});
},
(bucketPolicy, next) => metadataValidateBucket(metadataValParams, log,
(bucketPolicy, next) => metadataValidateBucket(metadataValParams, request.isImplicitIdentityDeny, log,
(err, bucket) => {
if (err) {
return next(err, bucket);
Expand Down
2 changes: 1 addition & 1 deletion lib/api/bucketPutReplication.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ function bucketPutReplication(authInfo, request, log, callback) {
// Check bucket user privileges and ensure versioning is 'Enabled'.
(config, next) =>
// TODO: Validate that destination bucket exists and has versioning.
metadataValidateBucket(metadataValParams, log, (err, bucket) => {
metadataValidateBucket(metadataValParams, request.isImplicitIdentityDeny, log, (err, bucket) => {
if (err) {
return next(err);
}
Expand Down
2 changes: 1 addition & 1 deletion lib/api/bucketPutTagging.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ function bucketPutTagging(authInfo, request, log, callback) {
};
let bucket = null;
return waterfall([
next => metadataValidateBucket(metadataValParams, log,
next => metadataValidateBucket(metadataValParams, request.isImplicitIdentityDeny, log,
(err, b) => {
bucket = b;
return next(err);
Expand Down
2 changes: 1 addition & 1 deletion lib/api/bucketPutVersioning.js
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ function bucketPutVersioning(authInfo, request, log, callback) {

return waterfall([
next => _parseXML(request, log, next),
next => metadataValidateBucket(metadataValParams, log,
next => metadataValidateBucket(metadataValParams, request.isImplicitIdentityDeny, log,
(err, bucket) => next(err, bucket)), // ignore extra null object,
(bucket, next) => parseString(request.post, (err, result) => {
// just for linting; there should not be any parsing error here
Expand Down
2 changes: 1 addition & 1 deletion lib/api/completeMultipartUpload.js
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ function completeMultipartUpload(authInfo, request, log, callback) {
// at the destinationBucket level are same as objectPut
requestType: 'objectPut',
};
metadataValidateBucketAndObj(metadataValParams, log, next);
metadataValidateBucketAndObj(metadataValParams, request.isImplicitIdentityDeny, log, next);
},
function validateMultipart(destBucket, objMD, next) {
if (objMD) {
Expand Down
2 changes: 1 addition & 1 deletion lib/api/initiateMultipartUpload.js
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,7 @@ function initiateMultipartUpload(authInfo, request, log, callback) {
}

async.waterfall([
next => metadataValidateBucketAndObj(metadataValParams, log,
next => metadataValidateBucketAndObj(metadataValParams, request.isImplicitIdentityDeny, log,
(error, destinationBucket) => {
const corsHeaders = collectCorsHeaders(request.headers.origin,
request.method, destinationBucket);
Expand Down
2 changes: 1 addition & 1 deletion lib/api/listMultipartUploads.js
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ function listMultipartUploads(authInfo, request, log, callback) {
function waterfall1(next) {
// Check final destination bucket for authorization rather
// than multipart upload bucket
metadataValidateBucket(metadataValParams, log,
metadataValidateBucket(metadataValParams, request.isImplicitIdentityDeny, log,
(err, bucket) => next(err, bucket));
},
function getMPUBucket(bucket, next) {
Expand Down
2 changes: 1 addition & 1 deletion lib/api/listParts.js
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ function listParts(authInfo, request, log, callback) {

async.waterfall([
function checkDestBucketVal(next) {
metadataValidateBucketAndObj(metadataValParams, log,
metadataValidateBucketAndObj(metadataValParams, request.isImplicitIdentityDeny, log,
(err, destinationBucket) => {
if (err) {
return next(err, destinationBucket, null);
Expand Down
4 changes: 2 additions & 2 deletions lib/api/objectCopy.js
Original file line number Diff line number Diff line change
Expand Up @@ -249,7 +249,7 @@ function objectCopy(authInfo, request, sourceBucket,
}
return async.waterfall([
function checkDestAuth(next) {
return metadataValidateBucketAndObj(valPutParams, log,
return metadataValidateBucketAndObj(valPutParams, request.isImplicitIdentityDeny, log,
(err, destBucketMD, destObjMD) => {
if (err) {
log.debug('error validating put part of request',
Expand All @@ -267,7 +267,7 @@ function objectCopy(authInfo, request, sourceBucket,
});
},
function checkSourceAuthorization(destBucketMD, destObjMD, next) {
return metadataValidateBucketAndObj(valGetParams, log,
return metadataValidateBucketAndObj(valGetParams, request.isImplicitIdentityDeny, log,
(err, sourceBucketMD, sourceObjMD) => {
if (err) {
log.debug('error validating get part of request',
Expand Down
2 changes: 1 addition & 1 deletion lib/api/objectDelete.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ function objectDelete(authInfo, request, log, cb) {
const canonicalID = authInfo.getCanonicalID();
return async.waterfall([
function validateBucketAndObj(next) {
return metadataValidateBucketAndObj(valParams, log,
return metadataValidateBucketAndObj(valParams, request.isImplicitIdentityDeny, log,
(err, bucketMD, objMD) => {
if (err) {
return next(err, bucketMD);
Expand Down
2 changes: 1 addition & 1 deletion lib/api/objectDeleteTagging.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ function objectDeleteTagging(authInfo, request, log, callback) {
};

return async.waterfall([
next => metadataValidateBucketAndObj(metadataValParams, log,
next => metadataValidateBucketAndObj(metadataValParams, request.isImplicitIdentityDeny, log,
(err, bucket, objectMD) => {
if (err) {
log.trace('request authorization failed',
Expand Down
Loading

0 comments on commit c65067d

Please sign in to comment.